fix(major2): --proposal-review komponerer med --resume, og armen som beviser det
To funn, ETT commit, fordi de deler vitnet ved konstruksjon: 02159d21 (run.py:2738, PLAN_EXECUTE_DRIFT) er vakten, da485928 (tests/...:1344, MISSING_TEST) er armen som skulle sett den. AA dele dem ville krevd en kastbar duplikattest. VAKTEN: `if args.checkpoint_dir is not None` nektet --proposal-review for HVER argv med en checkpoint-katalog - men --resume KREVER --checkpoint-dir (run.py:2776), saa komposisjonen nekten selv anbefaler («pass --proposal-review at --resume instead») var unaabar, og run.py:2218-helpen, README.md:546 og MAJOR-2-raden beskrev en sti ingen argv kunne ta. Vakten nekter naa en PARK (en etappe som returnerer foer noen kandidat finnes), aldri et LOEFT. ARMEN: `test_the_door_composes_with_resume` sendte hverken --resume, --checkpoint-dir eller --review-inbox - den var en vanlig enkeltkjoering T13 allerede dekket, altsaa groenn mot nettopp den defekten den var navngitt for. Den driver naa en EKTE resume: dag 1 parkerer en ekte plan-review gjennom run.main, ekspertens svar legges i en ekte innboks, og dag N sender --resume ... --checkpoint-dir ... --review-inbox ... --proposal-review med run_project innspilt og _refuse_model som kontroll paa null modellkall. MAALT, i denne rekkefoelgen (Iron Law): armen skrevet FOERST og kjoert mot uendret vakt -> ROED med nettopp nektlinja i stderr («pass --proposal-review at --resume instead»), calls == []. Etter vakt-fiksen: 49 passed i fila, og park-nekten (test_the_door_and_a_parked_exploration_contradict, M39) staar groenn - den sender --explore uten --resume. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9ed458c0ba
commit
c81a90c88a
2 changed files with 130 additions and 11 deletions
|
|
@ -2735,7 +2735,12 @@ def main(argv: list[str] | None = None) -> int:
|
|||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
if args.checkpoint_dir is not None:
|
||||
# ``and args.resume is None`` is load-bearing, not defensive: --resume REQUIRES
|
||||
# --checkpoint-dir (:2776 below), so a bare --checkpoint-dir test refused the very
|
||||
# composition this message recommends, and the help text, README and the invariant row all
|
||||
# described a path no argv could take. What is being refused is a PARK (a leg that returns
|
||||
# before any candidate exists), never a LIFT (a leg that runs the pipeline to a candidate).
|
||||
if args.checkpoint_dir is not None and args.resume is None:
|
||||
print(
|
||||
"run refused: --proposal-review and --checkpoint-dir: a parked exploration "
|
||||
"returns before any candidate exists, so the review would never be asked — pass "
|
||||
|
|
|
|||
|
|
@ -1325,14 +1325,124 @@ def test_the_door_and_a_parked_exploration_contradict(
|
|||
assert "--resume" in err
|
||||
|
||||
|
||||
def test_the_door_composes_with_resume(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""A3, VERIFIED rather than deferred: the resume block yields the parked exploration's mandate
|
||||
and falls through to the SAME full-run dispatch, so the reviewer built at the CLI is reached.
|
||||
Detach point: refusing ``--resume`` together with the door, or forgetting to pass the reviewer
|
||||
on that path.
|
||||
#: Day 1's parked exploration, driven exactly as an operator drives it: a real ``--explore`` leg
|
||||
#: with ``enable_plan_review`` armed and NO reviewer at the terminal, so the loop parks. The
|
||||
#: proposal-review door is deliberately absent here — that argv is the refusal this arm's sibling
|
||||
#: (``…and_a_parked_exploration_contradict``) keeps green.
|
||||
_RESUME_RUN_ID = "proposal-review-resume"
|
||||
|
||||
_RESUME_MANAGER_REPLY = json.dumps(
|
||||
{
|
||||
"is_request_satisfied": {"reason": "r", "answer": True},
|
||||
"is_in_loop": {"reason": "r", "answer": False},
|
||||
"is_progress_being_made": {"reason": "r", "answer": True},
|
||||
"next_speaker": {"reason": "r", "answer": "hypothesiser"},
|
||||
"instruction_or_question": {"reason": "r", "answer": "go"},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _resume_replies_file(tmp_path: Path) -> str:
|
||||
"""Both time-scales' roles in one file: the exploration's three and the debate's two. A
|
||||
missing ``navigator`` key is the ``KeyError`` M40 of økt 64 — the resume leg builds an
|
||||
exploration too, so it needs the same roster the park leg did."""
|
||||
path = tmp_path / "resume-replies.json"
|
||||
path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"proposer": _run_reply(_CLI_MEASURE, 30_000),
|
||||
"checker": "VERDICT: APPROVE",
|
||||
"manager": _RESUME_MANAGER_REPLY,
|
||||
"navigator": "NAVIGATOR: read the index.",
|
||||
"hypothesiser": "HYPOTHESIS: "
|
||||
+ json.dumps({"label": "Night setback", "rationale": "y"}),
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return str(path)
|
||||
|
||||
|
||||
def _resume_config_file(tmp_path: Path) -> str:
|
||||
path = tmp_path / "resume-exploration.json"
|
||||
path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"max_rounds": 4,
|
||||
"max_tokens": 200_000,
|
||||
"max_stall_count": 2,
|
||||
"max_reset_count": 1,
|
||||
"max_plan_revisions": 2,
|
||||
"enable_plan_review": True,
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return str(path)
|
||||
|
||||
|
||||
def _park_then_answer(tmp_path: Path) -> None:
|
||||
"""Day 1 and the days between: park a real plan review, then drop the expert's answer in the
|
||||
inbox. Both halves go through the shipped surfaces — a hand-written question file would test
|
||||
the fixture, not the door."""
|
||||
outbox = tmp_path / "outbox"
|
||||
assert (
|
||||
run.main(
|
||||
[
|
||||
_RUN_PID,
|
||||
"--docs-dir",
|
||||
str(_BUNDLE_DIR),
|
||||
"--bundle-dir",
|
||||
str(_BUNDLE_DIR),
|
||||
"--explore",
|
||||
"Find the cheapest saving.",
|
||||
"--explore-config",
|
||||
_resume_config_file(tmp_path),
|
||||
"--scripted-replies",
|
||||
_resume_replies_file(tmp_path),
|
||||
"--outbox-dir",
|
||||
str(outbox),
|
||||
"--checkpoint-dir",
|
||||
str(tmp_path / "checkpoints"),
|
||||
"--run-id",
|
||||
_RESUME_RUN_ID,
|
||||
]
|
||||
)
|
||||
== 0
|
||||
)
|
||||
question = json.loads(
|
||||
(outbox / f"{_RESUME_RUN_ID}-plan-review.json").read_text(encoding="utf-8")
|
||||
)
|
||||
inbox = tmp_path / "review-inbox"
|
||||
inbox.mkdir(parents=True, exist_ok=True)
|
||||
(inbox / f"{_RESUME_RUN_ID}-plan-review-answer.json").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"run_id": _RESUME_RUN_ID,
|
||||
"request_id": question["request_id"],
|
||||
"decision": "approve",
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
|
||||
def test_the_door_composes_with_resume(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""A3, and the WITNESS the review found missing: the ``--checkpoint-dir`` refusal points the
|
||||
operator at ``--resume``, and ``--resume`` itself REQUIRES ``--checkpoint-dir`` — so before
|
||||
this arm the recommended composition was refused by the very message that recommended it, and
|
||||
nothing in the suite could see it. Detach point: reverting the guard to a bare
|
||||
``if args.checkpoint_dir is not None``.
|
||||
|
||||
The argv is a REAL resume: day 1 parks a real plan review through ``run.main``, the expert's
|
||||
answer is dropped in a real inbox, and day N passes ``--resume … --checkpoint-dir …
|
||||
--review-inbox … --proposal-review``. The arm it replaced sent none of those three flags and
|
||||
was a plain single-project run T13 already covered — green against the defect it was named
|
||||
for. ``run_project`` is a recorder, so what is measured is the WIRING at the fall-through, and
|
||||
``_refuse_model`` proves the recorded call is the ONLY place a model would have been reached
|
||||
from."""
|
||||
_park_then_answer(tmp_path)
|
||||
|
||||
``run_project`` is replaced by a recorder, so the arm measures the WIRING rather than a whole
|
||||
resumed exploration."""
|
||||
calls: list[dict[str, Any]] = []
|
||||
|
||||
async def _recorder(*args: Any, **kwargs: Any) -> Any:
|
||||
|
|
@ -1349,15 +1459,19 @@ def test_the_door_composes_with_resume(tmp_path: Path, monkeypatch: pytest.Monke
|
|||
"--bundle-dir",
|
||||
str(_BUNDLE_DIR),
|
||||
"--scripted-replies",
|
||||
_cli_replies_file(tmp_path),
|
||||
_resume_replies_file(tmp_path),
|
||||
"--outbox-dir",
|
||||
str(tmp_path / "outbox"),
|
||||
"--run-id",
|
||||
_RUN_ID,
|
||||
"--checkpoint-dir",
|
||||
str(tmp_path / "checkpoints"),
|
||||
"--review-inbox",
|
||||
str(tmp_path / "review-inbox"),
|
||||
"--resume",
|
||||
_RESUME_RUN_ID,
|
||||
"--proposal-review",
|
||||
]
|
||||
)
|
||||
assert len(calls) == 1
|
||||
assert len(calls) == 1, "the resume must fall through to the full-run dispatch, not be refused"
|
||||
assert calls[0]["proposal_reviewer"] is not None
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue