Files
troupe-standup/wizard-work/ledger/verify_github_repo_census.py
T

95 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""verify_github_repo_census.py
Verifier for the github-repo-census-2026-11-02 artifact (extract lane).
Independent re-derivation: rebuilds the expected TSV from the committed
raw.json (no import of the extractor), then compares field-for-field with
the committed TSV and runs structural checks. Exit code IS the verdict:
0 iff everything matches, 1 on any mismatch.
"""
import csv
import json
import sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
RAW = HERE / "github-repo-census-2026-11-02.raw.json"
TSV = HERE / "github-repo-census-2026-11-02.tsv"
FIELDS = ["rank", "repo", "owner", "description", "stars", "forks", "language", "url"]
def derive():
api = json.loads(RAW.read_text(encoding="utf-8"))
items = sorted(api.get("items", []),
key=lambda i: i.get("stargazers_count", 0), reverse=True)[:15]
out = []
for i, it in enumerate(items, 1):
out.append({
"rank": i,
"repo": it.get("name", ""),
"owner": (it.get("owner") or {}).get("login", ""),
"description": (it.get("description") or "").strip(),
"stars": it.get("stargazers_count", 0),
"forks": it.get("forks_count", 0),
"language": (it.get("language") or "").strip(),
"url": it.get("html_url", ""),
})
return out
def read_committed():
with TSV.open(encoding="utf-8", newline="") as f:
return list(csv.DictReader(f, delimiter="\t"))
def main():
try:
expected = derive()
except Exception as exc: # noqa: BLE001
print(f"[fail] could not re-derive from raw.json: {exc}")
return 1
try:
committed = read_committed()
except Exception as exc: # noqa: BLE001
print(f"[fail] could not read committed TSV: {exc}")
return 1
problems = []
# Structural checks.
if len(committed) != len(expected):
problems.append(f"row count: committed={len(committed)} expected={len(expected)}")
stars = [int(r.get("stars", -1)) for r in committed]
if stars != sorted(stars, reverse=True):
problems.append("stars not sorted non-increasing")
if [r.get("rank") for r in committed] != [str(i) for i in range(1, len(committed) + 1)]:
problems.append("rank column not 1..N")
if len({r.get("repo") for r in committed}) != len(committed):
problems.append("duplicate repo names")
for r in committed:
if not r.get("url", "").startswith("https://github.com/"):
problems.append(f"bad url: {r.get('url')}")
break
# Field-for-field comparison of the full table.
if len(committed) == len(expected):
for i, (c, e) in enumerate(zip(committed, expected), 1):
for field in FIELDS:
if c.get(field) != str(e[field]):
problems.append(f"row {i} field {field}: committed={c.get(field)!r} "
f"expected={e[field]!r}")
if problems:
print("[fail] census verification mismatches:")
for p in problems:
print(" -", p)
return 1
print(f"[ok] census verified: {len(committed)} rows, sorted desc by stars, "
f"no duplicate repos, table equals independent re-derivation from raw.json")
return 0
if __name__ == "__main__":
sys.exit(main())