Skip to content
Closed
30 changes: 24 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ fully before making changes. In particular it defines:
deployment concerns. The hosted runtime must not be recreated under
`services/assessment_runtime` in this repository.

## Runtime Contract

The following block is machine-checked against package metadata and the shipped
backend-ownership policy. Keep it as one exact TOML block rather than replacing
it with an equivalent prose-only claim.

<!-- BEGIN fast-mlsirm-runtime-contract -->
```toml
[runtime_contract]
requires_python = ">=3.12"
auto_backend = "rust_required"
numpy_role = "reference_parity_only"
```
<!-- END fast-mlsirm-runtime-contract -->

## Common Commands

### Setup
Expand All @@ -35,9 +50,10 @@ toolchain should be on `PATH` (`cargo`/`rustc`) for deterministic local builds.
If cargo is absent, maturin may try to provision a temporary Rust toolchain via
`puccinialin`; set `MATURIN_NO_INSTALL_RUST=1` when you need a fail-fast
offline/proxy-safe build. A proxy or certificate error in that fallback is not
proof of a Python/PyO3 incompatibility. `pyproject.toml` declares Python
`>=3.10`; required CI currently builds and tests CPython 3.12, so broader
interpreter claims need matching build/import/full-suite CI evidence.
proof of a Python/PyO3 incompatibility. `pyproject.toml` declares
`requires-python = ">=3.12"`, matching the required CPython 3.12 and 3.14 CI
matrix. Broader interpreter claims need matching build/import/full-suite CI
evidence.

```bash
python -m pip install -e . # builds fast_mlsirm._core via maturin
Expand Down Expand Up @@ -145,9 +161,11 @@ examples/enterprise_demo/ Synthetic procurement evidence manifests
PyO3/numpy. maturin (configured in `pyproject.toml`) compiles the extension
into `fast_mlsirm._core` during install.
- The **backend axis is `{numpy, rust, auto}`** (default `auto`), resolved in
`python/fast_mlsirm/backend.py`: Rust when `_core` imports, otherwise the
numerically-identical NumPy reference in `python/fast_mlsirm/objective.py`
and `math.py`, which is kept for parity testing and fallback.
`python/fast_mlsirm/backend.py`: explicit `numpy` is the reference/parity
choice, explicit `rust` requires the compiled core, and production-convenience
`auto` resolves to Rust when `_core` imports. `auto` fails closed when the
compiled Rust core is unavailable; automatic resolution never silently
changes the numerical owner to NumPy.
- **GPU is a device sub-option of the Rust backend**, not a separate backend:
`FitConfig(backend="rust", rust_device={auto,cpu,gpu})`. The wgpu kernels in
`crates/mlsirm-core/src/gpu.rs` run in f32 and fall back to the f64 scalar
Expand Down
57 changes: 57 additions & 0 deletions tests/test_claude_runtime_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Prevent canonical agent guidance from drifting from shipped runtime policy."""

from __future__ import annotations

from pathlib import Path
import re
import tomllib


ROOT = Path(__file__).resolve().parents[1]
_RUNTIME_CONTRACT_START = "<!-- BEGIN fast-mlsirm-runtime-contract -->"
_RUNTIME_CONTRACT_END = "<!-- END fast-mlsirm-runtime-contract -->"


def _runtime_contract(guidance: str) -> dict[str, str]:
"""Return the single machine-readable runtime contract from agent guidance."""
assert guidance.count(_RUNTIME_CONTRACT_START) == 1
assert guidance.count(_RUNTIME_CONTRACT_END) == 1
payload = guidance.split(_RUNTIME_CONTRACT_START, 1)[1].split(
_RUNTIME_CONTRACT_END, 1
)[0]
match = re.fullmatch(r"\s*```toml\s*(.*?)\s*```\s*", payload, re.DOTALL)
assert match is not None
contract = tomllib.loads(match.group(1))["runtime_contract"]
assert all(type(value) is str for value in contract.values())
return contract


def test_claude_machine_runtime_contract_matches_shipped_policy() -> None:
"""Canonical machine guidance must pin package and backend ownership policy."""
project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))
guidance = (ROOT / "CLAUDE.md").read_text(encoding="utf-8")

assert _runtime_contract(guidance) == {
"requires_python": project["project"]["requires-python"],
"auto_backend": "rust_required",
"numpy_role": "reference_parity_only",
}


def test_claude_python_floor_matches_package_metadata() -> None:
"""Agent guidance must advertise the exact supported Python floor."""
project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))
requires_python = project["project"]["requires-python"]
guidance = (ROOT / "CLAUDE.md").read_text(encoding="utf-8")

assert f'`requires-python = "{requires_python}"`' in guidance
assert "`>=3.10`" not in guidance


def test_claude_auto_backend_matches_fail_closed_runtime() -> None:
"""Canonical guidance must not advertise a silent NumPy production fallback."""
guidance = (ROOT / "CLAUDE.md").read_text(encoding="utf-8")
normalized = " ".join(guidance.split())

assert "`auto` fails closed when the compiled Rust core is unavailable" in normalized
assert "otherwise the numerically-identical NumPy reference" not in normalized
Loading