feat(pr): top-level bounded rework + auto-merge gate + legacy-bypass pin (U6)
Generalizes the foreach-only bounded-rework mechanism to the top-level graph walk so the PR review loop (await-review -> pr-respond -> rework back) is a legal bounded cycle: a kind:rework back-edge to a stacked node returns a ReworkSignal the loop-head re-runs up to maxReworkCycles, then routes outcome:rework-exhausted. Non-rework cycles still throw 'Cycle detected' (safety preserved); foreach rework unchanged (shared core constants). Adds createAutoMergeGateHandler (live entity re-fetch + isPrEntityAutoMergeReady -> auto-on/auto-off). Pins R14: graph-executed PR tasks merge through pr-merge, never the legacy queue. 122 graph tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { WorkflowIrError, getStepParser } from "@fusion/core";
|
||||
import type { TaskDetail, TaskStep, WorkflowIrNode } from "@fusion/core";
|
||||
|
||||
import type { WorkflowNodeHandler, WorkflowNodeResult } from "./workflow-graph-executor.js";
|
||||
import { createPrNodeHandlers, type PrNodeDeps } from "./pr-nodes.js";
|
||||
import { createPrNodeHandlers, createAutoMergeGateHandler, type PrNodeDeps } from "./pr-nodes.js";
|
||||
|
||||
export type WorkflowSeamName = "planning" | "execute" | "review" | "merge" | "schedule" | "step-execute";
|
||||
|
||||
@@ -554,10 +554,20 @@ export function createDefaultNodeHandlers(
|
||||
"pr-respond": async () => ({ outcome: "failure", value: "pr-nodes-unwired" }),
|
||||
"pr-merge": async () => ({ outcome: "failure", value: "pr-nodes-unwired" }),
|
||||
};
|
||||
// Auto-merge gate (U6): a `gate` node carrying `config.gate === "auto-merge"`
|
||||
// routes on live PR-entity state (outcome:auto-on/auto-off) instead of the
|
||||
// generic context/executable gate. Wired only when PR deps are present; absent
|
||||
// them it falls back to the generic gate (fail-closed, no silent auto-merge).
|
||||
const genericGate = createGateHandler(runCustomNode);
|
||||
const autoMergeGate = deps?.prNodes ? createAutoMergeGateHandler(deps.prNodes) : undefined;
|
||||
const gate: WorkflowNodeHandler = autoMergeGate
|
||||
? (node, ctx) =>
|
||||
node.config?.gate === "auto-merge" ? autoMergeGate(node, ctx) : genericGate(node, ctx)
|
||||
: genericGate;
|
||||
return {
|
||||
prompt: promptLike,
|
||||
script: promptLike,
|
||||
gate: createGateHandler(runCustomNode),
|
||||
gate,
|
||||
"step-review": createStepReviewHandler(seams),
|
||||
"parse-steps": parseSteps,
|
||||
code: createCodeNodeHandler(deps?.runCode),
|
||||
|
||||
Reference in New Issue
Block a user