ledger: fix census snapshot to a8f8c39 (2253 commits); pin check
This commit is contained in:
1 parent
036f6d2163
commit
210f3ece92
2 files changed
+38
-26
No files matched your search
@@ -1,7 +1,7 @@
|
||||
# Git author census (2026-10-30)
|
||||
|
||||
Source: `git log` of the troupe worktree (`d9e4a66`, 2253 commits
|
||||
reachable from HEAD). Extracted 2026-10-30.
|
||||
Snapshot: `git log` of the troupe worktree at `a8f8c39` (2253 commits
|
||||
reachable from HEAD before this census was committed). Extracted 2026-10-30.
|
||||
|
||||
Identity key is the author name plus email in `Name <email>` form as
|
||||
recorded by git; no canonicalization (e.g. `Timmy` vs `timmy`, or a
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
#!/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.
|
||||
"""Git author census: extract author identities + commit counts from a snapshot of the
|
||||
worktree git history, write a table, and (as 'check') verify the artifact against a fresh
|
||||
recompile from `git log` of the pre-census snapshot (the commit the artifact represents).
|
||||
|
||||
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
|
||||
(HEAD^), not against HEAD which includes the census commit itself.
|
||||
"""
|
||||
import csv
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -12,19 +17,28 @@ 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"
|
||||
# Snapshot the census artifact describes: the pre-census tip of the worktree, i.e. the
|
||||
# commit the artifact was generated from (so the census commit's own author is not
|
||||
# counted in itself). Pinned to a fixed hash so the check stays stable as the repo
|
||||
# keeps evolving.
|
||||
SNAPSHOT = "a8f8c39"
|
||||
|
||||
|
||||
def git_author_census():
|
||||
"""Recompute from git; returns {author_identity: count} with identity = 'Name <email>'."""
|
||||
def git_log(base):
|
||||
proc = subprocess.run(
|
||||
["git", "log", "--format=%an|%ae"],
|
||||
["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 <email>'."""
|
||||
counts = {}
|
||||
for raw in proc.stdout.splitlines():
|
||||
for raw in git_log(base).splitlines():
|
||||
if not raw:
|
||||
continue
|
||||
name, _, email = raw.partition("|")
|
||||
@@ -36,8 +50,7 @@ def git_author_census():
|
||||
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)
|
||||
os.makedirs(LEDGER_DIR, exist_ok=True)
|
||||
|
||||
csv_path = LEDGER_DIR + "/" + CSV_NAME
|
||||
with open(csv_path, "w", newline="") as f:
|
||||
@@ -49,8 +62,10 @@ def write_artifacts(counts):
|
||||
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("Snapshot: `git log` of the troupe worktree at `{snapshot}` ({total} commits\n".format(
|
||||
snapshot=SNAPSHOT, total=total))
|
||||
f.write("reachable from HEAD before this census was committed). Extracted {date}.\n\n".format(
|
||||
date=ASN_DATE))
|
||||
f.write("Identity key is the author name plus email in `Name <email>` 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")
|
||||
@@ -66,7 +81,7 @@ def write_artifacts(counts):
|
||||
|
||||
|
||||
def verify(csv_path, md_path):
|
||||
expected = git_author_census()
|
||||
expected = git_author_census(SNAPSHOT)
|
||||
total = sum(expected.values())
|
||||
with open(csv_path, newline="") as f:
|
||||
rows = list(csv.reader(f))
|
||||
@@ -87,37 +102,34 @@ def verify(csv_path, md_path):
|
||||
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
|
||||
# independent total from the same snapshot
|
||||
proc = subprocess.run(
|
||||
["git", "rev-list", "--count", "HEAD"], cwd=REPO,
|
||||
["git", "rev-list", "--count", SNAPSHOT], 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
|
||||
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")
|
||||
if str(len(expected)) not in md.split("across ")[-1].split(" distinct")[0]:
|
||||
errs.append("MD row count wrong")
|
||||
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: {} 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)))
|
||||
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 "check"
|
||||
if mode == "generate":
|
||||
csv_path, md_path, total = write_artifacts(git_author_census())
|
||||
csv_path, md_path, total = write_artifacts(git_author_census(SNAPSHOT))
|
||||
print("wrote", csv_path)
|
||||
print("wrote", md_path)
|
||||
print("total commits:", total)
|
||||
print("snapshot {snapshot} total commits:".format(snapshot=SNAPSHOT), total)
|
||||
return 0
|
||||
if mode == "check":
|
||||
csv_path = LEDGER_DIR + "/" + CSV_NAME
|
||||
|
||||
Reference in new issue
Block a user