Implementation Spec · PLAN Phase · Visual Review
Wire the existing eval-only createEmitExpandSession + EvictionAsPut into the live api-bridge path so real usage fills the canonical W5b store — gated default-OFF, byte-identical-off. The #1 lever: filling the store makes recall measurable and re-fires the parked TDA.
The canonical store is empty because the eviction-capable session and EvictionAsPut exist but are eval-only — no live consumer imports them. Recall can't be measured because nothing fills the store.
EvictionAsPut + createEmitExpandSession sit in tests only.putTx commit → content keyed by sha256 = W5b address.Every unit stacks at the single seam SubstrateAdapter.put(raw) → {contentHash}. No unit reaches into another — a clean decorator chain across three owners.
LIVE api-bridge model turn (flag ON)
│
▼
createEmitExpandSession({ fetcher, eviction }) ← Layer 1 · gated mount (session.ts:30)
│ window overflow → eviction.onWindowOverflow (session.ts:140)
▼
EvictionAsPut({ substrate: gated, carryPolicy }) ← Layer 2 · my construction (eviction-as-put.ts:93)
│ cleanly-evictable span → putTx commit → sha256 wick = W5b address
▼
gated = wrapAdmission( adaptStoreToSubstrate(realStore), revive-build P1/P2, claude-revive ledger )
│ string-P1 (surrogate/secret/PII) │ byte-P2 (dedup/provenance) │ content-free terminal
▼
realStore.put(raw) → { contentHash } ← the canonical W5b store recall reads
adaptStoreToSubstrate (commit-only boundary) · flag-gated mount · PIN-B code-point boundary snap · bounded-retry ≤1 · construct EvictionAsPut + carryPolicy.
revive-build's wrapAdmission (store-agnostic P1/P2) + claude-revive's ledger (content-free terminals) + carryPolicy — stack without touching EvictionAsPut or the transport.
Store-fill is purely additive: it never owns window liveness (the session does), only STORE-or-NOT. Disposition branches on the admission's abstain reason — and store-availability is an orthogonal axis, not a fourth content category.
Clean content sliced at a bad code-unit boundary. PIN-B re-slices once on a code-point boundary → stores. PIN A stays-live applies HERE ONLY. ≤1 retry; still-broken ⇒ #3.
NOT pinned live. Session drains normally; store-fill declines to persist + records a content-free redaction terminal. Deliberate ledgered non-store ≠ data loss.
Yields to the session's own non-storing eviction; never force-store-at-broken-key, never a new blocking error. Ledgered dropped-unstorable, bounded + visible.
A durable-commit failure can strike valid content — a separate axis with its own terminal dropped-store-unavailable. Kept distinct so telemetry says "fix the store" vs "content unrepresentable".
The deepest finding (Codex + Gemini): the wick / recall-address is an effect of a successful durable put, never a promise of a future one. It is contentHash-identity applied to time, and it closes the mirror of the original surrogate hole.
The address's hash-domain must equal the store's key-domain: sha256(UTF-8(string)) on both sides. (store-without-recallable-address = orphan content)
Content is durably stored BEFORE its address is recall-visible. (emit-address-without-durable-store = dangling address, recall-resolves-missing)
consolidate already does put(:151) → hash-check(:156) → carry-pointer(:164), with an alignment guard that throws (never corrupts) on concurrent index-shift.Gemini R2 proved onWindowOverflow is synchronous (must free tokens now) — so fire-and-forget is impossible. Overwatch traced the disk: the durable commit putTx (store.ts:347) is synchronous and completes before store.put's only await (the best-effort vectorize tail, :408). Gate on the sync commit; detach the tail.
.catch swallow+log — no unhandledRejection crash). Slow/failing tail is irrelevant.dropped-store-unavailable. Caught; no new live-path error.eviction-stale-window.putTx is a synchronous single-thread call; a JS timeout can't preempt it. The live-path eviction uses its OWN short busy_timeout (tens of ms, distinct from the 5000ms batch default) → writer contention fails fast → fallback, never a multi-second serving stall. Degradation is metered (dropped-store-unavailable rate) so operators see it before users do.Conflating failure domains blinds audit. Three distinct, content-free terminals keep store-health, concurrency bugs, and content limits separable — plus an independent-domain drop signal so a store-substrate failure never silently swallows its own record.
| Terminal | Domain | Trigger | Disposition |
|---|---|---|---|
dropped-unstorable | content-intrinsic | intrinsic-broken / all-abstain | session non-storing eviction |
dropped-store-unavailable | store health | putTx throws | drop through valid coords + in-process counter + stderr signal |
eviction-stale-window | concurrency | alignment-guard throw | bounded re-derive → session fallback (tokens freed this turn) |
abstained-secret | policy | secret/PII on span text | deliberate non-persist, content-free redaction terminal |
The panel (Grok mandatory + Codex + Gemini + steelman) recorded each reviewer's actual verdict and refused to transition on any request_changes. No rubber-stamps — each round hardened a real defect before a line of code was written.
| Pin | Owner | Note |
|---|---|---|
| api-bridge injection point | coord-build-recall-b + claude-revive | the exact request-handler mount line — joint disk-trace (greenfield; no live consumer today) |
| commit-only store surface | claude-revive (store owner) | thin method / signal exposing the sync putTx result with vectorize detached |
| terminal enum | claude-revive (B3_PROVENANCE_WIRE_v1) | 3 failure-domain terminals + abstained-secret vs an abstainReason field |
| store durability = FULL | claude-revive · ruled + implemented | wick-coord ruling faaabd67 — pragma + power-fail test + SLA (already measured) |
| short busy_timeout value + span cap | coord-build-recall-b | the exact tens-of-ms number + a span-size cap for the bounded-compute case |