Context
Delivers AC4 of #13496 ("a safe repair/rebuild path is selected and validated on a copy or shadow collection before live mutation"). MC defrag previously failed closed (assertDefragTargetSupported throws DEFRAG_MEMORY_CORE_UNSAFE) because the KB extract path (collection.get({include:['embeddings']})) throws "Error finding id" for the missing-vector rows the stored-embedding export bug leaves behind. Shipped on branch agent/13496-ac2-defrag-wiring (PR #13635).
Live latest-open sweep: checked the latest 20 open issues at 2026-06-20; no equivalent repair-path leaf found.
Release classification: boardless — Agent OS / Memory Core stability, not v13-release-blocking.
The Problem
MC cannot delete/recreate-defrag (it is an irreplaceable store) and cannot use the KB extract (it throws for missing-vector rows). It needs a repair that recovers the missing vectors and promotes the result safely, without ever silently dropping data.
The Architectural Reality
ai/scripts/maintenance/defragChromaDB.mjs — the defrag orchestrator (the fail-closed gate + the shadow-promotion + the durable state-marker lifecycle).
ai/scripts/maintenance/checkChromaIntegrity.mjs — auditChromaVectorCoverage + enumerateMetadataVectorDrift (the full, uncapped metadata-id vs vector-index-id enumeration via includeFullIds).
ai/scripts/maintenance/repairMemoryCoreStoredEmbeddings.mjs — extractMemoryCoreCollectionData (extract intact rows with stored vectors + re-embed the missing-vector rows from their documents).
rewriteCollectionViaShadowPromotion — the existing shadow/parking promotion (writes durable per-phase state markers).
The Fix (shipped)
repairMemoryCoreCollectionsViaFullEnumeration: per MC collection, auditChromaVectorCoverage({includeFullIds:true}) → full {allIds, missingVectorIds} → extractMemoryCoreCollectionData (intact + re-embed missing) → rewriteCollectionViaShadowPromotion. Behind the explicit --allow-memory-core opt-in; the default still fails closed. The memory-core config adapt surfaces embeddingProvider for the re-embedder (TextEmbeddingService.embedTexts, lazy-imported only on the MC path).
Two-level fail-loud + state-marker lifecycle:
- Collection: any unrecoverable row (document-less / metadata-absent) aborts that collection's promotion with counts — never a silent partial.
- Operator CLI: any aborted collection exits non-zero (
anyRepairAborted → process.exit(1)) — a partial repair never reports success (mirrors the KB extractionErrors/hasRestoreErrors discipline).
- State marker: a clean repair clears the durable marker; an aborted repair rewrites an explicit
memory-core-repair-aborted marker so assertNoIncompleteDefragState blocks rerun with an accurate diagnostic instead of poisoning the next run as DEFRAG_INCOMPLETE_STATE.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Evidence |
defragChromaDB --allow-memory-core (CLI flag) |
this leaf |
opt-in to the MC repair-defrag path |
absent → fails closed (DEFRAG_MEMORY_CORE_UNSAFE) |
gate unit tests |
repairMemoryCoreCollectionsViaFullEnumeration (export) |
this leaf |
the MC repair orchestration + state-marker lifecycle |
n/a (new export) |
10/10 unit tests |
assertDefragTargetSupported({allowMemoryCore}) |
this leaf |
gate-param admits MC only on opt-in |
default false (fail closed) |
gate unit tests |
anyRepairAborted(results) (export) |
this leaf |
operator-boundary fail-loud predicate (CLI exits non-zero) |
n/a (new export) |
predicate unit tests |
| MC defrag state marker |
defragChromaDB.mjs (existing invariant) |
clear on clean success; rewrite explicit aborted marker on partial |
leave → next run blocks as DEFRAG_INCOMPLETE_STATE |
marker-lifecycle unit tests |
TARGETS['memory-core'].adapt.embeddingProvider |
ai/mcp/server/memory-core/config.mjs |
surfaces the re-embed provider |
n/a |
live run |
Decision Record impact
none — aligns with the existing shadow-promotion defrag architecture; adds an opt-in MC repair path + preserves the existing state-marker invariant on it, no ADR change.
Acceptance Criteria
Sub of #13496 (delivers AC4). #13496 stays open for AC5 (runbook) + AC6 (bounded healthchecks) + the live validation.
Context
Delivers AC4 of #13496 ("a safe repair/rebuild path is selected and validated on a copy or shadow collection before live mutation"). MC defrag previously failed closed (
assertDefragTargetSupportedthrowsDEFRAG_MEMORY_CORE_UNSAFE) because the KB extract path (collection.get({include:['embeddings']})) throws "Error finding id" for the missing-vector rows the stored-embedding export bug leaves behind. Shipped on branchagent/13496-ac2-defrag-wiring(PR #13635).Live latest-open sweep: checked the latest 20 open issues at 2026-06-20; no equivalent repair-path leaf found.
Release classification: boardless — Agent OS / Memory Core stability, not v13-release-blocking.
The Problem
MC cannot delete/recreate-defrag (it is an irreplaceable store) and cannot use the KB extract (it throws for missing-vector rows). It needs a repair that recovers the missing vectors and promotes the result safely, without ever silently dropping data.
The Architectural Reality
ai/scripts/maintenance/defragChromaDB.mjs— the defrag orchestrator (the fail-closed gate + the shadow-promotion + the durable state-marker lifecycle).ai/scripts/maintenance/checkChromaIntegrity.mjs—auditChromaVectorCoverage+enumerateMetadataVectorDrift(the full, uncapped metadata-id vs vector-index-id enumeration viaincludeFullIds).ai/scripts/maintenance/repairMemoryCoreStoredEmbeddings.mjs—extractMemoryCoreCollectionData(extract intact rows with stored vectors + re-embed the missing-vector rows from their documents).rewriteCollectionViaShadowPromotion— the existing shadow/parking promotion (writes durable per-phase state markers).The Fix (shipped)
repairMemoryCoreCollectionsViaFullEnumeration: per MC collection,auditChromaVectorCoverage({includeFullIds:true})→ full{allIds, missingVectorIds}→extractMemoryCoreCollectionData(intact + re-embed missing) →rewriteCollectionViaShadowPromotion. Behind the explicit--allow-memory-coreopt-in; the default still fails closed. Thememory-coreconfig adapt surfacesembeddingProviderfor the re-embedder (TextEmbeddingService.embedTexts, lazy-imported only on the MC path).Two-level fail-loud + state-marker lifecycle:
anyRepairAborted→process.exit(1)) — a partial repair never reports success (mirrors the KBextractionErrors/hasRestoreErrorsdiscipline).memory-core-repair-abortedmarker soassertNoIncompleteDefragStateblocks rerun with an accurate diagnostic instead of poisoning the next run asDEFRAG_INCOMPLETE_STATE.Contract Ledger Matrix
defragChromaDB --allow-memory-core(CLI flag)DEFRAG_MEMORY_CORE_UNSAFE)repairMemoryCoreCollectionsViaFullEnumeration(export)assertDefragTargetSupported({allowMemoryCore})false(fail closed)anyRepairAborted(results)(export)defragChromaDB.mjs(existing invariant)DEFRAG_INCOMPLETE_STATETARGETS['memory-core'].adapt.embeddingProviderai/mcp/server/memory-core/config.mjsDecision Record impact
none— aligns with the existing shadow-promotion defrag architecture; adds an opt-in MC repair path + preserves the existing state-marker invariant on it, no ADR change.Acceptance Criteria
--allow-memory-coreopt-in; default fails closed.Sub of #13496 (delivers AC4). #13496 stays open for AC5 (runbook) + AC6 (bounded healthchecks) + the live validation.