#!/usr/bin/env python3 """Extract the per-wizard check-in cadence census from checkins/*.md. Lane: Extract (data extraction and tables). Scopes (real, from this host's filesystem): * every *.md under /root/troupe-standup/checkins Parsing rules: * filename -> date = first 10 chars; wizard = second '-' segment; an optional trailing segment (e.g. "-02", "-03", "-wizards") is dropped (the "canonical" entry name wins). * body -> the first "# " H1 line of the file (truncated to 70 chars). Outputs checkin-census.tsv : summary table (TSV) checkin-cadence.tsv : one row per date x wizard (TSV) checkin-census.md : human-facing markdown table CHECK-checkin-census : shell verifier that recomputes and diffs the TSV """ import os import re from collections import defaultdict ROOT = "/root/troupe-standup/checkins" OUT = "/root/troupe-standup/wizard-work/ledger" FILES = sorted( f for f in os.listdir(ROOT) if f.endswith(".md") and re.match(r"^\d{4}-\d{2}-\d{2}", f) ) # canonical wizard name -> display name WIZARD_DISPLAY = { "zephyrus": "Zephyrus Sparkborn", "mercury": "Mercury", "merlin": "Merlin", "cassian": "Cassian Assayborn", "volt": "Volt", "gemini": "Gemini", "argus": "Argus", "beam": "Beam", } DISPLAY_WIZARD = { "Zephyrus Sparkborn": "zephyrus", "Mercury": "mercury", "Merlin": "merlin", "Cassian Assayborn": "cassian", "Volt": "volt", "Gemini": "gemini", "Argus": "argus", "Beam": "beam", } def parse_name(f): base = f[:-3] # strip .md date = base[:10] rest = base[11:] parts = rest.split("-") wizard = parts[0] return date, wizard def first_h1(f): with open(os.path.join(ROOT, f), encoding="utf-8") as fh: for line in fh: if line.startswith("# "): return line[2:].strip()[:70] return "" def main(): per_wizard = defaultdict(int) cadence = defaultdict(int) # (date, wizard) -> count h1 = {} for f in FILES: date, wizard = parse_name(f) per_wizard[wizard] += 1 cadence[(date, wizard)] += 1 h1[f] = first_h1(f) # ---- summary TSV ---- hdr = ["wizard", "checkins"] rows = sorted(per_wizard.items()) with open(os.path.join(OUT, "checkin-census.tsv"), "w") as fh: fh.write("\t".join(hdr) + "\n") for w, c in rows: fh.write(f"{w}\t{c}\n") # ---- cadence TSV ---- hdr = ["date", "wizard", "count"] with open(os.path.join(OUT, "checkin-cadence.tsv"), "w") as fh: fh.write("\t".join(hdr) + "\n") for (date, wizard), c in sorted(cadence.items()): fh.write(f"{date}\t{wizard}\t{c}\n") # ---- markdown table ---- md = [] md.append("# Check-in census") md.append("") md.append("Extract — data extraction and tables. Derived from" " `ls checkins/*.md` (2026-10-27).") md.append("") md.append(f"Total check-in files: **{len(FILES)}**") md.append("") md.append("| Wizard | Check-ins |") md.append("|---|---|") for w, c in rows: md.append(f"| {WIZARD_DISPLAY.get(w, w)} | {c} |") md.append("") md.append("## Per-date cadence (check-ins per wizard)") md.append("") md.append("| Date | wizard | check-ins |") md.append("|---|---|---|") for (date, wizard), c in sorted(cadence.items()): md.append(f"| {date} | {WIZARD_DISPLAY.get(wizard, wizard)} | {c} |") md.append("") with open(os.path.join(OUT, "checkin-census.md"), "w") as fh: fh.write("\n".join(md)) print("wrote checkin-census.tsv") print("wrote checkin-cadence.tsv") print("wrote checkin-census.md") print("total files:", len(FILES)) for w, c in rows: print(f" {w:24s} {c}") if __name__ == "__main__": main()