#!/usr/bin/env python3 """Extract the git commit census of the troupe-standup repo. Lane: Extract -- data extraction and tables. Source (single source of truth): git (local clone, branch main) -- every commit reachable from HEAD. Artifacts written beside this script (all re-derivable, none hand-typed): - commits-census.csv commits per author (unique author name) - commits-by-day.csv commits per calendar day (author date) - commits-full.csv one row per commit: hash, author, email, date, subject - README-commits-census.md Verification: verify_commits_census.py re-derives every table cell from git and exits 0 iff the committed tables match. The CHECK file runs that script. Run: python3 extract_commits_census.py """ import csv import os import subprocess import sys from collections import Counter REPO = "/root/troupe-standup" OUT = "/root/troupe-standup/wizard-work/ledger" # Pinned revision so the census is deterministic: other agents keep pushing to # main while this artifact is being produced. Verify against this hash only. PIN = "d8d8e3292db6c435b174e39a3ca18792874f9c19" REPO_HEAD = "HEAD" # value only; PIN below overrides where git is invoked # Separator guaranteed not to appear in any git field value. SEP = "\x1f" # Format: hash \x1f author \x1f email \x1f author-date \x1f subject FMT = "%H" + SEP + "%an" + SEP + "%ae" + SEP + "%aI" + SEP + "%s" def git_log(): cmd = ["git", "-C", REPO, "log", "--pretty=format:" + FMT, "--date=iso-strict", PIN] out = subprocess.run(cmd, check=True, capture_output=True, text=True).stdout rows = [] for c in out.splitlines(): if not c: continue h, an, ae, ad, s = c.split(SEP) rows.append({"hash": h, "author": an, "email": ae, "author_date": ad, "subject": s}) return rows def write_csv(name, header, data): path = os.path.join(OUT, name) with open(path, "w", newline="", encoding="utf-8") as f: w = csv.writer(f) w.writerow(header) w.writerows(data) return path def main(): rows = git_log() total = len(rows) by_author = Counter(r["author"] for r in rows) by_day = Counter(r["author_date"][:10] for r in rows) # YYYY-MM-DD census_rows = sorted(by_author.items(), key=lambda kv: (-kv[1], kv[0])) day_rows = sorted(by_day.items(), key=lambda kv: kv[0]) os.makedirs(OUT, exist_ok=True) write_csv("commits-census.csv", ["author", "commits"], [(a, c) for a, c in census_rows]) write_csv("commits-by-day.csv", ["date", "commits"], [(d, c) for d, c in day_rows]) write_csv("commits-full.csv", ["hash", "author", "email", "author_date", "subject"], [(r["hash"], r["author"], r["email"], r["author_date"], r["subject"]) for r in rows]) lines = [] lines.append("# Git commit census — troupe-standup") lines.append("") lines.append("Source: `git log --pretty=format:` over the pinned revision %s (fields: " "hash, author, email, author-date, subject)." % PIN) lines.append("") lines.append("Pinned revision (sha): `%s`" % PIN) lines.append("Total commits: **%d**" % total) lines.append("") lines.append("## Commits by author") lines.append("") lines.append("| author | commits |") lines.append("|---|---|") for a, c in census_rows: lines.append("| %s | %d |" % (a, c)) lines.append("| **total** | **%d** |" % total) lines.append("") lines.append("## Commits by calendar day") lines.append("") lines.append("| date | commits |") lines.append("|---|---|") for d, c in day_rows: lines.append("| %s | %d |" % (d, c)) lines.append("| **total** | **%d** |" % total) lines.append("") with open(os.path.join(OUT, "README-commits-census.md"), "w", encoding="utf-8") as f: f.write("\n".join(lines)) print("commits:", total) print("authors:", len(census_rows)) print("days:", len(day_rows)) print("wrote: commits-census.csv, commits-by-day.csv, commits-full.csv, README-commits-census.md") if __name__ == "__main__": sys.exit(main())