Context
While working on the broader malformed Chroma FTS5 investigation, I found that the first useful deliverable is a reusable on-demand diagnostic, not a repair. The broad repair/investigation ticket must stay open until the repair path is validated; this ticket captures only the copy-first diagnostic slice so the PR close target is honest.
Live latest-open sweep: checked latest 20 open issues on 2026-06-18 via list_issues({state:'open', limit:20, projection:'summary'}); only the broader #13467 and related #13466 were present, with no equivalent narrow diagnostic ticket.
A2A in-flight claim sweep: checked latest 30 messages via list_messages({status:'all', limit:30, box:'all'}); only my own [lane-claim][#13467] covered this scope, with no competing peer claim.
Release classification: post-release / operational-hardening diagnostic; boardless unless the operator promotes the broader repair to release-blocking.
The Problem
pragma quick_check and pragma integrity_check can report malformed inverted index for FTS5 table main.embedding_fulltext_search, but running ad-hoc probes directly against .neo-ai-data/chroma/unified/chroma.sqlite3 is easy to get wrong. We need a repeatable command that copies the SQLite file first, then runs integrity checks on the copy, and separately probes normal Chroma API read paths without mutating the live store.
The Architectural Reality
learn/agentos/decisions/0017-chroma-single-flat-unified-store.md defines the unified Chroma store: KB and MC share one flat chroma/unified persist directory, separated by collections, not folders.
learn/agentos/tooling/RestorationRunbook.md warns that the unified folder also contains irreplaceable MC data; diagnostics must not imply rm -rf or folder-level repair.
ai/scripts/maintenance/defragChromaDB.mjs is the destructive rewrite/defrag tool and already has its own snapshot and live-segment protections. This ticket is not a defrag wrapper.
ai/scripts/maintenance/purgeTestCollections.mjs is the sibling pattern for an on-demand operator maintenance script with pure helper coverage.
The Fix
Add ai/scripts/maintenance/checkChromaIntegrity.mjs and an npm script alias:
npm run ai:check-chroma-integrity
npm run ai:check-chroma-integrity -- --skip-api
npm run ai:check-chroma-integrity -- --sqlite /path/to/chroma.sqlite3 --json
The script must:
- Resolve the configured unified Chroma SQLite file by default.
- Copy
chroma.sqlite3 to a temporary snapshot before SQLite pragmas run.
- Run
quick_check and integrity_check against the copied snapshot only.
- Optionally perform read-only Chroma API probes (
count, sample-id fetch, document/metadata fetch, embedding fetch, query-by-existing-embedding) for the configured KB/MC collections.
- Exit non-zero when integrity checks or API probe steps fail.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
npm run ai:check-chroma-integrity |
package.json maintenance scripts + sibling purgeTestCollections.mjs |
Run a copy-first Chroma integrity diagnostic on demand |
Direct node ai/scripts/maintenance/checkChromaIntegrity.mjs invocation |
Script module JSDoc |
Script run output |
| SQLite integrity probe |
SQLite pragma quick_check / pragma integrity_check |
Execute only on a copied snapshot, never the live sqlite file |
--sqlite <path> can point at a pre-copied file |
Script module JSDoc |
Reproduces malformed FTS5 output on copy |
| Chroma API read probe |
Chroma client + current KB/MC config |
Perform read-only collection operation checks and report per-step failures |
--skip-api when only SQLite inspection is wanted |
Script module JSDoc |
API probe output per collection |
| Healthcheck hot path |
KB/MC healthcheck scope |
No new healthcheck work; diagnostic remains explicit operator command |
Existing bounded healthchecks remain unchanged |
N/A |
No healthcheck files touched |
Decision Record impact
aligned-with ADR 0017. The diagnostic respects the single flat unified store by probing a copied SQLite snapshot and using collection-scoped Chroma reads.
Acceptance Criteria
Out of Scope
- Determining or validating the actual repair path for the malformed FTS5/HNSW state.
- Running
REINDEX, VACUUM, defrag, delete/recreate, or any live store mutation.
- Closing the broader root-cause and repair investigation.
Avoided Traps
- Do not close the broader repair ticket with a diagnostic-only PR.
- Do not query the live SQLite file directly for routine diagnostics when copying first is cheap.
- Do not put SQLite
integrity_check into normal MCP healthchecks.
Related
Related: #13467
Related: #13466
Origin Session ID
Origin Session ID: 4ce60429-2986-4543-be2d-741957c75b6c
Handoff Retrieval Hints
query_raw_memories: copy-first Chroma integrity diagnostic malformed FTS5 quick_check
query_raw_memories: Chroma API read probe Error finding id embedding fetch memory sessions graph
Context
While working on the broader malformed Chroma FTS5 investigation, I found that the first useful deliverable is a reusable on-demand diagnostic, not a repair. The broad repair/investigation ticket must stay open until the repair path is validated; this ticket captures only the copy-first diagnostic slice so the PR close target is honest.
Live latest-open sweep: checked latest 20 open issues on 2026-06-18 via
list_issues({state:'open', limit:20, projection:'summary'}); only the broader #13467 and related #13466 were present, with no equivalent narrow diagnostic ticket.A2A in-flight claim sweep: checked latest 30 messages via
list_messages({status:'all', limit:30, box:'all'}); only my own[lane-claim][#13467]covered this scope, with no competing peer claim.Release classification: post-release / operational-hardening diagnostic; boardless unless the operator promotes the broader repair to release-blocking.
The Problem
pragma quick_checkandpragma integrity_checkcan reportmalformed inverted index for FTS5 table main.embedding_fulltext_search, but running ad-hoc probes directly against.neo-ai-data/chroma/unified/chroma.sqlite3is easy to get wrong. We need a repeatable command that copies the SQLite file first, then runs integrity checks on the copy, and separately probes normal Chroma API read paths without mutating the live store.The Architectural Reality
learn/agentos/decisions/0017-chroma-single-flat-unified-store.mddefines the unified Chroma store: KB and MC share one flatchroma/unifiedpersist directory, separated by collections, not folders.learn/agentos/tooling/RestorationRunbook.mdwarns that the unified folder also contains irreplaceable MC data; diagnostics must not implyrm -rfor folder-level repair.ai/scripts/maintenance/defragChromaDB.mjsis the destructive rewrite/defrag tool and already has its own snapshot and live-segment protections. This ticket is not a defrag wrapper.ai/scripts/maintenance/purgeTestCollections.mjsis the sibling pattern for an on-demand operator maintenance script with pure helper coverage.The Fix
Add
ai/scripts/maintenance/checkChromaIntegrity.mjsand an npm script alias:The script must:
chroma.sqlite3to a temporary snapshot before SQLite pragmas run.quick_checkandintegrity_checkagainst the copied snapshot only.count, sample-id fetch, document/metadata fetch, embedding fetch, query-by-existing-embedding) for the configured KB/MC collections.Contract Ledger Matrix
npm run ai:check-chroma-integritypackage.jsonmaintenance scripts + siblingpurgeTestCollections.mjsnode ai/scripts/maintenance/checkChromaIntegrity.mjsinvocationpragma quick_check/pragma integrity_check--sqlite <path>can point at a pre-copied file--skip-apiwhen only SQLite inspection is wantedDecision Record impact
aligned-with ADR 0017. The diagnostic respects the single flat unified store by probing a copied SQLite snapshot and using collection-scoped Chroma reads.
Acceptance Criteria
--skip-api.Out of Scope
REINDEX,VACUUM, defrag, delete/recreate, or any live store mutation.Avoided Traps
integrity_checkinto normal MCP healthchecks.Related
Related: #13467 Related: #13466
Origin Session ID
Origin Session ID: 4ce60429-2986-4543-be2d-741957c75b6c
Handoff Retrieval Hints
query_raw_memories:copy-first Chroma integrity diagnostic malformed FTS5 quick_checkquery_raw_memories:Chroma API read probe Error finding id embedding fetch memory sessions graph