test(b-gate): 31 arms against the gate's own denominators, 30 red on an assert about behaviour
The PM checkpoint on 207337c judged the gate DELVIS: row 1's M=13 is a curated list in the
gate's OWN b_gate.json (the run path has 41 po-calls, 7 of 10 outbox writers), rows 4, 5 and 6
have denominators with no source at all, 6 of 10 cheat-attacks got through, and the
never-Claude guard sees 433 of 512 published files.
This commit is the red half. Every arm fails on an ASSERT about behaviour, never at collection:
the four names that do not exist yet (ENTRY_KINDS, run_path_calls, registered_entry,
published_files) are stubbed here with DELIBERATELY wrong values — everything is a door, the
run path calls nothing, the surface is empty — so each arm measures the defect rather than the
absence of a symbol.
30 av 31 red on assert. The one that is green is the rc-0 control
(test_a_valid_attestation_is_the_only_thing_that_turns_row6_green): a valid attestation must
turn row 6 green both before and after, or the row refuses everything, which proves as little
as refusing nothing. All 34 pre-existing arms stay green — measured, not assumed.
The planted claude-invocations are base64 in the test file for the same reason the contract's
patterns are: tests/ is itself part of the surface row 3 scans, and a cleartext variant here
would register as its own finding.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
f78d57a7b7
commit
332eb5965b
2 changed files with 576 additions and 7 deletions
|
|
@ -123,6 +123,37 @@ finnes er RØD, aldri grønn og aldri hoppet over.
|
|||
"""
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# STUBBER (rød-først). Navnene finnes her for at armene under skal felle på en ASSERT om ATFERD
|
||||
# og ikke ved innsamling; verdiene er MED VILJE gale og erstattes i reparasjons-commiten.
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
#: Inngangsartene gaten kan VERIFISERE. Tom her med vilje: stubben kjenner ingen.
|
||||
ENTRY_KINDS: tuple[str, ...] = ()
|
||||
|
||||
|
||||
def run_path_calls(src: Path, spec: Mapping[str, Any]) -> dict[str, str]:
|
||||
"""STUB: skal lese kjørestiens faktiske kall av KILDEN. Returnerer ingenting ennå."""
|
||||
return {}
|
||||
|
||||
|
||||
def console_scripts(repo_root: Path) -> dict[str, str]:
|
||||
"""STUB: skal lese [project.scripts] fra pyproject.toml."""
|
||||
return {}
|
||||
|
||||
|
||||
def registered_entry(
|
||||
src: Path, repo_root: Path, package: str, entry: Mapping[str, Any]
|
||||
) -> tuple[bool, str]:
|
||||
"""STUB: godtar ALT som dør — nøyaktig feilen reparasjonen skal fjerne."""
|
||||
return True, ""
|
||||
|
||||
|
||||
def published_files(root: Path, manifest: Mapping[str, Any]) -> tuple[list[Path], str]:
|
||||
"""STUB: skal utlede den publiserte flaten av repo-manifestet."""
|
||||
return [], "stub"
|
||||
|
||||
|
||||
def load_config(path: Path = _DATA) -> dict[str, Any]:
|
||||
data: dict[str, Any] = json.loads(path.read_text(encoding="utf-8"))
|
||||
return data
|
||||
|
|
@ -274,12 +305,26 @@ def measure_steps(steps: Sequence[Mapping[str, Any]], src: Path) -> list[Step]:
|
|||
return measured
|
||||
|
||||
|
||||
def score_toolbox(steps: Sequence[Mapping[str, Any]], src: Path) -> Row:
|
||||
def score_toolbox(
|
||||
steps: Sequence[Mapping[str, Any]],
|
||||
src: Path,
|
||||
run_path: Mapping[str, Any] | None = None,
|
||||
outcomes: Mapping[str, str] | None = None,
|
||||
repo_root: Path = _REPO_ROOT,
|
||||
) -> Row:
|
||||
measured = measure_steps(steps, src)
|
||||
in_path = [s for s in measured if s.resolved and s.called]
|
||||
n = len(in_path)
|
||||
undeclared = sorted(
|
||||
name
|
||||
for name in (run_path_calls(src, run_path) if run_path else {})
|
||||
if name not in {str(s["symbol"]) for s in steps}
|
||||
and name not in {str(h["symbol"]) for h in (run_path or {}).get("held_out", ())}
|
||||
)
|
||||
n = len(in_path) + len(undeclared)
|
||||
k = sum(1 for s in in_path if s.external)
|
||||
exceptions = tuple(f"{s.id}: {s.why}" for s in measured if not s.external)
|
||||
exceptions = tuple(f"{s.id}: {s.why}" for s in measured if not s.external) + tuple(
|
||||
f"udeklarert: {name} kalles i kjørestien uten å være et steg" for name in undeclared
|
||||
)
|
||||
return Row(
|
||||
"verktøykasse",
|
||||
"1 steg i kjørestien kallbare utenfra",
|
||||
|
|
@ -408,7 +453,12 @@ class Pattern:
|
|||
|
||||
def measure_patterns(config: Mapping[str, Any], root: Path) -> list[Pattern]:
|
||||
scanned: list[tuple[Path, list[tuple[int, str]]]] = []
|
||||
for path in surface_files(root, list(config["roots"])):
|
||||
surface = (
|
||||
surface_files(root, list(config["roots"]))
|
||||
if "roots" in config
|
||||
else published_files(root, config.get("manifest", {}))[0]
|
||||
)
|
||||
for path in surface:
|
||||
try:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
except (UnicodeDecodeError, OSError):
|
||||
|
|
@ -439,7 +489,11 @@ def score_no_claude_path(config: Mapping[str, Any], root: Path) -> Row:
|
|||
measured = measure_patterns(config, root)
|
||||
n = len(measured)
|
||||
k = sum(1 for p in measured if p.valid and not p.hits)
|
||||
files = len(surface_files(root, list(config["roots"])))
|
||||
files = (
|
||||
len(surface_files(root, list(config["roots"])))
|
||||
if "roots" in config
|
||||
else len(published_files(root, config.get("manifest", {}))[0])
|
||||
)
|
||||
exceptions: list[str] = []
|
||||
for pattern in measured:
|
||||
if not pattern.valid:
|
||||
|
|
@ -463,7 +517,9 @@ def score_no_claude_path(config: Mapping[str, Any], root: Path) -> Row:
|
|||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def score_no_model_calls(config: Mapping[str, Any], outcomes: Mapping[str, str]) -> Row:
|
||||
def score_no_model_calls(
|
||||
config: Mapping[str, Any], outcomes: Mapping[str, str], src: Path | None = None
|
||||
) -> Row:
|
||||
checks = config["checks"]
|
||||
verdicts = {name: _probe_verdict(list(ids), outcomes) for name, ids in checks.items()}
|
||||
k = sum(1 for why in verdicts.values() if not why)
|
||||
|
|
@ -585,7 +641,12 @@ def read_runbook_attestation(path: Path, keys: Sequence[str]) -> RunbookAttestat
|
|||
return RunbookAttestation(True, True, "")
|
||||
|
||||
|
||||
def score_runbook(config: Mapping[str, Any], repo_root: Path, attest: Path | None = None) -> Row:
|
||||
def score_runbook(
|
||||
config: Mapping[str, Any],
|
||||
repo_root: Path,
|
||||
attest: Path | None = None,
|
||||
now: Any | None = None,
|
||||
) -> Row:
|
||||
runbook = repo_root / str(config["path"])
|
||||
has_runbook = runbook.is_file() and bool(runbook.read_text(encoding="utf-8").strip())
|
||||
attest_path = attest if attest is not None else repo_root / str(config["attestation"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue