import assert from "node:assert/strict"; import { mkdir, mkdtemp, readFile, rm, symlink, writeFile } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { after, test } from "node:test"; import { fileURLToPath } from "node:url"; import { checkCase, diskStore, formatSpecialization, localSandboxes, machine, scriptedHarness, splitCases, type CaseDraft, type HarnessRequest } from "../src/index.ts"; import { parseCases, parseDesign } from "../src/specialize.ts"; const repo = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const dirs: string[] = []; after(() => Promise.all(dirs.map((d) => rm(d, { recursive: true, force: true })))); async function tempDir() { const dir = await mkdtemp(path.join(os.tmpdir(), "machine-specialize-test-")); dirs.push(dir); return dir; } const sandboxes = () => localSandboxes(path.join(os.tmpdir(), `machine-specialize-boxes-${process.pid}`), { isolation: "none" }); const BUGGY = "def mean(xs):\n return sum(xs) / len(xs)\n"; const FIXED = "def mean(xs):\n if not xs:\n return 0\n return sum(xs) / len(xs)\n"; const TEST = "import unittest\nfrom stats import mean\n\n\nclass T(unittest.TestCase):\n def test_empty(self):\n self.assertEqual(mean([]), 0)\n\n\nif __name__ == '__main__':\n unittest.main()\n"; function caseBlock(input: string, source: string, solution: string, test = TEST) { return `\n${input}\n\n${source}\n\n${test}\n\n${solution}\npython3 -m unittest -q\n`; } test("parseDesign reads the tagged files and topics, and names what is missing", () => { const ok = parseDesign("Async```ts\nr\n```mi\n- races\n2. deadlocks\n"); assert.deepEqual(ok, { slug: "async", rubricTs: "r", machineTs: "m", instructions: "i", topics: ["races", "deadlocks"] }); assert.match(String(parseDesign("a")), /missing rubricTs, machineTs, instructions/); assert.match(String(parseDesign("Bad Slug!rmi")), /slug/); }); test("parseCases reads files, the solution, and the test command", () => { const [c] = parseCases(caseBlock("mean([]) crashes", BUGGY, FIXED)); assert.equal(c.input, "mean([]) crashes"); assert.deepEqual(Object.keys(c.files!), ["stats.py", "test_stats.py"]); assert.equal(c.solution!["stats.py"], FIXED); assert.deepEqual(c.test, { command: "python3", args: ["-m", "unittest", "-q"] }); }); test("checkCase keeps a test that fails before the fix and passes after, and discards the rest", async () => { const boxes = sandboxes(); const [good] = parseCases(caseBlock("mean([]) crashes", BUGGY, FIXED)); assert.equal(await checkCase(good, boxes, true), undefined); const [passing] = parseCases(caseBlock("already fine", FIXED, FIXED)); assert.match(String(await checkCase(passing, boxes, true)), /already passes/); const [wrongFix] = parseCases(caseBlock("bad fix", BUGGY, BUGGY)); assert.match(String(await checkCase(wrongFix, boxes, true)), /fail after the reference fix/); const cheat: CaseDraft = { ...good, solution: { "test_stats.py": "" } }; assert.match(String(await checkCase(cheat, boxes, true)), /changes a test file/); assert.match(String(await checkCase({ input: "x", files: { "a.py": "" } }, boxes, true)), /no test command/); assert.equal(await checkCase({ input: "no fixture needed" }, boxes, false), undefined); assert.match(String(await checkCase({ input: "x", files: { "../a.py": "" } }, boxes, false)), /relative path/); }); const HIDDEN = "import unittest\nfrom stats import mean\n\n\nclass H(unittest.TestCase):\n def test_one(self):\n self.assertEqual(mean([4]), 4)\n\n def test_empty_tuple(self):\n self.assertEqual(mean(()), 0)\n"; test("checkCase with hidden tests: they must be new test files that fail alone before the fix and pass with it", async () => { const boxes = sandboxes(); const [good] = parseCases(caseBlock("mean([]) crashes", BUGGY, FIXED).replace("", `\n${HIDDEN}\n`)); assert.deepEqual(Object.keys(good.hidden!), ["test_hidden_stats.py"]); assert.equal(await checkCase(good, boxes, true, true), undefined); const [none] = parseCases(caseBlock("mean([]) crashes", BUGGY, FIXED)); assert.match(String(await checkCase(none, boxes, true, true)), /no hidden tests/); const trivial: CaseDraft = { ...good, hidden: { "test_hidden_stats.py": "import unittest\n\n\nclass H(unittest.TestCase):\n def test_ok(self):\n pass\n" } }; assert.match(String(await checkCase(trivial, boxes, true, true)), /already pass before the fix/); const clobber: CaseDraft = { ...good, hidden: { "test_stats.py": HIDDEN } }; assert.match(String(await checkCase(clobber, boxes, true, true)), /new test file/); }); test("splitCases spreads held-out cases through the kept ones", () => { const { train, holdout } = splitCases(Array.from({ length: 28 }, (_, i) => i), 20, 8); assert.equal(train.length, 20); assert.equal(holdout.length, 8); assert.ok(holdout[0] < 4 && holdout.at(-1)! > 23, "spread from start to end"); const few = splitCases([1, 2, 3, 4, 5], 20, 8); assert.equal(few.train.length + few.holdout.length, 5); assert.ok(few.holdout.length >= 1); }); const PARENT = `import { check, defineEvaluator, defineMachine, defineRubric } from "../../src/index.ts"; const rubric = defineRubric({ good: { description: 'Says "good".' } }); export default defineMachine({ name: "toy", intent: "Fix small Python projects.", instructions: "Be good.", model: "Qwen/Qwen3-8B", rubric, evaluator: defineEvaluator(rubric, { good: check("good", (run) => run.output.includes("good")) }), }); `; const childRubric = (ids: string[]) => `import { defineRubric } from "../../../src/index.ts"; export const rubric = defineRubric({ ${ids.map((id) => ` ${id}: { description: "Mentions ${id}.", weight: 2 },`).join("\n")} });`; const CHILD = `import { check, defineChild, defineEvaluator, instructionsFrom, modelFrom } from "../../../src/index.ts"; import toy from "../machine.ts"; import { rubric } from "./rubric.ts"; export default defineChild(toy, { name: "toy/empty", intent: "Handle empty inputs.", instructions: instructionsFrom(import.meta.url), model: modelFrom(import.meta.url, "thinkingmachines/Inkling-Small"), rubric, evaluator: defineEvaluator(rubric, { mentions_empty: check("mentions-empty", (run) => ({ score: run.output.includes("empty") ? 1 : 0, reason: "looked" })) }), });`; const design = (rubricIds: string[]) => `empty\n${childRubric(rubricIds)}\n${CHILD}\nCheck empty inputs first.\n\nempty lists\nmissing keys\n`; test("specialize: the author's invalid child goes back to it, then the child and its checked cases are written", async () => { const dir = await tempDir(); await symlink(path.join(repo, "src"), path.join(dir, "src"), "dir"); await mkdir(path.join(dir, "machines", "toy"), { recursive: true }); await writeFile(path.join(dir, "machines", "toy", "machine.ts"), PARENT); await writeFile(path.join(dir, "machines", "toy", "cases.json"), JSON.stringify([{ input: "fix it", files: { "stats.py": BUGGY, "test_stats.py": TEST } }])); const prompts: HarnessRequest[] = []; let batch = 0; const harness = scriptedHarness((req) => { prompts.push(req); if (req.input.startsWith("Write a child machine")) return design(["good"]); // redefines the inherited criterion if (req.input.startsWith("Your child machine failed validation")) return design(["mentions_empty"]); batch++; // Each batch: two good cases and one whose test already passes (discarded). return [ caseBlock(`mean of an empty list crashes (${batch}a)`, BUGGY, FIXED), caseBlock(`mean([]) should be 0 (${batch}b)`, BUGGY, FIXED), caseBlock(`nothing wrong (${batch}c)`, FIXED, FIXED), ].join("\n"); }); const toy = await machine.load("toy", { workspace: dir, harness, store: diskStore(path.join(dir, ".machine")), sandboxes: sandboxes(), events: { emit() {} }, }); const result = await toy.specialize({ focus: "empty inputs", model: "thinkingmachines/Inkling-Small", authorModel: "author-model", budget: 1, trainCases: 4, holdoutCases: 2, concurrency: 1 }); assert.equal(result.name, "toy/empty"); assert.equal(result.attempts, 2, "one retry after the failed validation"); const retry = prompts.find((p) => p.input.startsWith("Your child machine failed validation"))!; assert.match(retry.input, /does not load|redefines/); assert.ok(retry.history.length > 0, "the retry sees the author's first attempt"); assert.deepEqual(result.inherited.map((c) => c.id), ["good"]); assert.deepEqual(result.added.map((c) => [c.id, c.grader]), [["mentions_empty", "check:mentions-empty"]]); assert.deepEqual(result.topics, ["empty lists", "missing keys"]); assert.equal(result.cases, 4); assert.equal(result.holdout, 2); assert.ok(result.discarded.some((d) => /already passes/.test(d.reason))); const childDir = path.join(dir, "machines", "toy", "empty"); const cases = JSON.parse(await readFile(path.join(childDir, "cases.json"), "utf8")); const holdout = JSON.parse(await readFile(path.join(childDir, "holdout.json"), "utf8")); assert.equal(cases.length + holdout.length, 6); assert.ok(cases.every((c: { solution?: unknown; files: Record }) => !c.solution && c.files["stats.py"] === BUGGY), "the reference fix is not in the cases"); assert.ok(!holdout.some((h: { input: string }) => cases.some((c: { input: string }) => c.input === h.input))); const child = await machine.load("toy/empty", { workspace: dir, harness, store: diskStore(path.join(dir, ".machine")), events: { emit() {} } }); assert.equal(child.model, "thinkingmachines/Inkling-Small"); assert.deepEqual(Object.keys(child.definition.rubric).sort(), ["good", "mentions_empty"]); assert.match(child.definition.instructions, /Be good\.\n\nCheck empty inputs first\./); // Rewriting the child keeps its cases. const again = await toy.specialize({ focus: "empty inputs", model: "thinkingmachines/Inkling-Small", authorModel: "author-model", budget: 1, slug: "empty", reuseCases: true }); assert.equal(again.cases, 4); assert.equal(again.holdout, 2); assert.deepEqual(JSON.parse(await readFile(path.join(childDir, "cases.json"), "utf8")), cases); const text = formatSpecialization(result); assert.match(text, /inherits\s+good/); assert.match(text, /adds\s+mentions_empty\s+check/); assert.ok(text.split("\n").length <= 14); }); test("validation rejects a check that grades only the files the run started with", async () => { const dir = await tempDir(); await symlink(path.join(repo, "src"), path.join(dir, "src"), "dir"); await mkdir(path.join(dir, "machines", "toy"), { recursive: true }); await writeFile(path.join(dir, "machines", "toy", "machine.ts"), PARENT); const fixtureOnly = CHILD.replace('run.output.includes("empty")', 'Object.keys(run.files ?? {}).length > 0'); let calls = 0; const harness = scriptedHarness(() => (calls++ === 0 ? design(["mentions_empty"]).replace(CHILD, fixtureOnly) : "xy")); const toy = await machine.load("toy", { workspace: dir, harness, store: diskStore(path.join(dir, ".machine")), events: { emit() {} } }); await assert.rejects(toy.specialize({ focus: "x", authorModel: "a", budget: 1, retries: 0 }), /reads run\.files/); }); test("specialize gives up after its retries when the child never validates", async () => { const dir = await tempDir(); await symlink(path.join(repo, "src"), path.join(dir, "src"), "dir"); await mkdir(path.join(dir, "machines", "toy"), { recursive: true }); await writeFile(path.join(dir, "machines", "toy", "machine.ts"), PARENT); let calls = 0; const harness = scriptedHarness(() => (calls++, design(["good"]))); const toy = await machine.load("toy", { workspace: dir, harness, store: diskStore(path.join(dir, ".machine")), events: { emit() {} } }); await assert.rejects(toy.specialize({ focus: "x", authorModel: "a", budget: 1, retries: 1 }), /failed validation after 2 attempts/); assert.equal(calls, 2); await assert.rejects(readFile(path.join(dir, "machines", "toy", "empty", "machine.ts")), "a child that never validated is removed"); }); test("specialize asks the author once to reconsider a check that scores every sample run the same, then accepts", async () => { const dir = await tempDir(); await symlink(path.join(repo, "src"), path.join(dir, "src"), "dir"); await mkdir(path.join(dir, "machines", "toy"), { recursive: true }); await writeFile(path.join(dir, "machines", "toy", "machine.ts"), PARENT); await writeFile(path.join(dir, "machines", "toy", "cases.json"), JSON.stringify(["a", "b", "c"])); const inputs: string[] = []; let n = 0; const harness = scriptedHarness((req) => { inputs.push(req.input); if (req.input.startsWith("Write ") && req.input.includes("cases for")) return `case ${++n}case ${++n}`; return design(["mentions_empty"]); // the check scores "Done." runs 0 every time }); const toy = await machine.load("toy", { workspace: dir, harness, store: diskStore(path.join(dir, ".machine")), events: { emit() {} } }); const result = await toy.specialize({ focus: "empty inputs", model: "thinkingmachines/Inkling-Small", authorModel: "a", budget: 1, trainCases: 3, holdoutCases: 1, concurrency: 1 }); assert.equal(result.attempts, 2); assert.ok(inputs.some((i) => i.startsWith("Your child machine is valid, but check these") && /mentions_empty gives every one of 3 sample runs/.test(i))); assert.equal(result.testedFixtures, false); assert.equal(result.cases + result.holdout, 4); });