test(b-gate): the pin moves 8 -> 15, and names the two steps that still share a door

`_EXTERNAL_TODAY` and `_WITH_A_DOOR_TODAY` are the arm's own count, not the gate's, so
the seven new doors have to be written down here before the suite agrees they exist. The
two assertions that pinned `kjørekonfig`/`utboks`/`prepass-artefakt`/`parse-feil` as
door-LESS are inverted rather than deleted: they were the arm's discriminator, and a
door that silently went away must still turn this red.

The manifest count moves 514 -> 515 for the one new probe file.

Also a probe for the shape guard: the writers take `Mapping`/`Sequence` and would
serialize whatever they were handed, so a list where an object belongs would become a
valid file with the wrong shape and the run that reads it later would be the one to
fail. The door refuses it as a 3 (the call parsed, so 2 is the wrong code) and leaves no
directory behind. Carries its rc-0 control.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-20 10:48:16 +02:00
commit c5aa5fcfde
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
2 changed files with 48 additions and 5 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 = 8
_EXTERNAL_TODAY = 15
_ROLES_TODAY = ("proposer", "checker")
_PATTERNS_TODAY = 15
@ -111,12 +111,19 @@ def test_the_step_denominator_equals_an_independent_count_of_the_source() -> Non
#: 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 = (
"coverage",
"debatt-verktøy",
"dom",
"forslagsvurderinger",
"gate",
"kjørekonfig",
"kontekst",
"kostnadsgrunnlag",
"pakke",
"parse-feil",
"prepass",
"prepass-artefakt",
"utboks",
"validering",
"verdict-id",
)
@ -126,7 +133,12 @@ def test_row1_today_is_red_and_names_exactly_the_steps_that_have_a_door() -> Non
"""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."""
(eller en probe som slutter å drive sin dør) blir rød her og ikke bare et annet tall.
20.09: 15 av 17 da de sju utboks-skriverne fikk hver sin underkommando. De TO som står igjen
er de to som deler `round_builder`-døren uten at kommandolinja kan skille dem gaten krever
at argv NAVNGIR steget når mer enn ett steg står bak samme dør, og den CLI-en har ingen
underkommando å navngi dem med."""
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)
@ -134,8 +146,8 @@ 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 "kjørekonfig" in uten_doer and "utboks" in uten_doer
assert "prepass-artefakt" in uten_doer and "parse-feil" in uten_doer
assert "kjørekonfig" not in uten_doer and "utboks" not in uten_doer
assert "prepass-artefakt" not in uten_doer and "parse-feil" not in uten_doer
bound = {x.split(":")[0] for x in row.exceptions if "atferdsprobe" in x}
assert bound == {"rundebinding", "rapport"}, row.exceptions
@ -589,7 +601,7 @@ _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
_PUBLISHED_TODAY = 515
_UNDECODABLE_TODAY = 1

View file

@ -391,3 +391,34 @@ def test_write_debate_tools_from_outside_writes_an_empty_trace_as_a_statement(
assert len(paa_disk["tool_calls"]) == len(kall)
assert len(paa_disk["requirements"]) == len(krav)
assert paa_disk["tool_calls"][1]["arguments"]["query"] == "varme"
# --- formvakten -------------------------------------------------------------------------------
def test_a_payload_of_the_wrong_shape_is_refused_rather_than_written(tmp_path: Path) -> None:
"""Skriverne tar `Mapping`/`Sequence` og ville serialisert hva som helst de fikk: en liste der
et objekt hører hjemme blir en gyldig fil med feil form, og kjøringen som leser den SENERE er
den som feiler. Døren feller formen med en gang, og gjør det som en avvisning (3) kallet
parset, 2 ville vært feil kode."""
ut = tmp_path / "ut"
feil = _json_arg(tmp_path / "feil.json", ["ikke", "et", "objekt"])
proc = _toolbox(
"write-proposal-reviews", "--outbox-dir", str(ut), "--run-id", _RUN, "--payload", feil
)
assert proc.returncode == 3, proc.stdout
assert json.loads(proc.stdout)["error"]["kind"] == "ValueError"
assert not ut.exists(), "en avvist form skal ikke ha lagt igjen en katalog eller en fil"
# rc-0-kontroll: SAMME dør, samme sti, riktig form. Uten den ville armen vært grønn mot en
# dør som avviste alt.
ok = _toolbox(
"write-proposal-reviews",
"--outbox-dir",
str(ut),
"--run-id",
_RUN,
"--payload",
_json_arg(tmp_path / "rett.json", {"reviews": []}),
)
assert ok.returncode == 0, ok.stderr
assert Path(json.loads(ok.stdout)["path"]).is_file()