Sub of epic #17018 — delivers AC-C (D#17015 r6 authoritative text). Sibling of #17019 (authority), #17021 (routing), #17022 (composition proof); the migration-scale contract is the separate leaf AC-E sub (one PR each — the authority/barrier primitive and the resumable rebuild runner are separable deliverables).
Live latest-open sweep: checked latest open issues at 2026-08-12T12:15Z; no equivalent found (#17021/#17022 are routing/composition, not generation election). A2A claim sweep: AC-C claimed by me in the #17018 kickoff and Emmy's epic-review gate names it as an unowned leaf awaiting exactly this filing.
Context
Any change to a load-bearing embedding-generation coordinate (provider/engine, immutable model digest, quantization, output dimension, pooling/normalization + distance semantics, preprocessing/chunk-strategy version — the OQ2 tuple) invalidates every existing vector. The epic's lane switch changes the embedding engine, so the cutover REQUIRES a new corpus generation — and today no global election authority exists: VectorService.embedViaShadowSwap() performs sequential live→parking / shadow→canonical renames with rollback handling for ONE KB collection (VectorService.mjs#L1037-L1068 at dev@173129edd394), while MC owns its own embedding collections (memories, session summaries, temporal summaries, graph collections) with separate shadow/recovery machinery. Per-collection swaps without one authority can disagree — a reader could see the new generation in KB and the old one in MC memories, which is precisely the mixed-generation state OQ2 forbids.
The Problem
Emmy's STEP_BACK correction (D#17015 DC_kwDODSospM4BEnrR) and r5 recheck falsified the "extend the KB-only primitive + no second pointer" framing as self-contradictory for a plane-wide election. The converged contract (r6 AC-C): per-collection work may proceed independently, but GENERATION VISIBILITY must commit through one durable authority — partial promotion never advertises the new generation.
The Architectural Reality
- KB:
ai/services/knowledge-base/VectorService.mjs — shadow build, embedViaShadowSwap(), parking/rollback collections.
- MC:
ai/services/memory-core/ embedding collections + their shadow/recovery equivalents (target-set recovery; the WAL drain writes embeddings per collection).
- Health surfaces (KB/MC healthcheck + deployment-state snapshot) must report the ELECTED and PARKED generations — acceptance reads them.
- ADR-0019 governs any config leaf this adds (the generation identity/pointer is deployment-state, not env-derived config).
The Fix
Introduce the coordinated vector-plane generation contract:
- A generation identity = the full OQ2 coordinate tuple, durably recorded.
- Per-collection candidate build + validation (reusing the existing shadow primitives per store) — validation receipts per collection BEFORE any promotion.
- One durable election authority (implementation open — deployment-state record, not a per-collection flag) that commits the generation via a stale-writer-fenced commit barrier or an explicitly quiesced bounded transition. No per-collection authorities that can disagree.
- Partial promotion never advertises: until the barrier commits, every reader resolves the prior generation.
- Full-set prior generation retained as rollback authority through the acceptance window; lifecycle
candidate → current → rollback-retained → retired with retention/GC after acceptance.
- Health/acceptance surfaces report elected + parked generations.
Acceptance Criteria
Out of Scope
- The resumable/budgeted rebuild runner + canonical-scale proof (the AC-E sibling leaf).
- The engine/lane switch itself (#17021/#17022) and the external cutover letter (AC-D stage 5).
Decision Record impact
aligned-with ADR-0014 (as amended by #17019/PR #17020); depends-on the D#17015 graduation (Decision Record from Discussion: Required — delivered by #17019).
Related
Epic #17018 · D#17015 r6 (AC-C) · #17019 · #17021 · #17022 · #16706 (incident evidence)
Origin Session ID: 8637b4b9-b852-45d9-b057-de34184aae8b
Retrieval Hint: "coordinated vector-plane generation election commit barrier shadow swap"
Contract Ledger
| Producer |
Consumer |
Contract |
Failure semantics |
createVectorGenerationIdentity |
election record, rebuild runner, poison store (join key) |
complete seven-coordinate tuple; digest-bearing model; placeholders refused; any change = new generation |
invalid/placeholder/mutable-tag coordinates throw; a tampered stored identity fails derived-hash validation and the record reads unprovable |
| election record (plane-singleton on ONE shared mount) |
both promote seams, rebuild runner, health surfaces |
promote admissible only when the writer view is the elected generation at the current epoch; transition renames additionally refuse outside the declared quiesce window |
stale writer, wrong generation, split/absent mount, or an expired window refuses before any rename; corrupt record refuses promotes while readers stay unaffected |
per-collection validation receipts (five-key census incl. mc.graph) |
commitVectorGenerationElection |
all census collections validated AND a quiesce window {scope, startedAt, boundMs} declared before any authority flip |
a missing receipt or missing/invalid window refuses the commit |
| promote/un-park completion marks |
acceptVectorGenerationElection / next declareCandidateVectorGeneration |
full-set semantics before authority transfer; rollback carries its own declared window |
a partial promotion cannot be accepted; a partial un-park refuses the next candidate |
projectVectorGenerationHealth |
KB/MC healthcheck payloads, cutover acceptance |
elected + parked identities, the active window, per-collection state |
missing/unavailable reported as status, never a throw |
Sub of epic #17018 — delivers AC-C (D#17015 r6 authoritative text). Sibling of #17019 (authority), #17021 (routing), #17022 (composition proof); the migration-scale contract is the separate leaf AC-E sub (one PR each — the authority/barrier primitive and the resumable rebuild runner are separable deliverables).
Live latest-open sweep: checked latest open issues at 2026-08-12T12:15Z; no equivalent found (#17021/#17022 are routing/composition, not generation election). A2A claim sweep: AC-C claimed by me in the #17018 kickoff and Emmy's epic-review gate names it as an unowned leaf awaiting exactly this filing.
Context
Any change to a load-bearing embedding-generation coordinate (provider/engine, immutable model digest, quantization, output dimension, pooling/normalization + distance semantics, preprocessing/chunk-strategy version — the OQ2 tuple) invalidates every existing vector. The epic's lane switch changes the embedding engine, so the cutover REQUIRES a new corpus generation — and today no global election authority exists:
VectorService.embedViaShadowSwap()performs sequential live→parking / shadow→canonical renames with rollback handling for ONE KB collection (VectorService.mjs#L1037-L1068atdev@173129edd394), while MC owns its own embedding collections (memories, session summaries, temporal summaries, graph collections) with separate shadow/recovery machinery. Per-collection swaps without one authority can disagree — a reader could see the new generation in KB and the old one in MC memories, which is precisely the mixed-generation state OQ2 forbids.The Problem
Emmy's STEP_BACK correction (D#17015
DC_kwDODSospM4BEnrR) and r5 recheck falsified the "extend the KB-only primitive + no second pointer" framing as self-contradictory for a plane-wide election. The converged contract (r6 AC-C): per-collection work may proceed independently, but GENERATION VISIBILITY must commit through one durable authority — partial promotion never advertises the new generation.The Architectural Reality
ai/services/knowledge-base/VectorService.mjs— shadow build,embedViaShadowSwap(), parking/rollback collections.ai/services/memory-core/embedding collections + their shadow/recovery equivalents (target-set recovery; the WAL drain writes embeddings per collection).The Fix
Introduce the coordinated vector-plane generation contract:
candidate → current → rollback-retained → retiredwith retention/GC after acceptance.Acceptance Criteria
Out of Scope
Decision Record impact
aligned-with ADR-0014 (as amended by #17019/PR #17020); depends-on the D#17015 graduation (Decision Record from Discussion: Required — delivered by #17019).
Related
Epic #17018 · D#17015 r6 (AC-C) · #17019 · #17021 · #17022 · #16706 (incident evidence)
Origin Session ID: 8637b4b9-b852-45d9-b057-de34184aae8b Retrieval Hint: "coordinated vector-plane generation election commit barrier shadow swap"
Contract Ledger
createVectorGenerationIdentitymc.graph)commitVectorGenerationElection{scope, startedAt, boundMs}declared before any authority flipacceptVectorGenerationElection/ nextdeclareCandidateVectorGenerationprojectVectorGenerationHealthmissing/unavailablereported as status, never a throw