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:
parent
2d44c5e224
commit
3cbea91a72
4 changed files with 69 additions and 14 deletions
|
|
@ -130,16 +130,16 @@ def _factory(
|
|||
|
||||
def factory(role: str) -> BaseChatClient:
|
||||
if role == explore.MANAGER_ROLE:
|
||||
return ScriptedChatClient(reply_selector=_manager_script(ledgers), role=role)
|
||||
return ScriptedChatClient(sink=sink, reply_selector=_manager_script(ledgers), role=role)
|
||||
if role == explore.HYPOTHESISER_ROLE:
|
||||
replies = list(hypothesiser)
|
||||
|
||||
def _hyp(_blob: str, _role: str) -> str:
|
||||
return replies.pop(0) if replies else "nothing further."
|
||||
|
||||
return ScriptedChatClient(reply_selector=_hyp, role=role)
|
||||
return ScriptedChatClient(sink=sink, reply_selector=_hyp, role=role)
|
||||
if role == explore.NAVIGATOR_ROLE:
|
||||
return ScriptedChatClient("NAVIGATOR: index read.", role=role)
|
||||
return ScriptedChatClient("NAVIGATOR: index read.", sink, role=role)
|
||||
return ScriptedChatClient(fallback, sink, role=role)
|
||||
|
||||
return factory
|
||||
|
|
@ -403,19 +403,22 @@ def test_explore_belongs_to_single_project_mode(tmp_path, capsys) -> None:
|
|||
|
||||
|
||||
@pytest.fixture()
|
||||
def _explored_main(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def _explored_main(monkeypatch: pytest.MonkeyPatch) -> list[str]:
|
||||
"""Inject the role-dispatching scripted factory into the seam ``main()`` resolves through.
|
||||
|
||||
``main()`` passes no ``client_factory``, and ``explore()`` imports ``run._default_factory``
|
||||
lazily at call time, so this ONE patch covers both the exploration and the pipeline it feeds —
|
||||
which is what makes the arm below end-to-end rather than a wiring spy.
|
||||
"""
|
||||
sink: list[str] = []
|
||||
factory = _factory(
|
||||
ledgers=[_ledger_json(satisfied=False), _ledger_json(satisfied=True)],
|
||||
hypothesiser=[_hypothesis_line(_LABEL, "the index says the fittings are old")],
|
||||
fallback=_ENERGY_REPLY,
|
||||
sink=sink,
|
||||
)
|
||||
monkeypatch.setattr("portfolio_optimiser.run._default_factory", lambda profile: factory)
|
||||
return sink
|
||||
|
||||
|
||||
def test_the_shaped_mandate_reaches_the_pipeline(tmp_path, capsys, _explored_main) -> None:
|
||||
|
|
@ -705,7 +708,6 @@ async def test_the_demo_scenario_lets_a_shaped_direction_reach_the_hypothesis(tm
|
|||
"""
|
||||
result = await simulation.simulate_exploration(str(_BUNDLE_DIR), str(tmp_path), max_rounds=3)
|
||||
|
||||
assert result.label_in_bundle is False, "the control the scenario refuses on"
|
||||
assert [a.label for a in result.exploration.mandate.approaches] == [result.label]
|
||||
assert result.label_in_generation_prompt, (
|
||||
"the shaped direction never reached the hypothesis prompt — the demo would show a mandate "
|
||||
|
|
@ -714,6 +716,31 @@ async def test_the_demo_scenario_lets_a_shaped_direction_reach_the_hypothesis(tm
|
|||
assert result.trace.ledger, "the exploration recorded no rounds"
|
||||
|
||||
|
||||
def test_an_outbox_without_a_run_id_is_refused_before_the_exploration_spends_anything(
|
||||
tmp_path, _explored_main
|
||||
) -> None:
|
||||
"""T16: an argv that cannot finish is refused BEFORE the loop costs anything.
|
||||
|
||||
``run_project`` refuses ``outbox_dir`` without ``run_id`` at its very first statement, which is
|
||||
early enough for every path that existed before U4. The exploration runs AHEAD of that call, so
|
||||
without this guard the run spends its whole exploration budget on model calls and only then
|
||||
refuses — and the artefact write is skipped too, so not even the evidence of what was spent
|
||||
survives. Exactly the hoist ``main()`` already performs twice ("an incomplete argv is refused
|
||||
BEFORE the honesty banner could claim a scripted run happened").
|
||||
|
||||
The assertion is that NO model call happened, not merely that rc is 1: a refusal that arrives
|
||||
after the spend looks identical at the exit code.
|
||||
|
||||
Detach point: drop the guard from the exploration block → RED.
|
||||
"""
|
||||
rc = run.main(_base_argv(tmp_path) + ["--outbox-dir", str(tmp_path / "outbox")])
|
||||
assert rc == 1
|
||||
assert not _explored_main, (
|
||||
"the exploration made model calls before the run was refused — the budget was spent on an "
|
||||
"argv that could never finish"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_direction_the_base_already_states_is_refused_as_vacuous(tmp_path) -> None:
|
||||
"""S2: a label the knowledge base ALREADY contains is refused, not demonstrated.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue