84 lines
2.5 KiB
Python
84 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Independent re-derivation of the check-in census for 2026-11-05.
|
|
|
|
Verifies the committed CSV under wizard-work/ledger/ against a from-scratch
|
|
re-derivation of `git ls-tree` at HEAD. Exit 0 iff identical; 1 otherwise.
|
|
"""
|
|
import argparse
|
|
import csv
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
CSV_NAME = "2026-11-05-checkin-census.csv"
|
|
|
|
|
|
def git(repo, *args):
|
|
return subprocess.run(
|
|
["git", "-C", repo] + list(args), check=True, capture_output=True, text=True
|
|
).stdout
|
|
|
|
|
|
def rederive(repo):
|
|
"""Return sorted [(date, wizard, path, size, sha)] straight from git."""
|
|
names = git(repo, "ls-tree", "-r", "--name-only", "HEAD").splitlines()
|
|
longs = git(repo, "ls-tree", "-r", "-l", "HEAD").splitlines()
|
|
big = {}
|
|
for ln in longs:
|
|
tab = ln.find("\t")
|
|
head, path = ln[:tab], ln[tab + 1:]
|
|
tok = head.split()
|
|
big[path] = (int(tok[3]), tok[2])
|
|
rows = []
|
|
for p in names:
|
|
if not p.startswith("checkins/") or p == "checkins/README.md":
|
|
continue
|
|
rel = p[len("checkins/"):]
|
|
rows.append((rel[:10], rel[11:-3], p, big[p][0], big[p][1]))
|
|
rows.sort()
|
|
return rows
|
|
|
|
|
|
def read_committed(repo):
|
|
path = os.path.join(repo, "wizard-work", "ledger", CSV_NAME)
|
|
with open(path, newline="") as f:
|
|
return list(csv.reader(f))
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--check", action="store_true", help="run the verification")
|
|
ap.add_argument("--repo", default="/root/troupe-standup")
|
|
args = ap.parse_args()
|
|
if not args.check:
|
|
return 0
|
|
|
|
repo = args.repo
|
|
committed = read_committed(repo)
|
|
expected = [[str(s) for s in r] for r in rederive(repo)]
|
|
|
|
ok = True
|
|
if len(committed) - 1 != len(expected):
|
|
ok = False
|
|
print("ROW COUNT MISMATCH: committed=%d expected=%d"
|
|
% (len(committed) - 1, len(expected)))
|
|
|
|
got = committed[1:]
|
|
for i in range(max(len(got), len(expected))):
|
|
a = got[i] if i < len(got) else None
|
|
b = expected[i] if i < len(expected) else None
|
|
if a != b:
|
|
ok = False
|
|
print("DIFF line %d: committed=%r expected=%r" % (i + 2, a, b))
|
|
|
|
dates = sorted({r[0] for r in rederive(repo)})
|
|
wizards = sorted({r[1] for r in rederive(repo)})
|
|
print("checkin census: rows=%d dates=%d wizards=%d"
|
|
% (len(expected), len(dates), len(wizards)))
|
|
print("check commit tree: HEAD -> %s" % git(repo, "rev-parse", "HEAD").strip()[:12])
|
|
sys.exit(0 if ok else 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|