ledger: add commit-author census extract (23 authors, 2163 commits) with CHECK
This commit is contained in:
1 parent
5d10c3f6f6
commit
2615c329da
5 files changed
+268
No files matched your search
@@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# CHECK -- commit-author census extract (Extract lane, ledger).
|
||||||
|
#
|
||||||
|
# Replays `git log --format=%an` from the committed tree and diffs the derived
|
||||||
|
# author->count map against the committed commits-by-author.tsv and
|
||||||
|
# commits-by-author.json. Exit code IS the verdict:
|
||||||
|
# 0 = PASS (replay matches committed files)
|
||||||
|
# nonzero = FAIL
|
||||||
|
#
|
||||||
|
# No || true / ; true / ; echo arms, no trailing prose: the exit code is the
|
||||||
|
# verdict and a prose gloss is a fault (tools/check_lint.py).
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
# Resolve the repo root from git so the check is location-independent.
|
||||||
|
REPO="$(git rev-parse --show-toplevel)" || exit 1
|
||||||
|
ART="$REPO/wizard-work/ledger/2026-10-29-commit-author-census"
|
||||||
|
cd "$ART" || exit 1
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
out = subprocess.run(
|
||||||
|
["git", "log", "--format=%an"], capture_output=True, text=True, check=True
|
||||||
|
).stdout
|
||||||
|
counts = {}
|
||||||
|
for line in out.splitlines():
|
||||||
|
counts[line] = counts.get(line, 0) + 1
|
||||||
|
|
||||||
|
# Deterministic order: count desc, author asc (matches the committed TSV/JSON).
|
||||||
|
expected = sorted(counts.items(), key=lambda kv: (-kv[1], kv[0]))
|
||||||
|
|
||||||
|
with open("commits-by-author.tsv", encoding="utf-8") as fh:
|
||||||
|
tsv = list(csv.reader(fh, delimiter="\t"))
|
||||||
|
committed = [(r[0], int(r[1])) for r in tsv[1:]]
|
||||||
|
|
||||||
|
if len(expected) != len(committed):
|
||||||
|
print(f"FAIL: author count replay={len(expected)} committed={len(committed)}")
|
||||||
|
sys.exit(1)
|
||||||
|
for (a_exp, c_exp), (a_got, c_got) in zip(expected, committed):
|
||||||
|
if a_exp != a_got or c_exp != c_got:
|
||||||
|
print(f"FAIL: TSV author={a_exp}/{c_exp} got={a_got}/{c_got}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
with open("commits-by-author.json", encoding="utf-8") as fh:
|
||||||
|
j = json.load(fh)
|
||||||
|
if j.get("total_commits") != sum(c for _, c in expected):
|
||||||
|
print("FAIL: JSON total_commits mismatch")
|
||||||
|
sys.exit(1)
|
||||||
|
if j.get("authors") != len(expected):
|
||||||
|
print("FAIL: JSON authors mismatch")
|
||||||
|
sys.exit(1)
|
||||||
|
for (a_exp, c_exp), gl in zip(expected, j["rows"]):
|
||||||
|
if (a_exp, c_exp) != (gl["author"], gl["commits"]):
|
||||||
|
print(f"FAIL: JSON row {a_exp}/{c_exp} got {gl['author']}/{gl['commits']}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"PASS: {len(expected)} authors, {sum(c for _, c in expected)} commits "
|
||||||
|
f"(replay == commits-by-author.tsv + .json)"
|
||||||
|
)
|
||||||
|
PY
|
||||||
|
exit $?
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"generated_utc": "2026-10-29T17:00:00Z",
|
||||||
|
"source": "git log --format=%an",
|
||||||
|
"total_commits": 2163,
|
||||||
|
"authors": 23,
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"author": "Timmy",
|
||||||
|
"commits": 556
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ledger",
|
||||||
|
"commits": 239
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "timmy",
|
||||||
|
"commits": 209
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "spark",
|
||||||
|
"commits": 193
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Volt",
|
||||||
|
"commits": 189
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Zephyrus Sparkborn",
|
||||||
|
"commits": 129
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Merlin",
|
||||||
|
"commits": 118
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "beam",
|
||||||
|
"commits": 107
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "sol",
|
||||||
|
"commits": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "quill",
|
||||||
|
"commits": 77
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "volt",
|
||||||
|
"commits": 66
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "forge",
|
||||||
|
"commits": 62
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "sphinx",
|
||||||
|
"commits": 32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "null",
|
||||||
|
"commits": 28
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Mercury",
|
||||||
|
"commits": 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "pipe",
|
||||||
|
"commits": 18
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "zephyrus-sparkborn",
|
||||||
|
"commits": 14
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "troupe-pipe",
|
||||||
|
"commits": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Cassian Assayborn",
|
||||||
|
"commits": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "argus",
|
||||||
|
"commits": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Argus",
|
||||||
|
"commits": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "rockachopa",
|
||||||
|
"commits": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "sentinel",
|
||||||
|
"commits": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Commit-author census
|
||||||
|
|
||||||
|
Live extract of commit authorship from the repository at
|
||||||
|
revision `9aba6df` (HEAD), generated 2026-10-29 17:00Z (UTC).
|
||||||
|
|
||||||
|
| rank | author | commits |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | Timmy | 556 |
|
||||||
|
| 2 | ledger | 239 |
|
||||||
|
| 3 | timmy | 209 |
|
||||||
|
| 4 | spark | 193 |
|
||||||
|
| 5 | Volt | 189 |
|
||||||
|
| 6 | Zephyrus Sparkborn | 129 |
|
||||||
|
| 7 | Merlin | 118 |
|
||||||
|
| 8 | beam | 107 |
|
||||||
|
| 9 | sol | 90 |
|
||||||
|
| 10 | quill | 77 |
|
||||||
|
| 11 | volt | 66 |
|
||||||
|
| 12 | forge | 62 |
|
||||||
|
| 13 | sphinx | 32 |
|
||||||
|
| 14 | null | 28 |
|
||||||
|
| 15 | Mercury | 21 |
|
||||||
|
| 16 | pipe | 18 |
|
||||||
|
| 17 | zephyrus-sparkborn | 14 |
|
||||||
|
| 18 | troupe-pipe | 6 |
|
||||||
|
| 19 | Cassian Assayborn | 3 |
|
||||||
|
| 20 | argus | 3 |
|
||||||
|
| 21 | Argus | 1 |
|
||||||
|
| 22 | rockachopa | 1 |
|
||||||
|
| 23 | sentinel | 1 |
|
||||||
|
|
||||||
|
Total commits: 2163 | authors: 23
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
author commits
|
||||||
|
Timmy 556
|
||||||
|
ledger 239
|
||||||
|
timmy 209
|
||||||
|
spark 193
|
||||||
|
Volt 189
|
||||||
|
Zephyrus Sparkborn 129
|
||||||
|
Merlin 118
|
||||||
|
beam 107
|
||||||
|
sol 90
|
||||||
|
quill 77
|
||||||
|
volt 66
|
||||||
|
forge 62
|
||||||
|
sphinx 32
|
||||||
|
null 28
|
||||||
|
Mercury 21
|
||||||
|
pipe 18
|
||||||
|
zephyrus-sparkborn 14
|
||||||
|
troupe-pipe 6
|
||||||
|
Cassian Assayborn 3
|
||||||
|
argus 3
|
||||||
|
Argus 1
|
||||||
|
rockachopa 1
|
||||||
|
sentinel 1
|
||||||
|
@@ -0,0 +1,46 @@
|
|||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
# True source of truth: the repo's git history, author by author.
|
||||||
|
out = subprocess.run(
|
||||||
|
["git", "log", "--format=%an"], capture_output=True, text=True, check=True
|
||||||
|
).stdout
|
||||||
|
counts = {}
|
||||||
|
for line in out.splitlines():
|
||||||
|
counts[line] = counts.get(line, 0) + 1
|
||||||
|
|
||||||
|
# Deterministic order: count desc, author asc.
|
||||||
|
rows = sorted(counts.items(), key=lambda kv: (-kv[1], kv[0]))
|
||||||
|
|
||||||
|
with open("commits-by-author.tsv", "w", encoding="utf-8") as fh:
|
||||||
|
w = csv.writer(fh, delimiter="\t", lineterminator="\n")
|
||||||
|
w.writerow(["author", "commits"])
|
||||||
|
for author, commits in rows:
|
||||||
|
w.writerow([author, commits])
|
||||||
|
|
||||||
|
total = sum(c for _, c in rows)
|
||||||
|
with open("commits-by-author.json", "w", encoding="utf-8") as fh:
|
||||||
|
json.dump(
|
||||||
|
{
|
||||||
|
"generated_utc": "2026-10-29T17:00:00Z",
|
||||||
|
"source": "git log --format=%an",
|
||||||
|
"total_commits": total,
|
||||||
|
"authors": len(rows),
|
||||||
|
"rows": [{"author": a, "commits": c} for a, c in rows],
|
||||||
|
},
|
||||||
|
fh,
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
fh.write("\n")
|
||||||
|
|
||||||
|
with open("commits-by-author.md", "w", encoding="utf-8") as fh:
|
||||||
|
fh.write(
|
||||||
|
"# Commit-author census\n\nLive extract of commit authorship from the repository at\nrevision `9aba6df` (HEAD), generated 2026-10-29 17:00Z (UTC).\n\n| rank | author | commits |\n|---|---|---|\n"
|
||||||
|
)
|
||||||
|
for i, (author, commits) in enumerate(rows, 1):
|
||||||
|
fh.write(f"| {i} | {author} | {commits} |\n")
|
||||||
|
fh.write(f"\nTotal commits: {total} | authors: {len(rows)}\n")
|
||||||
|
|
||||||
|
print("total_commits:", total)
|
||||||
|
print("authors:", len(rows))
|
||||||
Reference in new issue
Block a user