feat(p18): a listing is a WINDOW, and an invented path is refused by name
P18 part A (order 20260914T105139Z). P16 measured S7a-3's ladder against a delivered corpus for the first time and found two things fixture bases cannot show. (1) One level is not bounded by being one level. Measured 14.09 on the four mounted vegnormal bases: okf.directory_listing on krav/N200 is 169 974 chars over 1 132 documents, krav/N100 69 250 over 445, krav/N500 39 853 over 269, and R761's own root 110 912 over 2 728 SUBDIRECTORIES -- 27-113x the 1 500-char ceiling S7a-3 set, riding in every later prompt. That last number is why the window covers BOTH kinds: a pagination over documents only would have left the largest measured level unpaginated. read_dir now answers with a window. offset/limit page directories first then documents as ONE sequence (two independent windows make "the next ten" a question with two answers); total is the denominator and is always carried; limit is CLAMPED to 50, never refused. Default 10 chosen against the ceiling: one entry is 121-209 chars (median 145) over the four bases. After: n100 1 493, n500 1 453, R761 479, n200 1 537 -- 2.5 % over, stated rather than tuned away, because the ceiling is a character budget and the window is a count. Largest single call any caller can make: ~7 600 chars. filter narrows a level instead of paging it: case-insensitive SUBSTRING over title + req_number/prosessnr and over a directory path, answering with total_matches beside total. A substring and not a pattern for _ground_against_input's reason one rung down -- a form the rule does not know returns nothing, and an empty listing reads as "the base does not have this". A filter that matches nothing is an ANSWER (total_matches: 0), never a refusal. ORDER PREMISE FELLED before building on it: the order asks for a separate top-level reader "like own_frontmatter" because parse_frontmatter was last-write-wins -- P15 (f13dc64) already made a top-level key win, so BundleFile.frontmatter IS the concept's own value and a second reader here would be the second copy ko-(p) forbids. (2) 0 of 26 fasit concepts were opened in 32 read_file calls (the order's "24" is the four runs' DISTINCT paths, re-measured 14.09), and 10 of those calls named a path the base does not hold. Each reached the model as MAF's opaque "Error: Function failed." while counting toward the three consecutive tool errors that end a request. read_file now refuses such a path by name (BundlePathNotFound, funn-99 returned form) and names the nearest directory that actually HOLDS documents -- chosen off context_files, never the filesystem, because a directory can exist on disk and hold no navigated concept (read_dir would then refuse the very path the refusal handed back) and because context_files is what drops the type: verdict layer, so a refusal can never advertise by name the one layer no listing mentions. Narrow by construction: only an ABSENT path is translated; any other OSError propagates untouched. Two existing arms REWRITTEN, neither weakened: - test_a_nonexistent_sibling_is_still_an_os_error was a tripwire whose own docstring said "when it goes red, someone has closed it, and that is a decision to be recorded". This is the record. Its narrowness half survives as a new arm driving a real PermissionError on a file that IS there. - test_every_document_is_still_reachable_and_the_counts_add_up became STRONGER: the accounting must now page, so the same assertion also proves the window is complete and non-overlapping. tests/test_navigation_window_loadbearing.py: 13 arms. Arms needing the delivered bases SKIP with the root named (PORTFOLIO_VEGNORMAL_ROOT), as MAJOR-3's ceiling arm does; the window algebra, the filter negative and the refusal run over a synthetic base UNCONDITIONALLY, so the file can never be silently absent in full. Verification: uv run pytest -q 1672 passed / 5 skipped before the new file (1670 oncfd9079). ruff check + format clean, mypy clean (38 files). Golden demo-transcript.stdout BYTE-UNCHANGED, shasum -a 1 of the CONTENT = ea8c534773acdbe41ae68f2c55724d69aaf8be4f. No version bump, no push. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
cfd9079a4a
commit
9b47e5aa62
7 changed files with 634 additions and 42 deletions
49
CLAUDE.md
49
CLAUDE.md
|
|
@ -2472,6 +2472,55 @@ Python ≥3.10. MAF (`agent-framework-core` 1.16.0, `-orchestrations` 1.1.1 —
|
|||
gratis-turen etter at flaggene landet: samme stdout sa «Stops at: 3 rounds / 100000 tokens» TO
|
||||
linjer over «max_rounds=8, max_tokens=120000» — Fase-3-klassen, innfort av nettopp det flagget
|
||||
som annonseres. Rettet til argv; M16 (les konstantene igjen) → 1 rod, den armen ALENE.
|
||||
- **En listing er et VINDU, og en sti kalleren fant på er en NEKT (P18/A, 14.09):** S7a-3 bandt
|
||||
kostnaden til oppføringer på ETT nivå i stedet for dokumenter i basen, og på fixturbasene holdt
|
||||
det. P16 målte hva ett nivå koster på et LEVERT korpus: `krav/N200` **169 974 tegn** over 1 132
|
||||
dokumenter, `krav/N100` 69 250 over 445, og R761s egen rot **110 912 over 2 728 UNDERKATALOGER** —
|
||||
27–113× taket, ridende i hver senere prompt; 3 av 7 betalte kjøringer døde på tokentaket.
|
||||
**Vinduet dekker BEGGE slag, og det er en måling, ikke symmetri:** en paginering bare over
|
||||
dokumenter ville latt det STØRSTE målte nivået stå upaginert. `offset`/`limit` over kataloger
|
||||
FØRST, så dokumenter — ÉN sekvens, fordi to uavhengige vinduer gjør «neste ti» til et spørsmål
|
||||
med to svar. `limit` KLEMMES (`_DIRECTORY_PAGE_MAX = 50`), aldri nektes: kalleren ba om en
|
||||
listing, og å nekte den sender en modell som ba om for mye bort med ingenting. Default 10 er valgt
|
||||
MOT taket: én oppføring er 121–209 tegn (median 145) over de fire leverte basene, så ti av de
|
||||
STØRSTE er 2 090 tegn med oppføringer — n100 lander på 1 493 (ordrens bundne krav), n500 1 453,
|
||||
R761 479, og n200 på **1 537**, 2,5 % over, fordi taket er et TEGN-budsjett og vinduet er et
|
||||
ANTALL; uttalt, ikke justert bort. **`total` er NEVNEREN og bæres alltid** (ansikt 4: et vindu
|
||||
uten nevner er en måling uten nevner), mens `total_matches` er et ANNET faktum, ikke en andre kopi
|
||||
— «hva er her» og «hvor mye av det slapp filteret gjennom» er to spørsmål, og en navigatør som
|
||||
bare ser ett av dem kan ikke skille et for smalt filter fra et nesten tomt nivå. **`filter` er en
|
||||
DELSTRENG, ikke et mønster**, av `_ground_against_input`s grunn ett hakk ned: kalleren er en
|
||||
modell som velger ord, og en form regelen ikke kjenner ville returnert ingenting — en tom listing
|
||||
som leses som «basen har ikke dette». Delstreng feiler mot å vise MER, som kan snevres inn;
|
||||
et mønster feiler mot å vise ingenting, som ikke kan det. Matchet går over `title` +
|
||||
`req_number`/`prosessnr` (toppnivå, lest rett av `BundleFile.frontmatter` — **P15 (f13dc64) gjorde
|
||||
allerede toppnivå til vinner, så ordrens premiss om en egen `own_frontmatter`-leser er FELT: en
|
||||
andre leser her ville vært kø-(p)**) og over en katalogs sti; `description` er BEVISST utelatt
|
||||
(hvert konsept i alle fire baser har en, så prosa-match ville returnert mesteparten av et nivå for
|
||||
de fleste ord — et filter som ser ut til å virke uten å binde noe). **Et filter uten treff er et
|
||||
SVAR** (`total_matches: 0`), aldri en nekt: å nekte det gjør et ærlig negativt funn uskillbart fra
|
||||
en sti som ikke finnes — nøyaktig forvirringen `BundlePathNotFound` finnes for.
|
||||
**A3: en fraværende sti oversettes til `BundlePathNotFound` i funn-99-formen**, og den navngir
|
||||
den NÆRMESTE katalogen som faktisk HOLDER dokumenter — valgt av `context_files`, aldri av
|
||||
filsystemet, fordi en katalog kan finnes på disk og ikke holde noe navigert konsept (da nekter
|
||||
`read_dir` den, og nekten ville levert en sti som ikke resolverer — `_index_excerpt`-regelen), og
|
||||
fordi `context_files` er property-en som dropper `type: verdict`-laget, så en nekt aldri kan
|
||||
reklamere ved navn for det ene laget ingen listing nevner. **Innsnevringen er BÆRENDE:** kun en
|
||||
sti som er BORTE oversettes; enhver annen `OSError` propagerer urørt, fordi en nekt er et utsagn
|
||||
om KALLERENS sti og en fil som ER der og ikke kan leses er et annet faktum. Målt over P16s fire
|
||||
betalte kjøringer: **10 av 32** `read_file`-kall navnga en sti basen ikke holder (ordrens «24
|
||||
kall» er de fire kjøringenes DISTINKTE stier, ikke kallene — re-målt 14.09), og hvert av dem nådde
|
||||
modellen som MAFs ugjennomsiktige «Error: Function failed.» mens det telte mot de tre påfølgende
|
||||
verktøyfeilene som avslutter en forespørsel. Etter: 10 navngitte nekter, 22 dokumenter fortsatt
|
||||
servert — en gate som nektet alt ville bestått den første halvdelen alene. **TO EKSISTERENDE
|
||||
ARMER ER SKREVET OM, IKKE SVEKKET:** `test_a_nonexistent_sibling_is_still_an_os_error` var en
|
||||
TRIPWIRE hvis egen docstring sa «when it goes red, someone has closed it, and that is a decision
|
||||
to be recorded» — dette er protokollen; og `test_every_document_is_still_reachable_and_the_counts
|
||||
_add_up` ble STERKERE, ikke svakere: regnskapet må nå PAGINERE, så samme assert beviser i tillegg
|
||||
at vinduet er fullstendig og ikke-overlappende. **Ærlighets-grenser, uttalt:** `navigate_bundle`
|
||||
kalles fortsatt per verktøykall (I/O, ikke tokens); A3-nekten navigerer basen ÉN gang ekstra på
|
||||
feilstien for å finne den nærmeste listbare katalogen; at en LEVENDE modell BRUKER `filter` er
|
||||
ikke bevist (structured-output-grensens klasse) — DEL D er målingen.
|
||||
- **STATE.md er local-only** (gitignored). Voyage session-state er efemert; STATE.md er kanonisk kontinuitet.
|
||||
- Prosess: Voyage-plugin (`/trekbrief → /trekplan → /trekexecute → /trekreview`) per større fase.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue