Context
This is the next narrow implementation leaf under the broader #13496 repair investigation.
#13501 / PR #13502 shipped the bounded stored-embedding exportability diagnostic. #13503 / PR #13559 then shipped the exact metadata-vs-vector-index coverage audit. Those diagnostics confirmed the next #13496 risk: Memory Core export can encounter corrupted or missing vector IDs, rescue a partial subset, and still let the backup path treat the export as complete.
Live latest-open sweep: checked the latest 30 open GitHub issues at 2026-06-20T02:42:35Z; no equivalent partial-export / backup-completeness leaf was present. Closest open issue is the broader #13496 parent.
A2A in-flight claim sweep: checked latest 30 all-status A2A messages at 2026-06-20T02:42Z; no competing peer [lane-claim] / [lane-intent] for the Memory Core partial-export slice was present. The only matching claim was my own [lane-claim][#13496] Memory Core Chroma export completeness.
Exact sweep: rg "partial.*Chroma.*export|Chroma.*partial.*export|Memory Core.*partial.*export|fail loud.*export|export completeness|PARTIAL_COLLECTION_EXPORT|corrupted vector ID during export" resources/content/issues resources/content/discussions ai test -S found no existing ticket/discussion leaf. It found the active branch implementation strings and the older Knowledge Base export sibling log line, not an existing Memory Core backup-completeness ticket.
Release classification: boardless (post-release operational hardening; important for backup correctness but not a release blocker).
The Problem
ai/services/memory-core/DatabaseService.mjs currently counts source records before export, but its Chroma rescue path can skip corrupted vector IDs during per-ID fallback. The method then logs success and returns the original source count.
That is unsafe for #13496 because a partial Memory Core backup can look complete to the operator and to ai/scripts/maintenance/backup.mjs. The bundle verifier can only compare row counts when the SDK returns a numeric source count; a message-only or incorrectly counted export lets partial Memory Core JSONL artifacts pass as unverified or complete.
The Architectural Reality
Relevant surfaces:
ai/services/memory-core/DatabaseService.mjs owns Memory Core JSONL export/import through manageDatabaseBackup({action:'export'}).
ai/scripts/maintenance/backup.mjs assembles the canonical atomic backup bundle and verifies JSONL row-count parity when subsystem SDK results expose a numeric count.
- ADR 0017 keeps Memory Core and Knowledge Base in the unified Chroma store, with backup/export correctness as a collection-layer boundary. The fix must not add a daemon, path split, hot healthcheck, or live repair mutation.
The Fix
Tighten the Memory Core export contract:
- Track per-collection
expected, exported, skipped, and skippedIds while writing JSONL.
- If any collection exports fewer rows than its source count, fail loudly with a stable partial-export error instead of reporting success.
- Preserve the existing human
message, but add a numeric aggregate count and per-subsystem stats to successful exportDatabase() results so the backup bundle verifier can validate Memory Core row-count parity.
- Add focused unit coverage for both complete exports and corrupt-vector fallback producing a partial export.
- Keep live repair/rebuild out of scope.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
DatabaseService.#exportCollection() |
#13496 diagnostic ledger + existing Memory Core export path |
Return truthful export stats and throw when exported !== expected |
Partial JSONL may remain for forensic inspection, but the SDK call fails and cannot be treated as a complete backup |
JSDoc return contract |
Focused unit coverage with corrupt single-ID fallback |
DatabaseService.exportDatabase() result |
backup.mjs bundle verifier |
Preserve message, add numeric count, and expose memories / summaries / graph stats on success |
Existing consumers that read only message continue to work |
JSDoc return contract |
Unit coverage asserts count-bearing result |
backup.mjs Memory Core integrity check |
Atomic backup bundle contract |
Use Memory Core count to verify bundle row-count parity instead of skipping MC as non-numeric |
If a future SDK returns no count, existing skipped path remains explicit |
Existing verifier docs |
Unit coverage asserts MC integrity pass |
Decision Record impact
aligned-with ADR 0017 (learn/agentos/decisions/0017-chroma-single-flat-unified-store.md): strengthens collection-scoped backup/export correctness inside the unified Chroma store without changing topology.
Acceptance Criteria
Out of Scope
- Repairing or rebuilding any Chroma collection.
- Re-embedding Memory Core rows.
- Changing Knowledge Base export semantics.
- Adding heavy exportability checks to hot healthchecks.
- Closing #13496; this is one leaf in the broader repair investigation.
Avoided Traps
- Do not silently skip corrupted IDs and call the backup complete.
- Do not make the backup verifier infer correctness from log text.
- Do not mutate live Chroma as part of an export-completeness fix.
Related
Related: #13496
Related: #13501
Related: #13502
Related: #13503
Related: #13559
Origin Session ID: 152f9eee-42e2-4740-8bce-d23e1f575ec8
Handoff Retrieval Hints
query_raw_memories("Chroma stored embedding exportability metadata rows vector index ids missing from vector #13496 #13501")
query_raw_memories("Memory Core Chroma partial export skipped corrupted vector ID backup completeness")
- Exact files:
ai/services/memory-core/DatabaseService.mjs, ai/scripts/maintenance/backup.mjs, test/playwright/unit/ai/services/memory-core/DatabaseService.backupPath.spec.mjs
Context
This is the next narrow implementation leaf under the broader #13496 repair investigation.
#13501/ PR#13502shipped the bounded stored-embedding exportability diagnostic.#13503/ PR#13559then shipped the exact metadata-vs-vector-index coverage audit. Those diagnostics confirmed the next #13496 risk: Memory Core export can encounter corrupted or missing vector IDs, rescue a partial subset, and still let the backup path treat the export as complete.Live latest-open sweep: checked the latest 30 open GitHub issues at 2026-06-20T02:42:35Z; no equivalent partial-export / backup-completeness leaf was present. Closest open issue is the broader #13496 parent.
A2A in-flight claim sweep: checked latest 30 all-status A2A messages at 2026-06-20T02:42Z; no competing peer
[lane-claim]/[lane-intent]for the Memory Core partial-export slice was present. The only matching claim was my own[lane-claim][#13496] Memory Core Chroma export completeness.Exact sweep:
rg "partial.*Chroma.*export|Chroma.*partial.*export|Memory Core.*partial.*export|fail loud.*export|export completeness|PARTIAL_COLLECTION_EXPORT|corrupted vector ID during export" resources/content/issues resources/content/discussions ai test -Sfound no existing ticket/discussion leaf. It found the active branch implementation strings and the older Knowledge Base export sibling log line, not an existing Memory Core backup-completeness ticket.Release classification: boardless (post-release operational hardening; important for backup correctness but not a release blocker).
The Problem
ai/services/memory-core/DatabaseService.mjscurrently counts source records before export, but its Chroma rescue path can skip corrupted vector IDs during per-ID fallback. The method then logs success and returns the original source count.That is unsafe for #13496 because a partial Memory Core backup can look complete to the operator and to
ai/scripts/maintenance/backup.mjs. The bundle verifier can only compare row counts when the SDK returns a numeric source count; a message-only or incorrectly counted export lets partial Memory Core JSONL artifacts pass as unverified or complete.The Architectural Reality
Relevant surfaces:
ai/services/memory-core/DatabaseService.mjsowns Memory Core JSONL export/import throughmanageDatabaseBackup({action:'export'}).ai/scripts/maintenance/backup.mjsassembles the canonical atomic backup bundle and verifies JSONL row-count parity when subsystem SDK results expose a numericcount.The Fix
Tighten the Memory Core export contract:
expected,exported,skipped, andskippedIdswhile writing JSONL.message, but add a numeric aggregatecountand per-subsystem stats to successfulexportDatabase()results so the backup bundle verifier can validate Memory Core row-count parity.Contract Ledger Matrix
DatabaseService.#exportCollection()exported !== expectedDatabaseService.exportDatabase()resultbackup.mjsbundle verifiermessage, add numericcount, and exposememories/summaries/graphstats on successmessagecontinue to workbackup.mjsMemory Core integrity checkcountto verify bundle row-count parity instead of skipping MC as non-numericDecision Record impact
aligned-with ADR 0017 (
learn/agentos/decisions/0017-chroma-single-flat-unified-store.md): strengthens collection-scoped backup/export correctness inside the unified Chroma store without changing topology.Acceptance Criteria
expected,exported,skipped, andskippedIdscounts.countwhile preserving the existingmessagefield.Out of Scope
Avoided Traps
Related
Related: #13496 Related: #13501 Related: #13502 Related: #13503 Related: #13559
Origin Session ID: 152f9eee-42e2-4740-8bce-d23e1f575ec8
Handoff Retrieval Hints
query_raw_memories("Chroma stored embedding exportability metadata rows vector index ids missing from vector #13496 #13501")query_raw_memories("Memory Core Chroma partial export skipped corrupted vector ID backup completeness")ai/services/memory-core/DatabaseService.mjs,ai/scripts/maintenance/backup.mjs,test/playwright/unit/ai/services/memory-core/DatabaseService.backupPath.spec.mjs