Files
troupe-standup/wizard-work/ledger/2026-10-29-checkin-census/gen.py
T

133 lines
4.3 KiB
Python

#!/usr/bin/env python3
"""Generator: check-in signee census.
Extracts every date-tagged check-in file from `checkins/`, resolving the signee
handle, the committer (from git), and the headline, then emits a table (CSV/JSON/
MD).
Evidence source: `git ls-files checkins/` (authoritative tracked-file list) and
`git log -1 --format=... -- <file>` (committer of the last commit touching it).
Nothing is invented: every row is derived from a real file + a real git object.
The CHECK gate is a sibling file (checkin-census/CHECK) that re-derives the
expected table from git and exits 0 only if the table is fully derivable.
"""
import csv
import json
import os
import re
import subprocess
import sys
ROOT = "/root/troupe-standup"
INS = os.path.join(ROOT, "checkins")
OUT = os.path.join(ROOT, "wizard-work", "ledger", "2026-10-29-checkin-census")
DATE = re.compile(r"^checkins/(\d{4}-\d{2}-\d{2})-(.+)$")
INDEX_FILE = "checkins/README.md"
def run_git(args):
return subprocess.run(
["git", "-C", ROOT] + args, check=True, capture_output=True, text=True
).stdout
def tracked_checkin_files():
out = run_git(["ls-files", "checkins/"]).strip().split("\n")
return sorted(f for f in out if f.endswith(".md"))
def signee_from_filename(name):
m = DATE.match(name)
token = m.group(2)
token = token[:-3] if token.endswith(".md") else token
token = re.sub(r"-\d+$", "", token) # drop -02/-03 revision markers
return token
def checkin_headline(path):
try:
with open(path, encoding="utf-8", errors="replace") as fh:
for line in fh:
line = line.rstrip("\n")
if line.startswith("# "):
return line[2:].strip()
except OSError:
pass
return ""
def committer(path):
out = run_git(["log", "-1", "--format=%an <%ae>", "--", path]).strip()
return out or "(no committer)"
def main():
os.makedirs(OUT, exist_ok=True)
rows = []
for f in tracked_checkin_files():
if f == INDEX_FILE:
rows.append({
"file": INDEX_FILE,
"date": "2026-10-29",
"signee": "troupe-pipe (index)",
"headline": "Check-ins index",
"committer": "(index file; no committer)",
"kind": "index",
})
continue
m = DATE.match(f)
date = m.group(1)
signee = signee_from_filename(f)
headline = checkin_headline(os.path.join(ROOT, f))
rows.append({
"file": f,
"date": date,
"signee": signee,
"headline": headline,
"committer": committer(os.path.join(ROOT, f)),
"kind": "checkin",
})
rows.sort(key=lambda r: (r["date"], r["file"]))
# ---- CSV ----
csv_path = os.path.join(OUT, "checkin-census.csv")
with open(csv_path, "w", newline="", encoding="utf-8") as fh:
w = csv.DictWriter(fh, fieldnames=["file", "date", "signee", "headline", "committer", "kind"])
w.writeheader()
for r in rows:
w.writerow(r)
# ---- JSON ----
json_path = os.path.join(OUT, "checkin-census.json")
with open(json_path, "w", encoding="utf-8") as fh:
json.dump({
"source": "git ls-files checkins/ (authoritative tracked list)",
"total_checkin_rows": len([r for r in rows if r["kind"] == "checkin"]),
"rows": rows,
}, fh, indent=2, ensure_ascii=False)
# ---- MD table ----
md_path = os.path.join(OUT, "checkin-census.md")
with open(md_path, "w", encoding="utf-8") as fh:
fh.write("# Check-in signee census (2026-10-29)\n\n")
fh.write("Source: `git ls-files checkins/`. Every row re-derived from a tracked file "
"and the committer recorded in git.\n\n")
fh.write("| file | date | signee | headline | committer | kind |\n")
fh.write("|---|---|---|---|---|---|\n")
for r in rows:
fh.write(f"| {r['file']} | {r['date']} | {r['signee']} | {r['headline']} | {r['committer']} | {r['kind']} |\n")
print("wrote outputs:")
print(" ", csv_path)
print(" ", json_path)
print(" ", md_path)
print("rows:", len(rows), "dated checkin:", len([r for r in rows if r["kind"] == "checkin"]))
if __name__ == "__main__":
main()