From dc8e01250d07b538c38ddf124a746f633101c1a1 Mon Sep 17 00:00:00 2001 From: Loretta Date: Thu, 9 Jul 2026 06:57:22 +0200 Subject: [PATCH] Rotate DEC log, archive closed TODOs, add GiaApp consumer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rotated `LLM_PROTOCOL_DECISIONS.md` per last-15-active policy: archived entries 53–54 to `LLM_PROTOCOL_DECISIONS_2026_04.md`, updated archive pointers and summary notes. - Archived all `Status: Closed` entries from `SIGNALR_BINARY_PROTOCOL_TODO.md` to new `SIGNALR_BINARY_PROTOCOL_TODO_2026_05.md`; added archive pointer and explanatory header. - Updated `CONSUMERS.md` to add GiaApp (GIAAPP), raising consumer count to 7. - Keeps active logs concise and historical entries accessible per year-month bucket archival policy. --- .github/LLM_PROTOCOL_DECISIONS.md | 5 +- .github/LLM_PROTOCOL_DECISIONS_2026_04.md | 6 +- .../SIGNALR_BINARY_PROTOCOL_TODO.md | 123 +---------------- .../SIGNALR_BINARY_PROTOCOL_TODO_2026_05.md | 127 ++++++++++++++++++ CONSUMERS.md | 5 +- 5 files changed, 139 insertions(+), 127 deletions(-) create mode 100644 AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO_2026_05.md diff --git a/.github/LLM_PROTOCOL_DECISIONS.md b/.github/LLM_PROTOCOL_DECISIONS.md index 0e704a1..b51587a 100644 --- a/.github/LLM_PROTOCOL_DECISIONS.md +++ b/.github/LLM_PROTOCOL_DECISIONS.md @@ -112,14 +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. +> **Earlier entries archived**: LLMP-DEC-1..54 (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 ≤ 54), open the archive file to read the full text — IDs are stable, never reassigned. > > **Year-month buckets** (LLMP-DEC-67 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-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) | | LLMP-DEC-56 | 2026-04-26 | Phase 4 of ID-format migration: created `MIGRATION_ID_MAPPING.md` mapping table (79 entries surveyed and given new random `` suffix) | Phase 4 of LLMP-DEC-50 migration — survey + planning, no existing-entry rename. Workspace-wide grep `\b[A-Z]+-[A-Z]+-[0-9]+\b` over `.md` files: 79 unique entries identified — 77 in ACCORE (BIN: 19, LOG: 21, SIG: 15, SBP: 10, TOON: 11, XCUT: 1) + 2 in ACBLAZOR (GRID: 2). Other 5 repos: 0 entries. Each ID assigned a 4-char `[A-Z0-9]` random suffix; verified within-triplet uniqueness for all 12 `--` triplets. **Pending forward-refs documented separately**: `LOG-T-12` (referenced in `docs/AUTH/README.md` + ADR-0001 but not defined in `LOGGING_TODO.md`) and `SBP-T-9` (referenced in decorator-feature-stack ADR but not defined in `SIGNALR_BINARY_PROTOCOL_TODO.md`) — Phase 4 captures them in 'Pending forward-references' section, decision deferred to Phase 6. **Template/placeholder IDs noted**: `GRID-I-1` (MGGRID_ISSUES.md example line), `AUTH-I-N` (generic placeholder) — not migrated, reformatted alongside topic rename in Phase 5. **Original Phase 7 deletion plan** for this mapping file later revised by user — see LLMP-DEC-58. | new file: `AyCode.Core/.github/MIGRATION_ID_MAPPING.md` | | LLMP-DEC-57 | 2026-04-26 | Phase 5 of ID-format migration: per-topic rename of all 79 existing entries from 3-component `--` to 4-component `---` format (132 edits) | Phase 5 of LLMP-DEC-50 migration — actual entry rename. Topic-by-topic execution driven by Phase 4 mapping (LLMP-DEC-56). **Strict scope**: topic-pair files (`_ISSUES.md` + `_TODO.md`) + sister docs in same topic folder (e.g., `BINARY/README.md`, `BINARY_SGEN.md`, `BINARY_IMPLEMENTATION.md`, `TOON_INFERENCE.md`); inter-topic body anchors deferred to Phase 6. **Per-topic edit counts**: GRID 6 (2 IDs + placeholder template reformat), XCUT 7 (1 canonical + 2 cross-ref pointer headers in BINARY_ISSUES/SIGNALR_ISSUES + intra-XCUT body anchors), SBP 11 (10 IDs + 2 intra-file body refs), TOON 14 (11 IDs + 3 sister-doc anchors), BIN 33 (19 IDs + intra-pair anchors + 2 sister docs; **prefix-collision-driven descending order** required because BIN-I-1 is substring of BIN-I-10..15), SIG 21 (15 IDs + intra-pair anchors + sister doc + malformed `#issue-02` anchor fixed), LOG 40 (21 IDs + intra-pair anchors + sister LOGGING/README; LOG-I and LOG-T both required descending order — LOG-I-1 is prefix of LOG-I-10, LOG-T-1 is prefix of LOG-T-10/11). **Replace_all=true used per (file, old-id)** with descending-suffix order for prefix-collision-prone topics. **Final intra-scope verification**: 0 bare 3-component IDs remaining in any topic-pair file or sister doc; all 79 IDs renamed to canonical 4-component format. **Inter-topic refs known-deferred to Phase 6**: cross-file body anchors targeting renamed IDs (e.g., `XCUT_ISSUES.md#xcut-i-1` from `BINARY_TODO.md`), inter-topic body uppercase IDs (e.g., 'XCUT-I-1 / BIN-T-1 have landed' in SIG-T-6 body), AUTH/ADR cross-refs. | 7 topics, ~25 files: BINARY/{ISSUES,TODO,SGEN,IMPLEMENTATION}.md; LOGGING/{ISSUES,TODO,README}.md; SIGNALR/{ISSUES,TODO,README}.md; SIGNALR_BINARY_PROTOCOL/{ISSUES,TODO}.md; TOON/{ISSUES,TODO,README,IMPLEMENTATION,INFERENCE}.md; XCUT/{ISSUES,README}.md + cross-ref pointer entries in BINARY_ISSUES.md and SIGNALR_ISSUES.md; MGGRID/{TODO,ISSUES}.md; **132 edits total** | @@ -134,6 +132,7 @@ The "primary" vs "inherit" distinction is defined in `protocol-audit/references/ | 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) | | LLMP-DEC-68 | 2026-06-07 | SIGDS phase 2 (code side): relocated `AcSignalRDataSource` + `TrackingItemHelpers` (`AyCode.Services.Server` → `AyCode.Services`) + removed orphan `SignalR.Core 1.2.0` from `AyCode.Blazor.Components` → unblocked WASM AOT for Blazor WebAssembly consumers; closes `ACCORE-SIGDS-T-D9F2` | Completes the code side of LLMP-DEC-66 (which moved only the SIGDS docs). **Symptom**: `FruitBankHybrid.Web.Client` (InteractiveWebAssembly) could not AOT-publish — Mono AOT cross-compiler crashed (`exit -1073741819`) precompiling `Microsoft.AspNetCore.SignalR.Core.dll` (`HubCallerContext.get_Features` → missing `Http.Features 2.x`). **Two root sources**: (1) `AcSignalRDataSource` lived in `AyCode.Services.Server` — a server assembly whose graph pulls `SignalR.Core` + `AyCode.Database`/`KeyDerivation`/`SendGrid` (none WASM-compatible) — forcing every WASM consumer to reference it; (2) an **orphan `Microsoft.AspNetCore.SignalR.Core 1.2.0`** (netstandard2.0 server-hub) `PackageReference` in `AyCode.Blazor.Components.csproj`, unused by code. JIT-WASM tolerated both (lazy load); AOT compiles all assemblies eagerly → crash. **Fix**: (a) `git mv` both files to `AyCode.Services/SignalRs/`, namespace `…Server.SignalRs` → `AyCode.Services.SignalRs` (zero server-only deps; dropped stray `Castle.Core.Logging` using); (b) removed the `SignalR.Core 1.2.0` package; (c) cleaned `.Server` DLL refs from Web.Client/Shared/Components csproj; (d) updated consumer usings; (e) `RunAOTCompilation=true` on Web.Client. **Verified**: AOT-input 175→165 assemblies, `SignalR.Core` gone, publish green (`[164/164]` AOT + emcc link). **Server stays JIT** (IIS in-process compatible — server Native AOT was never the goal; only the browser-WASM client AOTs, the user-observed ~2-3× deserialize speedup). **TourIAm consumer intentionally NOT updated** (per user — its build breaks until separately fixed). | moved: `AyCode.Services/SignalRs/{AcSignalRDataSource,TrackingItemHelpers}.cs` + `AyCode.Services/docs/SIGNALR_DATASOURCE/` folder; modified: `AyCode.Blazor.Components.csproj` (SignalR.Core 1.2.0 + Services.Server ref removed), `MgGridBase.cs`/`MgGridSignalRDataSource.cs` usings; `FruitBankHybrid.Web.Client.csproj` (5 `.Server` refs removed, AOT on), `FruitBankHybrid.Shared.csproj` (Services.Server ref removed) + 3 Shared usings; `TOPIC_CODES.md` SIGDS path; `SIGNALR_DATASOURCE_TODO.md` (closed). **Doc-link cross-refs (~18) pending** — mechanical path rewrite, follow-up doc-sync. **Rolling-window**: per LLMP-DEC-67 this entry rotates LLMP-DEC-53 → archive on next `docs-archive` run. | +| LLMP-DEC-69 | 2026-07-08 | New repo joined the workspace: **GiaApp** (`GIAAPP`, product, Layer 2) — GPS ↔ worksheet reconciliation app on AyCode.Core + AyCode.Blazor; protocol docs scaffolded; `CONSUMERS.md` maps updated (ACCORE row added, ACBLAZOR file created) | 8th workspace repo (6th primary-rules file). **GiaApp**: Blazor Server (.NET 10) app matching field-service worksheet entries against GPS stops (~90 workers; import → stop-formation → geocoding → matching → approve/deny → justification workflow → month closure). Consumes AyCode.Core (entities/user-stack/`AcDalBase` data layer/logging) + AyCode.Blazor (MgGrid admin UI); does NOT use the SignalR binary transport or `MgGridSignalRDataSource` (server-side data binding); AcBinary/Toon + compression available where useful. **Amended 2026-07-09**: superseded same-day by the hybrid-concept update in the GiaApp analysis doc — app-level SignalR hubs DO use the base `AcBinaryHubProtocol` (`Bytes` mode, typed hub methods); only the tag-based client–server layer (`AcSignalRClientBase` / `AcWebSignalRHubBase` / `AcSignalRDataSource` / `AyCodeBinaryHubProtocol`) stays unused (analysis-doc decisions 13–14). **Prefix**: `GIAAPP` per `REPO_PREFIXES.md` "Picking a prefix" workflow (≥4 chars, no `Ac*`/`Mg*` collision, declared in `@repo` block). **Scaffolding**: `.github/copilot-instructions.md` (canonical Rules #1-6 copy from the FBANKAPP template — the pre-existing raw clone contained FruitBank domain rules + FBANKAPP prefix, fully replaced with GiaApp domain/technical rules from `docs/GPS-Munkalap-egyeztetes_elemzes-adatmodell-terv.md`); `.github/TOPIC_CODES.md` (empty per-repo registry, GIAAPP header); `docs/README.md` (navigation index); `docs/CONVENTIONS.md` (framework pointers + no-class-prefix product rule + XML Documentation section). **Consumer maps**: `AyCode.Core/CONSUMERS.md` — GIAAPP row added (7 consumers); `AyCode.Blazor/CONSUMERS.md` — NEW file (first ACBLAZOR consumer map: FBANKAPP + GIAAPP) per the LLMP-DEC-62 bounded-exception pattern. **Known follow-up**: protocol-audit scope texts say "all 5 repos" / "5 primary + 2 inherit" — with GiaApp it is 6 primary + 2 inherit; count-text refresh is a separate cross-repo pass (META-TODO candidate). | new: `GiaApp/.github/copilot-instructions.md` (rewrite), `GiaApp/.github/TOPIC_CODES.md` (rewrite), `GiaApp/docs/README.md`, `GiaApp/docs/CONVENTIONS.md`, `AyCode.Blazor/CONSUMERS.md`; modified: `AyCode.Core/CONSUMERS.md` (GIAAPP row + count), `GiaApp/docs/GPS-Munkalap-egyeztetes_elemzes-adatmodell-terv.md` (§3.1 "NEM használjuk" row narrowed to SignalR-only per user decision) | ## Known follow-ups diff --git a/.github/LLM_PROTOCOL_DECISIONS_2026_04.md b/.github/LLM_PROTOCOL_DECISIONS_2026_04.md index 5a06efe..e9737b6 100644 --- a/.github/LLM_PROTOCOL_DECISIONS_2026_04.md +++ b/.github/LLM_PROTOCOL_DECISIONS_2026_04.md @@ -70,9 +70,11 @@ Archived entries from `LLM_PROTOCOL_DECISIONS.md` per the **last-15-active reten | 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) | ## 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. +These 54 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) — plus the first two phases of the ID-format migration (LLMP-DEC-53, LLMP-DEC-54). -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. +The active log (`LLM_PROTOCOL_DECISIONS.md`) keeps **last 15 entries** (LLMP-DEC-55 through LLMP-DEC-69 as of 2026-07-09). 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/AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO.md b/AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO.md index 8060f3e..43415f1 100644 --- a/AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO.md +++ b/AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO.md @@ -3,6 +3,9 @@ ## Priority legend - **P0** blocker · **P1** important · **P2** nice-to-have · **P3** idea +> **Archived entries**: see [`SIGNALR_BINARY_PROTOCOL_TODO_2026_05.md`](SIGNALR_BINARY_PROTOCOL_TODO_2026_05.md) (`Status: Closed` entries rotate into year-month buckets as they accumulate). +> Archive files are not auto-loaded — read on demand if relevant context is suspected (regression hint, supersession reference, ID lookup for an archived entry). + --- ## ACCORE-SBP-T-Y2R8: Per-message protocol mode selection @@ -20,15 +23,6 @@ **Non-solution:** Auto-detect size heuristic rejected — wire-format size unknown until serialize (dynamic collections, string interning, ID tracking). -## ACCORE-SBP-T-P8X9: ~~SegmentBufferReader isolated unit tests~~ -**Status:** Closed (2026-05-03) — obsoleted by `ACCORE-SBP-T-G7T2` · **Priority:** ~~P1~~ · **Type:** ~~Test coverage~~ - -~~Original `vast-brewing-moonbeam` refactor plan (chunked receive-path) listed these tests in its verification section; they were never written. Needed: `Write` / `TryAdvanceSegment` / `Complete` basic contract; producer-consumer concurrency (grow-buffer handoff race); missed-signal double-check pattern under `ManualResetEventSlim` reset; `Dispose` lifecycle (buffer pool return, old-buffer cleanup).~~ - -### Resolution (2026-05-03) - -The `SegmentBufferReader` and `SegmentBufferReaderInput` types were deleted by `ACCORE-SBP-T-G7T2` (the Step 6 migration to `AsyncPipeReaderInput`). Test coverage for the equivalent contract on the replacement primitive lives in `AyCode.Core.Tests/Serialization/AcBinarySerializerPipeParallelTests.cs` (added by `ACCORE-BIN-T-D6H4`): `Feed` / `TryAdvanceSegment` / `Complete` / `Dispose` contracts plus framing-state-machine, multi-chunk handoff, sliding-window cycle, and producer-consumer concurrency cases. The original test scope is therefore covered on the replacement type — no separate test file needed. - ## ACCORE-SBP-T-K3J7: Chunked protocol integration test **Priority:** P1 · **Type:** Test coverage @@ -60,117 +54,6 @@ Alternative to wire-detection: use SignalR handshake message's `extensions` JSON ``` Zero first-message overhead, fully explicit. Both sides advertise their send-modes; pick intersection. Specification to be drafted; compatibility with non-AC clients (pure JSON etc.) must remain. -## ACCORE-SBP-T-G7T2: ~~Migrate `AcBinaryHubProtocol.TryParseChunkData` to `AsyncPipeReaderInput`; delete `SegmentBufferReader` + `SegmentBufferReaderInput`~~ (Step 6 of ADR-0003) -**Status:** Closed (2026-05-03) · **Priority:** ~~P1~~ · **Type:** ~~Refactor~~ · **Related ADR:** [`docs/adr/0003-acbinary-streaming-receive-architecture.md`](../../../docs/adr/0003-acbinary-streaming-receive-architecture.md) Step 6 - -~~Switch `AcBinaryHubProtocol.TryParseChunkData` from `SegmentBufferReader.Write(span)` to `AsyncPipeReaderInput.Feed(span)`. Update `AsyncChunkState` field type from `SegmentBufferReader Buffer` to `AsyncPipeReaderInput Input`. Lazy `Task.Run` deser-task start (after first chunk), `CHUNK_END` lifecycle (`Complete()` + `Dispose()` + `_chunkStates.Remove`), and the WASM synchronous-deser path all preserved. Wire format unchanged.~~ - -### Resolution (2026-05-03) - -Migration completed in three coordinated commits: - -1. **`AcBinaryHubProtocol.cs` receive-side migration**: - - `AsyncChunkState.Buffer : SegmentBufferReader` → `AsyncChunkState.Input : AsyncPipeReaderInput` - - `ParseAsyncChunkStart` instantiation: `new AsyncPipeReaderInput(BufferWriterChunkSize × 2, multiMessage: false)` — framing parsed externally by the protocol's own `[201]/[202]` branches in `TryParseChunkData`; raw data flows via `Feed`. - - `state.Buffer.Write(span)` → `state.Input.Feed(span)`, `Complete()` and `Dispose()` calls retained (same names on the new class). - - Background deser-task uses `AcBinaryDeserializer.Deserialize(AsyncPipeReaderInput, Type, opts)` overload (already present at line ~328). - - WASM fallback redesigned to use the streaming overload with `state.Input` directly — after `Complete()`, `TryAdvanceSegment` never enters the `MRES.Wait` path so no `PlatformNotSupportedException` risk. Replaces previous direct byte[]-mutation access (`state.Buffer.Buffer`, `WritePos`) which is not exposed on `AsyncPipeReaderInput`. - - Diagnostic warning log dropped the `WritePos` / `ReadPos` arguments (private on the new class) and substituted `chunkFrameBytesConsumed`. Deeper instrumentation available via `AsyncPipeReaderInput.DiagnosticLog` static hook (`[Conditional("DEBUG")]`). - -2. **`AcBinaryDeserializer.cs` API surface cleanup**: removed the public `Deserialize(SegmentBufferReader, Type, AcBinarySerializerOptions)` overload (was a 2-line forwarder to `DeserializeSequence(new SegmentBufferReaderInput(reader), ...)`). The only caller was the now-migrated `AcBinaryHubProtocol`. - -3. **File deletion**: `AyCode.Core/Serializers/Binaries/SegmentBufferReader.cs` and `AyCode.Core/Serializers/Binaries/SegmentBufferReaderInput.cs` removed from disk. - -**Acceptance criteria met:** -- ✅ All existing SignalR integration tests pass (`AcBinaryHubProtocolConcurrencyTests`: 2/2; AyCode.Core.Tests pipe/signalr/hubprotocol filters: 30/30) — no behavioral regression. -- ✅ Wire format unchanged at the protocol level — `[201]/[202]` framing still owned by SignalR's `TryParseChunkData`; `AsyncPipeReaderInput` with `multiMessage: false` is a passive byte buffer here, not a framing-aware reader. -- ✅ Code-search finds 0 references to `SegmentBufferReader` / `SegmentBufferReaderInput` in `.cs` files (only historical mentions remain in `docs/` — ADR-0003, deprecated TODO entries). -- The pre-cutover send-side migration (write-path uses `AsyncPipeWriterOutput` since the `bool waitForFlush` → `FlushPolicy` enum refactor) plus this receive-side cutover means **the SignalR protocol is now fully on the AsyncPipe primitives** — no parallel chunk-handling code in the protocol layer. - -**Note on ADR-0003 promotion to Accepted:** ADR-0003 status update tracked separately — the original wording referenced unimplemented Steps 4/5 (NamedPipe/FileStream helpers) which were dropped. ADR may need a Resolution-style addendum noting the scope reduction; orthogonal cleanup task. - -## ACCORE-SBP-T-Q3M7: ~~CHUNK_ABORT marker for mid-stream serialize-failure fault isolation~~ -**Status:** Closed (2026-05-23) · **Priority:** ~~P1~~ · **Type:** ~~Feature~~ - -~~Add a `[203]` CHUNK_ABORT marker to the AsyncSegment chunked-framing wire format. When the streamed-arg serialize throws after CHUNK_START has been sent, `WriteMessageChunked` emits the abort marker instead of letting the exception propagate (which would abort the entire SignalR transport connection in `HubConnectionContext.WriteCore`, killing all other in-flight invocations on the same WebSocket). The receiver's `TryParseChunkData` recognises `[203]` as a first-class case, tears down the chunk-state safely (mirroring the `[202]` Complete → DeserTask observe → Dispose ordering), and surfaces the failure to the awaiting caller as a synthesised `CompletionMessage.WithError(invocationId, ...)` — caller's task faults with a specific, actionable error rather than a transport timeout. Fault isolation: blast radius = one message; connection stays alive.~~ - -### Resolution (2026-05-23) - -Shipped in `AcBinaryHubProtocol.cs`: - -- **`MsgAsyncChunkAbort = 203`** constant added next to the `[200]/[201]/[202]` markers. -- **`WriteMessageChunked` (send side)**: `try/catch` around `AcBinarySerializer.Serialize(streamedArg, ...)`. The catch logs Error, then calls `TryEmitChunkAbort(pipeWriter)` (best-effort `GetSpan(1) + Advance + SyncFlush` on `[203]`). On success: returns gracefully; on emit-failure: rethrows so the SignalR outer handler aborts the connection (baseline behaviour preserved). -- **`TryParseChunkData` (receive side)**: new first-class branch on `firstByte == MsgAsyncChunkAbort`. Shared `AbandonChunkState(state, binder, reason)` helper for safe teardown (Complete → observe DeserTask → Dispose → Remove); `GetInvocationId(state.PartialMessage)` extracts the routing key; `CompletionMessage.WithError` synthesised for the caller. Fire-and-forget fallback: `PingMessage.Instance` (preserves the "consumed input ↔ produced message" contract). -- **Protocol-violation path tightened**: the previous "fallback to normal parse" guess-and-recover (for unknown byte in chunk mode) replaced with `LogError` + safe teardown + `System.IO.InvalidDataException`. With CHUNK_ABORT in the protocol, legitimate sender-abort is handled by the `[203]` branch; anything else is genuine framing corruption and must not be masked. - -**Acceptance criteria met:** -- ✅ Sender-side serialize failure no longer aborts the WebSocket — blast radius is the affected `requestId` only. -- ✅ Awaiting caller receives a specific error message rather than a transport timeout. -- ✅ Background deser task safely observed (no unobserved task exception, no Dispose-during-Wait race). -- ✅ Teardown logic deduplicated into the `AbandonChunkState` helper; `GetInvocationId` and `TryEmitChunkAbort` helpers extracted; nested try/catch eliminated. -- 🟡 **Deferred edge case** — mid-header serialize failure leaves a partial `[201][UINT16=N]` on the wire; `[203]` is parsed as chunk-data and the receiver lands on the protocol-violation `InvalidDataException` path. Robust graceful-abort fix tracked in [`../../../AyCode.Core/docs/BINARY/BINARY_ASYNCPIPE_TODO.md#accore-bin-t-z6n2`](../../../AyCode.Core/docs/BINARY/BINARY_ASYNCPIPE_TODO.md#accore-bin-t-z6n2). - -## ACCORE-SBP-T-W7K4: ~~Prefix-tier VarUInt protocol-side parity + `T = object` regression cluster~~ -**Status:** Closed (2026-05-27) · **Priority:** ~~P1~~ · **Type:** ~~Bug fix / Wire format~~ · **Related:** [`../../../AyCode.Core/docs/BINARY/BINARY_TODO.md#accore-bin-t-v3p9`](../../../AyCode.Core/docs/BINARY/BINARY_TODO.md#accore-bin-t-v3p9) - -~~Two coordinated fix waves after the V3P9 wire-format change exposed pre-existing latent bugs in -the SignalR-protocol layer: a standalone `ReadVarUInt` that still decoded under LEB128 grammar -(protocol-layer parity miss), and a cluster of `T = object` generic-inference regressions in -multiple developer-facing `Serialize` call sites that bound `T` to `object` instead of the -runtime concrete type, producing object-typed empty wire payloads.~~ - -### Resolution (2026-05-27) - -**1. Protocol-layer `ReadVarUInt` parity.** `AcBinaryHubProtocol.ReadVarUInt(ref SequenceReader)` -had its own LEB128 implementation that was missed during V3P9. After the serializer-side moved to -prefix-tier, the protocol's standalone `ReadVarUInt` continued decoding under LEB128 grammar, -corrupting argLength / header parsing on the chunked-stream path. Rewrote to match prefix-tier -(1-byte `0xxxxxxx` / 2-byte `10xxxxxx` / 3-byte `110xxxxx` / 4-byte `1110xxxx` / 5-byte `1111xxxx`). -Test count: 96 → 50 failing. - -**2. `T = object` generic-inference regression cluster.** Multiple call sites silently invoked -`Serialize(T value)` where the developer-facing call had `object?` static type, causing T to -bind to `object` instead of the runtime concrete type — wire payloads came out object-typed (empty, -no properties). Fixed via runtime-type capture (`value.GetType()`) and a new non-generic -`SerializeToBinary(object?, Type)` overload for heterogeneous `object?` call sites: - -- `AyCodeBinaryHubProtocol.WriteArgument` (streamed-arg AsyncSegment path, ~line 565) -- `ISignalParams.SetParameterValues` (per-param explicit-null branch) -- `SerializeObjectExtensions.CloneTo` / `CopyTo` (project-wide deep-clone) -- `SignalRSerializationHelper.CreateResponseData` (server response path) -- `AcSignalRClientBase` context-params, `AcWebSignalRHubBase` `isRawBytes` pre-serialize, - `AcSignalRDataSource` fallback re-serialize - -Test count: 50 → 10 failing (within baseline 13-15 flaky-test variance band). - -**3. `SignalRSerializationHelper` byte[]-overload migration.** `SerializeToBinary` overloads -switched from `ArrayBufferWriter` + `WrittenSpan.ToArray()` (2 allocations: writer buffer -+ ToArray copy) to direct `.ToBinary(...)` byte[]-output (1 pool-backed allocation, no copy). -Same wire output, fewer allocations per call. Same migration applied to `SerializeObjectExtensions` -internal use sites. - -**4. `DebugLogArgument [Conditional("DEBUG")]` diagnostics.** Added two `[Conditional("DEBUG")]` -overloads on the write-side (`Type, int, object?`) and read-side (`Type, int, long`) of the -argument framing path. Release-eliminated, debug-enabled — zero production cost, fast diagnostic -when wire-format regressions reappear (the SignalR test regression cluster would have been faster -to localize with these in place). - -### Acceptance criteria met - -- ✅ Full solution build (`AyCode.Core.sln`) — 0 errors. -- ✅ SignalR test suite: 10 failing (vs baseline 13-15) — within flaky-test variance band. -- ✅ Wire format unchanged at the protocol level — V3P9 covers the encoding change; this fix is - protocol-side parity catch-up + non-encoding-related generic-inference bugs. -- ✅ Allocation profile improvement on `SignalRSerializationHelper.SerializeToBinary` paths - (server response + heterogeneous `object?` call sites). - -### Note on regression-discovery flow - -The `T = object` regression cluster was latent (pre-V3P9), but only surfaced after V3P9 broke the -SignalR test baseline — the failing tests' close investigation exposed the entire generic-inference -gap. Future encoding-format breaks should pair with a focused `(value.GetType())` audit across the -project's `Serialize` / `ToBinary` call sites to catch this earlier. - --- # 🟡 NuGet competitiveness ideas — NOT current priority diff --git a/AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO_2026_05.md b/AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO_2026_05.md new file mode 100644 index 0000000..b4adfd0 --- /dev/null +++ b/AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO_2026_05.md @@ -0,0 +1,127 @@ +# Binary Hub Protocol (wire) — TODO Archive: 2026-05 + +Archived entries from `SIGNALR_BINARY_PROTOCOL_TODO.md` per the Status-based rotation rule (`docs-archive` Rule A — only `Status: Closed` entries). IDs preserved (never reassigned). Format identical to the active file. Year-month bucket = **2026-05** (Resolution dates 2026-05-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., an active entry or code comment references an ID below). Cross-references from active entries to these IDs remain functional — open this file when following a link. + +--- + +## ACCORE-SBP-T-P8X9: ~~SegmentBufferReader isolated unit tests~~ +**Status:** Closed (2026-05-03) — obsoleted by `ACCORE-SBP-T-G7T2` · **Priority:** ~~P1~~ · **Type:** ~~Test coverage~~ + +~~Original `vast-brewing-moonbeam` refactor plan (chunked receive-path) listed these tests in its verification section; they were never written. Needed: `Write` / `TryAdvanceSegment` / `Complete` basic contract; producer-consumer concurrency (grow-buffer handoff race); missed-signal double-check pattern under `ManualResetEventSlim` reset; `Dispose` lifecycle (buffer pool return, old-buffer cleanup).~~ + +### Resolution (2026-05-03) + +The `SegmentBufferReader` and `SegmentBufferReaderInput` types were deleted by `ACCORE-SBP-T-G7T2` (the Step 6 migration to `AsyncPipeReaderInput`). Test coverage for the equivalent contract on the replacement primitive lives in `AyCode.Core.Tests/Serialization/AcBinarySerializerPipeParallelTests.cs` (added by `ACCORE-BIN-T-D6H4`): `Feed` / `TryAdvanceSegment` / `Complete` / `Dispose` contracts plus framing-state-machine, multi-chunk handoff, sliding-window cycle, and producer-consumer concurrency cases. The original test scope is therefore covered on the replacement type — no separate test file needed. + +## ACCORE-SBP-T-G7T2: ~~Migrate `AcBinaryHubProtocol.TryParseChunkData` to `AsyncPipeReaderInput`; delete `SegmentBufferReader` + `SegmentBufferReaderInput`~~ (Step 6 of ADR-0003) +**Status:** Closed (2026-05-03) · **Priority:** ~~P1~~ · **Type:** ~~Refactor~~ · **Related ADR:** [`docs/adr/0003-acbinary-streaming-receive-architecture.md`](../../../docs/adr/0003-acbinary-streaming-receive-architecture.md) Step 6 + +~~Switch `AcBinaryHubProtocol.TryParseChunkData` from `SegmentBufferReader.Write(span)` to `AsyncPipeReaderInput.Feed(span)`. Update `AsyncChunkState` field type from `SegmentBufferReader Buffer` to `AsyncPipeReaderInput Input`. Lazy `Task.Run` deser-task start (after first chunk), `CHUNK_END` lifecycle (`Complete()` + `Dispose()` + `_chunkStates.Remove`), and the WASM synchronous-deser path all preserved. Wire format unchanged.~~ + +### Resolution (2026-05-03) + +Migration completed in three coordinated commits: + +1. **`AcBinaryHubProtocol.cs` receive-side migration**: + - `AsyncChunkState.Buffer : SegmentBufferReader` → `AsyncChunkState.Input : AsyncPipeReaderInput` + - `ParseAsyncChunkStart` instantiation: `new AsyncPipeReaderInput(BufferWriterChunkSize × 2, multiMessage: false)` — framing parsed externally by the protocol's own `[201]/[202]` branches in `TryParseChunkData`; raw data flows via `Feed`. + - `state.Buffer.Write(span)` → `state.Input.Feed(span)`, `Complete()` and `Dispose()` calls retained (same names on the new class). + - Background deser-task uses `AcBinaryDeserializer.Deserialize(AsyncPipeReaderInput, Type, opts)` overload (already present at line ~328). + - WASM fallback redesigned to use the streaming overload with `state.Input` directly — after `Complete()`, `TryAdvanceSegment` never enters the `MRES.Wait` path so no `PlatformNotSupportedException` risk. Replaces previous direct byte[]-mutation access (`state.Buffer.Buffer`, `WritePos`) which is not exposed on `AsyncPipeReaderInput`. + - Diagnostic warning log dropped the `WritePos` / `ReadPos` arguments (private on the new class) and substituted `chunkFrameBytesConsumed`. Deeper instrumentation available via `AsyncPipeReaderInput.DiagnosticLog` static hook (`[Conditional("DEBUG")]`). + +2. **`AcBinaryDeserializer.cs` API surface cleanup**: removed the public `Deserialize(SegmentBufferReader, Type, AcBinarySerializerOptions)` overload (was a 2-line forwarder to `DeserializeSequence(new SegmentBufferReaderInput(reader), ...)`). The only caller was the now-migrated `AcBinaryHubProtocol`. + +3. **File deletion**: `AyCode.Core/Serializers/Binaries/SegmentBufferReader.cs` and `AyCode.Core/Serializers/Binaries/SegmentBufferReaderInput.cs` removed from disk. + +**Acceptance criteria met:** +- ✅ All existing SignalR integration tests pass (`AcBinaryHubProtocolConcurrencyTests`: 2/2; AyCode.Core.Tests pipe/signalr/hubprotocol filters: 30/30) — no behavioral regression. +- ✅ Wire format unchanged at the protocol level — `[201]/[202]` framing still owned by SignalR's `TryParseChunkData`; `AsyncPipeReaderInput` with `multiMessage: false` is a passive byte buffer here, not a framing-aware reader. +- ✅ Code-search finds 0 references to `SegmentBufferReader` / `SegmentBufferReaderInput` in `.cs` files (only historical mentions remain in `docs/` — ADR-0003, deprecated TODO entries). +- The pre-cutover send-side migration (write-path uses `AsyncPipeWriterOutput` since the `bool waitForFlush` → `FlushPolicy` enum refactor) plus this receive-side cutover means **the SignalR protocol is now fully on the AsyncPipe primitives** — no parallel chunk-handling code in the protocol layer. + +**Note on ADR-0003 promotion to Accepted:** ADR-0003 status update tracked separately — the original wording referenced unimplemented Steps 4/5 (NamedPipe/FileStream helpers) which were dropped. ADR may need a Resolution-style addendum noting the scope reduction; orthogonal cleanup task. + +## ACCORE-SBP-T-Q3M7: ~~CHUNK_ABORT marker for mid-stream serialize-failure fault isolation~~ +**Status:** Closed (2026-05-23) · **Priority:** ~~P1~~ · **Type:** ~~Feature~~ + +~~Add a `[203]` CHUNK_ABORT marker to the AsyncSegment chunked-framing wire format. When the streamed-arg serialize throws after CHUNK_START has been sent, `WriteMessageChunked` emits the abort marker instead of letting the exception propagate (which would abort the entire SignalR transport connection in `HubConnectionContext.WriteCore`, killing all other in-flight invocations on the same WebSocket). The receiver's `TryParseChunkData` recognises `[203]` as a first-class case, tears down the chunk-state safely (mirroring the `[202]` Complete → DeserTask observe → Dispose ordering), and surfaces the failure to the awaiting caller as a synthesised `CompletionMessage.WithError(invocationId, ...)` — caller's task faults with a specific, actionable error rather than a transport timeout. Fault isolation: blast radius = one message; connection stays alive.~~ + +### Resolution (2026-05-23) + +Shipped in `AcBinaryHubProtocol.cs`: + +- **`MsgAsyncChunkAbort = 203`** constant added next to the `[200]/[201]/[202]` markers. +- **`WriteMessageChunked` (send side)**: `try/catch` around `AcBinarySerializer.Serialize(streamedArg, ...)`. The catch logs Error, then calls `TryEmitChunkAbort(pipeWriter)` (best-effort `GetSpan(1) + Advance + SyncFlush` on `[203]`). On success: returns gracefully; on emit-failure: rethrows so the SignalR outer handler aborts the connection (baseline behaviour preserved). +- **`TryParseChunkData` (receive side)**: new first-class branch on `firstByte == MsgAsyncChunkAbort`. Shared `AbandonChunkState(state, binder, reason)` helper for safe teardown (Complete → observe DeserTask → Dispose → Remove); `GetInvocationId(state.PartialMessage)` extracts the routing key; `CompletionMessage.WithError` synthesised for the caller. Fire-and-forget fallback: `PingMessage.Instance` (preserves the "consumed input ↔ produced message" contract). +- **Protocol-violation path tightened**: the previous "fallback to normal parse" guess-and-recover (for unknown byte in chunk mode) replaced with `LogError` + safe teardown + `System.IO.InvalidDataException`. With CHUNK_ABORT in the protocol, legitimate sender-abort is handled by the `[203]` branch; anything else is genuine framing corruption and must not be masked. + +**Acceptance criteria met:** +- ✅ Sender-side serialize failure no longer aborts the WebSocket — blast radius is the affected `requestId` only. +- ✅ Awaiting caller receives a specific error message rather than a transport timeout. +- ✅ Background deser task safely observed (no unobserved task exception, no Dispose-during-Wait race). +- ✅ Teardown logic deduplicated into the `AbandonChunkState` helper; `GetInvocationId` and `TryEmitChunkAbort` helpers extracted; nested try/catch eliminated. +- 🟡 **Deferred edge case** — mid-header serialize failure leaves a partial `[201][UINT16=N]` on the wire; `[203]` is parsed as chunk-data and the receiver lands on the protocol-violation `InvalidDataException` path. Robust graceful-abort fix tracked in [`../../../AyCode.Core/docs/BINARY/BINARY_ASYNCPIPE_TODO.md#accore-bin-t-z6n2`](../../../AyCode.Core/docs/BINARY/BINARY_ASYNCPIPE_TODO.md#accore-bin-t-z6n2). + +## ACCORE-SBP-T-W7K4: ~~Prefix-tier VarUInt protocol-side parity + `T = object` regression cluster~~ +**Status:** Closed (2026-05-27) · **Priority:** ~~P1~~ · **Type:** ~~Bug fix / Wire format~~ · **Related:** [`../../../AyCode.Core/docs/BINARY/BINARY_TODO.md#accore-bin-t-v3p9`](../../../AyCode.Core/docs/BINARY/BINARY_TODO.md#accore-bin-t-v3p9) + +~~Two coordinated fix waves after the V3P9 wire-format change exposed pre-existing latent bugs in +the SignalR-protocol layer: a standalone `ReadVarUInt` that still decoded under LEB128 grammar +(protocol-layer parity miss), and a cluster of `T = object` generic-inference regressions in +multiple developer-facing `Serialize` call sites that bound `T` to `object` instead of the +runtime concrete type, producing object-typed empty wire payloads.~~ + +### Resolution (2026-05-27) + +**1. Protocol-layer `ReadVarUInt` parity.** `AcBinaryHubProtocol.ReadVarUInt(ref SequenceReader)` +had its own LEB128 implementation that was missed during V3P9. After the serializer-side moved to +prefix-tier, the protocol's standalone `ReadVarUInt` continued decoding under LEB128 grammar, +corrupting argLength / header parsing on the chunked-stream path. Rewrote to match prefix-tier +(1-byte `0xxxxxxx` / 2-byte `10xxxxxx` / 3-byte `110xxxxx` / 4-byte `1110xxxx` / 5-byte `1111xxxx`). +Test count: 96 → 50 failing. + +**2. `T = object` generic-inference regression cluster.** Multiple call sites silently invoked +`Serialize(T value)` where the developer-facing call had `object?` static type, causing T to +bind to `object` instead of the runtime concrete type — wire payloads came out object-typed (empty, +no properties). Fixed via runtime-type capture (`value.GetType()`) and a new non-generic +`SerializeToBinary(object?, Type)` overload for heterogeneous `object?` call sites: + +- `AyCodeBinaryHubProtocol.WriteArgument` (streamed-arg AsyncSegment path, ~line 565) +- `ISignalParams.SetParameterValues` (per-param explicit-null branch) +- `SerializeObjectExtensions.CloneTo` / `CopyTo` (project-wide deep-clone) +- `SignalRSerializationHelper.CreateResponseData` (server response path) +- `AcSignalRClientBase` context-params, `AcWebSignalRHubBase` `isRawBytes` pre-serialize, + `AcSignalRDataSource` fallback re-serialize + +Test count: 50 → 10 failing (within baseline 13-15 flaky-test variance band). + +**3. `SignalRSerializationHelper` byte[]-overload migration.** `SerializeToBinary` overloads +switched from `ArrayBufferWriter` + `WrittenSpan.ToArray()` (2 allocations: writer buffer ++ ToArray copy) to direct `.ToBinary(...)` byte[]-output (1 pool-backed allocation, no copy). +Same wire output, fewer allocations per call. Same migration applied to `SerializeObjectExtensions` +internal use sites. + +**4. `DebugLogArgument [Conditional("DEBUG")]` diagnostics.** Added two `[Conditional("DEBUG")]` +overloads on the write-side (`Type, int, object?`) and read-side (`Type, int, long`) of the +argument framing path. Release-eliminated, debug-enabled — zero production cost, fast diagnostic +when wire-format regressions reappear (the SignalR test regression cluster would have been faster +to localize with these in place). + +### Acceptance criteria met + +- ✅ Full solution build (`AyCode.Core.sln`) — 0 errors. +- ✅ SignalR test suite: 10 failing (vs baseline 13-15) — within flaky-test variance band. +- ✅ Wire format unchanged at the protocol level — V3P9 covers the encoding change; this fix is + protocol-side parity catch-up + non-encoding-related generic-inference bugs. +- ✅ Allocation profile improvement on `SignalRSerializationHelper.SerializeToBinary` paths + (server response + heterogeneous `object?` call sites). + +### Note on regression-discovery flow + +The `T = object` regression cluster was latent (pre-V3P9), but only surfaced after V3P9 broke the +SignalR test baseline — the failing tests' close investigation exposed the entire generic-inference +gap. Future encoding-format breaks should pair with a focused `(value.GetType())` audit across the +project's `Serialize` / `ToBinary` call sites to catch this earlier. diff --git a/CONSUMERS.md b/CONSUMERS.md index 7f126da..36cbb12 100644 --- a/CONSUMERS.md +++ b/CONSUMERS.md @@ -4,7 +4,7 @@ > > **Strict rule**: AyCode.Core code, types, namespaces, topic IDs, and any other `.md` files (`docs/`, `.github/` excluding the narrow workspace-meta-history exception) MUST NOT name any specific consumer listed here. **This is the SINGLE place** in ACCORE that may name consumer repos. -## Workspace consumer map (as of 2026-04-26) +## Workspace consumer map (as of 2026-07-08) | Prefix | Repo | Layer | Type | Path (workspace-relative) | Brief usage | |----------------|-------------------------------|------:|---------------------|--------------------------------------------------------------------|------------------------------------------------------------------------------| @@ -14,13 +14,14 @@ | `MGFBANKPLUG` | Nop.Plugin.Misc.AIPlugin | 3 | consumer (plugin) | `.../Plugins/Nop.Plugin.Misc.AIPlugin` | FruitBank nopCommerce plugin source | | `FBANKNOP` | FruitBank | 2 | product (server) | `Mango/Source/FruitBank` | nopCommerce server source for the FruitBank deployment | | `FBANKAPP` | FruitBankHybridApp | 2 | product (hybrid) | `Mango/Source/FruitBankHybridApp` | MAUI/Blazor hybrid client app | +| `GIAAPP` | GiaApp | 2 | product (web) | `Mango/Source/GiaApp` | Blazor Server GPS ↔ worksheet reconciliation app (entities/user-stack/data-layer; app-level SignalR hubs on base `AcBinaryHubProtocol`, tag-based layer unused) | (See `.github/REPO_PREFIXES.md` for the prefix scheme; each consumer's own `.github/copilot-instructions.md` `@repo` block declares its `prefix` value per LLMP-DEC-58.) ## When modifying AyCode.Core — change-impact lens Use this list to assess change impact: -- A breaking change to a base class affects all 6 consumers above (cascading rebuilds + verification). +- A breaking change to a base class affects all 7 consumers above (cascading rebuilds + verification). - A new feature gated behind opt-in DI extension → no cascade, just new capability. - A signature change in a widely-used interface (e.g., `IAcSignalRClientBase`) → at minimum: ACBLAZOR + MGNOPLIB + MGFBANKPLUG + FBANKNOP + FBANKAPP all need verification. - A change to ID format / topic-code conventions → MGNOPCORE and MGFBANKPLUG (inherit-protocol) plus all primary repos need updating.