Context
Follow-up to #691 / PR #712.
#691 backfilled src/backend/db/schema.py with 11 tables, 14 columns, and ~22 indexes that existed only in src/backend/db/migrations.py. The fix re-encoded the drift class — there is no automated check preventing the next contributor from adding a migration without updating schema.py. In 6 months, the same drift will accumulate again unless we close the loop.
This was raised by both Codex and an independent Claude subagent during the autoplan dual-voice CEO review for #691, and approved at the final approval gate (D2 = B) as a follow-up issue to be filed alongside the implementation PR.
Proposal
Add a CI check that runs the parity verification scripts already documented in #691's plan against every PR that touches src/backend/db/migrations.py:
- Spin up an in-memory SQLite database, run
init_schema() only, snapshot state.
- Run
run_all_migrations(), snapshot state again.
- Diff tables, columns, indexes. Filter
schema_migrations (created internally by run_all_migrations).
- Run a strict DDL parity check: normalize whitespace and lowercase the
sqlite_master.sql text, compare entry-by-entry. Fail on any MISSING or DIFFERENT line.
Implementation sketch
A small Python check at scripts/check-schema-parity.py (or tests/unit/test_schema_parity.py so it runs with the existing test suite). The verification script from #691's plan is essentially the spec — it works against the current branch (verified during autoplan) and produces empty output when schema.py is faithful.
Wire into CI by:
- Running it as part of
tests/run-core.sh (Tier 2 pre-commit checks)
- Adding a GitHub Actions job that runs only when
src/backend/db/migrations.py or src/backend/db/schema.py changes (path filter)
Acceptance criteria
Out of scope
- Collapsing the two-source-of-truth pattern (e.g., migrating to Alembic, generating schema.py from migrations) — separate, larger discussion.
References
Context
Follow-up to #691 / PR #712.
#691 backfilled
src/backend/db/schema.pywith 11 tables, 14 columns, and ~22 indexes that existed only insrc/backend/db/migrations.py. The fix re-encoded the drift class — there is no automated check preventing the next contributor from adding a migration without updatingschema.py. In 6 months, the same drift will accumulate again unless we close the loop.This was raised by both Codex and an independent Claude subagent during the autoplan dual-voice CEO review for #691, and approved at the final approval gate (D2 = B) as a follow-up issue to be filed alongside the implementation PR.
Proposal
Add a CI check that runs the parity verification scripts already documented in #691's plan against every PR that touches
src/backend/db/migrations.py:init_schema()only, snapshot state.run_all_migrations(), snapshot state again.schema_migrations(created internally byrun_all_migrations).sqlite_master.sqltext, compare entry-by-entry. Fail on anyMISSINGorDIFFERENTline.Implementation sketch
A small Python check at
scripts/check-schema-parity.py(ortests/unit/test_schema_parity.pyso it runs with the existing test suite). The verification script from #691's plan is essentially the spec — it works against the current branch (verified during autoplan) and produces empty output when schema.py is faithful.Wire into CI by:
tests/run-core.sh(Tier 2 pre-commit checks)src/backend/db/migrations.pyorsrc/backend/db/schema.pychanges (path filter)Acceptance criteria
migrations.pyorschema.pyschema.pyproduces a CI failure with a clear "schema.py drift detected" message naming the missing table/column/indexinit_database()so it stays consistent with production semanticsOut of scope
References
docs/memory/architecture.md— Architectural Invariant Feature/vector log retention #3