Skip to content

[M056] Migration Rollback Completeness #95

@keithah

Description

@keithah

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

  • .down.sql exists for 012, 013, 016, 025, 026 and drops the tables/columns/indexes the up migration created, in reverse order.
  • Each down migration is tested by running updownup against a fresh Postgres + pgvector container and confirming the schema diff is empty.
  • No production data loss risk is introduced: down migrations document any data that would be lost and require a CONFIRM_DATA_LOSS=1 env 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

  • 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

  • .down.sql exists for 033, 034, 035, 036 with the same round-trip test as S01.
  • A decision is made about slot 030: either (a) write a no-op 030-reserved.sql + .down.sql with 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.
  • updownup test 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.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

  • A scripts/check-migrations-have-downs.ts script lists every src/db/migrations/*.sql and asserts each has a matching .down.sql unless annotated in an allowlist (for existing intentional exceptions from S02).
  • .github/workflows/ci.yml runs this check on every PR.
  • A DECISIONS.md entry (D-M056-02) records the contract: "Every forward migration ships with a rollback migration or an allowlisted rationale."

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions