fix(FN-1256): auto-recover tasks with all steps done but no task_done call

When context overflow or compaction causes an agent to lose awareness of
the task_done tool, the executor now checks if all steps are complete
before failing — treating it as an implicit task_done. Also adds
self-healing recovery for tasks that already slipped through as
misclassified failures in in-review.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-08 22:12:53 -07:00
parent f478876ee8
commit 6250cf4efb
3 changed files with 164 additions and 0 deletions

View File

@@ -1279,6 +1279,19 @@ export class TaskExecutor {
return;
}
// If the agent didn't explicitly call task_done, check whether
// all steps are already complete — treat as implicit done to avoid
// unnecessary retry sessions for context-overflow / compaction cases.
if (!taskDone) {
const implicitCheck = await this.store.getTask(task.id);
if (implicitCheck.steps.length > 0 &&
implicitCheck.steps.every((s) => s.status === "done" || s.status === "skipped")) {
taskDone = true;
executorLog.log(`${task.id} all steps done — treating as implicit task_done`);
await this.store.logEntry(task.id, "All steps complete — implicit task_done (agent did not call tool explicitly)");
}
}
if (taskDone) {
// Capture modified files before running workflow steps
const updatedTask = await this.store.getTask(task.id);
@@ -1357,6 +1370,20 @@ export class TaskExecutor {
await promptWithFallback(retrySession, retryPrompt);
checkSessionError(retrySession);
// If the agent didn't explicitly call task_done, check whether
// all steps are already complete — if so, treat as implicit done.
// This handles context-overflow / compaction scenarios where the
// agent lost awareness of the task_done tool but finished the work.
if (!taskDone) {
const implicitCheck = await this.store.getTask(task.id);
if (implicitCheck.steps.length > 0 &&
implicitCheck.steps.every((s) => s.status === "done" || s.status === "skipped")) {
taskDone = true;
executorLog.log(`${task.id} all steps done — treating as implicit task_done`);
await this.store.logEntry(task.id, "All steps complete — implicit task_done (agent did not call tool explicitly)");
}
}
if (taskDone) {
const updatedTask = await this.store.getTask(task.id);
const modifiedFiles = this.captureModifiedFiles(worktreePath, updatedTask.baseCommitSha);