test(b-gate): the contract binds the three judgement steps, and the pin moves 5 -> 8

The entries for validering / verdict-id / dom were console-script pointers at run.py::main, which
the gate itself refused with a named reason: the way from that main() requires a chat client.
They now point at the toolbox subcommand that reaches each symbol, with the probe that drives it.

Measured, same denominator both ways, no other row moved:
  row 1  5 av 17  ->  8 av 17   (RED both ways)
  row 2  0/2 · row 3  15/15 GREEN over 514 published files · row 4  0/3 · row 5  4/5 · row 6 NOT
  MEASURED -- unchanged, exit 1 unchanged.

_EXTERNAL_TODAY follows the measurement, and _WITH_A_DOOR_TODAY names WHICH eight, so a door that
moves without being built shows up as a red test rather than as a different number. The arm that
asserted "validering has no door" had to pick a step that still does not: kjorekonfig.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-20 10:08:48 +02:00
commit 10cef82f7b
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
2 changed files with 39 additions and 19 deletions

View file

@ -44,7 +44,7 @@ _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
_EXTERNAL_TODAY = 8
_ROLES_TODAY = ("proposer", "checker")
_PATTERNS_TODAY = 15
@ -106,14 +106,25 @@ def test_the_step_denominator_equals_an_independent_count_of_the_source() -> Non
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")
#: Stegene som HAR en dør ut 20.09.2026, skrevet ut. Sju av dem er verktøykassens under-
#: kommandoer — fire fra steg 2 i byggerekkefølgen og de tre dommen fikk i steg 3; ``gate`` er
#: v1-gatens egen kommando, som alltid var en ekte dørprobe og ble avvist på en navne-
#: teknikalitet til klasse-rettingen samme dag.
_WITH_A_DOOR_TODAY = (
"dom",
"gate",
"kontekst",
"kostnadsgrunnlag",
"pakke",
"prepass",
"validering",
"verdict-id",
)
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.
"""Var «3 av 17» til 19.09, så 0 av 17 da proben ble BUNDET til steget, 5 av 17 da verktøy-
kassens fire første dører sto, og 8 av 17 da dommens tre kom gjennom den samme døren.
Armen teller ikke bare k den navngir HVILKE, 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", ())}
@ -123,7 +134,7 @@ def test_row1_today_is_red_and_names_exactly_the_steps_that_have_a_door() -> Non
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 "kjørekonfig" 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