syntaxai/tdd.md · main · src / c14_judge.test.ts
// Sibling test for c32_judge.ts. The orchestrator itself (judge()) does
// git clone + test execution and isn't unit-testable without a real
// agent repo; the pure helpers underneath it (applyMode, explainRefactor)
// are the structural surface that matters for scoring decisions. Cover
// the mode-aware penalty math + the operator-facing explanations here.
import { describe, test, expect } from "bun:test";
import { applyMode, explainRefactor, judge } from "./c14_judge.ts";
describe("c32_judge — applyMode (mode-aware penalty math)", () => {
test("positive deltas pass through unchanged in every mode", () => {
expect(applyMode(10, "strict")).toBe(10);
expect(applyMode(10, "pragmatic")).toBe(10);
expect(applyMode(10, "learning")).toBe(10);
});
test("strict mode keeps the full negative penalty", () => {
expect(applyMode(-20, "strict")).toBe(-20);
expect(applyMode(-5, "strict")).toBe(-5);
});
test("pragmatic mode halves negative deltas (Math.ceil — never below half)", () => {
expect(applyMode(-20, "pragmatic")).toBe(-10);
expect(applyMode(-10, "pragmatic")).toBe(-5);
// -5 / 2 = -2.5 → Math.ceil(-2.5) = -2: the harsher half rounds up
// toward zero, which is the documented "softer score" behaviour.
expect(applyMode(-5, "pragmatic")).toBe(-2);
});
test("learning mode zeroes out every negative delta", () => {
expect(applyMode(-20, "learning")).toBe(0);
expect(applyMode(-5, "learning")).toBe(0);
expect(applyMode(-1, "learning")).toBe(0);
});
test("zero delta is neutral in every mode", () => {
expect(applyMode(0, "strict")).toBe(0);
expect(applyMode(0, "pragmatic")).toBe(0);
expect(applyMode(0, "learning")).toBe(0);
});
});
describe("c32_judge — explainRefactor", () => {
test("passed=true returns the canonical-refactor explanation", () => {
const s = explainRefactor(true);
expect(s).toContain("stayed green");
expect(s).toMatch(/canonical/i);
});
test("passed=false returns guidance to revert or open a new red→green", () => {
const s = explainRefactor(false);
expect(s).toContain("broke");
expect(s).toMatch(/revert|red→green/);
});
test("the two branches return different strings", () => {
expect(explainRefactor(true)).not.toBe(explainRefactor(false));
});
});
describe("c32_judge — orchestrator entry point", () => {
test("judge is exported as an async function (Promise-returning)", () => {
expect(typeof judge).toBe("function");
// The orchestrator does git clone + test execution; covering it
// end-to-end needs a real agent repo. A type-level check that the
// shape didn't drift is the documented minimum for this layer.
expect(judge.length).toBe(2);
});
});