fix(FN-7335): retry active merge pause aborts

This commit is contained in:
gsxdsm
2026-06-30 21:57:13 -07:00
parent a3ad0c8ecf
commit 234248a3cd
3 changed files with 32 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Retry workflow merge-node pause aborts while merge review is active.
category: fix
dev: Treats transient in-review statuses such as reviewing/merging as safe for bounded merge retry.

View File

@@ -127,6 +127,22 @@ describe("merge-node paused-abort retry classification (FN-6735)", () => {
expect(store.updateTask).not.toHaveBeenCalledWith(task.id, expect.objectContaining({ status: "failed" }), undefined);
});
it("retries FN-7335-style merge pause aborts while AI merge review status is active", async () => {
const { store, task, executor, mergeRequester } = makeHarness({ status: "reviewing" });
await invokeGraphFailure(executor, task, "merge");
expect(mergeRequester).toHaveBeenCalledWith(task.id);
const messages = logText(store);
expect(messages).toContain("Workflow graph merge failure at node 'merge' routed to bounded auto-merge retry after benign pause/resume abort");
expect(messages).not.toContain("operator action required");
expect(store.updateTask).not.toHaveBeenCalledWith(
task.id,
expect.objectContaining({ status: "failed" }),
undefined,
);
});
it("parks genuine merge conflicts as terminal instead of retrying forever", async () => {
const { store, task, executor, mergeRequester } = makeHarness();

View File

@@ -7592,6 +7592,14 @@ export class TaskExecutor {
|| normalized.includes("max retries");
}
private isRetryableMergePauseAbortStatus(status: string | null | undefined): boolean {
/*
FNXC:WorkflowMerge 2026-07-01-22:05:
FN-7335 surfaced a merge-node pause/resume abort while the row was legitimately `in-review` with status="reviewing" from the AI merge reviewer. That status is merge activity, not a pre-existing terminal failure; keep the retry classifier strict on real errors while allowing transient merge/review statuses to re-enter bounded merge retry.
*/
return status == null || status === "reviewing" || status === "merging" || status === "merging-pr";
}
private async isRetryableBenignMergePauseAbort(
live: TaskDetail,
result: WorkflowGraphTaskRunResult,
@@ -7605,7 +7613,7 @@ export class TaskExecutor {
if (!pausedAborted) return false;
if (abortProvenance === "global-pause" || live.userPaused === true) return false;
if (abortProvenance === "completion-finalize") return false;
if (live.column !== "in-review" || live.status != null || live.error != null) return false;
if (live.column !== "in-review" || !this.isRetryableMergePauseAbortStatus(live.status) || live.error != null) return false;
if (live.mergeDetails?.mergeConfirmed === true) return false;
if (this.isTerminalMergeGraphFailureValue(this.graphFailureValue(result))) return false;
const failedNode = result.visitedNodeIds[result.visitedNodeIds.length - 1];