feat(p21): a declaration that must have LOOKED, and a refusal that names the neighbours

C1. Round 4 produced 13 declarations over six runs and NOT ONE named a fasit concept.
The distinct documents opened before each were 1,1,1,1,1,1,1,2,5,5,6,13,13: seven
declared the base's FIRST requirement after opening exactly ONE document.

The order offered two rules and asked which discriminates. Replayed against the real
listings: "the declared document must have come back from a read_dir filtered on a word
from the approach's label" refuses 13 of 13 -- including Soraasen's 12.11, the closest
any run came -- because ZERO of the 13 were reached through a filtered listing at all.
A gate that refuses every measured case, right and wrong alike, cannot discriminate.
"fewer than k distinct documents opened" at k=3 refuses 8 of 13 and keeps the five that
navigated. k=3, 4 and 5 refuse the SAME eight -- the distribution has a gap between 2
and 5 -- so the threshold is not on a cliff, and 3 is the lowest of that plateau.
DISTINCT paths, not calls, and capped by the base's own size so a small base stays
declarable.

C2. Over the same traces 18 of 143 path-bearing calls named a path the base does not
hold, ELEVEN of them one run walking R761/4-3, 4.3, 4-2, 4-1, 4-0, 4-5, 4-6 while the
real names are R761/4, R761/41, R761/42. The refusal already named the nearest listable
ancestor; now it also names up to five of that rung's own subdirectories, ranked by
longest common prefix with the segment that failed. ONE copy shared by both refusal
sites, built from context_files through in_dimension, so every name handed back resolves
and the verdict layer can never be advertised in an apology. MEASURED after: 16 of 18.

Load-bearing MEASURED, four mutations all red against the WHOLE suite, green control
1863/5, golden byte-unchanged: C3(i) the declaration gate detached (2 red) . C3(ii) the
neighbour list empty (6) . C3(iii) built from files (1, the verdict arm alone) . C3(iv)
count CALLS instead of distinct documents (1, the repetition arm alone).

Three existing arms REWRITTEN, not weakened: all three read one document and declared,
which is the measured failure class exactly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-15 11:38:57 +02:00
commit ac0bfdba27
8 changed files with 534 additions and 28 deletions

View file

@ -110,13 +110,24 @@ def test_a_requirement_the_run_never_opened_is_refused_and_recorded_nowhere() ->
def test_the_correction_is_to_read_it_and_then_it_is_accepted() -> None:
"""(b) The refusal is a turn the model can correct — the half that makes (a) a gate."""
"""(b) The refusal is a turn the model can correct — the half that makes (a) a gate.
P21/C1 added a SECOND precondition the run must have opened at least three distinct
documents (capped by the base's own size) — so the correction is now "read it, and read enough
of the base to have looked". The arm keeps its meaning: a declaration the run's own trace
supports is ACCEPTED and RECORDED.
"""
tools, opened, declared = _wired()
path = _a_concept()
from portfolio_optimiser import okf
files = [f.name for f in okf.navigate_bundle(str(_TUNNEL)).context_files]
path = files[0]
body = tools["read_file"].func(bundle_id="tunnel-hauglia", path=path)
assert not body.startswith("REFUSED"), body[:120]
# The recorder is middleware in a real run; here the trace is appended directly, which is the
# SAME list the tool reads.
for other in files[1:3]:
opened.append(ToolCall(name="read_file", bundle_id="tunnel-hauglia", path=other))
opened.append(ToolCall(name="read_file", bundle_id="tunnel-hauglia", path=path))
answer = tools["declare_requirement"].func(
bundle_id="tunnel-hauglia", path=path, ref="Krav 12.1"