# tests/test_prevent_block_cell.py
"""The #42 HARD GATE: the prevent runner reproduces the oracle cross-file CATCH end-to-end.
RED: stage caller_vuln.ts (NO sink) → collect_deps resolves ./service_vuln → run_oracle_set fires on the
RESOLVED DEP → owner|referee (ratcheted) → BLOCK, exit 1, and the blocking finding's file is the DEP
(service_vuln.ts), proving resolution — NOT the caller — surfaced it (wiring-verified, not assumed).
GREEN: caller_safe.ts → mediated → exit 0. Skips where `bun` is absent."""
import importlib.util, os, shutil
import pytest

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CELLS = os.path.join(ROOT, "domains", "security", "detectors", "oracle", "cells")
pytestmark = pytest.mark.skipif(shutil.which("bun") is None, reason="oracle runtime `bun` not installed")

def _load(name, path):
    spec = importlib.util.spec_from_file_location(name, path)
    mod = importlib.util.module_from_spec(spec); spec.loader.exec_module(mod); return mod

runner = _load("sg_runner7", os.path.join(ROOT, "prevent", "runner.py"))
registry = _load("sg_registry7", os.path.join(ROOT, "prevent", "registry.py"))
DETECTORS, _ = registry.load(ROOT)
# the test's OWN ratchet — matches the cell, NOT the production confirmed.json (real multideal path)
CONFIRMED = [{"class": "S9", "file": "service_vuln.ts", "symbol": "owner|referee"}]

def test_red_caller_blocks_via_xfile_resolved_dep():
    cf = os.path.relpath(os.path.join(CELLS, "caller_vuln.ts"), ROOT)
    rep = runner.run([cf], "pre-commit", DETECTORS, ROOT, CONFIRMED)
    hits = [f for f in rep["blocking"]
            if f["symbol"].lower() == "owner|referee" and f["file"].endswith("service_vuln.ts")]
    assert hits, f"expected owner|referee BLOCK on the resolved dep service_vuln.ts; got {rep}"
    assert rep["exit_code"] == 1

def test_green_caller_allows():
    cf = os.path.relpath(os.path.join(CELLS, "caller_safe.ts"), ROOT)
    rep = runner.run([cf], "pre-commit", DETECTORS, ROOT, CONFIRMED)
    assert rep["exit_code"] == 0, f"safe caller must pass; got {rep}"
    assert not any(f["symbol"].lower() == "owner|referee" for f in rep["blocking"]), \
        f"owner|referee must be mediated in GREEN; got {rep}"
