#!/usr/bin/env python3 """Independent verification for the troupe-standup commit census artifact. Cross-checks the artifact against git: 1. internal consistency (summary <-> detail, manifest <-> rows), 2. every commit hash in commits-main.tsv resolves to a real git commit, 3. per-author counts in commits-by-author.tsv match a recomputation from git, excluding census metadata commits. Exit 0 only on full match. """ import subprocess, sys, os, json from collections import Counter OUT = "/root/.hermes/wizard-outputs/ledger" REPO = "/root/troupe-standup" def git(*args): return subprocess.run(["git","-C",REPO]+list(args), capture_output=True, text=True, check=True).stdout def fail(msg): print("FAIL:", msg) sys.exit(1) if not os.path.exists(os.path.join(OUT,"commits-by-author.tsv")) or not os.path.exists(os.path.join(OUT,"commits-main.tsv")) or not os.path.exists(os.path.join(OUT,"manifest.json")): fail("missing artifact file") actual = {} with open(os.path.join(OUT,"commits-by-author.tsv")) as f: header = f.readline().rstrip("\n") if header != "author\temail\tcommits": fail("bad author header") for line in f: line = line.rstrip("\n") if not line: continue p = line.split("\t") if len(p) != 3: fail("bad author row: %r" % line) actual[p[0]] = (p[1], int(p[2])) detail_count = 0 detail_by_author = Counter() with open(os.path.join(OUT,"commits-main.tsv")) as f: header = f.readline().rstrip("\n") if header != "hash\tshort\tauthor\temail\tdate\tsubject": fail("bad commits header") for line in f: line = line.rstrip("\n") if not line: continue parts = line.split("\t") if len(parts) != 6: fail("bad commits row: %r" % line) h = parts[0] r = subprocess.run(["git","-C",REPO,"rev-parse","--verify",h], capture_output=True, text=True) if r.returncode != 0: fail("invalid commit hash in artifact: %r" % h) detail_count += 1 detail_by_author[parts[2]] += 1 if detail_count != sum(v[1] for v in actual.values()): fail("detail rows=%d != summary commits=%d" % (detail_count, sum(v[1] for v in actual.values()))) m = json.load(open(os.path.join(OUT,"manifest.json"))) if m["commit_count"] != detail_count: fail("manifest.commit_count=%d != detail rows=%d" % (m["commit_count"], detail_count)) if dict(detail_by_author) != {k: v[1] for k, v in actual.items()}: fail("author counts detail vs summary mismatch") # metadata-aware cross-check with git (exclude census metadata commits) data = Counter() meta = 0 for h in git("rev-list","main").splitlines(): h = h.strip() if not h: continue subj = git("show","-s","--pretty=format:%s",h).strip() if subj.startswith("ledger: commit census"): meta += 1 continue data[git("show","-s","--pretty=format:%an",h).strip()] += 1 if len(data) != len(actual): fail("author count differs: artifact=%d git_data=%d" % (len(actual), len(data))) for name,(email,c) in actual.items(): if data.get(name,0) != c: fail("count mismatch author %r: artifact=%d git_data=%d" % (name,c,data.get(name,0))) print("OK: data_commits=%d authors=%d metadata=%d" % (detail_count, len(actual), meta))