From dceddcd75b3bf551ee563a6dfcc52ecbdb59a158 Mon Sep 17 00:00:00 2001 From: ledger Date: Sat, 31 Oct 2026 14:07:35 +0000 Subject: [PATCH] ledger: 2026-10-31 git-author census (snapshot 0c27162, 2350 commits, 48 identities) --- .../ledger/2026-10-31-git-author-census.csv | 49 ++++++ .../ledger/2026-10-31-git-author-census.md | 61 +++++++ .../build_2026-10-31_git_author_census.py | 157 ++++++++++++++++++ 3 files changed, 267 insertions(+) create mode 100644 wizard-work/ledger/2026-10-31-git-author-census.csv create mode 100644 wizard-work/ledger/2026-10-31-git-author-census.md create mode 100644 wizard-work/ledger/build_2026-10-31_git_author_census.py diff --git a/wizard-work/ledger/2026-10-31-git-author-census.csv b/wizard-work/ledger/2026-10-31-git-author-census.csv new file mode 100644 index 0000000..2f43d34 --- /dev/null +++ b/wizard-work/ledger/2026-10-31-git-author-census.csv @@ -0,0 +1,49 @@ +rank,author,commits +1,Timmy ,464 +2,ledger ,280 +3,spark ,240 +4,Volt ,182 +5,timmy ,156 +6,Zephyrus Sparkborn ,132 +7,beam ,132 +8,Merlin ,118 +9,sol ,113 +10,quill ,97 +11,forge ,62 +12,Timmy ,49 +13,timmy ,41 +14,Timmy ,39 +15,volt ,38 +16,sphinx ,32 +17,null ,28 +18,volt ,27 +19,Mercury ,22 +20,pipe ,18 +21,timmy ,10 +22,volt ,10 +23,volt ,7 +24,zephyrus-sparkborn ,7 +25,troupe-pipe ,6 +26,Volt ,5 +27,volt ,4 +28,Volt ,3 +29,argus ,3 +30,zephyrus-sparkborn ,3 +31,Cassian Assayborn ,2 +32,Timmy ,2 +33,Volt ,2 +34,zephyrus-sparkborn ,2 +35,Argus ,1 +36,Cassian Assayborn ,1 +37,Timmy ,1 +38,Timmy ,1 +39,Timmy ,1 +40,Volt ,1 +41,Volt ,1 +42,rockachopa ,1 +43,sentinel ,1 +44,timmy ,1 +45,timmy ,1 +46,volt ,1 +47,zephyrus-sparkborn ,1 +48,zephyrus-sparkborn ,1 diff --git a/wizard-work/ledger/2026-10-31-git-author-census.md b/wizard-work/ledger/2026-10-31-git-author-census.md new file mode 100644 index 0000000..1e8f24a --- /dev/null +++ b/wizard-work/ledger/2026-10-31-git-author-census.md @@ -0,0 +1,61 @@ +# Git author census (2026-10-31) + +Snapshot: `git log` of the troupe worktree at `0c2716235852ac9823082fb8938f1a6387fc4640` +(2350 commits reachable before the census commit landed). + +Identity key is the author name plus email in `Name ` form as +recorded by git; no canonicalization (e.g. `Timmy` vs `timmy`, or a +stackchain.ai vs agents.invalid address, stays a distinct row). + +| rank | author | commits | pct | +|---:|---|---:|---:| +| 1 | Timmy | 464 | 19.74 | +| 2 | ledger | 280 | 11.91 | +| 3 | spark | 240 | 10.21 | +| 4 | Volt | 182 | 7.74 | +| 5 | timmy | 156 | 6.64 | +| 6 | Zephyrus Sparkborn | 132 | 5.62 | +| 7 | beam | 132 | 5.62 | +| 8 | Merlin | 118 | 5.02 | +| 9 | sol | 113 | 4.81 | +| 10 | quill | 97 | 4.13 | +| 11 | forge | 62 | 2.64 | +| 12 | Timmy | 49 | 2.09 | +| 13 | timmy | 41 | 1.74 | +| 14 | Timmy | 39 | 1.66 | +| 15 | volt | 38 | 1.62 | +| 16 | sphinx | 32 | 1.36 | +| 17 | null | 28 | 1.19 | +| 18 | volt | 27 | 1.15 | +| 19 | Mercury | 22 | 0.94 | +| 20 | pipe | 18 | 0.77 | +| 21 | timmy | 10 | 0.43 | +| 22 | volt | 10 | 0.43 | +| 23 | volt | 7 | 0.30 | +| 24 | zephyrus-sparkborn | 7 | 0.30 | +| 25 | troupe-pipe | 6 | 0.26 | +| 26 | Volt | 5 | 0.21 | +| 27 | volt | 4 | 0.17 | +| 28 | Volt | 3 | 0.13 | +| 29 | argus | 3 | 0.13 | +| 30 | zephyrus-sparkborn | 3 | 0.13 | +| 31 | Cassian Assayborn | 2 | 0.09 | +| 32 | Timmy | 2 | 0.09 | +| 33 | Volt | 2 | 0.09 | +| 34 | zephyrus-sparkborn | 2 | 0.09 | +| 35 | Argus | 1 | 0.04 | +| 36 | Cassian Assayborn | 1 | 0.04 | +| 37 | Timmy | 1 | 0.04 | +| 38 | Timmy | 1 | 0.04 | +| 39 | Timmy | 1 | 0.04 | +| 40 | Volt | 1 | 0.04 | +| 41 | Volt | 1 | 0.04 | +| 42 | rockachopa | 1 | 0.04 | +| 43 | sentinel | 1 | 0.04 | +| 44 | timmy | 1 | 0.04 | +| 45 | timmy | 1 | 0.04 | +| 46 | volt | 1 | 0.04 | +| 47 | zephyrus-sparkborn | 1 | 0.04 | +| 48 | zephyrus-sparkborn | 1 | 0.04 | + +**Total: 2350 commits** across 48 distinct author identities. diff --git a/wizard-work/ledger/build_2026-10-31_git_author_census.py b/wizard-work/ledger/build_2026-10-31_git_author_census.py new file mode 100644 index 0000000..9e3f257 --- /dev/null +++ b/wizard-work/ledger/build_2026-10-31_git_author_census.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +"""Build the 2026-10-31 git-author census for the troupe-standup repo. + +Extract: author identities and commit counts from a pinned snapshot of the +worktree git history, and write a table (CSV + markdown). + +The census is a report ON the repo, committed AFTER it. To keep the check +honest (not a self-referential tautology), the artifact is verified against +the git snapshot it describes (SNAPSHOT), not against HEAD which includes the +census commit itself. SNAPSHOT is pinned to the pre-census tip so the check +stays stable as the repo keeps evolving. + +Run: + python3 build_2026-10-31_git_author_census.py # generate + python3 build_2026-10-31_git_author_census.py check # verify against SNAPSHOT +""" + +import csv +import os +import subprocess +import sys + +REPO = "/root/troupe-standup" +LEDGER_DIR = os.path.join(REPO, "wizard-work", "ledger") +CSV_NAME = "2026-10-31-git-author-census.csv" +MD_NAME = "2026-10-31-git-author-census.md" +ASN_DATE = "2026-10-31" +# Pre-census tip of main: the commit this census is a report ON. +SNAPSHOT = "0c2716235852ac9823082fb8938f1a6387fc4640" + + +def git_log(base): + proc = subprocess.run( + ["git", "log", base, "--format=%an|%ae"], + cwd=REPO, + check=True, + capture_output=True, + text=True, + ) + return proc.stdout + + +def git_author_census(base): + """Recompute from git; {author_identity: count}, identity = 'Name '.""" + counts = {} + for raw in git_log(base).splitlines(): + if not raw: + continue + name, _, email = raw.partition("|") + key = "{} <{}>".format(name.strip(), email.strip()) + counts[key] = counts.get(key, 0) + 1 + return counts + + +def write_artifacts(counts): + total = sum(counts.values()) + rows = sorted(counts.items(), key=lambda kv: (-kv[1], kv[0])) + os.makedirs(LEDGER_DIR, exist_ok=True) + + csv_path = os.path.join(LEDGER_DIR, CSV_NAME) + with open(csv_path, "w", newline="") as f: + w = csv.writer(f) + w.writerow(["rank", "author", "commits"]) + for i, (k, v) in enumerate(rows, 1): + w.writerow([i, k, v]) + + md_path = os.path.join(LEDGER_DIR, MD_NAME) + with open(md_path, "w") as f: + f.write("# Git author census ({date})\n\n".format(date=ASN_DATE)) + f.write("Snapshot: `git log` of the troupe worktree at `{snapshot}`\n".format( + snapshot=SNAPSHOT)) + f.write("({total} commits reachable before the census commit landed).\n\n".format( + total=total)) + f.write("Identity key is the author name plus email in `Name ` form as\n") + f.write("recorded by git; no canonicalization (e.g. `Timmy` vs `timmy`, or a\n") + f.write("stackchain.ai vs agents.invalid address, stays a distinct row).\n\n") + f.write("| rank | author | commits | pct |\n") + f.write("|---:|---|---:|---:|\n") + for i, (k, v) in enumerate(rows, 1): + pct = 100.0 * v / total if total else 0.0 + f.write("| {rank} | {author} | {commits} | {pct:.2f} |\n".format( + rank=i, author=k, commits=v, pct=pct)) + f.write("\n**Total: {total} commits** across {n} distinct author identities.\n".format( + total=total, n=len(rows))) + + return csv_path, md_path, total, SNAPSHOT + + +def verify(): + expected = git_author_census(SNAPSHOT) + total = sum(expected.values()) + csv_path = os.path.join(LEDGER_DIR, CSV_NAME) + md_path = os.path.join(LEDGER_DIR, MD_NAME) + + with open(csv_path, newline="") as f: + rows = list(csv.reader(f)) + + errs = [] + if not rows or rows[0] != ["rank", "author", "commits"]: + errs.append("CSV header wrong: {!r}".format(rows[0] if rows else None)) + body = rows[1:] + if len(body) != len(expected): + errs.append("row count {} != author count {}".format(len(body), len(expected))) + for i, row in enumerate(body, 1): + if len(row) != 3: + errs.append("bad row width: {!r}".format(row)) + continue + rank, author, commits = row + if str(i) != rank: + errs.append("rank mismatch at row {}: {!r}".format(i, rank)) + exp = expected.get(author) + if exp is None: + errs.append("author not in recomputed census: {!r}".format(author)) + elif str(exp) != commits: + errs.append("commits mismatch for {!r}: artifact {} expected {}".format( + author, commits, exp)) + + proc = subprocess.run( + ["git", "rev-list", "--count", SNAPSHOT], + cwd=REPO, check=True, capture_output=True, text=True) + if proc.stdout.strip() != str(total): + errs.append("snapshot commit total {} != census total {}".format( + proc.stdout.strip(), total)) + + md = open(md_path).read() + if "Total: {} commits".format(total) not in md: + errs.append("MD missing total line for {total}".format(total=total)) + + if errs: + print("FAIL:") + for e in errs: + print(" - " + e) + return 1 + + print("PASS: snapshot `{snapshot}` = {total} commits, {n} author identities; " + "{rows} CSV rows + MD match a fresh recompile from `git log {snapshot}`.".format( + snapshot=SNAPSHOT, total=total, n=len(expected), rows=len(body))) + return 0 + + +def main(): + mode = sys.argv[1] if len(sys.argv) > 1 else "generate" + if mode == "generate": + csv_path, md_path, total, snapshot = write_artifacts(git_author_census(SNAPSHOT)) + print("snapshot {snapshot} total commits:".format(snapshot=snapshot), total) + print("wrote", csv_path) + print("wrote", md_path) + return 0 + if mode == "check": + return verify() + print("usage: build_2026-10-31_git_author_census.py [generate|check]", + file=sys.stderr) + return 2 + + +if __name__ == "__main__": + sys.exit(main())