test: add Zopu integration smoke harness
This commit is contained in:
164
packages/primitives/src/smoke.test.ts
Normal file
164
packages/primitives/src/smoke.test.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { Effect } from "effect";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
SmokeContractError,
|
||||
advanceSmokeLoop,
|
||||
decodeSmokeChatText,
|
||||
decodeSmokeModelCatalog,
|
||||
decodeSmokePlan,
|
||||
decodeSmokeReview,
|
||||
decodeSmokeWorkerReport,
|
||||
initialSmokeLoopState,
|
||||
redactSmokeText,
|
||||
selectSmokeModelRoles,
|
||||
validateSmokeCapabilities,
|
||||
} from "./smoke";
|
||||
|
||||
const validRoleSelection = () => ({
|
||||
plannerReviewerModel: "glm-5.2",
|
||||
plannerReviewerProvider: "cheaptricks",
|
||||
workerModel: "minimax-m3",
|
||||
workerProvider: "cheaptricks",
|
||||
workerToolCallMode: "serial" as const,
|
||||
});
|
||||
|
||||
const run = <A, E>(effect: Effect.Effect<A, E>): A => Effect.runSync(effect);
|
||||
|
||||
describe("smoke primitives", () => {
|
||||
it("selects the planner/reviewer and serial M3 worker roles", () => {
|
||||
const roles = run(selectSmokeModelRoles(validRoleSelection()));
|
||||
|
||||
expect(roles.worker).toMatchObject({
|
||||
model: "minimax-m3",
|
||||
role: "worker",
|
||||
toolCallMode: "serial",
|
||||
});
|
||||
expect(roles.plannerReviewer).toMatchObject({
|
||||
model: "glm-5.2",
|
||||
role: "planner-reviewer",
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects a non-M3 worker or non-GLM planner", () => {
|
||||
const worker = validRoleSelection();
|
||||
worker.workerModel = "glm-5.2";
|
||||
const workerError = run(Effect.flip(selectSmokeModelRoles(worker)));
|
||||
expect(workerError).toBeInstanceOf(SmokeContractError);
|
||||
expect(workerError.reason).toBe("InvalidModelRole");
|
||||
|
||||
const planner = validRoleSelection();
|
||||
planner.plannerReviewerModel = "minimax-m3";
|
||||
const plannerError = run(Effect.flip(selectSmokeModelRoles(planner)));
|
||||
expect(plannerError.reason).toBe("InvalidModelRole");
|
||||
});
|
||||
|
||||
it("advances only through the serial smoke loop", () => {
|
||||
let state = initialSmokeLoopState();
|
||||
state = run(advanceSmokeLoop(state, "preflight-passed"));
|
||||
state = run(advanceSmokeLoop(state, "plan-validated"));
|
||||
state = run(advanceSmokeLoop(state, "worker-succeeded"));
|
||||
state = run(advanceSmokeLoop(state, "review-approved"));
|
||||
|
||||
expect(state.phase).toBe("completed");
|
||||
expect(state.history).toEqual([
|
||||
"preflight",
|
||||
"planning",
|
||||
"worker-running",
|
||||
"reviewing",
|
||||
"completed",
|
||||
]);
|
||||
});
|
||||
|
||||
it("turns contract failures into a terminal state", () => {
|
||||
const state = run(
|
||||
advanceSmokeLoop(
|
||||
initialSmokeLoopState(),
|
||||
"contract-failed",
|
||||
"daemon is offline"
|
||||
)
|
||||
);
|
||||
|
||||
expect(state.phase).toBe("failed");
|
||||
expect(state.lastError).toBe("daemon is offline");
|
||||
});
|
||||
|
||||
it("rejects out-of-order loop transitions", () => {
|
||||
const error = run(
|
||||
Effect.flip(advanceSmokeLoop(initialSmokeLoopState(), "review-approved"))
|
||||
);
|
||||
|
||||
expect(error).toBeInstanceOf(SmokeContractError);
|
||||
expect(error.reason).toBe("InvalidTransition");
|
||||
});
|
||||
|
||||
it("validates model reports at the primitive boundary", () => {
|
||||
const plan = run(
|
||||
decodeSmokePlan({
|
||||
acceptanceCriteria: ["The button renders"],
|
||||
nonGoals: [],
|
||||
steps: ["Add the button", "Run the web check"],
|
||||
summary: "Add a small button to the disposable project",
|
||||
})
|
||||
);
|
||||
const worker = run(
|
||||
decodeSmokeWorkerReport({
|
||||
status: "completed",
|
||||
summary: "Changed the project and ran the targeted check.",
|
||||
})
|
||||
);
|
||||
const review = run(
|
||||
decodeSmokeReview({
|
||||
approved: true,
|
||||
findings: [],
|
||||
summary: "The change matches the acceptance criteria.",
|
||||
})
|
||||
);
|
||||
|
||||
expect(plan.steps).toHaveLength(2);
|
||||
expect(worker.status).toBe("completed");
|
||||
expect(review.approved).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects empty or malformed model output", () => {
|
||||
const empty = run(
|
||||
Effect.flip(
|
||||
decodeSmokeChatText({ choices: [{ message: { content: " " } }] })
|
||||
)
|
||||
);
|
||||
expect(empty.reason).toBe("InvalidModelResponse");
|
||||
|
||||
const malformed = run(Effect.flip(decodeSmokeReview({ approved: true })));
|
||||
expect(malformed.reason).toBe("InvalidReport");
|
||||
});
|
||||
|
||||
it("validates the canonical CPA model catalog", () => {
|
||||
const catalog = run(
|
||||
decodeSmokeModelCatalog({
|
||||
data: [{ id: "minimax-m3" }, { id: "glm-5.2" }],
|
||||
})
|
||||
);
|
||||
|
||||
expect(catalog.data.map(({ id }) => id)).toEqual(["minimax-m3", "glm-5.2"]);
|
||||
});
|
||||
|
||||
it("fails a capability report when any required check fails", () => {
|
||||
const error = run(
|
||||
Effect.flip(
|
||||
validateSmokeCapabilities([
|
||||
{ id: "web", message: "ready", passed: true },
|
||||
{ id: "daemon", message: "daemon is offline", passed: false },
|
||||
])
|
||||
)
|
||||
);
|
||||
|
||||
expect(error.reason).toBe("InvalidReport");
|
||||
expect(error.message).toContain("daemon is offline");
|
||||
});
|
||||
|
||||
it("redacts secrets without changing unrelated text", () => {
|
||||
expect(
|
||||
redactSmokeText("status token=secret-key endpoint=ok", ["secret-key"])
|
||||
).toBe("status token=[REDACTED] endpoint=ok");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user