fix(schema): reorder ADR-0000 migrations so v70/v71/v72 run in order

After cherry-picking the swarm commits the migration file had v72
declared before v70/v71 — when applied to a v69 DB the loop ran v72
first, set appliedVersion=72, and the v70/v71 guards `if
(appliedVersion < 70)` then `< 71` short-circuited so neither
ALTER ran on legacy DBs. Reordered so the file flows v70 → v71 → v72
matching version numbers; idempotent column probes on fresh DBs
still pass.

Verified: full sf-db-migration suite 13/13 green, including the
v52-and-v27 legacy-fixture paths that exercise the migration ladder
end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mikael Hugo 2026-05-15 18:53:04 +02:00
parent 725affd126
commit 008f0c685d

View file

@ -3579,37 +3579,6 @@ function migrateSchema(db, { currentPath, withQueryTimeout }) {
if (ok) appliedVersion = 69;
}
if (appliedVersion < 72) {
const ok = runMigrationStep("v72", () => {
// Schema v72: per-slice vision trace (ADR-0000 P2, restoration of doctrine).
// Renumbered from the originally-planned v69 because parallel work on
// main used v69 for memory_extraction_attempts.failure_class.
//
// plan-milestone must emit a literal fragment of milestone.vision that each
// slice serves so validate-milestone has structured grounds for assessment
// instead of re-reading the entire vision via the LLM every time. The
// fragment is the canonical "this slice traces back to that purpose" link.
//
// NULL is allowed for legacy rows (slices planned before v72); the
// planning prompt and validation begin requiring it for new slices.
//
// Idempotent ALTER: probe via columnExists because the fresh-DB CREATE
// path already adds the column.
if (!columnExists(db, "slices", "traces_vision_fragment")) {
db.exec(
"ALTER TABLE slices ADD COLUMN traces_vision_fragment TEXT",
);
}
db.prepare(
"INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)",
).run({
":version": 72,
":applied_at": new Date().toISOString(),
});
});
if (ok) appliedVersion = 72;
}
if (appliedVersion < 70) {
const ok = runMigrationStep("v70", () => {
// Schema v70: per-task purpose trace (ADR-0000 restoration).
@ -3671,6 +3640,37 @@ function migrateSchema(db, { currentPath, withQueryTimeout }) {
if (ok) appliedVersion = 71;
}
if (appliedVersion < 72) {
const ok = runMigrationStep("v72", () => {
// Schema v72: per-slice vision trace (ADR-0000 P2, restoration of doctrine).
// Renumbered from the originally-planned v69 because parallel work on
// main used v69 for memory_extraction_attempts.failure_class.
//
// plan-milestone must emit a literal fragment of milestone.vision that each
// slice serves so validate-milestone has structured grounds for assessment
// instead of re-reading the entire vision via the LLM every time. The
// fragment is the canonical "this slice traces back to that purpose" link.
//
// NULL is allowed for legacy rows (slices planned before v72); the
// planning prompt and validation begin requiring it for new slices.
//
// Idempotent ALTER: probe via columnExists because the fresh-DB CREATE
// path already adds the column.
if (!columnExists(db, "slices", "traces_vision_fragment")) {
db.exec(
"ALTER TABLE slices ADD COLUMN traces_vision_fragment TEXT",
);
}
db.prepare(
"INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)",
).run({
":version": 72,
":applied_at": new Date().toISOString(),
});
});
if (ok) appliedVersion = 72;
}
// Post-migration assertion: ensure critical tables created by historical
// migrations are actually present. If a prior migration claimed success but
// the table is missing (e.g., due to a rolled-back transaction that failed