Files
oh-my-pi/packages/coding-agent/test/tools/review.test.ts
T
2026-05-25 18:01:45 +00:00

135 lines
3.6 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import { finalizeSubprocessOutput } from "../../src/task/executor";
import { subprocessToolRegistry } from "../../src/task/subprocess-tool-registry";
import { parseReportFindingDetails, toReviewFinding } from "../../src/tools/review";
describe("report_finding subprocess extraction", () => {
it("returns undefined for malformed finding details", () => {
expect(parseReportFindingDetails({})).toBeUndefined();
expect(
parseReportFindingDetails({
title: "[P1] Missing file path",
body: "Body",
priority: "P1",
confidence: 0.8,
line_start: 12,
line_end: 12,
}),
).toBeUndefined();
});
it("ignores error events and extracts valid details", () => {
const handler = subprocessToolRegistry.getHandler("report_finding");
if (!handler?.extractData) {
throw new Error("report_finding handler is not registered");
}
const validDetails = {
title: "[P1] Example finding",
body: "Details",
priority: "P1" as const,
confidence: 0.95,
file_path: "/tmp/example.ts",
line_start: 10,
line_end: 12,
};
expect(
handler.extractData({
toolName: "report_finding",
toolCallId: "call-1",
result: {
content: [{ type: "text", text: "Finding recorded" }],
details: validDetails,
},
isError: false,
}),
).toEqual(validDetails);
expect(
handler.extractData({
toolName: "report_finding",
toolCallId: "call-2",
result: {
content: [{ type: "text", text: "Validation failed" }],
details: {},
},
isError: true,
}),
).toBeUndefined();
});
});
describe("toReviewFinding", () => {
const base = {
title: "[P0] Example finding",
body: "Details",
confidence: 0.95,
file_path: "/tmp/example.ts",
line_start: 10,
line_end: 12,
} as const;
it("maps the priority string enum to its numeric ordinal", () => {
expect(toReviewFinding({ ...base, priority: "P0" }).priority).toBe(0);
expect(toReviewFinding({ ...base, priority: "P1" }).priority).toBe(1);
expect(toReviewFinding({ ...base, priority: "P2" }).priority).toBe(2);
expect(toReviewFinding({ ...base, priority: "P3" }).priority).toBe(3);
});
it("passes JTD validation against the reviewer agent's numeric priority schema (#1350)", () => {
// Mirrors the bundled reviewer agent's output schema. Before the fix the
// string priority from `report_finding` short-circuited every successful
// review run with `findings.0.priority: expected number, received string`.
const reviewerSchema = {
properties: {
overall_correctness: { enum: ["correct", "incorrect"] },
explanation: { type: "string" },
confidence: { type: "number" },
},
optionalProperties: {
findings: {
elements: {
properties: {
title: { type: "string" },
body: { type: "string" },
priority: { type: "number" },
confidence: { type: "number" },
file_path: { type: "string" },
line_start: { type: "number" },
line_end: { type: "number" },
},
},
},
},
};
const result = finalizeSubprocessOutput({
rawOutput: "",
exitCode: 0,
stderr: "",
doneAborted: false,
signalAborted: false,
yieldItems: [
{
status: "success",
data: {
overall_correctness: "incorrect",
explanation: "Found one bug",
confidence: 0.9,
},
},
],
reportFindings: [toReviewFinding({ ...base, priority: "P2" })],
outputSchema: reviewerSchema,
});
expect(result.exitCode).toBe(0);
expect(result.stderr).toBe("");
const parsed = JSON.parse(result.rawOutput) as {
findings: Array<{ priority: number }>;
};
expect(parsed.findings[0].priority).toBe(2);
});
});