feat(model-grounded-detection): group 1, subtract the noise architecture

99 source modules -> 81. 832 tests -> 646. The whole learning/ package (16
modules, ~4,100 lines) and six semantic/ modules removed, with the three gates
byte-identical to 2026-09-06-gate-baseline.txt at every step.

The sequence is what made it safe: vocabularies ported first (1.1), importers
detached second (1.2-1.3), deletion third (1.4). Every import break during the
deletion was therefore a detachment miss in the importer and was fixed there --
no module was restored to satisfy one. Both misses were the same shape and were
fixed as a class: operations.py and shapes.py each imported trailing_name from
the deleted variants.py, so it moved to semantic/ir.py, its natural home, and
both importers changed in one edit.

Ported before deleting: the closed guard vocabulary (verbatim, nothing else
holds it) into model/specs.py, which derives TaintSpec and DominanceSpec from
the retained ruleset facts rather than copying them. Re-homed: families ->
model/taxonomy, candidates -> model/candidates, endpoint -> model/endpoint,
plus Region, labeled_family and labeled_spans. labeled_family no longer falls
back to the LLM classifier -- an unlabeled pair is honestly unknown.

Four deviations, each recorded in the spec notes with its reason. improve/
evolve.py and validator.py were stripped, not deleted: each mixes the mechanism
lever (gone) with the deterministic rule-status loop `ousast improve` still
runs, which has no LLM in it; a test now asserts the lever's absence by symbol
so it cannot creep back. The learning CLI group became `model candidates`,
because deleting it outright would have orphaned the retained enumerator by
removing its only entry point. thinking moved from [learning] to [models].

A gap named rather than papered over: no retained sink fact routes by CWE to
path, output_encoding, untrusted_destination or prototype -- the same hole the
entailment ceiling diagnosed. The test asserts the seeded set and the gap set
exactly, so task 4.2 must update it when it authors those sinks.

The audit found exactly one genuine orphan: vectorstore.py, a bakeoff harness
with no production caller and no CLI, alive only through its own test. The five
named subsystems each carry an explicit decision. Manifest committed, with a
test asserting the tree still matches it.

Group 2 (the Joern go/no-go) has not started.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
This commit is contained in:
Marius Ciepluch
2026-09-08 12:15:54 +02:00
co-authored by Claude Opus 5
parent fc4dab97fb
commit 9ed0e45c5f
86 changed files with 1710 additions and 12158 deletions
+81
View File
@@ -0,0 +1,81 @@
"""model-grounded-detection Req 1.3: nothing survives that imports what this feature removed.
The noise architecture and the mechanism/evolve loop are deleted, not deprecated. This walks the AST of every
surviving module and fails on any import that names one of them — the check that turns a five-thousand-line
deletion from crash-driven discovery into one assertion.
"""
from __future__ import annotations
import ast
from pathlib import Path
SRC = Path("src/openultrasast")
REMOVED_MODULES = frozenset(
{
# the noise architecture (the whole learning/ package; taxonomy, candidates and endpoint re-homed to model/)
"learning",
# the mechanism/evolve optimisation loop
"semantic.mechanisms",
"semantic.variants",
"semantic.variant_search",
"semantic.prove_budget",
"semantic.loo",
"semantic.seed",
}
)
def _module_names(tree: ast.AST) -> set[str]:
names: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom) and node.module:
names.add(node.module)
elif isinstance(node, ast.Import):
names.update(alias.name for alias in node.names)
return names
def _names_a_removed_module(imported: str) -> bool:
trimmed = imported.lstrip(".")
return any(trimmed == removed or trimmed.startswith(f"{removed}.") for removed in REMOVED_MODULES)
def test_no_surviving_module_imports_a_removed_one() -> None:
offenders: dict[str, list[str]] = {}
for path in sorted(SRC.rglob("*.py")):
named = sorted(name for name in _module_names(ast.parse(path.read_text())) if _names_a_removed_module(name))
if named:
offenders[str(path)] = named
assert not offenders, f"dangling imports of removed modules: {offenders}"
def test_the_removed_modules_are_gone_from_the_tree() -> None:
assert not (SRC / "learning").exists(), "the learning package is removed; taxonomy/candidates/endpoint live under model/"
for relative in ("semantic/mechanisms.py", "semantic/variants.py", "semantic/variant_search.py",
"semantic/prove_budget.py", "semantic/loo.py", "semantic/seed.py"):
assert not (SRC / relative).exists(), f"{relative} still exists"
def test_the_mechanism_lever_is_gone_from_the_retained_improve_loop() -> None:
"""`improve/` survives with its lever removed, not deleted.
The design's Removed list named `improve/evolve.py` whole, but the file is a mix: the mechanism lever
(deleted here) and the deterministic rule-status loop that `ousast improve` still runs from benchmark
evidence, which has no LLM in it and is not what this feature supersedes. Deleting the file would have
taken a retained capability with it, so the lever is stripped and the loop stays — asserted by symbol so
the lever cannot creep back.
"""
evolve = (SRC / "improve" / "evolve.py").read_text()
validator = (SRC / "improve" / "validator.py").read_text()
for symbol in ("MechanismEdit", "MechanismStore", "apply_mechanism_edits", "evaluate_mechanism_profiles",
"propose_mechanism_edits", "validate_mechanism", "mechanism_store", "mechanism_candidates"):
assert symbol not in evolve, f"{symbol} survives in improve/evolve.py"
assert symbol not in validator, f"{symbol} survives in improve/validator.py"
assert "def run_improvement(" in evolve and "def propose_status_edits(" in evolve, "the rule-status loop must survive"
def test_the_re_homed_modules_are_where_the_model_layer_expects_them() -> None:
for relative in ("model/taxonomy.py", "model/candidates.py", "model/endpoint.py", "model/specs.py"):
assert (SRC / relative).is_file(), f"{relative} is missing"