Context
The chromadb/chroma:1.5.9 container's entrypoint executes chroma run /config.yaml; that shipped config pins persist_path: "/data", and PERSIST_DIRECTORY is not read on that path. All three base compose files mounted their storage surface at /chroma/unified and declared PERSIST_DIRECTORY=/chroma/unified — so the live store accumulated in the container's ephemeral writable layer while the mounted volume stayed empty. Live census on the canonical plane: /data = 1.1 GB, mounted /chroma/unified = 4 KB.
Incident owner: #16208 (corrected root cause + the v4.1 recovery plan). This leaf owns exactly the compose mount contract and its authority surfaces — fully delivered by one PR. The recovery execution (quiesced physical seed, recreate-survival proofs, reconciliation receipts) stays on #16208 and must NOT auto-close with this leaf.
Duplicate sweep: #16208 is the incident (open, non-closing here); #16206 is deploy layering; #16219 (Docker-owned volumes) is closed. No open ticket owns the mount contract itself.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
ai/deploy/docker-compose.yml chroma service |
the audited image entrypoint + shipped /config.yaml (persist_path: "/data"); live census |
named volume chroma-data:/data; PERSIST_DIRECTORY=/data declared on the same leaf |
exact image-pin assertion forces re-verification of the shipped config before any tag bump |
ADR 0017 §2.2 (corrected in place) |
ChromaPersistPathContract.spec.mjs RED→GREEN |
ai/deploy/docker-compose.dev.yml chroma service |
same |
parity-chroma:/data; env aligned |
same |
same |
same spec |
ai/deploy/docker-compose.test.yml chroma service |
same |
tmpfs at /data; env aligned |
same |
same |
same spec |
| ADR 0017 active prose |
the falsification evidence |
abstract / Decision / §2.2 / rejected-alternative row / handoff consistently state one-store topology + LOGICAL parity with the image-owned container leaf /data; the dated falsification record is retained as archaeology |
— |
the ADR itself |
zero active /chroma/unified prescriptions remain |
learn/agentos/cloud-deployment/PipelineWiring.md persistence row |
ADR 0017 §2.2 (corrected) |
names /data and why |
— |
the row |
updated in the same PR |
Acceptance Criteria
Out of Scope
- The v4.1 recovery execution — #16208 owns it.
- Overlay compose files (inherit the corrected base definitions; introduce no storage override — reviewer-verified on PR #16252).
- Server-side
NEO_CHROMA_DATA_DIR / engines.chroma.dataDirProd host-path semantics — a different contract.
- Deploy layering — #16206.
Related
- #16208 — incident owner (corrected root cause + v4.1 execution receipts); related, non-closing.
- #16167 — the migration epic.
- #16206 — deploy layering.
Origin Session ID: c4b84de4-d7d9-4cbf-99cc-5bd4a561783e
Retrieval Hint: chroma persist path data compose mount PERSIST_DIRECTORY image pinned named volume ephemeral writable layer store loss ADR 0017
Context
The
chromadb/chroma:1.5.9container's entrypoint executeschroma run /config.yaml; that shipped config pinspersist_path: "/data", andPERSIST_DIRECTORYis not read on that path. All three base compose files mounted their storage surface at/chroma/unifiedand declaredPERSIST_DIRECTORY=/chroma/unified— so the live store accumulated in the container's ephemeral writable layer while the mounted volume stayed empty. Live census on the canonical plane:/data= 1.1 GB, mounted/chroma/unified= 4 KB.Incident owner: #16208 (corrected root cause + the v4.1 recovery plan). This leaf owns exactly the compose mount contract and its authority surfaces — fully delivered by one PR. The recovery execution (quiesced physical seed, recreate-survival proofs, reconciliation receipts) stays on #16208 and must NOT auto-close with this leaf.
Duplicate sweep: #16208 is the incident (open, non-closing here); #16206 is deploy layering; #16219 (Docker-owned volumes) is closed. No open ticket owns the mount contract itself.
Contract Ledger
ai/deploy/docker-compose.ymlchroma service/config.yaml(persist_path: "/data"); live censuschroma-data:/data;PERSIST_DIRECTORY=/datadeclared on the same leafChromaPersistPathContract.spec.mjsRED→GREENai/deploy/docker-compose.dev.ymlchroma serviceparity-chroma:/data; env alignedai/deploy/docker-compose.test.ymlchroma service/data; env aligned/data; the dated falsification record is retained as archaeology/chroma/unifiedprescriptions remainlearn/agentos/cloud-deployment/PipelineWiring.mdpersistence row/dataand whyAcceptance Criteria
/datawithPERSIST_DIRECTORYaligned; zero storage surfaces target/chroma/unified.ChromaPersistPathContract.spec.mjsguards the contract per file with a positive control (service exists + exact image pin) so the negatives cannot pass vacuously; demonstrated RED against the old shape, GREEN after./data.Out of Scope
NEO_CHROMA_DATA_DIR/engines.chroma.dataDirProdhost-path semantics — a different contract.Related
Origin Session ID: c4b84de4-d7d9-4cbf-99cc-5bd4a561783e
Retrieval Hint:
chroma persist path data compose mount PERSIST_DIRECTORY image pinned named volume ephemeral writable layer store loss ADR 0017