Some checks failed
ci / check (push) Failing after 3s
The pattern is now measured over three rounds: 5 fatal, then 3 (2 from the previous round's corrections), then 4 (3 from them). The corrections are not getting safer. FATAL 1: round 2's short-cell assertion went into regulation.rs only. attack-value.rs — which produced every number in CB-EV-0030's DARVO table — still just warned, and the gate registered to close the finding claimed the property for both. FATAL 2, the sharpest of the three rounds: counting games proves they STARTED. Stopping the engine after one round gives 200 games, all-zero columns and exit 0 — byte for byte the signature CB-EV-0030 says the instrumentation distinguishes from a real result. Both harnesses now require every counted game to have reached an outcome over five rounds. FATAL 3: round 2's `.csv` filter was applied to all three loops, so catalog.yaml and rules_delta.yaml — whose missing digests were round 1's finding — were recorded and then never compared, and never checked against upstream at all. Only the parser loop filters now. FATAL 4: five of six tiebreak comparators had no coverage. GR-E04's tiebreak never executes in any scenario. All four are now covered and mutation-verified; the Blame key needed compensating claims to be reachable at all, since Blame also lowers the coalition score. SERIOUS: "peak held" computed the same number as "peak assigned" for every possible input — the real gap was that START_STRESS was an unchecked constant, now read off the dealt state; cadence="none" was a pure loophole, removed; sibling discovery swapped a hand-written list for hand-written globs and missed metadata.json and VARIANT.md, both named in the package's own changed_files — now walked, and it found them immediately; and "~72,000 games" was unsourced, make panels runs 17,600. Also separated two kinds of number that were presented alike: seats×games is invariant, 363 and 29 vary 7.1%-11.5% across samples. Round 4 owed. The conclusion is not that the work is nearly right — it is that author-made corrections to measurement work should be assumed defective until a fresh reader has attacked them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
225 lines
9.3 KiB
Python
Executable file
225 lines
9.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
|
|
|
|
EDITION = "editions/ground-darvo-r0"
|
|
PROVENANCE = f"{EDITION}/PROVENANCE.md"
|
|
UPSTREAM_DIR = os.path.join(os.path.dirname(ROOT), "ground-game", EDITION)
|
|
|
|
|
|
def digest(path):
|
|
return hashlib.sha256(open(path, "rb").read()).hexdigest()
|
|
|
|
|
|
def recorded():
|
|
"""Every recorded digest, by filename.
|
|
|
|
The first version matched ONE `sha256 <hex>` and assumed it described
|
|
`Problems.csv`. ADR-0015 vendored three more files, and the check
|
|
reported the first digest against the wrong file -- a gate written for
|
|
a single-file world silently comparing across files.
|
|
"""
|
|
text = open(os.path.join(ROOT, PROVENANCE)).read()
|
|
found = dict(
|
|
(name, d)
|
|
for d, name in re.findall(r"sha256\s+([0-9a-f]{64})\s+(\S+)", text)
|
|
)
|
|
if not found:
|
|
raise ValueError(f"{PROVENANCE} records no `sha256 <hex> <file>` digests")
|
|
return found
|
|
|
|
|
|
def vendored_files():
|
|
"""Every `.csv` actually present, so a file added without a digest is
|
|
caught rather than skipped."""
|
|
d = os.path.join(ROOT, EDITION)
|
|
return sorted(f for f in os.listdir(d) if f.endswith(".csv"))
|
|
|
|
|
|
# CB-WP-0038 vendored two things that are NOT inside the edition
|
|
# directory: `editions/catalog.yaml`, which selects between packages and
|
|
# so belongs above them, and the `h1-problem-stress` experiment package.
|
|
#
|
|
# Their digests were CLAIMED by that pass and never recorded. The
|
|
# adversarial review (CB-REV-0001) could not find them and reported the
|
|
# control unverified — correctly. Recorded relative to `editions/`.
|
|
SIBLINGS = "../"
|
|
|
|
# Discovered ON DISK, not read out of PROVENANCE (CB-REV-0002 #8). The
|
|
# first version listed siblings by reading the digest block, which made
|
|
# three controls vacuous at once: a recorded-but-absent file could never
|
|
# be reported missing (it was in `present` by construction), an absent one
|
|
# raised FileNotFoundError from `digest` instead of failing with the
|
|
# designed message, and "the sibling packages are covered" counted lines
|
|
# in a Markdown file -- it passed with all three files deleted.
|
|
# Everything under `editions/` that is not the edition directory itself.
|
|
# **Walked, not globbed** (CB-REV-0003 #8): the first version listed three
|
|
# hand-written glob patterns, which is the same self-certifying shape as
|
|
# reading the list out of PROVENANCE -- one hand-written list swapped for
|
|
# another. It missed `metadata.json` and `VARIANT.md`, both named in the
|
|
# package's OWN `changed_files` manifest, and anything a directory deeper.
|
|
SIBLING_SKIP = {".DS_Store"}
|
|
|
|
|
|
def sibling_files():
|
|
"""Every file beside the edition, as `../`-relative paths."""
|
|
base = os.path.join(ROOT, "editions")
|
|
edition_dir = os.path.join(ROOT, EDITION)
|
|
out = []
|
|
for dirpath, _dirs, files in os.walk(base):
|
|
if os.path.abspath(dirpath).startswith(os.path.abspath(edition_dir)):
|
|
continue
|
|
for name in files:
|
|
if name in SIBLING_SKIP:
|
|
continue
|
|
rel = os.path.relpath(os.path.join(dirpath, name), edition_dir)
|
|
out.append(rel.replace(os.sep, "/"))
|
|
return sorted(out)
|
|
|
|
|
|
def check():
|
|
want = recorded()
|
|
print("edition-check — vendored data against its provenance")
|
|
rc = 0
|
|
|
|
siblings = sibling_files()
|
|
present = vendored_files() + siblings
|
|
undocumented = [f for f in vendored_files() + siblings if f not in want]
|
|
if undocumented:
|
|
print(f" [FAIL] vendored with no recorded digest: {', '.join(undocumented)}")
|
|
rc = 1
|
|
missing = [f for f in want if f not in present]
|
|
if missing:
|
|
print(f" [FAIL] a digest is recorded for a file that is not here: {', '.join(missing)}")
|
|
rc = 1
|
|
|
|
for name in present:
|
|
if name not in want:
|
|
continue
|
|
path = os.path.join(ROOT, EDITION, name)
|
|
if not os.path.exists(path):
|
|
print(f" [FAIL] {name} is recorded but not on disk")
|
|
rc = 1
|
|
continue
|
|
have = digest(path)
|
|
# `../x` resolves out of the edition dir, which is the point.
|
|
if have != want[name]:
|
|
print(f" [FAIL] {name} does not match its recorded digest")
|
|
print(f" recorded {want[name]}\n actual {have}")
|
|
rc = 1
|
|
else:
|
|
print(f" [ok ] {name} matches its recorded digest")
|
|
|
|
# ADR-0015 D3's falsifier, checked rather than asserted: the hand
|
|
# reader handles commas inside quotes and NOTHING ELSE. A doubled
|
|
# quote or an embedded newline means `csv` is the answer after all.
|
|
# ONLY this loop filters: it is ADR-0015 D3's falsifier about the
|
|
# hand-rolled CSV reader, and running it over YAML made a valid
|
|
# `catalog.yaml` line with an odd quote count fail with a message
|
|
# about a parser that never reads it (CB-REV-0002 #9).
|
|
#
|
|
# **The digest and freshness loops must NOT filter** — CB-REV-0003 #3:
|
|
# the round-2 correction applied this filter to all three, so the two
|
|
# sibling YAMLs whose missing digests were round 1's finding were
|
|
# recorded and then never compared, and never checked against
|
|
# upstream at all. `make edition-check` answered its own headline
|
|
# question with [ok] when the answer was no.
|
|
for name in [f for f in present if f.endswith(".csv")]:
|
|
raw = open(os.path.join(ROOT, EDITION, name), encoding="utf-8-sig").read()
|
|
if '""' in raw:
|
|
print(f" [FAIL] {name} contains a doubled quote — ADR-0011's revisit")
|
|
print(" condition has fired; the hand reader cannot parse it")
|
|
rc = 1
|
|
# An embedded newline shows up as an odd quote count on a line.
|
|
for i, line in enumerate(raw.splitlines(), 1):
|
|
if line.count('"') % 2:
|
|
print(f" [FAIL] {name}:{i} has an unbalanced quote — embedded newline?")
|
|
rc = 1
|
|
break
|
|
if rc == 0:
|
|
print(" [ok ] no doubled quotes or embedded newlines (ADR-0015 D3)")
|
|
|
|
if not os.path.isdir(UPSTREAM_DIR):
|
|
# NOT a pass and NOT a failure: the question could not be asked.
|
|
print(" [----] upstream not checked out — freshness UNVERIFIED")
|
|
print(f" expected {UPSTREAM_DIR}")
|
|
return rc
|
|
for name in present:
|
|
up = os.path.join(UPSTREAM_DIR, name)
|
|
if not os.path.exists(up):
|
|
print(f" [FAIL] {name} is not in upstream — where did it come from?")
|
|
rc = 1
|
|
elif digest(up) != digest(os.path.join(ROOT, EDITION, name)):
|
|
print(f" [FAIL] upstream {name} has changed since it was vendored")
|
|
rc = 1
|
|
if rc == 0:
|
|
print(" [ok ] every vendored copy is current with ../ground-game")
|
|
return rc
|
|
|
|
|
|
def self_test():
|
|
"""A checker that cannot detect a mismatch is decoration."""
|
|
results = []
|
|
|
|
def chk(name, ok, detail=""):
|
|
results.append((name, ok, detail))
|
|
|
|
present = vendored_files()
|
|
want = recorded()
|
|
chk("vendored files exist", len(present) >= 4, ", ".join(present))
|
|
chk("every vendored file has a recorded digest",
|
|
all(f in want for f in present),
|
|
"a file added without a digest must fail, not be skipped")
|
|
# `present` is the edition's own CSVs plus the sibling paths recorded
|
|
# for the catalog and the experiment package (CB-WP-0038).
|
|
everything = present + sibling_files()
|
|
chk("every digest names a file that is here",
|
|
all(f in everything for f in want),
|
|
"a stale digest is a lie with a filename")
|
|
chk("digests match the real files",
|
|
all(digest(os.path.join(ROOT, EDITION, f)) == want[f] for f in everything))
|
|
chk("the sibling packages are covered",
|
|
all(f in want for f in sibling_files()) and len(sibling_files()) >= 3,
|
|
"catalog.yaml and rules_delta.yaml decide WHAT WE MEASURED; the first "
|
|
"version counted lines in PROVENANCE and passed with the files deleted")
|
|
|
|
# The control that matters: a changed byte must be detected.
|
|
import tempfile
|
|
one = present[0]
|
|
with tempfile.NamedTemporaryFile("wb", delete=False) as fh:
|
|
fh.write(open(os.path.join(ROOT, EDITION, one), "rb").read() + b"\n#tamper\n")
|
|
tampered = fh.name
|
|
chk("a tampered copy has a different digest",
|
|
digest(tampered) != want[one], "otherwise the check is decoration")
|
|
os.unlink(tampered)
|
|
|
|
# ADR-0015 D3's condition must be DETECTABLE, or asserting its absence
|
|
# in `check()` proves nothing.
|
|
chk("a doubled quote would be detected", '""' in 'a,""b""', "the pattern check itself")
|
|
chk("an unbalanced quote would be detected", 'a,"b'.count('"') % 2 == 1)
|
|
|
|
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())
|