fix(FN-000): clear stale queued state on task resume

Resume paths (unpause, drift recovery, engine restart) bypassed the
scheduler's todo->in-progress clear, leaving actively executing tasks
labeled status="queued" with a lingering blockedBy. Broadened
clearResumeFailureState to null both fields alongside the existing
failure cleanup, and added a defensive UI backstop so the "Queued"
badge no longer renders for tasks in the in-progress column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-20 11:28:56 -07:00
parent ee55075440
commit ca6ed92dd1
3 changed files with 26 additions and 4 deletions

View File

@@ -745,8 +745,25 @@ export class TaskExecutor {
}
private async clearResumeFailureState(task: Task): Promise<void> {
const updates: { status?: null; error?: null; blockedBy?: null } = {};
if (task.status === "failed" || task.error) {
await this.store.updateTask(task.id, { status: null, error: null });
updates.status = null;
updates.error = null;
}
// Pre-dispatch gating state must not survive into a resumed in-progress run.
// The scheduler sets status="queued" + blockedBy on dep/file-scope conflicts
// (scheduler.ts:618, 660) and clears them on the todo→in-progress transition
// (scheduler.ts:696). Resume paths (unpause, drift recovery, engine restart)
// bypass that clear, so a task can end up actively executing while still
// labeled "queued" in the UI.
if (task.status === "queued") {
updates.status = null;
}
if (task.blockedBy) {
updates.blockedBy = null;
}
if (Object.keys(updates).length > 0) {
await this.store.updateTask(task.id, updates);
}
}