fix(explore): utforskningen skal ikke brenne budsjettet paa en argv som ikke kan fullfoere (ORDRE 20260823T204216Z)

Tre review-funn fra oerkt 57, alle handtert.

1. DEFEKT, funnet i review og REPRODUSERT foer fiks: --explore --outbox-dir uten
   --run-id kjoerte HELE utforskningen og ble deretter nektet av run_project, som
   eier outbox-kontrakten og nekter paa sin FOERSTE setning - tidlig nok for enhver
   sti som fantes foer U4, men utforskningen kjoerer FORAN det kallet. Artefakt-
   skrivingen hoppet ogsaa over (den krever begge), saa ikke engang regnskapet over
   hva som ble brukt overlevde. Fiksen er en HOIST i utforskningsblokka, ikke en
   andre kopi av regelen - samme hoist main() alt gjoer for de paakrevde argumentene,
   av samme grunn. Testen asserterer at INGEN modellkall skjedde, ikke bare at rc er
   1: ved exit-koden ser en nekt etter forbruket identisk ut.

2. VAKUOES ASSERT FJERNET (repoets egen klasse, snudd innover): scenarioets
   label_in_bundle ble beregnet av den SAMME variabelen vakten raiser paa, saa feltet
   kunne strukturelt kun vaere False og assertet kunne ikke feile mot noen
   implementasjon - mens docstringen kalte det en kausalitetskontroll «akkurat som
   marker_in_run_a_prompt». Feltet og assertet er borte; vakten ER kontrollen, og en
   alltid-sann gjentakelse av den ville bare gjort den ekte lettere aa avfeie.

3. MAALINGS-PAASTANDEN PRESISERT: M10 (fjern --explore fra portefoelje-partisjonen)
   ble re-maalt mot HELE suiten etter test-fiksen - foer sto den kun maalt med -k.
   Invarianten sa «seksten mutasjoner mot HELE suiten + groenn kontroll 998/5» og
   slo dermed sammen tre ulike kontroller; den oppgir naa alle fire (990/5, 996/5,
   998/5, 999/5). En paastand om egen maaling som er upresis om sin egen nevner er
   premiss-vs-faktum-regelen vendt innover.

Pluss en uttalt aerlighets-grense i invarianten: den HOSTEDE flaten gir ingen innsyn
i hva som formet mandatet (ingen outbox, intet utforskningsfelt i _response_payload).
Bevisst scope-grense, men uttalt, fordi flatens hele argument er at svaret er
etterproevbart.

Sytten mutasjoner totalt, alle roede mot HELE suiten. 999 passed / 5 skipped.
Golden-transkriptet byte-uendret (ea8c534773acdbe41ae68f2c55724d69aaf8be4f).
mypy + ruff rene.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YRZhBJcxqTcqWyMW6hBttx
This commit is contained in:
Kjell Tore Guttormsen 2026-08-25 09:58:28 +02:00
commit 3cbea91a72
4 changed files with 69 additions and 14 deletions

View file

@ -1767,6 +1767,20 @@ def main(argv: list[str] | None = None) -> int:
file=sys.stderr,
)
return 1
if args.outbox_dir and not args.run_id:
# A HOIST, not a second copy of the rule: ``run_project`` owns the outbox contract and
# refuses on its first statement, which is early enough for every path that existed
# before U4. The exploration runs AHEAD of that call, so without this the whole
# exploration budget is spent on model calls and only THEN refused — and the artefact
# write is skipped as well, so not even the record of what was spent survives. The same
# hoist ``main()`` performs for the required-args guard, for the same reason.
print(
"run refused: --outbox-dir requires --run-id, and with --explore that has to be "
"settled BEFORE the exploration runs (otherwise the loop spends its whole budget "
"on an argv that cannot finish)",
file=sys.stderr,
)
return 1
exploration_contract: ExplorationContract | None = None
if args.explore_config is not None:

View file

@ -738,15 +738,16 @@ def scripted_exploration_factory(
class ExplorationSimulationResult:
"""The trace of one U4 walkthrough: what the loop shaped, and whether the pipeline used it.
``label_in_bundle`` is the causality control carried in the result, exactly as
``marker_in_run_a_prompt`` is: without it, a label the base already states would look like a
shaped direction and the whole scenario would prove nothing."""
There is deliberately NO ``label_in_bundle`` field. The vacuity guard below raises before a
result exists, so such a field could only ever be ``False`` an assertion on it would be green
against every implementation, which is the class this scenario's guard exists to prevent. The
guard IS the control; a second, always-true restatement of it would only make the real one
easier to discount."""
exploration: ExplorationResult
trace: ExplorationTrace
run: RunResult
label: str
label_in_bundle: bool
label_in_generation_prompt: bool
generation_prompts: list[str]
@ -828,7 +829,6 @@ async def simulate_exploration(
trace=trace,
run=run,
label=label,
label_in_bundle=label in context,
label_in_generation_prompt=any(label in p for p in prompts),
generation_prompts=prompts,
)