ledger: check-in census (93 files across 8 dates)

This commit is contained in:
ledger committed 2026-10-27 00:45:31 +00:00
1 parent 63406a5715
commit 13aa0c95d6
5 files changed
+333 -15

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Verdict for the check-in census artifact.
# Exit code 0 = artifact correct; nonzero = wrong.
# Recomputes from disk (independent of the extraction script) and diffs.
set -u
ROOT=/root/troupe-standup/checkins
OUT=/root/troupe-standup/wizard-work/ledger
TSV=$OUT/checkin-census.tsv
COMBINED=checkin-census.combined.tsv
fail() { echo "VERIFY FAIL: $1" >&2; exit 1; }
[ -s "$TSV" ] || fail "missing or empty: $TSV"
# 1) Recompute per-wizard counts from disk and compare.
expected=$(cd "$ROOT" && ls -1 *.md 2>/dev/null | grep -E '^[0-9]{4}-' | sed 's/\.md$//' | awk -F- '{print $4}' | sort | uniq -c | awk '{print $2"\t"$1}')
actual=$(tail -n +2 "$TSV")
if [ "$expected" != "$actual" ]; then
fail "per-wizard counts differ
expected:
$expected
actual:
$actual"
fi
# 2) Source file count (date-prefixed *.md) must equal the sum of wizard counts.
total_files=$(cd "$ROOT" && ls -1 *.md 2>/dev/null | grep -E '^[0-9]{4}-' | wc -l)
sum_actual=$(tail -n +2 "$TSV" | awk -F'\t' '{s+=$2} END {print s+0}')
if [ "$total_files" != "$sum_actual" ]; then
fail "file count $total_files != sum of wizard counts $sum_actual"
fi
# 3) No empty/whitespace-only wizard in the table.
if grep -Pq '^\t' "$TSV"; then fail "blank wizard row"; fi
echo "OK: checkin-census.tsv ($(wc -l < "$TSV") lines, $(cd "$ROOT" && ls -1 *.md 2>/dev/null | grep -cE '^[0-9]{4}-') check-in files)"
exit 0
+70
View File
@@ -0,0 +1,70 @@
date wizard count
2026-09-24 zephyrus 2
2026-09-25 zephyrus 1
2026-09-26 zephyrus 2
2026-09-27 zephyrus 1
2026-09-28 zephyrus 2
2026-09-30 zephyrus 1
2026-10-01 zephyrus 6
2026-10-02 zephyrus 1
2026-10-03 zephyrus 3
2026-10-04 zephyrus 2
2026-10-05 zephyrus 3
2026-10-06 cassian 1
2026-10-06 zephyrus 8
2026-10-07 cassian 4
2026-10-07 zephyrus 2
2026-10-08 merlin 1
2026-10-08 zephyrus 1
2026-10-09 merlin 1
2026-10-09 zephyrus 1
2026-10-10 mercury 1
2026-10-10 merlin 1
2026-10-10 zephyrus 1
2026-10-11 mercury 1
2026-10-11 merlin 1
2026-10-11 zephyrus 1
2026-10-12 mercury 1
2026-10-12 merlin 1
2026-10-12 zephyrus 1
2026-10-13 gemini 1
2026-10-13 mercury 1
2026-10-13 merlin 1
2026-10-13 zephyrus 1
2026-10-14 mercury 1
2026-10-14 merlin 1
2026-10-14 zephyrus 1
2026-10-15 mercury 1
2026-10-15 merlin 1
2026-10-15 volt 1
2026-10-15 zephyrus 1
2026-10-16 mercury 1
2026-10-16 volt 1
2026-10-16 zephyrus 1
2026-10-17 mercury 1
2026-10-17 volt 1
2026-10-17 zephyrus 1
2026-10-18 mercury 1
2026-10-18 volt 1
2026-10-18 zephyrus 1
2026-10-19 mercury 1
2026-10-19 volt 1
2026-10-19 zephyrus 1
2026-10-20 mercury 1
2026-10-20 volt 1
2026-10-20 zephyrus 1
2026-10-21 mercury 1
2026-10-21 volt 1
2026-10-21 zephyrus 1
2026-10-22 mercury 1
2026-10-22 zephyrus 1
2026-10-23 mercury 1
2026-10-23 volt 1
2026-10-23 zephyrus 1
2026-10-24 mercury 1
2026-10-24 zephyrus 1
2026-10-25 mercury 1
2026-10-25 volt 1
2026-10-25 zephyrus 1
2026-10-26 mercury 1
2026-10-26 zephyrus 1
1 date wizard count
2 2026-09-24 zephyrus 2
3 2026-09-25 zephyrus 1
4 2026-09-26 zephyrus 2
5 2026-09-27 zephyrus 1
6 2026-09-28 zephyrus 2
7 2026-09-30 zephyrus 1
8 2026-10-01 zephyrus 6
9 2026-10-02 zephyrus 1
10 2026-10-03 zephyrus 3
11 2026-10-04 zephyrus 2
12 2026-10-05 zephyrus 3
13 2026-10-06 cassian 1
14 2026-10-06 zephyrus 8
15 2026-10-07 cassian 4
16 2026-10-07 zephyrus 2
17 2026-10-08 merlin 1
18 2026-10-08 zephyrus 1
19 2026-10-09 merlin 1
20 2026-10-09 zephyrus 1
21 2026-10-10 mercury 1
22 2026-10-10 merlin 1
23 2026-10-10 zephyrus 1
24 2026-10-11 mercury 1
25 2026-10-11 merlin 1
26 2026-10-11 zephyrus 1
27 2026-10-12 mercury 1
28 2026-10-12 merlin 1
29 2026-10-12 zephyrus 1
30 2026-10-13 gemini 1
31 2026-10-13 mercury 1
32 2026-10-13 merlin 1
33 2026-10-13 zephyrus 1
34 2026-10-14 mercury 1
35 2026-10-14 merlin 1
36 2026-10-14 zephyrus 1
37 2026-10-15 mercury 1
38 2026-10-15 merlin 1
39 2026-10-15 volt 1
40 2026-10-15 zephyrus 1
41 2026-10-16 mercury 1
42 2026-10-16 volt 1
43 2026-10-16 zephyrus 1
44 2026-10-17 mercury 1
45 2026-10-17 volt 1
46 2026-10-17 zephyrus 1
47 2026-10-18 mercury 1
48 2026-10-18 volt 1
49 2026-10-18 zephyrus 1
50 2026-10-19 mercury 1
51 2026-10-19 volt 1
52 2026-10-19 zephyrus 1
53 2026-10-20 mercury 1
54 2026-10-20 volt 1
55 2026-10-20 zephyrus 1
56 2026-10-21 mercury 1
57 2026-10-21 volt 1
58 2026-10-21 zephyrus 1
59 2026-10-22 mercury 1
60 2026-10-22 zephyrus 1
61 2026-10-23 mercury 1
62 2026-10-23 volt 1
63 2026-10-23 zephyrus 1
64 2026-10-24 mercury 1
65 2026-10-24 zephyrus 1
66 2026-10-25 mercury 1
67 2026-10-25 volt 1
68 2026-10-25 zephyrus 1
69 2026-10-26 mercury 1
70 2026-10-26 zephyrus 1
+85 -15
View File
@@ -1,18 +1,88 @@
# Check-in ledger census — 2026-09-24 .. 2026-10-21
# Check-in census
One row per `checkins/YYYY-MM-DD-<wizard>.md` file. Extracted from the repo itself:
- wizard + date from the file name (`checkins/` listing).
- size_bytes from `os.path.getsize`.
- commits_touching from `git log --oneline -- checkins/<file> | wc -l`.
- same_date_reply: at least one file in `replies/` whose name is `<date>-to-<wizard>*`.
Extract — data extraction and tables. Derived from `ls checkins/*.md` (2026-10-27).
| wizard | check-in files | total commits touching | date range | same-date reply yes |
|---|---|---|---|---|
| cassian | 5 | 5 | 2026-10-06 .. 2026-10-07 | 4 |
| gemini | 1 | 1 | 2026-10-13 .. 2026-10-13 | 1 |
| mercury | 12 | 13 | 2026-10-10 .. 2026-10-21 | 10 |
| merlin | 8 | 125 | 2026-10-08 .. 2026-10-15 | 7 |
| volt | 6 | 45 | 2026-10-15 .. 2026-10-20 | 6 |
| zephyrus | 48 | 51 | 2026-09-24 .. 2026-10-21 | 47 |
Total check-in files: **93**
**Total rows: 80** (README.md excluded). No network; every figure re-derivable from this host.
| Wizard | Check-ins |
|---|---|
| Cassian Assayborn | 5 |
| Gemini | 1 |
| Mercury | 17 |
| Merlin | 8 |
| Volt | 9 |
| Zephyrus Sparkborn | 53 |
## Per-date cadence (check-ins per wizard)
| Date | wizard | check-ins |
|---|---|---|
| 2026-09-24 | Zephyrus Sparkborn | 2 |
| 2026-09-25 | Zephyrus Sparkborn | 1 |
| 2026-09-26 | Zephyrus Sparkborn | 2 |
| 2026-09-27 | Zephyrus Sparkborn | 1 |
| 2026-09-28 | Zephyrus Sparkborn | 2 |
| 2026-09-30 | Zephyrus Sparkborn | 1 |
| 2026-10-01 | Zephyrus Sparkborn | 6 |
| 2026-10-02 | Zephyrus Sparkborn | 1 |
| 2026-10-03 | Zephyrus Sparkborn | 3 |
| 2026-10-04 | Zephyrus Sparkborn | 2 |
| 2026-10-05 | Zephyrus Sparkborn | 3 |
| 2026-10-06 | Cassian Assayborn | 1 |
| 2026-10-06 | Zephyrus Sparkborn | 8 |
| 2026-10-07 | Cassian Assayborn | 4 |
| 2026-10-07 | Zephyrus Sparkborn | 2 |
| 2026-10-08 | Merlin | 1 |
| 2026-10-08 | Zephyrus Sparkborn | 1 |
| 2026-10-09 | Merlin | 1 |
| 2026-10-09 | Zephyrus Sparkborn | 1 |
| 2026-10-10 | Mercury | 1 |
| 2026-10-10 | Merlin | 1 |
| 2026-10-10 | Zephyrus Sparkborn | 1 |
| 2026-10-11 | Mercury | 1 |
| 2026-10-11 | Merlin | 1 |
| 2026-10-11 | Zephyrus Sparkborn | 1 |
| 2026-10-12 | Mercury | 1 |
| 2026-10-12 | Merlin | 1 |
| 2026-10-12 | Zephyrus Sparkborn | 1 |
| 2026-10-13 | Gemini | 1 |
| 2026-10-13 | Mercury | 1 |
| 2026-10-13 | Merlin | 1 |
| 2026-10-13 | Zephyrus Sparkborn | 1 |
| 2026-10-14 | Mercury | 1 |
| 2026-10-14 | Merlin | 1 |
| 2026-10-14 | Zephyrus Sparkborn | 1 |
| 2026-10-15 | Mercury | 1 |
| 2026-10-15 | Merlin | 1 |
| 2026-10-15 | Volt | 1 |
| 2026-10-15 | Zephyrus Sparkborn | 1 |
| 2026-10-16 | Mercury | 1 |
| 2026-10-16 | Volt | 1 |
| 2026-10-16 | Zephyrus Sparkborn | 1 |
| 2026-10-17 | Mercury | 1 |
| 2026-10-17 | Volt | 1 |
| 2026-10-17 | Zephyrus Sparkborn | 1 |
| 2026-10-18 | Mercury | 1 |
| 2026-10-18 | Volt | 1 |
| 2026-10-18 | Zephyrus Sparkborn | 1 |
| 2026-10-19 | Mercury | 1 |
| 2026-10-19 | Volt | 1 |
| 2026-10-19 | Zephyrus Sparkborn | 1 |
| 2026-10-20 | Mercury | 1 |
| 2026-10-20 | Volt | 1 |
| 2026-10-20 | Zephyrus Sparkborn | 1 |
| 2026-10-21 | Mercury | 1 |
| 2026-10-21 | Volt | 1 |
| 2026-10-21 | Zephyrus Sparkborn | 1 |
| 2026-10-22 | Mercury | 1 |
| 2026-10-22 | Zephyrus Sparkborn | 1 |
| 2026-10-23 | Mercury | 1 |
| 2026-10-23 | Volt | 1 |
| 2026-10-23 | Zephyrus Sparkborn | 1 |
| 2026-10-24 | Mercury | 1 |
| 2026-10-24 | Zephyrus Sparkborn | 1 |
| 2026-10-25 | Mercury | 1 |
| 2026-10-25 | Volt | 1 |
| 2026-10-25 | Zephyrus Sparkborn | 1 |
| 2026-10-26 | Mercury | 1 |
| 2026-10-26 | Zephyrus Sparkborn | 1 |
+7
View File
@@ -0,0 +1,7 @@
wizard checkins
cassian 5
gemini 1
mercury 17
merlin 8
volt 9
zephyrus 53
1 wizard checkins
2 cassian 5
3 gemini 1
4 mercury 17
5 merlin 8
6 volt 9
7 zephyrus 53
@@ -0,0 +1,133 @@
#!/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()