Context
Follow-up to #713 (PR #745). #713 closes the prevention loop for schema-vs-migrations drift via a CI gate. The dual-voice plan review for #713 (Codex + Claude subagent) flagged that the gate, while useful as a stopgap, ossifies the underlying dual-source-of-truth pattern — Trinity has two writable schema authorities (src/backend/db/schema.py declarative, src/backend/db/migrations.py versioned) and contributors must keep both in sync by hand.
Codex (during /autoplan dual-voice CEO review):
A CI gate is acceptable only as a temporary brake. As a durable answer, it normalizes the real failure mode: Trinity has two writable schema authorities. Once this lands, future contributors will learn the ritual "touch migration, touch schema.py" instead of the invariant "there is one schema source." That can ossify the bad pattern unless #713 explicitly creates a follow-up to eliminate dual-authoring through generation, a schema dump artifact, or Alembic-style migration ownership.
Claude subagent agreed, noting payback for unification is roughly 5x within 5 years on drift-cost alone, and the real value is eliminating the cognitive tax (53 tables, 36+ migrations, two places to remember per change).
Cost math (rough)
| Approach |
Cost |
Drift risk after |
| Status quo (post-#713 CI gate) |
$0 ongoing |
Gate catches table/column/index/trigger drift; constraint-level (NOT NULL/DEFAULT/FK/CHECK), reverse-direction, and trigger-body drift still slip through |
| Alembic migration |
~1 week |
Eliminated — Alembic auto-generates migrations from a declarative source |
Generated schema.py from migration end-state |
~3-5 days |
Eliminated — schema.py becomes a snapshot artifact, not a hand-edited file |
| Schema-dump check-in (snapshot in repo) |
~2 days |
Reduced — drift becomes a CI-visible diff in a generated artifact |
Proposal
Pick one of the three unification paths above by 2026-11 (~6 months from #713 ship). #713's gate buys us time; this issue is the alarm that the time is running.
Three options to evaluate:
- Migrate to Alembic — full standard solution; biggest behavior change.
- Generate
schema.py from migrations — keep two files, but make schema.py a CI-generated artifact (no hand edits). Smallest diff to current architecture.
- Repo-checked schema dump artifact — e.g.
src/backend/db/schema.sql regenerated by a script, diffed in CI. Lighter than (2) and gives a SQLite-canonical source.
Out of scope here
References
Context
Follow-up to #713 (PR #745). #713 closes the prevention loop for schema-vs-migrations drift via a CI gate. The dual-voice plan review for #713 (Codex + Claude subagent) flagged that the gate, while useful as a stopgap, ossifies the underlying dual-source-of-truth pattern — Trinity has two writable schema authorities (
src/backend/db/schema.pydeclarative,src/backend/db/migrations.pyversioned) and contributors must keep both in sync by hand.Codex (during /autoplan dual-voice CEO review):
Claude subagent agreed, noting payback for unification is roughly 5x within 5 years on drift-cost alone, and the real value is eliminating the cognitive tax (53 tables, 36+ migrations, two places to remember per change).
Cost math (rough)
schema.pyfrom migration end-stateProposal
Pick one of the three unification paths above by 2026-11 (~6 months from #713 ship). #713's gate buys us time; this issue is the alarm that the time is running.
Three options to evaluate:
schema.pyfrom migrations — keep two files, but makeschema.pya CI-generated artifact (no hand edits). Smallest diff to current architecture.src/backend/db/schema.sqlregenerated by a script, diffed in CI. Lighter than (2) and gives a SQLite-canonical source.Out of scope here
References
docs/memory/architecture.md— Architectural Invariant Feature/vector log retention #3