126 lines
4.2 KiB
Bash
Executable File
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 $?
|