#!/usr/bin/env python3 """report.py — the report is GENERATED from the artifacts. It is never composed. Every failure in this project's record lived at the report layer: the primary data was right and the summary of it was wrong. The enumeration said 7, the summary said 6. The harness ran 7 assertions and reported 6. The checker listed the new defect and printed 'ok'. Six agent results arrived and three were dropped. So the report layer stops being written by hand. Rules, enforced mechanically: 1. A number appears ONLY if it was extracted from a captured artifact. 2. An artifact whose bytes no longer match its manifest hash is a HARD FAILURE -- the report refuses to render at all. 3. A claim naming an artifact that does not exist is a HARD FAILURE. It does not degrade to a blank, a dash, or 'not available'. 4. Narrative may say why something matters. It may not contain a digit. """ import sys, os, csv, hashlib, re, subprocess class Unbacked(Exception): pass def sha256(p): h = hashlib.sha256() with open(p, 'rb') as f: for b in iter(lambda: f.read(65536), b''): h.update(b) return h.hexdigest() def load(evdir): """Read a manifest and VERIFY every artifact before anything may be quoted.""" man = os.path.join(evdir, 'MANIFEST.tsv') if not os.path.exists(man): raise Unbacked(f"no manifest at {evdir}") rows = [] with open(man) as f: for r in csv.DictReader(f, delimiter='\t'): art = os.path.join(evdir, r['artifact']) if not os.path.exists(art): raise Unbacked(f"artifact missing: {r['artifact']}") actual = sha256(art) if actual != r['sha256']: raise Unbacked(f"artifact ALTERED: {r['artifact']}\n manifest {r['sha256']}\n actual {actual}") r['_path'] = art rows.append(r) if not rows: raise Unbacked(f"manifest at {evdir} has no rows -- nothing to report") return rows def extract(rows, artifact, pattern, group=1): """Pull a value OUT OF the captured stdout. Cannot be typed, only found.""" for r in rows: if r['artifact'].endswith(artifact) or artifact in r['artifact']: txt = open(r['_path'], errors='replace').read() m = re.search(pattern, txt, re.M) if not m: raise Unbacked(f"pattern not found in {r['artifact']}: {pattern!r}") return m.group(group), r raise Unbacked(f"no artifact matching {artifact!r} -- the number has no source") def cite(r): return f"`{r['artifact']}` · sha `{r['sha256'][:12]}` · commit `{r['commit']}` · exit `{r['exit']}`" def narrative_ok(text): """Rule 4. Prose may not carry a quantity.""" stripped = re.sub(r'`[^`]*`', '', text) bad = re.findall(r'\b\d+(?:\.\d+)?\b', stripped) return (not bad), bad