core/tests/test_serve_quarantine_transitive.py
Shay c8160cacba fix(physics): close A-04 transitive serve breach — lazy Tier-2 barrel exports + process-level guard
Importing chat.runtime transitively loaded 5 off-serving modules
(wave_manifold, holographic_vault, fibonacci_search, multi_scale_energy,
wave_energy_boundary) through the core/physics package barrel — falsifying
the 'serve path not wired' acceptance row while the direct-AST A-04 pin
stayed green.

Reconciliation (ruled 2026-07-15): one substrate, two tiers.
- T1 sanctioned serve substrate: wave_manifold (goldtether/surprise/
  biography delegate to it) — stays eager, removed from the A-04 ban list.
- T2 off-serving (holographic_vault, fibonacci_search, wave_energy_boundary,
  multi_scale_energy): converted to PEP 562 lazy __getattr__ exports so the
  serve process never loads them; 'from core.physics import X' still works
  for off-serving callers. TYPE_CHECKING block keeps static analysis intact.
- New tests/test_serve_quarantine_transitive.py enforces the process-level
  invariant via a clean-interpreter sys.modules probe (RED against the old
  barrel, GREEN now).

Evidence: docs/research/adr-0241-0242-adversarial-and-fidelity-findings.md
(Finding #2). 179 affected tests green.
2026-07-15 12:48:45 -07:00

60 lines
2.3 KiB
Python

"""A-04 (transitive) — the serve process must not LOAD the wave/fibonacci substrate.
The existing `test_phase0_a04_serve_path_quarantines_wave_and_fibonacci` walks only
`chat/runtime.py`'s own AST import nodes, so it catches DIRECT imports only. The
stated invariant is process-level ("serve path stays quarantined"; modules labelled
"never serve"). This pin enforces the stated invariant: importing `chat.runtime` in
a clean interpreter must not pull any banned module into `sys.modules`.
RED until the `core/physics/__init__.py` barrel stops eagerly importing the
off-serving substrate (Finding #2, docs/research/adr-0241-0242-adversarial-and-fidelity-findings.md).
"""
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
_ROOT = Path(__file__).resolve().parents[1]
# Genuinely off-serving; must never load into the serve process.
_BANNED = (
"core.physics.holographic_vault",
"core.physics.fibonacci_search",
"core.physics.fibonacci_word_schedule",
"core.physics.atlas_packing",
"core.physics.wave_seam",
"core.physics.wave_energy_boundary",
"core.physics.multi_scale_energy",
"core.physics.sensorium_wave_feed",
# NOTE: core.physics.wave_manifold is intentionally excluded pending the
# Joshua design ruling (goldtether delegates to it). Add it here if the
# ruling is "quarantine wave_manifold for real".
)
def test_import_chat_runtime_does_not_load_offserving_substrate():
probe = (
"import importlib, sys, json;"
"importlib.import_module('chat.runtime');"
f"banned={list(_BANNED)!r};"
"leaked=sorted(m for m in sys.modules for b in banned if m==b or m.startswith(b+'.'));"
"print(json.dumps(leaked))"
)
result = subprocess.run(
[sys.executable, "-c", probe],
cwd=str(_ROOT),
capture_output=True,
text=True,
env={"PYTHONPATH": str(_ROOT), "PATH": ""},
)
assert result.returncode == 0, f"probe failed: {result.stderr[-2000:]}"
leaked = result.stdout.strip().splitlines()[-1]
import json as _json
leaked_list = _json.loads(leaked)
assert not leaked_list, (
"serve process transitively loaded off-serving modules "
f"(A-04 breach via core/physics barrel): {leaked_list}"
)