From 07c94433f34f4a8811884344e2628f4b813d7793 Mon Sep 17 00:00:00 2001 From: claude Date: Fri, 17 Jul 2026 14:35:54 +0200 Subject: [PATCH] =?UTF-8?q?audit:=20cycle-close=20tidy=20for=20#191=20?= =?UTF-8?q?=E2=80=94=20C18=20realization=20note=20for=20the=20identity=20i?= =?UTF-8?q?ndex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cycle #191 (identity-ref index) closes drift-resolved. Architect review held: results stay scan-identical via verify-on-hit (the same-identity- twin choice was order-unspecified before and stays unspecified in kind); zero caller/write-path/engine changes; the #276 append-lock discipline correctly extended to the fourth JSONL path. No regression scripts are configured; the architect review is the gate. Drift items and resolution: - C18 lacked a realization note for the new persistent sidecar store and its index-first/verify-on-hit/repair-walk mechanism, and the "identity refs by store scan" line was stale -> this commit adds the #191 realization note and dates the scan wording (fix, ledger-only). - The repair pass grew the sidecar without bound while same-identity twins coexisted (per-entry comparison against a mid-walk-stale snapshot) -> fixed in-cycle via RED pin 35865bb + collect-then-diff- append fix aa94f51; suite 1347/0, clippy clean. Cycle spec and plan (git-ignored working files) removed per lifecycle. refs #191 --- docs/design/INDEX.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/design/INDEX.md b/docs/design/INDEX.md index b543f81..cf4ba37 100644 --- a/docs/design/INDEX.md +++ b/docs/design/INDEX.md @@ -1541,7 +1541,7 @@ canonical JSON (`format_version` envelope, omit-defaults, no trailing newline) k move). Unlike `put_blueprint` (caller owns the hash), the document puts self-key from canonical bytes; gets are `Ok(None)` treat-as-empty. The **referential tier** (`validate_campaign_refs`) resolves process/strategy refs against the stores (identity refs -by store scan) and checks each campaign axis — name AND declared `ScalarKind`, the axis +by store scan in this cycle; index-first since #191, below) and checks each campaign axis — name AND declared `ScalarKind`, the axis carries its kind once — against the referenced blueprint's `param_space`. Campaign P1 control constructs (axes/gates/ladders per #188) carried intent only in this cycle: no executor existed yet — executor need was re-tested against the intent-persistence @@ -1658,7 +1658,29 @@ not merely true in the record. The guard's mutex serialises only the ref-count/hook-swap (O(1)), never the member computation, so C1 disjoint-parallel execution and determinism are preserved; ref-counting (save on 0→1, restore on 1→0) keeps concurrent sweep/walk-forward threads and any caller-installed hook -correct. **Guarantee.** Construction is a distinct phase, recursive at every level. Each +correct. +**Realization (#191, 2026-07-17 — identity-ref resolution is index-first).** +`find_blueprint_by_identity` no longer re-loads the whole blueprint store per +reference: a fourth persistent JSONL sidecar, `blueprint_identity_index.jsonl` +(identity id → content id; fixed-name sibling of the runs store, appends under +the #276 lock), is consulted first, and every hit is **verified** by loading +that one blueprint under the current resolver and recomputing its identity id — +the index is a cache, never an oracle, so resolution results stay +scan-identical under roster drift, store surgery, or index corruption (the one +unspecified corner is unchanged in kind: which same-identity twin answers was +`read_dir`-order-dependent before and is index-history-dependent now). Any miss +or failed verification runs the old scan as a **full-store repair pass**, +collect-then-diff-append: the walk's last-wins mapping is diffed against the +pre-walk snapshot after the walk, so a converged index — twin stores included — +appends nothing (the twin-convergence pin). Index reads never fail a lookup +(missing/unreadable file → empty, unparseable lines skipped), repair appends +are best-effort, and a pre-index store backfills itself on its first miss, no +migration; a read-only store keeps scanning as before. Write paths, the engine, +and both callers are untouched; maintenance is lazy-only — put-time indexing +was rejected because it would need a roster-free doc-level identity function +whose equivalence to the loaded-composite path no green test ratifies (decision +log: #191 comments). +**Guarantee.** Construction is a distinct phase, recursive at every level. Each node type has a **factory** `params → sized concrete node` (e.g. `SMA(length)` sizes its ring buffer). A **blueprint** is the param-generic, input-role-generic graph-as-data produced by running a Rust builder (C9); it carries *free* numeric