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:
parent
cd011c4ac7
commit
d6f3359fae
11 changed files with 381 additions and 26 deletions
17
CLAUDE.md
17
CLAUDE.md
|
|
@ -112,6 +112,23 @@ Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To b
|
|||
her) — så koden påstår ikke mer enn den gjør. Load-bearing:
|
||||
`tests/test_step5_refine_loadbearing.py` blir rød når reason-injeksjonen detaches (utfallet
|
||||
flipper aldri + reason-verbatim-asserten faller); kontrollen beviser at løkka forblir bundet.
|
||||
- **Falsifiserings-historikken FORLATER generate-løkka som typet returverdi (Steg 5, del 2):**
|
||||
`generate_via_llm` returnerer `GenerationResult(outcome, refinements)` — ikke lenger bare
|
||||
`ValidatedProposal | Rejection`. Før dette forbrukte løkka hver `Rejection` internt (`last`) og
|
||||
DROPPET den, så Steg 5 var det ene av åtte steg uten observerbart utfall. **Returverdi, ikke
|
||||
out-parameter/callback:** en returnert verdi kan ikke bli stille tapt av en kaller som glemmer å
|
||||
sende en samler, og mypy tvinger hvert kallsted til å ta stilling. **`refinements` bærer KUN
|
||||
avvisninger som faktisk ble matet tilbake** i et senere forsøks prompt — ved uttømt budsjett ER
|
||||
den siste avvisningen `outcome`, den informerte ingenting, og å telle den med ville vært
|
||||
dobbeltføring (en «samle alt»-implementasjon består den positive testen og faller på kontrollen).
|
||||
Taket er URØRT: `max_attempts` + `meter.tick_round` står, og `last` driver fortsatt prompten alene
|
||||
(prompt-veksten er uendret). `run.py` akkumulerer på tvers av `_evaluate`-kallene, så
|
||||
`_evaluate_mandate` er urørt; `RunResult.refinements` er defaultet (`coverage`-presedensen), og
|
||||
med mandat er den KONKATENERT på tvers av tiltak, ikke nøklet per tiltak (uttalt ærlighets-grense).
|
||||
`scripted_factory` tar nå `str | reply_selector` per rolle, så simuleringens proposer korrigerer
|
||||
seg innholds-nøklet uten en andre scriptet kropp. Load-bearing MÅLT
|
||||
(`tests/test_step5_history_loadbearing.py`), fire mutasjoner: detach returneringen · samle-alt ·
|
||||
detach run-wiringen · reverter simuleringens proposer til konstant svar.
|
||||
- **Lang/async fil-løkke (Steg 7, målbilde §3/§7):** `run_project(verdict_dir=...)` er den lange
|
||||
tilbakemeldings-tidsskalaen — en ekspert/persona dropper en verdict-fil (vanlig JSON, RAW-laget
|
||||
per §10 R2) i en inbox-mappe ETTER en kjøring, og en separat, senere kjøring `load_verdicts_from_dir`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue