feat(tasks): enforce dynamic execution plans
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import { createExecutionPlanSnapshot, executionPlanNeedsTaskPublish, executionPlanSchema, readExecutionPlans } from "../../src/routes/executionPlan.js";
|
||||
import { createExecutionPlanSnapshot, executionPlanNeedsTaskPublish, executionPlanSchema, newExecutionPlanSchema, readExecutionPlans } from "../../src/routes/executionPlan.js";
|
||||
import { streamPromptResponse } from "../../src/routes/chatStream.js";
|
||||
import type { OpencodeRuntimeAdapter } from "../../src/runtime/opencode.js";
|
||||
|
||||
@@ -13,6 +13,38 @@ const plan = {
|
||||
};
|
||||
|
||||
describe("execution plans", () => {
|
||||
it("requires v2 for newly published task plans while retaining legacy reads", () => {
|
||||
const legacy = {
|
||||
title: "Legacy plan",
|
||||
reason: "Stored before graph plans",
|
||||
nodes: [{ id: "inspect", title: "Inspect", status: "pending", owner: "agent", detail: "", evidence: [] }],
|
||||
edges: [],
|
||||
};
|
||||
|
||||
expect(executionPlanSchema.parse(legacy).schema).toBe("execution-plan@1");
|
||||
expect(newExecutionPlanSchema.safeParse(legacy).success).toBe(false);
|
||||
});
|
||||
|
||||
it("accepts explicit v2 branches and structural joins without invented evidence", () => {
|
||||
const v2 = {
|
||||
schema: "execution-plan@2", title: "动态调查", reason: "工单请求现场及数据并行核验",
|
||||
nodes: [
|
||||
{ id: "split", title: "并行启动", status: "completed", owner: "agent", detail: "同时核查", evidence: [], kind: "parallel_split" },
|
||||
{ id: "field", title: "现场采样", status: "waiting", owner: "human", detail: "等待采样", evidence: [], kind: "activity" },
|
||||
{ id: "data", title: "监测数据", status: "completed", owner: "agent", detail: "已核对", evidence: ["e-1"], kind: "activity" },
|
||||
{ id: "join", title: "证据汇合", status: "waiting", owner: "agent", detail: "等待现场", evidence: [], kind: "parallel_join" },
|
||||
],
|
||||
edges: [
|
||||
{ id: "field-route", from: "split", to: "field", label: "现场" },
|
||||
{ id: "data-route", from: "split", to: "data", label: "数据" },
|
||||
{ id: "field-join", from: "field", to: "join", label: "" },
|
||||
{ id: "data-join", from: "data", to: "join", label: "" },
|
||||
],
|
||||
};
|
||||
const parsed = executionPlanSchema.parse(v2);
|
||||
expect(createExecutionPlanSnapshot(parsed, [], "session-1").schema_version).toBe("execution-plan@2");
|
||||
expect(executionPlanSchema.safeParse({ ...v2, edges: [{ ...v2.edges[0], id: "data-route" }, ...v2.edges.slice(1)] }).success).toBe(false);
|
||||
});
|
||||
it("rejects missing dependencies, cycles, duplicate IDs and unsupported completion", () => {
|
||||
for (const invalid of [
|
||||
{ ...plan, edges: [{ from: "unknown", to: "sample", label: "" }] },
|
||||
|
||||
Reference in New Issue
Block a user