"""Versioned contracts shared by plans, trial artifacts, and analysis.""" from __future__ import annotations from collections.abc import Mapping, Sequence from typing import Any SCHEMA_VERSION = "1.0.0" SCHEMA_MAJOR = 1 STORAGE_FORMATS = { "plan": "json", "batch_manifest": "json", "trial_manifest": "json", "samples": "numpy-npz", "events": "json-lines", "trial_metrics": "json-lines", "paper_source_data": "csv", } class ContractError(ValueError): """Raised when an evidence artifact violates its declared contract.""" def require_schema(document: Mapping[str, Any], expected_kind: str) -> None: if not isinstance(document, Mapping): raise ContractError("document must be a mapping") if document.get("kind") != expected_kind: raise ContractError( f"expected kind {expected_kind!r}, got {document.get('kind')!r}" ) version = document.get("schema_version") if not isinstance(version, str): raise ContractError("schema_version must be a string") try: major = int(version.split(".", 1)[0]) except (TypeError, ValueError) as exc: raise ContractError(f"invalid schema_version {version!r}") from exc if major != SCHEMA_MAJOR: raise ContractError( f"unsupported schema major {major}; expected {SCHEMA_MAJOR}" ) def require_nonempty_string(value: Any, name: str) -> str: if not isinstance(value, str) or not value.strip(): raise ContractError(f"{name} must be a non-empty string") return value def require_sequence(value: Any, name: str) -> Sequence[Any]: if isinstance(value, (str, bytes)) or not isinstance(value, Sequence): raise ContractError(f"{name} must be a sequence") if not value: raise ContractError(f"{name} must not be empty") return value