Drop stale active_run_id when a task returns to todo/backlog

advanceTaskStatus cleared checkout_run_id when transitioning out of
in_progress but left active_run_id alone. Heartbeat selects candidate
tasks by !activeRunId, so a task recovered from a crash (moved
blocked → todo by the bootstrap recovery) could carry a dead
active_run_id pointer and remain silently unpickable by every future
wake, even though the run it points to is long since interrupted.

interruptStaleRuns normally clears active_run_id for tasks whose
owning run is now interrupted, but the guarantee relied on a single
startup pass. Make advanceTaskStatus defensive: when the terminal
state is todo or backlog, clear the pointer too. The invariant holds
end-to-end instead of relying on interruptStaleRuns having seen every
edge case.

Also harden the new-CEO team-building cue: make it an explicit
imperative ("call the bash tool to run the fetch POSTs now") and
route app_restart_resume through the same branch so a startup-crash
recovery wake lands on the same focused action script.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-19 20:09:33 -04:00
1 parent 2f318bfc35
commit 0c67779012
2 files changed
+14 -2

No files matched your search

+7
View File
@@ -110,6 +110,13 @@ export function buildTaskStatusMethods(
if (newStatus !== "in_progress") {
timestampSets.push("checkout_run_id = NULL");
}
// Returning a task to todo / backlog drops any active-run claim
// as well — heartbeat picks candidate tasks by !activeRunId, so
// leaving a stale pointer here (e.g. after startup recovery of a
// crashed run) silently hides the task from every future wake.
if (newStatus === "todo" || newStatus === "backlog") {
timestampSets.push("active_run_id = NULL");
}
getDb()
.prepare(`UPDATE tasks SET ${timestampSets.join(", ")} WHERE id = ?`)