140 lines
4.8 KiB
Bash
Executable File
140 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# CHECK — verifier for the live wizard roster (2026-10-29) extract
|
|
# (Extract lane: data extraction and tables).
|
|
#
|
|
# Exits 0 iff the committed TSV (`live-wizard-roster-2026-10-29.tsv`) is a
|
|
# faithful replay of the three evidence sources: WIZARDS-TABLE.md roster table,
|
|
# checkins/ filenames (latest check-in per wizard), and git log (newest commit
|
|
# per wizard). No `|| true` / `; exit 0` fallbacks; the last command's exit
|
|
# code is the verdict.
|
|
#
|
|
# Independently re-derives every row with string/file operations; does NOT
|
|
# import extract_live_wizard_roster.py.
|
|
|
|
set -u
|
|
|
|
cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../.." || exit 1
|
|
SRC="${PWD}/wizard-work/ledger/live-wizard-roster-2026-10-29.tsv"
|
|
|
|
python3 - "$SRC" <<'PY'
|
|
import csv
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
src = Path(sys.argv[1])
|
|
repo = Path("/root/troupe-standup")
|
|
WIZARDS = [
|
|
"Timmy", "Zephyrus Sparkborn", "Cassian Assayborn", "Merlin", "Mercury",
|
|
"Gemini", "Argus", "Volt", "Sentinel", "Beam",
|
|
]
|
|
fails = []
|
|
|
|
def check(name, cond, detail=""):
|
|
print(("PASS " if cond else "FAIL ") + name + (" " + repr(detail) if detail else ""))
|
|
if not cond:
|
|
fails.append(name)
|
|
|
|
# ---- 1. canonical roster rows from WIZARDS-TABLE.md -----------------------
|
|
table = (repo / "WIZARDS-TABLE.md").read_text(encoding="utf-8").splitlines()
|
|
roster = {}
|
|
for line in table:
|
|
if line.startswith("| Wizard |"):
|
|
break
|
|
for line in table:
|
|
if not line.startswith("|"):
|
|
continue
|
|
cells = [c.strip() for c in line.split("|") if c.strip()]
|
|
if len(cells) == 5 and cells[0] != "Wizard":
|
|
roster[cells[0]] = (cells[1], cells[2]) # model, lane
|
|
check("roster: all 10 canonical wizards present in WIZARDS-TABLE.md",
|
|
set(roster) >= set(WIZARDS), repr(sorted(roster)))
|
|
extra = sorted(set(roster) - set(WIZARDS))
|
|
if extra:
|
|
print(" (also rows in table but not wizards: %s)" % extra)
|
|
|
|
# ---- 2. latest check-in per wizard from checkins/ filenames ----------------
|
|
checkins = {}
|
|
slug2w = {"zephyrus": "Zephyrus Sparkborn", "merlin": "Merlin",
|
|
"mercury": "Mercury", "gemini": "Gemini", "volt": "Volt",
|
|
"sentinel": "Sentinel"}
|
|
for fh in (repo / "checkins").iterdir():
|
|
if not fh.is_file() or not fh.name.endswith(".md"):
|
|
continue
|
|
base = fh.name[:-3]
|
|
parts = base.split("-", 3)
|
|
if len(parts) < 4:
|
|
continue
|
|
date, slug = "-".join(parts[:3]), parts[3]
|
|
if slug.startswith("cassian"):
|
|
w = "Cassian Assayborn"
|
|
elif slug in slug2w:
|
|
w = slug2w[slug]
|
|
else:
|
|
continue
|
|
if w not in checkins or date > checkins[w]:
|
|
checkins[w] = date
|
|
check("checkins: covered wizards", set(checkins) == {"Zephyrus Sparkborn",
|
|
"Cassian Assayborn", "Merlin", "Mercury", "Gemini", "Volt", "Sentinel"},
|
|
repr(sorted(checkins)))
|
|
|
|
# ---- 3. newest commit per wizard from git log -------------------------------
|
|
author_alias = {}
|
|
for w in roster:
|
|
author_alias[w.lower()] = w
|
|
author_alias["cassian assayborn"] = "Cassian Assayborn"
|
|
author_alias["zephyrus sparkborn"] = "Zephyrus Sparkborn"
|
|
author_alias["zephyrus-sparkborn"] = "Zephyrus Sparkborn"
|
|
author_alias["sentinel"] = "Sentinel"
|
|
expected_commits = {w: None for w in roster}
|
|
out = subprocess.run(
|
|
["git", "log", "--format=%an%x00%H%x00%ad", "--date=short"],
|
|
cwd=repo, capture_output=True, text=True).stdout
|
|
best = {}
|
|
for line in out.splitlines():
|
|
if "\x00" not in line:
|
|
continue
|
|
author, hsh, date = line.split("\x00", 2)
|
|
w = author_alias.get(author.lower())
|
|
if w is None or w not in roster:
|
|
continue
|
|
prev = best.get(w)
|
|
if prev is None or date > prev[0]:
|
|
best[w] = (date, hsh)
|
|
for w in roster:
|
|
if w in best:
|
|
expected_commits[w] = best[w][1] + " " + best[w][0]
|
|
|
|
# ---- 4. build expected rows and compare against committed TSV --------------
|
|
with open(src, encoding="utf-8", newline="") as fh:
|
|
rows = list(csv.reader(fh, delimiter="\t"))
|
|
|
|
check("tsv header", rows[0] == ["Wizard", "Model", "Lane",
|
|
"Latest check-in", "Newest commit"],
|
|
repr(rows[0]))
|
|
committed = rows[1:]
|
|
check("row count", len(committed) == len(WIZARDS),
|
|
"committed=%d canonical_wizards=%d" % (len(committed), len(WIZARDS)))
|
|
|
|
expected = []
|
|
for w in WIZARDS:
|
|
model, lane = roster[w]
|
|
lc = checkins.get(w, "— (no check-in)")
|
|
nc = expected_commits[w] or "— (no commit)"
|
|
expected.append([w, model, lane, lc, nc])
|
|
|
|
mism = []
|
|
for k, (c, g) in enumerate(zip(committed, expected)):
|
|
if c != g:
|
|
mism.append((k, c, g))
|
|
check("rows identical to independent re-derive", not mism,
|
|
"first=%r" % (mism[0] if mism else None))
|
|
|
|
if fails:
|
|
print("\n%d CHECK(S) FAILED" % len(fails))
|
|
sys.exit(1)
|
|
print("\nALL CHECKS PASSED — 10 wizard rows re-derived from "
|
|
"WIZARDS-TABLE.md + checkins/ + git log, %d rows identical"
|
|
% len(committed))
|
|
PY
|
|
exit $? |