ledger: check-in census (93 files across 8 dates)
This commit is contained in:
1 parent
63406a5715
commit
13aa0c95d6
5 files changed
+333
-15
No files matched your search
Executable
+38
@@ -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
|
||||
@@ -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,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 |
|
||||
@@ -0,0 +1,7 @@
|
||||
wizard checkins
|
||||
cassian 5
|
||||
gemini 1
|
||||
mercury 17
|
||||
merlin 8
|
||||
volt 9
|
||||
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()
|
||||
Reference in new issue
Block a user