portfolio-optimiser/tests/test_b_gate.py
Kjell Tore Guttormsen a3f9df5251
test(b-gate): the published surface is 514, because this delivery put two files on it
`_PUBLISHED_TODAY` is the row-3 denominator, pinned in the suite against `git ls-files`. It read
512 and the arm was green in the worktree only because `toolbox.py` and `test_toolbox_doors.py`
were still untracked -- the clone measured 514 the moment they were committed. The pin is what it
is for: a surface that grows without anyone noticing is a surface the guard has not measured.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 08:14:31 +02:00

1908 lines
86 KiB
Python

"""B-gatens egne tester: hver rad KAN bli grønn og KAN bli rød — og kan ikke FAKES grønn.
Rammen er operatørbeslutningen 19.09.2026: i utvikling og test LEDER Claude Code, og
portfolio-optimiser er verktøykassen. po kaller ALDRI Claude. Gaten måler avstanden dit, rad for
rad, uten et eneste modellkall.
Tre ting gjør testene load-bearing i stedet for grønne-men-døde:
* **Nevneren telles uavhengig HER.** Rad 1 og rad 2 får ikke sine tall fra gatens egne funksjoner:
testen parser kilden selv (``ast``) eller importerer modulen og teller, og sammenligner. En gate
som hardkoder nevneren felles av arm ``M-1``, som kjører den mot en KONSTRUERT kilde der svaret
er et annet enn repoets.
* **Hver vakt har en kjent-positiv.** Et mønster som ikke treffer sin egen kjent-positive er ikke
en måling, og rad 3 nekter å telle det (``M-3``). Et fravær («0 treff») uttales med nevner.
* **Rad 6 kan ikke bli grønn av en fil gaten selv skriver** (``M-5``): armen kjører hele
``evaluate`` og krever at attesteringsfila fortsatt ikke finnes etterpå.
"""
from __future__ import annotations
import ast
import base64
import hashlib
import json
import re
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
import pytest
from portfolio_optimiser import workflow
from portfolio_optimiser.evals import b_gate as gate
from portfolio_optimiser.evals import v1_gate
_REPO = Path(__file__).resolve().parents[1]
_SRC = _REPO / "src" / "portfolio_optimiser"
_CONFIG = gate.load_config()
#: Klokka rad 6 leses mot, injisert: den ENE sjekken som ser på tiden skal ikke flytte seg.
_NOW = datetime(2026, 9, 19, 12, 0, tzinfo=timezone.utc)
#: Repoets egne tall ved skriving (19.09.2026), talt av armene under mot KILDEN. De står her for
#: at en stille endring i kjørestien skal vise seg som en rød test og ikke som et nytt tall.
_STEPS_TODAY = 17
_EXTERNAL_TODAY = 5
_ROLES_TODAY = ("proposer", "checker")
_PATTERNS_TODAY = 15
def _write(path: Path, text: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text, encoding="utf-8")
def _probes(outcome: str = "missing") -> Any:
return lambda nodeids: {n: outcome for n in nodeids}
def _row(rows: list[v1_gate.Row], key: str) -> v1_gate.Row:
return next(r for r in rows if r.key == key)
# ---------------------------------------------------------------------------------------------
# Rad 1 — verktøykassen er komplett
# ---------------------------------------------------------------------------------------------
def _independently_counted_steps() -> tuple[int, int]:
"""(steg som oppløses i kilden, steg med et kallsted) — talt HER, av testens egen parser.
Kilden er ``src/portfolio_optimiser/``; ingen av gatens funksjoner røres."""
resolved = called = 0
for step in _CONFIG["steps"]:
tree = ast.parse((_SRC / step["module"]).read_text(encoding="utf-8"))
defs = {
n.name
for n in tree.body
if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef))
}
if step["symbol"] in defs:
resolved += 1
driver = ast.parse((_SRC / step["driver"]["module"]).read_text(encoding="utf-8"))
scopes = [
n
for n in ast.walk(driver)
if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef))
and n.name == step["driver"]["scope"]
]
names = {
c.func.id if isinstance(c.func, ast.Name) else c.func.attr
for s in scopes
for c in ast.walk(s)
if isinstance(c, ast.Call) and isinstance(c.func, (ast.Name, ast.Attribute))
}
if step["symbol"] in names:
called += 1
return resolved, called
def test_the_step_denominator_equals_an_independent_count_of_the_source() -> None:
resolved, called = _independently_counted_steps()
assert resolved == called == _STEPS_TODAY, "kjørestien har endret seg — oppdater nevneren"
row = gate.score_toolbox(_CONFIG["steps"], _SRC, _CONFIG["run_path"], {}, _REPO)
assert row.n == _STEPS_TODAY
#: Stegene som HAR en dør ut 20.09.2026, skrevet ut. Fire av dem er verktøykassens under-
#: kommandoer (steg 2 i byggerekkefølgen); ``gate`` er v1-gatens egen kommando, som alltid var
#: en ekte dørprobe og ble avvist på en navneteknikalitet til klasse-rettingen samme dag.
_WITH_A_DOOR_TODAY = ("gate", "kontekst", "kostnadsgrunnlag", "pakke", "prepass")
def test_row1_today_is_red_and_names_exactly_the_steps_that_have_a_door() -> None:
"""Var «3 av 17» til 19.09, så 0 av 17 da proben ble BUNDET til steget, og 5 av 17 fra 20.09.
Armen teller ikke bare k — den navngir HVILKE, så en dør som flytter seg uten å bli bygd
(eller en probe som slutter å drive sin dør) blir rød her og ikke bare et annet tall."""
passing = {n: "passed" for step in _CONFIG["steps"] for n in step.get("probe", ())}
row = gate.score_toolbox(_CONFIG["steps"], _SRC, _CONFIG["run_path"], passing, _REPO)
assert (row.k, row.n, row.status) == (_EXTERNAL_TODAY, _STEPS_TODAY, gate.RED)
assert len(_WITH_A_DOOR_TODAY) == _EXTERNAL_TODAY
uten_doer = {x.split(":")[0] for x in row.exceptions}
alle = {str(s["id"]) for s in _CONFIG["steps"]}
assert sorted(alle - uten_doer) == sorted(_WITH_A_DOOR_TODAY), row.exceptions
assert "validering" in uten_doer and "utboks" in uten_doer
assert "prepass-artefakt" in uten_doer and "parse-feil" in uten_doer
bound = {x.split(":")[0] for x in row.exceptions if "atferdsprobe" in x}
assert bound == {"rundebinding", "rapport"}, row.exceptions
def _fake_src(root: Path, *, chat_client: bool, symbol: str = "gjoer_noe") -> Path:
"""En konstruert kilde med ETT steg: en inngang ``main`` som når steget.
``chat_client=True`` legger en chatklient på veien dit — steget er da fortsatt kallbart, men
ikke uten en modell, og skal ikke telle."""
src = root / "fakesrc"
body = " return create_chat_client()\n" if chat_client else " return 1\n"
_write(src / "steg.py", f"def {symbol}():\n return 42\n")
_write(
src / "driver.py",
"from fakesrc.steg import " + symbol + "\n\n"
"def _hjelper():\n" + body + "\n\n"
"def kjor():\n"
f" _hjelper()\n return {symbol}()\n\n\n"
"def main(argv=None):\n return kjor()\n\n\n"
'if __name__ == "__main__":\n raise SystemExit(main())\n',
)
return src
#: En dør er registrert OG bevist med atferd. De konstruerte kildene under bærer begge deler.
#: Probefila SKRIVES (``_write_probe``) i stedet for bare å navngis: fra 19.09 leser gaten probens
#: EGEN kilde, og en nodeid som ikke finnes er ikke en atferd.
_FAKE_PROBE = "tests/test_konstruerte_prober.py::test_doeren_skriver_artefaktet"
_FAKE_PASSED = {_FAKE_PROBE: "passed"}
def _fake_run_path() -> dict[str, Any]:
"""Kjørestien i den konstruerte kilden — bærer pakkenavnet døren måles mot."""
return {"module": "driver.py", "scope": "kjor", "package": "fakesrc"}
def _write_probe(
root: Path,
*,
door: str = "fakesrc.driver",
needle: str = "gjoer_noe",
asserts: bool = True,
docstring: str = "",
nodeid: str = _FAKE_PROBE,
) -> str:
"""En probe som DRIVER døren: kaller kommandoen og asserter på det den gjorde.
Hvert av de fire trekkene gaten måler kan skrus av her, ett om gangen: hvilken dør den rører
(``door``), hvilket steg den navngir (``needle``), om den asserter i det hele tatt, og hva
den bare OMTALER uten å røre (``docstring``)."""
file_part, _, name = nodeid.partition("::")
said = f' """{docstring}"""\n' if docstring else ""
body = (
"import subprocess\n"
"import sys\n\n\n"
f"def {name}(tmp_path):\n"
+ said
+ f' proc = subprocess.run([sys.executable, "-m", "{door}", "--steg", "{needle}"])\n'
+ (" assert proc.returncode == 0\n" if asserts else " return proc\n")
)
_write(root / file_part, body)
return nodeid
def _one_step(symbol: str = "gjoer_noe") -> list[dict[str, Any]]:
return [
{
"id": "steg",
"label": "ett steg",
"module": "steg.py",
"symbol": symbol,
"driver": {"module": "driver.py", "scope": "kjor"},
"entry": {"kind": "module-main", "module": "driver.py", "scope": "main"},
"probe": [_FAKE_PROBE],
}
]
def test_a_step_reachable_from_a_cli_entry_without_a_chat_client_counts(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path)
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n, row.status) == (1, 1, gate.GREEN), row.exceptions
def test_m2_a_step_that_needs_a_chat_client_is_not_callable_from_outside(tmp_path: Path) -> None:
"""M-2: fjernes chatklient-sjekken, hopper k fra 0 til 1 og denne armen feller mutanten."""
src = _fake_src(tmp_path, chat_client=True)
_write_probe(tmp_path)
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n, row.status) == (0, 1, gate.RED)
assert any("chatklient" in x for x in row.exceptions)
def test_m1_the_denominator_follows_the_source_and_is_not_the_config_length(
tmp_path: Path,
) -> None:
"""M-1: en hardkodet nevner overlever repoet, men ikke en kilde med ett steg mindre."""
src = _fake_src(tmp_path, chat_client=False)
steps = _one_step() + [
{
"id": "borte",
"label": "et steg som ikke finnes i kilden",
"module": "steg.py",
"symbol": "finnes_ikke",
"driver": {"module": "driver.py", "scope": "kjor"},
"entry": {"kind": "module-main", "module": "driver.py", "scope": "main"},
}
]
_write_probe(tmp_path)
row = gate.score_toolbox(steps, src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert row.n == 1, "et steg uten symbol i kilden er ikke et steg"
assert any("borte" in x for x in row.exceptions)
def test_a_step_the_driver_no_longer_calls_leaves_the_denominator(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
_write(src / "steg.py", "def gjoer_noe():\n return 42\n\n\ndef ubrukt():\n return 0\n")
steps = _one_step() + [
{
"id": "ubrukt",
"label": "definert, men ikke i kjørestien",
"module": "steg.py",
"symbol": "ubrukt",
"driver": {"module": "driver.py", "scope": "kjor"},
"entry": {"kind": "module-main", "module": "driver.py", "scope": "main"},
}
]
_write_probe(tmp_path)
row = gate.score_toolbox(steps, src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert row.n == 1
def test_an_entry_without_a_main_is_no_entry(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
text = (src / "driver.py").read_text(encoding="utf-8").replace("def main(", "def _main(")
_write(src / "driver.py", text)
_write_probe(tmp_path)
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1)
assert any("main" in x for x in row.exceptions)
# ---------------------------------------------------------------------------------------------
# Rad 2 — det modellen leverte, kan leveres utenfra
# ---------------------------------------------------------------------------------------------
def test_the_role_denominator_is_read_from_workflow_and_matches_the_imported_module() -> None:
assert workflow._MAKER_CHECKER_ROLES == _ROLES_TODAY # uavhengig telling: modulen selv
assert gate.run_roles(_SRC, _CONFIG["roles"]["source"]) == _ROLES_TODAY
def test_the_role_denominator_follows_a_changed_source(tmp_path: Path) -> None:
src = tmp_path / "fakesrc"
_write(src / "workflow.py", '_MAKER_CHECKER_ROLES = ("a", "b", "c")\n')
assert gate.run_roles(src, _CONFIG["roles"]["source"]) == ("a", "b", "c")
def test_a_role_counts_only_when_every_named_probe_passes() -> None:
evidence = _CONFIG["roles"]["evidence"]
outcomes = {n: "passed" for ns in evidence.values() for n in ns}
row = gate.score_roles(_CONFIG["roles"], outcomes, _SRC)
assert (row.k, row.n, row.status) == (2, 2, gate.GREEN)
outcomes[evidence["checker"][0]] = "failed"
row = gate.score_roles(_CONFIG["roles"], outcomes, _SRC)
assert (row.k, row.n, row.status) == (1, 2, gate.RED)
def test_row2_today_is_red_because_the_named_probes_do_not_exist_yet() -> None:
row = gate.score_roles(_CONFIG["roles"], {}, _SRC)
assert (row.k, row.n, row.status) == (0, 2, gate.RED)
assert all("missing" in x for x in row.exceptions)
def test_m4_row2_demands_byte_identical_artefacts_not_merely_present_ones() -> None:
"""M-4: byttes kravet til «finnes», står kontrakten igjen uten den ene setningen som skiller
en ekte likhet fra to filer med samme navn."""
assert "byte-identisk" in gate.BYTE_IDENTICAL_RULE
row = gate.score_roles(_CONFIG["roles"], {}, _SRC)
assert any("byte-identisk" in a for a in row.attests)
# ---------------------------------------------------------------------------------------------
# Rad 3 — po har ingen vei til Claude
# ---------------------------------------------------------------------------------------------
def _patterns() -> list[dict[str, str]]:
return list(_CONFIG["no_claude_path"]["patterns"])
def test_every_pattern_hits_its_own_known_positive_and_misses_its_known_negative() -> None:
"""Fravær er et måleresultat: en vakt som ikke kan treffe, måler ikke null — den måler
ingenting. Nevner: alle mønstrene i kontrakten."""
assert len(_patterns()) == _PATTERNS_TODAY
for spec in _patterns():
rx = re.compile(gate.decode(spec["pattern_b64"]))
assert rx.search(gate.decode(spec["known_positive_b64"])), spec["id"]
assert not rx.search(gate.decode(spec["known_negative_b64"])), spec["id"]
def _clean_surface(tmp_path: Path) -> dict[str, Any]:
"""En ren, konstruert flate med sin egen sentinel — nevneren er aldri 0 her."""
cfg = json.loads(json.dumps(_CONFIG["no_claude_path"]))
cfg["manifest"] = {"sentinel": "src/rent.py", "skip_dirs": [".git", "__pycache__"]}
_write(tmp_path / "src" / "rent.py", "print('ingenting her')\n")
return cfg
def test_m3_the_denominator_is_the_number_of_patterns_that_can_measure(tmp_path: Path) -> None:
"""M-3: fjernes et mønster, faller nevneren — og et mønster som ikke treffer sin egen
kjent-positive telles ikke som en vakt."""
cfg = _clean_surface(tmp_path)
row = gate.score_no_claude_path(cfg, tmp_path)
assert (row.k, row.n, row.status) == (_PATTERNS_TODAY, _PATTERNS_TODAY, gate.GREEN)
cfg["patterns"][0]["pattern_b64"] = base64.b64encode(b"finnes-aldri-xyzzy").decode()
row = gate.score_no_claude_path(cfg, tmp_path)
assert (row.k, row.n, row.status) == (_PATTERNS_TODAY - 1, _PATTERNS_TODAY, gate.RED)
assert any("kjent-positiv" in x for x in row.exceptions)
cfg["patterns"] = cfg["patterns"][1:]
row = gate.score_no_claude_path(cfg, tmp_path)
assert row.n == _PATTERNS_TODAY - 1
def test_a_planted_path_to_claude_turns_the_row_red_for_that_pattern(tmp_path: Path) -> None:
cfg = _clean_surface(tmp_path)
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN, "rc-0-kontrollen først"
for spec in cfg["patterns"]:
_write(
tmp_path / "src" / f"{spec['id']}.py", gate.decode(spec["known_positive_b64"]) + "\n"
)
row = gate.score_no_claude_path(cfg, tmp_path)
assert (row.k, row.status) == (0, gate.RED)
assert len(row.exceptions) == _PATTERNS_TODAY
def test_markdown_counts_only_inside_fenced_blocks(tmp_path: Path) -> None:
"""«docs med kjørbare kommandoer»: en pakkenavn-omtale i brødtekst er ikke en vei til Claude;
den samme linja i en kodeblokk er en kommando noen kan kjøre."""
cfg = _clean_surface(tmp_path)
spec = next(s for s in cfg["patterns"] if s["id"] == "maf-anthropic")
line = gate.decode(spec["known_positive_b64"])
_write(tmp_path / "docs" / "prosa.md", f"- vurdert og forkastet: `{line}` (aldri tatt inn)\n")
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN
_write(tmp_path / "docs" / "kjorbar.md", f"```bash\n{line}\n```\n")
row = gate.score_no_claude_path(cfg, tmp_path)
assert row.status == gate.RED
assert any("kjorbar.md" in x for x in row.exceptions)
def test_row3_on_the_real_published_surface_is_green_today() -> None:
row = gate.score_no_claude_path(_CONFIG["no_claude_path"], _REPO)
assert (row.k, row.n, row.status) == (_PATTERNS_TODAY, _PATTERNS_TODAY, gate.GREEN), (
row.exceptions
)
def test_the_surface_names_its_denominator_in_files_not_in_prose() -> None:
files, _ = gate.published_files(_REPO, _manifest())
assert len(files) > 100, "en tom flate ville gitt 0 treff uten å måle noe"
assert any(f.name == "run.py" for f in files)
# ---------------------------------------------------------------------------------------------
# Rad 4 — ingen modellkall i verktøykasse-modus
# ---------------------------------------------------------------------------------------------
def test_row4_is_red_today_and_names_all_three_checks() -> None:
row = gate.score_no_model_calls(_CONFIG["no_model_calls"], {}, _SRC)
assert (row.k, row.n, row.status) == (0, 3, gate.RED)
assert len(row.exceptions) == 3
def test_row4_counts_only_checks_whose_probes_pass() -> None:
checks = _CONFIG["no_model_calls"]["checks"]
outcomes = {n: "passed" for c in checks.values() for n in c["probe"]}
row = gate.score_no_model_calls(_CONFIG["no_model_calls"], outcomes, _SRC)
assert row.status == gate.GREEN
outcomes[checks["fullfører"]["probe"][0]] = "skipped"
row = gate.score_no_model_calls(_CONFIG["no_model_calls"], outcomes, _SRC)
assert (row.k, row.status) == (2, gate.RED)
def test_row4_states_what_the_budget_guard_is_in_b_instead_of_pretending() -> None:
row = gate.score_no_model_calls(_CONFIG["no_model_calls"], {}, _SRC)
assert any("budsjett" in a.casefold() for a in row.attests)
assert "valgt" in gate.BUDGET_IN_B.casefold()
# ---------------------------------------------------------------------------------------------
# Rad 5 — Foundry-veien urørt
# ---------------------------------------------------------------------------------------------
def test_the_foundry_path_is_intact_in_the_source_today() -> None:
ok, missing = gate.foundry_intact(_CONFIG["foundry"], _SRC)
assert (ok, missing) == (True, ())
def test_the_foundry_check_fails_when_the_azure_profile_is_gone(tmp_path: Path) -> None:
src = tmp_path / "fakesrc"
_write(src / "backends.py", "class Profile:\n LOCAL = 'local'\n")
_write(src / "run.py", "def run_project(client_factory=None):\n return 1\n")
ok, missing = gate.foundry_intact(_CONFIG["foundry"], src)
assert ok is False
assert any("AZURE" in m for m in missing)
def test_row5_is_red_until_the_schema_comparison_probe_passes() -> None:
structural = len(_CONFIG["foundry"]["profile"]["members"]) + 2
row = gate.score_foundry(_CONFIG["foundry"], {}, _SRC)
assert (row.k, row.n, row.status) == (structural, structural + 1, gate.RED)
nodeid = _CONFIG["foundry"]["evidence"]["samme-skjema"][0]
row = gate.score_foundry(_CONFIG["foundry"], {nodeid: "passed"}, _SRC)
assert (row.k, row.n, row.status) == (structural + 1, structural + 1, gate.GREEN)
# ---------------------------------------------------------------------------------------------
# Rad 6 — kjøreboka finnes
# ---------------------------------------------------------------------------------------------
def test_row6_is_not_measured_while_the_runbook_is_missing(tmp_path: Path) -> None:
row = gate.score_runbook(_CONFIG["runbook"], tmp_path)
assert (row.k, row.n, row.status) == (0, 2, gate.NOT_MEASURED)
assert row.failing is True
def test_row6_is_still_not_measured_without_the_operators_attestation(tmp_path: Path) -> None:
_runbook(tmp_path)
row = gate.score_runbook(_CONFIG["runbook"], tmp_path)
assert (row.k, row.n, row.status) == (1, 2, gate.NOT_MEASURED)
def test_row6_goes_green_only_with_every_required_key(tmp_path: Path) -> None:
cfg = _CONFIG["runbook"]
digest = _runbook(tmp_path)
attest = tmp_path / cfg["attestation"]
_write(attest, f"kjørebok: {cfg['path']}\nsjekksum: {digest}\nkjørt: operatøren\n")
row = gate.score_runbook(cfg, tmp_path, now=_NOW)
assert row.status == gate.NOT_MEASURED
assert any("dato" in x for x in row.exceptions)
_attestation_lines(tmp_path, digest)
row = gate.score_runbook(cfg, tmp_path, now=_NOW)
assert (row.k, row.n, row.status) == (2, 2, gate.GREEN)
def test_a_duplicated_key_in_the_attestation_is_red(tmp_path: Path) -> None:
cfg = _CONFIG["runbook"]
digest = _runbook(tmp_path)
_attestation_lines(tmp_path, digest)
path = tmp_path / cfg["attestation"]
path.write_text(path.read_text(encoding="utf-8") + "kjørt: en annen\n", encoding="utf-8")
row = gate.score_runbook(cfg, tmp_path, now=_NOW)
assert row.status == gate.NOT_MEASURED
assert any("to ganger" in x for x in row.exceptions)
def test_m5_the_gate_never_writes_the_attestation_itself(tmp_path: Path) -> None:
"""M-5: kan gaten skrive fila den leser, er rad 6 en sløyfe som bekrefter seg selv."""
_write(tmp_path / _CONFIG["runbook"]["path"], "# kjørebok\n")
attest = tmp_path / _CONFIG["runbook"]["attestation"]
rows = gate.evaluate(config=_CONFIG, repo_root=tmp_path, src=_SRC, probe_runner=_probes())
assert not attest.exists(), "gaten skrev operatørens attestering — da beviser rad 6 ingenting"
assert _row(rows, "kjørebok").status == gate.NOT_MEASURED
assert any("aldri" in a for a in _row(rows, "kjørebok").attests)
# ---------------------------------------------------------------------------------------------
# Hele gaten
# ---------------------------------------------------------------------------------------------
def test_the_gate_is_red_today_and_every_row_is_red_for_a_measured_reason() -> None:
rows = gate.evaluate(config=_CONFIG, repo_root=_REPO, src=_SRC, probe_runner=_probes())
assert gate.exit_code(rows) == 1
assert [r.key for r in rows] == [
"verktøykasse",
"roller",
"ingen-claude-vei",
"ingen-modellkall",
"foundry",
"kjørebok",
]
for row in rows:
assert row.status in {gate.GREEN, gate.RED, gate.NOT_MEASURED}
if row.status != gate.GREEN:
assert row.k is not None and row.n is not None, f"{row.key} mangler k av N"
assert row.exceptions, f"{row.key} er ikke grønn uten å si hvorfor"
def test_the_probe_runner_separates_a_test_that_exists_from_one_that_does_not() -> None:
"""Kjent-positiv for selve probe-mekanismen: «missing» over hele lista ville vært et
måleresultat uten nevner. Nevneren er to nodeid-er — én som finnes i suiten og én som ikke
gjør det — og mekanismen må skille dem. Proben peker med vilje UT av denne fila: en nodeid
herfra ville fått barne-pytest til å kjøre denne testen igjen, i det uendelige."""
lever = "tests/test_ledger.py::test_totals_per_project_and_portfolio"
dod = "tests/test_ledger.py::test_finnes_ikke_xyzzy"
outcomes = v1_gate.run_probes([lever, dod], _REPO)
assert outcomes[lever] == "passed"
assert outcomes[dod] == "missing"
def test_render_names_every_row_the_budget_choice_and_the_runbook_rule() -> None:
rows = gate.evaluate(config=_CONFIG, repo_root=_REPO, src=_SRC, probe_runner=_probes())
text = gate.render(rows)
for row in rows:
assert row.title in text
assert gate.BUDGET_IN_B in text
assert gate.RUNBOOK_RULE in text
def test_the_command_runs_offline_and_exits_one() -> None:
proc = subprocess.run(
[sys.executable, "-m", "portfolio_optimiser.evals.b_gate", "--json"],
cwd=_REPO,
capture_output=True,
text=True,
)
assert proc.returncode == 1, proc.stderr
payload = json.loads(proc.stdout)
assert payload["exit"] == 1
assert len(payload["rows"]) == 6
def test_a_bad_attestation_path_is_usage_error_not_a_silent_green(tmp_path: Path) -> None:
proc = subprocess.run(
[sys.executable, "-m", "portfolio_optimiser.evals.b_gate", "--attest", str(tmp_path / "x")],
cwd=_REPO,
capture_output=True,
text=True,
)
assert proc.returncode == 2
# =============================================================================================
# REPARASJONEN 19.09.2026 (PM-sjekkpunktet på 207337c): nevnerne utledet av KILDEN, en dør som
# må være REGISTRERT og bevist med atferd, hele den publiserte flaten, og en attestering som kan
# felles. Hver arm under feller på en ASSERT om atferd, aldri ved innsamling.
# =============================================================================================
#: po-funksjoner ``run.py::run_project`` faktisk kaller — talt av armens EGEN parser under.
#: 41 = PMs 39 deterministiske + de to som krever en chatklient og holdes utenfor med grunn.
_RUN_PATH_CALLS_TODAY = 41
#: utboks-skrivere: definert i outbox.py / kalt i kjørestien. PMs tall, talt om igjen her.
_WRITERS_DEFINED = 10
_WRITERS_IN_RUN_PATH = 7
#: publiserte filer i git-manifestet (uttrekk og arbeidstre gir SAMME tall — det var hele poenget
#: med å slutte å telle filtreet: 435 i arbeidstreet var to gitignorerte .local.md-filer).
_PUBLISHED_TODAY = 514
_UNDECODABLE_TODAY = 1
def _manifest() -> dict[str, Any]:
manifest = _CONFIG["no_claude_path"].get("manifest")
assert manifest is not None, "kontrakten utleder ikke flaten av repo-manifestet"
return dict(manifest)
def _run_path_spec() -> dict[str, Any]:
spec = _CONFIG.get("run_path")
assert spec is not None, "kontrakten navngir ingen kjørested — nevneren har da ingen kilde"
return dict(spec)
def _independently_counted_run_path() -> dict[str, str]:
"""po-funksjonene ``run_project`` kaller, talt av TESTENS egen parser — ingen gate-kode rørt.
Regelen: et navn importert fra en ``portfolio_optimiser``-undermodul og kalt i scopet, eller
et attributt på en modul importert som ``from portfolio_optimiser import X``. Klasser og
unntak (stor forbokstav) er ikke steg; private hjelpere i run.py heller ikke."""
tree = ast.parse((_SRC / "run.py").read_text(encoding="utf-8"))
symbols: dict[str, str] = {}
aliases: set[str] = set()
for node in ast.walk(tree):
if not isinstance(node, ast.ImportFrom):
continue
module = node.module or ""
if module == "portfolio_optimiser":
aliases |= {a.asname or a.name for a in node.names}
elif module.startswith("portfolio_optimiser."):
for alias in node.names:
symbols[alias.asname or alias.name] = module.split(".")[-1] + ".py"
scope = next(
n
for n in ast.walk(tree)
if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)) and n.name == "run_project"
)
found: dict[str, str] = {}
for call in ast.walk(scope):
if not isinstance(call, ast.Call):
continue
func = call.func
if isinstance(func, ast.Name) and func.id in symbols and func.id[:1].islower():
found[func.id] = symbols[func.id]
elif (
isinstance(func, ast.Attribute)
and isinstance(func.value, ast.Name)
and func.value.id in aliases
and func.attr[:1].islower()
):
found[func.attr] = f"{func.value.id}.py"
return found
def test_the_run_path_denominator_is_read_from_the_source_not_from_the_contract() -> None:
"""Rad 1s nevner kom fra gatens EGEN b_gate.json. Nå leses kjørestien av kilden, og testen
teller den om igjen selv."""
mine = _independently_counted_run_path()
assert len(mine) == _RUN_PATH_CALLS_TODAY, sorted(mine)
theirs = gate.run_path_calls(_SRC, _run_path_spec())
assert set(theirs) == set(mine), sorted(set(mine) ^ set(theirs))
def test_every_call_in_the_run_path_is_either_a_declared_step_or_held_out_with_a_reason() -> None:
"""Den ene egenskapen en kuratert liste ikke har: ingenting kan utelates STILLE."""
calls = set(_independently_counted_run_path())
declared = {str(s["symbol"]) for s in _CONFIG["steps"]}
held = {
str(h["symbol"]): str(h.get("reason", "")) for h in _run_path_spec().get("held_out", ())
}
assert not (calls - declared - set(held)), sorted(calls - declared - set(held))
assert all(held.values()), [s for s, why in held.items() if not why]
assert len(calls & declared) + len(held) == _RUN_PATH_CALLS_TODAY
def test_the_outbox_writers_the_run_path_uses_are_all_declared_steps() -> None:
"""PMs 7 av 10, talt om igjen her: artefaktfamilien er ikke tre filer, den er sju."""
outbox_tree = ast.parse((_SRC / "outbox.py").read_text(encoding="utf-8"))
writers = {
n.name
for n in outbox_tree.body
if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)) and n.name.startswith("write_")
}
assert len(writers) == _WRITERS_DEFINED
in_path = writers & set(_independently_counted_run_path())
assert len(in_path) == _WRITERS_IN_RUN_PATH, sorted(in_path)
declared = {str(s["symbol"]) for s in _CONFIG["steps"]}
assert not (in_path - declared), sorted(in_path - declared)
def _mini_run_path(root: Path, *, extra_call: bool) -> tuple[Path, dict[str, Any]]:
"""En konstruert kilde med en kjøresti som kaller ett eller to po-steg."""
src = root / "minisrc"
_write(src / "steg.py", "def alfa():\n return 1\n\n\ndef beta():\n return 2\n")
body = " alfa()\n" + (" beta()\n" if extra_call else "")
_write(
src / "kjor.py",
f"from minisrc.steg import alfa, beta\n\n\nasync def run_project():\n{body} return 0\n",
)
return src, {"module": "kjor.py", "scope": "run_project", "package": "minisrc"}
def test_an_undeclared_call_in_the_run_path_raises_the_denominator_and_is_named(
tmp_path: Path,
) -> None:
"""M-6: nevneren kan ikke krympe stille — et kall ingen erklærte teller som et steg UTEN dør."""
src, spec = _mini_run_path(tmp_path, extra_call=True)
steps = [
{
"id": "alfa",
"label": "alfa",
"module": "steg.py",
"symbol": "alfa",
"driver": {"module": "kjor.py", "scope": "run_project"},
"entry": {"kind": "module-main", "module": "kjor.py", "scope": "main"},
}
]
row = gate.score_toolbox(steps, src, spec, {}, tmp_path)
assert row.n == 2, "beta kalles i kjørestien og er verken erklært eller holdt utenfor"
assert any("beta" in x for x in row.exceptions)
def test_a_held_out_call_leaves_the_denominator_but_is_named_with_its_reason(
tmp_path: Path,
) -> None:
src, spec = _mini_run_path(tmp_path, extra_call=True)
spec["held_out"] = [{"symbol": "beta", "reason": "hjelper inne i alfa, ikke et eget steg"}]
steps = [
{
"id": "alfa",
"label": "alfa",
"module": "steg.py",
"symbol": "alfa",
"driver": {"module": "kjor.py", "scope": "run_project"},
"entry": {"kind": "module-main", "module": "kjor.py", "scope": "main"},
}
]
row = gate.score_toolbox(steps, src, spec, {}, tmp_path)
assert row.n == 1
assert any("beta" in d and "hjelper inne i alfa" in d for d in row.diagnostics), row.diagnostics
def test_removing_a_declared_step_does_not_shrink_the_denominator(tmp_path: Path) -> None:
"""A2 fra sjekkpunktet: «utboks» fjernet fra steps ga «3 av 12» uten en klage."""
src, spec = _mini_run_path(tmp_path, extra_call=True)
row = gate.score_toolbox([], src, spec, {}, tmp_path)
assert row.n == 2, "begge kallene står igjen i kjørestien selv om kontrakten glemte dem"
assert len(row.exceptions) == 2
# --- døren: registrert, av en art gaten kan verifisere, og bevist med atferd -------------------
def _fake_pyproject(root: Path, scripts: dict[str, str]) -> None:
lines = "\n".join(f'{name} = "{target}"' for name, target in scripts.items())
_write(
root / "pyproject.toml",
f'[project]\nname = "fake"\nversion = "0"\n\n[project.scripts]\n{lines}\n\n[tool.x]\ny = 1\n',
)
def test_an_entry_kind_the_gate_cannot_verify_is_never_a_door(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
ok, why = gate.registered_entry(
src, tmp_path, "fakesrc", {"kind": "magi", "module": "driver.py", "scope": "main"}
)
assert ok is False and "magi" in why
assert "magi" not in gate.ENTRY_KINDS
def test_a_console_script_is_a_door_only_when_the_manifest_registers_it(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
entry = {"kind": "console-script", "module": "driver.py", "scope": "main"}
_fake_pyproject(tmp_path, {})
ok, why = gate.registered_entry(src, tmp_path, "fakesrc", entry)
assert ok is False and "pyproject" in why
_fake_pyproject(tmp_path, {"fake-kommando": "fakesrc.driver:main"})
assert gate.registered_entry(src, tmp_path, "fakesrc", entry) == (True, "")
def test_a_module_main_is_a_door_only_with_the_dunder_guard(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
entry = {"kind": "module-main", "module": "driver.py", "scope": "main"}
assert gate.registered_entry(src, tmp_path, "fakesrc", entry) == (True, "")
stripped = (src / "driver.py").read_text(encoding="utf-8")
_write(src / "driver.py", stripped[: stripped.index("if __name__")])
ok, why = gate.registered_entry(src, tmp_path, "fakesrc", entry)
assert ok is False and "__main__" in why
def test_a_subcommand_is_a_door_only_when_the_parser_registers_that_name(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
entry = {
"kind": "subcommand",
"module": "driver.py",
"scope": "main",
"command": "naviger-pakke",
}
assert gate.registered_entry(src, tmp_path, "fakesrc", entry)[0] is False
_write(
src / "driver.py",
(src / "driver.py").read_text(encoding="utf-8")
+ '\n\ndef _parser(sub):\n sub.add_parser("naviger-pakke")\n',
)
assert gate.registered_entry(src, tmp_path, "fakesrc", entry) == (True, "")
def test_a_stub_main_is_not_a_door_without_a_registered_entry(tmp_path: Path) -> None:
"""A1 fra sjekkpunktet, felt: en modul med bare `def main(): return <symbol>()` tok rad 1 fra
3 til 4 av 13. Navn alene er aldri grønt."""
src = _fake_src(tmp_path, chat_client=False)
_fake_pyproject(tmp_path, {})
steps = _one_step()
steps[0]["entry"] = {"kind": "console-script", "module": "driver.py", "scope": "main"}
_write_probe(tmp_path)
row = gate.score_toolbox(steps, src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1)
assert any("pyproject" in x for x in row.exceptions), row.exceptions
def test_a_registered_door_without_a_passing_behaviour_probe_does_not_count(
tmp_path: Path,
) -> None:
"""«Kallet med en fixture gir det dokumenterte artefaktet» — et navn er ikke en atferd."""
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path)
steps = _one_step()
row = gate.score_toolbox(steps, src, _fake_run_path(), {}, tmp_path)
assert (row.k, row.n) == (0, 1)
assert any("atferdsprobe" in x for x in row.exceptions), row.exceptions
row = gate.score_toolbox(steps, src, _fake_run_path(), {_FAKE_PROBE: "skipped"}, tmp_path)
assert row.k == 0, "hoppet over er ikke bestått"
row = gate.score_toolbox(steps, src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n, row.status) == (1, 1, gate.GREEN), row.exceptions
def test_a_step_without_any_probe_is_never_a_door(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path)
steps = _one_step()
steps[0].pop("probe")
row = gate.score_toolbox(steps, src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1)
assert any("ingen atferdsprobe" in x for x in row.exceptions), row.exceptions
def test_the_door_rule_claims_only_kinds_the_gate_can_verify() -> None:
"""A8: EXTERNAL_DOOR påsto at en MCP-registrert dør telles; «kind» ble aldri lest."""
assert gate.ENTRY_KINDS
assert "mcp" not in gate.EXTERNAL_DOOR.casefold().replace("mcp ville", "")
assert all(kind in gate.EXTERNAL_DOOR for kind in gate.ENTRY_KINDS)
assert '"kind"' in Path(gate.__file__).read_text(encoding="utf-8")
# --- rad 3: hele den publiserte flaten, og de indirekte veiene ---------------------------------
def test_the_published_surface_is_the_repo_manifest_and_not_a_handlist() -> None:
"""A10: main.py, examples/, spikes/ og contexts/ er publisert, men lå utenfor roots.
Armen holder i BEGGE verdener — arbeidstreet (git-manifestet) og et rent uttrekk (filtreet),
som er nøyaktig det publiserte. Den nøyaktige nevneren pinnes av armen under, som er den ene
som trenger repoets egen git-metadata."""
files, _source = gate.published_files(_REPO, _manifest())
names = {str(p.relative_to(_REPO)) for p in files}
assert "main.py" in names and "CLAUDE.md" in names and "llms.txt" in names
assert any(n.startswith("examples/") for n in names)
assert any(n.startswith("spikes/") for n in names)
assert any(n.startswith("contexts/") for n in names)
assert len(files) > 400, len(files)
def test_the_surface_count_matches_an_independent_count_of_the_manifest() -> None:
"""Den ENE armen som trenger repoets egen git-metadata. I et rent uttrekk («not a git
repository») finnes ikke manifestet å telle mot, og armen HOPPER OVER seg selv i stedet for å
felle: ellers vokser «røde i uttrekket» med hver ny git-avhengig arm, og tallet slutter å
være et funn. Nevneren pinnes HER, ikke i armen over."""
listing = subprocess.run(["git", "ls-files", "-z"], cwd=_REPO, capture_output=True, text=True)
if listing.returncode != 0:
pytest.skip("uttrekk uten git-metadata: manifestet finnes ikke å telle mot")
mine = {t for t in listing.stdout.split("\0") if t}
assert len(mine) == _PUBLISHED_TODAY, len(mine)
files, source = gate.published_files(_REPO, _manifest())
assert {str(p.relative_to(_REPO)) for p in files} == mine
assert "git-manifestet" == source
def test_a_surface_without_its_sentinel_is_not_measured_instead_of_green(tmp_path: Path) -> None:
"""A4: «6 av 6 GRØNN over 0 publiserte filer». Et fravær uten nevner er ikke et bevis."""
cfg = json.loads(json.dumps(_CONFIG["no_claude_path"]))
cfg.pop("roots", None)
cfg["manifest"] = {"sentinel": "src/portfolio_optimiser/run.py"}
row = gate.score_no_claude_path(cfg, tmp_path)
assert row.status == gate.NOT_MEASURED, row.reason
assert any("sentinel" in x for x in row.exceptions), row.exceptions
assert "0 publiserte filer" in row.reason
def test_the_row_names_which_manifest_it_read() -> None:
"""Nevneren står i radens EGEN tekst, sammen med hvor lista kom fra og hvor mange filer som
ikke lot seg avkode — «0 treff» uten nevner er ikke et bevis."""
row = gate.score_no_claude_path(_CONFIG["no_claude_path"], _REPO)
files, source = gate.published_files(_REPO, _manifest())
assert f"over {len(files)} publiserte filer" in row.reason
assert source in row.reason
assert f"{_UNDECODABLE_TODAY} ikke-UTF-8, lest som byte-tekst" in row.reason
def test_the_surface_falls_back_to_the_tree_when_there_is_no_git_metadata(tmp_path: Path) -> None:
"""Et rent uttrekk (`git archive | tar -x`) har ingen .git — og ER nøyaktig det publiserte."""
_write(tmp_path / "src" / "portfolio_optimiser" / "run.py", "x = 1\n")
_write(tmp_path / "main.py", "y = 2\n")
_write(tmp_path / "__pycache__" / "skrot.pyc", "nei\n")
files, source = gate.published_files(tmp_path, {"sentinel": "src/portfolio_optimiser/run.py"})
names = {str(p.relative_to(tmp_path)) for p in files}
assert names == {"src/portfolio_optimiser/run.py", "main.py"}
assert "uttrekk" in source
#: PMs fem realistiske kall-varianter, base64-kodet av samme grunn som mønstrene i kontrakten:
#: tests/ er selv en del av den publiserte flaten raden skanner, og en klartekst-variant her
#: ville registrert seg som sitt eget funn.
_INDIRECT_VARIANTS = (
("direkte", "c3VicHJvY2Vzcy5ydW4oWyJjbGF1ZGUiLCAiLXAiLCAieCJdKQ=="),
("absolutt-sti", "c3VicHJvY2Vzcy5ydW4oWyIvdXNyL2xvY2FsL2Jpbi9jbGF1ZGUiLCAiLXAiLCAieCJdKQ=="),
("liste-i-variabel", "Y21kID0gWyJjbGF1ZGUiLCAiLXAiLCAieCJdCnN1YnByb2Nlc3MucnVuKGNtZCk="),
(
"konstant",
"Q0xBVURFX0JJTiA9ICJjbGF1ZGUiCnN1YnByb2Nlc3MucnVuKFtDTEFVREVfQklOLCAiLXAiLCAieCJdKQ==",
),
("shell-streng", "c3VicHJvY2Vzcy5ydW4oc2hsZXguc3BsaXQoImNsYXVkZSAtcCB4Iikp"),
)
def test_every_indirect_way_of_starting_claude_is_caught(tmp_path: Path) -> None:
"""A9: 4 av 5 realistiske varianter slapp forbi. Hver plantes som kjent-positiv, én om
gangen, og hver skal felle raden."""
cfg = json.loads(json.dumps(_CONFIG["no_claude_path"]))
cfg.pop("roots", None)
cfg["manifest"] = {"sentinel": "src/run.py"}
_write(tmp_path / "src" / "run.py", "x = 1\n")
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN, "kontroll: ren flate"
for name, snippet in _INDIRECT_VARIANTS:
planted = tmp_path / "src" / f"{name}.py"
_write(planted, gate.decode(snippet) + "\n")
row = gate.score_no_claude_path(cfg, tmp_path)
assert row.status == gate.RED, name
assert any(name in x for x in row.exceptions), (name, row.exceptions)
planted.unlink()
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN
def test_the_row_states_the_limit_its_patterns_cannot_reach() -> None:
row = gate.score_no_claude_path(_CONFIG["no_claude_path"], _REPO)
assert any("satt sammen" in a or "miljøvariabel" in a for a in row.attests), row.attests
# --- rad 4, 5 og 6: hver nevner med en navngitt kilde -----------------------------------------
def test_row4_counts_only_checks_whose_named_source_resolves(tmp_path: Path) -> None:
"""M=3 var en konstant i gatens egen konfig. Nå er hver sjekk bundet til et symbol i kilden."""
cfg = json.loads(json.dumps(_CONFIG["no_model_calls"]))
row = gate.score_no_model_calls(cfg, {}, _SRC)
assert (row.k, row.n, row.status) == (0, 3, gate.RED)
for name, check in cfg["checks"].items():
assert isinstance(check, dict) and "source" in check, name
tree = ast.parse((_SRC / check["source"]["module"]).read_text(encoding="utf-8"))
names = {
n.name for n in tree.body if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef))
} | {
t.id
for n in tree.body
if isinstance(n, ast.Assign)
for t in n.targets
if isinstance(t, ast.Name)
}
assert check["source"]["symbol"] in names, name
src = tmp_path / "tom"
src.mkdir()
row = gate.score_no_model_calls(cfg, {}, src)
assert row.n == 0, "en sjekk uten kilde i koden teller ikke med i nevneren"
assert len(row.exceptions) == 3
def test_row5_counts_each_structural_requirement_on_its_own(tmp_path: Path) -> None:
"""M=2 blandet profil, fabrikk og injeksjonssøm til ÉN enhet. Nå telles hvert krav for seg,
og hvert av dem er et symbol i kilden."""
row = gate.score_foundry(_CONFIG["foundry"], {}, _SRC)
members = len(_CONFIG["foundry"]["profile"]["members"])
evidence = len(_CONFIG["foundry"]["evidence"])
assert row.n == members + 2 + evidence
assert (row.k, row.status) == (members + 2, gate.RED)
nodeid = _CONFIG["foundry"]["evidence"]["samme-skjema"][0]
row = gate.score_foundry(_CONFIG["foundry"], {nodeid: "passed"}, _SRC)
assert row.status == gate.GREEN
def test_row5_denominator_follows_the_named_members(tmp_path: Path) -> None:
cfg = json.loads(json.dumps(_CONFIG["foundry"]))
cfg["profile"]["members"].append("FINNES_IKKE")
row = gate.score_foundry(cfg, {}, _SRC)
assert row.n == len(cfg["profile"]["members"]) + 2 + len(cfg["evidence"])
assert any("FINNES_IKKE" in x for x in row.exceptions)
def test_row6_denominator_comes_from_the_artefacts_the_contract_names(tmp_path: Path) -> None:
artefacts = _CONFIG["runbook"].get("artefacts")
assert artefacts is not None, "M=2 var en konstant i koden, ikke noe kontrakten navngir"
row = gate.score_runbook(_CONFIG["runbook"], tmp_path)
assert row.n == len(artefacts)
# --- rad 6: attesteringen kan felles ----------------------------------------------------------
def _runbook(root: Path) -> str:
"""En kjørebok som bærer seksjonene kontrakten navngir — ellers er «x» en kjørebok (N3)."""
sections = "\n".join(
f"## {s}\n\nsteg 1: naviger pakken\n" for s in _CONFIG["runbook"]["sections"]
)
text = f"# kjørebok\n\n{sections}"
_write(root / _CONFIG["runbook"]["path"], text)
return hashlib.sha256(text.encode("utf-8")).hexdigest()
def _attestation_lines(root: Path, digest: str, **over: str) -> None:
fields = {
"kjørebok": _CONFIG["runbook"]["path"],
"sjekksum": digest,
"kjørt": "operatøren",
"dato": "2026-09-19",
}
fields.update(over)
_write(
root / _CONFIG["runbook"]["attestation"],
"".join(f"{k}: {v}\n" for k, v in fields.items()),
)
def test_a_valid_attestation_is_the_only_thing_that_turns_row6_green(tmp_path: Path) -> None:
"""rc-0-kontrollen FØRST: en gate som nekter alt er like ubrukelig som en som nekter noe."""
digest = _runbook(tmp_path)
_attestation_lines(tmp_path, digest)
row = gate.score_runbook(_CONFIG["runbook"], tmp_path, now=_NOW)
assert (row.k, row.n, row.status) == (2, 2, gate.GREEN), row.exceptions
def test_an_attestation_that_names_another_runbook_is_refused(tmp_path: Path) -> None:
"""A7: «kjørebok: x» ga 2 av 2 GRØNN."""
digest = _runbook(tmp_path)
_attestation_lines(tmp_path, digest, **{"kjørebok": "x"})
row = gate.score_runbook(_CONFIG["runbook"], tmp_path, now=_NOW)
assert row.status == gate.NOT_MEASURED
assert any("kjørebok" in x for x in row.exceptions)
def test_an_attestation_whose_checksum_does_not_match_the_runbook_is_refused(
tmp_path: Path,
) -> None:
"""En attestering av en ANNEN versjon av kjøreboka er ikke en attestering av denne."""
_runbook(tmp_path)
_attestation_lines(tmp_path, "0" * 64)
row = gate.score_runbook(_CONFIG["runbook"], tmp_path, now=_NOW)
assert row.status == gate.NOT_MEASURED
assert any("sjekksum" in x for x in row.exceptions)
def test_an_attestation_dated_in_the_future_is_refused(tmp_path: Path) -> None:
"""A7: framtidsdato 3026-01-01 ga GRØNN. Samme regel som v1-gaten, gjenbrukt."""
digest = _runbook(tmp_path)
_attestation_lines(tmp_path, digest, dato="3026-01-01")
row = gate.score_runbook(_CONFIG["runbook"], tmp_path, now=_NOW)
assert row.status == gate.NOT_MEASURED
assert any("framtiden" in x for x in row.exceptions)
def test_an_attestation_without_a_real_date_is_refused(tmp_path: Path) -> None:
digest = _runbook(tmp_path)
_attestation_lines(tmp_path, digest, dato="x")
row = gate.score_runbook(_CONFIG["runbook"], tmp_path, now=_NOW)
assert row.status == gate.NOT_MEASURED
assert any("ISO" in x or "dato" in x for x in row.exceptions)
def test_an_attestation_with_a_bom_is_still_read(tmp_path: Path) -> None:
"""v1-gaten TÅLER BOM — en editor som skriver den er ikke operatørens feil."""
digest = _runbook(tmp_path)
_attestation_lines(tmp_path, digest)
path = tmp_path / _CONFIG["runbook"]["attestation"]
path.write_bytes(b"\xef\xbb\xbf" + path.read_bytes())
assert gate.score_runbook(_CONFIG["runbook"], tmp_path, now=_NOW).status == gate.GREEN
# =============================================================================================
# REPARASJON 2, 19.09.2026 (PM-sjekkpunktet på c1bdb37): en probe som er bundet til SITT steg,
# en grenseerklæring som er sann, og en grunn som ikke kan være tom. Hver arm under feller på en
# ASSERT om atferd, og hver nekt-arm bærer sin egen rc-0-kontroll FØRST: en regel som nekter alt
# er like ubrukelig som en som nekter ingenting.
# =============================================================================================
#: Den konstruerte doblen brukes i to steg-varianter; symbolene står her fordi armene teller dem.
_TWO_STEP_SYMBOLS = ("gjoer_noe", "gjoer_noe_annet")
def _two_step_src(root: Path) -> Path:
"""En konstruert kilde med TO steg bak samme dør — der en delt probe blir et spørsmål."""
src = root / "fakesrc"
_write(
src / "steg.py",
"def gjoer_noe():\n return 42\n\n\ndef gjoer_noe_annet():\n return 43\n",
)
_write(
src / "driver.py",
"from fakesrc.steg import gjoer_noe, gjoer_noe_annet\n\n\n"
"def kjor():\n gjoer_noe()\n return gjoer_noe_annet()\n\n\n"
"def main(argv=None):\n return kjor()\n\n\n"
'if __name__ == "__main__":\n raise SystemExit(main())\n',
)
return src
def _two_steps(probe_a: str, probe_b: str) -> list[dict[str, Any]]:
entry = {"kind": "module-main", "module": "driver.py", "scope": "main"}
return [
{
"id": "steg-a",
"label": "steg a",
"module": "steg.py",
"symbol": "gjoer_noe",
"driver": {"module": "driver.py", "scope": "kjor"},
"entry": dict(entry),
"probe": [probe_a],
},
{
"id": "steg-b",
"label": "steg b",
"module": "steg.py",
"symbol": "gjoer_noe_annet",
"driver": {"module": "driver.py", "scope": "kjor"},
"entry": dict(entry),
"probe": [probe_b],
},
]
def test_a_probe_that_never_touches_the_door_is_not_a_behaviour_probe(tmp_path: Path) -> None:
"""N2 fra sjekkpunktet: en registrert stub-dør + en probe pekt på en URELATERT grønn test tok
rad 1 fra 3 til 4 av 17. Det som skilte dem var ingenting — gaten slo bare opp om nodeid-en
var ``passed``. Nå leses probens EGEN kilde, og «rører døren» er målt, ikke erklært."""
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path)
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n, row.status) == (1, 1, gate.GREEN), row.exceptions
_write_probe(tmp_path, door="fakesrc.enhelt_annen_modul")
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1)
assert any("rører ikke døren" in x for x in row.exceptions), row.exceptions
def test_a_probe_that_drives_the_door_without_naming_the_step_proves_the_door_only(
tmp_path: Path,
) -> None:
"""To steg bak SAMME dør er det vanlige tilfellet (``round_builder`` bærer to). En probe som
bare kjører kommandoen skiller dem ikke — den må navngi steget den beviser.
Nevneren er TO med vilje (endret 20.09): navngivningen er en diskriminator, og et steg som
er alene bak sin dør har ingenting å skilles fra — se
``test_the_sole_step_behind_a_door_is_proved_by_driving_that_door``."""
src = _two_step_src(tmp_path)
a = _write_probe(tmp_path, needle="gjoer_noe", nodeid="tests/test_a.py::test_a")
b = _write_probe(tmp_path, needle="gjoer_noe_annet", nodeid="tests/test_b.py::test_b")
outcomes = {a: "passed", b: "passed"}
assert gate.score_toolbox(_two_steps(a, b), src, _fake_run_path(), outcomes, tmp_path).k == 2
b = _write_probe(tmp_path, needle="et_helt_annet_steg", nodeid="tests/test_b.py::test_b")
row = gate.score_toolbox(_two_steps(a, b), src, _fake_run_path(), outcomes, tmp_path)
assert (row.k, row.n) == (1, 2)
assert any("navngir ikke steget" in x for x in row.exceptions), row.exceptions
def test_a_probe_that_only_mentions_the_door_or_the_step_proves_neither(tmp_path: Path) -> None:
"""FUNN 19.09, mutant M12 overlevde FØRSTE forsøk på å felle den: leses HELE probens kropp,
holder det å skrive dørens navn som en streng som står alene. Da er «rører døren» en omtale
igjen, ikke en atferd — nøyaktig feilen ett hakk lenger inne.
Nålen er dørens navn NØYAKTIG, ikke som del av en setning: gaten sammenligner hele strenger,
så en docstring som OMTALER modulen i prosa faller uansett. Den billigste måten å jukse på er
derfor å skrive navnet bart, og det er den formen armen planter."""
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path, docstring="en ekte probe: den kjører døren og sjekker exit-koden")
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (1, 1), row.exceptions
_write_probe(tmp_path, door="fakesrc.enhelt_annen_modul", docstring="fakesrc.driver")
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1), row.exceptions
assert any("rører ikke døren" in x for x in row.exceptions), row.exceptions
to_steg = _two_step_src(tmp_path)
a = _write_probe(tmp_path, needle="gjoer_noe", nodeid="tests/test_a.py::test_a")
b = _write_probe(
tmp_path,
needle="et_annet_navn",
docstring="gjoer_noe_annet",
nodeid="tests/test_b.py::test_b",
)
row = gate.score_toolbox(
_two_steps(a, b), to_steg, _fake_run_path(), {a: "passed", b: "passed"}, tmp_path
)
assert (row.k, row.n) == (1, 2), row.exceptions
assert any("navngir ikke steget" in x for x in row.exceptions), row.exceptions
def test_a_probe_that_asserts_nothing_is_not_a_behaviour_probe(tmp_path: Path) -> None:
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path)
assert gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path).k == 1
_write_probe(tmp_path, asserts=False)
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1)
assert any("asserter" in x for x in row.exceptions), row.exceptions
def test_a_probe_whose_test_does_not_exist_is_never_a_door(tmp_path: Path) -> None:
"""«passed» for en nodeid som ikke finnes er et måleresultat uten kilde."""
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path)
assert gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path).k == 1
(tmp_path / "tests" / "test_konstruerte_prober.py").unlink()
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1)
assert any("finnes ikke" in x for x in row.exceptions), row.exceptions
_write_probe(tmp_path, nodeid="tests/test_konstruerte_prober.py::test_et_annet_navn")
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1), row.exceptions
def test_one_probe_cannot_prove_two_steps(tmp_path: Path) -> None:
"""N2b sin kjerne: ÉN test brukt som atferdsprobe for alle stegene samtidig. En probe som er
delt beviser høyst ett av dem, og gaten vet ikke hvilket — altså ingen."""
src = _two_step_src(tmp_path)
a = _write_probe(tmp_path, needle="gjoer_noe", nodeid="tests/test_a.py::test_a")
b = _write_probe(tmp_path, needle="gjoer_noe_annet", nodeid="tests/test_b.py::test_b")
outcomes = {a: "passed", b: "passed"}
row = gate.score_toolbox(_two_steps(a, b), src, _fake_run_path(), outcomes, tmp_path)
assert (row.k, row.n, row.status) == (2, 2, gate.GREEN), row.exceptions
shared = _write_probe(
tmp_path,
needle="gjoer_noe",
nodeid="tests/test_delt.py::test_delt",
)
row = gate.score_toolbox(
_two_steps(shared, shared), src, _fake_run_path(), {shared: "passed"}, tmp_path
)
assert row.k == 0, row.exceptions
assert all("delt" in x for x in row.exceptions), row.exceptions
def test_the_same_unrelated_green_test_cannot_turn_the_real_row1_into_a_door(
tmp_path: Path,
) -> None:
"""N2b mot KONTRAKTEN som står: hver av de 17 stegenes probe byttet ut med én urelatert
bestått test. Målt 19.09 ga det «17 av 17 GRØNN» med fjorten stubber; her er nevneren
repoets egen kontrakt, og ingen av stegene skal telle."""
steps = json.loads(json.dumps(_CONFIG["steps"]))
unrelated = "tests/test_ledger.py::test_totals_per_project_and_portfolio"
for step in steps:
step["probe"] = [unrelated]
row = gate.score_toolbox(steps, _SRC, _CONFIG["run_path"], {unrelated: "passed"}, _REPO)
assert row.n == _STEPS_TODAY
assert row.k == 0, row.exceptions
def test_the_door_rule_says_what_it_measures_about_the_probe() -> None:
"""A8-klassen igjen: `EXTERNAL_DOOR` lovet at proben «kaller døren og leser artefaktet den
skriver», og det fantes ingen kode. Regelen skal si nøyaktig det gaten MÅLER."""
rule = gate.EXTERNAL_DOOR.casefold()
assert "probens egen kilde" in rule
assert "delt" in rule
# --- rad 1: en grunn kan ikke være tom, og de kuraterte stegene navngis ------------------------
def test_a_held_out_call_without_a_reason_stays_in_the_denominator(tmp_path: Path) -> None:
"""N4/N5: et steg flyttet fra ``steps`` til ``held_out`` tok nevneren 17 → 16 MED ELLER UTEN
grunn. Unntakslista er den nye kurateringsflaten; en tom grunn er ingen grunn."""
src, spec = _mini_run_path(tmp_path, extra_call=True)
steps = [
{
"id": "alfa",
"label": "alfa",
"module": "steg.py",
"symbol": "alfa",
"driver": {"module": "kjor.py", "scope": "run_project"},
"entry": {"kind": "module-main", "module": "kjor.py", "scope": "main"},
}
]
spec["held_out"] = [{"symbol": "beta", "reason": "hjelper inne i alfa, ikke et eget steg"}]
assert gate.score_toolbox(steps, src, spec, {}, tmp_path).n == 1, "kontroll: en ekte grunn"
spec["held_out"] = [{"symbol": "beta", "reason": " "}]
row = gate.score_toolbox(steps, src, spec, {}, tmp_path)
assert row.n == 2, "en tom grunn skal ikke kunne krympe nevneren"
assert any("beta" in x for x in row.exceptions), row.exceptions
def test_the_row_summary_counts_reasons_and_not_entries(tmp_path: Path) -> None:
"""Radens sammendrag sa «29 kall holdt utenfor med grunn» også når grunnen var tom."""
src, spec = _mini_run_path(tmp_path, extra_call=True)
spec["held_out"] = [{"symbol": "beta", "reason": ""}]
row = gate.score_toolbox([], src, spec, {}, tmp_path)
assert "0 kall holdt utenfor med grunn" in row.reason, row.reason
def test_every_held_out_entry_in_the_contract_carries_a_non_empty_reason() -> None:
held = list(_CONFIG["run_path"]["held_out"])
assert held
assert all(str(h.get("reason", "")).strip() for h in held), [
h["symbol"] for h in held if not str(h.get("reason", "")).strip()
]
def test_the_steps_outside_the_run_path_are_named_as_having_no_derived_source() -> None:
"""N7: et erklært steg UTENFOR kjørestien kan slettes stille — det har ingen kilde å lukke
mot. Fire av sytten er slike. De skal stå i radens egen tekst, ikke telles stille."""
row = gate.score_toolbox(_CONFIG["steps"], _SRC, _CONFIG["run_path"], {}, _REPO)
spec = _CONFIG["run_path"]
outside = [
str(s["id"])
for s in _CONFIG["steps"]
if (s["driver"]["module"], s["driver"]["scope"]) != (spec["module"], spec["scope"])
]
assert outside, "kontrakten har ingen steg utenfor kjørestien — da er denne armen foreldet"
for step_id in outside:
assert any(step_id in d and "uten utledet kilde" in d for d in row.diagnostics), (
step_id,
row.diagnostics,
)
def test_the_row_states_that_a_call_moved_into_a_helper_leaves_its_denominator() -> None:
"""N8: et po-kall flyttet én etasje ned, fra ``run_project`` til en hjelper den kaller, tar
nevneren 41 → 40. Gaten NAVNGIR at kallet er borte, men feller ikke — og grensen er radens
egen å uttale."""
row = gate.score_toolbox(_CONFIG["steps"], _SRC, _CONFIG["run_path"], {}, _REPO)
assert any("hjelper" in a for a in row.attests), row.attests
# --- rad 3: veiene som fortsatt sto åpne, og grenseerklæringen som var usann -------------------
#: PMs seks MÅLTE omgåelser av aldri-Claude-vakten, base64 av samme grunn som mønstrene: tests/
#: er selv en del av flaten raden skanner, og en klartekst-variant her ville vært sitt eget funn.
_MEASURED_ESCAPES = (
("sdk-anthropic", "aW1wb3J0IGFudGhyb3BpYw=="),
("sdk-anthropic-from", "ZnJvbSBhbnRocm9waWMgaW1wb3J0IEFudGhyb3BpYw=="),
("node-runner", "bnB4IEBhbnRocm9waWMtYWkvY2xhdWRlLWNvZGUgLXAgImFuYWx5c2VyIg=="),
(
"node-runner-argv",
"c3VicHJvY2Vzcy5ydW4oWyJucHgiLCAiQGFudGhyb3BpYy1haS9jbGF1ZGUtY29kZSIsICItcCIsICJ4Il0p",
),
("uv-runner", "dXZ4IGNsYXVkZS1jb2RlIC1wICJ4Ig=="),
("dynamisk-import", "X19pbXBvcnRfXygiY2xhdWRlX2FnZW50X3NkayIp"),
)
def test_every_way_the_checkpoint_measured_as_open_and_cheap_to_close_is_caught(
tmp_path: Path,
) -> None:
"""De seks formene PM plantet og målte som USETTE 19.09: den offisielle Python-SDK-en (to
skriveformer), node-kjøreren (to former), uv-kjøreren og et dynamisk import-kall. Hver
plantes én om gangen, med rc-0-kontroll først og etter.
Formene STÅR IKKE skrevet her, bare base64-kodet — denne fila er selv en del av flaten raden
skanner, og en klartekst-variant ville vært sitt eget funn. Målt: den var det, i første
utkast av denne docstringen, og vakten fant den."""
cfg = json.loads(json.dumps(_CONFIG["no_claude_path"]))
cfg["manifest"] = {"sentinel": "src/run.py", "sentinels": ["src/run.py"]}
_write(tmp_path / "src" / "run.py", "x = 1\n")
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN, "kontroll: ren flate"
for name, snippet in _MEASURED_ESCAPES:
planted = tmp_path / "src" / f"{name}.py"
_write(planted, gate.decode(snippet) + "\n")
row = gate.score_no_claude_path(cfg, tmp_path)
assert row.status == gate.RED, name
assert any(name in x for x in row.exceptions), (name, row.exceptions)
planted.unlink()
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN
def test_the_row_states_the_ways_that_measurably_remain_and_no_longer_claims_two() -> None:
"""Radens egen grenseerklæring oppga NØYAKTIG TO veier igjen; målt sto minst SEKS. De fire
billige er lukket over; de tre som står skal stå NAVNGITT — og «to veier» skal være borte."""
limit = gate.NO_CLAUDE_LIMIT.casefold()
assert "to veier står igjen" not in limit
assert "base64" in limit
assert "miljøvariabel" in limit
assert "satt sammen" in limit
def test_the_row_says_its_ratio_is_not_a_coverage_measure() -> None:
"""N11: k av n kan polstres med en vakt som bare treffer sin egen kjent-positive. Tallet er
et mål på at hver vakt MÅLER, aldri på hvor mye av angrepsflaten som er dekket."""
assert "dekningsmål" in gate.NO_CLAUDE_LIMIT
def test_a_file_that_is_not_utf8_is_still_scanned_for_a_command(tmp_path: Path) -> None:
"""N9: ``\\xff\\xfe`` + kommandoen ga GRØNN, og fila ble bare telt som «ulesbar». Et fravær
som er målt bort er ikke et fravær."""
cfg = json.loads(json.dumps(_CONFIG["no_claude_path"]))
cfg["manifest"] = {"sentinel": "src/run.py", "sentinels": ["src/run.py"]}
_write(tmp_path / "src" / "run.py", "x = 1\n")
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN, "kontroll: ren flate"
spec = next(s for s in cfg["patterns"] if s["id"] == "prosess")
payload = b"\xff\xfe" + gate.decode(spec["known_positive_b64"]).encode("utf-8") + b"\n"
(tmp_path / "src" / "skjult.bin").write_bytes(payload)
row = gate.score_no_claude_path(cfg, tmp_path)
assert row.status == gate.RED, row.reason
assert any("skjult.bin" in x for x in row.exceptions), row.exceptions
def test_a_symlink_pointing_out_of_the_tree_is_refused(tmp_path: Path) -> None:
"""N10b: symlenker filtreres bort. Peker lenka INN i treet skannes målet selv; peker den UT,
bar den en kommando usett."""
cfg = json.loads(json.dumps(_CONFIG["no_claude_path"]))
cfg["manifest"] = {"sentinel": "src/run.py", "sentinels": ["src/run.py"]}
repo = tmp_path / "repo"
_write(repo / "src" / "run.py", "x = 1\n")
assert gate.score_no_claude_path(cfg, repo).status == gate.GREEN, "kontroll: ren flate"
spec = next(s for s in cfg["patterns"] if s["id"] == "prosess")
utenfor = tmp_path / "utenfor.py"
_write(utenfor, gate.decode(spec["known_positive_b64"]) + "\n")
(repo / "src" / "lenke.py").symlink_to(utenfor)
row = gate.score_no_claude_path(cfg, repo)
assert row.status != gate.GREEN, row.reason
assert any("lenke.py" in x for x in row.exceptions), row.exceptions
def test_a_pruned_manifest_is_not_measured_instead_of_green(tmp_path: Path) -> None:
"""N6: manifestet filtrert fra 512 til 451 filer (hele ``examples/``, ``spikes/``,
``contexts/`` og ``main.py``) ga fortsatt «9 av 9 GRØNN». Sentinel-vakten stoppet en TOM
flate, ikke en beskåret — én sentinel per område den beskjæringen tok."""
cfg = json.loads(json.dumps(_CONFIG["no_claude_path"]))
cfg["manifest"] = {
"sentinels": ["src/run.py", "main.py", "eksempler/en.md"],
"skip_dirs": [".git", "__pycache__"],
}
for rel in cfg["manifest"]["sentinels"]:
_write(tmp_path / rel, "x = 1\n")
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN, "kontroll: hel flate"
(tmp_path / "eksempler" / "en.md").unlink()
row = gate.score_no_claude_path(cfg, tmp_path)
assert row.status == gate.NOT_MEASURED, row.reason
assert any("eksempler/en.md" in x for x in row.exceptions), row.exceptions
def test_the_contract_plants_a_sentinel_in_every_area_the_handlist_missed() -> None:
"""De 69 sporede filene utenfor den gamle håndlista lå i fire områder. Hvert av dem bærer nå
sin egen sentinel, så en beskåret flate er IKKE MÅLT og ikke grønn."""
sentinels = list(_CONFIG["no_claude_path"]["manifest"].get("sentinels", ()))
assert sentinels, "kontrakten har ingen sentinel-liste — da måler en beskåret flate grønt"
areas = {s.split("/")[0] for s in sentinels}
assert {"main.py", "examples", "spikes", "contexts", "src"} <= areas, sorted(areas)
for rel in sentinels:
assert (_REPO / rel).is_file(), rel
# --- rad 6: en kjørebok må ha et innhold kontrakten navngir ------------------------------------
def test_a_runbook_without_the_sections_the_contract_names_is_not_green(tmp_path: Path) -> None:
"""N3: en kjørebok hvis hele innhold er «x», med en korrekt sjekksummet attestering, ga
«2 av 2 GRØNN». Tom fil var alt som var avvist."""
cfg = _CONFIG["runbook"]
sections = list(cfg.get("sections", ()))
assert sections, "kontrakten navngir ingen seksjoner — da er «x» en kjørebok"
text = "# kjørebok\n\n" + "\n".join(f"## {s}\n\nnoe\n" for s in sections)
_write(tmp_path / cfg["path"], text)
digest = hashlib.sha256(text.encode("utf-8")).hexdigest()
_attestation_lines(tmp_path, digest)
row = gate.score_runbook(cfg, tmp_path, now=_NOW)
assert (row.k, row.n, row.status) == (2, 2, gate.GREEN), row.exceptions
_write(tmp_path / cfg["path"], "x\n")
digest = hashlib.sha256(b"x\n").hexdigest()
_attestation_lines(tmp_path, digest)
row = gate.score_runbook(cfg, tmp_path, now=_NOW)
assert row.status == gate.NOT_MEASURED, row.exceptions
assert any("seksjon" in x for x in row.exceptions), row.exceptions
# --- rad 1, TREDJE reparasjon: bindingen måler UTFØRELSE, ikke tekst --------------------------
#
# Sjekkpunktet 19.09 (`a37e429`) MÅLTE at rad 1 kunne bli 17 av 17 med 17 énlinjes-prober og en
# dørmodul uten én eneste import: «proben rører døren» var en tekstsjekk ett hakk lenger inne.
# Dommerens seks probeformer + oppskriften står her, hver som sin egen arm, og hver skal gi 0.
def _write_raw_probe(root: Path, body: str, nodeid: str = _FAKE_PROBE) -> str:
"""En probe skrevet ORDRETT — de uærlige formene kan ikke uttrykkes gjennom ``_write_probe``."""
file_part, _, name = nodeid.partition("::")
_write(root / file_part, body.replace("<navn>", name))
return nodeid
#: Dommerens sju former, verbatim slik de ble målt: seks som BRAST mot forrige utgave, pluss
#: oppskriften «17 énlinjes-prober + dørmodul uten imports» i sin minste form. Døren er
#: ``fakesrc.driver``, steget ``gjoer_noe`` — nøyaktig dem ``_one_step`` erklærer.
_JUKSEFORMER: tuple[tuple[str, str], ...] = (
(
"a1-navn-i-ubrukt-variabel",
"def <navn>(tmp_path):\n"
' door = "fakesrc.driver"\n'
' steg = "gjoer_noe"\n'
" assert isinstance(door, str) and isinstance(steg, str)\n",
),
(
"a2-importert-aldri-kalt",
"from fakesrc import driver\n\n\n"
"def <navn>(tmp_path):\n"
" assert driver is not None\n"
' assert "gjoer_noe"\n',
),
(
"b1-kallet-i-doed-gren",
"import subprocess\nimport sys\n\n\n"
"def <navn>(tmp_path):\n"
" if False:\n"
' subprocess.run([sys.executable, "-m", "fakesrc.driver", "--steg", "gjoer_noe"])\n'
" assert True\n",
),
(
"b2-kallet-etter-return",
"import subprocess\nimport sys\n\n\n"
"def <navn>(tmp_path):\n"
' assert "gjoer_noe"\n'
" return None\n"
' subprocess.run([sys.executable, "-m", "fakesrc.driver", "--steg", "gjoer_noe"])\n',
),
(
"c1-resultatet-forkastet",
"import subprocess\nimport sys\n\n\n"
"def <navn>(tmp_path):\n"
' subprocess.run([sys.executable, "-m", "fakesrc.driver", "--steg", "gjoer_noe"])\n'
" assert 2 + 2 == 4\n",
),
(
"c2-bare-skrevet-ut",
'def <navn>(tmp_path):\n print("fakesrc.driver", "gjoer_noe")\n assert True\n',
),
(
"oppskriften-enlinjes",
'def <navn>(tmp_path):\n assert len("fakesrc.driver") and len("gjoer_noe")\n',
),
)
@pytest.mark.parametrize(("form", "body"), _JUKSEFORMER, ids=[n for n, _ in _JUKSEFORMER])
def test_none_of_the_judges_seven_forms_is_a_behaviour_probe(
tmp_path: Path, form: str, body: str
) -> None:
"""Hver form plantes ALENE, med rc-0-kontrollen først: den ærlige proben teller, formen ikke.
Uten kontrollen ville armen bestått mot en gate som avviste ALT — «0 av 1» er et
måleresultat bare når 1 av 1 er oppnåelig i samme oppsett."""
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path)
kontroll = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (kontroll.k, kontroll.n) == (1, 1), kontroll.exceptions
_write_raw_probe(tmp_path, body)
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1), (form, row.exceptions)
assert any("atferdsprobe" in x for x in row.exceptions), (form, row.exceptions)
def test_a_probe_that_runs_the_door_and_throws_the_result_away_proves_nothing(
tmp_path: Path,
) -> None:
"""Dommerens c1, med sin EGEN grunn: kallet skjedde, men ingen assert leser det det ga.
Skilles fra «rører ikke døren», for det er to ulike feil og bare den ene er en løgn."""
src = _fake_src(tmp_path, chat_client=False)
_write_raw_probe(tmp_path, dict(_JUKSEFORMER)["c1-resultatet-forkastet"])
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert row.k == 0
assert any("asserter ikke på det døren" in x for x in row.exceptions), row.exceptions
def test_a_probe_that_only_names_the_door_never_reaches_the_execution_rule(
tmp_path: Path,
) -> None:
"""Dommerens a1: navnet står i kilden, men ingen prosess starter. Grunnen skal være at døren
ikke RØRES — ikke at asserten er feil, for da ville en assert-fiks «løst» det."""
src = _fake_src(tmp_path, chat_client=False)
_write_raw_probe(tmp_path, dict(_JUKSEFORMER)["a1-navn-i-ubrukt-variabel"])
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert any("rører ikke døren" in x for x in row.exceptions), row.exceptions
def test_an_honest_probe_that_starts_the_door_through_a_helper_still_counts(
tmp_path: Path,
) -> None:
"""Den ÆRLIGE formen suiten faktisk bruker (``test_v1_gate._cli``): subprosessen startes i en
hjelper, og testen asserter på det hjelperen ga tilbake. En regel som feller den, feller
kapabilitet — som er den motsatte feilen av den vi retter."""
src = _fake_src(tmp_path, chat_client=False)
_write_raw_probe(
tmp_path,
"import subprocess\nimport sys\n\n\n"
"def _cli(*args):\n"
" return subprocess.run(\n"
' [sys.executable, "-m", "fakesrc.driver", *args], capture_output=True, text=True\n'
" )\n\n\n"
"def <navn>(tmp_path):\n"
' proc = _cli("--steg", "gjoer_noe")\n'
" assert proc.returncode == 0\n",
)
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (1, 1), row.exceptions
def test_a_probe_that_builds_the_command_in_a_variable_first_still_counts(
tmp_path: Path,
) -> None:
"""``round_builder``-probens form: ``base = [sys.executable, "-m", "<modul>"]`` og
``subprocess.run([*base, …])``. Strengen når kallet gjennom en variabel; det er en
utførelse."""
src = _fake_src(tmp_path, chat_client=False)
_write_raw_probe(
tmp_path,
"import subprocess\nimport sys\n\n\n"
"def <navn>(tmp_path):\n"
' base = [sys.executable, "-m", "fakesrc.driver"]\n'
' ok = subprocess.run([*base, "--steg", "gjoer_noe"], capture_output=True, text=True)\n'
" assert ok.returncode == 0, ok.stderr\n",
)
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (1, 1), row.exceptions
def test_the_step_name_must_stand_in_what_was_actually_executed(tmp_path: Path) -> None:
"""Navngivningen flyttes fra «et hvilket som helst kall-argument» til DEN kommandolinja som
ble kjørt. To steg bak samme dør, samme kommando — ordet som skiller dem må være i argv."""
src = _two_step_src(tmp_path)
a = _write_raw_probe(
tmp_path,
"import subprocess\nimport sys\n\n\n"
"def <navn>(tmp_path):\n"
" proc = subprocess.run(\n"
' [sys.executable, "-m", "fakesrc.driver", "--steg", "gjoer_noe"],\n'
" capture_output=True,\n"
" )\n"
" assert proc.returncode == 0\n",
nodeid="tests/test_a.py::test_a",
)
b = _write_raw_probe(
tmp_path,
"import subprocess\nimport sys\n\n\n"
"def <navn>(tmp_path):\n"
" proc = subprocess.run(\n"
' [sys.executable, "-m", "fakesrc.driver"], capture_output=True\n'
" )\n"
' hjelp("gjoer_noe_annet")\n'
" assert proc.returncode == 0\n",
nodeid="tests/test_b.py::test_b",
)
row = gate.score_toolbox(
_two_steps(a, b), src, _fake_run_path(), {a: "passed", b: "passed"}, tmp_path
)
assert (row.k, row.n) == (1, 2), row.exceptions
assert any("navngir ikke steget" in x for x in row.exceptions), row.exceptions
def test_the_sole_step_behind_a_door_is_proved_by_driving_that_door(tmp_path: Path) -> None:
"""KLASSE-rettingen av 3 → 0: navngivningen er en DISKRIMINATOR mellom steg som deler dør.
Er steget alene bak sin dør, er det å kjøre døren å kjøre steget — og en ekte ende-til-ende
dørprobe skal ikke avvises på en navneteknikalitet (målt 19.09 på ``gate``-proben)."""
src = _fake_src(tmp_path, chat_client=False)
_write_probe(tmp_path, needle="et_helt_annet_ord")
row = gate.score_toolbox(_one_step(), src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (1, 1), row.exceptions
# ... og den samme proben beviser INGEN av to steg som deler døren.
delt = _write_probe(tmp_path, needle="et_helt_annet_ord", nodeid="tests/test_x.py::test_x")
annen = _write_probe(tmp_path, needle="et_helt_annet_ord", nodeid="tests/test_y.py::test_y")
row = gate.score_toolbox(
_two_steps(delt, annen),
_two_step_src(tmp_path),
_fake_run_path(),
{delt: "passed", annen: "passed"},
tmp_path,
)
assert row.k == 0, row.exceptions
assert all("navngir ikke steget" in x for x in row.exceptions), row.exceptions
def test_the_gates_own_gate_probe_binds_after_the_class_fix() -> None:
"""Det ene steget som SKULLE telle før og ikke gjorde det: ``gate`` kjører v1-gaten som
subprosess og leser JSON-en ut av den, og er ALENE bak sin dør — talt her, ikke antatt.
Målt gjennom raden, ikke gjennom en hjelper: det er raden som er påstanden."""
doer = [
(s["entry"]["module"], s["entry"].get("scope", "main"), s["entry"].get("command", ""))
for s in _CONFIG["steps"]
]
gate_step = next(s for s in _CONFIG["steps"] if s["id"] == "gate")
noekkel = (
gate_step["entry"]["module"],
gate_step["entry"].get("scope", "main"),
gate_step["entry"].get("command", ""),
)
assert doer.count(noekkel) == 1, "armen forutsetter at gate er alene bak sin dør"
row = gate.score_toolbox(
_CONFIG["steps"], _SRC, _CONFIG["run_path"], _all_probes_passed(), _REPO
)
assert not any(x.startswith("gate:") for x in row.exceptions), row.exceptions
def _all_probes_passed() -> dict[str, str]:
"""Hver nodeid kontrakten navngir, som «passed» — utfallet er IKKE det som måles her."""
return {nodeid: "passed" for nodeid in gate.probe_nodeids(_CONFIG)}
def test_the_door_rule_says_that_it_measures_an_execution_and_states_its_limit() -> None:
"""A8-klassen: regelen skal si nøyaktig hva koden MÅLER, og hva den ikke kan se."""
rule = gate.EXTERNAL_DOOR.casefold()
assert "utførelse" in rule
assert "dataavhengig" in rule
assert "alene bak" in rule
# Grensen dommeren navnga som den eneste formen som ikke kan skrives forbi.
assert "muter" in rule or "mutant" in rule
# --- rad 1: en grunn skal være NAVNGITT prosa, ikke bare ikke-tom -----------------------------
@pytest.mark.parametrize("plassholder", ["-", "todo", "x", ".", "??", "n/a"])
def test_a_placeholder_is_not_a_named_reason(tmp_path: Path, plassholder: str) -> None:
"""Sjekkpunktet målte at «-», «todo», «x» og «.» alle ble godtatt som grunn: ``.strip()``
skilte tom fra ikke-tom, ikke grunn fra ikke-grunn."""
src, spec = _mini_run_path(tmp_path, extra_call=True)
spec["held_out"] = [{"symbol": "beta", "reason": "hjelper inne i alfa, ikke et eget steg"}]
steps = [
{
"id": "alfa",
"label": "alfa",
"module": "steg.py",
"symbol": "alfa",
"driver": {"module": "kjor.py", "scope": "run_project"},
"entry": {"kind": "module-main", "module": "kjor.py", "scope": "main"},
}
]
assert gate.score_toolbox(steps, src, spec, {}, tmp_path).n == 1, "kontroll: ekte prosa holder"
spec["held_out"] = [{"symbol": "beta", "reason": plassholder}]
row = gate.score_toolbox(steps, src, spec, {}, tmp_path)
assert row.n == 2, f"{plassholder!r} er ingen grunn — symbolet blir i nevneren"
assert any("UTEN grunn" in x for x in row.exceptions), row.exceptions
def test_every_held_out_reason_in_the_contract_is_named_prose() -> None:
"""Terskelen måles mot kontraktens egne 28 grunner, gjennom RADEN: strammes den så den
feller ekte prosa, vokser nevneren og denne armen blir rød. Tallet 28 er talt her."""
grunner = [str(h["reason"]) for h in _CONFIG["run_path"]["held_out"]]
assert len(grunner) == 28
assert min(len(g) for g in grunner) >= 30, "margin mot terskelen, målt"
row = gate.score_toolbox(_CONFIG["steps"], _SRC, _CONFIG["run_path"], {}, _REPO)
assert row.n == _STEPS_TODAY, "en ekte grunn skal ikke falle ut som plassholder"
assert sum(1 for d in row.diagnostics if d.startswith("holdt utenfor: ")) >= len(grunner)
assert not any("UTEN GRUNN" in d for d in row.diagnostics), row.diagnostics
def test_the_row_limit_says_the_off_path_steps_have_no_derived_denominator() -> None:
"""N7, uttalt: de fire stegene utenfor kjørestien har ingen utledet kilde, og et slettet
off-path-steg tar derfor nevneren 17 → 16. Gaten kan ikke felle det; suiten kan."""
assert "utenfor kjørestien" in gate.RUN_PATH_LIMIT
assert "suiten" in gate.RUN_PATH_LIMIT
#: De fire stegene som er erklært UTENFOR kjørestien, talt for hånd i kontrakten 20.09.2026.
#: Dette er N7s eneste vakt: sletter noen et av dem, krymper nevneren stille i GATEN — her blir
#: det rødt, og navnet står igjen i suiten.
_OFF_PATH_TODAY: tuple[tuple[str, str, str], ...] = (
("gate", "evals/v1_gate.py", "main"),
("rapport", "evals/round_builder.py", "build_round"),
("rundebinding", "evals/round_builder.py", "main"),
("validering", "run.py", "evaluate_mandate_candidates"),
)
def test_no_off_path_step_can_be_deleted_without_this_arm_going_red() -> None:
driver = (str(_CONFIG["run_path"]["module"]), str(_CONFIG["run_path"]["scope"]))
funnet = tuple(
sorted(
(str(s["id"]), str(s["driver"]["module"]), str(s["driver"]["scope"]))
for s in _CONFIG["steps"]
if (str(s["driver"]["module"]), str(s["driver"]["scope"])) != driver
)
)
assert funnet == _OFF_PATH_TODAY
# --- rad 1: en underkommando er bare en dør når modulen selv er kallbar utenfra ---------------
def test_a_subcommand_is_only_a_door_when_its_module_is_reachable_from_outside(
tmp_path: Path,
) -> None:
"""En ``add_parser("x")`` i en modul ingen kan starte er ingen dør: underkommandoen er et
navn inne i en CLI, og CLI-en selv må være registrert (konsoll-skript eller ``-m``)."""
src = tmp_path / "fakesrc"
_write(src / "steg.py", "def gjoer_noe():\n return 42\n")
_write(
src / "verktoey.py",
"import argparse\n\nfrom fakesrc.steg import gjoer_noe\n\n\n"
"def main(argv=None):\n"
" parser = argparse.ArgumentParser()\n"
' sub = parser.add_subparsers(dest="kommando")\n'
' sub.add_parser("naviger-pakke")\n'
" args = parser.parse_args(argv)\n"
' if args.kommando == "naviger-pakke":\n'
" return gjoer_noe()\n"
" return 2\n",
)
entry = {
"kind": "subcommand",
"module": "verktoey.py",
"scope": "main",
"command": "naviger-pakke",
}
_fake_pyproject(tmp_path, {})
ok, why = gate.registered_entry(src, tmp_path, "fakesrc", entry)
assert ok is False and ("pyproject" in why or "__main__" in why), why
_fake_pyproject(tmp_path, {"fake-verktoey": "fakesrc.verktoey:main"})
assert gate.registered_entry(src, tmp_path, "fakesrc", entry) == (True, "")
# --- rad 3: de fem veiene sjekkpunktet målte som åpne OG billige å lukke ----------------------
#: Hver form er base64 av nøyaktig det som ble plantet. Klartekst her ville vært radens eget funn.
_MAALTE_AAPNE_VEIER = (
("dynamisk-import-modul", "aW1wb3J0bGliLmltcG9ydF9tb2R1bGUoImNsYXVkZV9hZ2VudF9zZGsiKQ=="),
("dynamisk-import-modul-anthropic", "aW1wb3J0bGliLmltcG9ydF9tb2R1bGUoImFudGhyb3BpYyIp"),
("node-runner-deno", "ZGVubyBydW4gLUEgbnBtOkBhbnRocm9waWMtYWkvY2xhdWRlLWNvZGUgLXAgIngi"),
("node-runner-npm-exec", "bnBtIGV4ZWMgQGFudGhyb3BpYy1haS9jbGF1ZGUtY29kZSAtLSAtcCAieCI="),
("node-runner-yarn-dlx", "eWFybiBkbHggQGFudGhyb3BpYy1haS9jbGF1ZGUtY29kZSAtcCAieCI="),
(
"sdk-ts-import",
"aW1wb3J0IHsgcXVlcnkgfSBmcm9tICJAYW50aHJvcGljLWFpL2NsYXVkZS1hZ2VudC1zZGsiOw==",
),
)
@pytest.mark.parametrize(
("form", "snippet"), _MAALTE_AAPNE_VEIER, ids=[n for n, _ in _MAALTE_AAPNE_VEIER]
)
def test_every_form_the_checkpoint_measured_as_slipping_through_is_now_caught(
tmp_path: Path, form: str, snippet: str
) -> None:
"""Tolv indirekte former slapp 19.09; fem av dem var verken eksotiske eller uoppregnelige.
Hver plantes alene, med rc-0-kontroll før og etter."""
cfg = json.loads(json.dumps(_CONFIG["no_claude_path"]))
cfg["manifest"] = {"sentinel": "src/run.py", "sentinels": ["src/run.py"]}
_write(tmp_path / "src" / "run.py", "x = 1\n")
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN, "kontroll: ren flate"
planted = tmp_path / "src" / "plantet.ts"
_write(planted, gate.decode(snippet) + "\n")
row = gate.score_no_claude_path(cfg, tmp_path)
assert row.status == gate.RED, (form, row.exceptions)
planted.unlink()
assert gate.score_no_claude_path(cfg, tmp_path).status == gate.GREEN
def test_the_row_limit_is_a_class_description_and_no_longer_an_enumeration() -> None:
"""Tredje runde med samme mønster: «NØYAKTIG TO veier» → «TRE veier», begge falsifisert av
den første målingen som ble gjort. Setningen skal si hva vakten ER og hva den ikke ser —
aldri hvor mange veier som står igjen."""
limit = gate.NO_CLAUDE_LIMIT.casefold()
assert "to veier står igjen" not in limit
assert "tre veier står igjen" not in limit
assert "tekstmønstre" in limit or "tekstvakt" in limit
assert "uttømmende" in limit
assert "git-manifestet" in limit
def test_a_subcommand_door_is_only_driven_when_the_command_stands_in_argv(
tmp_path: Path,
) -> None:
"""For en underkommando ER kommandonavnet døren. En probe som starter CLI-en uten det har
kjørt en annen dør — eller ingen. Uten denne armen ville kravet kunne fjernes uten at noe
ble rødt: verktøykassens egne prober har alle navnet i argv."""
src = _fake_src(tmp_path, chat_client=False)
_write(
src / "verktoey.py",
"import argparse\n\nfrom fakesrc.steg import gjoer_noe\n\n\n"
"def main(argv=None):\n"
" parser = argparse.ArgumentParser()\n"
' sub = parser.add_subparsers(dest="kommando", required=True)\n'
' sub.add_parser("naviger-pakke")\n'
" parser.parse_args(argv)\n"
" return gjoer_noe()\n\n\n"
'if __name__ == "__main__":\n raise SystemExit(main())\n',
)
steg = _one_step()
steg[0]["entry"] = {
"kind": "subcommand",
"module": "verktoey.py",
"scope": "main",
"command": "naviger-pakke",
}
_write_probe(tmp_path, door="fakesrc.verktoey", needle="naviger-pakke")
row = gate.score_toolbox(steg, src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (1, 1), row.exceptions
_write_probe(tmp_path, door="fakesrc.verktoey", needle="gjoer_noe")
row = gate.score_toolbox(steg, src, _fake_run_path(), _FAKE_PASSED, tmp_path)
assert (row.k, row.n) == (0, 1), row.exceptions
assert any("underkommandoen" in x for x in row.exceptions), row.exceptions