#!/usr/bin/env python3 """Extract the dated check-in census for the troupe repo into CSV. One row per dated check-in file under checkins/ (README.md is repo docs, not a check-in, and is excluded). Columns: date, wizard, path, size_bytes, blob_sha1. The re-derivation is from git itself (ls-tree), so the CSV is a faithful extraction of the committed tree, independent of the working-tree state. """ import csv import os import subprocess import sys def git(repo, *args): return subprocess.run( ["git", "-C", repo] + list(args), check=True, capture_output=True, text=True ).stdout def main(): repo = sys.argv[1] if len(sys.argv) > 1 else "/root/troupe-standup" out_csv = ( sys.argv[2] if len(sys.argv) > 2 else os.path.join(repo, "wizard-work/ledger/2026-11-05-checkin-census.csv") ) names = git(repo, "ls-tree", "-r", "--name-only", "HEAD").splitlines() longs = git(repo, "ls-tree", "-r", "-l", "HEAD").splitlines() long_by_path = {} for ln in longs: tab = ln.find("\t") head, path = ln[:tab], ln[tab + 1:] tok = head.split() sha, size = tok[2], int(tok[3]) long_by_path[path] = (size, sha) rows = [] for p in names: if not p.startswith("checkins/") or p == "checkins/README.md": continue rel = p[len("checkins/"):] date = rel[:10] wizard = rel[11:-3] if rel.endswith(".md") else rel[11:] size, sha = long_by_path[p] rows.append([date, wizard, p, size, sha]) rows.sort(key=lambda r: (r[0], r[1], r[2])) os.makedirs(os.path.dirname(out_csv), exist_ok=True) with open(out_csv, "w", newline="") as f: w = csv.writer(f) w.writerow(["date", "wizard", "path", "size_bytes", "blob_sha1"]) w.writerows(rows) print("rows=%d" % len(rows)) print("output=%s" % out_csv) print("sample:") for r in rows[:3]: print(" ", r) if __name__ == "__main__": main()