Files
fusion/packages/engine/src/workflow-node-execution-needs.ts
gsxdsm dc7bb40948 FN-7990: share worktree classifier so Code Review acquires a worktree
Unify write-capability classification so graph preparation acquires a worktree for inline-fix Code Review before runtime runs, eliminating the immediate no-worktree-for-write-node failure.

- Add shared workflowNodeRequiresWorktree helper for preparation and runtime
- Plumb optional-group context and reviewerInlineFixes into graph preparation
- Acquire/reuse/reacquire worktrees for write-capable inline review nodes
- Keep Plan Review and disabled inline fixes read-only
- Add regression tests and a patch changeset

Files changed:
 .changeset/fn-7990-code-review-worktree.md         |  7 ++
 .../__tests__/ce-workflow-step-executor.test.ts    | 97 ++++++++++++++++++++++
 .../workflow-node-execution-needs.test.ts          | 47 +++++++++++
 packages/engine/src/executor.ts                    | 32 +++----
 packages/engine/src/workflow-graph-executor.ts     | 52 ++++++++----
 .../engine/src/workflow-node-execution-needs.ts    | 46 ++++++++++
 6 files changed, 243 insertions(+), 38 deletions(-)

Fusion-Task-Id: FN-7990

Fusion-Task-Lineage: f5d19181-0b98-4827-8adb-069f7dc05c03

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-15 15:34:43 -07:00

47 lines
1.9 KiB
TypeScript

import type { WorkflowIrNode } from "@fusion/core";
export interface WorkflowNodeExecutionNeedsOptions {
optionalGroupId?: string;
/** Inline review fixes are enabled unless settings explicitly disable them. */
reviewerInlineFixes?: boolean;
}
/**
* FNXC:WorkflowExecution 2026-07-15-00:00:
* Issue #2075 exposed divergent worktree classifiers: graph preparation treated
* inline-fix reviews as read-only while runtime rejected them without a worktree.
* This pure helper is the single source of truth for write-capable workflow nodes;
* preparation and runtime must both use it before selecting an execution target.
*/
export function workflowNodeRequiresWorktree(
node: WorkflowIrNode,
{ optionalGroupId, reviewerInlineFixes }: WorkflowNodeExecutionNeedsOptions = {},
): boolean {
const cfg = node.config ?? {};
const executorKind = typeof cfg.executor === "string" ? cfg.executor : "model";
const scriptName = typeof cfg.scriptName === "string" && cfg.scriptName.trim()
? cfg.scriptName
: undefined;
const rawCliCommand = executorKind === "cli" && typeof cfg.cliCommand === "string" && cfg.cliCommand.trim()
? cfg.cliCommand
: undefined;
const nodeName = typeof cfg.name === "string" && cfg.name.trim() ? cfg.name.trim() : node.id;
const isPlanReview = node.id === "plan-review-step" || nodeName === "Plan Review" || optionalGroupId === "plan-review";
const isInlineFixReview = reviewerInlineFixes !== false
&& executorKind !== "cli"
&& !isPlanReview
&& (
cfg.reviewCanFixInline === true
|| /(?:^|\b)(?:review|verification)(?:\b|$)/i.test(nodeName)
|| optionalGroupId === "code-review"
|| optionalGroupId === "browser-verification"
);
return cfg.toolMode === "coding"
|| node.kind === "script"
|| executorKind === "cli-agent"
|| Boolean(scriptName)
|| Boolean(rawCliCommand)
|| isInlineFixReview;
}