Files
troupe-standup/wizard-work/ledger/verify_wizard_roster_2026-10-29.py

141 lines
5.0 KiB
Python

#!/usr/bin/env python3
"""Independent verifier for the WIZARDS-TABLE roster extract (Extract lane).
Recomputes the expected table from WIZARDS-TABLE.md using only string/file
operations (does NOT import extract_wizard_roster.py) and diffs the replay
against the committed 2026-10-29-wizard-roster.{csv,json,md}.
Exit code IS the verdict: 0 = PASS, nonzero = FAIL.
"""
import csv
import io
import json
import sys
from pathlib import Path
REPO_ROOT = Path("/root/troupe-standup")
SRC = REPO_ROOT / "WIZARDS-TABLE.md"
CSV_ART = REPO_ROOT / "wizard-work" / "ledger" / "2026-10-29-wizard-roster.csv"
JSON_ART = REPO_ROOT / "wizard-work" / "ledger" / "2026-10-29-wizard-roster.json"
MD_ART = REPO_ROOT / "wizard-work" / "ledger" / "2026-10-29-wizard-roster.md"
FAILS = []
def check(name, cond, detail=""):
tag = "PASS" if cond else "FAIL"
line = "%s %s" % (tag, name)
if detail:
line += " " + detail
print(line)
if not cond:
FAILS.append(name)
def parse_table(source):
lines = source.read_text(encoding="utf-8").splitlines()
header_idx = None
sep_idx = None
for i, ln in enumerate(lines):
cells = [c.strip() for c in ln.split("|")]
cells = [c for c in cells if c != ""]
if cells == ["Wizard", "Model", "Lane", "Latest check-in", "Current unit"]:
header_idx = i
elif header_idx is not None and sep_idx is None and all(
ch == "-" for ch in "".join(cells)):
sep_idx = i
if header_idx is None or sep_idx is None:
return None
rows = []
for ln in lines[sep_idx + 1:]:
stripped = ln.strip()
# Stop at the next section heading (e.g. '## Lane signers ...').
if stripped.startswith("#"):
break
if not stripped:
continue
cells = [c.strip() for c in stripped.split("|")]
cells = [c for c in cells if c != ""]
if all(ch == "-" for ch in "".join(cells)):
break
if len(cells) != 5:
return None
rows.append(cells)
return rows
def main():
actual = parse_table(SRC)
if actual is None:
print("FAIL table header not found")
sys.exit(1)
check("re-derived table row count", len(actual) == 18, "rows=%d" % len(actual))
wizards = actual[:10]
lane_signers = [r[0] for r in actual[10:]]
check("10 wizard rows", len(wizards) == 10)
check("8 lane signer rows", len(lane_signers) == 8)
check("lane_signers", lane_signers == [
"forge", "ledger", "sol", "quill", "spark", "sphinx", "null", "zeph"],
repr(lane_signers))
# --- 1) CSV replay ---
expected_csv = io.StringIO()
writer = csv.DictWriter(expected_csv,
fieldnames=["Wizard", "Model", "Lane",
"Latest check-in", "Current unit"],
lineterminator="\n")
writer.writeheader()
for r in wizards:
writer.writerow({c: r[i] for i, c in enumerate(
["Wizard", "Model", "Lane", "Latest check-in", "Current unit"])})
got_csv = CSV_ART.read_text(encoding="utf-8")
if got_csv != expected_csv.getvalue():
FAILS.append("CSV replay mismatch")
print(" expected CSV head:\n" + expected_csv.getvalue()[:400])
print(" got CSV head:\n" + got_csv[:400])
else:
check("CSV replay", True)
# --- 2) Markdown replay ---
md_lines = MD_ART.read_text(encoding="utf-8").splitlines()
md_data = []
for l in md_lines:
segs = [p.strip() for p in l.split("|")]
segs = [p for p in segs if p != ""]
if len(segs) == 5 and segs[0] == "Wizard":
continue
if len(segs) == 5 and all(ch == "-" for ch in "".join(segs)):
continue
if l.startswith("| "):
md_data.append(l)
expected_md = ["| " + " | ".join(r) + " |" for r in wizards]
check("MD data rows replay", md_data == expected_md,
"got=%d expected=%d" % (len(md_data), len(expected_md)))
# --- 3) JSON replay ---
j = json.loads(JSON_ART.read_text(encoding="utf-8"))
check("JSON total_table_rows", j.get("total_table_rows") == 18,
repr(j.get("total_table_rows")))
check("JSON wizard_rows_extracted", j.get("wizard_rows_extracted") == 10,
repr(j.get("wizard_rows_extracted")))
check("JSON lane_signers",
j.get("lane_signers") == lane_signers, repr(j.get("lane_signers")))
check("JSON lane_signers_count", j.get("lane_signers_count") == 8,
repr(j.get("lane_signers_count")))
check("JSON wizards records match",
j.get("wizards") == [
{"Wizard": r[0], "Model": r[1], "Lane": r[2],
"Latest check-in": r[3], "Current unit": r[4]} for r in wizards],
repr(j.get("wizards")))
if FAILS:
print("\n%d CHECK(S) FAILED" % len(FAILS))
sys.exit(1)
print("\nALL CHECKS PASSED -- table re-derived from WIZARDS-TABLE.md; "
"CSV / MD / JSON replay clean")
sys.exit(0)
if __name__ == "__main__":
main()