portfolio-optimiser-claude/tests/test_provenance_sdk_version_loadbearing.py
Kjell Tore Guttormsen f300c64b0e feat(run): stamp the drill's SDK build in the dry-run run-config [skip-docs]
The K8 drill captured a run-config that described the rig it rehearsed —
model ids, parameters, caps — without saying which SDK build would drive it.
The SDK's reported USD figure is computed against a price table frozen at build
time, so a rig record without the build is not traceable, and the drill exists
precisely to rig a future live run.

build_dry_run_config now takes the client the drill constructed and reads the
build from it, the same seam rule the provenance stamp follows: a drill driven
by the scripted stand-in stamps null rather than the installed version, because
reading the environment would describe a rig that never existed (§1).

Load-bearing (§11): the two new tests went RED before the change (no such key),
and the detach point is named in the class docstring — read importlib.metadata
instead of the client and the scripted drill claims a build it never used. The
existing dry-run tests assert individual keys rather than a key set, so the
additive field leaves them untouched, and byte-determinism still holds.

624 -> 627 passed, ruff + mypy --strict clean. README states the new field.
STATE post 2a, approved by the operator this session.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MQu2xxwedckjU56byu1aUG
2026-07-25 15:35:16 +02:00

208 lines
9.2 KiB
Python

"""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.
The same rule governs the K8 drill's run-config: it records the build of the
client the drill CONSTRUCTED (and never called), so the rehearsed rig is
traceable without ever claiming a build the drill did not use.
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 TestTheDrillStampsTheSameWay:
"""LOAD-BEARING (§1, §11): the K8 drill's run-config obeys the same seam rule.
The run-config is the comparison protocol's §4 pt 3 record of what a live
run WOULD carry — model ids, parameters, caps. Without the build id it
describes a rig whose SDK version is unknown, which is the one thing that
makes a reported USD figure traceable. It is read from the CLIENT the drill
constructed, exactly like the provenance stamp: the drill builds the client
before it stops, so the honest source is right there.
Detach point: stamp ``importlib.metadata`` (or drop the client argument and
hard-code a value) → the scripted drill claims a build it never used → RED.
"""
def _drill_runconfig(self, tmp_path: Path, *, sdk_version: str | None) -> dict[str, object]:
created: list[ScriptedClient] = []
def factory(contracts: Contracts, max_budget_usd_per_call: float) -> ModelClient:
# No replies: any model call would both record and raise, so the
# drill's zero-call promise still holds while this runs.
client = ScriptedClient(replies=[])
if sdk_version is not None:
client.sdk_version = sdk_version # type: ignore[attr-defined]
created.append(client)
return client
outbox = tmp_path / "outbox"
main(
[
"--bundle",
str(BUNDLE),
"--outbox",
str(outbox),
"--run-id",
"drill-sdk",
"--live-dry-run",
],
client_factory=factory,
)
(client,) = created
assert client.calls == [] # the drill still made no model call
payload: dict[str, object] = json.loads(
(outbox / "drill-sdk-runconfig.json").read_text(encoding="utf-8")
)
return payload
def test_a_drill_not_produced_by_the_sdk_stamps_no_build(self, tmp_path: Path) -> None:
payload = self._drill_runconfig(tmp_path, sdk_version=None)
assert payload["sdk_version"] is None
assert payload["sdk_version"] != importlib.metadata.version("claude-agent-sdk")
def test_the_drills_client_has_its_build_stamped_verbatim(self, tmp_path: Path) -> None:
payload = self._drill_runconfig(tmp_path, sdk_version=FIXTURE_BUILD)
assert payload["sdk_version"] == FIXTURE_BUILD
def test_the_stamp_does_not_disturb_the_rest_of_the_run_config(self, tmp_path: Path) -> None:
# The field is additive: §4 pt 3's existing content is unchanged, and the
# log still carries no wall-clock date (determinism).
payload = self._drill_runconfig(tmp_path, sdk_version=FIXTURE_BUILD)
assert payload["run_id"] == "drill-sdk"
assert payload["profile"] == "anthropic"
assert "date" not in payload
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"