diff --git a/src/resources/extensions/sf/sf-db.js b/src/resources/extensions/sf/sf-db.js index d5e79ebde..9e9363e86 100644 --- a/src/resources/extensions/sf/sf-db.js +++ b/src/resources/extensions/sf/sf-db.js @@ -114,7 +114,7 @@ function openRawDb(path) { loadProvider(); return new DatabaseSync(path); } -const SCHEMA_VERSION = 46; +const SCHEMA_VERSION = 47; function indexExists(db, name) { return !!db .prepare( @@ -2558,7 +2558,6 @@ function migrateSchema(db) { started_at TEXT, completed_at TEXT, created_at TEXT NOT NULL, - superseded_by TEXT, FOREIGN KEY (milestone_id) REFERENCES milestones(id) ) `); @@ -2585,6 +2584,25 @@ function migrateSchema(db) { ":applied_at": new Date().toISOString(), }); } + if (currentVersion < 47) { + // Drop unused superseded_by column from validation_runs. + // The column was never written or queried — dead schema from v46. + const cols = db + .prepare("PRAGMA table_info(validation_runs)") + .all() + .map((c) => c.name); + if (cols.includes("superseded_by")) { + db.exec( + "ALTER TABLE validation_runs DROP COLUMN superseded_by", + ); + } + db.prepare( + "INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)", + ).run({ + ":version": 47, + ":applied_at": new Date().toISOString(), + }); + } db.exec("COMMIT"); } catch (err) { db.exec("ROLLBACK"); @@ -7304,7 +7322,9 @@ export function completeValidationRun({ findings = "", }) { if (!currentDb) throw new SFError(SF_STALE_STATE, "sf-db: No database open"); - currentDb + const status = + verdict === "pass" ? "pass" : verdict === "fail" ? "fail" : "error"; + const result = currentDb .prepare( `UPDATE validation_runs SET status = :status, @@ -7312,15 +7332,21 @@ export function completeValidationRun({ rationale = :rationale, findings = :findings, completed_at = datetime('now') - WHERE run_id = :run_id`, + WHERE run_id = :run_id AND status = 'running'`, ) .run({ ":run_id": runId, - ":status": verdict === "pass" ? "pass" : verdict === "fail" ? "fail" : "error", + ":status": status, ":verdict": verdict ?? "", ":rationale": rationale ?? "", ":findings": findings ?? "", }); + if (result.changes === 0) { + throw new SFError( + SF_STALE_STATE, + `sf-db: completeValidationRun: no running validation run found for run_id=${runId}`, + ); + } } /**