"""SDK build in the provenance stamp — LOAD-BEARING (§1, §9, §11). The seam this file keeps alive: a run's provenance records **which SDK build produced it**, and it takes that from the PRODUCING CLIENT, never from the environment. That distinction is the whole point. The SDK's reported ``total_cost_usd`` is a client-side estimate computed against a price table frozen when the SDK was built, so a cost figure is only traceable if the run says which build produced it. But a run driven by the scripted stand-in used no SDK at all — stamping the installed version there would attribute a build to a run that never touched it, which is exactly the fabrication §1 forbids. Detach proof: make the stamp read ``importlib.metadata`` instead of the client → a scripted run claims an SDK build it never used → red. Second guard: the S10 fasit predates this field and is a historical record of a run executed 2026-07-03. Retro-stamping it would invent provenance for a run whose SDK build we would be guessing. The fasit stays byte-frozen — red the moment someone back-fills it. """ from __future__ import annotations import importlib.metadata import json from pathlib import Path from typing import Callable import pytest from pydantic import ValidationError from _scripted import ScriptedClient, reply from portfolio_optimiser_claude.contracts import Contracts, ModelMapContract from portfolio_optimiser_claude.ir import load_validator_input from portfolio_optimiser_claude.loop import ModelClient from portfolio_optimiser_claude.provenance import Citation, Provenance from portfolio_optimiser_claude.run import main from portfolio_optimiser_claude.sdk_client import SdkModelClient REPO_ROOT = Path(__file__).resolve().parents[1] BUNDLE = REPO_ROOT / "shared" / "examples" / "bygg-energi-mikro" S10_PROVENANCE = REPO_ROOT / "runs" / "s10" / "provenance.json" ClientFactory = Callable[[Contracts, float], ModelClient] # A build id no installed package could ever report, so a test that sees it # knows the value came from the CLIENT and from nowhere else. FIXTURE_BUILD = "0.2.120-fixture-not-installed" def _scripted_factory(*, sdk_version: str | None) -> tuple[ClientFactory, list[ScriptedClient]]: created: list[ScriptedClient] = [] def factory(contracts: Contracts, max_budget_usd_per_call: float) -> ModelClient: client = ScriptedClient( replies=[ reply("debate reasoning"), reply("VERDICT: APPROVE"), reply(json.dumps(load_validator_input(BUNDLE).model_dump())), ] ) if sdk_version is not None: # Only a client that genuinely carries the attribute reports one. client.sdk_version = sdk_version # type: ignore[attr-defined] created.append(client) return client return factory, created def _run_and_read_provenance(tmp_path: Path, *, sdk_version: str | None) -> dict[str, object]: out = tmp_path / "out" factory, _ = _scripted_factory(sdk_version=sdk_version) code = main(["--bundle", str(BUNDLE), "--out", str(out)], client_factory=factory) assert code == 0 payload: dict[str, object] = json.loads((out / "provenance.json").read_text(encoding="utf-8")) return payload class TestTheStampComesFromTheClient: """LOAD-BEARING (§11): the producing client reports the build, or nobody does.""" def test_a_run_not_produced_by_the_sdk_stamps_no_build(self, tmp_path: Path) -> None: # Detach point: read importlib.metadata instead of the client → this # scripted run claims the installed build it never used → RED. payload = _run_and_read_provenance(tmp_path, sdk_version=None) assert payload["sdk_version"] is None assert payload["sdk_version"] != importlib.metadata.version("claude-agent-sdk") def test_a_producing_client_has_its_build_stamped_verbatim(self, tmp_path: Path) -> None: payload = _run_and_read_provenance(tmp_path, sdk_version=FIXTURE_BUILD) assert payload["sdk_version"] == FIXTURE_BUILD def test_the_sdk_client_reports_the_installed_build_offline(self) -> None: # Constructing the real client needs no key and touches no network # (the same premise test_sdk_isolation.py relies on), so the build id # it exposes is readable in the offline suite. client = SdkModelClient( ModelMapContract(profiles={"anthropic": {"default": "claude-haiku-4-5-20251001"}}) ) assert client.sdk_version == importlib.metadata.version("claude-agent-sdk") class TestTheStampStaysOptional: """The field is additive: every existing caller keeps validating unchanged.""" def test_provenance_validates_without_a_build(self) -> None: stamp = Provenance( citations=[Citation(file="index.md", span="chars 0-1", snippet="x")], model="claude-haiku-4-5-20251001", role="proposer", validator_decision="validated", tokens_used=10, ) assert stamp.sdk_version is None def test_a_blank_build_is_refused_rather_than_stored(self) -> None: # An empty string would read as "no SDK" while occupying the field — # null is the one way to say "not produced by the SDK" (§1). with pytest.raises(ValidationError): Provenance( citations=[Citation(file="index.md", span="chars 0-1", snippet="x")], model="m", role="proposer", validator_decision="validated", tokens_used=10, sdk_version="", ) class TestTheFasitIsNotRetroStamped: """LOAD-BEARING (§1): the historical record is never back-filled.""" def test_the_s10_provenance_carries_no_sdk_build(self) -> None: # runs/s10/ is the byte-frozen record of the ONE live run (2026-07-03), # executed before this field existed. Adding a build id to it now would # be a guess presented as provenance. RED if someone back-fills it. payload = json.loads(S10_PROVENANCE.read_text(encoding="utf-8")) assert "sdk_version" not in payload assert payload["model"] == "claude-haiku-4-5-20251001"