diff --git a/scripts/test/budget-audit.test.mjs b/scripts/test/budget-audit.test.mjs index 3bfbcb8..2513e51 100644 --- a/scripts/test/budget-audit.test.mjs +++ b/scripts/test/budget-audit.test.mjs @@ -101,10 +101,20 @@ await test("CPU2 the ladder is RE-RUN (the gate references measure-route-cpu) an assert.ok(src.includes("P95_BUDGET_MS = 8"), "the gate must carry the 8 ms product budget constant"); }); -await test("CPU3 on the current tree the ladder runs, the measured p95 is printed against the 8 ms budget and the 10 ms free ceiling, and the child's own GATE line is carried", async () => { +await test("CPU3 when the local graph binary is present the ladder runs, the measured p95 is printed against the 8 ms budget and the 10 ms free ceiling, and the child's own GATE line is carried", async () => { const m = await import(gatesUrl); + // The binary is a GITIGNORED FORK-REBUILDABLE ARTIFACT, not a committed + // file (routing/data/.gitignore ignores *.bin; docs/ROAD-GRAPH.md — forks + // build + upload their own). On a fresh fork its absence is the legal + // notRun class — CPU4's law — so the real-graph leg SKIPs honestly and is + // NEVER a failure; the ladder is demanded only when the binary is present. + const graphPresent = existsSync(path.join(ROOT, "routing", "data", "kl-roadgraph.v1.bin")); + if (!graphPresent) { + console.log(" SKIP — CPU3 needs the gitignored local binary (build it first: node routing/scripts/build-road-graph.mjs); not a failure"); + return; + } const r = await m.runCpuLadderGate(); - assert.equal(r.notRun, undefined, "the graph binary is committed — the ladder must run, not skip"); + assert.equal(r.notRun, undefined, "the binary is present — the ladder must run, not skip"); assert.equal(r.pass, true, `the measured state must sit inside the documented accepted c3 band: ${r.evidence}`); assert.match(r.evidence, /p95 \d+(\.\d+)? ms/, "the measured p95 must be printed"); assert.match(r.evidence, /8 ms/, "the 8 ms product budget must be printed beside the measurement");