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:
@@ -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");
|
||||
});
|
||||
});
|
||||
60
packages/core/src/builtin-coding-workflow-ir.ts
Normal file
60
packages/core/src/builtin-coding-workflow-ir.ts
Normal 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));
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user