import { describe, expect, it } from "vitest"; import { sha256Hex } from "./contract/hash.js"; import type { ConformInput, ConformResult } from "./conform.js"; import { PROVE_DEFAULT_MAX_PASSES, PROVE_MAX_PASSES, type ProveSamplerArgs, clampMaxPasses, emptyConformResult, proveCompliant, proveIssueCount, resolveProveVerdict, } from "./conform-prove.js"; // ── conform stubs ───────────────────────────────────────────────────────── function clean(code: string): ConformResult { return { conformed: code, changed: false, summary: "clean", changes: [], suggestions: [], unresolved: [], }; } const oneChange: ConformResult["changes"] = [ { kind: "replace-token", ruleId: "styles/no-raw-color", code: "FUI6001", severity: "warning", message: "Replaced hardcoded color.", before: "#2563eb", after: "var(--brand-600)", confidence: "high", }, ]; const oneSuggestion: ConformResult["suggestions"] = [ { kind: "review-low-confidence", message: "Ambiguous variant.", confidence: "medium" }, ]; /** Replaces a raw color once, then is clean — the canonical 2-pass convergence. */ function tokenizing(input: ConformInput): ConformResult { if (input.code.includes("#2563eb")) { return { conformed: input.code.replace("#2563eb", "var(--brand-600)"), changed: true, summary: "Mapped one hardcoded value.", changes: oneChange, suggestions: [], unresolved: [], }; } return clean(input.code); } /** Always stalls (no deterministic change) with one residual suggestion. */ function residual(input: ConformInput): ConformResult { return { conformed: input.code, changed: false, summary: "Needs review.", changes: [], suggestions: oneSuggestion, unresolved: [], }; } describe("proveCompliant — pure validate-fix-validate primitive", () => { it("loops deterministic fixes until a clean pass proves compliance", async () => { const out = await proveCompliant( { code: '
Send
' }, { conform: tokenizing } ); expect(out.verdict).toBe("pass"); expect(out.provedCompliant).toBe(true); expect(out.issueCount).toBe(0); expect(out.corrections).toBe(1); expect(out.changed).toBe(true); expect(out.conformed).toContain("var(--brand-600)"); expect(out.passHistory.map((p) => ({ pass: p.pass, issues: p.issues }))).toEqual([ { pass: 1, issues: 1 }, { pass: 2, issues: 0 }, ]); expect(out.reason).toBe("0 findings after 2 passes."); }); it("certifies a clean-on-first-pass result with no coverage signal", async () => { const out = await proveCompliant({ code: "
hi
" }, { conform: (i) => clean(i.code) }); expect(out).toMatchObject({ verdict: "pass", provedCompliant: true, issueCount: 0 }); expect(out.passHistory).toHaveLength(1); expect(out.reason).toBe("0 findings after 1 pass."); expect(out.changed).toBe(false); }); it("returns insufficient_coverage (NOT pass) for a clean run over an empty catalog", async () => { const out = await proveCompliant( { code: "
hi
" }, { conform: (i) => ({ ...clean(i.code), coverage: { tokens: 0, components: 0, evaluated: false }, }), } ); expect(out.verdict).toBe("insufficient_coverage"); expect(out.provedCompliant).toBe(false); expect(out.issueCount).toBe(0); expect(out.reason).toContain("could not be evaluated"); }); it("fails with residual findings when no sampler is provided", async () => { const out = await proveCompliant({ code: "" }, { conform: residual }); expect(out.verdict).toBe("fail"); expect(out.issueCount).toBe(1); expect(out.reason).toBe("no sampler was available and residual issues remain."); expect(out.residual.suggestions).toHaveLength(1); }); it("does not sample when allowSampling is false", async () => { let sampled = false; const out = await proveCompliant( { code: "" }, { conform: residual, sampler: () => { sampled = true; return null; }, }, { allowSampling: false } ); expect(sampled).toBe(false); expect(out.verdict).toBe("fail"); expect(out.reason).toBe("sampling was disabled and residual issues remain."); }); it("uses the sampler for residual issues and re-validates the sampled code", async () => { const out = await proveCompliant( { code: "" }, { conform: (i) => (i.code.includes("aria-label") ? clean(i.code) : residual(i)), sampler: () => ({ code: '', model: "test-model", }), } ); expect(out.verdict).toBe("pass"); expect(out.conformed).toBe(''); expect(out.passHistory[0]?.sampling).toMatchObject({ requested: true, used: true, model: "test-model", }); expect(out.passHistory).toHaveLength(2); }); it("does NOT accept a sampled fix that still has residual findings", async () => { const out = await proveCompliant( { code: "" }, { // Sampler returns a different-but-still-broken snippet; conform never // reaches clean, so the loop must not certify compliance. conform: (i) => residual(i), sampler: ({ code }) => ({ code: `${code}\n{/* attempt */}` }), }, { maxPasses: 3 } ); expect(out.verdict).toBe("fail"); expect(out.provedCompliant).toBe(false); expect(out.issueCount).toBe(1); }); it("counts a declining sampler (null) as used:false and fails", async () => { const out = await proveCompliant({ code: "" }, { conform: residual, sampler: () => null }); expect(out.verdict).toBe("fail"); expect(out.passHistory[0]?.sampling).toMatchObject({ requested: true, used: false }); }); it("threads (pass, seq, codeHashAtRequest) into the sampler across rounds", async () => { const seen: ProveSamplerArgs["metadata"][] = []; const codesSampled: string[] = []; await proveCompliant( { code: "ROUND0" }, { conform: (i) => residual(i), // always stalls -> sampler invoked each round sampler: ({ code, metadata }) => { seen.push(metadata); codesSampled.push(code); return { code: `ROUND${metadata.seq + 1}` }; // always a fresh snippet }, }, { maxPasses: 4 } ); // maxPasses 4 -> sampler fires at seq 0,1,2 (cap is samplingAttempts < maxPasses-1) expect(seen.map((m) => m.seq)).toEqual([0, 1, 2]); expect(seen.map((m) => m.pass)).toEqual([1, 2, 3]); // codeHashAtRequest is the real SHA-256 of the code the sampler saw. expect(seen.map((m) => m.codeHashAtRequest)).toEqual(codesSampled.map((c) => sha256Hex(c))); expect(seen[0]?.codeHashAtRequest).toBe(sha256Hex("ROUND0")); expect(seen[1]?.codeHashAtRequest).toBe(sha256Hex("ROUND1")); }); it("stops at maxPasses when deterministic fixes keep producing findings", async () => { let calls = 0; const out = await proveCompliant( { code: "raw" }, { conform: (i) => { calls += 1; return { conformed: `${i.code}\n/* ${calls} */`, changed: true, summary: "still dirty", changes: oneChange, suggestions: [], unresolved: [], }; }, }, { maxPasses: 2 } ); expect(calls).toBe(2); expect(out.verdict).toBe("fail"); expect(out.passHistory).toHaveLength(2); expect(out.corrections).toBe(2); expect(out.reason).toBe("stopped after 2 passes with 1 finding(s)."); }); it("is deterministic — identical inputs produce identical results", async () => { const run = () => proveCompliant( { code: '
Send
' }, { conform: tokenizing } ); expect(await run()).toEqual(await run()); }); }); describe("prove primitive helpers", () => { it("proveIssueCount sums changes + suggestions + unresolved", () => { expect(proveIssueCount(clean("x"))).toBe(0); expect(proveIssueCount(residual({ code: "x" }))).toBe(1); }); it("emptyConformResult is a neutral, unchanged result", () => { const r = emptyConformResult("abc"); expect(r).toMatchObject({ conformed: "abc", changed: false }); expect(proveIssueCount(r)).toBe(0); }); it("resolveProveVerdict: coverage trumps everything", () => { expect(resolveProveVerdict({ coverageEvaluated: false, provedCompliant: true })).toBe( "insufficient_coverage" ); expect(resolveProveVerdict({ coverageEvaluated: true, provedCompliant: true })).toBe("pass"); expect(resolveProveVerdict({ coverageEvaluated: true, provedCompliant: false })).toBe("fail"); }); it("clampMaxPasses clamps to 1..8 and defaults non-numbers to 4", () => { expect(clampMaxPasses(0)).toBe(1); expect(clampMaxPasses(1)).toBe(1); expect(clampMaxPasses(4)).toBe(PROVE_DEFAULT_MAX_PASSES); expect(clampMaxPasses(8)).toBe(PROVE_MAX_PASSES); expect(clampMaxPasses(99)).toBe(PROVE_MAX_PASSES); expect(clampMaxPasses(3.7)).toBe(3); expect(clampMaxPasses(undefined)).toBe(PROVE_DEFAULT_MAX_PASSES); expect(clampMaxPasses(Number.NaN)).toBe(PROVE_DEFAULT_MAX_PASSES); }); });