feat(explore): read_bundle costs O(documents), never O(bytes of the base)

[skip-docs]

S2c / MAJOR-3, order 20260902T151931Z-250257273. The measurement landed first
in ce7f687; this commit is the one seam it authorised, plus the after-table.

read_bundle returned okf.bundle_context -- the WHOLE navigated base. Because
the exploration's participants share one conversation history, that single
function_result rode in FIVE later prompts at full price without anyone asking
for it again: 54-59 percent of every prompt-token in a CLI --explore run.

It now returns the catalogue form one rung down the ladder -- one entry per
concept document (name, type, title, chars) -- with read_file as the next rung.
Tunnel base: 12 595 -> 259 o200k tokens, exploration prompt-tokens -91 percent.

The listing is built from Bundle.context_files and never from files: that is
the property which drops the type: verdict layer at every level, and a listing
built from files would route prior verdicts in front of the navigator around
the gated ExpeL fold while every cost arm stayed green.

A premise was felled before anything was built on it: the tunnel base's root
index body is 4 763 chars alone, nearly the whole ceiling, for a field the
catalogue already excerpts and read_file still returns whole. So read_bundle
carries the listing and not the index.

The tool description and the navigator's instruction both claimed "read its
navigated context" and were updated in the same move -- a description that lies
about the body IS the model's instruction. Two pre-existing asserts would have
gone vacuously true against a list and were strengthened rather than left.

Ceiling lives in the test, not in explore.py. Deviation stated there and in the
docs: it bounds CHARACTERS, not tokens, because tiktoken is not a project
dependency and a gate that skips when an optional package is missing is a gate
that can be silently absent; the conversion was measured (2.89 chars/token) and
the order's own token criterion verified once by the instrument.

Load-bearing measured: seven mutations, all red against the WHOLE suite; green
control 1195 passed / 5 skipped (from 1189/5, strict superset); golden
demo-transcript.stdout byte-unchanged; and the debate's three bundle_context
copies are byte-identical before and after, which proves run.py and the
nav-goldens were not touched rather than asserting it.
This commit is contained in:
Kjell Tore Guttormsen 2026-09-03 00:36:01 +02:00
commit b799cc527f
6 changed files with 356 additions and 10 deletions

View file

@ -1073,6 +1073,52 @@ Python ≥3.10. MAF (`agent-framework-core` 1.16.0, `-orchestrations` 1.1.1 —
nye verktøyet, så at en manager velger BEDRE med et utdrag enn med hele indeksen er ikke bevist
(structured-output-grensens klasse); og ordrens nevner for N100:2023 var 34 mens disken viser 40 —
tallene bruker den målte nevneren. Måling: `docs/2026-08-26-katalogkostnaden.md`.
- **`read_bundle` koster O(DOKUMENTER i én base), aldri O(bytes av den — S2c/MAJOR-3, økt 77):**
verktøyet returnerte `okf.bundle_context`, altså HELE den navigerte basen, og fordi utforskningens
deltakere deler ÉN samtalehistorikk red det ene `function_result`-et med i **hver senere prompt**
til full pris uten at noen ba om det igjen. **MÅLT FØRST, med nevner, og committet som docs før én
linje kode ble rørt** (`docs/2026-09-02-read-bundle-kontekstkostnad.md`): 3 861 / 10 406 / **12 595**
o200k-tokens for de tre eksempelbasene, **5 kopier** per CLI-`--explore`-kjøring (navigatør ×1,
manager ×3, hypotesiser ×1) = **54 % / 59 % / 59 %** av ALLE prompt-tokens. Instrumentet ble
validert mot en KJENT POSITIV før bruk (det reproduserte commons' egne publiserte
`bundle_context`-fasittall eksakt), og prompten måles som tekst + `function_call` +
`function_result``.text` alene måler en kontekstbærende prompt til noen få tegn.
**Formen er katalogens, ett trinn ned på stigen** (`list_bundles` = hvilke baser finnes,
`read_bundle` = hva er i DENNE, `read_file` = hva sier dokumentet): én oppføring per konseptfil med
`name`, `type`, `title`, `chars`. Etter: **259 tokens** på tunnelbasen, utforskningens
prompt-tokens 77 / 90 / **91 %**. **Listen bygges av `Bundle.context_files`, ALDRI `files`**
det er dén property som dropper `type: verdict`-laget (og nestede `index.md`) på hvert nivå, og en
liste bygget av `files` ville rutet tidligere dommer foran navigatøren UTENOM den gatede
ExpeL-folden mens hver kostnads-arm forble grønn. **Et premiss ble felt før noe ble bygget på det:**
«indeksbodyen er basens egen navigasjonsprosa, så den hører hjemme her» — tunnelbasens rot-indeks er
**alene 4 763 tegn ≈ 1 400 tokens**, altså nesten hele taket, for et felt katalogen alt gir et
bundet utdrag av og `read_file(id, "index.md")` fortsatt gir helt. **Taket bor i TESTEN**
(`_CEILING_CHARS = 1 500`), katalogtakets regel av katalogtakets grunn. **AVVIK fra ordren, uttalt:**
ordren ordlegger gaten i o200k-TOKENS; gaten bounder TEGN, fordi `tiktoken` ikke er en
prosjektavhengighet og en gate som skipper når en valgfri pakke mangler er en gate som kan være
stille fraværende — konverteringen er MÅLT (748 tegn / 259 tokens = 2,89 tegn/token), og ordrens
eget kriterium er verifisert direkte én gang av instrumentet. **«Ikke utløs» er bevist som en
MÅLING, ikke som en forsikring:** debattens tre `okf.bundle_context`-kopier er **byte-identiske før
og etter** i alle tre baser (12 047 / 32 567 / 39 104 prompt-tokens, hver prompt uendret) — sterkere
enn å påstå at `run.py` ikke ble rørt. **Verktøybeskrivelsen og navigatørens instruksjon er oppdatert
i samme trekk:** begge påsto «read its navigated context», og en beskrivelse som lyver om kroppen er
modellens instruks (Fase 3-klassen, påstander flaten gjør om SEG SELV). **To eksisterende asserts
ville blitt VAKUØSE i stillhet** (`read_bundle(...) != ""` er sant for enhver liste,
`test_explore_loadbearing.py` + `test_bundle_id_reconciliation_loadbearing.py`) og er styrket, ikke
latt stå. Load-bearing MÅLT (`tests/test_read_bundle_cost_loadbearing.py`, 6 armer), **sju mutasjoner
alle røde mot HELE suiten** + grønn kontroll **1 195/5** (fra 1 189/5, supersett, 0 fjernet) og golden
`demo-transcript.stdout` BYTE-UENDRET (`ea8c534773acdbe41ae68f2c55724d69aaf8be4f`): reverter sømmen
(7 røde) · bygg fra `files` (3) · bundet men VAKUØS tom liste (6) · dropp `chars` (2) · bær
indeksbodyen likevel (4) · `read_file` trunkerer (2 — inkludert katalog-gaten, et uavhengig vitne) ·
detach `reconcile_bundle_id` (1). **Ærlighets-grenser, uttalt:** dette er IKKE «59 % kostnad» — en
navigatør som åpner *k* dokumenter betaler *k* `read_file`-resultater, og gevinsten er at den betaler
for det den VALGTE og at hvert resultat rir fra SITT kall og framover; at en LEVENDE modell velger
BEDRE med en liste enn med hele konteksten er IKKE bevist (structured-output-grensens klasse);
multiplikatoren 5 gjelder dette manuset (`misjonsreview-v2` § 4 målte 7× med et annet); debattens 3×
er PM-ens egen beslutning og er urørt; prefiks-caching (≈ 60 % debatt / ≈ 40 % utforskning cachebart
som koden står) er NOTERT, ikke bygget. **Et fravær som var instrumentfeil, ikke faktum:** første
ETTER-kjøring rapporterte 0 kopier på to baser — sonden var en midtskive som traff norske tegn
prompten serialiserer escaped; byttet til et ASCII-konseptfilnavn ga 5, som før.
- **Ekspertdommen kan ikke oppstå av STILLHET, og fraværet er en FØRSTEKLASSES tilstand (F2,
non-goal 3, økt 66):** `run_project` KREVDE `verdict_input` og kjørte `capture_verdict`
ubetinget, CLI-en defaultet det til `{"approved", "reviewed by expert"}`, og hosting listet det