# Topic Codes — registry for AyCode.Core's own topics (`ACCORE`)

Per the Framework-First Design Principle, this Layer 0 registry lists **only the framework's own (`ACCORE`) topics**. Each higher-layer repo hosts its own `TOPIC_CODES.md` for repo-specific topics — see `## Per-repo extension convention` below. A consumer's topic-search at runtime walks `own-dep-repos` to gather both its own and all inherited (lower-layer) topic registries.

Full ID format: `<PREFIX>-<TOPIC>-<TYPE>-<RAND>` — see `AyCode.Core/.github/REPO_PREFIXES.md` for the `<PREFIX>` and `<RAND>` components. The `<TOPIC>` and `<TYPE>` components are defined in this file (for the framework) and in each higher-layer repo's own equivalent (for consumer-side topics).

## Why this registry exists

To make IDs like `ACCORE-LOG-I-K7M2`, `ACCORE-SIG-B-3R9P`, `ACCORE-XCUT-I-A4B7` unambiguous within the framework. The `<TOPIC>` component (registered here for ACCORE) combines with `<PREFIX>` (per `REPO_PREFIXES.md`) and `<RAND>` (4-character random alphanumeric suffix) to form the full ID.

## Framework's own (ACCORE) topic codes

| Code    | Topic                       | Scope                                                                             | Docs location                                                                                            |
|---------|-----------------------------|-----------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| `LOG`   | LOGGING                     | Logger system: levels, writers, config-reading vs DI factory                      | `AyCode.Core/AyCode.Core/docs/LOGGING/` (+ variants in `AyCode.Core.Server`, `AyCode.Services`)          |
| `AUTH`  | AUTH                        | User authentication: bearer tokens, JWT, login flow, hub authorization            | `AyCode.Core/docs/AUTH/`                                                                                 |
| `SIG`   | SIGNALR                     | SignalR transport: tags, client base, dispatch, session                           | `AyCode.Core/AyCode.Services/docs/SIGNALR/` (+ variant in `AyCode.Services.Server`)                      |
| `SBP`   | SIGNALR_BINARY_PROTOCOL     | Binary wire protocol over SignalR: framing, chunking, argument read               | `AyCode.Core/AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/`                                              |
| `SIGDS` | SIGNALR_DATASOURCE          | Client-server DataSource on SignalR transport: change tracking, rollback, sync state, load lifecycle, IList<T> wrapper | `AyCode.Core/AyCode.Services/docs/SIGNALR_DATASOURCE/`                                            |
| `BIN`   | BINARY                      | AcBinary serializer: features, format, writers, source generator                  | `AyCode.Core/AyCode.Core/docs/BINARY/`                                                                   |
| `TOON`  | TOON                        | Toon serializer: LLM-optimized format with @meta/@types/@data sections            | `AyCode.Core/AyCode.Core/docs/TOON/`                                                                     |
| `XCUT`  | cross-cutting               | Issues / TODOs spanning ≥2 ACCORE topics — one canonical home, referenced from each affected topic | `AyCode.Core/AyCode.Core/docs/XCUT/`                                                            |
| `META`  | meta-tooling                | Issues/TODOs **about the workspace meta-tooling itself**: skills, registries, `.github/` conventions, ADR/Decision Log governance, protocol-stack edge cases. Distinct from code-domain topics (LOG, BIN, etc.). | `AyCode.Core/.github/META_ISSUES.md` + `AyCode.Core/.github/META_TODO.md`                                  |
| `LLMP`  | LLM-protocol meta           | LLM protocol decisions (Decision Log entries only — uses `LLMP-DEC-N` form, no prefix) | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md`                                                      |

## Type codes (universal across all repos)

| Code  | Type           | Used in file                                 | Notes                                                                                              |
|-------|----------------|----------------------------------------------|----------------------------------------------------------------------------------------------------|
| `I`   | Issue          | `{TOPIC}_ISSUES.md`                          | Concrete concern: spec inconsistency, broken contract, observable edge case                        |
| `T`   | TODO           | `{TOPIC}_TODO.md`                            | Forward-looking planned work: refactor, missing feature, optimization                              |
| `B`   | Bug            | `{TOPIC}_ISSUES.md` (alongside `I` entries)  | Confirmed broken behaviour, reproducible, needs a code fix                                         |
| `C`   | Critical       | `{TOPIC}_ISSUES.md` or `{TOPIC}_TODO.md`     | **Severity override** — emergency priority, supersedes `I`/`B`/`T` category; body explains type    |
| `DEC` | Decision       | `LLM_PROTOCOL_DECISIONS.md`                  | **LLMP-only.** Append-only protocol decision entries.                                              |

### Distinctions

- **I vs B**: Both tracked together in `_ISSUES.md`. Use `B` only when the behaviour is confirmed broken with a reproducer. `I` covers concerns, inconsistencies, doc drift, edge cases without an active bug.
- **C (Critical)**: A severity flag, not a category. `ACCORE-LOG-C-K7M2` means "AyCode.Core's logger critical item with random suffix K7M2" — body must state whether it's an underlying bug / issue / todo. Prefer `C` over `I`/`B`/`T` when severity is emergency. Do NOT double-classify (no `ACCORE-LOG-IB-K7M2` or similar).
- **DEC**: LLMP exception — long form because "LLMP-D-1" is unreadable. Decision Log entries only.

## Per-repo extension convention

Each higher-layer repo MAY host its own `TOPIC_CODES.md` for repo-specific topics. Recommended location:

```
<repo>/.github/TOPIC_CODES.md
```

This per-repo file lists ONLY that repo's own topic codes. Lower-layer (inherited) topics are reachable through the dependency tree — at runtime, the `docs-check` skill walks `own-dep-repos` from the invocation point to gather both this repo's own topics AND all inherited topics from deps.

Topic codes need NOT be globally unique across repos — the `<PREFIX>` component disambiguates. Two repos may legitimately use the same topic code for repo-local concepts (e.g., one framework's `DAL` ≠ another framework's `DAL`).

If a higher-layer repo has no repo-specific topics, the file is omitted (default = the repo uses only inherited topics from its deps).

The framework (this file) does NOT enumerate higher-layer topics — that would violate Framework-First. To find all topics workspace-wide, agents walk the dep tree from a top-layer consumer (which transitively sees everything).

## ID format rules

1. **Format**: `<PREFIX>-<TOPIC>-<TYPE>-<RAND>` — all uppercase, hyphen-separated. The `<PREFIX>` component identifies the owning repo per `AyCode.Core/.github/REPO_PREFIXES.md` (and per each repo's own `@repo.prefix` field). **LLMP exception**: `LLMP-DEC-N` entries (workspace-meta Decision Log) skip the prefix and use sequential `N` instead of `<RAND>` — single-file serialization avoids parallel-branch collision.
2. **Random suffix**: `<RAND>` is a 4-character alphanumeric suffix from `[A-Z0-9]` (~1.7M combinations per `<PREFIX>-<TOPIC>-<TYPE>` triple). Generated at entry creation; the agent globs existing entries (active topic file + all year-month bucket archive files) and verifies uniqueness; regenerate on rare collision.
3. **Append-only**: once assigned, IDs never change. If an entry is reversed or superseded, add a NEW entry that references the prior one — do not renumber, do not re-randomize.
4. **Hash anchor** (markdown cross-file refs): lowercase with hyphens preserved (`LOGGING_ISSUES.md#accore-log-i-k7m2` — GitHub auto-converts). Always use the full prefixed form; bare hash anchors without prefix are ambiguous across repos.
5. **No sub-category in ID**: legacy sub-prefixes like `PROTO-`, `DISPATCH-`, `CONN-`, `DS-` are NOT allowed at ID level. Capture sub-category in the entry body header: `## ACCORE-SIG-I-K7M2 [PROTO]: ...`.

## Registry maintenance — adding a new ACCORE topic

To add a new topic code **for AyCode.Core specifically**:
1. Propose the code (2-6 uppercase chars), short and mnemonic, scoped to ACCORE's domain (framework concerns only).
2. Check it doesn't collide with C# class-name prefixes (`Ac*` / `Mg*`) — the topic code should be visually distinct in mixed code/markdown content.
3. Check it doesn't collide with existing ACCORE topic codes in the table above.
4. Add a row to the "Framework's own (ACCORE) topic codes" table.
5. Create the topic folder: `AyCode.Core/<project>/docs/{TOPIC_FOLDER_NAME}/` with `README.md`, optional `{TOPIC_FOLDER_NAME}_ISSUES.md`, `{TOPIC_FOLDER_NAME}_TODO.md`.
6. Add a Decision Log entry (`LLMP-DEC-N`, in the workspace-level `LLM_PROTOCOL_DECISIONS.md`) recording the new framework topic.

For higher-layer repos: each consumer registers its own topics in its own `TOPIC_CODES.md` per the per-repo extension convention. No framework-level approval is needed — the consumer is sovereign over its own domain.

## Collision avoidance with class-name prefixes

C# code conventions in this workspace:
- `Ac*` — AyCode.Core framework types (e.g., `AcLoggerBase`, `AcBinarySerializer`)
- `Mg*` — Mango company types (e.g., `MgGrid`, `MgDbTableBase`, `MgEntityBase`)

Topic codes intentionally avoid these 2-char prefixes (`Ac`, `Mg`) to prevent visual confusion in mixed content. Topic codes are 2-6 chars and SHOULD NOT start with `Ac` or `Mg`. (Example principle: a hypothetical 2-char `MG` topic code would visually collide with `Mg*` class names; choose a more distinctive ≥3-char code.)

## Examples (ACCORE only)

```
ACCORE-LOG-I-K7M2          # framework's logger issue (random suffix K7M2)
ACCORE-LOG-T-3R9P          # framework's logger TODO
ACCORE-LOG-B-A4B7          # framework's logger bug (confirmed broken)
ACCORE-LOG-C-X9Q4          # framework's logger CRITICAL — body: underlying bug / issue / todo
ACCORE-SIG-I-M2K8          # framework's SignalR issue (body may note: [PROTO] sub-category)
ACCORE-SBP-T-7N3F          # framework's SignalR Binary Protocol TODO
ACCORE-BIN-B-P5W2          # framework's Binary serializer bug
ACCORE-TOON-I-D8R6         # framework's Toon issue
ACCORE-XCUT-I-F4G1         # framework's cross-cutting issue (affects ≥2 ACCORE topics)
LLMP-DEC-50                # workspace-meta Decision Log entry (no prefix — bare exception)
```

The `<RAND>` suffixes shown above are illustrative. Real entries generate fresh random suffixes at creation time per `REPO_PREFIXES.md`'s "Random suffix spec".

## Cross-references to other files

- **Reference format** (cross-file in markdown): `LOGGING_ISSUES.md#accore-log-i-k7m2` (filename + lowercase hash anchor with full 4-component ID). Always use the full prefixed form — bare hash anchors without prefix are ambiguous across repos.
- **Code comments**: `// See ACCORE-LOG-I-K7M2` — full prefixed form, since the ID is globally unique only with prefix.
- **DB natural key** (future migration): `(prefix, topic, type, suffix)` tuple; or the full string `ACCORE-LOG-I-K7M2` as a single column.
- **Workspace registries**: `AyCode.Core/.github/REPO_PREFIXES.md` (framework prefix spec); this file (ACCORE topics + format spec); each higher-layer repo's own `.github/TOPIC_CODES.md` (consumer-side topics); `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` (LLMP-DEC entries, workspace-meta history).

## Status field conventions

Every entry in `_ISSUES.md`, `_TODO.md`, and `LLM_PROTOCOL_DECISIONS.md` SHOULD carry an explicit `Status` field. **3 allowed values**:

| Status | Meaning | Archive eligible? |
|---|---|---|
| `Open` | Active / unresolved (default for new entries); also used for documented-current-behaviour entries that must remain visible | No |
| `InProgress` | Partial work in flight; some scope addressed but more remains | No |
| `Closed` | Done — bug fixed, decision made (won't fix / superseded by another entry / accepted), TODO completed. The body of the entry explains *what happened* (date, ref, rationale). | Yes |

### Defaults

- New entries default to `Status: Open`.
- For documented current-behaviour entries (accepted limitations / "by design" / "this is how it works"), use `Status: Open` with an optional body callout: `> **Note:** This entry documents accepted current behaviour — not scheduled for change.` These never archive (Open status).

### Update workflow

When status changes, update the `Status` line in-place. **This is the ONE exception to append-only** — the Status field is mutable; entry body / ID / Description remain immutable.

When marking `Closed`:
1. **Format the Status line as** `Status: Closed (YYYY-MM-DD)` — the inline date is what `docs-archive` uses to determine the destination year-bucket.
2. **Add a `### Resolution` sub-section** documenting the closure. **Strongly recommended** — without it, future readers (and the `docs-archive` skill on lookup) have no context for "what changed, why, where". Suggested fields:
   - **What:** one-line summary of the change.
   - **Where:** code reference (file/class/commit hash) or doc reference (ADR / PR).
   - **Why:** the rationale (fix / "won't fix because X" / "superseded by ACCORE-LOG-I-XXXX" / "accepted as-is").
   - Optional: scope, date if different from Status line, related entries.

The body carries the **nuance**; the Status field only signals archive-eligibility.

### Lifecycle: archive

`Closed` entries are eligible for rotation into year-month bucket archive files (`<file>_<YYYY>_<MM>.md`) via the `docs-archive` skill. Year-month derived from a date in the entry body. Archive operation is user-invoked — closed entries don't disappear automatically. See `AyCode.Core/.github/skills/docs-archive/SKILL.md`.

## Change history

See the Decision Log (`../../../LLM_PROTOCOL_DECISIONS.md`) for the introduction of this registry and future topic-code additions.
