Files
troupe-standup/wizard-work/ledger/CHECK-wizard-work-census-2026-11-01

107 lines
4.6 KiB
Bash

#!/usr/bin/env bash
# CHECK — ledger worktree census re-derivation verification (2026-11-01).
#
# The committed wizard-work-census-2026-11-01.json is a point-in-time snapshot
# of the git state at the pinned revision stored in the JSON (field `head`).
# This check re-derives every census field from git AT that pinned revision
# and compares it field-for-field against the file on disk. It does NOT look
# at live HEAD, so later commits cannot move the goalpost.
#
# Exits 0 only on exact match of all census fields.
set -u
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" || exit 2
OUT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
JSON="$OUT/wizard-work-census-2026-11-01.json"
python3 - "$JSON" "$REPO" <<'PY'
import json, subprocess, sys
from collections import Counter
json_path = sys.argv[1]
# The tree is the one this CHECK sits in, never a host path: the first version
# hardcoded /root/troupe-standup twice and graded the HOST repository at the
# pin, so a clean clone at another path read a green tick about someone else's
# tree (Q144).
repo = sys.argv[2]
def git(repo, *args):
return subprocess.run(["git", "-C", repo, *args],
capture_output=True, text=True, check=True).stdout
def git_at(pin, *args):
return git(repo, *args, pin)
def derive_at(pin):
data = {}
data["branch"] = git(repo, "symbolic-ref", "--short", "HEAD").strip()
data["branch_head"] = git_at(pin, "rev-parse", "--short").strip()
data["head"] = git_at(pin, "rev-parse").strip()
data["commit_count"] = int(git_at(pin, "rev-list", "--count").strip())
data["tracked_file_count"] = len(git_at(pin, "ls-tree", "-r", "--name-only").splitlines())
data["total_unique_emails"] = len(
{e for e in git_at(pin, "log", "--format=%ae").splitlines() if e}
)
by_pair = {}
for line in git_at(pin, "log", "--format=%an%x00%ae%x00%ad", "--date=iso-strict").splitlines():
if not line.strip():
continue
name, email, date = line.split("\x00")
by_pair.setdefault((name, email), []).append(date)
rows = []
for (name, email), dates in by_pair.items():
rows.append({"name": name, "email": email, "count": len(dates),
"first": min(dates), "last": max(dates)})
nc = Counter(r["name"] for r in rows)
ec = Counter(r["email"] for r in rows)
for r in rows:
r["name_collides"] = nc[r["name"]] > 1
r["email_collides"] = ec[r["email"]] > 1
rows.sort(key=lambda r: (-r["count"], r["name"].lower(), r["email"]))
data["author_census"] = rows
names = git_at(pin, "log", "--pretty=format:", "--name-only").splitlines()
fc = Counter(n for n in names if n.strip())
data["top_modified_files"] = [{"path": p, "commits": c} for p, c in fc.most_common()]
return data
committed = json.load(open(json_path))
pin = committed.get("head")
if not pin:
print("[CHECK] JSON missing 'head' pin", file=sys.stderr)
sys.exit(2)
try:
derived = derive_at(pin)
except (subprocess.CalledProcessError, OSError, ValueError) as exc:
# rc 2 = could not grade: git could not answer at the pin (bad pin, not a
# repository, detached HEAD with no branch to name). The old body let the
# CalledProcessError escape as a traceback with rc 1, which reads as a
# verdict on the artifact rather than on the instrument.
print("[CHECK] CANNOT GRADE at pin %s: %r" % (pin, exc), file=sys.stderr)
sys.exit(2)
fields = ["branch", "branch_head", "head", "commit_count", "tracked_file_count",
"total_unique_emails"]
for k in fields:
if derived.get(k) != committed.get(k):
print(" FIELD %r MISMATCH (pin %s): derived=%r committed=%r" %
(k, pin, derived.get(k), committed.get(k)), file=sys.stderr)
sys.exit(1)
if len(derived["author_census"]) != len(committed["author_census"]):
print(" CENSUS LENGTH MISMATCH: derived %d rows, committed %d rows" % (
len(derived["author_census"]), len(committed["author_census"])), file=sys.stderr)
sys.exit(1)
for i, (e, c) in enumerate(zip(derived["author_census"], committed["author_census"])):
for k in ("name", "email", "count", "first", "last", "name_collides", "email_collides"):
if e.get(k) != c.get(k):
print(" CENSUS ROW %d FIELD %r MISMATCH: derived=%r committed=%r" %
(i, k, e.get(k), c.get(k)), file=sys.stderr)
sys.exit(1)
if derived["top_modified_files"] != committed["top_modified_files"]:
print(" TOP_FILES MISMATCH", file=sys.stderr)
sys.exit(1)
print("[CHECK] derived from git at pinned rev %s and compared field-for-field against %s — PASS" % (pin, json_path))
PY