near-toll-audit / pipeline/verify_claims.py · raw
#!/usr/bin/env python3"""Proves every number in THESIS.md and README.md came from the frozen metrics.Re-renders both files from thesis/*_frozen.json and compares bytes. A hand-typed number breaks the match. The memo bodymust also stay under 1,500 words. Run pipeline/freeze.py only to issue a new memo."""import json, pathlib, sysROOT = pathlib.Path(__file__).resolve().parent.parentsys.path.insert(0, str(ROOT / "pipeline"))from build import derived, render  # noqa: E402def main():    if not (ROOT / "thesis" / "metrics_frozen.json").exists():        print("memo not frozen yet")        return 0    metrics = derived(json.loads((ROOT / "thesis" / "metrics_frozen.json").read_text()))    model = json.loads((ROOT / "thesis" / "model_frozen.json").read_text())    grades = json.loads((ROOT / "thesis" / "grades_frozen.json").read_text())    bad = 0    for src, dst in (("thesis/THESIS.tmpl.md", "THESIS.md"), ("thesis/README.tmpl.md", "README.md")):        want = render((ROOT / src).read_text(), metrics, model, grades, escape=False)        got = (ROOT / dst).read_text()        if want != got:            bad += 1            print(f"MISMATCH {dst}: it no longer matches a render from the frozen metrics")    memo = (ROOT / "THESIS.md").read_text()    words = len(memo.split("## The strongest case against this thesis")[0].split())    print(f"memo and README match the frozen metrics: {not bad}; memo body {words} words")    if words > 1500:        print("memo body is over 1,500 words")        return 1    return 1 if bad else 0if __name__ == "__main__":    sys.exit(main())