Commit graph

2 commits

Author SHA1 Message Date
eb4137415c feat(prepass,explore): padding dies at the prompt; a refusal the model can act on is a return value [skip-docs]
Order 20260908T195801Z. Findings 4 and 5 from the S7 acid test, then the two things
finding 99 measured and deliberately did not fix (D3, D2).

No user-facing surface changes: no new flag, no new command, no changed output
contract. Both seams are internal (the pre-pass rendering, and the shape a tool
answers a model with), so [skip-docs] rather than a README edit that would describe
nothing an operator can do differently.

FINDING 4 -- MEASURED, NOTHING BUILT. K2's price schedule IS readable without
guessing (8 column spans, 71 of 91 non-blank rows give >= 2 cells, the split stable
for K = 2..64). But 0 of 92 rows name all three of code/quantity/unit_cost -- also
under a looser substring match -- and 0 of 91 data rows carry code + quantity +
amount. The triple is not formatted away; it is not in the document. It is a price
SUMMARY plus nine rate cards whose unit-price columns are empty (pre-award). The
order's binding decision rule therefore falls against building:
--derive-cost-baseline keeps refusing, and MAJOR-4's own honesty limit holds.

FINDING 5 -- BUILT. Measured on the actual rendering path (concept_text, not the
raw file): the delivered excerpt is 104 lines / 67 245 chars, carrying 208 interior
whitespace runs, 117 of them >= 100 and the longest 887 -- 56 806 of 67 245
characters = 84.5 %, over 72 of 104 lines. collapse_padding, called from
_data_blocks (the one renderer both arms share, and therefore AFTER
verify_against_bundle -- collapsing in concept_text would break every payload's own
digest), gives -72.4 %: line count invariant, non-whitespace byte-identical, leading
indentation untouched, no number changed.

F99-D3 -- read_file / read_dir / read_bundle now RETURN their refusal. MAF turns a
tool raise into "Error: Function failed." (_tools.py:1410-1432, :1427) and counts it
against DEFAULT_MAX_CONSECUTIVE_ERRORS_PER_REQUEST = 3, so everything the refusing
arm knows is destroyed on the way out. The gates are unchanged; the property they
exist for -- the reason travels, the bytes never do -- is now asserted explicitly on
the returned value. The arm is keyed on named classes, never bare Exception, because
ExplorationError is itself a RuntimeError subclass.

F99-D2 -- the invariant row, plus one for finding 5 (a stated deviation from "one
row only": finding 5 is a separately built seam and the ledger's standing rule
requires its own row).

19 existing arms rewritten, never deleted and never weakened: where the class
carried a distinction, the refusal KIND carries it now.

13 mutations, all red against the whole suite (W1-W5, M1-M8), each restored from
scratchpad with shasum -c. Control 1543 passed / 5 skipped (from 1529/5, a strict
superset, 0 removed). Golden demo-transcript.stdout unchanged
(shasum -a 1 of the CONTENT = ea8c534773acdbe41ae68f2c55724d69aaf8be4f).

Measurement: docs/2026-09-08-funn-4-5-og-read-nekt.md

Co-Authored-By: Claude <Opus 5>
2026-09-08 23:36:54 +02:00
ab747bc7e8 fix(tools): read_file paa en KATALOG nektes ved navn og peker paa read_dir
Funn (c) fra oekt 94s levende K2-maaling (docs/2026-09-06-major2-levende-k2.md
§ 3/§ 4): en levende modell gikk stigen list_bundles -> read_bundle -> read_dir
-> read_file, naadde et nivaa med underkataloger (30-1, 30-7, 521-001 ...) og
kalte read_file paa en av dem. Tre slike kall i EN kjoering.

SJEKKET FOERST, som ordren ber om: ordren aapner for to aarsaker. Det er den
ANDRE. En listing SKILLER allerede de to slagene strukturelt - hver
directory_listing-payload svarer med "directories" (oppfoeringer noeklet "path",
med subtre-telling) og "documents" (noeklet "name", med type/title/chars) som TO
distinkte noekler, og en katalog opptrer aldri blant dokumentene. Arm (4) pinner
det, fordi det er en egenskap denne fila naa HVILER paa. Derfor ingen
trailing-/-markoer: formen sier allerede hva som er hva, og aa endre payloaden
ville flyttet en listing tre eldre gates maaler byte for byte.

Det som MANGLET var den andre halvdelen. MAALT foer arbeidet, paa den shippede
nestede eksempelbasen:

    read_file(id, "a") -> IsADirectoryError: [Errno 21] Is a directory: <abs sti>

En OSError, altsaa krasj-kanalen i stedet for CLI-ens nekt-tuppel og hostings
400-arm, og den navnga verken hva stien VAR eller hvilken sprosse kalleren
skulle brukt. DirectoryPathRefused (ValueError, BundlePathNotFound- og
DimensionScopeRefused-presedensen) navngir begge. Regelen bor i VERKTOEYET, saa
den gjelder begge kallere (utforskningen, og siden S2c debatten) - samme
plassering som verdict-gaten, og FOER den: declares_verdict_type leser stiens
frontmatter, saa paa en katalog ville den reist noeyaktig den OSError-en denne
grenen finnes for aa erstatte.

MAALT, RAPPORTERT, IKKE FIKSET (utenfor ordren): det levende kallet var
read_file(".../30-7.md") - modellen la .md paa et katalogNAVN, som resolverer
til en sti som ikke finnes i det hele tatt, ikke til katalogen. Maalt paa samme
base gir den FileNotFoundError, altsaa samme form (OSError paa krasj-kanalen der
en navngitt nekt hoerer hjemme). Denne ordren fikser katalog-tilfellet; arm (5)
pinner maalingen av naboen, saa gapet er et faktum i suiten og ikke en setning i
en rapport.

RoedT foerst: import-feil paa DirectoryPathRefused (klassen fantes ikke).
Ingen endring i prompter.

Suite 1381 passed / 5 skipped (fra 1368/5; +13, 0 fjernet - strengt supersett).
ruff + mypy rene. Golden demo-transcript.stdout BYTE-UENDRET,
shasum -a 1 av INNHOLDET = ea8c534773acdbe41ae68f2c55724d69aaf8be4f.

Ordre 20260906T212735Z-2448754-from-.claude, funn (c).

Co-Authored-By: Claude <claude-opus-5>
2026-09-06 23:38:44 +02:00