76 lines
2.7 KiB
Bash
Executable File
76 lines
2.7 KiB
Bash
Executable File
#!/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
|