feat(major2): run_mandate_across_bundles threads one reviewer; run_portfolio takes none [skip-docs]

Ordre 20260904T173146Z-8102814273-from-portfolio-optimiser, steg 8 av 10.

Dispatcheren faar proposal_reviewer og videresender den til hver per-base run_project.
EN gjenstand, aldri en kopi per base: dispatchen er SEKVENSIELL, saa en terminal-reviewer
komponerer. Assertert med `is`, ikke `==` - en fersk reviewer per base ville vaert en annen
gjenstand med identisk oppfoersel, som `==` paa en vanlig callable ikke kan skille (samme
identitets-leksjon test_multibase_loadbearings store-arm ble rettet til).

Doera faar sitt EGET vitne (S7a-3-regelen: hver doer som aapner en base faar sin egen
mutasjon, fordi en uvitnet kopi kan regrere alene).

run_portfolio faar INGENTING - samtidige boelger deler en terminal, som er --portfolio-
partisjonens egen grunn - og fravaeret er ASSERTERT, saa en senere "symmetri"-endring er en
roed test og ikke en stille utvidelse.

RODT foer impl: T22 (TypeError paa ukjent keyword).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-05 07:10:31 +02:00
commit ee7da3bb94
2 changed files with 53 additions and 0 deletions

View file

@ -1844,6 +1844,12 @@ async def run_mandate_across_bundles(
max_tokens: int = _DEFAULT_MAX_TOKENS,
top_k: int = 3,
portfolio_meter: PortfolioMeter | None = None,
#: MAJOR-2, threaded unchanged into every per-base ``run_project``. ONE object, never a copy
#: per base: the dispatch is SEQUENTIAL, so a single terminal reviewer composes. Which base is
#: being asked about is visible to the expert because the request carries the approach label
#: AND ``project_id`` — each base's own, read by ``_project_from_bundle`` — so bases can be
#: told apart even when a multi-base commission reuses approach ids.
proposal_reviewer: ProposalReviewer | None = None,
) -> MultiBaseResult:
"""Evaluate ONE commission across SEVERAL knowledge bases — the multi-base dispatch (§ C.7).
@ -1976,6 +1982,7 @@ async def run_mandate_across_bundles(
top_k=top_k,
mandate=sub_mandate,
meter=_run_meter(None, portfolio_meter, max_rounds),
proposal_reviewer=proposal_reviewer,
),
)
# D2, dispatcher-side accounting. The condition is the dispatcher's OWN map and nothing

View file

@ -1455,3 +1455,49 @@ def test_the_refused_name_enters_neither_half_of_the_whitelist() -> None:
assert set(hosting._REFUSED_BY_NAME).isdisjoint(inspect.signature(run_project).parameters)
# ...and the parameter it corresponds to is a real one, so the refusal names a door that exists.
assert "proposal_reviewer" in inspect.signature(run_project).parameters
async def test_t22_the_dispatcher_threads_one_reviewer_into_every_base(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""T22 — the multi-base dispatcher gets its OWN witness (the S7a-3 rule: every door that opens
a base gets its own mutation, because an unwitnessed copy can regress alone). Detach point:
the dispatcher stops threading it (M36).
ONE object is threaded, asserted with ``is`` and not ``==``: the dispatch is SEQUENTIAL, so a
single terminal reviewer composes and a fresh reviewer per base would be a different object
with identical behaviour, which ``==`` on a plain callable cannot tell apart (the identity
lesson ``test_multibase_loadbearing``'s store arm was corrected into).
The signature arm is paired with it for the Fase-4e reason: a ``**kwargs`` recorder cannot see
a name ``run_project`` does not actually take."""
calls: list[dict[str, Any]] = []
async def _recorder(project_id: str, profile: Any = "local", **kwargs: Any) -> Any:
calls.append({"project_id": project_id, **kwargs})
raise RuntimeError("recorded")
reviewer = _RunReviewer()
monkeypatch.setattr(run, "run_project", _recorder)
with pytest.raises(RuntimeError):
await run.run_mandate_across_bundles(
Mandate(
objective="o",
approaches=(
Approach(id="a", label="A", bundle_id="tunnel-hauglia"),
Approach(id="b", label="B", bundle_id="veglys-fv-soer"),
),
),
(str(_EXAMPLES / "tunnel-hauglia"), str(_EXAMPLES / "veglys-fv-soer")),
proposal_reviewer=reviewer,
)
assert calls, "the dispatcher must have reached run_project at least once"
assert all(c["proposal_reviewer"] is reviewer for c in calls)
assert "proposal_reviewer" in inspect.signature(run_project).parameters
def test_run_portfolio_takes_no_reviewer() -> None:
"""The ABSENCE arm (brief § Non-Goals). Concurrent portfolio waves share one terminal, which
is the ``--portfolio`` partition's own reason — so a later "symmetry" edit must be a RED test,
not a silent widening."""
assert "proposal_reviewer" not in inspect.signature(run.run_portfolio).parameters