clay-borg/tools/edition-check.py
tegwick 2da19a49b7 CB-WP-0021 T01/T02/T05: the engine plays its own data — AM-7 blocks
ADR-0011 decided it: vendor the CSV with a checked digest, read it with
a ~50-line reader, and let the hashes move.

The declaration's constraint was measured against the WRONG BUDGET. It
said a CSV crate costs 21,613 against AM-4a's 3,798 of headroom, '5.7x
over, settled by measurement'. But setup and problem_priorities are
cfg(scenarios) and are not in the shipped runtime at all, so AM-4a never
sees them. Against AM-4b, csv costs 17,651 against 19,742 -- it FITS,
with 2,091 to spare. It is refused anyway, on proportion: 89% of the
budget's remaining capacity to read 20 rows. The revisit condition is
stated (nested quoting, embedded newlines, multiple dialects).

GR-S01 now deals Surface + hidden 1..=k as ruled, with edition values and
suits. Measured: 6/9/12 available against thresholds 5/7/9 -- the game is
winnable at every seat count, which is what the maintainer could not do.
gd0001 is INVERTED, not deleted, and now also asserts the 6/9/12 so a
deal that is reachable for the wrong reason still fails.

Blast radius was scenario expectations, exactly as the ADR predicted: no
scenario pinned a hash and no bundle is committed. Six scenarios and two
unit tests updated, each with a note. gr-e01-threshold-unreachable-2p is
RENAMED to -reachable- and rewritten as the non-provisional import check
ground-game asked for by name. gr-e03's setup was restructured, not just
renumbered: with values 2,2,2 its personal-edge test would have tied
three ways and asserted nothing.

BLOCKING: AM-7 fails at median 0.845 against its 0.9 floor. Isolated
across three runs -- 3 problems + stand-in 0.97, 3 problems + edition
0.909, 4 problems + edition 0.845. State is BOUNDED (proven: identical
after 5k and 100k events), so this is not the unbounded-growth defect
AM-7 exists to catch; it is a bigger working set streaming a long log.
Whether AM-7's floor is still right for a larger aggregate is a spec
question and lowering it requires an ADR, so it is not being tuned here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 00:47:56 +02:00

93 lines
3.3 KiB
Python
Executable file

#!/usr/bin/env python3
"""Is the vendored edition still what ground-game published? (ADR-0011 D2)
`editions/ground-darvo-r0/` is a copy of content owned by another repo.
A stale copy is worse than no copy, so the digest is committed and this
compares it.
**An absent upstream is reported absent, never as a pass.** That is the
shape ADR-0009 used for `node`: a check that cannot run says so, because
a silent skip is the class this project has found seven times.
"""
import hashlib
import os
import re
import sys
from repo import ROOT, enter_root
VENDORED = "editions/ground-darvo-r0/Problems.csv"
PROVENANCE = "editions/ground-darvo-r0/PROVENANCE.md"
UPSTREAM = os.path.join(os.path.dirname(ROOT), "ground-game", VENDORED)
def digest(path):
return hashlib.sha256(open(path, "rb").read()).hexdigest()
def recorded():
text = open(os.path.join(ROOT, PROVENANCE)).read()
m = re.search(r"sha256\s+([0-9a-f]{64})", text)
if not m:
raise ValueError(f"{PROVENANCE} records no sha256 digest")
return m.group(1)
def check():
have = digest(os.path.join(ROOT, VENDORED))
want = recorded()
print("edition-check — vendored data against its provenance")
if have != want:
print(f" [FAIL] {VENDORED} does not match its recorded digest")
print(f" recorded {want}\n actual {have}")
return 1
print(f" [ok ] vendored copy matches its recorded digest")
if not os.path.exists(UPSTREAM):
# NOT a pass and NOT a failure: the question could not be asked.
print(" [----] upstream not checked out — freshness UNVERIFIED")
print(f" expected {UPSTREAM}")
return 0
up = digest(UPSTREAM)
if up != have:
print(" [FAIL] upstream has changed since this copy was vendored")
print(f" upstream {up}\n vendored {have}")
print(" ground-game froze point_value and required_solution")
print(" within r0 — a change here is a new revision, or a")
print(" contract violation worth raising.")
return 1
print(" [ok ] vendored copy is current with ../ground-game")
return 0
def self_test():
"""A checker that cannot detect a mismatch is decoration."""
results = []
def chk(name, ok, detail=""):
results.append((name, ok, detail))
chk("the vendored file exists", os.path.exists(os.path.join(ROOT, VENDORED)))
chk("provenance records a digest", len(recorded()) == 64)
chk("digest of the real file matches provenance",
digest(os.path.join(ROOT, VENDORED)) == recorded())
# The control that matters: a changed byte must be detected.
import tempfile
with tempfile.NamedTemporaryFile("wb", delete=False) as fh:
fh.write(open(os.path.join(ROOT, VENDORED), "rb").read() + b"\n#tamper\n")
tampered = fh.name
chk("a tampered copy has a different digest",
digest(tampered) != recorded(), "otherwise the check is decoration")
os.unlink(tampered)
print("edition-check self-test (positive control)")
ok = True
for name, passed, det in results:
print(f" [{'ok ' if passed else 'FAIL'}] {name}" + (f"{det}" if det else ""))
ok &= passed
return 0 if ok else 1
if __name__ == "__main__":
enter_root()
raise SystemExit(self_test() if "--self-test" in sys.argv else check())