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>
47 lines
1.9 KiB
TypeScript
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;
|
|
}
|