fix(FN-7224): clear workflow pins on retry

Fusion-Task-Id: FN-7224
This commit is contained in:
gsxdsm
2026-06-29 02:12:25 -07:00
parent c93217dee0
commit 7cd5552f76
3 changed files with 23 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Make dashboard retry clear stale workflow step pins before re-execution.
category: fix
dev: Clears persisted workflow step instances on manual execution retry so parse-steps can repin the current plan.

View File

@@ -216,6 +216,7 @@ function createMockStore(overrides: Partial<TaskStore> = {}): TaskStore {
getWorkflowStep: vi.fn(),
updateWorkflowStep: vi.fn(),
deleteWorkflowStep: vi.fn(),
clearWorkflowRunStepInstances: vi.fn(),
getMissionStore: vi.fn().mockReturnValue({
listMissions: vi.fn().mockReturnValue([]),
createMission: vi.fn(),
@@ -808,6 +809,7 @@ describe("POST /tasks/:id/retry", () => {
baseCommitSha: null,
...buildManualRetryResetPatch({ resetMergeRetries: true }),
});
expect(store.clearWorkflowRunStepInstances).toHaveBeenCalledWith("KB-001");
expect(store.moveTask).toHaveBeenCalledWith("KB-001", "todo");
});
@@ -896,6 +898,7 @@ describe("POST /tasks/:id/retry", () => {
error: null,
...buildManualRetryResetPatch(),
});
expect(store.clearWorkflowRunStepInstances).toHaveBeenCalledWith("KB-001");
expect(store.moveTask).toHaveBeenCalledWith("KB-001", "todo", { preserveProgress: true });
expect(store.logEntry).toHaveBeenCalledWith(
"KB-001",
@@ -927,6 +930,7 @@ describe("POST /tasks/:id/retry", () => {
error: null,
...buildManualRetryResetPatch(),
});
expect(store.clearWorkflowRunStepInstances).toHaveBeenCalledWith("KB-001");
expect(store.moveTask).toHaveBeenCalledWith("KB-001", "todo", { preserveProgress: true });
expect(store.logEntry).toHaveBeenCalledWith(
"KB-001",
@@ -963,6 +967,7 @@ describe("POST /tasks/:id/retry", () => {
error: null,
...buildManualRetryResetPatch(),
});
expect(store.clearWorkflowRunStepInstances).toHaveBeenCalledWith("KB-001");
expect(store.moveTask).toHaveBeenCalledWith("KB-001", "todo", { preserveProgress: true });
expect(store.logEntry).toHaveBeenCalledWith(
"KB-001",

View File

@@ -1683,6 +1683,11 @@ export function registerTaskWorkflowRoutes(ctx: ApiRoutesContext, deps: TaskWork
// and merge failures (all steps done).
if (isInReviewRetry) {
if (isExecutionFailureInReview) {
/*
FNXC:WorkflowRetry 2026-06-29-02:18:
Dashboard retry for an in-review execution failure re-enters the workflow graph from parse/execution, so it must clear persisted foreach step-instance pins. Otherwise a stale pin from the failed run makes the retry hit the same parse pin-mismatch immediately.
*/
clearRebuiltSpecWorkflowPins(scopedStore, req.params.id);
await scopedStore.updateTask(req.params.id, {
status: null,
error: null,
@@ -1734,6 +1739,12 @@ export function registerTaskWorkflowRoutes(ctx: ApiRoutesContext, deps: TaskWork
return;
}
/*
FNXC:WorkflowRetry 2026-06-29-02:18:
Non-planning manual retry is also a fresh execution boundary. Clear graph step-instance rows before moving back to todo so parse-steps can repin the current PROMPT.md instead of inheriting failed foreach state.
*/
clearRebuiltSpecWorkflowPins(scopedStore, req.params.id);
// Reset steps if the branch has no unique commits (work was lost with worktree)
const completedSteps = task.steps.filter(
(s: { status: string }) => s.status === "done" || s.status === "in-progress",