feat(FN-1854): send tasks back to in-progress when verification fails

- Add sendTaskBackForFix() method that encapsulates the 'verification failed
  — send back to in-progress' pattern
- Replace all 4 hard failure locations with sendTaskBackForFix() calls
- Update failure feedback template to mention 'sent back to in-progress'
- Update test assertions for workflow step failure cases
- Rename test that verifies passing workflow step behavior
- Add new test for verification failure send-back flow
- Add addTaskComment mock to store factories for testing

The task executor now sends tasks back to in-progress (instead of 'in-review'
with 'failed' status) when workflow step verification fails and retries are
exhausted. This allows the executor to attempt to fix the issues on the
next pass, mirroring the existing deterministic verification failure behavior
in project-engine.ts.
This commit is contained in:
Fusion
2026-04-15 08:28:51 -07:00
committed by gsxdsm
parent ed35b494fe
commit 8b631a98df
3 changed files with 249 additions and 57 deletions

View File

@@ -133,6 +133,7 @@ function createMockStore(overrides: Record<string, any> = {}) {
return makeTask(id, col);
}),
logEntry: vi.fn().mockResolvedValue(undefined),
addTaskComment: vi.fn().mockResolvedValue(undefined),
appendAgentLog: vi.fn().mockResolvedValue(undefined),
parseStepsFromPrompt: vi.fn().mockResolvedValue([]),
parseFileScopeFromPrompt: vi.fn().mockResolvedValue([]),
@@ -498,15 +499,39 @@ describe("In-progress task resume after restart", () => {
return "" as any;
});
// Use fake timers to control the setTimeout in sendTaskBackForFix
vi.useFakeTimers();
const executor = new TaskExecutor(store, "/tmp/test");
const recovered = await executor.recoverCompletedTask(task);
expect(recovered).toBe(true);
// Task should be cleared and reset for retry (not failed + in-review)
expect(store.updateTask).toHaveBeenCalledWith("FN-963", {
status: "failed",
error: "Workflow step failed during recovery",
status: null,
error: null,
sessionFile: null,
workflowStepRetries: 0,
});
expect(store.moveTask).toHaveBeenCalledWith("FN-963", "in-review");
// Should add a comment with failure feedback
expect(store.addTaskComment).toHaveBeenCalledWith(
"FN-963",
expect.stringContaining("Workflow step failed during recovery"),
"agent",
);
// Should reset all steps to pending
expect(store.updateStep).toHaveBeenCalledWith("FN-963", 0, "pending");
// Advance timers to trigger the setTimeout that moves task to todo then in-progress
vi.advanceTimersByTime(0);
// Run any pending microtasks (the async code in setTimeout)
await vi.runAllTimersAsync();
// Task should move to todo then in-progress (not in-review)
expect(store.moveTask).toHaveBeenCalledWith("FN-963", "todo");
expect(store.moveTask).toHaveBeenCalledWith("FN-963", "in-progress");
vi.useRealTimers();
});
});