FN-5766: add flagged-off workflow graph executor scaffold

Add the Phase 2 workflow-graph interpreter scaffold and builtin coding IR wiring while keeping execution behavior unchanged by default.

- add BUILTIN_CODING_WORKFLOW_IR and builder in @fusion/core with coverage tests
- export new coding workflow IR APIs from core index
- add WorkflowGraphExecutor scaffold in @fusion/engine plus parity-focused test coverage
- document the flagged-off interpreter scaffold, parity gate, and v1 IR gap reconciliation in workflow docs
- include a changeset for published @runfusion/fusion

Files changed:
 .../fn-5766-workflow-graph-executor-scaffold.md    | 11 +++
 docs/workflow-steps.md                             | 27 +++++++
 .../__tests__/builtin-coding-workflow-ir.test.ts   | 34 +++++++++
 packages/core/src/builtin-coding-workflow-ir.ts    | 60 ++++++++++++++++
 packages/core/src/index.ts                         |  4 ++
 .../workflow-graph-executor-parity.test.ts         | 32 +++++++++
 packages/engine/src/index.ts                       |  7 ++
 packages/engine/src/workflow-graph-executor.ts     | 82 ++++++++++++++++++++++
 8 files changed, 257 insertions(+)

Fusion-Task-Id: FN-5766
Fusion-Task-Lineage: 4bbef713-a415-4d42-a20b-9ae4f3235419
This commit is contained in:
gsxdsm
2026-05-31 04:47:42 -07:00
parent 3d22a98cf2
commit 1edbb54fce
8 changed files with 257 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
import { describe, expect, it } from "vitest";
import {
BUILTIN_CODING_WORKFLOW_IR,
WORKFLOW_IR_SCHEMA_VERSION,
buildBuiltinCodingWorkflowIr,
parseWorkflowIr,
serializeWorkflowIr,
} from "../index.js";
describe("builtin coding workflow ir", () => {
it("parses and round-trips", () => {
const parsed = parseWorkflowIr(BUILTIN_CODING_WORKFLOW_IR);
const reparsed = parseWorkflowIr(serializeWorkflowIr(parsed));
expect(reparsed).toEqual(parsed);
expect(parsed.schemaVersion).toBe(WORKFLOW_IR_SCHEMA_VERSION);
});
it("contains exactly one start and one end node", () => {
const nodes = BUILTIN_CODING_WORKFLOW_IR.nodes;
expect(nodes.filter((node) => node.kind === "start")).toHaveLength(1);
expect(nodes.filter((node) => node.kind === "end")).toHaveLength(1);
});
it("exposes coding lifecycle stages", () => {
const stageNodes = BUILTIN_CODING_WORKFLOW_IR.nodes.filter((node) => node.config?.stage);
const stages = stageNodes.map((node) => String(node.config?.stage));
expect(stages).toEqual(expect.arrayContaining(["triage", "execute", "review", "merge"]));
});
it("builder returns parser-validated ir", () => {
const built = buildBuiltinCodingWorkflowIr();
expect(built.metadata.name).toContain("Coding Lifecycle");
});
});

View File

@@ -0,0 +1,60 @@
import { parseWorkflowIr, serializeWorkflowIr } from "./workflow-ir.js";
import { WORKFLOW_IR_SCHEMA_VERSION, type WorkflowIr } from "./workflow-ir-types.js";
/**
* Built-in coding lifecycle workflow encoded in v1 Workflow IR.
*
* Mapping notes:
* - Legacy "agent-call" semantics are represented by `prompt` nodes with `config.agentRole`.
* - Typed edge semantics are represented via `edge.condition` tokens.
*/
export const BUILTIN_CODING_WORKFLOW_IR: WorkflowIr = {
schemaVersion: WORKFLOW_IR_SCHEMA_VERSION,
metadata: {
name: "Built-in Coding Lifecycle Workflow",
description: "Legacy authoritative coding lifecycle encoded as v1 IR scaffold.",
createdAt: "2026-05-31T00:00:00.000Z",
templateId: "builtin-coding-lifecycle-v1",
},
nodes: [
{ id: "node-start", kind: "start", label: "Start" },
{
id: "node-triage",
kind: "prompt",
label: "Triage",
config: { stage: "triage", agentRole: "triage", legacySeam: "triage" },
},
{
id: "node-execute",
kind: "prompt",
label: "Execute",
config: { stage: "execute", agentRole: "executor", legacySeam: "executor" },
},
{
id: "node-review",
kind: "gate",
label: "Review",
config: { stage: "review", gateMode: "approval", legacySeam: "reviewer" },
},
{
id: "node-merge",
kind: "script",
label: "Merge",
config: { stage: "merge", script: "legacy-merger", legacySeam: "merger" },
},
{ id: "node-end", kind: "end", label: "End" },
],
edges: [
{ id: "edge-start-triage", from: "node-start", to: "node-triage" },
{ id: "edge-triage-execute", from: "node-triage", to: "node-execute", condition: "success" },
{ id: "edge-execute-review", from: "node-execute", to: "node-review", condition: "success" },
{ id: "edge-review-merge", from: "node-review", to: "node-merge", condition: "approved" },
{ id: "edge-review-execute", from: "node-review", to: "node-execute", condition: "revise" },
{ id: "edge-merge-end", from: "node-merge", to: "node-end", condition: "success" },
],
};
/** Ensure built-in IR remains parser-valid and serializable. */
export function buildBuiltinCodingWorkflowIr(): WorkflowIr {
return parseWorkflowIr(serializeWorkflowIr(BUILTIN_CODING_WORKFLOW_IR));
}

View File

@@ -16,6 +16,10 @@ export {
WorkflowIrError,
BUILTIN_WORKFLOW_IR_FIXTURE,
} from "./workflow-ir.js";
export {
BUILTIN_CODING_WORKFLOW_IR,
buildBuiltinCodingWorkflowIr,
} from "./builtin-coding-workflow-ir.js";
export { customProviderRegistryKey } from "./custom-provider-key.js";
export { MOCK_PROVIDER_ID } from "./mock-provider-constants.js";
export type { MockProviderId, MockSessionPurpose } from "./mock-provider-constants.js";