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
208 lines
9.2 KiB
Python
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"
|