#!/usr/bin/env bash # CHECK — ledger churn artifact verification. # Re-derives Table A (git log) and Table B (filesystem) from the live repo and # compares against the committed JSON/CSV tables. Exits 0 only on exact match. set -u REPO=/root/troupe-standup OUT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # --- Table A: recompute commits-by-author-day from git log --- echo "[CHECK] recomputing Table A from git log ..." python3 - "$OUT" <<'PY' import sys, json, subprocess, collections OUT = sys.argv[1] git = subprocess.run( ["git", "-C", "/root/troupe-standup", "log", "--format=%ad|%an", "--date=short"], capture_output=True, text=True, check=True).stdout exp = collections.Counter() for line in git.splitlines(): if line.strip(): d, a = line.split("|", 1) exp[(d, a)] += 1 got = collections.Counter() for x in json.load(open(OUT + "/commits_by_author_day.json")): got[(x["date"], x["author"])] = x["commits"] if dict(exp) != dict(got): print(" Table A MISMATCH", file=sys.stderr) print(" expected %d pairs, committed %d pairs" % (len(exp), len(got)), file=sys.stderr) sys.exit(1) PY if [ $? -ne 0 ]; then exit 1; fi # --- Table B: recompute work inventory from filesystem --- echo "[CHECK] recomputing Table B from filesystem ..." python3 - "$OUT" <<'PY' import sys, os, json OUT = sys.argv[1] REPO = "/root/troupe-standup" inv = {} for d in os.listdir(os.path.join(REPO, "wizard-work")): p = os.path.join(REPO, "wizard-work", d) if not os.path.isdir(p): continue fl = [] for root, _, names in os.walk(p): for n in names: f = os.path.join(root, n) st = os.stat(f) fl.append({"bytes": st.st_size}) inv[d] = {"files": len(fl), "bytes": sum(x["bytes"] for x in fl)} got = {r["wizard"]: {"files": r["files"], "bytes": r["bytes"]} for r in json.load(open(OUT + "/wizard_inventory.json"))} if inv != got: print(" Table B MISMATCH", file=sys.stderr) sys.exit(1) PY if [ $? -ne 0 ]; then exit 1; fi # --- Table C: spot-check headline totals in the md artifact --- echo "[CHECK] re-deriving headline totals ..." python3 - "$OUT" <<'PY' import sys, json OUT = sys.argv[1] commits = sum(x["commits"] for x in json.load(open(OUT + "/commits_by_author_day.json"))) files = sum(r["files"] for r in json.load(open(OUT + "/wizard_inventory.json"))) bytes_ = sum(r["bytes"] for r in json.load(open(OUT + "/wizard_inventory.json"))) head = open(OUT + "/troupe-churn.md").read() for needle in [str(commits), str(files), format(bytes_, ",")]: if needle not in head: print(" Table C MISMATCH: missing " + needle, file=sys.stderr) sys.exit(1) PY if [ $? -ne 0 ]; then exit 1; fi echo "CHECK PASS: Table A, Table B, and headline totals all re-derive cleanly." exit 0