Hotfix B2 Phase 1: drop task_leases.run_id FK (v51 migration)

Production bug on launch — user reports UI 'FOREIGN KEY constraint
failed' on 启动公司 and the main-process log loops forever with
'[heartbeat] CEO not ready: checkout_race_lost'. Both trace to the
same root cause introduced by v50 (e2c839b..2656684 B2 Phase 1):

  task_leases.run_id TEXT NOT NULL REFERENCES runs(id)

The orchestration sequence contradicts this FK. In both heartbeat.ts
(line 165) and task-runner.ts (line 91), the caller generates a fresh
runId = randomUUID() and immediately calls db.tasks.checkoutTask
BEFORE the corresponding row is inserted into the runs table. The
legacy tasks.checkout_run_id column has always been 'dangling
allowed' — the run row saves later when task-runner.ts opens the
run record. v50's FK tightened the shadow lease contract without
coordinating with that insertion sequence, so every checkoutTask
attempt now rolls back with a FK violation, takes the whole CAS
transaction with it, returns changes=0, and the heartbeat reports
checkout_race_lost. The task never advances — the exact orphan
symptom B2 was supposed to eliminate.

Fix: migration v51 recreates task_leases WITHOUT the run_id FK.

- task_id FK + ON DELETE CASCADE stays (a lease for a non-existent
  task is still meaningless)
- UNIQUE(task_id, run_id) stays (still a correctness constraint)
- run_id loses the FK — it mirrors the legacy checkout_run_id's
  loose semantics, which is exactly what Phase 1 dual-write is
  supposed to mirror
- Existing data preserved verbatim via INSERT SELECT
- Uses PRAGMA defer_foreign_keys=ON inside the transaction (the
  pragma is valid inside a txn; regular foreign_keys=OFF would not
  be since runMigrations already opened BEGIN IMMEDIATE)

Post-v51 the run_id column is still NOT NULL and the shadow probe
(ab4afba) will still surface missing runs as divergence — the FK
tightening is a Phase 2 concern coordinated with the saveRun
insertion order, not a Phase 1 shadow-write concern.

typecheck green, 529 unit tests green, 8/8 eval green.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-20 14:44:59 -04:00
1 parent 17ffec7ea5
commit b628b49016
2 files changed
+91

No files matched your search

+2
View File
@@ -16,6 +16,7 @@ import { createMigrationsV47V47 } from "./migrations/v47-v47";
import { createMigrationsV48V48 } from "./migrations/v48-v48";
import { createMigrationsV49V49 } from "./migrations/v49-v49";
import { createMigrationsV50V50 } from "./migrations/v50-v50";
import { createMigrationsV51V51 } from "./migrations/v51-v51";
import {
columnExists,
nowIso,
@@ -212,6 +213,7 @@ export function runMigrations(
...createMigrationsV48V48(deps),
...createMigrationsV49V49(deps),
...createMigrationsV50V50(deps),
...createMigrationsV51V51(deps),
];
// Pre-migration snapshot. If any migration is pending we take a full