Files
troupe-standup/wizard-work/null/check.py
T

261 lines
11 KiB
Python

#!/usr/bin/env python3
"""null verification for the Wizard Troupe standup.
Exit code IS the verdict: 0 = every claim below holds, 1 = broken.
python3 /root/troupe-standup/wizard-work/null/check.py
What this gate measures, in order:
1. the three files exist, compile, expose the documented API;
2. craft() and render() are pure functions of their arguments -- no clock;
3. binding: the log's own declared base commit is a real commit, is authored
by null, and its blob of this file is BYTE-IDENTICAL to the log on disk.
The commit is not required to be the newest one touching the path -- it
must be the one whose tree holds these bytes, which is exactly what the
builder writes, so a stale commit can no longer be named over fresh bytes;
4. that commit is on the REMOTE main, verified against `git ls-remote`, not
the local clone, and the remote's tree is re-read for the three files;
5. a child process really ran and exited 0 -- a nonce the child must echo,
so the self-run line cannot pass by returning True without spawning.
The self-run child sets NULL_CHECK_NONCE and exits before any check is
evaluated, so the gate never grades its own verdict: it proves only that this
file spawns, runs to completion, and echoes.
"""
import os
import re
import subprocess
import sys
import uuid
MYDIR = os.path.dirname(os.path.abspath(__file__))
REPO = os.path.dirname(os.path.dirname(MYDIR))
LOGNAME = "wizard.log.md"
NEED = ("wizard.log.md", "wizard.py", "check.py")
LOGPATH = "wizard-work/null/" + LOGNAME
PASSED, FAILED = [], []
def check(name, ok, detail=""):
ok = bool(ok)
(PASSED if ok else FAILED).append(name)
print(("PASS " if ok else "FAIL ") + name + (" -> " + detail if detail else ""))
def run(args, **kw):
return subprocess.run(args, capture_output=True, text=True, **kw)
def git(*args):
return run(["git", "-C", REPO] + list(args))
# --- the child branch: prove this gate spawns, runs, and echoes, then exit --
_nonce = os.environ.get("NULL_CHECK_NONCE")
if _nonce:
print("NONCE " + _nonce)
sys.exit(0)
def _compiles(src, name):
try:
compile(src, name, "exec")
return True
except SyntaxError:
return False
def _name_differing_line(commit, other):
r = git("show", "%s:%s" % (commit, LOGPATH))
if r.returncode != 0:
return
a, b = r.stdout.splitlines(), (other or "").splitlines()
for i in range(max(len(a), len(b))):
x = a[i] if i < len(a) else "<missing>"
y = b[i] if i < len(b) else "<missing>"
if x != y:
print(" differing line %d:\n committed: %s\n rendered: %s"
% (i + 1, x, y))
return
def _self_run(nonce):
"""Spawn check.py with a nonce; return (ok, output) or None if it never ran.
ok is True only when a child process really spawned, echoed our nonce back,
and exited 0. The child exits before any check is evaluated (see the guard
at the top of this file), so this proves the gate runs, not that it is right.
"""
env = dict(os.environ, NULL_CHECK_NONCE=nonce)
try:
r = run([sys.executable, os.path.join(MYDIR, "check.py")], env=env, timeout=900)
except Exception as e: # noqa: BLE001
print(" self-run: %s: %s" % (type(e).__name__, e))
return None
return r.returncode == 0 and ("NONCE %s" % nonce) in r.stdout, r.stdout + r.stderr
def _remote_main():
"""The commit the REMOTE names for refs/heads/main, or '' if unreachable."""
r = run(["git", "-C", REPO, "ls-remote", "origin", "refs/heads/main"])
if r.returncode != 0 or not r.stdout.strip():
return ""
return r.stdout.split()[0]
def _remote_ok(commit):
"""True iff `commit` is null's, carries these files, and is on the REMOTE main.
ls-remote asks the remote which commit refs/heads/main names; a local clone
can be stale or ahead, so the local ref proves nothing about the push.
"""
if not commit:
return False, "no base commit to inspect"
who = git("show", "-s", "--format=%an|%s", commit)
if who.returncode != 0:
return False, "commit unreadable"
author, subject = who.stdout.strip().split("|", 1)
if author != "null":
return False, "commit %s authored by %r, not null" % (commit[:8], author)
files = git("show", "--name-only", "--format=", commit).stdout.split()
need = {"wizard-work/null/" + f for f in NEED}
if not need.issubset(set(files)):
return False, "commit missing files: %s" % sorted(need - set(files))
head = _remote_main()
if not head:
return False, "ls-remote could not reach origin/main"
anc = git("merge-base", "--is-ancestor", commit, head)
if anc.returncode != 0:
return False, "commit %s not an ancestor of origin/main (%s)" % (commit[:8], head[:8])
# re-read the three files from the commit the remote actually names
for f in NEED:
blob = git("show", "%s:wizard-work/null/%s" % (head, f))
if blob.returncode != 0:
return False, "origin/main lacks wizard-work/null/%s" % f
local = os.path.join(MYDIR, f)
if os.path.isfile(local):
with open(local, encoding="utf-8") as fh:
if fh.read() != blob.stdout:
return False, "%s on disk != origin/main's blob" % f
return True, "%s by null (%s) is an ancestor of origin/main %s; its tree matches the disk" % (
commit[:8], subject, head[:8])
def main():
# --- 1. presence / compile / API --------------------------------------
for fn in NEED:
check("artifact present: " + fn, os.path.isfile(os.path.join(MYDIR, fn)))
src = open(os.path.join(MYDIR, "wizard.py"), encoding="utf-8").read()
check("wizard.py compiles", _compiles(src, "wizard.py"))
ns = {"__name__": "wizard_module", "__file__": os.path.join(MYDIR, "wizard.py")}
if _compiles(src, "wizard.py"):
exec(compile(src, "wizard.py", "exec"), ns)
check("API: craft exists", callable(ns.get("craft")))
check("API: render exists", callable(ns.get("render")))
check("API: VERDICT/CHECK markers exist", "VERDICT:" in src and "CHECK:" in src)
# --- 2. craft() / render() are pure in their arguments -----------------
try:
args = ("t", "a", "L", "deadbeef", "null", "2026-10-24 00:00 UTC")
v1, c1, _ = ns["craft"](*args)
v2, c2, _ = ns["craft"](*args)
v3, _, _ = ns["craft"]("t", "a", "L", "deadbeef", "null", "2030-01-01 00:00 UTC")
check("craft() deterministic in its stamp argument",
(v1, c1) == (v2, c2) and v1 != v3 and c1.startswith("CHECK: "),
"same stamp -> identical bytes; different stamp -> different verdict")
except Exception as e: # noqa: BLE001
check("craft() deterministic in its stamp argument", False,
"%s: %s" % (type(e).__name__, e))
# --- 3. binding: the declared commit's blob IS the log on disk ----------
log_path = os.path.join(MYDIR, LOGNAME)
disk = open(log_path, encoding="utf-8").read() if os.path.exists(log_path) else ""
fields = dict(ns["parse_log"](disk)) if callable(ns.get("parse_log")) else {}
lane = fields.get("lane", "")
area = fields.get("target area", "")
operator = fields.get("operator", "null")
commit = fields.get("base commit", "")
stamp = fields.get("stamp", "")
rendered = None
try:
rendered = ns["render"](lane, area, lane, commit, operator, stamp)
except Exception: # noqa: BLE001
pass
check("log declares a base commit SHA", bool(commit), repr(commit))
obj = git("cat-file", "-t", commit) if commit else None
check("base commit resolves as a git object",
bool(obj and obj.returncode == 0 and obj.stdout.strip() == "commit"),
(obj.stdout.strip() if obj else "no sha") or (obj.stderr.strip() if obj else ""))
if commit and obj and obj.returncode == 0:
author = git("show", "-s", "--format=%an", commit).stdout.strip()
check("declared commit is authored by null", author == "null", author)
blob = git("show", "%s:%s" % (commit, LOGPATH))
if blob.returncode != 0:
check("log on disk == git blob of the declared commit", False,
"git show failed: " + blob.stderr.strip()[:120])
elif disk == blob.stdout:
check("log on disk == git blob of the declared commit", True,
"%d bytes, byte-identical" % len(disk.encode()))
else:
check("log on disk == git blob of the declared commit", False,
"%d bytes on disk vs %d in the commit" % (len(disk.encode()), len(blob.stdout.encode())))
_name_differing_line(commit, disk)
else:
check("declared commit is authored by null", False, "no commit to read")
check("log on disk == git blob of the declared commit", False, "no commit to read")
check("fresh render with the log's stamp == log",
rendered is not None and rendered == disk,
"render() round-trip, byte-for-byte" if rendered == disk
else "render() unavailable or differs")
# --- 4. shape of the log -----------------------------------------------
nv = len(re.findall(r"(?m)^VERDICT:", disk))
nc = len(re.findall(r"(?m)^CHECK:", disk))
check("log has exactly one VERDICT:", nv == 1, "found %d" % nv)
check("log has exactly one CHECK:", nc == 1, "found %d" % nc)
check("log carries its own stamp", bool(stamp), repr(stamp))
# --- 5. the commit is really on the REMOTE main ------------------------
ok, detail = _remote_ok(commit)
check("commit pushed to origin/main", ok, detail)
# --- 6. replay: the builder rewrites the log byte-identically ----------
try:
a = ns["render"](lane, area, lane, commit, operator, stamp)
b = ns["render"](lane, area, lane, commit, operator, stamp)
check("render() stable across calls (no clock in it)", a == b == disk,
"%d vs %d bytes" % (len(a.encode()), len(b.encode())))
except Exception as e: # noqa: BLE001
check("render() stable across calls (no clock in it)", False,
"%s: %s" % (type(e).__name__, e))
# --- 7. self-run: a child really spawned and echoed the nonce ----------
n = uuid.uuid4().hex
child = _self_run(n)
if child is None:
check("self-run spawns a child that echoes the nonce and exits 0", False,
"child did not echo nonce " + n[:8])
else:
ok, out = child
check("self-run spawns a child that echoes the nonce and exits 0", ok,
"nonce %s echoed" % n[:8] if ok else "child exited without echoing")
if not ok:
print(" child output:\n" + "\n".join(
" " + l for l in (out or "").strip().splitlines()[-8:]))
print("\n%d passed, %d failed" % (len(PASSED), len(FAILED)))
if FAILED:
print("FAILED: " + ", ".join(FAILED))
return 1
print("ALL CHECKS GREEN")
return 0
if __name__ == "__main__":
sys.exit(main())