feat(slots): Phase 3 task 6.3 — model-disabled, slot-contracted deterministic stages

Express the deterministic scan stages as model-disabled processors carrying work in
named slots under a read/write allow-list validated on every lifecycle hook.

- slot_contract.py (zero-dep): SlotContractError, SlotContractMixin (reads_slots/
  writes_slots/skip_model=True, validates reads pre-hook and writes post-hook),
  SlotPipeline (runs stages in order, enforces the model-disabled invariant, emits
  stage_start/stage_end lifecycle hooks). Preserves the ProcessorSpec.reads/writes
  provenance discipline without forcing deterministic stages through HarnessX's agent
  loop ("bridge, do not map").
- stage_processors.py: Preprocess/EntryPoint/Rank/QuickFindings/PolicyScoring/Score as
  skip_model slot processors; run_quick_pipeline is byte-identical to the quick path.
  host_under_harnessx is the lazy, capability-gated bridge that disables the model on
  HarnessX's BeforeModelEvent.skip_model (proven against the real API when the extra
  is present).
- 8.4 zero-dep guard hardened: now hermetic (subprocess) and covers the two new
  modules; the module-level import scan flags only column-0 imports so the intended
  lazy import inside host_under_harnessx is allowed.

The sync HarnessRuntime stays the top-level driver (design "stays through Phase 4");
these slot processors are the model-disabled representation, ready for Phase 5.

tests/test_slot_contract.py (8 tests). 153 passed, 3 skipped; ruff + mypy clean;
detection gate PASS.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Marius Ciepluch
2026-06-22 18:39:09 +02:00
co-authored by Claude Opus 4.8
parent bebfc72cf7
commit b9caeeb835
6 changed files with 410 additions and 13 deletions
+10 -10
View File
@@ -6,9 +6,7 @@
8.4 — the governance/scoring/benchmark planes never import the HarnessX extra.
"""
import importlib
import json
import sys
from pathlib import Path
import pytest
@@ -146,17 +144,20 @@ GOVERNANCE_SCORING_BENCHMARK_PLANES = (
"openultrasast.ruleset.store",
"openultrasast.improve",
"openultrasast.improve.evolve",
"openultrasast.slot_contract",
"openultrasast.stage_processors",
)
def test_governance_scoring_benchmark_planes_never_import_harnessx() -> None:
for module in GOVERNANCE_SCORING_BENCHMARK_PLANES:
importlib.import_module(module)
leaked = sorted(name for name in sys.modules if name == "harnessx" or name.startswith("harnessx."))
assert leaked == [], f"governance/scoring/benchmark planes leaked HarnessX imports: {leaked}"
def test_governance_scoring_benchmark_planes_never_import_harnessx(assert_cold_of_harnessx) -> None: # type: ignore[no-untyped-def]
# Hermetic: a fresh interpreter imports every plane and must pull no harnessx.
imports = "\n".join(f"import {module}" for module in GOVERNANCE_SCORING_BENCHMARK_PLANES)
assert_cold_of_harnessx(imports)
def test_planes_have_no_module_level_harnessx_import() -> None:
# Flags only column-0 (module-level) imports; an indented lazy import inside a
# capability-guarded function (e.g. stage_processors.host_under_harnessx) is fine.
src = Path("src/openultrasast")
offenders = []
for module in GOVERNANCE_SCORING_BENCHMARK_PLANES:
@@ -166,7 +167,6 @@ def test_planes_have_no_module_level_harnessx_import() -> None:
if path is None:
continue
for line in path.read_text().splitlines():
stripped = line.strip()
if stripped.startswith(("import harnessx", "from harnessx")):
offenders.append(f"{path}: {stripped}")
if line.startswith(("import harnessx", "from harnessx")):
offenders.append(f"{path}: {line}")
assert offenders == [], f"plane modules import HarnessX at module scope: {offenders}"