"""Runtime guard enforcing the spec invariant: labels/masks are EVAL-ONLY. Any code path that constructs, fits, or tunes the lesion subspace must run inside `subspace_construction_guard()`. While that guard is active, any attempt to load a lesion label or mask raises `LabelLeakError`. This ties the spec rule ("Never use lesion masks or labels to define, fit, or tune the lesion subspace") to an enforceable runtime check, exercised by tests/test_label_leak.py. """ from __future__ import annotations import threading from contextlib import contextmanager _state = threading.local() class LabelLeakError(RuntimeError): """Raised when a lesion label/mask is accessed during subspace construction.""" def _in_construction() -> bool: return getattr(_state, "depth", 0) > 0 @contextmanager def subspace_construction_guard(): """Mark a region as label-free subspace construction. Mask/label loading inside this region is a spec violation and raises. """ _state.depth = getattr(_state, "depth", 0) + 1 try: yield finally: _state.depth -= 1 def assert_label_free(what: str = "lesion label/mask") -> None: """Call this at every label/mask read site. Raises inside subspace construction.""" if _in_construction(): raise LabelLeakError( f"Spec violation: attempted to access {what} during label-free " f"subspace construction. Masks/labels are EVAL-ONLY " f"(IMPLEMENTATION_SPEC ยง0.6, CLAUDE.md). " f"Move this access outside subspace_construction_guard()." )