"""Step 12 smoke — run_project composes the slice end-to-end on an injected FakeChatClient. Returns a ValidatedProposal with a populated first-class ProvenanceStamp. Pattern: tests/test_smoke.py. """ from spikes._harness import FakeChatClient from portfolio_optimiser.provenance import ProvenanceStamp from portfolio_optimiser.run import run_project from portfolio_optimiser.validator import ValidatedProposal _VALID = ( '{"project_id":"KONTOR-IT-E1","measure":"Reduce scope",' '"affected_items":[{"code":"05.2","quantity":4300,"unit_cost":215},' '{"code":"03.1","quantity":1800,"unit_cost":310}],"claimed_saving_nok":200000}' ) async def test_run_project_smoke(tmp_path) -> None: docs = tmp_path / "docs" docs.mkdir() (docs / "cost.txt").write_text( "Licence unit price renegotiation reduced the office-suite cost for the head office.", encoding="utf-8", ) def factory(role: str) -> FakeChatClient: return FakeChatClient(default_reply=_VALID) result = await run_project( "KONTOR-IT-E1", "local", docs_dir=str(docs), verdict_input={"decision": "approved", "rationale": "feasible within range"}, client_factory=factory, ) assert isinstance(result.outcome, ValidatedProposal) assert isinstance(result.provenance, ProvenanceStamp) assert len(result.provenance.citations) >= 1