ADR-0131: Canonical store + rebuildable projection is a standing rule, not a one-off fix¶
Status: Accepted (2026-10-05)
Relates to: ADR-0105 (user-fact store coherence — the worked example this ADR
generalizes), docs/architecture/memory-store-registry.md, docs/oss-plan-review.md,
the L4.5 Harness Hardening milestone.
Context¶
IRIS persists memory across several representations: SQLite stores, five ChromaDB
collections (iris_user_facts, iris_learning_signals, iris_conversation_turns,
iris_wiki_pages, iris_episodic_patterns), the Memris graph, and
identity-file projections (USER.md's auto-detected block, episodic.md). An external
architecture review asked the right question: which of these is canonical, and which
are rebuildable projections IRIS can delete and reconstruct without data loss?
The honest answer, checked against the code rather than assumed, is: this project already has the right architecture, it was just never stated as a general rule.
- Facts: ADR-0105 made this explicit and shipped it.
memory.db(SQLite) plususer_fact_historyis canonical;FactCoordinatoris the single write-seam;SemanticIndex.reconcile_facts()andidentity/loader.py::reconcile_user_facts_md()rebuild the ChromaDB andUSER.mdprojections from the store, dropping orphans, not just adding;iris memory doctoris the standing health check plus--repair. - Signals and turns:
SemanticIndex.sync_from_store()rebuilds both fromMemoryStoreat startup (turns incrementally, via a watermark). - Episodic patterns:
SemanticIndex.sync_episodic_patterns()reconciles theiris_episodic_patternscollection againstepisodic.md, including dropping stale ids — the same shape as the facts path. - Wiki:
memory/knowledge/wiki_index.pyowns its own rebuild/reindex path, independent of the above (confirmed by the existing startup-sync test intests/unit/iris_harness/memory/test_knowledge/test_wiki_engine.py). - Memris: is itself the canonical store (a
GraphStorecontract over SQLite); nothing insrc/iris_harness/memory/derives a second, separate vector projection from it that would need its own reconciliation. - Open question, not yet resolved:
src/iris_harness/services/rag/index.py(the document-RAG ChromaDB index) has no explicit rebuild/reindex function in that module. It may already be de facto rebuildable — re-running a connector's ingest is likely idempotent per source — but that has not been verified the way the five memory collections above were for this ADR.
Decision¶
-
State the rule explicitly, project-wide: every persisted representation of memory is either the canonical record (has provenance, is the thing a human or
iris memory doctor-style tool can audit and correct) or a projection that can be deleted and rebuilt from a canonical source with no data loss. A new store added toiris_harness/memory/(or any future sibling) must say, in its own module docstring or an ADR, which one it is and point at its rebuild path if it's a projection. -
ADR-0105 is the reference implementation of this rule, not a one-off fix to a single reported "store sprawl" concern. Point future reviewers here first.
-
Close the one open question: verify
services/rag/index.py's rebuildability (confirm each connector's ingest path is safely re-runnable from scratch, or add an explicit rebuild entry point if it isn't) as a fast-follow under the L4.5 milestone. This is a verification task, not a redesign — if ingestion is already idempotent, the fix is documenting that fact next to the index, not writing new code.
Alternatives considered¶
- Audit and "fix" every store as if a new gap exists. Rejected after checking the code: the five memory collections already satisfy this rule. Treating a sound architecture as broken because the general principle was never written down would have produced redundant, directionless work.
- Leave the principle implicit, since the code already does the right thing.
Rejected: an unstated invariant is not enforceable against future additions. The
review's real finding is that
docs/architecture/memory-subsystem.mdhas no canonical-vs-projection statement at all — this ADR is that statement.
Consequences¶
- Positive: a one-sentence test any future store addition must pass ("canonical, or rebuildable from what?"), backed by five working examples instead of a single abstract principle.
- Negative: none identified beyond the RAG-index verification task, which is small.
- Reversible: this is a documentation/process ADR; it changes no code by itself.
Files¶
docs/architecture/memory-subsystem.md— should cross-reference this ADR directly.docs/architecture/memory-store-registry.md— the per-store registry ADR-0105 introduced; this ADR is the rule that registry exists to serve.src/iris_harness/services/rag/index.py— subject of the fast-follow verification.