From 036f6d21637fd3cb88f00d8514d40627809ee66b Mon Sep 17 00:00:00 2001 From: ledger Date: Fri, 30 Oct 2026 15:38:56 +0000 Subject: [PATCH] ledger: git author census 2026-10-30 (48 identities, 2253 commits, git log) --- .../ledger/2026-10-30-git-author-census.csv | 49 +++++++ .../ledger/2026-10-30-git-author-census.md | 61 ++++++++ wizard-work/ledger/check_git_author_census.py | 131 ++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 wizard-work/ledger/2026-10-30-git-author-census.csv create mode 100644 wizard-work/ledger/2026-10-30-git-author-census.md create mode 100644 wizard-work/ledger/check_git_author_census.py diff --git a/wizard-work/ledger/2026-10-30-git-author-census.csv b/wizard-work/ledger/2026-10-30-git-author-census.csv new file mode 100644 index 0000000..b049d39 --- /dev/null +++ b/wizard-work/ledger/2026-10-30-git-author-census.csv @@ -0,0 +1,49 @@ +rank,author,commits +1,Timmy ,464 +2,ledger ,257 +3,spark ,220 +4,Volt ,178 +5,timmy ,156 +6,Zephyrus Sparkborn ,132 +7,beam ,119 +8,Merlin ,118 +9,sol ,99 +10,quill ,87 +11,forge ,62 +12,Timmy ,49 +13,timmy ,41 +14,Timmy ,38 +15,volt ,33 +16,sphinx ,32 +17,null ,28 +18,volt ,23 +19,Mercury ,22 +20,pipe ,18 +21,timmy ,10 +22,volt ,9 +23,zephyrus-sparkborn ,7 +24,troupe-pipe ,6 +25,Volt ,5 +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-30-git-author-census.md b/wizard-work/ledger/2026-10-30-git-author-census.md new file mode 100644 index 0000000..ddb8ba5 --- /dev/null +++ b/wizard-work/ledger/2026-10-30-git-author-census.md @@ -0,0 +1,61 @@ +# Git author census (2026-10-30) + +Source: `git log` of the troupe worktree (`d9e4a66`, 2253 commits +reachable from HEAD). Extracted 2026-10-30. + +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 | 20.59 | +| 2 | ledger | 257 | 11.41 | +| 3 | spark | 220 | 9.76 | +| 4 | Volt | 178 | 7.90 | +| 5 | timmy | 156 | 6.92 | +| 6 | Zephyrus Sparkborn | 132 | 5.86 | +| 7 | beam | 119 | 5.28 | +| 8 | Merlin | 118 | 5.24 | +| 9 | sol | 99 | 4.39 | +| 10 | quill | 87 | 3.86 | +| 11 | forge | 62 | 2.75 | +| 12 | Timmy | 49 | 2.17 | +| 13 | timmy | 41 | 1.82 | +| 14 | Timmy | 38 | 1.69 | +| 15 | volt | 33 | 1.46 | +| 16 | sphinx | 32 | 1.42 | +| 17 | null | 28 | 1.24 | +| 18 | volt | 23 | 1.02 | +| 19 | Mercury | 22 | 0.98 | +| 20 | pipe | 18 | 0.80 | +| 21 | timmy | 10 | 0.44 | +| 22 | volt | 9 | 0.40 | +| 23 | zephyrus-sparkborn | 7 | 0.31 | +| 24 | troupe-pipe | 6 | 0.27 | +| 25 | Volt | 5 | 0.22 | +| 26 | volt | 5 | 0.22 | +| 27 | volt | 4 | 0.18 | +| 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: 2253 commits** across 48 distinct author identities. diff --git a/wizard-work/ledger/check_git_author_census.py b/wizard-work/ledger/check_git_author_census.py new file mode 100644 index 0000000..1f648c3 --- /dev/null +++ b/wizard-work/ledger/check_git_author_census.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +"""Git author census: extract author identities + commit counts from the worktree +git history, write a table, and (as 'check') verify the artifact against a fresh +recompile from `git log`. Pure extraction; no fabricated numbers. +""" +import csv +import subprocess +import sys + +REPO = "/root/troupe-standup" +LEDGER_DIR = REPO + "/wizard-work/ledger" +CSV_NAME = "2026-10-30-git-author-census.csv" +MD_NAME = "2026-10-30-git-author-census.md" +ASN_DATE = "2026-10-30" + + +def git_author_census(): + """Recompute from git; returns {author_identity: count} with identity = 'Name '.""" + proc = subprocess.run( + ["git", "log", "--format=%an|%ae"], + cwd=REPO, + check=True, + capture_output=True, + text=True, + ) + counts = {} + for raw in proc.stdout.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_dir = __import__("os") + os_dir.makedirs(LEDGER_DIR, exist_ok=True) + + csv_path = 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 = 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("Source: `git log` of the troupe worktree (`d9e4a66`, {total} commits\n".format(total=total)) + f.write("reachable from HEAD). Extracted {date}.\n\n".format(date=ASN_DATE)) + 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 + + +def verify(csv_path, md_path): + expected = git_author_census() + total = sum(expected.values()) + 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)) + # independent total from the commit object count + proc = subprocess.run( + ["git", "rev-list", "--count", "HEAD"], cwd=REPO, + check=True, capture_output=True, text=True) + if proc.stdout.strip() != str(total): + errs.append("rev-list total {} != census total {}".format(proc.stdout.strip(), total)) + # md should contain the total and the correct number of rows + md = open(md_path).read() + if "Total: {} commits".format(total) not in md: + errs.append("MD missing total line") + if str(len(expected)) not in md.split("across ")[-1].split(" distinct")[0]: + errs.append("MD row count wrong") + + if errs: + print("FAIL:") + for e in errs: + print(" - " + e) + return 1 + print("PASS: {} author identities, {} commits; {} CSV rows + MD match a fresh " + "recompile from `git log` and `git rev-list --count HEAD`.".format( + len(expected), total, len(body))) + return 0 + + +def main(): + mode = sys.argv[1] if len(sys.argv) > 1 else "check" + if mode == "generate": + csv_path, md_path, total = write_artifacts(git_author_census()) + print("wrote", csv_path) + print("wrote", md_path) + print("total commits:", total) + return 0 + if mode == "check": + csv_path = LEDGER_DIR + "/" + CSV_NAME + md_path = LEDGER_DIR + "/" + MD_NAME + return verify(csv_path, md_path) + print("usage: check_git_author_census.py [generate|check]", file=sys.stderr) + return 2 + + +if __name__ == "__main__": + sys.exit(main())