fix(FN-2054): harden agent loop stuck-detection and self-healing

- Add defensive cleanup for in-memory task tracking when tasks move state or agents pause
- Improve stuck-detection and self-healing flow to reduce leaked state and missed recovery paths
- Add logging around previously swallowed errors and tighten executor cleanup behavior
- Expand restart and self-healing reliability tests to cover regression scenarios
This commit is contained in:
Fusion
2026-04-18 11:08:41 -07:00
committed by gsxdsm
parent eb04fd148d
commit 3977b38895
8 changed files with 290 additions and 91 deletions

View File

@@ -670,6 +670,21 @@ export class Scheduler {
reservedWorktreeNames,
);
// Compare-and-swap: re-read the task to verify it's still in "todo" before dispatching.
// This prevents dispatching a task twice if another schedule() call or user action
// moved it away from "todo" between our initial snapshot and this dispatch attempt.
// The re-entrance guard prevents overlapping schedule() passes, but external events
// (user moves, API calls) can still trigger concurrent state changes.
const freshTask = await this.store.getTask(task.id);
if (!freshTask || freshTask.column !== "todo") {
schedulerLog.log(`Task ${task.id} no longer in "todo" (column=${freshTask?.column ?? "N/A"}) — skipping dispatch`);
continue;
}
if (freshTask.paused) {
schedulerLog.log(`Task ${task.id} is paused — skipping dispatch`);
continue;
}
// Clear status, reserve worktree path, and then move to in-progress
schedulerLog.log(`Starting ${task.id}: ${task.title || task.id} (deps satisfied)`);
await this.store.updateTask(task.id, {