P7 is right and landed, but re-measuring it exposed a consequence no row stated: with the gate live, 29 of 29 cost codes in 13 of 13 delivered proposals fall across the three free recordings (PM's denominator; 14 of 14 in 8 proposals on the PARSEABLE one -- the five blobs that separate the numbers are refused by pydantic's `claimed <= total` and never reach stage 0b). All 29 were invented, so the gate is right; but a gate that always refuses is as useless as one that never does. The cause is that the PROMPT asks for something the input cannot supply. `_build_messages` requires each affected_item to "restate a cost line as the project's price schedule already carries it", while K2's delivered input carries 9 occurrences / 2 distinct code-shaped tokens -- `SHA-01`/`SHA-10`, both document numbers off a page footer -- and `derive_cost_baseline` refuses the base outright. There is no cost line in it to restate. `GroundingOffer(chars, identifiers, cost_lines)` reports it. The PAIR is the diagnosis: "50 identifiers, 0 cost lines" says what neither number says alone. A REPORT, never a gate -- it blocks nothing, because a blocking requirement IS `--require-cost-baseline` (F4/D-3, opt-in, untouched), and `_ground_against_input` is untouched. The callsite is MEASURED, not chosen: `generate.py` composes the grounding per attempt, after `await _fetch_parsed`, so a report there could only speak once an attempt had been paid for; `run.py` binds both halves above the `--live-dry-run` cut and before the first `debate.run`, so the FREE trip says it. `delivered` is bound ONCE and the same variable feeds the report and `_evaluate`; the report composes THROUGH `_grounding_text`, the gate's own composer. A pattern is admissible here and not in the gate, and that is the difference between a report and a falsifier: an unknown form is a token left uncounted -- an under-count, never a false rejection. The forms are transcribed from the measurement; bare numbers are excluded with the number (46 394 / 2 117 in K2). `grounding_offer_notice` is the ONE renderer and is silent when the run CAN anchor -- omission, never an empty row. Load-bearing MEASURED (tests/test_grounding_offer_loadbearing.py, 12 arms), nine mutations all red against the WHOLE suite + green control 1570/5 (from 1558/5, strict superset, 0 removed) and the golden byte-unchanged (shasum -a 1 of the CONTENT = ea8c534773acdbe41ae68f2c55724d69aaf8be4f). Measurement: docs/2026-09-09-p8-forankringstilbudet.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
227 lines
14 KiB
Markdown
227 lines
14 KiB
Markdown
# P8 — den leverte inputen bærer ingen kostlinjer, så ingen forankret proposal kan oppstå
|
||
|
||
Ordre `20260909T142951Z-365478643-from-.claude`, økt 110. HEAD ved start: `277bb95`.
|
||
Alt i dette dokumentet er målt **gratis** — null modellkall, **NOK 0,00**.
|
||
|
||
## § 0 Hva som ER målt og hva som IKKE er det
|
||
|
||
**Målt:** hva de tre gratis opptakene faktisk leverte og hvor mange av kodene P7-gaten feller;
|
||
hva den LEVERTE inputen i hvert korpus po har liggende kan tilby som lovlig `affected_item`-kode;
|
||
og at rapporten som nå bygges sier null der tilbudet er null og positivt der det er positivt.
|
||
|
||
**Ikke målt:** at rapporten endrer noe LEVENDE. Ingen betalt kjøring er gjort, og ingen er
|
||
bestilt. At en modell som får se linja oppfører seg annerledes er ikke vist — samme klasse som
|
||
structured-output-grensen. Rapporten er dessuten skrevet på grunnlag av tre opptak fra **ÉN**
|
||
modell og **ETT** deployment.
|
||
|
||
**Ikke bygget, med vilje:** prosa-skanningen (operatørbeslutning A) og
|
||
`--require-cost-baseline` som default (operatørbeslutning, F4/D-3). Begge står uendret.
|
||
|
||
## § 1 Premissene (i)–(viii) — hver verifisert selv
|
||
|
||
| # | Premiss (PM) | Mitt utfall |
|
||
|---|---|---|
|
||
| (i) | HEAD `277bb95`, `git ls-remote origin main` = `eb41374`, upushet 2 | **BEKREFTET** ordrett |
|
||
| (ii) | To utrackede: presentasjons-HTML (parallell økt) + `scratchpad/` | **BEKREFTET**, intet tredje |
|
||
| (iii) | 1558 passed / 5 skipped, ruff rent, mypy rent (37 filer), golden `ea8c534…` | **BEKREFTET** alle fire |
|
||
| (iv) | 13 forslag / 29 koder / 29 ugrunnet | **BEKREFTET på PMs nevner, med et avvik — se § 2** |
|
||
| (v) | K2 leverer 9/2 distinkte kodeformede (`SHA-01`/`SHA-10`, dokumentnumre); N100 0 kodeformede, 17/8 kravnumre | **BEKREFTET ordrett** |
|
||
| (vi) | Ved uttømte forsøk returneres siste `Rejection`, ingen krasj | **BEKREFTET**: `generate.py` returnerer `GenerationResult(outcome=last_ruling, …)` etter forsøksløkka |
|
||
| (vii) | `--require-cost-baseline` er opt-in og skal ikke bli default | **RESPEKTERT**, urørt |
|
||
| (viii) | (A) og (B) er operatørens | **RESPEKTERT**, ikke avgjort her |
|
||
|
||
## § 2 Konsekvensen — og AVVIKET mot PMs tall
|
||
|
||
PMs tall er reprodusert nøyaktig **på PMs nevner**, men den nevneren teller blobs som aldri
|
||
NÅR P7-gaten. Begge tall er sanne om hver sin ting, og begge gir 100 %:
|
||
|
||
| Opptak | Rå JSON-blobs | Koder | Ugrunnet | Parsebare til IR | Koder | Ugrunnet |
|
||
|---|---|---|---|---|---|---|
|
||
| `p6-Aopen-records.json` | 2 | 4 | **4** | 2 | 4 | **4** |
|
||
| `Aopen-records.json` | 8 | 22 | **22** | 3 | 7 | **7** |
|
||
| `p4-n100-free-records.json` | 3 | 3 | **3** | 3 | 3 | **3** |
|
||
| **Totalt** | **13** | **29** | **29 (100 %)** | **8** | **14** | **14 (100 %)** |
|
||
|
||
De fem blobene som skiller tallene avvises av en **annen og TIDLIGERE falsifiserer** —
|
||
pydantics `claimed_saving_nok <= affected items' total` — og når derfor aldri stadium 0b.
|
||
Det er ikke en svakhet i PMs måling; det er to nevnere om to ulike hendelser. Grunnlaget er
|
||
det **mest sjenerøse** som finnes: unionen av ALLE prompter i opptaket. Selv der er ingen kode
|
||
grunnet.
|
||
|
||
Et instrument-forbehold, skrevet ned fordi det først ga feil svar: en rå
|
||
`SavingsProposal.model_validate_json` avviser **alle 13**, fordi svarene bærer WIRE-formen av
|
||
`assumptions` (et array) som `_normalise_assumptions` folder tilbake. En måling som stoppet der
|
||
ville rapportert 0 forslag — null fordi instrumentet ikke kunne lese formen, ikke fordi formen
|
||
manglet.
|
||
|
||
## § 3 Årsaken — prompten ber om noe inputen ikke kan levere
|
||
|
||
`generate._build_messages` sier ordrett: «Each entry in `affected_items` must restate a cost line
|
||
as the project's price schedule already carries it». Målt på record 0 (turen som bar bundelen):
|
||
|
||
* **K2** (P6: 96 567 tegn; S7c: 145 281 tegn) → **9 forekomster / 2 distinkte** kodeformede, og
|
||
begge er `SHA-01` / `SHA-10`. Konteksten er entydig: `Oppdragsnr.: 52308329 Dokumentnr.: SHA-01
|
||
Versjon: 01` — en sidefot i en SHA-plan — og `Dokumentnavn: SHA-10 - … Restrisikorapport`.
|
||
**Dokumentnumre, ikke kostlinjer.**
|
||
* **N100** (10 569 tegn) → **0** kodeformede, men **17 forekomster / 8 distinkte** kravnumre på
|
||
`Krav X.Y.Z—N`-form (em-dash U+2014).
|
||
|
||
Modellen ble bedt om å gjengi en kostlinje som ikke finnes, og fabrikkerte den. Dette rimer med
|
||
funn 4 (økt 107): K2s prisskjema bærer ingen mengdefortegnelse, 0 av 92 rader navngir
|
||
kode/mengde/enhetspris.
|
||
|
||
## § 4 Tilbudet per korpus — målt med den SHIPPEDE funksjonen
|
||
|
||
Teksten er komponert nøyaktig som `run_project` komponerer P7s grunnlag
|
||
(`"\n".join([context, bundle_grounding])`, deretter gjennom `generate._grounding_text`).
|
||
«Kostlinje» er po sin EGEN definisjon (`okf.derive_cost_baseline`, MAJOR-4) — ikke en ny
|
||
heuristikk oppfunnet her.
|
||
|
||
| Korpus | Konsepter | Grunnlag (tegn) | Distinkte identifikatorer | Kostlinjer | `derive_cost_baseline` |
|
||
|---|---|---|---|---|---|
|
||
| K2 s7c + `payload-open` | 630 | 1 991 597 | 50 | **0** | REFUSED |
|
||
| K2 s7c + `payload-default` | 630 | 1 970 415 | 50 | **0** | REFUSED |
|
||
| K2 s7a2 (peker-armen, P6) | 629 | 1 894 500 | 50 | **0** | REFUSED |
|
||
| N100 `n100-2023` | 446 | 462 041 | 435 | **0** | REFUSED |
|
||
| N200 `n200-2024` | 1 133 | 1 500 962 | 982 | **0** | REFUSED |
|
||
| N500 `n500-2024` | 270 | 408 220 | 272 | **0** | REFUSED |
|
||
| `shared/veglys-fv-soer` | 5 | 30 038 | 3 | **1** | REFUSED (men fila finnes) |
|
||
| `shared/tunnel-hauglia` | 5 | 36 546 | 2 | **1** | REFUSED (men fila finnes) |
|
||
| `shared/bygg-energi-mikro` | 4 | 11 019 | 2 | **0** | REFUSED |
|
||
|
||
**Klassene, målt.** K2s 50 distinkte kodeformede er tegningsnumre (`B-20-00-00`, `F-20-00-01`,
|
||
`V-73-20-01-01`), dokumentnumre (`SHA-01`, `RIM-02`, `RIA-01`, `NOT-01`), stoff- og
|
||
standardreferanser (`PCB-7`, `PAH-16`, `DALI-2`) og forskriftsnumre
|
||
(`FOR-2011-12-06-1357`). **Ingen av dem er en kostkode.** N-korpusene bærer kravnumre og UUID-er
|
||
(N200: 2 290 distinkte UUID-er), ingen kostkoder.
|
||
|
||
**Er et forankret forslag i det hele tatt MULIG?** For **K2: NEI**, og tallet er 0 —
|
||
`derive_cost_baseline` nekter basen, og ingen av de 50 identifikatorene er en kostlinje. Bare
|
||
**2 av 50** når i det hele tatt prompten. For **N-korpusene: NEI** på kostlinje — en vegnormal
|
||
bærer ingen — men **JA** på identifikator: 435 / 982 / 272 distinkte kravnumre er sitérbare, og
|
||
8 av dem sto i N100-prompten.
|
||
|
||
**Rene tall er farligst og bæres videre uendret:** 46 394 forekomster / 2 117 distinkte i K2
|
||
(P7 § 2). Regelen er inert mot dem og feiler ÅPENT. Ikke bygget om på.
|
||
|
||
**Gammel default.** Alt over er målt på `K2-bundle-20260903`. okf melder (innboks
|
||
`20260909T134141Z`, `reply-expected: no`, lukket med `coord-done`) at deres default-bygg sluttet å
|
||
emittere den 2026-09-08, at gjeldende default er 436 konsepter / 832 filer, og at de leser
|
||
formfunnet som fortsatt stående fordi endringen treffer FORMEN, ikke innholdet. Ingen ny bundle er
|
||
bygget eller konsumert her — deres endring er ikke pushet, og en re-måling på den nye defaulten er
|
||
en senere, separat ordre.
|
||
|
||
## § 5 Hva som er bygget — en RAPPORT, ikke en gate
|
||
|
||
`generate.GroundingOffer(chars, identifiers, cost_lines)` + `generate.grounding_offer(...)`,
|
||
kalt fra `run.py`, rendret av `run.grounding_offer_notice`.
|
||
|
||
**Valget av kallsted, med grunnen (ordrens eget krav).** Begge kandidater ble lest først.
|
||
`generate.py` komponerer grunnlaget **per forsøk, ETTER `await _fetch_parsed(messages)`** — en
|
||
rapport derfra kan først tale når ett forsøk allerede er betalt, altså nøyaktig det ordren ber
|
||
den om å komme foran. `run.py` binder begge halvdeler ved `run.py:1228`, **over
|
||
`--live-dry-run`-kuttet og før første `debate.run`**. Valgt: **`run.py`**. Tellefunksjonen bor
|
||
likevel i `generate.py`, ved siden av `_grounding_text` den måler — å skille dem ville gitt to
|
||
steder å bli uenige på.
|
||
|
||
**De fire kravene:**
|
||
|
||
1. **BLOKKERER ikke.** En kjøring med null tilbud kjører som før. Et blokkerende krav ER
|
||
`--require-cost-baseline`, som premiss (vii) fredet.
|
||
2. **Måler den EKSAKTE teksten.** `grounding_offer` komponerer GJENNOM `_grounding_text` —
|
||
samme funksjon P7s gate bruker — og `run.py` binder `delivered` **én gang** og gir samme
|
||
variabel til både rapporten og `_evaluate`. To komposisjoner av én tekst er fri til å være
|
||
uenige (kø-(p)); her er de identiske ved konstruksjon.
|
||
3. **Når utfallet operatøren leser.** `RunResult.grounding_offer`, `DryRunReport.grounding_offer`
|
||
og én linje på stdout i begge CLI-armene.
|
||
4. **Gjenbruker P7s sømmer.** Ingen ny domstype ved siden av `Rejection`/`ValidatedProposal`.
|
||
`_ground_against_input` er **URØRT**.
|
||
|
||
**Identifikator-formene er TRANSKRIBERT fra målingen i § 4**, ikke valgt: `[A-ZÆØÅ]{1,8}[-_]\d…`
|
||
(K2s 50) og `Krav X.Y.Z—N` (N-korpusenes dominerende form). At et mønster er tillatt HER og ikke i
|
||
`_ground_against_input` er selve skillet mellom en rapport og en gate: en form rapporten ikke
|
||
kjenner er et token den unnlater å telle, altså en **under-telling** — aldri en falsk avvisning.
|
||
**Rene tall er BEVISST utelatt, med tallet** (46 394 / 2 117): å telle dem ville gjort hver rapport
|
||
positiv og målingen inert — repoets kardinalklasse, en gate som bare kan bli grønn.
|
||
|
||
Rendereren er **ÉN**, og den tier når kjøringen KAN forankre en kostlinje — omisjon, aldri en tom
|
||
rad (`cost_baseline_notice`s regel). Den bærer **begge tall**, fordi paret er diagnosen:
|
||
«0 kostlinjer» alene leses som en gjentakelse av `cost_baseline_notice`, «50 identifikatorer» alene
|
||
leses som gode nyheter.
|
||
|
||
## § 6 Kjent-positiv og kontroll
|
||
|
||
**Kjent-positiven (bindende):** N100s input bærer `Krav 3.3.1—13` (em-dash U+2014; P7 premiss
|
||
(vii): 6 av 6 prompter). Rapporten sier **positivt tilbud** der, og armen er paret med en kontroll
|
||
på at strengen faktisk STÅR i fixturen — en rapport som fant null fordi den lette etter ingenting
|
||
ville ellers bestått.
|
||
|
||
**Kontrollen på samme materiale:** K2s to genererings-prompter, der tilbudet er **null i begge
|
||
tall**. Uten den beviser en grønn kjent-positiv ingenting.
|
||
|
||
**Fixturvalget, uttalt.** Testene leser P7s egne SPORede fixturer under
|
||
`tests/fixtures/p7-grounding/`. De leverte KUTTENE (10 kB N100, 96 kB K2) er ikke sporet: å
|
||
committe verbatim anbudstekst og standardtekst inn i et repo som publiseres på `open/` er en
|
||
publiseringsbeslutning som tilhører operatøren, ikke denne ordren. 8-/435-distinkt-tallene står
|
||
derfor i § 4 som MÅLINGER; det testene asserterer er EGENSKAPEN, på tekst repoet allerede
|
||
shipper.
|
||
|
||
## § 7 Mutasjonstabellen
|
||
|
||
Grønn kontroll **1570 passed / 5 skipped** (fra 1558/5; **+12 node-ider, 0 fjernet**, målt med
|
||
`comm` mot en liste bygget fra HEAD). Golden `demo-transcript.stdout` BYTE-UENDRET,
|
||
`shasum -a 1` av INNHOLDET = `ea8c534773acdbe41ae68f2c55724d69aaf8be4f` (ALDRI git-blob-id-en).
|
||
Hver mutasjon kjørt mot HELE suiten, én per kall, restaurert fra `scratchpad/p8/mut-backup/`
|
||
med `shasum -c`, aldri `git checkout`.
|
||
|
||
| # | Mutasjon | Røde |
|
||
|---|---|---|
|
||
| M1 | rapporten teller alltid null | **2** (kjent-positiven blant dem) |
|
||
| M2 | rapporten teller alltid positivt | **7** (K2-kontrollen først) |
|
||
| M3 | rapporten bygges fra `delivered` alene, ikke gjennom `_grounding_text` | **1** (krav (2)-armen alene) |
|
||
| M4 | rapporten når aldri `RunResult` | **3** |
|
||
| M5 | rapporten når aldri `DryRunReport` | **3** |
|
||
| M6 | rendereren skriver alltid linja | **2** (omisjonen er selv gatet, på begge flater) |
|
||
| M7 | detach dry-run-utskriften | **1** |
|
||
| M8 | detach fullkjørings-utskriften | **1** |
|
||
| M9 | rene tall telles som tilbud | **2** |
|
||
|
||
Ni mutasjoner, **alle røde**. Ingen grønn mutasjon, altså ingen uvitnet søm i denne leveransen.
|
||
|
||
## § 8 Honesty limits
|
||
|
||
* **Alt er målt OFFLINE** på tre opptak fra **ÉN modell** og **ETT deployment**. Ingen betalt
|
||
kjøring bekrefter at rapporten endrer noe levende, og at en modell som ser linja velger
|
||
annerledes er **ikke vist** (structured-output-grensens klasse).
|
||
* **Rapporten BLOKKERER ikke.** En kjøring med null tilbud kan fortsatt brenne tre forsøk på et
|
||
forslag som ikke kan bli forankret. Det er **VALGT**, ikke oversett: et blokkerende krav er
|
||
`--require-cost-baseline`, og F4/D-3 la den beslutningen hos operatøren.
|
||
* **Identifikator-formene er et mønster**, og et mønster kan mangle en form. Retningen er
|
||
under-telling, aldri falsk avvisning — men et korpus med en tredje form vil rapportere lavere
|
||
enn det tilbyr, til noen måler den formen.
|
||
* **`cost_lines` er `len(baseline.items)`**, lest av SAMME `baseline`-binding `_grounding_text`
|
||
tar som sin tredje kilde. Den gjentar altså forankringen som et ANTALL. Den står her fordi
|
||
paret er diagnosen, ikke fordi antallet er en ny kjensgjerning.
|
||
* **Portefølje-armen er BEVISST ikke wiret.** `run_portfolio` skriver ingen slik linje;
|
||
`bundle_id_notice`s avgjørelse, ikke `cost_baseline_notice`s. Asymmetrien står her fordi
|
||
stillhet om den er det eneste gale svaret.
|
||
* **Den hostede flaten er urørt.** Feltet er i ingen av hostings tre sett, så Fase 4es to
|
||
halvdeler står uendret.
|
||
* **Tilbudsmålingen er gjort på okf sin GAMLE default-bundle** (`K2-bundle-20260903`). En
|
||
re-måling på den nye (436 konsepter / 832 filer) er en senere, separat ordre.
|
||
* **(A) prosa-skanningen og (B) blindsone-valget forblir OPERATØRENS.** Målingen her informerer
|
||
(B) — den handler om **TILBUDET** i inputen, ikke om hvilket utdrag modellen **VELGER** — men
|
||
den avgjør den ikke.
|
||
|
||
## § 9 Reproduksjon
|
||
|
||
uv run pytest -q tests/test_grounding_offer_loadbearing.py
|
||
uv run python -m portfolio_optimiser.run BYGG-KONTOR-NORD \
|
||
--docs-dir shared/examples/bygg-energi-mikro \
|
||
--bundle-dir shared/examples/bygg-energi-mikro --live-dry-run
|
||
uv run python -m portfolio_optimiser.run VEGLYS-FV-SOER \
|
||
--docs-dir shared/examples/veglys-fv-soer \
|
||
--bundle-dir shared/examples/veglys-fv-soer --live-dry-run
|
||
|
||
Den første basen har ingen kostbaseline og skriver tilbudslinja; den andre har én og tier.
|
||
Måleskriptene ligger i `scratchpad/p8/` (utracket).
|