Files
troupe-standup/wizard-work/ledger/CHECK-git-history
T

126 lines
4.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# CHECK — ledger commit-history refresh (Extract lane).
#
# Verifies the committed 2026-10-25-git-history.{csv,json,md} against a
# RE-DERIVATION of the same snapshot, keyed by the committed `head` field
# (the HEAD of the repo at the moment the artifact was captured). Because the
# pinned head is re-derived with `git rev-list <head>`, this is immune to new
# commits landing above the snapshot: those commits are simply outside scope.
# Exits 0 only when every check matches exactly.
set -u
REPO=/root/troupe-standup
OUT="$REPO/wizard-work/ledger"
JSON="$OUT/2026-10-25-git-history.json"
CSV="$OUT/2026-10-25-git-history.csv"
python3 - "$JSON" "$CSV" <<'PY'
import json, csv, subprocess, sys
repo = "/root/troupe-standup"
json_path, csv_path = sys.argv[1], sys.argv[2]
def git(*args):
return subprocess.run(
["git", "-C", repo] + list(args), check=True,
capture_output=True, text=True).stdout
# ---- Load the committed snapshot and its pinned head ----
with open(json_path) as f:
fixed = json.load(f)
head = fixed.get("head")
if not head:
print("FAIL: json has no 'head' field")
sys.exit(1)
with open(csv_path, newline="") as f:
rd = list(csv.reader(f))
hdr, data = rd[0], rd[1:]
fails = []
def check(name, obs, exp):
if obs == exp:
print("PASS: %s" % name)
else:
print("FAIL: %s" % name)
print(" observed: %r" % (obs,))
print(" expected: %r" % (exp,))
fails.append(name)
# ---- Re-derive the snapshot from live git, keyed at `head` ----
meta = git("log", "--format=" + "%x01%H%x01%h%x01%an%x01%ae%x01%aI%x01%s",
"--name-status", head).splitlines()
rows = []
i = 0
while i < len(meta):
line = meta[i]
if not line.startswith("\x01"):
i += 1
continue
fields = line.split("\x01")
if len(fields) < 7:
i += 1
continue
_full, full, short, name, email, date, subject = fields[:7]
subject = subject.lstrip("\x01")
paths = []
i += 1
while i < len(meta) and not meta[i].startswith("\x01"):
ns = meta[i]
if "\t" in ns:
paths.append(ns.split("\t", 1)[1])
i += 1
rows.append({"hash": full, "short": short, "name": name, "email": email,
"date": date, "subject": subject, "files": len(set(paths))})
rows.sort(key=lambda r: r["date"])
earliest, latest = rows[0]["date"], rows[-1]["date"]
rows.sort(key=lambda r: (-r["files"], r["date"], r["hash"]))
for idx, r in enumerate(rows, 1):
r["rank"] = idx
# 1. Column structure of the committed CSV.
check("csv header", hdr, ["rank","hash","short","name","email","date","subject","files"])
# 2. Full row-level agreement, field for field (rank, hash, short, name, email,
# date, subject, files) against the independent re-derivation.
exp_rows = [[str(r["rank"]), r["hash"], r["short"], r["name"], r["email"],
r["date"], r["subject"], str(r["files"])] for r in rows]
if len(data) != len(rows):
fails.append("csv row count")
for a, b in zip(data, exp_rows):
if a != b:
fails.append("row mismatch at data index %d" % data.index(a))
break
else:
check("csv rows field-for-field re-derive",
"all %d rows identical" % len(rows),
"all %d rows identical" % len(rows))
# 3. Headline numbers.
check("json commits == re-derived commit count",
fixed.get("commits"), len(rows))
check("json earliest", fixed.get("earliest"), earliest)
check("json first_commit", fixed.get("first_commit"), rows[-1]["hash"])
# 4. The top-10 by file-churn must reproduce the independent re-derivation.
top = sorted(rows, key=lambda r: (-r["files"], r["date"], r["hash"]))[:10]
exp_top = [(str(r["rank"]), r["short"], str(r["files"])) for r in top]
obs_top = []
for rank, short, files in exp_top:
for row in data:
if row[0] == rank:
obs_top.append((rank, short, files))
break
check("top-10 (hash, files) == re-derivation", obs_top, exp_top)
print("snapshot head: %s" % head)
print("re-derived commits: %d | earliest: %s | latest: %s | first_commit: %s"
% (len(rows), earliest, latest, rows[-1]["hash"]))
if fails:
print("CHECK FAIL: %s" % ", ".join(fails))
sys.exit(1)
print("CHECK PASS: git commit-history extraction re-derives cleanly.")
PY
exit $?