test(fase3): SC1 new project via config-only + no-hardcoded-id src guard

This commit is contained in:
Kjell Tore Guttormsen 2026-06-26 12:13:44 +02:00
commit 0020776b26
3 changed files with 53 additions and 0 deletions

View file

@ -178,3 +178,36 @@ async def test_d_both_profiles_run_offline(
# Profile-dependent teeth (offline, no egress): each profile resolves its own model.
assert resolve_model(profile, "proposer")
assert resolve_model("local", "proposer") != resolve_model("azure", "proposer")
async def test_e_new_project_flows_through_via_config_only(
make_portfolio_client_factory, fresh_store
) -> None:
"""SC1: a brand-new project (SKOLE-VVS-OPPGR) added by CONFIG ONLY — a JSON entry + a bundled
docs folder, zero ``src/*.py`` change flows end-to-end through run_portfolio. Its id is not
in REPLIES, so the default reply (which omits project_id) inherits the new project's id via
``_parse_ir`` setdefault, proving the loader wired the config-only project through."""
result = await run_portfolio(
["SKOLE-VVS-OPPGR"],
"local",
store=fresh_store,
client_factory=make_portfolio_client_factory(REPLIES),
)
assert len(result.runs) == 1
assert result.runs[0].outcome.proposal.project_id == "SKOLE-VVS-OPPGR"
def test_f_no_hardcoded_project_ids_in_src() -> None:
"""SC1 load-bearing guard: reference-project ids live ONLY in the data JSON, never in code.
If a future project is onboarded via a code-side id->path/verdict mapping, this reddens
backing the 'config-only' claim. Pattern: test_budget.py:88-99 (src anti-pattern grep)."""
from pathlib import Path
ids = ("FV42-GSV-E1", "RV13-RAS-TP", "BRU-LAKS-REHAB", "SKOLE-VVS-OPPGR")
offenders = [
f"{py.name}: {pid}"
for py in Path("src/portfolio_optimiser").rglob("*.py")
for pid in ids
if pid in py.read_text(encoding="utf-8")
]
assert offenders == [], f"hardcoded project ids in src: {offenders}"