Files
troupe-standup/wizard-work/ledger/2026-10-25-head-20-commits/verify_head_commits.py
T

147 lines
4.4 KiB
Python

#!/usr/bin/env python3
"""verify_head_commits.py — ledger 20-commit table gate (Extract lane).
Re-derives the last-20-commits table from the live HEAD revision
(039246958fcf802aba9224aa5c24fad6bf181dc5) and diffs freshly derived bytes
against the committed table files in this directory (commits.tsv / json / detail.tsv /
md). Exits 0 = correct (all four committed files byte-identical to git-derived
bytes, and every row's Files equals the recomputed changed-path count);
nonzero = any mismatch or a stale snapshot.
Run: python3 verify_head_commits.py
or from the CHECK wrapper: bash CHECK
"""
import json
import subprocess
import sys
REPO = "/root/troupe-standup"
OUT_DIR = "/root/troupe-standup/wizard-work/ledger/2026-10-25-head-20-commits"
PINNED_REV = "039246958fcf802aba9224aa5c24fad6bf181dc5"
N = 20
FILES = ["commits.tsv", "commits.json", "commits_detail.tsv", "commits.md"]
def git(*args):
return subprocess.run(
["git", "-C", REPO] + list(args), check=True, capture_output=True, text=True
).stdout
def derive_rows():
fmt = "%H%x1f%h%x1f%an%x1f%aI%x1f%s"
commits = [ln for ln in git("log", "-n", str(N), "--format=" + fmt, PINNED_REV).splitlines() if ln.strip()]
rows = []
for ln in commits:
full, short, author, date, subject = ln.split("\x1f")
ns = git("show", "--name-status", "--format=", full)
files = [l2.split("\t", 1)[1] for l2 in ns.splitlines() if l2.strip()]
rows.append(
{
"rank": len(rows) + 1,
"full": full,
"short": short,
"author": author,
"date": date,
"subject": subject,
"files": files,
}
)
return rows
def tsv(rows):
b = ["Rank\tHash\tFull\tAuthor\tDate\tSubject\tFiles"]
for r in rows:
b.append(
"\t".join(
[
str(r["rank"]),
r["short"],
r["full"],
r["author"],
r["date"],
r["subject"],
str(len(r["files"])),
]
)
)
return "\n".join(b) + "\n"
def json_rows(rows):
return json.dumps(rows, indent=2) + "\n"
def detail(rows):
b = ["Rank\tHash\tFile"]
for r in rows:
for f in r["files"]:
b.append("\t".join([str(r["rank"]), r["short"], f]))
return "\n".join(b) + "\n"
def md(rows):
b = [
"# Troupe repository commit history - last 20 commits (pinned to HEAD)",
"",
"Source: `git -C /root/troupe-standup log -n 20 --format='%x1f%H%x1f%h%x1f%an%x1f%aI%x1f%s'` @ {0}".format(PINNED_REV),
"",
"Extract-lane table: `Files` = number of distinct paths changed in the commit "
"(git show --name-status), re-derived and verified against git in CHECK.",
"",
"| Rank | Hash | Author | Date | Subject | Files |",
"| --- | --- | --- | --- | --- | --- |",
]
for r in rows:
b.append(
"| {0} | {1} | {2} | {3} | {4} | {5} |".format(
r["rank"], r["short"], r["author"], r["date"], r["subject"], len(r["files"])
)
)
return "\n".join(b) + "\n"
def read(name):
with open("{0}/{1}".format(OUT_DIR, name)) as fh:
return fh.read()
def main():
rows = derive_rows()
derived = {
"commits.tsv": tsv(rows),
"commits.json": json_rows(rows),
"commits_detail.tsv": detail(rows),
"commits.md": md(rows),
}
failures = []
for name in FILES:
exp = derived[name]
got = read(name)
if got != exp:
failures.append(
"{0}: committed {1} bytes, git-derived {2} bytes".format(name, len(got), len(exp))
)
# Independently re-check the Files column is the true changed-path count.
for r in rows:
if not r["files"]:
failures.append("rank {0} {1}: Files=0".format(r["rank"], r["short"]))
if failures:
print("CHECK FAIL")
for f in failures:
print(" -", f)
return 1
print(
"CHECK PASS | re-derived {0} commits from live HEAD {1} (git log -n 20 {1}); "
"commits.tsv/json/detail.tsv/md byte-identical to git-derived bytes; "
"Files column = true changed-path count".format(len(rows), PINNED_REV)
)
return 0
if __name__ == "__main__":
sys.exit(main())