Files
pi-plan/test/judge-args.test.ts
T
wassnameandClaudypoo c0f80b869e v2: delete the parser -- plan.md is for LLMs, the judge subsumes the machinery
The v1 lesson: the parser existed so TypeScript could read goals.md, but every
reader is a model. v2 injects .pi/plan.md verbatim each turn, teaches the format
as a convention, and hands the whole file to the judge, which now does the goal
matching (tolerates wording drift), evidence validation, verify execution, and
format reading that v1 did in code. 1874 -> 530 lines.

Deleted: plan-file.ts + tests, JSON-stream judge transport, custom tool
rendering, review menu + $EDITOR + newSession dance, pruneCompleted, unwired
continuation/loopJudge prompts, MUTATING_BASH_PATTERNS. CompleteGoal's only
write is the ## Log sign-off line (the audit trail); the agent ticks [x] itself.
Judge runs with --no-extensions so a broken global extension can't take down
sign-offs (pi-hermes-memory currently does exactly that). File renamed
goals.md -> plan.md.

UAT (real judge subprocess on a toy repo, /tmp/claude-goals-uat/judge-*.log):
accept with verify run + byte-check, reject on placeholder evidence + missing
file, accept under drifted goal wording.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
2026-07-03 10:24:35 +08:00

32 lines
1.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { buildJudgeArgs } from "../src/index.js";
describe("buildJudgeArgs", () => {
it("omits --model when judgeModel is null (pi uses its configured default; never a pre-emptive 'no model' failure)", () => {
const args = buildJudgeArgs(null);
expect(args).not.toContain("--model");
// an empty --model "" would make every sign-off silently inconclusive -- guard against it
const i = args.indexOf("--model");
expect(i).toBe(-1);
});
it("includes --model <ref> when an explicit/session model is set", () => {
const args = buildJudgeArgs("openrouter/~anthropic/claude-haiku-latest");
const i = args.indexOf("--model");
expect(i).not.toBe(-1);
expect(args[i + 1]).toBe("openrouter/~anthropic/claude-haiku-latest");
});
it("always sets --no-session, --no-extensions, the read-only tool allowlist, and edit/write exclusion", () => {
for (const m of [null, "some/model"]) {
const args = buildJudgeArgs(m);
expect(args).toContain("--no-session");
expect(args).toContain("--no-extensions"); // a broken global extension must not take down sign-offs
expect(args).toContain("--tools");
expect(args.some((a) => a.startsWith("read,bash,grep,find,ls"))).toBe(true);
expect(args).toContain("--exclude-tools");
expect(args.some((a) => a.includes("edit") && a.includes("write"))).toBe(true);
}
});
});