#!/usr/bin/env python3 """Independent verifier for the replies volume census artifacts. Recomputes ground truth from the LIVE /replies/ directory using shell pipelines (grep/sed/cut/sort/uniq via subprocess), then asserts the committed TSV artifacts and the markdown summary match that ground truth. The extractor parses with a compiled regex over pathlib; this verifier parses with shell text tools -- two independent code paths over the same evidence directory, so agreement is a real cross-check. Exit status: 0 artifact matches ground truth 1 mismatch (or artifact missing / unreadable) Used as the CHECK line: python3 wizard-work/ledger/verify_reply_volume_census.py """ import csv import subprocess import sys from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] REPLIES = REPO_ROOT / "replies" DATE_TSV = REPO_ROOT / "wizard-work" / "ledger" / "reply-volume-census.tsv" RECIP_TSV = REPO_ROOT / "wizard-work" / "ledger" / "reply-volume-by-recipient.tsv" MD = REPO_ROOT / "wizard-work" / "ledger" / "reply-volume-census.md" DATE_PAT = r"^[0-9]{4}-[0-9]{2}-[0-9]{2}-to-" FIND_BASENAMES = "find replies -maxdepth 1 -type f -name '*.md' -printf '%f\\n'" SEP = "-------------------------------------------------------------------------------" def sh(cmd): """Run a shell command and return stripped stdout.""" return subprocess.run( cmd, shell=True, check=True, capture_output=True, text=True ).stdout def ground_truth(): """Independent ground truth derived from the live replies/ directory.""" date_cmd = (FIND_BASENAMES + " | grep -E '" + DATE_PAT + "' | " "sed -E 's/-to-.*//' | sort | uniq -c") date_files = sh(date_cmd).strip().splitlines() date_counts = {} for line in date_files: cnt, date = line.split(None, 1) date_counts[date] = int(cnt) # Recipients: strip the date prefix, drop ".md", then drop a trailing "-NN". recip_cmd = (FIND_BASENAMES + " | grep -E '" + DATE_PAT + "' | " "sed -E 's/^" + DATE_PAT + "//' | sed -E 's/\\.md$//' | " "sed -E 's/-[0-9]+$//' | sort | uniq -c") recip_files = sh(recip_cmd).strip().splitlines() recip_counts = {} for line in recip_files: cnt, recip = line.split(None, 1) recip_counts[recip] = int(cnt) return date_counts, recip_counts, sum(date_counts.values()) def parse_tsv(path): rows = {} with path.open(newline="", encoding="utf-8") as fh: reader = csv.reader(fh, delimiter="\t") next(reader, None) # skip header row for row in reader: if len(row) == 2: rows[row[0]] = int(row[1]) return rows def main(): date_gt, recip_gt, total_gt = ground_truth() problems = [] for label, tsv_path, gt in (("date", DATE_TSV, date_gt), ("recipient", RECIP_TSV, recip_gt)): if not tsv_path.is_file(): problems.append("missing " + str(tsv_path)) continue rows = parse_tsv(tsv_path) rows_data = {k: v for k, v in rows.items() if k != "TOTAL"} if rows_data != gt: problems.append( "%s: data rows differ; got %d keys, ground truth %d keys" % (label, len(rows_data), len(gt)) ) if rows.get("TOTAL", -1) != sum(gt.values()): problems.append( "%s: TOTAL row %r != sum of rows %d" % (label, rows.get("TOTAL"), sum(gt.values())) ) # Markdown summary must name the correct headline numbers. if MD.is_file(): text = MD.read_text(encoding="utf-8") for token in ("430", "34", "17", "README.md"): if token not in text: problems.append("markdown missing assertion: %s" % token) else: problems.append("missing " + str(MD)) if problems: print("CHECK FAIL") for p in problems: print(" -", p) sys.exit(1) print( "CHECK PASS: %d replies, %d dates, %d recipients " "(md_files=%d, canonical=%d)" % (total_gt, len(date_gt), len(recip_gt), md_total(), total_gt) ) sys.exit(0) def md_total(): return len(sh("ls -1 replies/*.md").splitlines()) if __name__ == "__main__": main()