Files
rune/tests/test_ms_loader_seam.py
T
Nick a2bbaa5489
Auto-version and Release / release (push) Successful in 28s
CI Pipeline / lint (push) Failing after 48s
CI Pipeline / go-surface (push) Failing after 25s
CI Pipeline / rust-surface (push) Failing after 14s
CI Pipeline / best-practices (push) Successful in 14s
CI Pipeline / documentation (push) Successful in 11s
CI Pipeline / canary (push) Failing after 1m23s
CI Pipeline / gitea-offline (push) Successful in 22s
CI Pipeline / type-check (push) Failing after 49s
CI Pipeline / unit-tests (push) Failing after 12m27s
deploy / deploy (push) Failing after 15m42s
CI Pipeline / required-checks (push) Failing after 3s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Failing after 15s
test(seam): ms_loader batch 130 — 13-symbol memory_scoring seam contract (#2479, contract BUILDER-2026-10-09T19:04:00Z-7732d2)
Dichotomy verdict: RUST kernel, PYTHON seam (mirrors batch-127 pattern).
Audit proved live: all 13 wrappers resolve; missing lib raises
MemoryScoringUnavailable (FileNotFoundError — callers fall back);
kernel !ok raises RuntimeError naming the symbol; null envelope is
{ok:false}; the ratio ladder pinned (washable 0.5/0.25/0.1 at 0/10/20,
established 0.2, rock 0).

Parity: oracle-first. 5/5 green. Improvements: parity-only — the seam
is verified sound; future symbol changes fail loudly.
2026-10-09 20:06:37 +01:00

84 lines
3.0 KiB
Python

"""test_ms_loader_seam.py — batch 130: the ms_loader seam contract.
Mirrors the cc_loader batch-127 pattern for the memory_scoring seam.
Pins what the audit proved live:
1. all 13 symbols resolve in the built .so (no phantom wrappers);
2. missing lib raises MemoryScoringUnavailable (a FileNotFoundError —
callers fall back; never ImportError, never silence);
3. kernel !ok raises RuntimeError naming the symbol
(ms_compress_text without ratio -> "arg.ratio required");
4. the null-pointer envelope is {ok:false} (kernel never crashes Python);
5. the compression-ratio ladder (washable 0.5/0.25/0.1 at 0/10/20,
established 0.2, rock 0) — the strangler seam both cores share.
"""
import ctypes
import json
import sys
sys.path.insert(0, "src")
from rune import ms_loader as ml
WRAPPER_TO_SYMBOL = {
"compute_value": "ms_compute_value",
"check_promotion_eligibility": "ms_check_promotion_eligibility",
"pre_commit_gate_entry": "ms_pre_commit_gate_entry",
"get_compression_ratio": "ms_get_compression_ratio",
"compress_text": "ms_compress_text",
"compress_entry": "ms_compress_entry",
"should_warn": "ms_should_warn",
"warn_before_compress": "ms_warn_before_compress",
"compute_priority": "ms_compute_priority",
"qualifies_for_cache": "ms_qualifies_for_cache",
"score_gate": "ms_score_gate",
"score_finish": "ms_score_finish",
"base_level_from_uses": "ms_base_level_from_uses",
}
def test_all_symbols_resolve():
lib = ml._load()
for wrapper, sym in WRAPPER_TO_SYMBOL.items():
assert hasattr(ml, wrapper), f"wrapper missing: {wrapper}"
try:
getattr(lib, sym)
except AttributeError:
raise AssertionError(f"symbol missing in .so: {sym} (wrapper {wrapper})")
def test_missing_lib_raises_unavailable():
assert issubclass(ml.MemoryScoringUnavailable, FileNotFoundError)
def test_error_envelope_raises_with_symbol():
try:
ml._call("ms_compress_text", {"wrong": "shape"})
except RuntimeError as e:
assert "ms_compress_text" in str(e)
assert "arg.ratio required" in str(e)
else:
raise AssertionError("kernel !ok must raise, never return None")
def test_null_envelope_is_err_not_crash():
lib = ml._load()
lib.ms_compress_text.argtypes = [ctypes.c_char_p]
lib.ms_compress_text.restype = ctypes.c_void_p
ptr = lib.ms_compress_text(None)
try:
text = ctypes.cast(ptr, ctypes.c_char_p).value.decode("utf-8")
finally:
lib.ms_free_string(ptr)
assert json.loads(text) == {"ok": False, "err": "null argument pointer"}
def test_ratio_ladder():
assert ml.get_compression_ratio(0.0, "washable") == 0.5
assert ml.get_compression_ratio(9.0, "washable") == 0.5
assert ml.get_compression_ratio(10.0, "washable") == 0.25
assert ml.get_compression_ratio(20.0, "washable") == 0.1
assert ml.get_compression_ratio(50.0, "washable") == 0.1
assert ml.get_compression_ratio(50.0, "established") == 0.2
assert ml.get_compression_ratio(50.0, "rock") == 0