feat(step5): the falsification that informed the next hypothesis now leaves the loop

generate_via_llm consumed each validator Rejection internally (`last`), fed it into the
next attempt's prompt, and dropped it. So Step 5 was real but unobservable: a caller could
see THAT a proposal validated, never that it validated on attempt 2 after the deterministic
validator falsified attempt 1. It was the one step of the eight with no output to show.

The seam is a typed return value -- GenerationResult(outcome, refinements) -- rather than an
out-parameter or a callback: a returned value cannot be silently lost by a caller that forgets
to pass a collector, and mypy forces every call site to acknowledge it.

refinements carries ONLY rejections that were actually fed back. When the attempt budget runs
out the final rejection IS outcome; counting it here would be double-counting, and the bounded
control test goes red on the collect-everything implementation that gets this wrong.

The loop's bound is untouched: max_attempts and meter.tick_round stand, and `last` still drives
the prompt alone, so prompt growth is unchanged. run.py accumulates across _evaluate calls, so
_evaluate_mandate is untouched; RunResult.refinements defaults (the coverage precedent) and is
concatenated across approaches rather than keyed per approach -- stated as an honesty limit.

The simulation now shows it: the scripted proposer overclaims 250000, which the validator
falsifies against P90 = 90000, and the corrected 30000 validates. Only the overclaim is
scripted -- the rejection is computed. scripted_factory takes a per-role reply selector so this
needs no second scripted client body.

README records the two accuracy changes only (Step 5 is now inspectable; the simulation trace
shows the correction). The level-2 publishing claim stays deferred until after the demo (O4).

Load-bearing MEASURED against the full suite with a control, four mutations all red:
detach the returned history (4 tests) - collect-everything (control only) - detach the run
wiring (2 tests) - revert the simulation's proposer to a constant (the demo-protection test).
Control: 759 passed / 4 skipped; ruff, format and mypy clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CcWFcREUi6YPjEpN3ACDP
This commit is contained in:
Kjell Tore Guttormsen 2026-08-06 15:12:06 +02:00
commit d6f3359fae
11 changed files with 381 additions and 26 deletions

View file

@ -45,7 +45,7 @@ Dette er ikke en unnskyldning som svekker demoen — det er selve grunnregelen r
| 2 — Hypotese | forslaget med parametere | data finnes, printes ikke | `print` |
| 3 — Debatt (maker-checker) | begge deltakere + `checker_verdict` | checker printes | `print` |
| 4 — Valider / falsifiser | validator-linja med P90 | **printes** ✔ | — |
| 5 — Forbedre, informert og bundet | avvisning → korrigert forslag | **ikke mulig** | **BYGG** |
| 5 — Forbedre, informert og bundet | avvisning → korrigert forslag | **bygget 7. aug** ✔ | — |
| 6 — Forkast eller foreslå | typet `outcome` | data finnes, printes ikke | `print` |
| 7 — Svar på tilbakemelding | persona-dom + fil-innboksen | dommen printes | `print` |
| 8 — Promoter godkjent kunnskap | promotert fil + index-lenke | **printes** ✔ | — |
@ -58,12 +58,20 @@ blir avvist og deretter korrigert.
## 3. Dagsplan
**Fredag 7. august — steg 5-sømmen (den ene kodejobben).**
**Fredag 7. august — steg 5-sømmen (den ene kodejobben). ✔ GJORT.**
Slipp avvisnings-historikken ut av `generate_via_llm` uten å endre løkkas tak (`max_attempts` +
`meter.tick_round` står urørt — «forbedre til god nok» uten tak er forbudt). Nytt skriptet
avvis-så-korriger-forløp. Ny load-bearing-test: RØD når sømmen kobles fra. Ligger først i uka
med vilje — det er den eneste jobben som kan overraske, og den har fem dagers slakk bak seg.
> **Utfall:** den åpne beslutningen ble **egen returtype**`generate_via_llm` returnerer
> `GenerationResult(outcome, refinements)`, og `RunResult.refinements` bærer den ut av kjøringen.
> En returverdi kan ikke bli stille tapt slik en out-parameter kan, og mypy tvinger hvert kallsted
> til å ta stilling. `refinements` bærer KUN avvisninger som faktisk ble matet tilbake (den siste
> avvisningen ved uttømt budsjett ER `outcome`). Simuleringens proposer overklager 250 000 NOK, som
> den deterministiske validatoren felt mot P90 = 90 000; det korrigerte forslaget på 30 000
> validerer. Fire mutasjoner målt røde mot hele suiten, med kontroll.
**Lørdag 8. søndag 9. august — presentasjonslaget.**
De fem `print`-tilleggene over, formet som én lesbar gjennomgang med steg-nummer i margen.
Ingen ny logikk. Målet er at en tilhører kan følge hvert steg uten at du forklarer hva de ser på.