diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 5cd849e..bd8114b 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -62,7 +62,9 @@ "Bash(Format-Table -AutoSize -Wrap)", "PowerShell($paths = @\\(\"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\bin\\\\Release\\\\net9.0\", \"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\bin\\\\Debug\\\\net9.0\"\\); foreach \\($p in $paths\\) { if \\(Test-Path $p\\) { Write-Output \"=== $p ===\"; Get-ChildItem -Path $p -Recurse -Include \"AyCode.Services.dll\",\"AyCode.Core.dll\",\"Mango.Nop.Core.dll\",\"Nop.Plugin.Misc.FruitBankPlugin.dll\",\"Nop.Plugin.Misc.AIPlugin.dll\",\"Mango.Nop.Services.dll\" -ErrorAction SilentlyContinue | Select-Object LastWriteTime, Length, FullName | Sort-Object FullName | Format-Table -AutoSize -Wrap } })", "PowerShell($pluginRoots = @\\(\"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\Plugins\", \"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\bin\\\\Release\\\\net9.0\\\\Plugins\", \"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\bin\\\\Debug\\\\net9.0\\\\Plugins\"\\); foreach \\($p in $pluginRoots\\) { if \\(Test-Path $p\\) { Write-Output \"=== $p ===\"; Get-ChildItem -Path $p -Recurse -Include \"AyCode.Services.dll\",\"AyCode.Core.dll\",\"Mango.Nop.Core.dll\",\"Nop.Plugin.Misc.FruitBankPlugin.dll\",\"Mango.Nop.Services.dll\" -ErrorAction SilentlyContinue | Select-Object LastWriteTime, Length, FullName | Sort-Object FullName | Format-Table -AutoSize -Wrap } else { Write-Output \"NOT FOUND: $p\" } })", - "PowerShell($appDataPaths = @\\(\"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\App_Data\\\\plugins.json\", \"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\App_Data\\\\plugins.installed.json\"\\); foreach \\($f in $appDataPaths\\) { if \\(Test-Path $f\\) { Write-Output \"=== $f ===\"; Get-Content $f -Raw } else { Write-Output \"NOT FOUND: $f\" } })" + "PowerShell($appDataPaths = @\\(\"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\App_Data\\\\plugins.json\", \"H:\\\\Applications\\\\Mango\\\\Source\\\\FruitBank\\\\Presentation\\\\Nop.Web\\\\App_Data\\\\plugins.installed.json\"\\); foreach \\($f in $appDataPaths\\) { if \\(Test-Path $f\\) { Write-Output \"=== $f ===\"; Get-Content $f -Raw } else { Write-Output \"NOT FOUND: $f\" } })", + "Read(//h/Applications/Mango//**)", + "Read(//h/Applications/Mango/LLM_PLAN//**)" ] } } diff --git a/.github/LLM_PROTOCOL_DECISIONS.md b/.github/LLM_PROTOCOL_DECISIONS.md index ac8e5d6..7585b03 100644 --- a/.github/LLM_PROTOCOL_DECISIONS.md +++ b/.github/LLM_PROTOCOL_DECISIONS.md @@ -62,7 +62,7 @@ Active as of **2026-04-26**. For the full evolution history, see the dated table **Decision Log governance (this file)**: - **Append-only.** Never rewrite or delete entries. Reversals and refinements get *new* entries that reference the superseded one by ID (e.g., "LLMP-DEC-26 superseded by LLMP-DEC-27"). - **Entries have `LLMP-DEC-N` IDs** (topic=LLMP, type=DEC — see TOPIC_CODES.md). Sequential, append-only, never renumber. Reference entries by ID for unambiguous citation from code comments, other `.md` files, or cross-repo. -- **Archive annually** once the log reaches ~50 entries (split to `LLM_PROTOCOL_DECISIONS_.md`). IDs stay unique across archives. +- **Archive policy** (LLMP-DEC-65): active log keeps **last 15 entries** (rolling window); older entries rotate to **year-month bucket** archive files (`LLM_PROTOCOL_DECISIONS__.md`, e.g., `_2026_04.md`). Sparse files OK — only month-buckets with archived entries get a file. Triggered manually via `docs-archive` skill on user request, or automatically when active count > 15. IDs stay unique across archives. **Supersedes** the original "annual at ~50" policy from LLMP-DEC-25. - **`Affected` column** uses the scope codes defined below. - **User consent required** for every new entry. - **No skill / template version labels.** Skills and templates are continuously iterated; the Decision Log entry IS the version history. Reference changes by date or `LLMP-DEC-N` ID, not by synthetic version numbers (`v1.1`, `v2.0`, etc.) — neither in skill content, frontmatter metadata, nor in conversation when discussing changes. LLMP-DEC-45 removed legacy `metadata: version` fields from all SKILL.md files; LLMP-DEC-47 codifies the principle explicitly to prevent the linguistic regression of using `vN.M` as colloquial shorthand for "recent changes". @@ -112,61 +112,12 @@ The "primary" vs "inherit" distinction is defined in `protocol-audit/references/ ## 2026 +> **Earlier entries archived**: LLMP-DEC-1..52 (2026-04-20 through 2026-04-26) → see [`LLM_PROTOCOL_DECISIONS_2026_04.md`](./LLM_PROTOCOL_DECISIONS_2026_04.md) per the **last-15-active retention policy** (LLMP-DEC-67). The active table below contains only the most recent 15 entries (rolling window). Cross-link integrity preserved: when a recent entry references `LLMP-DEC-X` (X ≤ 49), open the archive file to read the full text — IDs are stable, never reassigned. +> +> **Year-month buckets** (LLMP-DEC-65 policy): future archive files use `LLM_PROTOCOL_DECISIONS__.md` (e.g., `_2026_05.md` for May 2026 entries). Cross-month archives are sparse files keyed on the entry's date column. The retention rule scans on `docs-archive` invocation: archive when active count > 15, target by entry date. + | ID | Date | Decision | Rationale | Affected | |---------------|------------|-------------------------------------------------------|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| -| LLMP-DEC-1 | 2026-04-20 | Added CROSS-REPO HARD-GATE to Rule #2 | Docs-before-code was applied only to the own repo, not external deps | `5× primary` | -| LLMP-DEC-2 | 2026-04-20 | Added PER-QUESTION DOC-FIRST to Rule #2 | LLM skipped checking for relevant `.md` before jumping to code search | `5× primary` | -| LLMP-DEC-3 | 2026-04-21 | Expanded Rule #5 scope: "code/files" → "any file..." | Memory / config / docs edits also need consent; old wording too narrow | `5× primary` | -| LLMP-DEC-4 | 2026-04-22 | Added Auto-detection triggers to Rule #4 | "realize" was subjective; post-compaction reset to `[LOADED_DOCS: NONE]` didn't fire reliably | `5× primary` | -| LLMP-DEC-5 | 2026-04-22 | Added "in context" definition to Rule #3 | Summary content was mistaken for actually-loaded docs (lossy compression) | `5× primary` | -| LLMP-DEC-6 | 2026-04-22 | Unified AyCode.Blazor Rule #3 with the other 4 repos | Was custom "CRITICAL TOOL EXECUTION FIREWALL" variant; normalized | `AyCode.Blazor/copilot-instructions.md` | -| LLMP-DEC-7 | 2026-04-22 | "strictly maintain rule X" → "rule 3" | Per-repo numbers varied (15/18/19/20/21); unified reference | `5× primary` | -| LLMP-DEC-8 | 2026-04-22 | Created `protocol-audit` skill at repo-level | Cross-repo consistency check; `.github/skills/` chosen over personal paths (DRY) | `protocol-audit/SKILL.md` + `protocol-audit/references/REPOS.md` | -| LLMP-DEC-9 | 2026-04-22 | Added `## Shared Agent Skills` section (protocol-audit) | Discoverability of AyCode.Core-hosted skills from dependent repos | `4× non-Core primary` | -| LLMP-DEC-10 | 2026-04-23 | Created `docs-discovery` skill (parallel session) | Paired-doc (`main` + `_ISSUES` + `_TODO`) auto-loading before code search | `docs-discovery/SKILL.md` + `AyCode.Core/copilot-instructions.md` | -| LLMP-DEC-11 | 2026-04-23 | Extended `## Shared Agent Skills` with `docs-discovery` (parallel session) | Both skills now listed in each dependent repo | `4× non-Core primary` + `Mango.Nop.Core/copilot-instructions.md` | -| LLMP-DEC-12 | 2026-04-24 | LOADED_DOCS prefix: full list → count+delta format | Long lists became visual noise at scale; delta preserves self-commitment | `5× primary` + `docs-discovery/SKILL.md` | -| LLMP-DEC-13 | 2026-04-24 | Created this Decision Log | Institutional memory for protocol evolution; avoid re-debating resolved choices | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` | -| LLMP-DEC-14 | 2026-04-24 | Added `## Protocol History` section | Cross-repo discoverability of the Decision Log | `4× non-Core primary` + `Mango.Nop.Core/copilot-instructions.md` | -| LLMP-DEC-15 | 2026-04-24 | Filled empty Nop.Plugin.Misc.AIPlugin instruction file | Previously 0 bytes; now minimal inherit-pattern referencing AyCode.Core + both skills + log | `Nop.Plugin.Misc.AIPlugin/copilot-instructions.md` | -| LLMP-DEC-16 | 2026-04-24 | Filled empty Mango\FruitBank instruction file | Previously 0 bytes; now minimal inherit-pattern with ⚠️ "purpose TBD" notice | `Mango/FruitBank/copilot-instructions.md` | -| LLMP-DEC-17 | 2026-04-24 | Expanded REPOS.md: 5 repos → 8 (primary + inherit) | Audit scope was incomplete; sub-project & plugin files were missed | `protocol-audit/references/REPOS.md` | -| LLMP-DEC-18 | 2026-04-24 | Fixed Mango.Nop.Core `@repo` path (7 `..` → 6 `..`) | Previous path resolved to `H:\Aycode\...` (non-existent). Corrected relative depth from repo root | `Mango.Nop.Core/copilot-instructions.md` | -| LLMP-DEC-19 | 2026-04-24 | Resolved Mango.FruitBank purpose (nopCommerce host) | Confirmed: directory is a nopCommerce deployment for FruitBank company, hosting Nop.Plugin.Misc.AIPlugin. Layer 4 (host), not TBD. Updated content accordingly. | `Mango/FruitBank/copilot-instructions.md` | -| LLMP-DEC-20 | 2026-04-24 | `protocol-audit` v1.0 → v2.0: primary/inherit invariant split | SKILL.md now applies Common + Primary invariants to rows 1-5, Common + Inherit + Cross-cutting to rows 6-8. New invariants: P3 (Rule #1 count+delta format), X1 (Shared Agent Skills), X2 (Protocol History). | `protocol-audit/SKILL.md` + `protocol-audit/references/REPOS.md` (issues cleared) | -| LLMP-DEC-21 | 2026-04-24 | Docs layout: paired topics migrated to `TOPIC/README.md + TOPIC/TOPIC_*.md` pattern (Option C) | Single `docs/` folder with flat `TOPIC_*.md` files was noisy at scale; folder grouping reinforces the "folder navigation rule" and gives each topic a canonical `README.md` entry point. Option C (README.md main + topic-prefixed companions) chosen over pure Pattern B for (a) glob-pattern compatibility with old `**/TOPIC*.md`, (b) unique LOADED_DOCS basenames for companion files, (c) GitHub README auto-render preserved. Single-file topics (ARCHITECTURE, GLOSSARY, CONVENTIONS, DTOS, etc.) kept flat. | 13 `docs/` folders across 5 repos (AyCode.Core, AyCode.Blazor, Libraries, FruitBankHybridApp, Nop.Plugin.Misc.AIPlugin); ~35 file renames/moves; 13 new `README.md` index files; 4 csproj files converted from explicit file-lists to recursive glob (`docs\**\*.md`); `docs-discovery/SKILL.md` Step 2 glob patterns updated to match Pattern B layout | -| LLMP-DEC-22 | 2026-04-24 | Rule #1 LOADED_DOCS format: "basenames only" → "shortest unique short names" | After the Pattern B docs migration, many `README.md` files share the same basename across different topic folders (e.g., `LOGGING/README.md`, `BINARY/README.md`, `SIGNALR/README.md`). A bare `README.md` in the LOADED_DOCS prefix is ambiguous and breaks the self-commitment / no-re-read mechanism. New rule: basename by default (already unique for topic-prefixed companions and flat single-file topics); `TOPIC/README.md` for topic-folder READMEs; further disambiguation upward for cross-project collisions. | `5× primary` + `docs-discovery/SKILL.md` Step 4 | -| LLMP-DEC-23 | 2026-04-24 | Full cross-reference cleanup after Pattern B migration (batch sed + targeted fixes) | After the docs migration, ~45 `.md` files contained outdated paths (flat `TOPIC_*.md` refs that are now `TOPIC/TOPIC_*.md`; renamed mains `LOGGING_SERVER.md`→`LOGGING/README.md` etc.; pre-existing depth bugs like `AyCode.Core/docs/LOGGING.md` that were always wrong depth; cross-folder sibling refs inside `SIGNALR_BINARY_PROTOCOL/` pointing to `SIGNALR/` topics by basename). Three-pass cleanup: (1) batch sed on 44 files for `docs/TOPIC*.md` → Pattern B paths; (2) second sed pass for pre-existing `AyCode.Core/docs/{LOGGING,BINARY,SIGNALR}/` → `AyCode.Core/{AyCode.Core,AyCode.Services}/docs/...` depth correction (with placeholder guard to avoid double-substitution); (3) targeted Edits for cross-folder sibling refs and project-level README doc-listing tables. Final grep: zero old-style references remain. | ~45 `.md` files across all 5 repos; AyCode.Core/copilot-instructions.md rule 8 + 19; AyCode.Blazor rule 14; FruitBankHybridApp rules 15+20; 7 project-level `README.md` "doc listing" tables; 9 MGGRID sibling refs; 5 cross-folder SIGNALR↔SIGNALR_BINARY_PROTOCOL refs | -| LLMP-DEC-24 | 2026-04-24 | Phantom-reference fixes: `docs/ARCHITECTURE.md` from `.github/` + BINARY/README.md serializer-overview target | (1) `AyCode.Core/.github/copilot-instructions.md:96` had `docs/ARCHITECTURE.md#framework-vs-consumer-boundary` which resolved to `.github/docs/ARCHITECTURE.md` (non-existent) relative to the file's own location. Fixed to `../docs/ARCHITECTURE.md#framework-vs-consumer-boundary` so the path resolves to the existing repo-root `docs/ARCHITECTURE.md`. (2) `AyCode.Core/AyCode.Core/docs/BINARY/README.md:22` pointed to `docs/ARCHITECTURE.md` for "Serialization overview (Toon vs AcBinary vs AcJson)". The new `TOON/README.md` (created by a parallel session) uses the more canonical `../../Serializers/README.md` — the serializer-framework-level README that genuinely compares all three formats. Aligned BINARY/README.md to the same target for consistency. | `AyCode.Core/.github/copilot-instructions.md` + `AyCode.Core/AyCode.Core/docs/BINARY/README.md` | -| LLMP-DEC-25 | 2026-04-24 | Added "Current protocol state (quick reference)" section to the top of the Decision Log | The log grows monotonically (append-only); readers landing on it shouldn't have to scan every dated entry to learn the currently-active protocol. The new top-of-file summary captures Rules #1-5, docs layout convention, instruction-file inventory (5 primary + 3 inherit), agent skills, and Decision Log governance. Dated entries remain the source of truth for *why* each decision was made; the summary is the *what* at a glance. Archival plan noted: yearly split at ~50 entries. | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` | -| LLMP-DEC-26 | 2026-04-24 | Extended docs-sync rule with two sub-rules: `File registration` + `Issue / TODO surfacing` (initial version; superseded by 2026-04-24 revision below) | (1) **File registration** — every new `.md` must be visible in Visual Studio Solution Explorer, which requires a `` entry (or matching recursive glob) in the nearest `.csproj`. (2) **Issue / TODO surfacing** — surface concrete bugs/TODO candidates in `[DOCUMENTATION CHECK]` when not already in loaded `_ISSUES.md` / `_TODO.md`. Initial calibration: "concrete + non-duplicate + actionable — silence beats noise". **This version was revised after two external LLM critiques — see the next entry.** | `5× primary` (docs-sync rule: AyCode.Core #18, AyCode.Blazor #13, Libraries #16, FruitBank #14, FruitBankHybridApp #14) | -| LLMP-DEC-27 | 2026-04-24 | Revision of the two new sub-rules after two-session LLM review + proactive csproj glob expansion | Two external LLM critiques identified gaps in the initial sub-rule text. Applied revisions: (A) **File registration scope-limit** — check only if the new file falls OUTSIDE an existing recursive glob (zero-cost skip for the common `docs/`-path case). (B) **Issue / TODO surfacing guardrails** — added 4 explicit prerequisites (companion must be in `LOADED_DOCS` for reliable duplicate check; high confidence with quotable evidence; concrete observation; not duplicate). Added **volume cap max 3 per response**. Removed **ID assignment** from draft entries (user assigns at apply-time to avoid parallel-session collisions). Added **status-update-on-fix** clause (fixing an issue listed in loaded `_ISSUES.md` → surface `Status: FIXED` suggestion). (C) **ENFORCEMENT empty-state guard** — if nothing to report: `[DOCUMENTATION CHECK] None.` single line (no prose padding). (D) **Proactive csproj glob expansion** — added `` to 9 csproj files already having `docs/**` glob; added the same pattern (without `docs/**` exclusion) to 5 csproj files lacking any md glob. Together these cover folder-level `README.md` files in code directories (Loggers, Serializers, SignalRs, DbContexts, LogItems, etc.), making them visible in VS Solution Explorer without per-file rule trigger. The rule sub-rule A now mostly fires only for truly unusual locations. Cross-reference added between sub-rule B and the existing "Identify missing documentation" clause (different targets: main docs vs companions). | `5× primary` instruction files (docs-sync rule revision); **14 csproj files** (glob expansion): 9 with `docs/**` + `**/README.md`, 5 with only `**/README.md` | -| LLMP-DEC-28 | 2026-04-24 | Created `docs-check` skill; docs-sync rule → short pointer | Observation: both Claude Code and Copilot interpret and follow *skills* more reliably than numbered rules (explicit activation, step-by-step SKILL.md, description-matching forces deliberate thought). The docs-sync rule had grown into a multi-step procedure (drift detection, missing docs, topic separation, file registration, issue/TODO surfacing with 4 prereqs + volume cap + status-update-on-fix, empty-state handling) — exactly the shape of a skill, not a rule. Created `AyCode.Core/.github/skills/docs-check/SKILL.md` (v1.0) encapsulating the full procedure in 7 steps + edge cases + negative examples. Rule #18 (and equivalents) shortened in each primary file to a single pointer: *"at the end of EVERY code-modifying response, invoke the docs-check skill ..."*. Removed ~40 lines of duplicated procedure per primary file (×5 = ~200 lines of redundant text across the workspace). Skill is read-only on loaded docs (no new `Read`/`Grep` during invocation); all patches surface as proposals (Rule #5). | **1 new skill**: `docs-check/SKILL.md`; **5 primary** copilot-instructions.md (docs-sync rule shortened); **7 non-Core** files (`## Shared Agent Skills` section extended with the `docs-check` bullet: 4 primary non-Core + 3 inherit) | -| LLMP-DEC-29 | 2026-04-24 | `protocol-audit` v2.0 → v2.1 | (a) X1 invariant extended to expect all three skills in `## Shared Agent Skills` (was two: docs-discovery + protocol-audit; now adds docs-check). (b) New **X3** invariant: the docs-sync rule in each primary file points to the `docs-check` skill (checks for backtick-wrapped `` `docs-check` `` and the skill path). (c) Applicability matrix extended: X3 applies to all 5 primary files, N/A for the 3 inherit files (they don't have the numbered docs-sync rule). | `protocol-audit/SKILL.md` | -| LLMP-DEC-30 | 2026-04-24 | Introduced globally-unique issue/TODO/decision ID system + batch-migrated existing entries | Three reasons: (a) make IDs like `ISSUE-01` unambiguous outside their containing file (DB natural-key ready, code-comment friendly, cross-repo clear); (b) remove collision risk across parallel LLM sessions (per-topic+type counter is a smaller concurrency domain than global counter); (c) standardize the inconsistent mix of existing prefixes (`PROTO-`, `DISPATCH-`, `DS-`, `CONN-`, `XCUT-`, `DESER-`, `SER-`, `SGEN-`, `BWO-`, and per-file `ISSUE-NN`/`TODO-NN`). **Format:** `{TOPIC}-{TYPE}-{N}` — topic code from registry, type = `I`(ssue) / `T`(ODO) / `B`(ug) / `C`(ritical severity override) / `DEC` (LLMP-only), N is per-topic-per-type counter starting at 1 (no zero-padding). **Topic codes:** `LOG`, `SIG`, `SBP`, `BIN`, `TOON`, `GRID` (avoids `MG`-prefix-collision with `Mg*` class naming), `XCUT`, `LLMP`. Sub-categories (`PROTO`, `DISPATCH`, `CONN`, etc.) move from ID to body header tag (`## SIG-I-1 [PROTO]: ...`). Registry maintained in `docs-check/references/TOPIC_CODES.md`. Migration: ~50 existing entries renumbered across 10 files (LOGGING, SIGNALR, SBP, BINARY, TOON topic folders) + cross-references updated workspace-wide; found and mapped the previously-uncatalogued `BWO-4` entry → `BIN-I-15`. | `docs-check/references/TOPIC_CODES.md` (new); `docs-check/SKILL.md` (Step 5 draft entry format + topic registry reference); **10 topic doc files** (IDs renumbered); cross-ref updates across ~20 `.md` files in the workspace | -| LLMP-DEC-31 | 2026-04-24 | Consolidated XCUT cross-cutting entries into dedicated `docs/XCUT/` folder | Before: cross-cutting entries (currently just `XCUT-I-1: JSON-in-Binary request parameters`) were duplicated — canonical body in `BINARY_ISSUES.md`, short cross-ref in `SIGNALR_ISSUES.md`. This pattern breaks down as more XCUT entries arrive (every added cross-cutting topic needs duplicate maintenance, and the concept of "which side is canonical" is arbitrary). **Now:** canonical home is `AyCode.Core/AyCode.Core/docs/XCUT/` (topic-folder at project level, consistent with LOGGING/, BINARY/, TOON/ placement). Contains `README.md` (explaining XCUT concept + convention), `XCUT_ISSUES.md` (canonical entries), `XCUT_TODO.md` (template + future entries). Each affected topic's file keeps a **short cross-ref** pointing to the canonical entry; body size per topic drops to ~2 lines. Migrated `XCUT-I-1` — full body now lives in `XCUT_ISSUES.md`, with cross-refs from `BINARY_ISSUES.md` and `SIGNALR_ISSUES.md`. Also updated: `BINARY_TODO.md#bin-t-1` Related-link now points to canonical; `AyCode.Core/docs/CONVENTIONS.md` JSON-in-Binary section references canonical. | New folder `AyCode.Core/AyCode.Core/docs/XCUT/` (3 files); updated `BINARY_ISSUES.md`, `SIGNALR_ISSUES.md` (XCUT sections); `BINARY_TODO.md`, `AyCode.Core/docs/CONVENTIONS.md` (related-link updates); `AyCode.Core/AyCode.Core/docs/README.md` (topic list extended) | -| LLMP-DEC-32 | 2026-04-24 | SKILL.md generalization + workspace-meta-tooling exception documented | Two related concerns raised: (1) SKILL.md files had hardcoded specific repo/project names (e.g., "5 AyCode/Mango repos (AyCode.Core, AyCode.Blazor, Libraries, FruitBank, FruitBankHybridApp)" in protocol-audit's `description`; "`AyCode.Core/AyCode.Core/docs/XCUT/`" in docs-check's Step 5). Skills should describe BEHAVIOR; specific data lives in `references/` files. (2) The `.github/skills/` registry files (`REPOS.md`, `TOPIC_CODES.md`) list higher-layer products (Layer 3 consumers like FruitBank) — a literal Framework-First Design Principle violation if interpreted strictly. **Decisions:** (a) Skills stay **universal** (one copy under `AyCode.Core/.github/skills/`, referenced by all other repos via Shared Agent Skills section) — per-layer skill duplication rejected as maintenance-hostile. (b) SKILL.md files generalized to read from `references/` registries instead of hardcoding names. (c) The `.github/` folder is **explicitly exempted** from Framework-First: it is workspace-configuration, not framework code. Rule added to AyCode.Core/copilot-instructions.md's Framework-First Design Principle section. Scope notes added to `REPOS.md` and `TOPIC_CODES.md` at their tops. **Future escape hatch:** if a skill becomes truly layer-specific (e.g., `fruit-measurement-audit` for FruitBank-only concerns), it goes in that layer's `.github/skills/`, not in AyCode.Core's. | `protocol-audit/SKILL.md` (description + invariant X3 + applicability note generalized); `docs-check/SKILL.md` (Step 5 XCUT path reference generalized); `docs-discovery/SKILL.md` (consumer-specific class-name example swapped for a placeholder); `AyCode.Core/.github/copilot-instructions.md` (Framework-First section + "Exception for workspace meta-tooling" paragraph); `protocol-audit/references/REPOS.md` (scope note header); `docs-check/references/TOPIC_CODES.md` (scope note header) | -| LLMP-DEC-33 | 2026-04-24 | `protocol-audit` v2.1 → v2.2 — added C4 invariant for Session Setup section presence | New common invariant `C4` enforces `## Session Setup` section presence across all 8 files, with references to the three skill SKILL.md files (and for inherit files, also the canonical host's `copilot-instructions.md`). Ensures the new Session Setup rule is mechanically verifiable. Applicability matrix updated: C-invariant range extended from C1-C3 to C1-C4. | `protocol-audit/SKILL.md` (version bump; new C4 invariant; applicability matrix update) | -| LLMP-DEC-34 | 2026-04-24 | Token-economics principle made explicit — amortization over multi-turn sessions is the central design principle | **Observation**: a validation session exposed an LLM reasoning bias — when asked whether the protocol's upfront cost was worth it, the agent's first answer categorized `protocol-audit/SKILL.md` (~6K tokens) as "wasteful for this specific turn" because the turn didn't invoke it. A single user reminder ("the session just started") was enough for the LLM to self-correct and reframe the cost as amortizing over the full session lifetime. **Issue**: the Session Setup rule's rationale said "one-time cost per session" but did NOT explicitly name the single-turn optimization trap. LLMs default to per-turn local optimization and can mis-judge pre-loaded content as wasteful, especially in early session turns or quick one-off queries. **Fix**: extended the `## Session Setup` "Why mandatory" paragraph in all 8 `copilot-instructions.md` files (5 primary + 3 inherit) with an explicit `**Amortization — critical, do NOT re-evaluate per-turn**` note. The note states: (a) cost is measured over the ENTIRE session; (b) the first domain question alone recoups it; (c) the alternative (repeated source-code searches per turn) costs 10-20K tokens per turn with lower quality; (d) the design depends on cross-turn amortization + Rule #3 (no-re-read) + Rule #4 (context recovery as only exception); (e) this is the **central token-economics principle** of the entire stack. Proactively inoculates future sessions against the single-turn-optimization bias that was observed. | `5× primary` + `3× inherit` `copilot-instructions.md` (Session Setup "Why mandatory" paragraph extended with Amortization sub-paragraph) | -| LLMP-DEC-35 | 2026-04-24 | Added mandatory Session Setup — pre-load 3 SKILL.md files at session start | **Problem:** Claude Code does NOT populate workspace skills into its system-reminder / native skill-registry. Previous design relied on instruction-driven invocation (rule pointer → LLM reads SKILL.md on first trigger). This is **fragile**: the agent might not recognize implicit triggers (e.g., "this is a domain question → load docs-discovery"), might forget to load the SKILL.md, or might delay loading until after a code-search has already started. A test session confirmed the risk: an LLM answered a rule-listing question without loading any skill, then retroactively loaded them only when asked directly — the first domain question would have missed the docs-discovery trigger. **Solution:** Added `## Session Setup` section to all 8 `copilot-instructions.md` files (primary and inherit). Rule mandates pre-loading of all three SKILL.md files (`docs-discovery`, `docs-check`, `protocol-audit`) at session start, immediately after reading the main `copilot-instructions.md`. For inherit files, AyCode.Core's `copilot-instructions.md` is also in the mandatory load set (because inherit files do not duplicate Rules #1-5 — the canonical host has them). Expected `[LOADED_DOCS: ...]` prefix on first response: 4 files for primary, 5 for inherit. **Cost:** ~10-13K tokens one-time per session; Rule #3 (no-re-read) prevents repeated reads. **Reliability gain:** implicit triggers fire reliably for the entire session. The `## Shared Agent Skills` section intros (in 7 non-Core files) were also updated to cross-reference the Session Setup mandate. | `5× primary` + `3× inherit` `copilot-instructions.md` (added `## Session Setup` section); `4× non-Core primary` + `3× inherit` = `7× non-Core` (Shared Agent Skills intro updated to cross-reference Session Setup) | -| LLMP-DEC-36 | 2026-04-24 | Migrated Toon docs to `TOON/README.md` + `TOON_*.md` (Option C) | Last AyCode.Core domain still on flat layout. Absorbed the orphan `ToonExtendedInfo.txt` at repo root; added paired `TOON_ISSUES.md` / `TOON_TODO.md` per convention. Verified format spec against actual code (`MetaWriter`, `DataSection`, `TypeDefinitions`, `Descriptions`), not just the legacy marketing-style txt — surfaced richer reality (placeholder system, enum backing-field detection, navigation metadata, type relation constants) absent from the old txt. Serialize-only status recorded as `TOON_TODO.md#toon-t-6`. | `AyCode.Core/docs/TOON/` (8 new files) + `AyCode.Core/docs/README.md` (topic list) + `AyCode.Core/Serializers/Toons/README.md` (stub pointer) + `ToonExtendedInfo.txt` (removed) | -| LLMP-DEC-37 | 2026-04-24 | `docs-discovery` SKILL.md hardening: literal-path tilalom + false-empty guardrail (cross-session validation feedback) | **Incident**: a parallel Copilot session executed `docs-discovery` for a logger-review query but substituted a literal `AyCode.Core/docs/LOGGING/...` path for the spec'd `**/docs/{TOKEN}/**/*.md` glob. The literal path missed AyCode.Core's project-level docs layout (`//docs/LOGGING/`), yielded 0 matches, and Copilot concluded "docs are empty" → fell through to code-only review, skipping the loaded paired-docs set (8 known issues, 11 prioritized TODOs). **Fix scope**: minimal — 2 sentences appended to existing steps, NOT new rules. (a) Step 2 end: explicit prohibition on substituting literal `/docs/...` for the recursive `**/docs/...` glob, with one-line rationale that `**` matches both repo-root and project-level layouts in a single pass. (b) Step 3 end: false-empty guardrail — if glob returns 0 matches OR all matches are 0-byte, re-validate the glob (typo? literal substituted?) and retry once with the same token under a corrected `**/docs/...` pattern (NEVER an ad-hoc path guess) before falling through to code-search. **Rejected alternatives**: an early Copilot draft proposed 5 new numbered rules + 5 new SKILL steps (incl. a Step 0 "load every README.md" pass). Evaluation: most were redundant with existing rules (vs. hard-gate, paired-docs Step 5, Rule #1 prefix), one was based on `**`-semantics misunderstanding (proposed "two-pass" globs where the second pattern is a strict subset of the first), one was actively harmful to token economy (Step 0). Net: ~80% reduction in proposed protocol surface, same bug-class coverage. | `docs-discovery/SKILL.md` (Step 2 end + Step 3 end) | -| LLMP-DEC-38 | 2026-04-24 | Retroactively assigned `LLMP-DEC-N` IDs to existing Decision Log entries | When the globally-unique ID system was introduced (LLMP-DEC-30) with the `LLMP` topic code for LLM-protocol meta-decisions using `DEC` type, the existing ~37 Decision Log entries remained keyed by date alone. This meant the design intention (entries have unambiguous string IDs for cross-referencing) wasn't realized for historical entries. Fix: added an `ID` column as the leftmost in the 2026 table, and populated LLMP-DEC-1 through LLMP-DEC-37 in chronological order (retroactive assignment, this entry is LLMP-DEC-38 as the first ID-aware addition). Entries now referenceable by ID from code comments, other `.md` files, PR descriptions, or future DB migration. The `LLMP-DEC-N` format is append-only (IDs never renumber); superseded decisions get new entries that reference old ones by ID (e.g., "LLMP-DEC-26 superseded by LLMP-DEC-27"). | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` (ID column + 37 retroactive IDs) | -| LLMP-DEC-39 | 2026-04-24 | `docs-discovery` SKILL.md Step 2 restructuring — recursive `**/` wildcard requirement moved to prominent CRITICAL section at TOP (second iteration; LLMP-DEC-37 proved insufficient) | **Incident**: a second Copilot session exhibited the same literal-path bug that LLMP-DEC-37 was supposed to prevent — it synthesized `AyCode.Core/docs/LOGGING/README.md` (a path that doesn't exist; the real docs are at `AyCode.Core/AyCode.Core/docs/LOGGING/`, one level deeper at project-level) instead of using the recursive `**/docs/LOGGING/**/*.md` glob. LLMP-DEC-37 had appended a warning to the END of Step 2, which was not prominent enough — Copilot read Step 2, formed its own mental model of "usual docs paths", and never reached the trailing caution. **Fix**: moved the warning to the TOP of Step 2 as a `### ⚠️ CRITICAL` subsection. Content expanded: (a) explicit depth-level enumeration (repo-root `/docs/TOPIC/`, project-level `//docs/TOPIC/`, nested), (b) concrete failure-mode walkthrough showing the specific "know the repo → synthesize shallow path → 0 matches → false-empty conclusion" pattern that fires for Pattern B layouts, (c) correct-vs-wrong form side-by-side examples, (d) absolute rule: NEVER drop the leading `**/` even when the repo is known. The old trailing warning was consolidated to a back-reference to the new top section to keep Step 2 from splitting the message. User rejected intermediate proposals (byte-count verification, flat `**/docs/TOPIC.md` defensive pattern) as "drótozás" (hardcoding) — fix stays structural, no glob pattern additions. | `docs-discovery/SKILL.md` (Step 2 restructuring; supersedes LLMP-DEC-37's Step-2-end placement) | -| LLMP-DEC-40 | 2026-04-24 | Rule #1 clarification: removed false "globally unique by basename" claim for `copilot-instructions.md` | **Observation**: a parallel Claude Code self-audit session noticed a literal contradiction in Rule #1. The short-name rule line 18 said `copilot-instructions.md` is "globally unique by basename" — true for a typical session (1 active repo = 1 loaded copilot-instructions.md) but FALSE for `protocol-audit` sessions, which load all 8 `copilot-instructions.md` files simultaneously. The claim conflicts with the cross-project-disambiguation rule one line above (line 17) whenever the audit use-case fires. The LLM correctly identified the ambiguity and proposed a patch. **Fix**: replaced the parenthetical "globally unique by basename" with an explicit acknowledgment of the `protocol-audit` collision case + pointer to the already-existing cross-project-disambiguation rule above. New wording uses concrete disambiguation examples (`AyCode.Core/copilot-instructions.md`, `FruitBankHybridApp/copilot-instructions.md`). The `.github/` prefix tiltás is retained — now justified as "implicit location" rather than "already unique". **Deferred (explicit YAGNI)**: proposed new `protocol-audit` C5 invariant (semantic validation: Rule #1 basename-uniqueness claims must match the actual file-set in REPOS.md). Rejected for now — one known instance isn't enough to justify invariant surface / false-positive risk; revisit if a second similar contradiction appears. | `5× primary` `copilot-instructions.md` (Rule #1 line 18 patched) | -| LLMP-DEC-41 | 2026-04-24 | Created `adr-author` skill — 4th workspace skill, extends Session Setup pre-load from 3 to 4 | **Gap identified**: the existing skill-stack (docs-discovery, docs-check, protocol-audit) covers documentation retrieval, code↔docs drift detection, and cross-repo file-structural audit — but has no artifact-producing workflow for **pre-code architectural decisions** (greenfield repo planning, feature design, tech-stack choices, library selection, migration planning). The `{TOPIC}_TODO.md` format is an implementation queue (known scope, code ref expected, P1-P3 priority); it cannot naturally hold decision rationale, weighed alternatives, or trade-off tables. Without a dedicated artifact, design rationale tends to disappear into chat history or get flattened into TODO entries that lose the "why". **Solution**: `adr-author` skill encoding the canonical Michael Nygard ADR workflow as a structured interview (Step 1 routing → Step 2 context → Step 3 alternatives → Step 4 trade-offs → Step 5 decision → Step 6 consequences → Step 7 draft + write → Step 8 cross-refs). Tool-neutral like the other three skills. **Routing logic**: two decision-log paradigms supported — per-repo `docs/adr/NNNN-.md` Nygard-style files (product/code/domain decisions) VS workspace-level `LLMP_PROTOCOL_DECISIONS.md` table rows with ID `LLMP-DEC-N` (protocol-meta decisions). **Invocation model (new): explicit user request OR LLM-suggest-back** — LLM flags when conversation exhibits 2+ ADR-heuristics (multiple alternatives weighed, irreversible, cross-cutting, 6-18mo re-openable); user must confirm before invocation. Never auto-invoke. **Session Setup pre-load 3 → 4 skill**: consistent with existing `protocol-audit` (on-demand) pattern — the skill's content must be in context for trigger recognition. **Handoff**: `docs-check` can flag ADR-worthy observations at end-of-response; `docs-discovery` owns "how does X work" questions, `adr-author` owns "let's design X" questions. **User rationale for broader scope than greenfield-only**: user correctly pointed out ADR-worthy decisions arise in mature code too (refactors, library additions, migration paths), not just new-repo planning — the original Nygard definition supports this scope. | new: `AyCode.Core/.github/skills/adr-author/SKILL.md` + `AyCode.Core/.github/skills/adr-author/references/ADR_TEMPLATE.md`; `5× primary` `copilot-instructions.md` (Session Setup: three→four; prefix count 4→5); `3× inherit` `copilot-instructions.md` (Session Setup: three→four; prefix count 5→6); `4× non-Core primary` + `3× inherit` `copilot-instructions.md` (Shared Agent Skills intro "All three"→"All four"; new adr-author bullet added after docs-check bullet) | -| LLMP-DEC-42 | 2026-04-25 | `adr-author` SKILL.md: added "Multi-project repo case" placement guidance to Step 1 (cross-cutting vs project-scoped) | **Incident**: a Claude Code session executing `adr-author` for a bearer token design produced an excellent ADR draft but left the `docs/adr/` location ambiguous — the draft path said `docs/adr/0001-...` without resolving whether that meant `/docs/adr/` (repo root, cross-cutting placement) or `//docs/adr/` (project-scoped). The decision in question affected 2+ projects (`AyCode.Services` client + `AyCode.Services.Server`), so the placement question was real, not academic. The original SKILL.md Step 1 used `/docs/adr/...` placeholder which silently assumed single-project repos; multi-project layouts (which exist in this and likely other repos) had no explicit guidance. **Fix**: added a "Multi-project repo case" sub-section to Step 1 with three rules: (1) existing convention wins (Glob first; never fragment by creating a parallel folder); (2) no existing folder → match scope to placement (cross-cutting → highest common ancestor, typically repo root; project-scoped → that project's `docs/`); (3) ambiguous scope → ask the user explicitly before proceeding. Step 7's path reference updated to `` resolved in Step 1, removing the misleading `/docs/adr/` literal. **Generic, not hardcoded**: no specific repo names or project paths in the rules — they apply to any multi-project repo. | `adr-author/SKILL.md` (Step 1 + Step 7 updates) | -| LLMP-DEC-43 | 2026-04-25 | Lazy-load shift for user-gated skills + new `docs-archive` skill + Status field convention | **Three integrated changes consolidated into one decision** because they share the underlying principle "user-gated skills are lazy-loaded; reactive skills stay pre-loaded": (A) **Lazy-load shift**: `protocol-audit` and `adr-author` (LLMP-DEC-41) move from Session Setup pre-load to lazy-load. The `## Shared Agent Skills` bullets in `copilot-instructions.md` already contain enough trigger description for the LLM to recognize when to invoke; the full SKILL.md only needs to be in context at execution time. Token savings: ~10-14K per session (3 SKILL.md × ~5K avg). (B) **New `docs-archive` skill** (lazy-loaded, user-gated + LLM-suggest-back): rotates closed entries (`Status` ∈ {Fixed, Resolved, Won't fix, Superseded by X}) from active `_ISSUES.md` / `_TODO.md` / `LLM_PROTOCOL_DECISIONS.md` into year-bucketed `*_.md` archive files. Year of Status update determines destination bucket. Status-based filter (no foundational-flag complexity, no age threshold). Active file gets a 2-line pointer block at top; archive files NOT auto-loaded by `docs-discovery` (lazy-on-suspicion read pattern documented in `docs-discovery/SKILL.md` "Archive files" section). (C) **Status field convention** formalized in `TOPIC_CODES.md`: explicit value list (`Open`, `Partially Fixed`, `Fixed`, `Resolved`, `Won't fix`, `Documented limitation`, `Superseded by`), date stamping rules, partial-fix `### Resolution status` sub-section format, archive-eligibility filter. Status updates are the **one exception** to append-only — field is mutable; entry body / ID / Description remain immutable. **Cross-skill integration**: `docs-discovery/SKILL.md` gets new "Archive files" section (default-exclude year-suffixed glob; on-demand read on regression / supersession-ref / cross-ref signals). `docs-check` already had status-update-on-fix logic (LLMP-DEC-27); this entry formalizes the value vocabulary it should use. **Workflow**: `docs-archive` reports per-file analysis (Step 2), user selects scope (Step 3), generates plan with diff (Step 4), applies on explicit consent (Step 5, Rule #5). Archive operation is on-demand — no automatic monitoring, no background size checks. **Note**: an earlier in-conversation draft proposed the lazy-load shift as a standalone LLMP-DEC entry; folded into this LLMP-DEC-43 instead, since lazy-load and `docs-archive` skill share the same design rationale and benefit from being recorded as one decision. | new: `AyCode.Core/.github/skills/docs-archive/SKILL.md`; updated: `docs-check/references/TOPIC_CODES.md` (new "Status field conventions" section); `docs-discovery/SKILL.md` (new "Archive files" section); `5× primary` `copilot-instructions.md` (Session Setup: 4→2 pre-loaded SKILL.md, prefix count 5→3, lazy-load list added); `3× inherit` `copilot-instructions.md` (Session Setup: 4→2 pre-loaded SKILL.md, prefix count 6→4, lazy-load list added); `4× non-Core primary` + `3× inherit` `copilot-instructions.md` (Shared Agent Skills intro updated; new `docs-archive` bullet added after `adr-author`) | -| LLMP-DEC-44 | 2026-04-25 | Status field vocabulary simplified: 7 values → 3 (`Open`, `InProgress`, `Closed`); bulk-migrated all existing TODO/Issue entries to `Open` | **Refinement of LLMP-DEC-43 (C)**: the 7-value Status vocabulary (`Open`, `Partially Fixed`, `Fixed`, `Resolved`, `Won't fix`, `Documented limitation`, `Superseded by`) was deemed over-engineered. **Reduced to 3 values**: `Open` (active/unresolved; also used for documented-current-behaviour entries that must remain visible), `InProgress` (partial work in flight), `Closed` (done — bug fixed, decision made, TODO completed; archive-eligible). Distinctions previously encoded in the Status (Fixed vs Resolved vs Won't fix vs Superseded) move to the **entry body** — body explains "what happened" (date, ref, rationale); Status only signals "is this still in the active set?". Documented-current-behaviour entries (previously `Documented limitation`, `By design`, `Acceptable`, `Limitation`, `Upstream SDK limitation`, etc.) stay as `Open` with an optional body callout (`> **Note:** This entry documents accepted current behaviour — not scheduled for change.`). **Bulk migration** applied: every existing `Status` value in `_ISSUES.md` and `_TODO.md` files across the workspace (LOGGING, XCUT, BINARY, SIGNALR, SBP) was set to `Open` as a clean-slate starting point — future Status updates use the new 3-value vocabulary. **Archive criterion** in `docs-archive` simplified to a single rule: `Status == "Closed"` → archive-eligible. **Known anomaly**: `SIGNALR_ISSUES.md` had a single `Status: DONE` entry — also set to `Open` per the bulk-migration rule, but semantically should likely be `Closed` (work was actually done). User to manually re-mark if appropriate. **Why simpler is better**: the previous 7 values created false precision — the distinction between Fixed/Resolved/Won't fix matters in the body, not in the Status field. The `Documented limitation` value semantically conflicted with archiving (it's not "closed work"); folding it into `Open` with a body callout removes the conflict. Archive logic becomes a single equality check. | `docs-check/references/TOPIC_CODES.md` (Status section: 7 → 3 values, simpler workflow); `docs-archive/SKILL.md` (archive criterion simplified to `Status == "Closed"`); 6 files affected by bulk Status migration: `LOGGING_ISSUES.md`, `XCUT_ISSUES.md`, `BINARY_ISSUES.md`, `SIGNALR_ISSUES.md`, `SIGNALR_BINARY_PROTOCOL_ISSUES.md`, `SIGNALR_BINARY_PROTOCOL_TODO.md` (`TOON_ISSUES.md` unchanged — all real entries already `Open`) | - -| LLMP-DEC-45 | 2026-04-25 | `adr-author` SKILL.md + ADR_TEMPLATE first-real-use feedback batch (9 changes); `version` field removed from all 5 SKILL.md frontmatters | First end-to-end use of `adr-author` (bearer token ADR session, `0001-user-bearer-token-flow.md`) surfaced 9 friction points across the skill and template, plus consolidates 2 previously-parked feedback items (Copilot session out-of-scope routing, Claude Code session dimensional alternatives — now subsumed). **Changes** (priority order): (#1) Step 8 #3 split into "decision-closes-entry" vs "pre-flight-closed-entry" cases — pre-flight case (entry already closed before ADR formalizes the architecture) gets a soft cross-ref to `### Related` instead of Status update; (#2) new Step 9 "Hand-off after write" — short, ask-don't-assume-next-action; (#3) Step 8 #1 explicit `/README.md` Index table update (not just generic "PRODUCT_DECISIONS.md"); (#4) Step 7 NNNN re-Glob immediately before `Write` (collision safety); (#5) Step 5 opinion-when-asked nuance — frame as preference not prescription, with anti-example pair (❌ "X, egyértelmű." vs ✅ "I lean toward X because Y, but you decide."); (#6) ADR_TEMPLATE Status placeholder fixed `Proposed` → `Proposed (YYYY-MM-DD)` (was inconsistent with skill Step 5); (#7) `docs/adr/0000-TEMPLATE.md` becomes 1-paragraph pointer to canonical `references/ADR_TEMPLATE.md` — eliminates duplication / drift risk; (#8) ADR_TEMPLATE Alternatives section adds optional Reversibility/Cost/Future-flex sub-bullets with explicit "use sparingly" guidance; (#9) ADR_TEMPLATE Status comment notes Status vocabulary distinct from `_ISSUES.md` / `_TODO.md` (Open/InProgress/Closed) — see `TOPIC_CODES.md`. Plus Edge cases "Parallel LLM sessions" updated to point back to Step 7's explicit re-Glob rule (was redundant). **Housekeeping**: `metadata: version` field removed from all 5 SKILL.md frontmatters (`adr-author`, `docs-archive`, `docs-discovery`, `docs-check`, `protocol-audit`). Internal iteration doesn't need versioning ceremony — Decision Log entries are the version history. **No backward-compat concerns**: bearer token ADR (0001) was a test run, not a production consumer; no external dependents on prior skill behaviour. | `adr-author/SKILL.md` (Steps 5/7/8/9, Edge cases, frontmatter); `adr-author/references/ADR_TEMPLATE.md` (Status section, Alternatives section); `docs/adr/0000-TEMPLATE.md` (full rewrite as pointer); `docs-discovery/SKILL.md`, `docs-check/SKILL.md`, `protocol-audit/SKILL.md`, `docs-archive/SKILL.md` (frontmatter `version` field removed) | -| LLMP-DEC-46 | 2026-04-25 | `docs-discovery` SKILL.md Step 2: forward-slash mandate added (Windows backslash trap) | **Recurring failure mode**: a Copilot session in VS attempted `file_search` with a Windows-backslash glob pattern (`...\docs\**\*.md`); the glob engine silently returned 0 matches despite files existing, and the agent fell through to code-search per the same false-empty pattern that LLMP-DEC-39 addressed. Same root cause class as the `**/` lehagyás (LLMP-DEC-37, LLMP-DEC-39) — a syntactically malformed pattern returns no match, the agent interprets "no files" as "no docs exist". **Fix**: added a new `### ⚠️ Path separators — forward slashes ONLY in glob patterns` sub-section to `docs-discovery/SKILL.md` Step 2 (placed between the existing `**/` CRITICAL section and "File layout convention"). Content: forward-slash mandate regardless of host OS, correct vs wrong example, failure-mode description (silent 0 matches), absolute rule statement, cross-reference to the `**/` mandate. **Why both rules together**: the `**/` recursive mandate + the `/` separator mandate are the two most common syntactic glob errors observed in real sessions; both produce identical "0 matches → false-empty → code-search fall-through" failure mode. Documenting them adjacent in Step 2 lets the LLM see them as a paired class of pitfalls. **Bug class is host-agnostic**: glob engines uniformly require forward slashes (Microsoft.Extensions.FileSystemGlobbing, ripgrep, Node glob, Python pathlib, JS minimatch) — backslash-in-pattern is silently malformed everywhere. | `docs-discovery/SKILL.md` (Step 2 — new "Path separators" sub-section between the existing `**/` CRITICAL and "File layout convention") | -| LLMP-DEC-47 | 2026-04-25 | Decision Log governance: explicit "No skill / template version labels" clause added | **Recurring slip detected**: even after LLMP-DEC-45 removed `metadata: version` from all 5 SKILL.md frontmatters, the LLM (this agent) continued using "v1.1" colloquially in conversation as shorthand for "the recent batch of changes" — including in a substantive ADR-plan critique. The user pointed out the regression: the slip itself is evidence the principle was not explicit enough. Implicit removal of metadata fields didn't prevent the linguistic ceremony in dialogue or in cross-doc references. **Fix**: added a new bullet to the `Decision Log governance` section in this file's `## Current protocol state (quick reference)` block. The rule covers three surfaces: (a) skill content, (b) frontmatter metadata, (c) conversational / cross-doc references. Reference changes by **date or `LLMP-DEC-N` ID** instead. **Why explicit codification matters**: structural removal (deleting metadata fields) is a one-time mechanical change; linguistic habit is a recurring behavioral one. Implicit principles drift in language even when followed structurally. Codifying prevents the regression at the source — every future agent reading the governance bullets will see the rule before being tempted to introduce `vN.M` shorthand. | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` (Decision Log governance section — new bullet) | -| LLMP-DEC-48 | 2026-04-25 | `adr-author` SKILL.md Step 1 restructured: fresh-folder creation rule factored out as shared rule (covers fresh-repo + multi-project cases); template wording "copy of" → "1-paragraph pointer to" (sync with LLMP-DEC-45 #7) | **Drift detected by parallel session**: LLMP-DEC-45 #7 made `/docs/adr/0000-TEMPLATE.md` a 1-line pointer to the canonical `references/ADR_TEMPLATE.md` (eliminating duplication / drift risk). The `adr-author/SKILL.md` Step 1 fresh-repo case still said *"Propose creating `0000-TEMPLATE.md` (copy of `references/ADR_TEMPLATE.md`)"* — stale wording. Additionally, the Step 1 multi-project case did not mention 0000-TEMPLATE creation at all (implicit only via inheritance from the fresh-repo case). **Discovery context**: a parallel Claude Code session, planning a project-scoped ADR folder for `AyCode.Services/docs/adr/`, followed the SKILL Step 1 literally and proposed creating a full template copy — which would have created an inconsistent state across the workspace (one folder with pointer, another with copy). **Fix**: SKILL Step 1 restructured. The fresh-folder creation directive (`README.md` + `0000-TEMPLATE.md`) factored out of the fresh-repo case into a **shared rule applying to any newly-created `docs/adr/` folder** (whether at repo root or project-scoped). The 0000-TEMPLATE wording changed from "copy of" to "1-paragraph pointer to" the canonical, with rationale stated in-line ("single source of truth, avoids template drift"). The README.md description also extended to mention the index table. **Universality preserved (no drót)**: SKILL.md does NOT reference LLMP-DEC IDs (workspace-specific) — it states the principle directly so the skill remains portable to any workspace adopting the protocol-stack. The LLMP-DEC link lives only in this Decision Log entry. | `adr-author/SKILL.md` (Step 1 path resolution section — fresh-folder creation factored out as shared rule + canonical-pointer wording) | -| LLMP-DEC-49 | 2026-04-25 | Created `AUTH` topic — registered topic code in `TOPIC_CODES.md`, scaffolded `docs/AUTH/{README, AUTH_ISSUES, AUTH_TODO}.md` at repo root | Bearer-token ADR-0001 (`docs/adr/0001-user-bearer-token-flow.md`, `Accepted (2026-04-25)`) needs a topic home for ongoing issues, planned work, and consumer recipe. **Pre-implementation scaffold**: `README.md` is honest about pre-impl state and includes a Scope table mirroring the ADR's Decision section + a "Security: Never log secrets" guideline (auth-specific phrasing, will trim to cross-ref when `LOG-T-12` lands the canonical version in `LOGGING/README.md`); `AUTH_ISSUES.md` and `AUTH_TODO.md` are empty-state with entry-format templates. **Placement**: repo-root `docs/AUTH/` (not project-level) chosen because AUTH is cross-cutting — affects `AyCode.Services` + `AyCode.Services.Server` + `AyCode.Interfaces` + every consumer. Same parallel-to-projects positioning as `docs/adr/` and `docs/XCUT/` (sibling cross-cutting topics). **`LOG-I-9` / `LOG-I-10`** (auth security leaks closed pre-flight) remain in `LOGGING_ISSUES.md` per their existing Discovery-context note; relocation to `AUTH_ISSUES.md` as `AUTH-I-N` is a separate user-approved follow-up listed in ADR-0001's "Status migration on AUTH topic creation" section — not part of this entry. | `docs-check/references/TOPIC_CODES.md` (new `AUTH` row inserted between `LOG` and `SIG`); 3 new files: `AyCode.Core/docs/AUTH/README.md`, `AUTH_ISSUES.md`, `AUTH_TODO.md` | -| LLMP-DEC-50 | 2026-04-26 | New Rule #6 added to all primary `copilot-instructions.md` — Authority, Rule scope, Skill invocation (3 general behavioral principles) | **Diagnosis from real-world session evidence**: a parallel session reviewing FruitBank plugin docs surfaced 5 distinct misinterpretation patterns: (1) inventing topic codes ad-hoc without consulting the canonical registry; (2) proposing TOC-with-offset re-read patterns that work around the no-re-read rule's scope; (3) inventing custom URL schemes (`@Repo:`) outside markdown standard; (4) proposing empty `_ISSUES.md` files without applying the established Status convention; (5) manually reimplementing a skill's workflow instead of invoking the skill. Five distinct surfaces, **one root cause**: the session knew skills/rules existed at the surface but did not follow references to depth, did not treat authoritative registries as binding, and improvised over canonicalized procedures. **Plus self-evidence**: this assistant slipped THREE times using `vN.M` version-label colloquialism in conversation despite LLMP-DEC-47 explicitly forbidding the pattern — proof that Decision Log entries alone do NOT propagate to behavior. Decision Log governance is not session-start mandatory load; rules in `copilot-instructions.md` are. **Fix**: codify three **general** behavioral principles as Rule #6 in all 5 primary `copilot-instructions.md` files. (a) **Authority before proposal** — verify against authoritative source before inventing categories/IDs/conventions. (b) **Rule implications are part of the rule** — apply rules conservatively, don't work around scope with novel patterns. (c) **Skill invocation preferred over reimplementation** — invoke skills explicitly rather than ad-hoc reimplementation. **General, not workspace-specific**: the rule text mentions NO specific registry, skill, convention, or workspace artifact — it states principles applicable to any registry, any skill, any future workspace. **Why Rule #6, not Rule #2 extension**: Rules #1-5 are state/input/output mechanics (LOADED_DOCS prefix, docs-before-code, no-re-read, context-recovery, modification consent); Rule #6 is **behavioral correctness** of how proposals are formed — separate functional category, separate rule. **Coverage**: Authority covers misinterpretations 1, 3, 4; Rule implications covers 2; Skill invocation covers 5 — full 5/5 of observed patterns. **Why this might still not be enough**: even codified rules slip in agent behavior (the v-label evidence). Multi-LLM independent validation remains structurally necessary as the final safety net; rule-text shifts the probability, doesn't reach 100%. | `5× primary copilot-instructions.md` (new Rule #6 inserted after Rule #5, before `## Session Setup`) | -| LLMP-DEC-51 | 2026-04-26 | Removed `Mango/FruitBank/` deployment-host folder — REPOS.md inherit count 3 → 2, total 8 → 7 | The `Mango/FruitBank/` folder was originally created (LLMP-DEC-16, LLMP-DEC-19) as a nopCommerce deployment host for the FruitBank company, intended to host `Nop.Plugin.Misc.AIPlugin`. User confirmed the folder is no longer used — empty except for the legacy `.github/copilot-instructions.md`. **Pre-removal content audit**: the file contained only deployment-host meta (host-role description, `@repo` block declaring `type=host, layer=4`, scope-guidance for what NOT to write here, pointers to plugin and framework docs). NO substantive content about the plugin (later renamed MGFBANKPLUG) or FruitBank-Nop code (later renamed FBANKNOP) — pure host-side metadata, irrelevant once the host doesn't exist. **Removed**: `Mango/FruitBank/.github/copilot-instructions.md`, the `.github/` folder, and the parent `Mango/FruitBank/` folder (now empty). **Updated**: `protocol-audit/references/REPOS.md` — inherit count 3 → 2, total entries 8 → 7. **Historical record preserved**: LLMP-DEC-15 (plugin file fill, separate concern), LLMP-DEC-16 (host file fill), LLMP-DEC-19 (host purpose resolution) remain in the Decision Log per append-only governance — they describe a past state of the workspace. **Phase 0.5 of the ID-format migration (LLMP-DEC-50 design context)**: this cleanup is prerequisite to Phase 1, so the upcoming `REPO_PREFIXES.md` reflects the actual 7-repo workspace topology (no MGFBANKHOST prefix needed). | deleted: `Mango/FruitBank/.github/copilot-instructions.md`, `Mango/FruitBank/.github/`, `Mango/FruitBank/`; updated: `protocol-audit/references/REPOS.md` (Inherit table row 8 removed; own-dep-repos Inherit table Mango.FruitBank row removed) | -| LLMP-DEC-52 | 2026-04-26 | Corrective addition to LLMP-DEC-51: deployment-host context re-attributed to FBANKNOP (FruitBank nopCommerce Server) docs | **LLMP-DEC-51 over-pruned**: the agent's content audit before deletion concluded "no substantive content to migrate from the `Mango/FruitBank/` folder" — but the user identified that the deployment-context information (this FruitBank product targets a nopCommerce instance hosting `Nop.Plugin.Misc.AIPlugin` plugin for the FruitBank company) IS meaningful workspace-topology information, not pure host-side metadata. The deleted folder's role description and hosted-plugin pointer were workspace-relevant — they document a real relationship between FBANKNOP (the server-source product) and MGFBANKPLUG (the plugin source). Without that info, the workspace loses the explicit "this source compiles and deploys here" relationship statement. **Fix**: added a new `## Deployment & Hosting` section to `Mango/Source/FruitBank/.github/copilot-instructions.md` (FBANKNOP's primary instruction file). The section captures: (a) FBANKNOP is the nopCommerce server source for a runtime instance; (b) the runtime hosts MGFBANKPLUG; (c) deployment config / runtime state is external to source repo; (d) historical note that `Mango/FruitBank/` folder was the previous tracking location, now removed per LLMP-DEC-51, with the deployment-context info now living at FBANKNOP (where the source code resides). **Append-only preserved**: LLMP-DEC-51 itself is NOT modified — this corrective entry stands as the augmentation. **Why FBANKNOP, not MGFBANKPLUG**: per user judgment ("inkább a FBANKNOP a valószínűbb"), the deployment-context is more naturally attached to the broader server source (FBANKNOP) than to the plugin source (MGFBANKPLUG); the plugin is one component within the deployment, not the deployment itself. **Process lesson for future cleanups**: pre-deletion content audits must distinguish between (a) pure folder-meta (irrelevant once folder is gone) and (b) workspace-topology references that survive folder removal — the latter need explicit re-attribution, not deletion. | `Mango/Source/FruitBank/.github/copilot-instructions.md` (new `## Deployment & Hosting` section inserted between `## Workspace Dependencies` and `## Shared Agent Skills`) | | LLMP-DEC-53 | 2026-04-26 | Phase 1 of ID-format migration: created `REPO_PREFIXES.md` workspace prefix registry | First foundation step of the per-repo prefix namespace migration designed in LLMP-DEC-50. **Created**: `AyCode.Core/.github/REPO_PREFIXES.md` — workspace-meta-tooling registry listing 7 repo prefixes (ACCORE, ACBLAZOR, MGNOPLIB, MGNOPCORE, MGFBANKPLUG, FBANKNOP, FBANKAPP) plus the LLMP-DEC bare exception (workspace-meta, single-file serialization). The registry includes: full ID format spec (`---`), 4-char random alphanumeric suffix `[A-Z0-9]` specification with generation rules (~1.7M combinations per topic-type-prefix triple), archive-time collision detection policy (skill aborts on collision, signals user, manual resolution), cross-references to `TOPIC_CODES.md` and `REPOS.md`, and add/remove workflow with explicit collision-check against C# class-name prefixes. **Workspace-meta-tooling exception preserved**: this registry lists prefixes across all layers (framework, shared libs, consumer products) — Framework-First Design Principle exception per existing convention (mirroring `TOPIC_CODES.md` and `REPOS.md` scope-note). **No entry IDs renamed yet** — this phase is purely the registry creation; existing IDs (LOG-I-N, BIN-I-N, etc.) remain unchanged. Phase 2 (TOPIC_CODES.md scope-note + format-rule update for the new 4-component ID), Phase 3 (skill `SKILL.md` updates with placeholder examples + ID-generation guidance + cross-repo glob), Phase 4 (mapping table — `OLD_ID → NEW_ID`), Phase 5 (per-topic rename of existing entries to new format), Phase 6 (cross-file cross-ref cleanup — ADRs, Decision Log, code comments, hash anchors), Phase 7 (final verification + completion entry) follow per the LLMP-DEC-50 plan. **User pre-Phase 1 commit established a rollback point**: if any phase produces unexpected state, `git reset` to the pre-migration tag is the safety net. | new file: `AyCode.Core/.github/REPO_PREFIXES.md` | | LLMP-DEC-54 | 2026-04-26 | Phase 2 of ID-format migration: `TOPIC_CODES.md` updated for 4-component ID format and per-repo registry awareness | Phase 2 of the LLMP-DEC-50 migration. Updated `AyCode.Core/.github/skills/docs-check/references/TOPIC_CODES.md` in 8 sections to align with the new prefix scheme established in Phase 1 (LLMP-DEC-53, `REPO_PREFIXES.md`). **Changes**: (a) **Scope note** acknowledges per-repo `TOPIC_CODES.md` possibility (each repo may host its own at `/.github/skills/docs-check/references/TOPIC_CODES.md`); points to `REPO_PREFIXES.md` for the prefix scheme; flags that the legacy multi-repo Topic codes table will migrate in subsequent phases. (b) **Brief intro** updated to reference full 4-component ID format with cross-link to `REPO_PREFIXES.md`. (c) **Why this registry exists** — example IDs upgraded from 3-component (`LOG-I-5`) to 4-component (`ACCORE-LOG-I-K7M2`). (d) **Distinctions section** — `LOG-C-1` example upgraded to `ACCORE-LOG-C-K7M2`. (e) **ID format rules** restructured: 6 rules → 5 rules (former rules 2 "Sequential number" + 3 "Counter scope" merged into new rule 2 "Random suffix" with 4-char `[A-Z0-9]` spec); LLMP exception explicit; full prefixed form mandatory in hash anchors. (f) **Registry maintenance workflow** — 5 steps → 7 steps; per-repo `TOPIC_CODES.md` ownership clarification; topic codes need NOT be globally unique (prefix disambiguates); collision check both against C# class-name prefixes AND within same repo's TOPIC_CODES.md. (g) **Examples** updated: all 13 examples use full 4-component placeholder format with realistic `` illustrations + LLMP bare exception; explicit note that `` is illustrative not actual. (h) **Cross-references section** — bare-ID-may-be-used wording removed (full prefixed form mandatory); workspace-registries entry added cross-linking to `REPO_PREFIXES.md`. **No existing entry IDs renamed** — Phase 2 is purely the convention update; the Topic codes table currently still lists all workspace topics (legacy state), to be migrated to per-repo registries in Phase 4-5. **Phase 1 + Phase 2 together establish the FORMAT FOUNDATION**; Phase 3 (skill `SKILL.md` updates with placeholder examples + ID-generation guidance + cross-repo glob), Phase 4 (mapping table), Phase 5 (per-topic existing-entry rename), Phase 6 (cross-file ref cleanup), Phase 7 (final verification) follow. | `docs-check/references/TOPIC_CODES.md` (Scope note, brief intro, "Why this registry exists", Distinctions, ID format rules, Registry maintenance, Examples, Cross-references — 8 sections updated) | | LLMP-DEC-55 | 2026-04-26 | Phase 3 of ID-format migration: skill `SKILL.md` files updated for 4-component ID format and per-repo registry awareness | Phase 3 of the LLMP-DEC-50 migration. Updated 4 skill `SKILL.md` files + 1 reference template to align with the format foundation established in Phases 1-2 (LLMP-DEC-53 `REPO_PREFIXES.md`, LLMP-DEC-54 `TOPIC_CODES.md`). **`docs-check/SKILL.md`** (5 edits): (a) Step 5 Proposed ID spec — `{TOPIC}-{TYPE}-{N}` → `---`, with both registries cross-linked, random-suffix generation procedure (glob + collision-check + regenerate), `` source clarification (active repo's). (b) Sub-category example — `## SIG-I-4 [PROTO]: ...` → `## ACCORE-SIG-I-K7M2 [PROTO]: ...`. (c) Topic code selection — per-repo TOPIC_CODES.md awareness, prefix-disambiguation note, cross-repo XCUT case flagged as not-formalized, new-topic proposal references Registry maintenance workflow. (d) Step 6 renamed "Status update on fix" → "Status update on close" — aligned with LLMP-DEC-44 vocabulary (Open/InProgress/Closed); example anchor updated to full prefixed form; Resolution sub-section requirement added per Status field conventions. (e) Output template — `[tentative: TOPIC-TYPE-N]` → `[tentative: ---]`. **`docs-discovery/SKILL.md`** (2 edits): (f) Archive file ID example — `LOG-I-X` → `ACCORE-LOG-I-K7M2`. (g) NEW section "Cross-repo ID search" — describes prefix-wildcard glob patterns (`**/*-LOG-I-*`, `**/*-MEAS-T-*`) for finding entries of a topic across all repos, complementing Step 2's topic-folder discovery; explicit "globs do the work, no central index" principle. **`docs-archive/SKILL.md`** (1 edit): (h) Year-derivation example updated — `Fixed 2026-04-25`, `Won't fix 2026-04-25`, `LOG-I-X` → `Status: Closed (2026-04-25)`, `### Resolution` sub-section, `ACCORE-LOG-I-K7M2`; explicit Status vocabulary alignment with TOPIC_CODES.md (only Closed archives). **`adr-author/SKILL.md`** (1 edit): (i) Step 8 #4 follow-up TODO format — `{TOPIC}-T-N` → `--T-` with cross-link to TOPIC_CODES.md and REPO_PREFIXES.md. **`adr-author/references/ADR_TEMPLATE.md`** (1 edit): (j) Related TODOs/Issues placeholder — `` → realistic 4-component placeholders with registry cross-link. **No existing entry IDs renamed** — Phase 3 is purely skill-text update; existing entries (e.g., `LOG-I-1` through `LOG-I-10` in LOGGING_ISSUES.md) remain in legacy 3-component format until Phase 5 migrates them. **Phases 1-3 complete = format foundation done**; Phase 4 (mapping table OLD_ID → NEW_ID for existing entries), Phase 5 (per-topic existing-entry rename), Phase 6 (cross-file ref cleanup including ADR / Decision Log / code comments), Phase 7 (final verification + completion entry) follow per LLMP-DEC-50. | `docs-check/SKILL.md` (Steps 5/6, output template); `docs-discovery/SKILL.md` (Archive section example + new "Cross-repo ID search" section); `docs-archive/SKILL.md` (year-derivation example + Status vocabulary alignment); `adr-author/SKILL.md` (Step 8 #4 follow-up TODO format); `adr-author/references/ADR_TEMPLATE.md` (Related TODOs/Issues placeholder) | @@ -179,6 +130,9 @@ The "primary" vs "inherit" distinction is defined in `protocol-audit/references/ | LLMP-DEC-62 | 2026-04-26 | Three protocol-stack additions: (a) `META` topic for meta-tooling issues/TODOs; (b) docs-side Framework-First rule with bounded `CONSUMERS.md` exception; (c) `adr-author` skill complexity-aware ask-back trigger restructure | **User-driven coherent batch** addressing 3 long-tail observations from the Phase 1-6 migration: **(1) Mental tracking failure** for protocol-stack issues. The 5-skill stack + 7 repos + per-repo registries had grown complex enough that issues observed mid-session (e.g., `LOGGING_TODO.md` L88 path/anchor typo, `Current protocol state` summary staleness, `docs-check` runtime-discovery deferral, anchor-mismatch typo class) had no formal home — they either landed in LLMP-DEC entries (which are meant for closed decisions, not open issues) or got lost. **Fix**: new `META` topic registered in `TOPIC_CODES.md` (ACCORE-META-*); `META_ISSUES.md` + `META_TODO.md` created at `AyCode.Core/.github/`; seeded with 3 META-T entries from the migration's deferred items: `ACCORE-META-T-J9N4` (docs-check runtime discovery for per-repo TOPIC_CODES.md), `ACCORE-META-T-K2P7` (protocol-audit anchor-mismatch detection invariant), `ACCORE-META-T-F8R3` (Current protocol state summary auto-staleness detection). Empty-state ISSUES file with template. **(2) Docs-side Framework-First** was implicit but not codified. Phase 5.1 (LLMP-DEC-58) retightened `.github/`, but `docs/` files still allowed cross-layer references in principle. User clarified the rule extends to `docs/` AND added a **bounded consumer-awareness exception**: a single `CONSUMERS.md` per repo MAY list higher-layer consumers for change-impact assessment when working in that repo. **Fix**: new sub-bullet in `AyCode.Core/.github/copilot-instructions.md` `## Framework-First Design Principle` section after the Phase-5.1 workspace-meta-history exception paragraph; new file `AyCode.Core/CONSUMERS.md` listing the 6 known ACCORE consumers (ACBLAZOR, MGNOPLIB, MGNOPCORE, MGFBANKPLUG, FBANKNOP, FBANKAPP) with brief usage notes + change-impact lens. The `CONSUMERS.md` is the SINGLE place in ACCORE allowed to name consumer repos; other docs / code stay consumer-agnostic. Top-of-tree consumer products (FBANKNOP, FBANKAPP) need no own CONSUMERS.md. **(3) `adr-author` skill over-trigger / under-trigger.** The previous "When to invoke" section had a flat list of trigger phrases ("let's plan X", "design Y", "döntsük el Y vagy Z") that fired too liberally for trivial planning AND missed architectural intent without the explicit "ADR" keyword. User proposed a 3-tier model: explicit ADR-keyword → auto-trigger; implicit planning + complexity-sniff → ASK-BACK; trivial → no trigger. **Fix**: `adr-author/SKILL.md` `## When to invoke` section restructured into 4 sub-cases — "Explicit ADR invocation (auto-trigger)" / "Implicit planning request (ASK BACK)" / "Trivial — no ADR" / "Proactive flag (drift)". Complexity-sniff heuristics enumerated explicitly (cross-cutting, cross-repo, reversibility-low, ≥2 alternatives, vocabulary signals, re-openable, new-API). Ask-back template is bilingual (Hungarian + English). Default behaviour: ASK if complexity-sniff fires; never silently auto-invoke. **Coherence**: the 3 changes reinforce each other — META topic gives meta-tooling issues a durable home; CONSUMERS.md formalizes a Phase 5.1 implicit gap with a Framework-First-respecting design; adr-author refinement reduces over-classification of "design discussion" as ADR-worthy (which would otherwise pollute the META topic with mis-classified entries). **Self-evidence**: this very batch was tested against the new adr-author trigger logic — user said *"de most nem kell ehhez adr"* (= "no ADR needed for this") and asked for the 3 changes done in one go; the new SKILL.md flow correctly handles this as "Implicit planning + ASK BACK + user said 'no'" → no `adr-author` skill invocation, just structured execution. | new files: `AyCode.Core/.github/META_ISSUES.md`, `AyCode.Core/.github/META_TODO.md` (3 seeded TODOs), `AyCode.Core/CONSUMERS.md`; modified: `AyCode.Core/.github/skills/docs-check/references/TOPIC_CODES.md` (META row added between XCUT and LLMP), `AyCode.Core/.github/copilot-instructions.md` (Framework-First section sub-bullet for docs-side rule + CONSUMERS.md exception), `AyCode.Core/.github/skills/adr-author/SKILL.md` (`## When to invoke` section restructured into 4 sub-cases) | | LLMP-DEC-63 | 2026-04-26 | Filed 7 META-TODO entries from cross-source improvement review (3 parallel Copilot reviews + own analysis); codified workspace cost-function principle: **correctness > token-economy** | **User-initiated meta-review of protocol-stack improvement opportunities**, surfaced via 3 parallel Copilot session reviews after the LLMP-DEC-62 batch landed. The reviewers proposed ~17 candidate improvements across docs structure, skill behaviour, ADR governance. Cross-source convergence analysis (3-of-3, 2-of-3, 1-of-3, already-covered) identified genuine signal vs. individual ideas vs. overengineering. **User reframing of the cost function** — the reviewers' suggestions implicitly assumed "minimize tokens" as calibration goal, but user clarified: *"felesleges kör költsége >> tokenköltség. inkább több, mint hibás."* (wasted-round cost dominates token cost; prefer broader loading over wrong-answer-then-retry). This **extends the existing amortization principle (LLMP-DEC-43) from session-start-only to per-turn decisions** — every turn faces (a) read-then-answer vs. (b) guess-then-maybe-be-wrong; default toward (a). **7 new META-TODO entries filed** in `META_TODO.md` (LLMP-DEC-62's `META` topic infrastructure proven useful in its first week of existence): `ACCORE-META-T-M5T8` (TL;DR / "When to read" blocks on topic READMEs — 3-of-3 reviewer convergence + user agreement, P2); `ACCORE-META-T-Y4Q9` (Hot-path / Fast-path tagging — single-source, **recalibrated to P3** by user reframing because "load more" preference reduces fast-path criticality); `ACCORE-META-T-V7L2` (ADR quality lint, warning-mode not hard-fail, P3); `ACCORE-META-T-N8K3` (Last-verified-commit opt-in metadata for anti-hallucination drift detection, P3); `ACCORE-META-T-P9F4` (pre-load expansion with foundational reference docs — direct application of user reframing, P2); `ACCORE-META-T-R2W6` (workspace user-preference statement codifying "correctness > token-economy" — the meta-rule, P2); `ACCORE-META-T-C5J7` (docs-check / docs-discovery cap revisit refining LLMP-DEC-27, direct application, P3). **Implementation dependency clusters**: the P2 trio R2W6 → P9F4 → C5J7 should land together (R2W6 codifies the preference; P9F4 applies it to session-start; C5J7 applies it to skill behaviour) — half-state would be inconsistent; M5T8 → Y4Q9 are parent-child convention pair (TL;DR is the bigger signal, fast-path is finer-grained child); V7L2 + LLMP-DEC-62-era K2P7 are lint-family synergy candidates (one validates ADR structure, the other validates cross-ref anchors). **No implementation in this entry** — pure filing. The entries themselves are the actionable plan; **this LLMP-DEC documents the cost-function clarification** as a new protocol principle (which belongs in the Decision Log even before R2W6 codifies it into `copilot-instructions.md`, because the principle now governs subsequent agent behaviour as a known user preference even when the rule text isn't yet present). **Self-evidence again**: this very review — 3 Copilot reviews + user reframing → my recalibration → 7 META-T filed — exercised the LLMP-DEC-62 adr-author flow correctly: planning-language was used (`mi a véleményed`), complexity-sniff fired (≥2 alternatives, cross-cutting impact, new-API), I asked back (`Akarod hogy LLMP-DEC-63-at is felírjam`), user said yes → execute. No spurious ADR; no ad-hoc structural decision without confirmation. | `AyCode.Core/.github/META_TODO.md` (7 new entries `M5T8 / Y4Q9 / V7L2 / N8K3 / P9F4 / R2W6 / C5J7` inserted between `ACCORE-META-T-B6V2` and the TODO entry template — total META-T entries now 11) | | LLMP-DEC-64 | 2026-04-27 | Fixed `protocol-audit/SKILL.md` C4 + X1 invariant text drift (5-skill matrix wording stale since LLMP-DEC-43); broadened `ACCORE-META-T-F8R3` scope to cover SKILL.md / registry text drift class | A parallel Claude session ran the post-Phase-5.1 `protocol-audit` skill against the workspace and surfaced **3 stale text references in `protocol-audit/SKILL.md` itself** — a positive self-evidence event for the runtime-discovery audit design (LLMP-DEC-58). All 3 share the SAME root cause: **LLMP-DEC-43** introduced the 5-skill 2-reactive/3-user-gated matrix (2 mandatory pre-loaded: `docs-discovery` + `docs-check`; 3 lazy-loaded: `protocol-audit` + `adr-author` + `docs-archive`); the `copilot-instructions.md` files (5 primary + 2 inherit) updated correctly to list all 5 skills + classification, but `protocol-audit/SKILL.md` invariant texts did not. **Drifts identified**: (i) C4 invariant text said *"all three skills"* — stale since 3-skill era; (ii) C4 expected `[LOADED_DOCS]` counts said *"4 for primary, 5 for inherit"* — stale (correct counts after LLMP-DEC-43: **3 for primary, 4 for inherit**, since 3 user-gated skills no longer pre-load); (iii) X1 invariant said *"all three bullets must be listed"* — same stale 3-skill list. **Audit impact**: the actual instruction files PASS (their `## Shared Agent Skills` now has 5 bullets, which is a SUPERSET of the stale 3-bullet check), but the invariant TEXT was misleading and would mislead future maintainers. **Patches applied**: 2 Edits to `protocol-audit/SKILL.md` — C4 rewritten to require reactive/user-gated classification + correct counts (3/4); X1 rewritten to require all 5 bullets with reactive/user-gated labels. **Broader META observation**: this is a **SKILL.md text drift class** parallel to the `Current protocol state` summary drift class previously captured in `ACCORE-META-T-F8R3`. F8R3's description was broadened (3 Edits to `META_TODO.md`) to cover BOTH classes — the auto-staleness detection (when implemented) catches `LLM_PROTOCOL_DECISIONS.md` summary drift AND any SKILL.md / registry text describing 'current state'. **Self-evidence (positive)**: the protocol-audit skill flagged its OWN SKILL.md content drift — exactly the design intent of LLMP-DEC-58 runtime-discovery audit (catches real maintenance debt). The Copilot session's report explicitly noted *"a runtime-discovery audit design (LLMP-DEC-58) is working as intended, surfacing real maintenance debt"* — independent confirmation. | `protocol-audit/SKILL.md` (C4 + X1 invariant text rewrites); `META_TODO.md` (`ACCORE-META-T-F8R3` description + parallel-drift-class section + Fix-direction options widened) | +| LLMP-DEC-65 | 2026-04-27 | Topic-code length cap raised 2-5 → 2-6 in `TOPIC_CODES.md` | Adding the new `SIGDS` topic (5 chars, fits the prior cap) prompted a forward-looking review of the topic-code length spec. The 2-5 cap originally derived from C# class-name visual-distinction concerns (≥3 to avoid `Ac*`/`Mg*` collision; ≤5 to keep IDs visually compact). User judgment: future composite topics (transport-prefixed DataSource variants, multi-domain layered topics) may benefit from one extra char of namespace headroom. Existing 9 ACCORE topics max at 4 chars (XCUT, AUTH, META, LLMP, TOON) — non-breaking change. The 2-6 range still stays well below the `@repo.prefix` 4-12 char range — visually distinct. **Two edits**: `TOPIC_CODES.md` Step 1 ("(2-5 uppercase chars)" → "(2-6 uppercase chars)") and Collision-avoidance section ("are 2-5 chars" → "are 2-6 chars"). Class-name collision rule preserved (no `Ac*`/`Mg*` start). | `docs-check/references/TOPIC_CODES.md` (2 sentence-level edits — Registry maintenance Step 1 + Collision avoidance section) | +| LLMP-DEC-66 | 2026-04-27 | Created `SIGDS` topic (`SIGNALR_DATASOURCE`) — registered in `TOPIC_CODES.md`, scaffolded `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/{README, SIGNALR_DATASOURCE_ISSUES, SIGNALR_DATASOURCE_TODO}.md`, relocated DataSource doc from sibling `SIGNALR/` folder, updated 15 cross-refs across AyCode.Core (9) + AyCode.Blazor (6); README rewrite incorporates 7 doc-vs-code drift fixes + Sample-placeholder Framework-First cleanup; 3 new entries (B-T4K9 / I-W2H6 / T-N5R8) | `AcSignalRDataSource` is conceptually a **client-server DataSource** (change tracking, rollback, sync state, lifecycle events, `IList` wrapper) — the SignalR transport is one current implementation detail, not the topic's defining identity. Previous placement under the `SIG` topic conflated transport concerns with state-management concerns. **Topic chosen**: `SIGDS` (5 chars, within the 2-6 cap raised in LLMP-DEC-65) — `SIG` prefix preserves "SignalR-coupled DataSource" identity (distinguishes from any future `RESTDS`, `GRPCDS` etc.); `DS` suffix is the universal DataSource shorthand. **Topic name**: `SIGNALR_DATASOURCE` (matches existing `SIGNALR_BINARY_PROTOCOL` uppercase+underscore convention). **Folder migration**: `AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md` → `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` (folder + paired `SIGNALR_DATASOURCE_ISSUES.md` + `SIGNALR_DATASOURCE_TODO.md`). **README content rewrite** incorporates 7 doc-vs-code drift fixes identified in pre-migration code review: (a) abstract class declaration explicit + subclassing example; (b) `SerializerType` property + JSON/GZip path documented; (c) full `LoadDataSource*` overload set including in-memory `LoadDataSource(TIList fromSource, ...)`; (d) fallback re-serialize path in `LoadDataSourceFromResponseData`; (e) missing public methods enumerated — `AddRange`, `TryRemove`, `TryGetValue`, `TryGetIndex`, `AsReadOnly`, `BinarySearch`; (f) `TrackingState.Get` added to event/state values; (g) `TryRollbackItem(id, out originalValue)` signature shown. **Framework-First cleanup**: replaced consumer-leaking `Order*` placeholder (`OrderGetAll = 300`, etc.) with domain-agnostic `Sample*` (`SampleGetAll = 300`, etc.) — Layer 0 doc no longer references consumer domain types. **Cross-ref updates** (15 references): `AyCode.Core/.github/copilot-instructions.md` Layer #151; `AyCode.Core/README.md` doc-folder table cell; `docs/GLOSSARY.md`; `docs/CONVENTIONS.md`; `AyCode.Services/SignalRs/README.md`; `AyCode.Services.Server/SignalRs/README.md`; `AyCode.Services.Server/README.md`; `AyCode.Services.Server/docs/SIGNALR/README.md` (relative cross-ref `SIGNALR_DATASOURCE.md` → `../SIGNALR_DATASOURCE/README.md`); `AyCode.Services/docs/SIGNALR/README.md`; AyCode.Blazor: `docs/GLOSSARY.md` (×2 same path), `MGGRID/README.md` (×2 same path), `MGGRID/MGGRID_DATASOURCE.md`, `MGGRID/MGGRID_PARAMETERS.md`. **3 new entries**: `ACCORE-SIGDS-B-T4K9` (SaveChangesAsync inner Task drop), `ACCORE-SIGDS-I-W2H6` (BinarySearch NotImpl), `ACCORE-SIGDS-T-N5R8` (ChangeTracking Dictionary perf refactor — pre-existing `//TODO: Dictionary... - J.` comment). **Existing `ACCORE-SIG-I-T7S2`** (GetAll raw byte[] for populate/merge) stays in `SIGNALR_ISSUES.md` per append-only ID rule — its body has cross-cutting transport+DataSource concerns, naturally lives under `SIG`; the new `SIGNALR_DATASOURCE_ISSUES.md` opens with a cross-ref pointer to it. | `docs-check/references/TOPIC_CODES.md` (new `SIGDS` row inserted between `SBP` and `BIN`); 3 new files: `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md`, `SIGNALR_DATASOURCE_ISSUES.md`, `SIGNALR_DATASOURCE_TODO.md`; deleted: `AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md`; modified: 15 cross-ref locations across `AyCode.Core` (9 files) + `AyCode.Blazor` (4 files, 6 occurrences) | +| LLMP-DEC-67 | 2026-04-27 | Decision Log retention policy revised: **last-15-active rolling window + year-month bucket archives** (supersedes LLMP-DEC-25's "annual at ~50"); first archive operation executed (LLMP-DEC-1..52 → `LLM_PROTOCOL_DECISIONS_2026_04.md`); `docs-archive/SKILL.md` Rule A + Rule B refactor | **User-driven policy revision triggered by acute pain**: this `LLM_PROTOCOL_DECISIONS.md` file had grown past 25K tokens (multiple LLM sessions flagged the size as routine pre-load cost). The original LLMP-DEC-25 archival plan ("annual split at ~50 entries") was set when the protocol stack was nascent and entry velocity low. The April 2026 ID-format migration (LLMP-DEC-50..63 batch) generated 14 entries in 2 days; year-bucket archives would still grow into 100+-entry monsters during similar future high-velocity periods. **Two coordinated changes** based on user input *("inkább csak az utolsó 10 [→ 15] active entry-t tartsuk meg, többit archiválni; year+month bucket year helyett")*: **(A) Retention rule shift**: from "annual at ~50" to **last-N-active rolling window + year-month bucket archives**, where N = 15 (compromise between user's initial "10" suggestion and the migration-batch size of 14 entries — 15 keeps a complete recent initiative + buffer). **(B) Bucket granularity shift**: from `*_.md` to `*__.md`. Sparse files OK — only month-buckets containing archived entries get a file. Year-month scales for high-velocity periods (a heavy month produces a manageable file, a quiet month produces no file). **First archive operation**: LLMP-DEC-1..52 (2026-04-20 through 2026-04-26) moved to `LLM_PROTOCOL_DECISIONS_2026_04.md`. Active log now contains LLMP-DEC-53..67 (15 entries). **Second-pass archive note**: parallel sessions added LLMP-DEC-65 (topic-code length cap raise) and LLMP-DEC-66 (SIGDS topic creation) AFTER my drift-fix LLMP-DEC-64 but BEFORE this entry; the policy entry was originally planned as LLMP-DEC-65, became 67. The archive operation extended from 49 entries (LLMP-DEC-1..49) to 52 (LLMP-DEC-1..52) to maintain strict 15-cap at this entry's commit (without LLMP-DEC-50/51/52 archived too, active count would have been 18). **Cross-link integrity**: archive file is on-disk, on-demand readable; references from active entries to archived IDs (e.g., LLMP-DEC-58 references LLMP-DEC-43, LLMP-DEC-50) work — readers open the archive when following a link. IDs are append-only and stable across active ↔ archive boundaries. **Foundational decisions preserved**: the `## Current protocol state (quick reference)` summary at the top of the active file (introduced by LLMP-DEC-25, refreshed by LLMP-DEC-60) stays unchanged — survives all archiving. Foundational decisions (Rules #1-6, ID format spec, governance, etc.) reachable via the summary even when their dated entries are archived. **`docs-archive/SKILL.md` updates** (6 edits): frontmatter description rewritten; intro rewritten; `## Archive criterion (single rule)` restructured into `## Archive criteria (two rules)` with Rule A (Status-based for ISSUES/TODO) + Rule B (Last-15-active for DEC log) + "Why two rules" rationale; Step 4 updated to year-month bucket + sparse-files clause; pointer block example updated; Step 7 fully rewritten. **Governance section in summary** updated: LLMP-DEC-25-era "Archive annually at ~50" bullet replaced with "Last-15-active + year-month bucket" wording, cross-linking LLMP-DEC-67. **Active entry count = 15** — next archive triggers at LLMP-DEC-68 (LLMP-DEC-53 would rotate). | new file: `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS_2026_04.md` (52 entries); modified: `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` (entries 1..52 removed via two sed passes; pointer block added + updated; governance bullet rewritten); `AyCode.Core/.github/skills/docs-archive/SKILL.md` (6 edits) | ## Known follow-ups diff --git a/.github/LLM_PROTOCOL_DECISIONS_2026_04.md b/.github/LLM_PROTOCOL_DECISIONS_2026_04.md new file mode 100644 index 0000000..1492871 --- /dev/null +++ b/.github/LLM_PROTOCOL_DECISIONS_2026_04.md @@ -0,0 +1,78 @@ +# LLM Protocol Decisions — Archive: 2026-04 + +Archived entries from `LLM_PROTOCOL_DECISIONS.md` per the **last-15-active retention policy** (LLMP-DEC-65). All entries here have IDs in the LLMP-DEC namespace; year-month bucket = **2026-04** (entries dated 2026-04-XX). + +> **Archive files are NOT auto-loaded** by `docs-discovery` or any session-start pre-load. Read on-demand when historical context is needed (e.g., a recent entry references LLMP-DEC-X — open this file to read the full text). IDs are preserved (never reassigned). Format identical to the active log. +> +> **For the currently-active protocol state**, see the `## Current protocol state (quick reference)` section at the top of `LLM_PROTOCOL_DECISIONS.md` (active log) — that summary is kept fresh per LLMP-DEC-25 / LLMP-DEC-60 governance and supersedes any specific historical claim recorded in the dated entries below. +> +> **Cross-link integrity**: cross-references from active log entries to entries in this archive (e.g., `LLMP-DEC-58` referencing `LLMP-DEC-43`) work as before — open this file when following a link. The link target IDs in this file are stable. + +## Archived range + +- **From**: LLMP-DEC-1 (2026-04-20) +- **To**: LLMP-DEC-52 (2026-04-26) +- **Count**: 52 entries + +## 2026-04 + +| ID | Date | Decision | Rationale | Affected | +|---------------|------------|-------------------------------------------------------|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| +| LLMP-DEC-1 | 2026-04-20 | Added CROSS-REPO HARD-GATE to Rule #2 | Docs-before-code was applied only to the own repo, not external deps | `5× primary` | +| LLMP-DEC-2 | 2026-04-20 | Added PER-QUESTION DOC-FIRST to Rule #2 | LLM skipped checking for relevant `.md` before jumping to code search | `5× primary` | +| LLMP-DEC-3 | 2026-04-21 | Expanded Rule #5 scope: "code/files" → "any file..." | Memory / config / docs edits also need consent; old wording too narrow | `5× primary` | +| LLMP-DEC-4 | 2026-04-22 | Added Auto-detection triggers to Rule #4 | "realize" was subjective; post-compaction reset to `[LOADED_DOCS: NONE]` didn't fire reliably | `5× primary` | +| LLMP-DEC-5 | 2026-04-22 | Added "in context" definition to Rule #3 | Summary content was mistaken for actually-loaded docs (lossy compression) | `5× primary` | +| LLMP-DEC-6 | 2026-04-22 | Unified AyCode.Blazor Rule #3 with the other 4 repos | Was custom "CRITICAL TOOL EXECUTION FIREWALL" variant; normalized | `AyCode.Blazor/copilot-instructions.md` | +| LLMP-DEC-7 | 2026-04-22 | "strictly maintain rule X" → "rule 3" | Per-repo numbers varied (15/18/19/20/21); unified reference | `5× primary` | +| LLMP-DEC-8 | 2026-04-22 | Created `protocol-audit` skill at repo-level | Cross-repo consistency check; `.github/skills/` chosen over personal paths (DRY) | `protocol-audit/SKILL.md` + `protocol-audit/references/REPOS.md` | +| LLMP-DEC-9 | 2026-04-22 | Added `## Shared Agent Skills` section (protocol-audit) | Discoverability of AyCode.Core-hosted skills from dependent repos | `4× non-Core primary` | +| LLMP-DEC-10 | 2026-04-23 | Created `docs-discovery` skill (parallel session) | Paired-doc (`main` + `_ISSUES` + `_TODO`) auto-loading before code search | `docs-discovery/SKILL.md` + `AyCode.Core/copilot-instructions.md` | +| LLMP-DEC-11 | 2026-04-23 | Extended `## Shared Agent Skills` with `docs-discovery` (parallel session) | Both skills now listed in each dependent repo | `4× non-Core primary` + `Mango.Nop.Core/copilot-instructions.md` | +| LLMP-DEC-12 | 2026-04-24 | LOADED_DOCS prefix: full list → count+delta format | Long lists became visual noise at scale; delta preserves self-commitment | `5× primary` + `docs-discovery/SKILL.md` | +| LLMP-DEC-13 | 2026-04-24 | Created this Decision Log | Institutional memory for protocol evolution; avoid re-debating resolved choices | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` | +| LLMP-DEC-14 | 2026-04-24 | Added `## Protocol History` section | Cross-repo discoverability of the Decision Log | `4× non-Core primary` + `Mango.Nop.Core/copilot-instructions.md` | +| LLMP-DEC-15 | 2026-04-24 | Filled empty Nop.Plugin.Misc.AIPlugin instruction file | Previously 0 bytes; now minimal inherit-pattern referencing AyCode.Core + both skills + log | `Nop.Plugin.Misc.AIPlugin/copilot-instructions.md` | +| LLMP-DEC-16 | 2026-04-24 | Filled empty Mango\FruitBank instruction file | Previously 0 bytes; now minimal inherit-pattern with ⚠️ "purpose TBD" notice | `Mango/FruitBank/copilot-instructions.md` | +| LLMP-DEC-17 | 2026-04-24 | Expanded REPOS.md: 5 repos → 8 (primary + inherit) | Audit scope was incomplete; sub-project & plugin files were missed | `protocol-audit/references/REPOS.md` | +| LLMP-DEC-18 | 2026-04-24 | Fixed Mango.Nop.Core `@repo` path (7 `..` → 6 `..`) | Previous path resolved to `H:\Aycode\...` (non-existent). Corrected relative depth from repo root | `Mango.Nop.Core/copilot-instructions.md` | +| LLMP-DEC-19 | 2026-04-24 | Resolved Mango.FruitBank purpose (nopCommerce host) | Confirmed: directory is a nopCommerce deployment for FruitBank company, hosting Nop.Plugin.Misc.AIPlugin. Layer 4 (host), not TBD. Updated content accordingly. | `Mango/FruitBank/copilot-instructions.md` | +| LLMP-DEC-20 | 2026-04-24 | `protocol-audit` v1.0 → v2.0: primary/inherit invariant split | SKILL.md now applies Common + Primary invariants to rows 1-5, Common + Inherit + Cross-cutting to rows 6-8. New invariants: P3 (Rule #1 count+delta format), X1 (Shared Agent Skills), X2 (Protocol History). | `protocol-audit/SKILL.md` + `protocol-audit/references/REPOS.md` (issues cleared) | +| LLMP-DEC-21 | 2026-04-24 | Docs layout: paired topics migrated to `TOPIC/README.md + TOPIC/TOPIC_*.md` pattern (Option C) | Single `docs/` folder with flat `TOPIC_*.md` files was noisy at scale; folder grouping reinforces the "folder navigation rule" and gives each topic a canonical `README.md` entry point. Option C (README.md main + topic-prefixed companions) chosen over pure Pattern B for (a) glob-pattern compatibility with old `**/TOPIC*.md`, (b) unique LOADED_DOCS basenames for companion files, (c) GitHub README auto-render preserved. Single-file topics (ARCHITECTURE, GLOSSARY, CONVENTIONS, DTOS, etc.) kept flat. | 13 `docs/` folders across 5 repos (AyCode.Core, AyCode.Blazor, Libraries, FruitBankHybridApp, Nop.Plugin.Misc.AIPlugin); ~35 file renames/moves; 13 new `README.md` index files; 4 csproj files converted from explicit file-lists to recursive glob (`docs\**\*.md`); `docs-discovery/SKILL.md` Step 2 glob patterns updated to match Pattern B layout | +| LLMP-DEC-22 | 2026-04-24 | Rule #1 LOADED_DOCS format: "basenames only" → "shortest unique short names" | After the Pattern B docs migration, many `README.md` files share the same basename across different topic folders (e.g., `LOGGING/README.md`, `BINARY/README.md`, `SIGNALR/README.md`). A bare `README.md` in the LOADED_DOCS prefix is ambiguous and breaks the self-commitment / no-re-read mechanism. New rule: basename by default (already unique for topic-prefixed companions and flat single-file topics); `TOPIC/README.md` for topic-folder READMEs; further disambiguation upward for cross-project collisions. | `5× primary` + `docs-discovery/SKILL.md` Step 4 | +| LLMP-DEC-23 | 2026-04-24 | Full cross-reference cleanup after Pattern B migration (batch sed + targeted fixes) | After the docs migration, ~45 `.md` files contained outdated paths (flat `TOPIC_*.md` refs that are now `TOPIC/TOPIC_*.md`; renamed mains `LOGGING_SERVER.md`→`LOGGING/README.md` etc.; pre-existing depth bugs like `AyCode.Core/docs/LOGGING.md` that were always wrong depth; cross-folder sibling refs inside `SIGNALR_BINARY_PROTOCOL/` pointing to `SIGNALR/` topics by basename). Three-pass cleanup: (1) batch sed on 44 files for `docs/TOPIC*.md` → Pattern B paths; (2) second sed pass for pre-existing `AyCode.Core/docs/{LOGGING,BINARY,SIGNALR}/` → `AyCode.Core/{AyCode.Core,AyCode.Services}/docs/...` depth correction (with placeholder guard to avoid double-substitution); (3) targeted Edits for cross-folder sibling refs and project-level README doc-listing tables. Final grep: zero old-style references remain. | ~45 `.md` files across all 5 repos; AyCode.Core/copilot-instructions.md rule 8 + 19; AyCode.Blazor rule 14; FruitBankHybridApp rules 15+20; 7 project-level `README.md` "doc listing" tables; 9 MGGRID sibling refs; 5 cross-folder SIGNALR↔SIGNALR_BINARY_PROTOCOL refs | +| LLMP-DEC-24 | 2026-04-24 | Phantom-reference fixes: `docs/ARCHITECTURE.md` from `.github/` + BINARY/README.md serializer-overview target | (1) `AyCode.Core/.github/copilot-instructions.md:96` had `docs/ARCHITECTURE.md#framework-vs-consumer-boundary` which resolved to `.github/docs/ARCHITECTURE.md` (non-existent) relative to the file's own location. Fixed to `../docs/ARCHITECTURE.md#framework-vs-consumer-boundary` so the path resolves to the existing repo-root `docs/ARCHITECTURE.md`. (2) `AyCode.Core/AyCode.Core/docs/BINARY/README.md:22` pointed to `docs/ARCHITECTURE.md` for "Serialization overview (Toon vs AcBinary vs AcJson)". The new `TOON/README.md` (created by a parallel session) uses the more canonical `../../Serializers/README.md` — the serializer-framework-level README that genuinely compares all three formats. Aligned BINARY/README.md to the same target for consistency. | `AyCode.Core/.github/copilot-instructions.md` + `AyCode.Core/AyCode.Core/docs/BINARY/README.md` | +| LLMP-DEC-25 | 2026-04-24 | Added "Current protocol state (quick reference)" section to the top of the Decision Log | The log grows monotonically (append-only); readers landing on it shouldn't have to scan every dated entry to learn the currently-active protocol. The new top-of-file summary captures Rules #1-5, docs layout convention, instruction-file inventory (5 primary + 3 inherit), agent skills, and Decision Log governance. Dated entries remain the source of truth for *why* each decision was made; the summary is the *what* at a glance. Archival plan noted: yearly split at ~50 entries. | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` | +| LLMP-DEC-26 | 2026-04-24 | Extended docs-sync rule with two sub-rules: `File registration` + `Issue / TODO surfacing` (initial version; superseded by 2026-04-24 revision below) | (1) **File registration** — every new `.md` must be visible in Visual Studio Solution Explorer, which requires a `` entry (or matching recursive glob) in the nearest `.csproj`. (2) **Issue / TODO surfacing** — surface concrete bugs/TODO candidates in `[DOCUMENTATION CHECK]` when not already in loaded `_ISSUES.md` / `_TODO.md`. Initial calibration: "concrete + non-duplicate + actionable — silence beats noise". **This version was revised after two external LLM critiques — see the next entry.** | `5× primary` (docs-sync rule: AyCode.Core #18, AyCode.Blazor #13, Libraries #16, FruitBank #14, FruitBankHybridApp #14) | +| LLMP-DEC-27 | 2026-04-24 | Revision of the two new sub-rules after two-session LLM review + proactive csproj glob expansion | Two external LLM critiques identified gaps in the initial sub-rule text. Applied revisions: (A) **File registration scope-limit** — check only if the new file falls OUTSIDE an existing recursive glob (zero-cost skip for the common `docs/`-path case). (B) **Issue / TODO surfacing guardrails** — added 4 explicit prerequisites (companion must be in `LOADED_DOCS` for reliable duplicate check; high confidence with quotable evidence; concrete observation; not duplicate). Added **volume cap max 3 per response**. Removed **ID assignment** from draft entries (user assigns at apply-time to avoid parallel-session collisions). Added **status-update-on-fix** clause (fixing an issue listed in loaded `_ISSUES.md` → surface `Status: FIXED` suggestion). (C) **ENFORCEMENT empty-state guard** — if nothing to report: `[DOCUMENTATION CHECK] None.` single line (no prose padding). (D) **Proactive csproj glob expansion** — added `` to 9 csproj files already having `docs/**` glob; added the same pattern (without `docs/**` exclusion) to 5 csproj files lacking any md glob. Together these cover folder-level `README.md` files in code directories (Loggers, Serializers, SignalRs, DbContexts, LogItems, etc.), making them visible in VS Solution Explorer without per-file rule trigger. The rule sub-rule A now mostly fires only for truly unusual locations. Cross-reference added between sub-rule B and the existing "Identify missing documentation" clause (different targets: main docs vs companions). | `5× primary` instruction files (docs-sync rule revision); **14 csproj files** (glob expansion): 9 with `docs/**` + `**/README.md`, 5 with only `**/README.md` | +| LLMP-DEC-28 | 2026-04-24 | Created `docs-check` skill; docs-sync rule → short pointer | Observation: both Claude Code and Copilot interpret and follow *skills* more reliably than numbered rules (explicit activation, step-by-step SKILL.md, description-matching forces deliberate thought). The docs-sync rule had grown into a multi-step procedure (drift detection, missing docs, topic separation, file registration, issue/TODO surfacing with 4 prereqs + volume cap + status-update-on-fix, empty-state handling) — exactly the shape of a skill, not a rule. Created `AyCode.Core/.github/skills/docs-check/SKILL.md` (v1.0) encapsulating the full procedure in 7 steps + edge cases + negative examples. Rule #18 (and equivalents) shortened in each primary file to a single pointer: *"at the end of EVERY code-modifying response, invoke the docs-check skill ..."*. Removed ~40 lines of duplicated procedure per primary file (×5 = ~200 lines of redundant text across the workspace). Skill is read-only on loaded docs (no new `Read`/`Grep` during invocation); all patches surface as proposals (Rule #5). | **1 new skill**: `docs-check/SKILL.md`; **5 primary** copilot-instructions.md (docs-sync rule shortened); **7 non-Core** files (`## Shared Agent Skills` section extended with the `docs-check` bullet: 4 primary non-Core + 3 inherit) | +| LLMP-DEC-29 | 2026-04-24 | `protocol-audit` v2.0 → v2.1 | (a) X1 invariant extended to expect all three skills in `## Shared Agent Skills` (was two: docs-discovery + protocol-audit; now adds docs-check). (b) New **X3** invariant: the docs-sync rule in each primary file points to the `docs-check` skill (checks for backtick-wrapped `` `docs-check` `` and the skill path). (c) Applicability matrix extended: X3 applies to all 5 primary files, N/A for the 3 inherit files (they don't have the numbered docs-sync rule). | `protocol-audit/SKILL.md` | +| LLMP-DEC-30 | 2026-04-24 | Introduced globally-unique issue/TODO/decision ID system + batch-migrated existing entries | Three reasons: (a) make IDs like `ISSUE-01` unambiguous outside their containing file (DB natural-key ready, code-comment friendly, cross-repo clear); (b) remove collision risk across parallel LLM sessions (per-topic+type counter is a smaller concurrency domain than global counter); (c) standardize the inconsistent mix of existing prefixes (`PROTO-`, `DISPATCH-`, `DS-`, `CONN-`, `XCUT-`, `DESER-`, `SER-`, `SGEN-`, `BWO-`, and per-file `ISSUE-NN`/`TODO-NN`). **Format:** `{TOPIC}-{TYPE}-{N}` — topic code from registry, type = `I`(ssue) / `T`(ODO) / `B`(ug) / `C`(ritical severity override) / `DEC` (LLMP-only), N is per-topic-per-type counter starting at 1 (no zero-padding). **Topic codes:** `LOG`, `SIG`, `SBP`, `BIN`, `TOON`, `GRID` (avoids `MG`-prefix-collision with `Mg*` class naming), `XCUT`, `LLMP`. Sub-categories (`PROTO`, `DISPATCH`, `CONN`, etc.) move from ID to body header tag (`## SIG-I-1 [PROTO]: ...`). Registry maintained in `docs-check/references/TOPIC_CODES.md`. Migration: ~50 existing entries renumbered across 10 files (LOGGING, SIGNALR, SBP, BINARY, TOON topic folders) + cross-references updated workspace-wide; found and mapped the previously-uncatalogued `BWO-4` entry → `BIN-I-15`. | `docs-check/references/TOPIC_CODES.md` (new); `docs-check/SKILL.md` (Step 5 draft entry format + topic registry reference); **10 topic doc files** (IDs renumbered); cross-ref updates across ~20 `.md` files in the workspace | +| LLMP-DEC-31 | 2026-04-24 | Consolidated XCUT cross-cutting entries into dedicated `docs/XCUT/` folder | Before: cross-cutting entries (currently just `XCUT-I-1: JSON-in-Binary request parameters`) were duplicated — canonical body in `BINARY_ISSUES.md`, short cross-ref in `SIGNALR_ISSUES.md`. This pattern breaks down as more XCUT entries arrive (every added cross-cutting topic needs duplicate maintenance, and the concept of "which side is canonical" is arbitrary). **Now:** canonical home is `AyCode.Core/AyCode.Core/docs/XCUT/` (topic-folder at project level, consistent with LOGGING/, BINARY/, TOON/ placement). Contains `README.md` (explaining XCUT concept + convention), `XCUT_ISSUES.md` (canonical entries), `XCUT_TODO.md` (template + future entries). Each affected topic's file keeps a **short cross-ref** pointing to the canonical entry; body size per topic drops to ~2 lines. Migrated `XCUT-I-1` — full body now lives in `XCUT_ISSUES.md`, with cross-refs from `BINARY_ISSUES.md` and `SIGNALR_ISSUES.md`. Also updated: `BINARY_TODO.md#bin-t-1` Related-link now points to canonical; `AyCode.Core/docs/CONVENTIONS.md` JSON-in-Binary section references canonical. | New folder `AyCode.Core/AyCode.Core/docs/XCUT/` (3 files); updated `BINARY_ISSUES.md`, `SIGNALR_ISSUES.md` (XCUT sections); `BINARY_TODO.md`, `AyCode.Core/docs/CONVENTIONS.md` (related-link updates); `AyCode.Core/AyCode.Core/docs/README.md` (topic list extended) | +| LLMP-DEC-32 | 2026-04-24 | SKILL.md generalization + workspace-meta-tooling exception documented | Two related concerns raised: (1) SKILL.md files had hardcoded specific repo/project names (e.g., "5 AyCode/Mango repos (AyCode.Core, AyCode.Blazor, Libraries, FruitBank, FruitBankHybridApp)" in protocol-audit's `description`; "`AyCode.Core/AyCode.Core/docs/XCUT/`" in docs-check's Step 5). Skills should describe BEHAVIOR; specific data lives in `references/` files. (2) The `.github/skills/` registry files (`REPOS.md`, `TOPIC_CODES.md`) list higher-layer products (Layer 3 consumers like FruitBank) — a literal Framework-First Design Principle violation if interpreted strictly. **Decisions:** (a) Skills stay **universal** (one copy under `AyCode.Core/.github/skills/`, referenced by all other repos via Shared Agent Skills section) — per-layer skill duplication rejected as maintenance-hostile. (b) SKILL.md files generalized to read from `references/` registries instead of hardcoding names. (c) The `.github/` folder is **explicitly exempted** from Framework-First: it is workspace-configuration, not framework code. Rule added to AyCode.Core/copilot-instructions.md's Framework-First Design Principle section. Scope notes added to `REPOS.md` and `TOPIC_CODES.md` at their tops. **Future escape hatch:** if a skill becomes truly layer-specific (e.g., `fruit-measurement-audit` for FruitBank-only concerns), it goes in that layer's `.github/skills/`, not in AyCode.Core's. | `protocol-audit/SKILL.md` (description + invariant X3 + applicability note generalized); `docs-check/SKILL.md` (Step 5 XCUT path reference generalized); `docs-discovery/SKILL.md` (consumer-specific class-name example swapped for a placeholder); `AyCode.Core/.github/copilot-instructions.md` (Framework-First section + "Exception for workspace meta-tooling" paragraph); `protocol-audit/references/REPOS.md` (scope note header); `docs-check/references/TOPIC_CODES.md` (scope note header) | +| LLMP-DEC-33 | 2026-04-24 | `protocol-audit` v2.1 → v2.2 — added C4 invariant for Session Setup section presence | New common invariant `C4` enforces `## Session Setup` section presence across all 8 files, with references to the three skill SKILL.md files (and for inherit files, also the canonical host's `copilot-instructions.md`). Ensures the new Session Setup rule is mechanically verifiable. Applicability matrix updated: C-invariant range extended from C1-C3 to C1-C4. | `protocol-audit/SKILL.md` (version bump; new C4 invariant; applicability matrix update) | +| LLMP-DEC-34 | 2026-04-24 | Token-economics principle made explicit — amortization over multi-turn sessions is the central design principle | **Observation**: a validation session exposed an LLM reasoning bias — when asked whether the protocol's upfront cost was worth it, the agent's first answer categorized `protocol-audit/SKILL.md` (~6K tokens) as "wasteful for this specific turn" because the turn didn't invoke it. A single user reminder ("the session just started") was enough for the LLM to self-correct and reframe the cost as amortizing over the full session lifetime. **Issue**: the Session Setup rule's rationale said "one-time cost per session" but did NOT explicitly name the single-turn optimization trap. LLMs default to per-turn local optimization and can mis-judge pre-loaded content as wasteful, especially in early session turns or quick one-off queries. **Fix**: extended the `## Session Setup` "Why mandatory" paragraph in all 8 `copilot-instructions.md` files (5 primary + 3 inherit) with an explicit `**Amortization — critical, do NOT re-evaluate per-turn**` note. The note states: (a) cost is measured over the ENTIRE session; (b) the first domain question alone recoups it; (c) the alternative (repeated source-code searches per turn) costs 10-20K tokens per turn with lower quality; (d) the design depends on cross-turn amortization + Rule #3 (no-re-read) + Rule #4 (context recovery as only exception); (e) this is the **central token-economics principle** of the entire stack. Proactively inoculates future sessions against the single-turn-optimization bias that was observed. | `5× primary` + `3× inherit` `copilot-instructions.md` (Session Setup "Why mandatory" paragraph extended with Amortization sub-paragraph) | +| LLMP-DEC-35 | 2026-04-24 | Added mandatory Session Setup — pre-load 3 SKILL.md files at session start | **Problem:** Claude Code does NOT populate workspace skills into its system-reminder / native skill-registry. Previous design relied on instruction-driven invocation (rule pointer → LLM reads SKILL.md on first trigger). This is **fragile**: the agent might not recognize implicit triggers (e.g., "this is a domain question → load docs-discovery"), might forget to load the SKILL.md, or might delay loading until after a code-search has already started. A test session confirmed the risk: an LLM answered a rule-listing question without loading any skill, then retroactively loaded them only when asked directly — the first domain question would have missed the docs-discovery trigger. **Solution:** Added `## Session Setup` section to all 8 `copilot-instructions.md` files (primary and inherit). Rule mandates pre-loading of all three SKILL.md files (`docs-discovery`, `docs-check`, `protocol-audit`) at session start, immediately after reading the main `copilot-instructions.md`. For inherit files, AyCode.Core's `copilot-instructions.md` is also in the mandatory load set (because inherit files do not duplicate Rules #1-5 — the canonical host has them). Expected `[LOADED_DOCS: ...]` prefix on first response: 4 files for primary, 5 for inherit. **Cost:** ~10-13K tokens one-time per session; Rule #3 (no-re-read) prevents repeated reads. **Reliability gain:** implicit triggers fire reliably for the entire session. The `## Shared Agent Skills` section intros (in 7 non-Core files) were also updated to cross-reference the Session Setup mandate. | `5× primary` + `3× inherit` `copilot-instructions.md` (added `## Session Setup` section); `4× non-Core primary` + `3× inherit` = `7× non-Core` (Shared Agent Skills intro updated to cross-reference Session Setup) | +| LLMP-DEC-36 | 2026-04-24 | Migrated Toon docs to `TOON/README.md` + `TOON_*.md` (Option C) | Last AyCode.Core domain still on flat layout. Absorbed the orphan `ToonExtendedInfo.txt` at repo root; added paired `TOON_ISSUES.md` / `TOON_TODO.md` per convention. Verified format spec against actual code (`MetaWriter`, `DataSection`, `TypeDefinitions`, `Descriptions`), not just the legacy marketing-style txt — surfaced richer reality (placeholder system, enum backing-field detection, navigation metadata, type relation constants) absent from the old txt. Serialize-only status recorded as `TOON_TODO.md#toon-t-6`. | `AyCode.Core/docs/TOON/` (8 new files) + `AyCode.Core/docs/README.md` (topic list) + `AyCode.Core/Serializers/Toons/README.md` (stub pointer) + `ToonExtendedInfo.txt` (removed) | +| LLMP-DEC-37 | 2026-04-24 | `docs-discovery` SKILL.md hardening: literal-path tilalom + false-empty guardrail (cross-session validation feedback) | **Incident**: a parallel Copilot session executed `docs-discovery` for a logger-review query but substituted a literal `AyCode.Core/docs/LOGGING/...` path for the spec'd `**/docs/{TOKEN}/**/*.md` glob. The literal path missed AyCode.Core's project-level docs layout (`//docs/LOGGING/`), yielded 0 matches, and Copilot concluded "docs are empty" → fell through to code-only review, skipping the loaded paired-docs set (8 known issues, 11 prioritized TODOs). **Fix scope**: minimal — 2 sentences appended to existing steps, NOT new rules. (a) Step 2 end: explicit prohibition on substituting literal `/docs/...` for the recursive `**/docs/...` glob, with one-line rationale that `**` matches both repo-root and project-level layouts in a single pass. (b) Step 3 end: false-empty guardrail — if glob returns 0 matches OR all matches are 0-byte, re-validate the glob (typo? literal substituted?) and retry once with the same token under a corrected `**/docs/...` pattern (NEVER an ad-hoc path guess) before falling through to code-search. **Rejected alternatives**: an early Copilot draft proposed 5 new numbered rules + 5 new SKILL steps (incl. a Step 0 "load every README.md" pass). Evaluation: most were redundant with existing rules (vs. hard-gate, paired-docs Step 5, Rule #1 prefix), one was based on `**`-semantics misunderstanding (proposed "two-pass" globs where the second pattern is a strict subset of the first), one was actively harmful to token economy (Step 0). Net: ~80% reduction in proposed protocol surface, same bug-class coverage. | `docs-discovery/SKILL.md` (Step 2 end + Step 3 end) | +| LLMP-DEC-38 | 2026-04-24 | Retroactively assigned `LLMP-DEC-N` IDs to existing Decision Log entries | When the globally-unique ID system was introduced (LLMP-DEC-30) with the `LLMP` topic code for LLM-protocol meta-decisions using `DEC` type, the existing ~37 Decision Log entries remained keyed by date alone. This meant the design intention (entries have unambiguous string IDs for cross-referencing) wasn't realized for historical entries. Fix: added an `ID` column as the leftmost in the 2026 table, and populated LLMP-DEC-1 through LLMP-DEC-37 in chronological order (retroactive assignment, this entry is LLMP-DEC-38 as the first ID-aware addition). Entries now referenceable by ID from code comments, other `.md` files, PR descriptions, or future DB migration. The `LLMP-DEC-N` format is append-only (IDs never renumber); superseded decisions get new entries that reference old ones by ID (e.g., "LLMP-DEC-26 superseded by LLMP-DEC-27"). | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` (ID column + 37 retroactive IDs) | +| LLMP-DEC-39 | 2026-04-24 | `docs-discovery` SKILL.md Step 2 restructuring — recursive `**/` wildcard requirement moved to prominent CRITICAL section at TOP (second iteration; LLMP-DEC-37 proved insufficient) | **Incident**: a second Copilot session exhibited the same literal-path bug that LLMP-DEC-37 was supposed to prevent — it synthesized `AyCode.Core/docs/LOGGING/README.md` (a path that doesn't exist; the real docs are at `AyCode.Core/AyCode.Core/docs/LOGGING/`, one level deeper at project-level) instead of using the recursive `**/docs/LOGGING/**/*.md` glob. LLMP-DEC-37 had appended a warning to the END of Step 2, which was not prominent enough — Copilot read Step 2, formed its own mental model of "usual docs paths", and never reached the trailing caution. **Fix**: moved the warning to the TOP of Step 2 as a `### ⚠️ CRITICAL` subsection. Content expanded: (a) explicit depth-level enumeration (repo-root `/docs/TOPIC/`, project-level `//docs/TOPIC/`, nested), (b) concrete failure-mode walkthrough showing the specific "know the repo → synthesize shallow path → 0 matches → false-empty conclusion" pattern that fires for Pattern B layouts, (c) correct-vs-wrong form side-by-side examples, (d) absolute rule: NEVER drop the leading `**/` even when the repo is known. The old trailing warning was consolidated to a back-reference to the new top section to keep Step 2 from splitting the message. User rejected intermediate proposals (byte-count verification, flat `**/docs/TOPIC.md` defensive pattern) as "drótozás" (hardcoding) — fix stays structural, no glob pattern additions. | `docs-discovery/SKILL.md` (Step 2 restructuring; supersedes LLMP-DEC-37's Step-2-end placement) | +| LLMP-DEC-40 | 2026-04-24 | Rule #1 clarification: removed false "globally unique by basename" claim for `copilot-instructions.md` | **Observation**: a parallel Claude Code self-audit session noticed a literal contradiction in Rule #1. The short-name rule line 18 said `copilot-instructions.md` is "globally unique by basename" — true for a typical session (1 active repo = 1 loaded copilot-instructions.md) but FALSE for `protocol-audit` sessions, which load all 8 `copilot-instructions.md` files simultaneously. The claim conflicts with the cross-project-disambiguation rule one line above (line 17) whenever the audit use-case fires. The LLM correctly identified the ambiguity and proposed a patch. **Fix**: replaced the parenthetical "globally unique by basename" with an explicit acknowledgment of the `protocol-audit` collision case + pointer to the already-existing cross-project-disambiguation rule above. New wording uses concrete disambiguation examples (`AyCode.Core/copilot-instructions.md`, `FruitBankHybridApp/copilot-instructions.md`). The `.github/` prefix tiltás is retained — now justified as "implicit location" rather than "already unique". **Deferred (explicit YAGNI)**: proposed new `protocol-audit` C5 invariant (semantic validation: Rule #1 basename-uniqueness claims must match the actual file-set in REPOS.md). Rejected for now — one known instance isn't enough to justify invariant surface / false-positive risk; revisit if a second similar contradiction appears. | `5× primary` `copilot-instructions.md` (Rule #1 line 18 patched) | +| LLMP-DEC-41 | 2026-04-24 | Created `adr-author` skill — 4th workspace skill, extends Session Setup pre-load from 3 to 4 | **Gap identified**: the existing skill-stack (docs-discovery, docs-check, protocol-audit) covers documentation retrieval, code↔docs drift detection, and cross-repo file-structural audit — but has no artifact-producing workflow for **pre-code architectural decisions** (greenfield repo planning, feature design, tech-stack choices, library selection, migration planning). The `{TOPIC}_TODO.md` format is an implementation queue (known scope, code ref expected, P1-P3 priority); it cannot naturally hold decision rationale, weighed alternatives, or trade-off tables. Without a dedicated artifact, design rationale tends to disappear into chat history or get flattened into TODO entries that lose the "why". **Solution**: `adr-author` skill encoding the canonical Michael Nygard ADR workflow as a structured interview (Step 1 routing → Step 2 context → Step 3 alternatives → Step 4 trade-offs → Step 5 decision → Step 6 consequences → Step 7 draft + write → Step 8 cross-refs). Tool-neutral like the other three skills. **Routing logic**: two decision-log paradigms supported — per-repo `docs/adr/NNNN-.md` Nygard-style files (product/code/domain decisions) VS workspace-level `LLMP_PROTOCOL_DECISIONS.md` table rows with ID `LLMP-DEC-N` (protocol-meta decisions). **Invocation model (new): explicit user request OR LLM-suggest-back** — LLM flags when conversation exhibits 2+ ADR-heuristics (multiple alternatives weighed, irreversible, cross-cutting, 6-18mo re-openable); user must confirm before invocation. Never auto-invoke. **Session Setup pre-load 3 → 4 skill**: consistent with existing `protocol-audit` (on-demand) pattern — the skill's content must be in context for trigger recognition. **Handoff**: `docs-check` can flag ADR-worthy observations at end-of-response; `docs-discovery` owns "how does X work" questions, `adr-author` owns "let's design X" questions. **User rationale for broader scope than greenfield-only**: user correctly pointed out ADR-worthy decisions arise in mature code too (refactors, library additions, migration paths), not just new-repo planning — the original Nygard definition supports this scope. | new: `AyCode.Core/.github/skills/adr-author/SKILL.md` + `AyCode.Core/.github/skills/adr-author/references/ADR_TEMPLATE.md`; `5× primary` `copilot-instructions.md` (Session Setup: three→four; prefix count 4→5); `3× inherit` `copilot-instructions.md` (Session Setup: three→four; prefix count 5→6); `4× non-Core primary` + `3× inherit` `copilot-instructions.md` (Shared Agent Skills intro "All three"→"All four"; new adr-author bullet added after docs-check bullet) | +| LLMP-DEC-42 | 2026-04-25 | `adr-author` SKILL.md: added "Multi-project repo case" placement guidance to Step 1 (cross-cutting vs project-scoped) | **Incident**: a Claude Code session executing `adr-author` for a bearer token design produced an excellent ADR draft but left the `docs/adr/` location ambiguous — the draft path said `docs/adr/0001-...` without resolving whether that meant `/docs/adr/` (repo root, cross-cutting placement) or `//docs/adr/` (project-scoped). The decision in question affected 2+ projects (`AyCode.Services` client + `AyCode.Services.Server`), so the placement question was real, not academic. The original SKILL.md Step 1 used `/docs/adr/...` placeholder which silently assumed single-project repos; multi-project layouts (which exist in this and likely other repos) had no explicit guidance. **Fix**: added a "Multi-project repo case" sub-section to Step 1 with three rules: (1) existing convention wins (Glob first; never fragment by creating a parallel folder); (2) no existing folder → match scope to placement (cross-cutting → highest common ancestor, typically repo root; project-scoped → that project's `docs/`); (3) ambiguous scope → ask the user explicitly before proceeding. Step 7's path reference updated to `` resolved in Step 1, removing the misleading `/docs/adr/` literal. **Generic, not hardcoded**: no specific repo names or project paths in the rules — they apply to any multi-project repo. | `adr-author/SKILL.md` (Step 1 + Step 7 updates) | +| LLMP-DEC-43 | 2026-04-25 | Lazy-load shift for user-gated skills + new `docs-archive` skill + Status field convention | **Three integrated changes consolidated into one decision** because they share the underlying principle "user-gated skills are lazy-loaded; reactive skills stay pre-loaded": (A) **Lazy-load shift**: `protocol-audit` and `adr-author` (LLMP-DEC-41) move from Session Setup pre-load to lazy-load. The `## Shared Agent Skills` bullets in `copilot-instructions.md` already contain enough trigger description for the LLM to recognize when to invoke; the full SKILL.md only needs to be in context at execution time. Token savings: ~10-14K per session (3 SKILL.md × ~5K avg). (B) **New `docs-archive` skill** (lazy-loaded, user-gated + LLM-suggest-back): rotates closed entries (`Status` ∈ {Fixed, Resolved, Won't fix, Superseded by X}) from active `_ISSUES.md` / `_TODO.md` / `LLM_PROTOCOL_DECISIONS.md` into year-bucketed `*_.md` archive files. Year of Status update determines destination bucket. Status-based filter (no foundational-flag complexity, no age threshold). Active file gets a 2-line pointer block at top; archive files NOT auto-loaded by `docs-discovery` (lazy-on-suspicion read pattern documented in `docs-discovery/SKILL.md` "Archive files" section). (C) **Status field convention** formalized in `TOPIC_CODES.md`: explicit value list (`Open`, `Partially Fixed`, `Fixed`, `Resolved`, `Won't fix`, `Documented limitation`, `Superseded by`), date stamping rules, partial-fix `### Resolution status` sub-section format, archive-eligibility filter. Status updates are the **one exception** to append-only — field is mutable; entry body / ID / Description remain immutable. **Cross-skill integration**: `docs-discovery/SKILL.md` gets new "Archive files" section (default-exclude year-suffixed glob; on-demand read on regression / supersession-ref / cross-ref signals). `docs-check` already had status-update-on-fix logic (LLMP-DEC-27); this entry formalizes the value vocabulary it should use. **Workflow**: `docs-archive` reports per-file analysis (Step 2), user selects scope (Step 3), generates plan with diff (Step 4), applies on explicit consent (Step 5, Rule #5). Archive operation is on-demand — no automatic monitoring, no background size checks. **Note**: an earlier in-conversation draft proposed the lazy-load shift as a standalone LLMP-DEC entry; folded into this LLMP-DEC-43 instead, since lazy-load and `docs-archive` skill share the same design rationale and benefit from being recorded as one decision. | new: `AyCode.Core/.github/skills/docs-archive/SKILL.md`; updated: `docs-check/references/TOPIC_CODES.md` (new "Status field conventions" section); `docs-discovery/SKILL.md` (new "Archive files" section); `5× primary` `copilot-instructions.md` (Session Setup: 4→2 pre-loaded SKILL.md, prefix count 5→3, lazy-load list added); `3× inherit` `copilot-instructions.md` (Session Setup: 4→2 pre-loaded SKILL.md, prefix count 6→4, lazy-load list added); `4× non-Core primary` + `3× inherit` `copilot-instructions.md` (Shared Agent Skills intro updated; new `docs-archive` bullet added after `adr-author`) | +| LLMP-DEC-44 | 2026-04-25 | Status field vocabulary simplified: 7 values → 3 (`Open`, `InProgress`, `Closed`); bulk-migrated all existing TODO/Issue entries to `Open` | **Refinement of LLMP-DEC-43 (C)**: the 7-value Status vocabulary (`Open`, `Partially Fixed`, `Fixed`, `Resolved`, `Won't fix`, `Documented limitation`, `Superseded by`) was deemed over-engineered. **Reduced to 3 values**: `Open` (active/unresolved; also used for documented-current-behaviour entries that must remain visible), `InProgress` (partial work in flight), `Closed` (done — bug fixed, decision made, TODO completed; archive-eligible). Distinctions previously encoded in the Status (Fixed vs Resolved vs Won't fix vs Superseded) move to the **entry body** — body explains "what happened" (date, ref, rationale); Status only signals "is this still in the active set?". Documented-current-behaviour entries (previously `Documented limitation`, `By design`, `Acceptable`, `Limitation`, `Upstream SDK limitation`, etc.) stay as `Open` with an optional body callout (`> **Note:** This entry documents accepted current behaviour — not scheduled for change.`). **Bulk migration** applied: every existing `Status` value in `_ISSUES.md` and `_TODO.md` files across the workspace (LOGGING, XCUT, BINARY, SIGNALR, SBP) was set to `Open` as a clean-slate starting point — future Status updates use the new 3-value vocabulary. **Archive criterion** in `docs-archive` simplified to a single rule: `Status == "Closed"` → archive-eligible. **Known anomaly**: `SIGNALR_ISSUES.md` had a single `Status: DONE` entry — also set to `Open` per the bulk-migration rule, but semantically should likely be `Closed` (work was actually done). User to manually re-mark if appropriate. **Why simpler is better**: the previous 7 values created false precision — the distinction between Fixed/Resolved/Won't fix matters in the body, not in the Status field. The `Documented limitation` value semantically conflicted with archiving (it's not "closed work"); folding it into `Open` with a body callout removes the conflict. Archive logic becomes a single equality check. | `docs-check/references/TOPIC_CODES.md` (Status section: 7 → 3 values, simpler workflow); `docs-archive/SKILL.md` (archive criterion simplified to `Status == "Closed"`); 6 files affected by bulk Status migration: `LOGGING_ISSUES.md`, `XCUT_ISSUES.md`, `BINARY_ISSUES.md`, `SIGNALR_ISSUES.md`, `SIGNALR_BINARY_PROTOCOL_ISSUES.md`, `SIGNALR_BINARY_PROTOCOL_TODO.md` (`TOON_ISSUES.md` unchanged — all real entries already `Open`) | +| LLMP-DEC-45 | 2026-04-25 | `adr-author` SKILL.md + ADR_TEMPLATE first-real-use feedback batch (9 changes); `version` field removed from all 5 SKILL.md frontmatters | First end-to-end use of `adr-author` (bearer token ADR session, `0001-user-bearer-token-flow.md`) surfaced 9 friction points across the skill and template, plus consolidates 2 previously-parked feedback items (Copilot session out-of-scope routing, Claude Code session dimensional alternatives — now subsumed). **Changes** (priority order): (#1) Step 8 #3 split into "decision-closes-entry" vs "pre-flight-closed-entry" cases — pre-flight case (entry already closed before ADR formalizes the architecture) gets a soft cross-ref to `### Related` instead of Status update; (#2) new Step 9 "Hand-off after write" — short, ask-don't-assume-next-action; (#3) Step 8 #1 explicit `/README.md` Index table update (not just generic "PRODUCT_DECISIONS.md"); (#4) Step 7 NNNN re-Glob immediately before `Write` (collision safety); (#5) Step 5 opinion-when-asked nuance — frame as preference not prescription, with anti-example pair (❌ "X, egyértelmű." vs ✅ "I lean toward X because Y, but you decide."); (#6) ADR_TEMPLATE Status placeholder fixed `Proposed` → `Proposed (YYYY-MM-DD)` (was inconsistent with skill Step 5); (#7) `docs/adr/0000-TEMPLATE.md` becomes 1-paragraph pointer to canonical `references/ADR_TEMPLATE.md` — eliminates duplication / drift risk; (#8) ADR_TEMPLATE Alternatives section adds optional Reversibility/Cost/Future-flex sub-bullets with explicit "use sparingly" guidance; (#9) ADR_TEMPLATE Status comment notes Status vocabulary distinct from `_ISSUES.md` / `_TODO.md` (Open/InProgress/Closed) — see `TOPIC_CODES.md`. Plus Edge cases "Parallel LLM sessions" updated to point back to Step 7's explicit re-Glob rule (was redundant). **Housekeeping**: `metadata: version` field removed from all 5 SKILL.md frontmatters (`adr-author`, `docs-archive`, `docs-discovery`, `docs-check`, `protocol-audit`). Internal iteration doesn't need versioning ceremony — Decision Log entries are the version history. **No backward-compat concerns**: bearer token ADR (0001) was a test run, not a production consumer; no external dependents on prior skill behaviour. | `adr-author/SKILL.md` (Steps 5/7/8/9, Edge cases, frontmatter); `adr-author/references/ADR_TEMPLATE.md` (Status section, Alternatives section); `docs/adr/0000-TEMPLATE.md` (full rewrite as pointer); `docs-discovery/SKILL.md`, `docs-check/SKILL.md`, `protocol-audit/SKILL.md`, `docs-archive/SKILL.md` (frontmatter `version` field removed) | +| LLMP-DEC-46 | 2026-04-25 | `docs-discovery` SKILL.md Step 2: forward-slash mandate added (Windows backslash trap) | **Recurring failure mode**: a Copilot session in VS attempted `file_search` with a Windows-backslash glob pattern (`...\docs\**\*.md`); the glob engine silently returned 0 matches despite files existing, and the agent fell through to code-search per the same false-empty pattern that LLMP-DEC-39 addressed. Same root cause class as the `**/` lehagyás (LLMP-DEC-37, LLMP-DEC-39) — a syntactically malformed pattern returns no match, the agent interprets "no files" as "no docs exist". **Fix**: added a new `### ⚠️ Path separators — forward slashes ONLY in glob patterns` sub-section to `docs-discovery/SKILL.md` Step 2 (placed between the existing `**/` CRITICAL section and "File layout convention"). Content: forward-slash mandate regardless of host OS, correct vs wrong example, failure-mode description (silent 0 matches), absolute rule statement, cross-reference to the `**/` mandate. **Why both rules together**: the `**/` recursive mandate + the `/` separator mandate are the two most common syntactic glob errors observed in real sessions; both produce identical "0 matches → false-empty → code-search fall-through" failure mode. Documenting them adjacent in Step 2 lets the LLM see them as a paired class of pitfalls. **Bug class is host-agnostic**: glob engines uniformly require forward slashes (Microsoft.Extensions.FileSystemGlobbing, ripgrep, Node glob, Python pathlib, JS minimatch) — backslash-in-pattern is silently malformed everywhere. | `docs-discovery/SKILL.md` (Step 2 — new "Path separators" sub-section between the existing `**/` CRITICAL and "File layout convention") | +| LLMP-DEC-47 | 2026-04-25 | Decision Log governance: explicit "No skill / template version labels" clause added | **Recurring slip detected**: even after LLMP-DEC-45 removed `metadata: version` from all 5 SKILL.md frontmatters, the LLM (this agent) continued using "v1.1" colloquially in conversation as shorthand for "the recent batch of changes" — including in a substantive ADR-plan critique. The user pointed out the regression: the slip itself is evidence the principle was not explicit enough. Implicit removal of metadata fields didn't prevent the linguistic ceremony in dialogue or in cross-doc references. **Fix**: added a new bullet to the `Decision Log governance` section in this file's `## Current protocol state (quick reference)` block. The rule covers three surfaces: (a) skill content, (b) frontmatter metadata, (c) conversational / cross-doc references. Reference changes by **date or `LLMP-DEC-N` ID** instead. **Why explicit codification matters**: structural removal (deleting metadata fields) is a one-time mechanical change; linguistic habit is a recurring behavioral one. Implicit principles drift in language even when followed structurally. Codifying prevents the regression at the source — every future agent reading the governance bullets will see the rule before being tempted to introduce `vN.M` shorthand. | `AyCode.Core/.github/LLM_PROTOCOL_DECISIONS.md` (Decision Log governance section — new bullet) | +| LLMP-DEC-48 | 2026-04-25 | `adr-author` SKILL.md Step 1 restructured: fresh-folder creation rule factored out as shared rule (covers fresh-repo + multi-project cases); template wording "copy of" → "1-paragraph pointer to" (sync with LLMP-DEC-45 #7) | **Drift detected by parallel session**: LLMP-DEC-45 #7 made `/docs/adr/0000-TEMPLATE.md` a 1-line pointer to the canonical `references/ADR_TEMPLATE.md` (eliminating duplication / drift risk). The `adr-author/SKILL.md` Step 1 fresh-repo case still said *"Propose creating `0000-TEMPLATE.md` (copy of `references/ADR_TEMPLATE.md`)"* — stale wording. Additionally, the Step 1 multi-project case did not mention 0000-TEMPLATE creation at all (implicit only via inheritance from the fresh-repo case). **Discovery context**: a parallel Claude Code session, planning a project-scoped ADR folder for `AyCode.Services/docs/adr/`, followed the SKILL Step 1 literally and proposed creating a full template copy — which would have created an inconsistent state across the workspace (one folder with pointer, another with copy). **Fix**: SKILL Step 1 restructured. The fresh-folder creation directive (`README.md` + `0000-TEMPLATE.md`) factored out of the fresh-repo case into a **shared rule applying to any newly-created `docs/adr/` folder** (whether at repo root or project-scoped). The 0000-TEMPLATE wording changed from "copy of" to "1-paragraph pointer to" the canonical, with rationale stated in-line ("single source of truth, avoids template drift"). The README.md description also extended to mention the index table. **Universality preserved (no drót)**: SKILL.md does NOT reference LLMP-DEC IDs (workspace-specific) — it states the principle directly so the skill remains portable to any workspace adopting the protocol-stack. The LLMP-DEC link lives only in this Decision Log entry. | `adr-author/SKILL.md` (Step 1 path resolution section — fresh-folder creation factored out as shared rule + canonical-pointer wording) | +| LLMP-DEC-49 | 2026-04-25 | Created `AUTH` topic — registered topic code in `TOPIC_CODES.md`, scaffolded `docs/AUTH/{README, AUTH_ISSUES, AUTH_TODO}.md` at repo root | Bearer-token ADR-0001 (`docs/adr/0001-user-bearer-token-flow.md`, `Accepted (2026-04-25)`) needs a topic home for ongoing issues, planned work, and consumer recipe. **Pre-implementation scaffold**: `README.md` is honest about pre-impl state and includes a Scope table mirroring the ADR's Decision section + a "Security: Never log secrets" guideline (auth-specific phrasing, will trim to cross-ref when `LOG-T-12` lands the canonical version in `LOGGING/README.md`); `AUTH_ISSUES.md` and `AUTH_TODO.md` are empty-state with entry-format templates. **Placement**: repo-root `docs/AUTH/` (not project-level) chosen because AUTH is cross-cutting — affects `AyCode.Services` + `AyCode.Services.Server` + `AyCode.Interfaces` + every consumer. Same parallel-to-projects positioning as `docs/adr/` and `docs/XCUT/` (sibling cross-cutting topics). **`LOG-I-9` / `LOG-I-10`** (auth security leaks closed pre-flight) remain in `LOGGING_ISSUES.md` per their existing Discovery-context note; relocation to `AUTH_ISSUES.md` as `AUTH-I-N` is a separate user-approved follow-up listed in ADR-0001's "Status migration on AUTH topic creation" section — not part of this entry. | `docs-check/references/TOPIC_CODES.md` (new `AUTH` row inserted between `LOG` and `SIG`); 3 new files: `AyCode.Core/docs/AUTH/README.md`, `AUTH_ISSUES.md`, `AUTH_TODO.md` | +| LLMP-DEC-50 | 2026-04-26 | New Rule #6 added to all primary `copilot-instructions.md` — Authority, Rule scope, Skill invocation (3 general behavioral principles) | **Diagnosis from real-world session evidence**: a parallel session reviewing FruitBank plugin docs surfaced 5 distinct misinterpretation patterns: (1) inventing topic codes ad-hoc without consulting the canonical registry; (2) proposing TOC-with-offset re-read patterns that work around the no-re-read rule's scope; (3) inventing custom URL schemes (`@Repo:`) outside markdown standard; (4) proposing empty `_ISSUES.md` files without applying the established Status convention; (5) manually reimplementing a skill's workflow instead of invoking the skill. Five distinct surfaces, **one root cause**: the session knew skills/rules existed at the surface but did not follow references to depth, did not treat authoritative registries as binding, and improvised over canonicalized procedures. **Plus self-evidence**: this assistant slipped THREE times using `vN.M` version-label colloquialism in conversation despite LLMP-DEC-47 explicitly forbidding the pattern — proof that Decision Log entries alone do NOT propagate to behavior. Decision Log governance is not session-start mandatory load; rules in `copilot-instructions.md` are. **Fix**: codify three **general** behavioral principles as Rule #6 in all 5 primary `copilot-instructions.md` files. (a) **Authority before proposal** — verify against authoritative source before inventing categories/IDs/conventions. (b) **Rule implications are part of the rule** — apply rules conservatively, don't work around scope with novel patterns. (c) **Skill invocation preferred over reimplementation** — invoke skills explicitly rather than ad-hoc reimplementation. **General, not workspace-specific**: the rule text mentions NO specific registry, skill, convention, or workspace artifact — it states principles applicable to any registry, any skill, any future workspace. **Why Rule #6, not Rule #2 extension**: Rules #1-5 are state/input/output mechanics (LOADED_DOCS prefix, docs-before-code, no-re-read, context-recovery, modification consent); Rule #6 is **behavioral correctness** of how proposals are formed — separate functional category, separate rule. **Coverage**: Authority covers misinterpretations 1, 3, 4; Rule implications covers 2; Skill invocation covers 5 — full 5/5 of observed patterns. **Why this might still not be enough**: even codified rules slip in agent behavior (the v-label evidence). Multi-LLM independent validation remains structurally necessary as the final safety net; rule-text shifts the probability, doesn't reach 100%. | `5× primary copilot-instructions.md` (new Rule #6 inserted after Rule #5, before `## Session Setup`) | +| LLMP-DEC-51 | 2026-04-26 | Removed `Mango/FruitBank/` deployment-host folder — REPOS.md inherit count 3 → 2, total 8 → 7 | The `Mango/FruitBank/` folder was originally created (LLMP-DEC-16, LLMP-DEC-19) as a nopCommerce deployment host for the FruitBank company, intended to host `Nop.Plugin.Misc.AIPlugin`. User confirmed the folder is no longer used — empty except for the legacy `.github/copilot-instructions.md`. **Pre-removal content audit**: the file contained only deployment-host meta (host-role description, `@repo` block declaring `type=host, layer=4`, scope-guidance for what NOT to write here, pointers to plugin and framework docs). NO substantive content about the plugin (later renamed MGFBANKPLUG) or FruitBank-Nop code (later renamed FBANKNOP) — pure host-side metadata, irrelevant once the host doesn't exist. **Removed**: `Mango/FruitBank/.github/copilot-instructions.md`, the `.github/` folder, and the parent `Mango/FruitBank/` folder (now empty). **Updated**: `protocol-audit/references/REPOS.md` — inherit count 3 → 2, total entries 8 → 7. **Historical record preserved**: LLMP-DEC-15 (plugin file fill, separate concern), LLMP-DEC-16 (host file fill), LLMP-DEC-19 (host purpose resolution) remain in the Decision Log per append-only governance — they describe a past state of the workspace. **Phase 0.5 of the ID-format migration (LLMP-DEC-50 design context)**: this cleanup is prerequisite to Phase 1, so the upcoming `REPO_PREFIXES.md` reflects the actual 7-repo workspace topology (no MGFBANKHOST prefix needed). | deleted: `Mango/FruitBank/.github/copilot-instructions.md`, `Mango/FruitBank/.github/`, `Mango/FruitBank/`; updated: `protocol-audit/references/REPOS.md` (Inherit table row 8 removed; own-dep-repos Inherit table Mango.FruitBank row removed) | +| LLMP-DEC-52 | 2026-04-26 | Corrective addition to LLMP-DEC-51: deployment-host context re-attributed to FBANKNOP (FruitBank nopCommerce Server) docs | **LLMP-DEC-51 over-pruned**: the agent's content audit before deletion concluded "no substantive content to migrate from the `Mango/FruitBank/` folder" — but the user identified that the deployment-context information (this FruitBank product targets a nopCommerce instance hosting `Nop.Plugin.Misc.AIPlugin` plugin for the FruitBank company) IS meaningful workspace-topology information, not pure host-side metadata. The deleted folder's role description and hosted-plugin pointer were workspace-relevant — they document a real relationship between FBANKNOP (the server-source product) and MGFBANKPLUG (the plugin source). Without that info, the workspace loses the explicit "this source compiles and deploys here" relationship statement. **Fix**: added a new `## Deployment & Hosting` section to `Mango/Source/FruitBank/.github/copilot-instructions.md` (FBANKNOP's primary instruction file). The section captures: (a) FBANKNOP is the nopCommerce server source for a runtime instance; (b) the runtime hosts MGFBANKPLUG; (c) deployment config / runtime state is external to source repo; (d) historical note that `Mango/FruitBank/` folder was the previous tracking location, now removed per LLMP-DEC-51, with the deployment-context info now living at FBANKNOP (where the source code resides). **Append-only preserved**: LLMP-DEC-51 itself is NOT modified — this corrective entry stands as the augmentation. **Why FBANKNOP, not MGFBANKPLUG**: per user judgment ("inkább a FBANKNOP a valószínűbb"), the deployment-context is more naturally attached to the broader server source (FBANKNOP) than to the plugin source (MGFBANKPLUG); the plugin is one component within the deployment, not the deployment itself. **Process lesson for future cleanups**: pre-deletion content audits must distinguish between (a) pure folder-meta (irrelevant once folder is gone) and (b) workspace-topology references that survive folder removal — the latter need explicit re-attribution, not deletion. | `Mango/Source/FruitBank/.github/copilot-instructions.md` (new `## Deployment & Hosting` section inserted between `## Workspace Dependencies` and `## Shared Agent Skills`) | + +## Notes + +These 52 entries represent the **early protocol-stack development** (2026-04-20 through 2026-04-26): rule refinements, the 5-skill stack creation, docs layout migration (LLMP-DEC-21), the ID system introduction (LLMP-DEC-30), the Status field convention iteration (LLMP-DEC-43/44), the AUTH topic scaffold (LLMP-DEC-49), Rule #6 introduction (LLMP-DEC-50), and the workspace topology cleanup (LLMP-DEC-51/52) — all leading into the ID-format migration that started with LLMP-DEC-53. + +The active log (`LLM_PROTOCOL_DECISIONS.md`) keeps **last 15 entries** (LLMP-DEC-53 through LLMP-DEC-67 as of 2026-04-27). When new entries push the active count beyond 15, the oldest get rotated into this archive (or into a new year-month archive if a calendar boundary is crossed). See `docs-archive/SKILL.md` for the rotation rules. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 602bc5c..1c77125 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -148,7 +148,7 @@ Full doctrine: `../docs/ARCHITECTURE.md#framework-vs-consumer-boundary` ## SignalR 7. **Tag-based transport (no conventional hub methods)** — SignalR communication should generally use the generic methods provided by `AcWebSignalRHubBase` (server) and `AcSignalRClientBase` (client). Request types are conventionally identified by `int` tags. Try to avoid adding custom, business-specific, or conventional string-based Hub methods (e.g., `GetUsers()`). -8. **AcSignalRDataSource** — generic `IList` with change tracking, CRUD via `SignalRCrudTags`, binary merge, rollback. See `AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md`. Transport docs: `AyCode.Services/docs/SIGNALR/README.md`. +8. **AcSignalRDataSource** — generic `IList` with change tracking, CRUD via `SignalRCrudTags`, binary merge, rollback. See `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md`. Transport docs: `AyCode.Services/docs/SIGNALR/README.md`. 9. ~~**JSON-in-Binary tech debt**~~ — **REMOVED** 2026-04-26 (resolved: `AyCode.Core/docs/XCUT/XCUT_ISSUES.md#accore-xcut-i-x8q1`). Number kept reserved to prevent renumbering of subsequent items. ## Critical Warnings diff --git a/.github/skills/docs-archive/SKILL.md b/.github/skills/docs-archive/SKILL.md index b09a92e..9e1f2b7 100644 --- a/.github/skills/docs-archive/SKILL.md +++ b/.github/skills/docs-archive/SKILL.md @@ -1,6 +1,6 @@ --- name: docs-archive -description: Rotate closed entries (Status: Fixed/Resolved/Won't fix/Superseded by X) from active `_ISSUES.md` / `_TODO.md` / `LLM_PROTOCOL_DECISIONS.md` files into year-bucketed archive companions (`*_.md`). Year of the Status update determines destination file. Active files retain only Open/Partially Fixed entries plus a header pointer to the archives. Archive files are NOT auto-loaded by `docs-discovery`; agents read them on-demand when historical context becomes relevant. Invoke explicitly ("archive ISSUES", "rotate logs") or via LLM-suggest-back when a loaded file shows many closed prior entries. +description: Rotate entries from active `_ISSUES.md` / `_TODO.md` / `LLM_PROTOCOL_DECISIONS.md` files into **year-month bucket** archive companions (`*__.md`). Two rotation criteria: (Rule A) for `_ISSUES.md` / `_TODO.md` — `Status: Closed` entries archive-eligible (Status field per `TOPIC_CODES.md` 3-value vocabulary); (Rule B) for `LLM_PROTOCOL_DECISIONS.md` — **last-15-active rolling window**: entries beyond the 15 most recent rotate by entry-date (LLMP-DEC-65, supersedes the original "annual at ~50" from LLMP-DEC-25). Year-month bucket from the entry's date. Active files retain a header pointer to archives. Archive files are NOT auto-loaded by `docs-discovery`; agents read them on-demand when historical context becomes relevant. Invoke explicitly ("archive ISSUES", "rotate logs", "archive DEC log") or via LLM-suggest-back when a loaded file is bloated. compatibility: Designed for Claude Code and GitHub Copilot (VS). Uses the host agent's Read/Write/Edit/Glob/Grep tools. metadata: author: Fullepi @@ -8,7 +8,7 @@ metadata: # docs-archive -Lifecycle skill for the workspace's append-only artifact files. Active files grow without bound as work accumulates; this skill consolidates closed entries into year-bucketed archive companions, keeping the active file as a focused "what's still open" view. +Lifecycle skill for the workspace's append-only artifact files. Active files grow without bound as work accumulates; this skill consolidates eligible entries into **year-month bucket** archive companions (`*__.md`), keeping the active file as a focused "currently relevant" view. Two rotation criteria: **Status-based** (Rule A) for `_ISSUES.md` / `_TODO.md` per LLMP-DEC-44 vocabulary, and **last-15-active rolling window** (Rule B) for `LLM_PROTOCOL_DECISIONS.md` per LLMP-DEC-65 (supersedes the original yearly-at-~50 rule from LLMP-DEC-25). ## When to invoke @@ -33,18 +33,30 @@ User confirmation required. Never auto-invoke. - File has no closed entries — nothing to move - User is mid-investigation referencing entries that may be archived — defer until done -## Archive criterion (single rule) +## Archive criteria (two rules) + +### Rule A — Status-based (for `_ISSUES.md` / `_TODO.md`) Move entry X to archive IF `Status: Closed`. -Year derived from a date in the entry body (e.g., `Status: Closed (2026-04-25)` or a `### Resolution` sub-section dated `2026-04-25`, or `Superseded by ACCORE-LOG-I-K7M2 (2026-04-25)`). If no parseable date in body, default to current year. Status vocabulary follows `TOPIC_CODES.md` Status field conventions: only `Closed` is archive-eligible; `Open` and `InProgress` stay active. +**Year-month** derived from a date in the entry body (e.g., `Status: Closed (2026-04-25)` → bucket `2026_04`; or a `### Resolution` sub-section dated `2026-04-25` → same; or `Superseded by ACCORE-LOG-I-K7M2 (2026-04-25)` → same). If no parseable date in body, default to current year-month. Status vocabulary follows `TOPIC_CODES.md` Status field conventions: only `Closed` is archive-eligible; `Open` and `InProgress` stay active. **Stay in active file**: -- `Status: Open` — including documented-current-behaviour entries (these stay Open with a body callout per `TOPIC_CODES.md`'s Status field conventions) -- `Status: InProgress` -- Any entry without parseable Status (treat as Open; flag to user) +- `Status: Open` — including documented-current-behaviour entries (these stay Open with a body callout per `TOPIC_CODES.md`'s Status field conventions). +- `Status: InProgress`. +- Any entry without parseable Status (treat as Open; flag to user). -**Foundational LLMP-DEC entries**: protocol-meta decisions describing CURRENTLY-ACTIVE rules typically have no Status field — they stay in the active file naturally. If later superseded, they get `Status: Closed` and become archive-eligible normally. +### Rule B — Last-15-active rolling window (for `LLM_PROTOCOL_DECISIONS.md` only) + +The Decision Log's entries (`LLMP-DEC-N`) generally do NOT carry `Status` fields — they describe **historical decisions**, not work items with a lifecycle. Status-based archiving doesn't apply. + +Instead: **active log keeps last 15 entries** (rolling window — the 15 most-recent `LLMP-DEC-N` IDs). Older entries rotate to archive by **entry date** (year-month bucket from the `Date` column). + +Per LLMP-DEC-65 (supersedes the original "annual at ~50 entries" rule from LLMP-DEC-25). Foundational decisions (Rules #1-6, ID format spec, governance, etc.) survive in the **`## Current protocol state (quick reference)` summary** at the top of the active log even after their dated entry archives — that summary is the source of truth for "what's currently active" (LLMP-DEC-25 design + LLMP-DEC-60 governance). + +### Why two rules + +`_ISSUES.md` / `_TODO.md` track **work items** with a clear lifecycle (Open → InProgress → Closed); the `Closed` filter is meaningful. `LLM_PROTOCOL_DECISIONS.md` tracks **decisions** (each entry is a permanent record of a moment); there's no "Closed" lifecycle. Retention must differ. ## Step 1 — Identify scope @@ -83,17 +95,18 @@ If unclear, ask: *"process all 4 files (LOG, BIN, SIG, DEC)? Or narrow?"* For each affected file: -1. **Build archive file content** for each year present: - - Filename: `_.md` (e.g., `LOGGING_ISSUES_2025.md`) - - Header (2 lines): topic + "Archived entries (Status: closed) from ``. IDs preserved (never reassigned). Format identical to active file." - - Entries: closed entries from that year, in original chronological/ID order. +1. **Build archive file content** for each **year-month bucket** present: + - Filename: `__.md` (e.g., `LOGGING_ISSUES_2026_04.md`, `LLM_PROTOCOL_DECISIONS_2026_04.md`). + - Header: topic + "Archived entries from `` per LLMP-DEC-65 retention policy. IDs preserved (never reassigned). Format identical to active file." + - Entries: archive-eligible entries dated within that year-month, in original chronological/ID order. + - **Sparse files OK**: only month-buckets containing at least one archived entry get a file. No empty placeholder files. 2. **Build new active file content**: - Original header preserved. - **Insert a pointer block immediately after the header**: ``` - > **Archived entries**: see `_2025.md`, `_2026.md` (closed entries by year). - > Archive files are not auto-loaded — read on demand if relevant context is suspected (regression hint, supersession reference). + > **Archived entries**: see `_2026_04.md` (and other year-month buckets as more accumulate). + > Archive files are not auto-loaded — read on demand if relevant context is suspected (regression hint, supersession reference, ID lookup for archived entry). ``` - Remaining entries: only Open / Partially Fixed / Documented limitation / unknown-status. @@ -110,12 +123,19 @@ On explicit user approval: `Grep` archived IDs in: code (`*.cs`), other `.md` files. Report any references — but **do not auto-rewrite**. IDs are preserved; `docs-discovery`'s on-demand archive read finds them when needed. -## Step 7 — Decision Log archive case +## Step 7 — Decision Log archive case (Rule B specifics) -If `LLM_PROTOCOL_DECISIONS.md` was archived: -- "Current protocol state" summary at top stays in active file unchanged. -- Dated table rows for `Superseded by` entries move to `LLM_PROTOCOL_DECISIONS_.md`. -- Yearly archive convention already documented (LLMP-DEC governance section). +If `LLM_PROTOCOL_DECISIONS.md` is being archived (Rule B): + +1. **`## Current protocol state (quick reference)` summary** at top STAYS in the active file unchanged. This summary is foundational — the source of truth for "what's currently active" — and survives all archiving (per LLMP-DEC-25 design + LLMP-DEC-60 governance). +2. **Identify entries beyond the rolling window**: count active table rows under `## YYYY`. If count > 15, the oldest entries (lowest `LLMP-DEC-N` IDs) above the cap are archive-eligible. +3. **Group archive-eligible entries by year-month** based on each entry's `Date` column. +4. **Filename**: `LLM_PROTOCOL_DECISIONS__.md` (one file per year-month bucket present in the eligible set; sparse OK). +5. **Pointer block** at top of `## YYYY` section in the active log: brief sentence + reference to all known archive files for this log (e.g., "Earlier entries (LLMP-DEC-1..49) archived to `LLM_PROTOCOL_DECISIONS_2026_04.md` per LLMP-DEC-65"). Update / append as more archives accumulate. +6. **Cross-link integrity**: when active entries reference archived entries by ID (e.g., LLMP-DEC-58 references LLMP-DEC-43), the references remain functional — readers open the archive file. IDs are append-only and stable. +7. **Governance section** in the summary stays synchronized with the LLMP-DEC-65 last-15-active + year-month bucket rule. If the rule itself changes, governance text + this Step 7 + the frontmatter description all update together (cross-LLMP-DEC governance). + +Per LLMP-DEC-65 (supersedes the original "annual at ~50 entries" rule from LLMP-DEC-25). Only the new (LLMP-DEC-65) is in effect. ## Edge cases diff --git a/AyCode.Core.Tests/Serialization/AcBinarySerializerPipeParallelTests.cs b/AyCode.Core.Tests/Serialization/AcBinarySerializerPipeParallelTests.cs new file mode 100644 index 0000000..9814cae --- /dev/null +++ b/AyCode.Core.Tests/Serialization/AcBinarySerializerPipeParallelTests.cs @@ -0,0 +1,146 @@ +using AyCode.Core.Serializers.Binaries; +using static AyCode.Core.Tests.TestModels.AcSerializerModels; + +namespace AyCode.Core.Tests.Serialization; + +[TestClass] +public class AcBinarySerializerPipeParallelTests +{ + [TestMethod] + public async Task SerializeAndDeserialize_InParallelOnTwoTasks_ThroughPipe_RoundTrip() + { + var original = CreatePayload(200); + var options = AcBinarySerializerOptions.Default; + + using var reader = new SegmentBufferReader(64); + + var deserializeTask = Task.Run(() => + (TestParentWithDateTimeItemCollection?)AcBinaryDeserializer.Deserialize(reader, typeof(TestParentWithDateTimeItemCollection), options)); + + var serializeTask = Task.Run(async () => + { + try + { + var binary = AcBinarySerializer.Serialize(original, options); + var offset = 0; + var chunkSizes = new[] { 7, 31, 13, 64, 5, 29 }; + + for (var chunkIndex = 0; offset < binary.Length; chunkIndex++) + { + var chunkSize = Math.Min(chunkSizes[chunkIndex % chunkSizes.Length], binary.Length - offset); + reader.Write(binary.AsSpan(offset, chunkSize)); + offset += chunkSize; + + if (chunkIndex % 4 == 0) + await Task.Yield(); + } + } + finally + { + reader.Complete(); + } + }); + + await Task.WhenAll(serializeTask, deserializeTask); + + var result = deserializeTask.Result; + Assert.IsNotNull(result); + AssertPayloadEquals(original, result); + } + + [TestMethod] + public async Task SerializeAndDeserialize_InParallelOnTwoTasks_WithMultiplePipelines_RoundTrip() + { + var options = AcBinarySerializerOptions.Default; + + var pipelines = Enumerable.Range(1, 8).Select(async seed => + { + var original = CreatePayload(80 + seed * 10); + + using var reader = new SegmentBufferReader(32); + + var deserializeTask = Task.Run(() => + (TestParentWithDateTimeItemCollection?)AcBinaryDeserializer.Deserialize(reader, typeof(TestParentWithDateTimeItemCollection), options)); + + var serializeTask = Task.Run(async () => + { + try + { + var binary = AcBinarySerializer.Serialize(original, options); + var offset = 0; + var chunkSize = (seed % 5) + 1; + while (offset < binary.Length) + { + var take = Math.Min(chunkSize, binary.Length - offset); + reader.Write(binary.AsSpan(offset, take)); + offset += take; + await Task.Yield(); + } + } + finally + { + reader.Complete(); + } + }); + + await Task.WhenAll(serializeTask, deserializeTask); + + var result = deserializeTask.Result; + Assert.IsNotNull(result); + AssertPayloadEquals(original, result); + }); + + await Task.WhenAll(pipelines); + } + + private static TestParentWithDateTimeItemCollection CreatePayload(int itemCount) + { + var now = DateTime.UtcNow; + var items = new List(itemCount); + + for (var i = 0; i < itemCount; i++) + { + items.Add(new TestEntityWithDateTimeAndInt + { + Id = i + 1, + IntValue = i * 3, + Created = now.AddMinutes(-i), + Modified = now.AddMinutes(i), + StatusCode = i % 4, + Name = $"item-{i}" + }); + } + + return new TestParentWithDateTimeItemCollection + { + Id = 11, + Name = "pipe-parallel-test", + Created = now, + Items = items + }; + } + + private static void AssertPayloadEquals(TestParentWithDateTimeItemCollection expected, TestParentWithDateTimeItemCollection actual) + { + Assert.AreEqual(expected.Id, actual.Id); + Assert.AreEqual(expected.Name, actual.Name); + Assert.AreEqual(expected.Created, actual.Created); + + Assert.IsNotNull(expected.Items); + Assert.IsNotNull(actual.Items); + Assert.AreEqual(expected.Items.Count, actual.Items.Count); + + for (var i = 0; i < expected.Items.Count; i++) + { + var e = expected.Items[i]; + var a = actual.Items[i]; + + Assert.AreEqual(e.Id, a.Id); + Assert.AreEqual(e.IntValue, a.IntValue); + Assert.AreEqual(e.Created, a.Created); + Assert.AreEqual(e.Modified, a.Modified); + Assert.AreEqual(e.StatusCode, a.StatusCode); + Assert.AreEqual(e.Name, a.Name); + } + } +} diff --git a/AyCode.Services.Server/README.md b/AyCode.Services.Server/README.md index d590eab..49f64fc 100644 --- a/AyCode.Services.Server/README.md +++ b/AyCode.Services.Server/README.md @@ -11,7 +11,7 @@ Server-side service implementations: JWT authentication, SendGrid email delivery | Document | Topic | |---|---| | `SIGNALR/README.md` | Server-side SignalR hub (dispatch, session, broadcast) | -| `SIGNALR/SIGNALR_DATASOURCE.md` | Real-time DataSource with CRUD & change tracking | +| `SIGNALR_DATASOURCE/README.md` | Real-time DataSource with CRUD & change tracking | ## Folder Structure diff --git a/AyCode.Services.Server/SignalRs/README.md b/AyCode.Services.Server/SignalRs/README.md index b83dbe1..8a29b99 100644 --- a/AyCode.Services.Server/SignalRs/README.md +++ b/AyCode.Services.Server/SignalRs/README.md @@ -18,7 +18,7 @@ Server-side SignalR hub infrastructure: hub base class, session management, data ### Data Source -> **Full specification:** `AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md` +> **Full specification:** `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` - **`AcSignalRDataSource.cs`** — Generic real-time collection (`AcSignalRDataSource`) implementing `IList` with full CRUD and change tracking. - **Change tracking:** `TrackingItem` wraps each modified item with `TrackingState` + `OriginalValue` for rollback. `ChangeTracking` manages the tracking list. diff --git a/AyCode.Services.Server/docs/README.md b/AyCode.Services.Server/docs/README.md index 52e3bf4..089e4ba 100644 --- a/AyCode.Services.Server/docs/README.md +++ b/AyCode.Services.Server/docs/README.md @@ -4,7 +4,8 @@ Topic documentation for the `AyCode.Services.Server` project (Layer 0, server-si ## Topics -- [`SIGNALR/`](SIGNALR/README.md) — Server-side SignalR (hub base + data source pattern) +- [`SIGNALR/`](SIGNALR/README.md) — Server-side SignalR hub (dispatch, session, broadcast) +- [`SIGNALR_DATASOURCE/`](SIGNALR_DATASOURCE/README.md) — Client-server DataSource on SignalR transport (change tracking, rollback, sync state, IList wrapper) ## Navigation diff --git a/AyCode.Services.Server/docs/SIGNALR/README.md b/AyCode.Services.Server/docs/SIGNALR/README.md index 020309c..e1f5efe 100644 --- a/AyCode.Services.Server/docs/SIGNALR/README.md +++ b/AyCode.Services.Server/docs/SIGNALR/README.md @@ -3,7 +3,7 @@ Server-side SignalR hub infrastructure: method dispatch, session management, broadcast, and diagnostics. Source: `SignalRs/` in this project. > For client-side transport (tags, wire protocol, client base) see `AyCode.Services/docs/SIGNALR/README.md`. -> For the DataSource collection see `SIGNALR_DATASOURCE.md`. +> For the DataSource collection see `../SIGNALR_DATASOURCE/README.md`. ## Server Processing diff --git a/AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md b/AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md deleted file mode 100644 index c6eb289..0000000 --- a/AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md +++ /dev/null @@ -1,191 +0,0 @@ -# SignalR DataSource - -Change-tracked real-time collection built on top of the SignalR transport layer. Source: `SignalRs/AcSignalRDataSource.cs` in this project. - -> For the underlying transport (tag system, wire protocol, client base) see `AyCode.Services/docs/SIGNALR/README.md`. -> For server hub infrastructure see `README.md`. - -## Overview - -`AcSignalRDataSource` is a generic `IList` that synchronizes with the server via CRUD tags. It handles change tracking, rollback, sync state, and binary deserialization — so consuming code works with a regular list while the DataSource manages communication. - -```csharp -AcSignalRDataSource - where TDataItem : class, IId // entity with ID - where TId : struct // Guid, int, etc. - where TIList : class, IList // List or AcObservableCollection -``` - -Implements `IList`, `IList`, `IReadOnlyList`. - -**Constructor:** - -```csharp -new AcSignalRDataSource( - AcSignalRClientBase signalRClient, // transport client - SignalRCrudTags crudTags, // 5 tags for CRUD operations - object[]? contextIds = null // optional server-side filter context -) -``` - -## SignalRCrudTags - -A `sealed class` that bundles **5 independent tag integers** — one per CRUD operation. Tags are NOT sequential offsets; each tag is independently assigned: - -```csharp -public sealed class SignalRCrudTags( - int getAllTag, - int getItemTag, - int addTag, - int updateTag, - int removeTag) -``` - -**Usage (consuming project):** - -```csharp -public abstract class MyProjectTags : AcSignalRTags -{ - public const int OrderGetAll = 300; - public const int OrderGetItem = 301; - public const int OrderAdd = 302; - public const int OrderUpdate = 303; - public const int OrderRemove = 304; -} - -var crudTags = new SignalRCrudTags( - MyProjectTags.OrderGetAll, - MyProjectTags.OrderGetItem, - MyProjectTags.OrderAdd, - MyProjectTags.OrderUpdate, - MyProjectTags.OrderRemove -); -``` - -**Tag lookup:** `GetMessageTagByTrackingState(TrackingState)` maps tracking state to the corresponding tag via switch expression. - -## Data Loading - -```csharp -await dataSource.LoadDataSource(); // sync-wait transport (polls up to 60s) -await dataSource.LoadDataSourceAsync(); // async callback path -await dataSource.LoadDataSourceFromResponseData(responseData, serializerType); -await dataSource.LoadItem(id); // single item by ID -``` - -**Deserialization paths:** -- **Typed response** (`T != byte[]`): protocol eagerly deserializes via `SignalDataType` → `GetResponseData()` direct cast. -- **Raw byte[] response** (`IsRawBytesData`): protocol returns raw `byte[]` → consumer deserializes: - - `AcObservableCollection`: `BeginUpdate()` → `PopulateMerge(bytes)` → `EndUpdate()` — single batched UI notification. - - `List`: `BinaryTo(InnerList)` — direct populate. - -**Context/Filtering:** `ContextIds` (object[]) and `FilterText` (string) are sent with every GetAll request for server-side filtering. - -## Change Tracking - -Each modified item is wrapped in `TrackingItem`: - -| Field | Purpose | -|-------|---------| -| `TrackingState` | Add, Update, Remove | -| `CurrentValue` | Current item reference | -| `OriginalValue` | Clone for rollback (`JsonClone` or `ReflectionClone`) | - -The `ChangeTracking` class manages the list of tracked items. - -### CRUD Operations - -``` -Add(item): → TrackingState.Add + InnerList.Add(item) -AddOrUpdate(item): → exists? Update : Add (determines TrackingState automatically) -Insert(index, item): → TrackingState.Add + InnerList.Insert(index, item) -Update(i, item): → TrackingState.Update + clone original + InnerList[i] = item -Remove(id): → TrackingState.Remove + clone original + InnerList.RemoveAt(index) -``` - -Each operation has an optional `autoSave` parameter — if true, immediately calls `SaveItem()` for that single change. - -**Manual tracking:** `SetTrackingStateToUpdate(item)` marks an existing item as modified without replacing it — useful when properties are mutated in-place. - -### Events - -| Event | Signature | Fires when | -|-------|-----------|------------| -| `OnDataSourceItemChanged` | `Func, Task>?` | After each item is saved or loaded | -| `OnDataSourceLoaded` | `Func?` | After `LoadDataSource` / `LoadDataSourceAsync` completes | -| `OnSyncingStateChanged` | `Action?` | On 0→1 (true) and 1→0 (false) sync transitions | - -## SaveChanges - -| Method | Returns | Transport pattern | Use case | -|--------|---------|-------------------|----------| -| `SaveChanges()` | `List` (remaining failures) | Sync-wait (`ContinueWith`) | When caller needs to know what failed | -| `SaveChangesAsync()` | `Task` (void) | Fire-and-forget callback (`Action`) | Background save, no result inspection | - -``` -Both follow the same flow: - BeginSync() - for each tracked item: - tag = CrudTags.GetMessageTagByTrackingState(state) - response = SignalRClient.PostDataAsync(tag, item) - on success: remove from tracking, CopyTo InnerList item with server response - on failure: TryRollbackItem() → restore OriginalValue - EndSync() -``` - -**Rollback:** `TryRollbackItem(id)` restores `OriginalValue` to `InnerList`. For `TrackingState.Add`: removes item entirely. For `Remove`: re-adds `OriginalValue`. Manual `Rollback()` reverts all tracked changes at once. - -## Sync State - -```csharp -private int _activeSyncOperations; // Interlocked counter - -BeginSync(): Interlocked.Increment → fires OnSyncingStateChanged(true) on 0→1 -EndSync(): Interlocked.Decrement → fires OnSyncingStateChanged(false) on 1→0 -IsSyncing: _activeSyncOperations > 0 -``` - -UI binds to `IsSyncing` to show loading indicators. The counter supports nested sync operations. - -## Working Reference List - -```csharp -dataSource.SetWorkingReferenceList(externalList); -// Now dataSource operates directly on externalList — same reference, no copy - -TIList innerList = dataSource.GetReferenceInnerList(); -``` - -Useful when the UI already has a bound collection and you want the DataSource to manage it in-place. - -## Locking Strategy - -| Lock | Scope | Used by | -|------|-------|---------| -| `object _syncRoot` | Synchronous | Count, Contains, IndexOf, GetEnumerator | -| `SemaphoreSlim _asyncLock` | Asynchronous | Add/Update/Remove with save, LoadDataSource | - -`GetEnumerator()` returns `InnerList.ToList().GetEnumerator()` — safe copy to avoid mutation during iteration. - -## Relationship to Transport - -The DataSource is a **consumer** of the SignalR transport, not part of it: - -``` -DataSource.SaveChanges() - → CrudTags.GetMessageTagByTrackingState(state) → tag - → AcSignalRClientBase.PostDataAsync(tag, item) ← transport layer - → OnReceiveMessage(tag, bytes, requestId) ← wire protocol - → Server method with [SignalR(tag)] ← tag dispatch -``` - -Projects can also call the transport directly without DataSource — see `AyCode.Services/docs/SIGNALR/README.md`. - -## Key Source Files - -| Component | Path | -|-----------|------| -| DataSource | `SignalRs/AcSignalRDataSource.cs` | -| Tracking helpers | `SignalRs/TrackingItemHelpers.cs` | -| CRUD tags | `AyCode.Services/SignalRs/SignalRCrudTags.cs` | -| Transport client | `AyCode.Services/SignalRs/AcSignalRClientBase.cs` | diff --git a/AyCode.Services.Server/docs/SIGNALR_DATASOURCE/SIGNALR_DATASOURCE_TODO.md b/AyCode.Services.Server/docs/SIGNALR_DATASOURCE/SIGNALR_DATASOURCE_TODO.md index 381cfcf..f94f497 100644 --- a/AyCode.Services.Server/docs/SIGNALR_DATASOURCE/SIGNALR_DATASOURCE_TODO.md +++ b/AyCode.Services.Server/docs/SIGNALR_DATASOURCE/SIGNALR_DATASOURCE_TODO.md @@ -7,6 +7,39 @@ Forward-looking work specific to `AcSignalRDataSource`. Transport-side TODOs liv --- +## ACCORE-SIGDS-T-D9F2: Relocate AcSignalRDataSource + TrackingItemHelpers to AyCode.Services +**Priority:** P2 · **Type:** Architectural cleanup · **Status:** Open + +Both files currently live in `AyCode.Services.Server/SignalRs/`, but **neither has any Server-only dependency**: + +- `AcSignalRDataSource.cs` using statements: only `AyCode.Core.*` + `AyCode.Services.SignalRs` (client-side namespace) — zero `AyCode.*.Server` references. +- `TrackingItemHelpers.cs` using statements: only `System.Reflection` + `AyCode.Core.Extensions`. +- `AyCode.Services.csproj` reference graph already covers all transitive needs (AyCode.Core, AyCode.Entities, AyCode.Interfaces, AyCode.Models). +- `SignalRCrudTags` (the DataSource constructor's required argument type) lives in `AyCode.Services` — consumers must currently reference both `AyCode.Services` and `AyCode.Services.Server` for one logical API. +- All other files in `AyCode.Services.Server/SignalRs/` are genuinely Server-only (Hub subclasses, session service, broadcast, server protocol extensions, server hub interfaces). + +**Practical impact:** Blazor.WebAssembly cannot reference `AyCode.Services.Server` (its dependency graph pulls in `AyCode.Database`, `KeyDerivation`, `SendGrid` — none WASM-compatible). WASM consumers wanting `AcSignalRDataSource` are currently blocked. + +### Acceptance +- [ ] `AcSignalRDataSource.cs` moved: `AyCode.Services.Server/SignalRs/` → `AyCode.Services/SignalRs/`; namespace `AyCode.Services.Server.SignalRs` → `AyCode.Services.SignalRs`. +- [ ] `TrackingItemHelpers.cs` moved + namespace updated. +- [ ] Consumer `using AyCode.Services.Server.SignalRs;` lines pulling these types updated to `using AyCode.Services.SignalRs;`. +- [ ] Doc folder relocated: `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/` → `AyCode.Services/docs/SIGNALR_DATASOURCE/` (3 files: README + ISSUES + TODO). +- [ ] `TOPIC_CODES.md` SIGDS row "Docs location" updated (`AyCode.Services.Server/...` → `AyCode.Services/...`). +- [ ] Doc-index READMEs updated: remove SIGDS row from `Services.Server/docs/README.md`; add to `Services/docs/README.md`. +- [ ] All cross-refs in workspace updated (~15 paths across AyCode.Core + AyCode.Blazor) per the path-rewrite pattern used in LLMP-DEC-66. +- [ ] `AyCode.Services.Server/README.md` + `AyCode.Services.Server/SignalRs/README.md` doc tables: SIGDS rows removed. +- [ ] `AyCode.Services/SignalRs/README.md` doc table: DataSource entry added (currently no Data Source section there). +- [ ] Tests in `AyCode.Services.Server.Tests/SignalRs/SignalRDatasources/` re-evaluated — likely keep in Server.Tests (full hub environment) but update `using` statements; or split into `AyCode.Services.Tests/SignalRs/SignalRDatasources/` if isolated. +- [ ] New `LLMP-DEC` entry filed (SIGDS phase 2 relocation, cross-references `LLMP-DEC-66`). +- [ ] Build green across all consumers (AyCode.Blazor.Components, FruitBankHybridApp, etc.); WASM build verified if applicable. + +### Related +- `LLMP-DEC-66` (SIGDS topic introduction — this TODO completes the architectural side that the docs-side migration left open) +- Parallels `LLMP-DEC-58` Framework-First retightening principle (consumer-side code shouldn't live in Server-flavored projects) + +--- + ## ACCORE-SIGDS-T-N5R8: ChangeTracking._trackingItems → Dictionary **Priority:** P3 · **Type:** Performance refactor · **Status:** Open diff --git a/AyCode.Services/SignalRs/README.md b/AyCode.Services/SignalRs/README.md index c4c6b67..207c6ce 100644 --- a/AyCode.Services/SignalRs/README.md +++ b/AyCode.Services/SignalRs/README.md @@ -21,7 +21,7 @@ Custom binary SignalR protocol, client infrastructure, message tagging, and seri ### Message Tagging - **`SignalMessageTagAttribute.cs`** — Three attributes: `TagAttribute` (base, int messageTag), `SignalRAttribute` (server method routing + client notification), `SignalRSendToClientAttribute` (client-side receive). - **`AcSignalRTags.cs`** — Static constants: `None`, `PingTag`, `EchoTag`. -- **`SignalRCrudTags.cs`** — Sealed class bundling 5 independent CRUD tag integers. `GetMessageTagByTrackingState()` maps `TrackingState` -> tag. See `AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md`. +- **`SignalRCrudTags.cs`** — Sealed class bundling 5 independent CRUD tag integers. `GetMessageTagByTrackingState()` maps `TrackingState` -> tag. See `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md`. - **`SendToClientType.cs`** — Enum: None, Others, Caller, All. ### Serialization & Pooling diff --git a/AyCode.Services/docs/README.md b/AyCode.Services/docs/README.md index b245b71..7c5d111 100644 --- a/AyCode.Services/docs/README.md +++ b/AyCode.Services/docs/README.md @@ -17,4 +17,5 @@ Per the AI Agent Core Protocol (folder navigation rule), start from this README - **Base logger** (framework): `../../AyCode.Core/AyCode.Core/docs/LOGGING/README.md` - **Server-side logger** (variant): `../../AyCode.Core.Server/docs/LOGGING/README.md` - **Server-side SignalR**: `../../AyCode.Services.Server/docs/SIGNALR/README.md` +- **Server-side SignalR DataSource**: `../../AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` - **Binary serializer** (used by SIGNALR_BINARY_PROTOCOL): `../../AyCode.Core/AyCode.Core/docs/BINARY/README.md` diff --git a/AyCode.Services/docs/SIGNALR/README.md b/AyCode.Services/docs/SIGNALR/README.md index e1979b7..2555e9b 100644 --- a/AyCode.Services/docs/SIGNALR/README.md +++ b/AyCode.Services/docs/SIGNALR/README.md @@ -3,7 +3,7 @@ Client-side SignalR transport: custom binary protocol, tag-based dispatch. Source: `SignalRs/` > Server-side hub, session, broadcast: `AyCode.Services.Server/docs/SIGNALR/README.md` -> DataSource collection: `AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md` +> DataSource collection: `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md` ## Design diff --git a/README.md b/README.md index 00df25b..5e09c70 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Project-level docs — each project's `docs/` folder documents the code it defin | `AyCode.Core/docs/` | `BINARY/` (README, FORMAT, FEATURES, OPTIONS, …), `LOGGING/` (README, ISSUES, TODO) | | `AyCode.Core.Server/docs/` | `LOGGING/README.md` (server-side variant) | | `AyCode.Services/docs/` | `SIGNALR/`, `SIGNALR_BINARY_PROTOCOL/`, `LOGGING/README.md` (remote variant) | -| `AyCode.Services.Server/docs/` | `SIGNALR/` (README + SIGNALR_DATASOURCE) | +| `AyCode.Services.Server/docs/` | `SIGNALR/` (README), `SIGNALR_DATASOURCE/` (README + ISSUES + TODO) | ## Solution Structure diff --git a/docs/CONVENTIONS.md b/docs/CONVENTIONS.md index c5b8dea..0dfa5d0 100644 --- a/docs/CONVENTIONS.md +++ b/docs/CONVENTIONS.md @@ -28,7 +28,7 @@ See `AyCode.Services/docs/SIGNALR/README.md` for full architecture documentation - **Single dispatch method** — all communication goes through `OnReceiveMessage(int messageTag, int? requestId, SignalParams signalParams, object data)`. Do not add new hub methods. - **Tag-based routing** — associate methods with integer tags via `[SignalR(tag)]` (server) or `[SignalRSendToClient(tag)]` (client). Tags must be unique across the entire system. -- **CRUD bundles** — entities use `SignalRCrudTags(getAllTag, getItemTag, addTag, updateTag, removeTag)` with 5 independent tag integers. Tags must be unique across the system. See `AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md`. +- **CRUD bundles** — entities use `SignalRCrudTags(getAllTag, getItemTag, addTag, updateTag, removeTag)` with 5 independent tag integers. Tags must be unique across the system. See `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md`. - **Binary protocol** — `AyCodeBinaryHubProtocol` (derived from `AcBinaryHubProtocol`) is the transport protocol. Zero-copy write: `AcBinarySerializer.Serialize(value, output)` directly to pipe. Zero-copy read: `SequenceReader` + type-aware deserialization via `SignalParams.SignalDataType`. Three read paths: byte[] fast-path (0x44 tag), IsRawBytesData (raw byte[]), typed deserialization. ### ⚠️ Temporary: JSON-in-Binary Request Parameters diff --git a/docs/GLOSSARY.md b/docs/GLOSSARY.md index 01c8eed..1a23a82 100644 --- a/docs/GLOSSARY.md +++ b/docs/GLOSSARY.md @@ -76,7 +76,7 @@ For full architecture see `AyCode.Services/docs/SIGNALR/README.md`. | **SignalParams** | Metadata sent alongside message payload as separate hub argument. Contains `Status`, `DataSerializerType`, `Parameters` (`byte[]?` — packed `byte[][]` as single blob), `SignalDataType` (`string?` — response type for eager deserialization), `IsRawBytesData` (`bool` — return raw bytes without deserialization). Typed access via `SetParameterValues(object[])` / `GetParameterValues(ParameterInfo[])` — PostDataJson pattern. `[AcBinarySerializable]`. Never null — only fields inside are nullable. | | **Message Tag** | Integer identifier mapping to a method via `[SignalR(tag)]` or `[SignalRSendToClient(tag)]` attributes. | | **DynamicMethodRegistry** | Resolves message tags to `MethodInfo` at runtime. Static `ConcurrentDictionary` cache with lazy scan on miss. | -| **SignalRCrudTags** | Sealed class bundling 5 independent tag integers (getAllTag, getItemTag, addTag, updateTag, removeTag) for entity CRUD. See `AyCode.Services.Server/docs/SIGNALR/SIGNALR_DATASOURCE.md`. | +| **SignalRCrudTags** | Sealed class bundling 5 independent tag integers (getAllTag, getItemTag, addTag, updateTag, removeTag) for entity CRUD. See `AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md`. | | **AcBinaryHubProtocol** | Unsealed base `IHubProtocol` replacing SignalR's JSON+Base64 with `AcBinarySerializer`. Protocol name: `"acbinary"` (configurable). Options-based ctor: `new AcBinaryHubProtocol(AcBinaryHubProtocolOptions)`. Write: `BufferWriterBinaryOutput` / `AsyncPipeWriterOutput` zero-copy to pipe. Read: `ArrayBinaryInput` via `GetArgBytes` (zero-copy single-seg / pool-rent multi-seg) for non-chunked; chunked receive via `SegmentBufferReader` + `SegmentBufferReaderInput` with platform-aware fallback. | | **AyCodeBinaryHubProtocol** | Consumer-specific derived protocol (per-message header with `DataFlags`, `IsRawBytesData`, type resolution). Registered via `services.AddSignalR().AddAcBinaryProtocol(...)` on the server and `hubBuilder.AddAcBinaryProtocol(...)` on the client. | | **AcBinaryHubProtocolOptions** | Mutable config class for protocol registration. Properties: `SerializerOptions`, `ProtocolMode`, `BufferSize`, `WaitForFlush`, `FlushTimeout`, `Name`, `Logger`. `Validate()` enforces invariants (incl. WASM + AsyncSegment block). `Clone()` for DI `IOptions` safety. | diff --git a/docs/README.md b/docs/README.md index 42d9a4d..6c43db4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ Top-level documentation for the `AyCode.Core` repo (Layer 0 — core framework). - `AyCode.Core/docs/` — Logger, Binary serializer (paired topics: LOGGING/, BINARY/) - `AyCode.Core.Server/docs/` — Server-side logger variant (LOGGING/) - `AyCode.Services/docs/` — Remote logger variant, SignalR, SignalR binary protocol -- `AyCode.Services.Server/docs/` — Server-side SignalR + data source +- `AyCode.Services.Server/docs/` — Server-side SignalR hub (SIGNALR/), SignalR DataSource (SIGNALR_DATASOURCE/) ## Navigation