"""Unit tests for kernel loading and version semantics.""" from __future__ import annotations from pathlib import Path import pytest from fable_selfplay.kernel import load_kernel REPO_ROOT = Path(__file__).resolve().parents[2] KERNEL_V01 = REPO_ROOT / "kernel" / "kernel-v0.1.yaml" KERNEL_V02 = REPO_ROOT / "kernel" / "kernel-v0.2.yaml" def test_load_kernel_v01(): kernel = load_kernel(KERNEL_V01) assert kernel.version.startswith("0.1") def test_load_kernel_v02(): kernel = load_kernel(KERNEL_V02) assert kernel.version.startswith("0.2") def test_versions_are_distinct(): assert load_kernel(KERNEL_V01).version != load_kernel(KERNEL_V02).version def test_kernel_exposes_governance_parameters(): """The legality gate must read thresholds from the kernel, not from code. Both kernel versions must therefore expose a non-empty parameter mapping; a kernel with no parameters would mean the rules live in Python, which breaks the entire replay-under-different-text mechanism. """ for path in (KERNEL_V01, KERNEL_V02): kernel = load_kernel(path) assert isinstance(kernel.params, dict) assert kernel.params, f"{path.name} exposes no governance parameters" def test_v02_params_differ_from_v01(): """v0.2 was driven by failing regression tests; if its effective parameters are identical to v0.1's, the amendments are cosmetic and the six closed exploits would still reproduce.""" p1 = load_kernel(KERNEL_V01).params p2 = load_kernel(KERNEL_V02).params assert p1 != p2 def test_missing_kernel_file_raises(): with pytest.raises((FileNotFoundError, OSError)): load_kernel(REPO_ROOT / "kernel" / "kernel-v9.9.yaml")