feat(run,generate): a run says what its delivered input can ground, before it spends an attempt [skip-docs]

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>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-09 17:50:02 +02:00
commit 455d611660
5 changed files with 767 additions and 2 deletions

View file

@ -2316,6 +2316,49 @@ Python ≥3.10. MAF (`agent-framework-core` 1.16.0, `-orchestrations` 1.1.1 —
den hostede flaten er urørt (feltet er i ingen av hostings tre sett); og
`--require-cost-baseline` er IKKE gjort til default (F4/D-3). Måling:
`docs/2026-09-09-p7-forankrede-identifikatorer.md`.
- **En kjøring SIER hva den leverte inputen kan forankre, før den bruker et forsøk på et forslag
som ikke kan bli forankret (P8, 09.09):** P7 er riktig og landet — men re-målingen avdekket en
konsekvens ingen rad uttalte: med gaten live faller **29 av 29 koder i 13 av 13 leverte forslag**
over de tre gratis-opptakene (PMs nevner; på den PARSEBARE nevneren 14 av 14 i 8 forslag — de
fem blobene som skiller tallene avvises av pydantics `claimed <= total` og når aldri stadium 0b).
Alle 29 VAR oppdiktet, så gaten er riktig; men en gate som alltid nekter er like ubrukelig som en
som aldri gjør det. **Årsaken er at PROMPTEN ber om noe inputen ikke kan levere:**
`_build_messages` krever at hver `affected_item` «restate a cost line as the project's price
schedule already carries it», mens K2s LEVERTE input bærer **9 forekomster / 2 distinkte**
kodeformede tokens — `SHA-01`/`SHA-10`, begge dokumentnumre fra en sidefot — og
`derive_cost_baseline` nekter basen: det finnes ingen kostlinje å gjengi. `GroundingOffer(chars,
identifiers, cost_lines)` er svaret, og **PARET er diagnosen**: «50 identifikatorer, 0
kostlinjer» sier det ingen av tallene sier alene. **En RAPPORT, aldri en gate** — den blokkerer
ikke, fordi et blokkerende krav ER `--require-cost-baseline` (F4/D-3, opt-in, urørt), og
`_ground_against_input` er URØRT. **Kallstedet er MÅLT, ikke valgt:** `generate.py` komponerer
grunnlaget PER FORSØK, etter `await _fetch_parsed`, så en rapport derfra kan først tale når ett
forsøk er betalt; `run.py` binder begge halvdeler over `--live-dry-run`-kuttet og før første
`debate.run`, så den FRIE turen sier det. `delivered` bindes ÉN gang og gir samme variabel til
rapporten og til `_evaluate` (to komposisjoner av én tekst er kø-(p)), og rapporten komponerer
GJENNOM `_grounding_text` — samme funksjon gaten bruker. **Et mønster er tillatt HER og ikke i
gaten**, og det er skillet mellom rapport og gate: en ukjent form er et token som ikke telles,
altså under-telling, aldri falsk avvisning. Formene er TRANSKRIBERT fra målingen (K2: 50
distinkte kodeformede, 0 kravnumre; N-korpusene: 269981 distinkte kravnumre, ≤3 kodeformede);
**rene tall er BEVISST utelatt med tallet** (46 394 / 2 117 i K2 — å telle dem gjør hver rapport
positiv og målingen inert). `grounding_offer_notice` er ENESTE renderer og tier når kjøringen KAN
forankre — omisjon, aldri tom rad. Load-bearing MÅLT
(`tests/test_grounding_offer_loadbearing.py`, 12 armer), **ni mutasjoner alle røde mot HELE
suiten** + grønn kontroll **1570/5** (fra 1558/5, supersett, 0 fjernet) og golden BYTE-UENDRET
(`shasum -a 1` av INNHOLDET = `ea8c534773acdbe41ae68f2c55724d69aaf8be4f`): M1 teller alltid null
(2, kjent-positiven blant dem) · M2 teller alltid positivt (7, K2-kontrollen) · M3 bygg fra
`delivered` alene (1) · M4 når aldri `RunResult` (3) · M5 når aldri `DryRunReport` (3) ·
M6 rendereren skriver alltid linja (2) · M7 detach dry-run-utskriften (1) · M8 detach
fullkjørings-utskriften (1) · M9 rene tall telles (2). **Ærlighets-grenser, uttalt:** ingen betalt
kjøring bekrefter at rapporten endrer noe levende (tre opptak, ÉN modell, ETT deployment); den
BLOKKERER ikke, så en kjøring med null tilbud kan fortsatt brenne tre forsøk — VALGT, ikke
oversett; `cost_lines` er `len(baseline.items)`, altså forankringen som ANTALL, og står her fordi
paret er diagnosen; testfixturene er P7s SPORede prompter, ikke de leverte kuttene (10 kB / 96 kB
verbatim anbuds- og standardtekst inn i et repo publisert på `open/` er operatørens
publiseringsbeslutning, ikke denne ordrens) — 8-/435-distinkt-tallene er MÅLT og står i
dokumentet; portefølje-armen og den hostede flaten er BEVISST urørt; og tilbudsmålingen er gjort
på okf sin GAMLE default-bundle (`K2-bundle-20260903`), så en re-måling på den nye (436 konsepter
/ 832 filer) er en senere, separat ordre. Måling:
`docs/2026-09-09-p8-forankringstilbudet.md`.
- **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.