test(fase3): SC3 load-bearing meter-isolation detach guard

This commit is contained in:
Kjell Tore Guttormsen 2026-06-26 12:07:28 +02:00
commit 66065053b1

View file

@ -12,7 +12,7 @@ scanning the prompt for its id, so one production-shaped factory serves the whol
import pytest
from portfolio_optimiser.run import PortfolioResult, RunResult, run_portfolio
from portfolio_optimiser.run import PortfolioResult, RunResult, run_portfolio, run_project
# The synthetic reply IS the proposal: generate._parse_ir builds affected_items (each with its
# own quantity/unit_cost) straight from this JSON, and the validator's P90 = 0.30 x Σ(qty·unit_cost)
@ -105,3 +105,48 @@ async def test_b_shared_store_accumulates_and_surfaces_prior_verdict(
assert len(set(ids)) == 3 # pairwise distinct minted ids (no collision)
# BRU surfaces FV42 (the structural match), ranked above the decoy.
assert result.runs[2].retrieved[0].id == result.runs[0].verdict.id
async def test_c_execution_state_isolation_is_load_bearing(
make_client_factory, fresh_store
) -> None:
"""SC3 (cap-independent automatic detach guard): each project's execution state (the budget
meter) is built FRESH per run, so per-project token_usage is its OWN only. Built on the
Step-1 ``meter=`` seam + Step-3 ``meter_factory``. The factory emits a UNIFORM but VALID
proposal (REPLIES["FV42-GSV-E1"] for every call) so both projects complete a bare
unparseable default would loop the generate fetch to BudgetExceeded instead. Both arms run
every CI, so the detach is encoded automatically (no manual reviewer-revert)."""
from portfolio_optimiser.budget import Budget, TokenMeter
from portfolio_optimiser.reference_domain import load_reference_projects
f = make_client_factory(REPLIES["FV42-GSV-E1"])
rv13 = {p.id: p for p in load_reference_projects()}["RV13-RAS-TP"]
# 1. Baseline: RV13 run standalone (its own fresh meter).
standalone = await run_project(
"RV13-RAS-TP",
"local",
docs_dir=rv13.docs_dir,
verdict_input=rv13.verdict_input,
client_factory=f,
)
# 2. Isolated (default, no meter_factory): RV13 as project 1 in the portfolio. Its usage
# equals the standalone baseline — independent of project 0. THE load-bearing assertion:
# if run_portfolio shared a meter by default, runs[1] would be cumulative and this breaks.
iso = await run_portfolio(
["FV42-GSV-E1", "RV13-RAS-TP"],
"local",
store=fresh_store,
client_factory=f,
)
assert iso.runs[1].provenance.token_usage == standalone.provenance.token_usage
# 3. Shared (injected one meter across both): usage accumulates, proving the detach is real
# (and that the == arm above would redden under sharing).
shared = TokenMeter(Budget(max_tokens=1_000_000, max_rounds=1000))
sh = await run_portfolio(
["FV42-GSV-E1", "RV13-RAS-TP"],
"local",
client_factory=f,
meter_factory=lambda: shared,
)
assert sh.runs[1].provenance.token_usage > sh.runs[0].provenance.token_usage