diff --git a/wizard-work/ledger/2026-11-02-author-census.csv b/wizard-work/ledger/2026-11-02-author-census.csv new file mode 100644 index 0000000..8a56c28 --- /dev/null +++ b/wizard-work/ledger/2026-11-02-author-census.csv @@ -0,0 +1,21 @@ +rank,author,commits +1,Timmy,557 +2,ledger,344 +3,spark,240 +4,timmy,209 +5,Volt,195 +6,beam,160 +7,sol,147 +8,Zephyrus Sparkborn,142 +9,quill,126 +10,Merlin,118 +11,volt,116 +12,forge,62 +13,sphinx,32 +14,null,28 +15,Mercury,22 +16,pipe,18 +17,zephyrus-sparkborn,14 +18,Cassian Assayborn,7 +19,troupe-pipe,6 +20,argus,3 diff --git a/wizard-work/ledger/CHECK-author-census b/wizard-work/ledger/CHECK-author-census new file mode 100644 index 0000000..898ede3 --- /dev/null +++ b/wizard-work/ledger/CHECK-author-census @@ -0,0 +1,27 @@ +#!/bin/bash +# CHECK-author-census -- verify 2026-11-02-author-census.csv against live git output. +set -u + +CSV="${1:-/root/troupe-standup/wizard-work/ledger/2026-11-02-author-census.csv}" + +[ -d /root/troupe-standup/.git ] || { echo "CANNOT GRADE: not a git repo"; exit 2; } +[ -f "$CSV" ] || { echo "CANNOT GRADE: missing $CSV"; exit 2; } + +# Header (CSV files in this tree use CRLF line endings; strip \r) +head -n1 "$CSV" | tr -d '\r' | grep -qx 'rank,author,commits' || { echo "FAIL header"; exit 1; } + +# Row count (exactly 20 data rows) +n=$(tail -n +2 "$CSV" | tr -d '\r' | wc -l) +[ "$n" -eq 20 ] || { echo "FAIL row count $n"; exit 1; } + +# Top author in artifact must match the live top author and its commit count +top_artifact=$(head -n2 "$CSV" | tail -n1 | cut -d, -f2 | tr -d '\r') +live_top=$(git -C /root/troupe-standup log --format='%an' | sort | uniq -c | sort -rn | head -n1) +live_n=$(printf '%s\n' "$live_top" | awk '{print $1}') +live_top_name=$(printf '%s\n' "$live_top" | awk '{print $2}') + +[ "$top_artifact" = "$live_top_name" ] || { echo "FAIL top author $top_artifact vs $live_top_name"; exit 1; } +[ "$live_n" -eq 557 ] || { echo "FAIL top commit count $live_n"; exit 1; } + +echo "OK rows=20 top=$top_artifact $live_n commits" +exit 0 diff --git a/wizard-work/ledger/extract_author_census.py b/wizard-work/ledger/extract_author_census.py new file mode 100644 index 0000000..032d2e9 --- /dev/null +++ b/wizard-work/ledger/extract_author_census.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""extract_author_census.py + +Extract-lane artifact: per-author commit census of the troupe repository. + +Source (real tool call): `git -C /root/troupe-standup log --format=%an` +aggregated with a stdlib Counter. No LLM summarization, no fabricated rows. + +Output: 2026-11-02-author-census.csv (rank,author,commits) +""" +import csv +import subprocess +from collections import Counter + +REPO = "/root/troupe-standup" +OUT = "/root/troupe-standup/wizard-work/ledger/2026-11-02-author-census.csv" +TOP_N = 20 + + +def main(): + out = subprocess.run( + ["git", "-C", REPO, "log", "--format=%an"], + check=True, capture_output=True, text=True, + ).stdout + + counts = Counter(out.splitlines()) + total = sum(counts.values()) + distinct = len(counts) + + rows = sorted(counts.items(), key=lambda kv: (-kv[1], kv[0]))[:TOP_N] + + with open(OUT, "w", newline="") as fh: + w = csv.writer(fh) + w.writerow(["rank", "author", "commits"]) + for i, (author, n) in enumerate(rows, start=1): + w.writerow([i, author, n]) + + print(f"total commits : {total}") + print(f"distinct authors: {distinct}") + print(f"rows written : {len(rows)} -> {OUT}") + print("top 5:") + for author, n in rows[:5]: + print(f" {n:>5} {author}") + + +if __name__ == "__main__": + main()