Roadmap source: kodiai-roadmap.md
- Phase: Phase 3 — Code Safety Net
- Milestone: M056
Slice M056/S01 — Down-migrations for early gaps (012, 013, 016, 025, 026)
What this is
src/db/migrations/ is missing .down.sql for: 012-wiki-staleness-run-state, 013-review-clusters, 016-issue-triage-state, 025-wiki-style-cache, 026-guardrail-audit. These predate M033–M036 and have likely been live in production for months. The original gap analysis missed them because it only scanned the recent migrations.
Why now
If any of these tables needs to be dropped or altered for a rollback, there's no canonical rollback DDL. Each has to be reconstructed from memory under pressure.
Acceptance criteria
Files to touch
src/db/migrations/012-wiki-staleness-run-state.down.sql — create.
src/db/migrations/013-review-clusters.down.sql — create.
src/db/migrations/016-issue-triage-state.down.sql — create.
src/db/migrations/025-wiki-style-cache.down.sql — create.
src/db/migrations/026-guardrail-audit.down.sql — create.
Verify contract
- Command:
bun run verify:m056:s01
- Script:
scripts/verify-m056-s01.ts
- Check IDs:
down_file_present_per_up, up_down_up_schema_diff_empty, data_loss_guarded.
- Status codes:
m056_s01_ok, m056_s01_missing_down, m056_s01_schema_drift_after_roundtrip.
Slice M056/S02 — Down-migrations for M033–M036 + missing 030
What this is
Migrations 033–036 ship without .down.sql:
033-canonical-code-corpus.sql
034-review-graph.sql
035-generated-rules.sql
036-suggestion-cluster-models.sql
And the migration sequence has a real gap: 029-embedding-repair-state.sql is followed by 031-wiki-comment-identity.sql — there is no 030-*.sql file on disk. The .gsd/milestones/M030/ folder exists (planning artifact) but no corresponding database migration shipped under the 030 slot.
Acceptance criteria
Files to touch
src/db/migrations/033-canonical-code-corpus.down.sql — create.
src/db/migrations/034-review-graph.down.sql — create.
src/db/migrations/035-generated-rules.down.sql — create.
src/db/migrations/036-suggestion-cluster-models.down.sql — create.
src/db/migrations/030-reserved.sql + .down.sql or .gsd/DECISIONS.md entry D-M056-01.
Verify contract
- Command:
bun run verify:m056:s02
- Script:
scripts/verify-m056-s02.ts
- Check IDs:
down_file_present_033_036, slot_030_resolved, round_trip_passes.
- Status codes:
m056_s02_ok, m056_s02_missing_down, m056_s02_slot_030_ambiguous.
Slice M056/S03 — CI gate: no new .sql without .down.sql
What this is
Once S01 and S02 close the historical gap, the only way to prevent it from reopening is to make CI reject any PR that adds a .sql migration without an .down.sql sibling.
Acceptance criteria
Files to touch
scripts/check-migrations-have-downs.ts — create.
.github/workflows/ci.yml — add step.
.gsd/DECISIONS.md — append D-M056-02.
Verify contract
- Command:
bun run verify:m056:s03 (which itself invokes check-migrations-have-downs.ts).
- Check IDs:
ci_step_registered, allowlist_minimal, decision_record_present.
- Status codes:
m056_s03_ok, m056_s03_ci_step_missing, m056_s03_allowlist_bloat.
Roadmap source:
kodiai-roadmap.mdSlice M056/S01 — Down-migrations for early gaps (012, 013, 016, 025, 026)
What this is
src/db/migrations/is missing.down.sqlfor:012-wiki-staleness-run-state,013-review-clusters,016-issue-triage-state,025-wiki-style-cache,026-guardrail-audit. These predate M033–M036 and have likely been live in production for months. The original gap analysis missed them because it only scanned the recent migrations.Why now
If any of these tables needs to be dropped or altered for a rollback, there's no canonical rollback DDL. Each has to be reconstructed from memory under pressure.
Acceptance criteria
.down.sqlexists for 012, 013, 016, 025, 026 and drops the tables/columns/indexes the up migration created, in reverse order.up→down→upagainst a fresh Postgres + pgvector container and confirming the schema diff is empty.CONFIRM_DATA_LOSS=1env guard where applicable.Files to touch
src/db/migrations/012-wiki-staleness-run-state.down.sql— create.src/db/migrations/013-review-clusters.down.sql— create.src/db/migrations/016-issue-triage-state.down.sql— create.src/db/migrations/025-wiki-style-cache.down.sql— create.src/db/migrations/026-guardrail-audit.down.sql— create.Verify contract
bun run verify:m056:s01scripts/verify-m056-s01.tsdown_file_present_per_up,up_down_up_schema_diff_empty,data_loss_guarded.m056_s01_ok,m056_s01_missing_down,m056_s01_schema_drift_after_roundtrip.Slice M056/S02 — Down-migrations for M033–M036 + missing 030
What this is
Migrations 033–036 ship without
.down.sql:033-canonical-code-corpus.sql034-review-graph.sql035-generated-rules.sql036-suggestion-cluster-models.sqlAnd the migration sequence has a real gap:
029-embedding-repair-state.sqlis followed by031-wiki-comment-identity.sql— there is no030-*.sqlfile on disk. The.gsd/milestones/M030/folder exists (planning artifact) but no corresponding database migration shipped under the 030 slot.Acceptance criteria
.down.sqlexists for 033, 034, 035, 036 with the same round-trip test as S01.030-reserved.sql+.down.sqlwith an explanatory comment referencing the M030 planning folder, or (b) document in.gsd/DECISIONS.md(D-M056-01) that 030 is intentionally skipped and add a comment to the migration runner explaining the gap.up→down→uptest passes across 033–036 against the pgvector container.Files to touch
src/db/migrations/033-canonical-code-corpus.down.sql— create.src/db/migrations/034-review-graph.down.sql— create.src/db/migrations/035-generated-rules.down.sql— create.src/db/migrations/036-suggestion-cluster-models.down.sql— create.src/db/migrations/030-reserved.sql+.down.sqlor.gsd/DECISIONS.mdentry D-M056-01.Verify contract
bun run verify:m056:s02scripts/verify-m056-s02.tsdown_file_present_033_036,slot_030_resolved,round_trip_passes.m056_s02_ok,m056_s02_missing_down,m056_s02_slot_030_ambiguous.Slice M056/S03 — CI gate: no new
.sqlwithout.down.sqlWhat this is
Once S01 and S02 close the historical gap, the only way to prevent it from reopening is to make CI reject any PR that adds a
.sqlmigration without an.down.sqlsibling.Acceptance criteria
scripts/check-migrations-have-downs.tsscript lists everysrc/db/migrations/*.sqland asserts each has a matching.down.sqlunless annotated in an allowlist (for existing intentional exceptions from S02)..github/workflows/ci.ymlruns this check on every PR.Files to touch
scripts/check-migrations-have-downs.ts— create..github/workflows/ci.yml— add step..gsd/DECISIONS.md— append D-M056-02.Verify contract
bun run verify:m056:s03(which itself invokescheck-migrations-have-downs.ts).ci_step_registered,allowlist_minimal,decision_record_present.m056_s03_ok,m056_s03_ci_step_missing,m056_s03_allowlist_bloat.