feat(fase4): route the validator falsification into the next hypothesis (informed refinement)
Closes gap #5 (maalbilde §5/§7): generate_via_llm's outer max_attempts loop built the prompt ONCE and re-sent it identically — a BLIND retry. The validator's per-attempt Rejection.reason was captured in `last` but never reached the next prompt, so the proposer re-answered the same question with no knowledge of WHY the prior candidate failed. Step 5 routes that reason into the next attempt. - generate.py: _build_messages() gains prior_rejection; when set it appends a revision block carrying ONLY the falsification reason verbatim (never the rejected proposal JSON). None -> the byte-identical base prompt, so attempt 1 is unchanged. generate_via_llm() rebuilds messages inside the outer loop with prior_rejection=`last` (None on attempt 1); _fetch_parsed() takes messages as an explicit parameter. `last` is overwritten each round -> only the most-recent falsification ("forrige"), never an accumulated history. Bound unchanged: max_attempts + meter.tick_round (no new loop; §6 — "improve until good enough" without a ceiling stays impossible). - Scope honesty: the only per-attempt falsifier here is the validator. The checker is a run-level, one-shot signal (run.py, before generation); seeding generation with the checker critique is separately scoped and NOT done here. The boundary is written into the generate_via_llm docstring + README + CLAUDE. Load-bearing (maalbilde §7): tests/test_step5_refine_loadbearing.py is a PAIR — the positive test keys the proposer's flip on the validator REASON PAYLOAD (the rejected claim value, derived from validate_proposal(bad).reason so test and SUT share one source of truth), and asserts the reason reached attempt 2's prompt VERBATIM (the green-but-dead guard). It goes RED on detach (build messages once): the flip token never arrives, so the outcome never flips AND the verbatim assertion fails — proven double-red. The bounded control proves a never-fixed proposer exhausts exactly max_attempts and returns a Rejection. Adversarial Plan agent hardened the design pre-implementation (flip on payload not wrapper/call-count; derive flip-key from the validator reason; drive through generate_via_llm directly; docstring honesty). Suite 136->138 passed, 4 skipped; mypy + ruff check clean. New test ruff-formatted; pre-existing ruff-format drift (budget/verdicts/test_contracts) left untouched for a surgical diff. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MHR8iKxJRxDiDfNw8HZmWE
This commit is contained in:
parent
4ec778c855
commit
f7c81b45ec
4 changed files with 188 additions and 10 deletions
10
CLAUDE.md
10
CLAUDE.md
|
|
@ -46,6 +46,16 @@ Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To b
|
|||
aldri checkeren (de to falsifisererne blandes aldri). Load-bearing:
|
||||
`tests/test_checker_gate_loadbearing.py` blir rød ved BEGGE detach-punkt (revert `output_from`,
|
||||
eller fjern override). Checkeren «må faktisk gate, ELLER vi slutter å kalle det maker-checker».
|
||||
- **Informert forbedring, bundet (Steg 5, målbilde §5/§7):** `generate_via_llm`s ytre
|
||||
`max_attempts`-løkke er ikke lenger blind — validatorens *forrige* `Rejection.reason` mates inn i
|
||||
neste forsøks prompt (`_build_messages(prior_rejection=...)`), så proposeren korrigerer i stedet
|
||||
for å gjenta. Kun den mest-nylige falsifiseringen (`last`, ikke akkumulert), kun grunnen (aldri
|
||||
forrige proposal-JSON), under EKSISTERENDE tak (`meter.tick_round` + `max_attempts` — ingen ny
|
||||
løkke; «forbedre til god nok» uten tak er forbudt). Eneste *per-forsøk*-falsifiserer her er
|
||||
validatoren; å seede generering med checker-*kritikken* er run-nivå og separat scoped (IKKE bygget
|
||||
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.
|
||||
- **Kostnadsdisiplin:** utvikle primært på lokal profil (gratis); Foundry/Azure (privat tenant finnes) kun til målrettet, minimal verifisering; billigste modeller + små syntetiske data + harde token-tak. Ingen tunge test-kjøringer.
|
||||
- **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