Complete Phase 3 interpreter parity by routing workflow graph execution through legacy seam handlers. - Simplify workflow IR schema and built-in coding workflow to seam-based v1 nodes/edges. - Add workflow node handler layer with default legacy seam adapters and dedicated handler/parity tests. - Update engine exports/executor behavior for conditional traversal, retries, outcome context, and parity assertions. - Refresh core workflow IR tests/coverage for the new shape (including seam-stage expectations without triage) and remove obsolete schema fixture test. Files changed: .changeset/fn-5767-interpreter-parity.md | 5 + .github/actions/setup-node-pnpm/action.yml | 41 +--- docs/workflow-steps.md | 17 ++ .../__tests__/builtin-coding-workflow-ir.test.ts | 25 +-- packages/core/src/__tests__/workflow-ir.test.ts | 70 ------ packages/core/src/builtin-coding-workflow-ir.ts | 71 ++---- packages/core/src/index.ts | 31 +-- packages/core/src/workflow-ir-types.ts | 91 +------- packages/core/src/workflow-ir.ts | 246 ++------------------- .../workflow-graph-executor-handlers.test.ts | 201 +++++++++++++++++ .../workflow-graph-executor-parity.test.ts | 126 ++++++++--- .../src/__tests__/workflow-node-handlers.test.ts | 50 +++++ packages/engine/src/index.ts | 16 +- packages/engine/src/workflow-graph-executor.ts | 205 ++++++++++++----- packages/engine/src/workflow-node-handlers.ts | 56 +++++ 15 files changed, 661 insertions(+), 590 deletions(-) Fusion-Task-Id: FN-5767 Fusion-Task-Lineage: 0c68586e-2709-4521-a2ce-938ba1006ae0
57 lines
2.1 KiB
TypeScript
57 lines
2.1 KiB
TypeScript
import { WorkflowIrError } from "@fusion/core";
|
|
import type { TaskDetail } from "@fusion/core";
|
|
|
|
import type { WorkflowNodeHandler, WorkflowNodeResult } from "./workflow-graph-executor.js";
|
|
|
|
export type WorkflowSeamName = "execute" | "review" | "merge" | "schedule";
|
|
|
|
export interface WorkflowLegacySeams {
|
|
execute: (task: TaskDetail, context: Record<string, unknown>) => Promise<WorkflowNodeResult>;
|
|
review: (task: TaskDetail, context: Record<string, unknown>) => Promise<WorkflowNodeResult>;
|
|
merge: (task: TaskDetail, context: Record<string, unknown>) => Promise<WorkflowNodeResult>;
|
|
schedule: (task: TaskDetail, context: Record<string, unknown>) => Promise<WorkflowNodeResult>;
|
|
}
|
|
|
|
function resolveSeam(node: { config?: Record<string, unknown> }): WorkflowSeamName {
|
|
const seam = node.config?.seam;
|
|
if (seam === "execute" || seam === "review" || seam === "merge" || seam === "schedule") {
|
|
return seam;
|
|
}
|
|
throw new WorkflowIrError(`Unsupported workflow seam: ${String(seam)}`);
|
|
}
|
|
|
|
export function createPromptLikeHandler(seams: WorkflowLegacySeams): WorkflowNodeHandler {
|
|
return async (node, context) => {
|
|
const seam = resolveSeam(node);
|
|
return seams[seam](context.task, context.context);
|
|
};
|
|
}
|
|
|
|
export const gateNodeHandler: WorkflowNodeHandler = async (node, context) => {
|
|
const expected = node.config?.expect;
|
|
const actual = context.context[String(node.config?.contextKey ?? "outcome")];
|
|
if (typeof expected === "string" && actual !== expected) {
|
|
return { outcome: "failure", value: "gate-mismatch" };
|
|
}
|
|
return { outcome: "success" };
|
|
};
|
|
|
|
export function createDefaultNodeHandlers(seams: WorkflowLegacySeams): Record<"prompt" | "script" | "gate", WorkflowNodeHandler> {
|
|
const promptLike = createPromptLikeHandler(seams);
|
|
return {
|
|
prompt: promptLike,
|
|
script: promptLike,
|
|
gate: gateNodeHandler,
|
|
};
|
|
}
|
|
|
|
export function createNoopLegacySeams(): WorkflowLegacySeams {
|
|
const success = async (): Promise<WorkflowNodeResult> => ({ outcome: "success" });
|
|
return {
|
|
execute: success,
|
|
review: success,
|
|
merge: success,
|
|
schedule: success,
|
|
};
|
|
}
|