fix(audit): the module audit checks real imports before the spec-owned list

model/audit.py classified anything named in SPEC_OWNED or STANDALONE before
looking at the import graph, so five modules nothing imports were reported
load_bearing and the committed manifest said 0 orphans.

- Reachability from the gates, the CLI and every module with a __main__ block
  (python -m, the plane runner) now decides the class; the lists only supply
  reason text, and an unreachable listed module is orphaned with its listing.
- `from .pkg import sub` now records the submodule edge (plane.engine_alerts
  was only reachable by its SPEC_OWNED entry).
- `python -m openultrasast.model.audit` regenerates the manifest.
- Manifest regenerated: 145 load_bearing, 5 standalone, 5 orphaned
  (model.calibrate, model.execution, model.judge, slot_contract,
  stage_processors). The zero-orphan test is strict-xfail until they go.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-10-02 07:17:26 +02:00
co-authored by Claude Opus 5.5
parent 7b17eacd44
commit b7f1f3d05b
3 changed files with 235 additions and 131 deletions
@@ -1,24 +1,29 @@
{ {
"modules": 155, "modules": 155,
"counts": { "counts": {
"load_bearing": 148, "load_bearing": 145,
"standalone_capability": 7 "orphaned": 5,
"standalone_capability": 5
}, },
"orphaned": [], "orphaned": [
"model.calibrate",
"model.execution",
"model.judge",
"slot_contract",
"stage_processors"
],
"standalone": { "standalone": {
"fusion": "two-panel adjudication engine; reached from the scan's report stage and used standalone", "fusion": "two-panel adjudication engine; reached from the scan's report stage and used standalone",
"mcp": "narrow MCP server over stdio; its own `ousast mcp` entry point and OpenCode integration", "mcp": "narrow MCP server over stdio; its own `ousast mcp` entry point and OpenCode integration",
"push_inputs": "pre-push-safety-net task 1.2: offline input provenance validator; python -m openultrasast.push_inputs", "push_inputs": "pre-push-safety-net task 1.2: offline input provenance validator; python -m openultrasast.push_inputs",
"push_scoring": "pre-push-safety-net task 1.3: frozen-profile diagnostic outcome scorer; python -m openultrasast.push_scoring", "push_scoring": "pre-push-safety-net task 1.3: frozen-profile diagnostic outcome scorer; python -m openultrasast.push_scoring",
"skills": "skill router; consumed by mcp and by the OpenCode integration, not by the scan path", "skills": "skill router; consumed by mcp and by the OpenCode integration, not by the scan path"
"slot_contract": "the slot/contract protocol stage_processors implements",
"stage_processors": "deterministic slot-contracted scan stages; pinned by the zero-dependency guard in test_gate"
}, },
"rows": [ "rows": [
{ {
"module": "benchmark", "module": "benchmark",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"gate", "gate",
@@ -32,7 +37,7 @@
{ {
"module": "calibration", "module": "calibration",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -48,7 +53,7 @@
{ {
"module": "complexity", "module": "complexity",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"complexity.hints", "complexity.hints",
@@ -64,7 +69,7 @@
{ {
"module": "complexity.hints", "module": "complexity.hints",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"complexity", "complexity",
"complexity.map" "complexity.map"
@@ -73,7 +78,7 @@
{ {
"module": "complexity.ledger", "module": "complexity.ledger",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"complexity", "complexity",
@@ -84,8 +89,9 @@
{ {
"module": "complexity.map", "module": "complexity.map",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli",
"complexity", "complexity",
"complexity.hints", "complexity.hints",
"complexity.ledger", "complexity.ledger",
@@ -99,7 +105,7 @@
{ {
"module": "complexity.signals", "module": "complexity.signals",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"complexity", "complexity",
"complexity.hints", "complexity.hints",
@@ -109,7 +115,7 @@
{ {
"module": "config", "module": "config",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"harness", "harness",
@@ -206,7 +212,7 @@
{ {
"module": "cpg.session", "module": "cpg.session",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cpg.backend" "cpg.backend"
] ]
@@ -214,7 +220,7 @@
{ {
"module": "findings", "module": "findings",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"benchmark", "benchmark",
"calibration", "calibration",
@@ -264,7 +270,7 @@
{ {
"module": "harness", "module": "harness",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"slot_contract" "slot_contract"
@@ -273,7 +279,7 @@
{ {
"module": "hunter", "module": "hunter",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -281,7 +287,7 @@
{ {
"module": "hunter_tools", "module": "hunter_tools",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"tool_hunter" "tool_hunter"
] ]
@@ -289,7 +295,7 @@
{ {
"module": "improve", "module": "improve",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"improve.evolve", "improve.evolve",
@@ -300,7 +306,7 @@
{ {
"module": "improve.evolve", "module": "improve.evolve",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"improve", "improve",
"plane.tasks.loop" "plane.tasks.loop"
@@ -309,7 +315,7 @@
{ {
"module": "improve.journal", "module": "improve.journal",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"improve", "improve",
"improve.evolve", "improve.evolve",
@@ -320,7 +326,7 @@
{ {
"module": "improve.memory", "module": "improve.memory",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"improve.evolve", "improve.evolve",
@@ -330,7 +336,7 @@
{ {
"module": "improve.validator", "module": "improve.validator",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"improve", "improve",
"improve.evolve", "improve.evolve",
@@ -341,7 +347,7 @@
{ {
"module": "index", "module": "index",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"skills" "skills"
@@ -350,7 +356,7 @@
{ {
"module": "learn", "module": "learn",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"learn.calibrate", "learn.calibrate",
@@ -376,7 +382,7 @@
{ {
"module": "learn.calibrate", "module": "learn.calibrate",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.evaluate" "learn.evaluate"
] ]
@@ -384,7 +390,7 @@
{ {
"module": "learn.cli", "module": "learn.cli",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -392,7 +398,7 @@
{ {
"module": "learn.compile", "module": "learn.compile",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.cli", "learn.cli",
"learn.evaluate" "learn.evaluate"
@@ -401,7 +407,7 @@
{ {
"module": "learn.embeddings", "module": "learn.embeddings",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.cli", "learn.cli",
"learn.retrieve" "learn.retrieve"
@@ -410,7 +416,7 @@
{ {
"module": "learn.evaluate", "module": "learn.evaluate",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.cli", "learn.cli",
"learn.compile" "learn.compile"
@@ -419,7 +425,7 @@
{ {
"module": "learn.examples", "module": "learn.examples",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.cli", "learn.cli",
"learn.compile", "learn.compile",
@@ -432,7 +438,7 @@
{ {
"module": "learn.excerpt", "module": "learn.excerpt",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.embeddings", "learn.embeddings",
"learn.examples", "learn.examples",
@@ -443,7 +449,7 @@
{ {
"module": "learn.features", "module": "learn.features",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.excerpt", "learn.excerpt",
"plane.tasks.features" "plane.tasks.features"
@@ -452,7 +458,7 @@
{ {
"module": "learn.folds", "module": "learn.folds",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.cli", "learn.cli",
"learn.compile", "learn.compile",
@@ -464,7 +470,7 @@
{ {
"module": "learn.labels", "module": "learn.labels",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"learn.calibrate", "learn.calibrate",
@@ -480,7 +486,7 @@
{ {
"module": "learn.leaks", "module": "learn.leaks",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.cli" "learn.cli"
] ]
@@ -498,7 +504,7 @@
{ {
"module": "learn.retrieve", "module": "learn.retrieve",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.evaluate", "learn.evaluate",
"learn.program" "learn.program"
@@ -507,7 +513,7 @@
{ {
"module": "learn.roles", "module": "learn.roles",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.features", "learn.features",
"plane.tasks.features", "plane.tasks.features",
@@ -517,7 +523,7 @@
{ {
"module": "learn.schema", "module": "learn.schema",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.compile", "learn.compile",
"learn.evaluate", "learn.evaluate",
@@ -539,7 +545,7 @@
{ {
"module": "mapping", "module": "mapping",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"gate", "gate",
@@ -566,7 +572,7 @@
{ {
"module": "model", "module": "model",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"cpg.backend", "cpg.backend",
@@ -612,14 +618,14 @@
}, },
{ {
"module": "model.calibrate", "module": "model.calibrate",
"classification": "load_bearing", "classification": "orphaned",
"reason": "model-grounded-detection Req 9: the corpus as the model's calibration set", "reason": "no import path from an entry point or a python -m module; listed as: model-grounded-detection Req 9: the corpus as the model's calibration set",
"importers": [] "importers": []
}, },
{ {
"module": "model.candidates", "module": "model.candidates",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"model.scan" "model.scan"
@@ -681,21 +687,21 @@
{ {
"module": "model.evidence", "module": "model.evidence",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"model.scan" "model.scan"
] ]
}, },
{ {
"module": "model.execution", "module": "model.execution",
"classification": "load_bearing", "classification": "orphaned",
"reason": "model-grounded-detection Req 10: the deferred execution tier seam, adopted not built", "reason": "no import path from an entry point or a python -m module; listed as: model-grounded-detection Req 10: the deferred execution tier seam, adopted not built",
"importers": [] "importers": []
}, },
{ {
"module": "model.judge", "module": "model.judge",
"classification": "load_bearing", "classification": "orphaned",
"reason": "model-grounded-detection Req 8: one bounded question, checked against the model", "reason": "no import path from an entry point or a python -m module; listed as: model-grounded-detection Req 8: one bounded question, checked against the model",
"importers": [] "importers": []
}, },
{ {
@@ -716,7 +722,7 @@
{ {
"module": "model.layout", "module": "model.layout",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"model.partitions", "model.partitions",
"model.scan", "model.scan",
@@ -728,7 +734,7 @@
{ {
"module": "model.partitions", "module": "model.partitions",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"model.scan" "model.scan"
] ]
@@ -778,7 +784,7 @@
{ {
"module": "model.shipped", "module": "model.shipped",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"push.runner" "push.runner"
@@ -813,7 +819,7 @@
{ {
"module": "model.taxonomy", "module": "model.taxonomy",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"learn.features", "learn.features",
@@ -836,7 +842,7 @@
{ {
"module": "pairs", "module": "pairs",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"improve", "improve",
@@ -894,7 +900,7 @@
{ {
"module": "plane.doctor", "module": "plane.doctor",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"plane.reconciler" "plane.reconciler"
] ]
@@ -902,7 +908,7 @@
{ {
"module": "plane.egress", "module": "plane.egress",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"plane.reconciler" "plane.reconciler"
] ]
@@ -911,7 +917,9 @@
"module": "plane.engine_alerts", "module": "plane.engine_alerts",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "harnessx-removal Req 6.3: engine alerts where quick mode has no rules (PHP), on the host", "reason": "harnessx-removal Req 6.3: engine alerts where quick mode has no rules (PHP), on the host",
"importers": [] "importers": [
"cli"
]
}, },
{ {
"module": "plane.generate", "module": "plane.generate",
@@ -925,7 +933,7 @@
{ {
"module": "plane.harvest", "module": "plane.harvest",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -950,6 +958,7 @@
"classification": "load_bearing", "classification": "load_bearing",
"reason": "harnessx-removal Req 6.1/6.4: the memory store (file, MinIO), ingest and fact reuse; `ousast plane remember`", "reason": "harnessx-removal Req 6.1/6.4: the memory store (file, MinIO), ingest and fact reuse; `ousast plane remember`",
"importers": [ "importers": [
"cli",
"improve.memory", "improve.memory",
"learn.cli", "learn.cli",
"learn.compile", "learn.compile",
@@ -966,6 +975,8 @@
"classification": "load_bearing", "classification": "load_bearing",
"reason": "ai-service-plane Req 3.1-3.5, 7.3: ax-backed Run execution, status attribution and doctor; `ousast plane`", "reason": "ai-service-plane Req 3.1-3.5, 7.3: ax-backed Run execution, status attribution and doctor; `ousast plane`",
"importers": [ "importers": [
"cli",
"plane.engine_alerts",
"plane.generate", "plane.generate",
"plane.harvest", "plane.harvest",
"plane.memory", "plane.memory",
@@ -975,7 +986,7 @@
{ {
"module": "plane.router", "module": "plane.router",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"plane.reconciler", "plane.reconciler",
"plane.runner" "plane.runner"
@@ -1093,7 +1104,7 @@
{ {
"module": "policy", "module": "policy",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"findings", "findings",
@@ -1109,7 +1120,7 @@
{ {
"module": "policy.verycode", "module": "policy.verycode",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"policy" "policy"
] ]
@@ -1117,7 +1128,7 @@
{ {
"module": "preprocess", "module": "preprocess",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"complexity.hints", "complexity.hints",
@@ -1153,7 +1164,7 @@
{ {
"module": "profiling", "module": "profiling",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -1161,7 +1172,7 @@
{ {
"module": "provenance", "module": "provenance",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -1169,7 +1180,7 @@
{ {
"module": "provider", "module": "provider",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.cli", "learn.cli",
"learn.compile", "learn.compile",
@@ -1181,7 +1192,7 @@
{ {
"module": "provider.openrouter", "module": "provider.openrouter",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.cli", "learn.cli",
"learn.compile", "learn.compile",
@@ -1209,7 +1220,7 @@
{ {
"module": "push.assistance", "module": "push.assistance",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"push.runner" "push.runner"
] ]
@@ -1240,7 +1251,7 @@
{ {
"module": "push.eligibility", "module": "push.eligibility",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"push.runner" "push.runner"
] ]
@@ -1268,7 +1279,7 @@
{ {
"module": "push.reuse", "module": "push.reuse",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"push.runner" "push.runner"
] ]
@@ -1276,7 +1287,7 @@
{ {
"module": "push.runner", "module": "push.runner",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"push.assistance" "push.assistance"
@@ -1293,7 +1304,7 @@
{ {
"module": "push.vetoes", "module": "push.vetoes",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"push.runner" "push.runner"
] ]
@@ -1315,7 +1326,7 @@
{ {
"module": "rank", "module": "rank",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"calibration", "calibration",
"cli", "cli",
@@ -1333,7 +1344,7 @@
{ {
"module": "redaction", "module": "redaction",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"harness", "harness",
"model.judge", "model.judge",
@@ -1347,7 +1358,7 @@
{ {
"module": "regress", "module": "regress",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"regress.candidate" "regress.candidate"
@@ -1356,7 +1367,7 @@
{ {
"module": "regress.candidate", "module": "regress.candidate",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"regress" "regress"
] ]
@@ -1364,7 +1375,7 @@
{ {
"module": "regress.recipes", "module": "regress.recipes",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"regress", "regress",
"regress.candidate" "regress.candidate"
@@ -1373,7 +1384,7 @@
{ {
"module": "regress.safety", "module": "regress.safety",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"regress", "regress",
"regress.candidate" "regress.candidate"
@@ -1382,7 +1393,7 @@
{ {
"module": "regress.verdict", "module": "regress.verdict",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"regress", "regress",
"regress.candidate" "regress.candidate"
@@ -1391,7 +1402,7 @@
{ {
"module": "reports", "module": "reports",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -1399,7 +1410,7 @@
{ {
"module": "repos", "module": "repos",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"push_inputs" "push_inputs"
@@ -1408,7 +1419,7 @@
{ {
"module": "ruleset", "module": "ruleset",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"findings", "findings",
@@ -1431,7 +1442,7 @@
{ {
"module": "ruleset.frameworks", "module": "ruleset.frameworks",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"learn.labels", "learn.labels",
"learn.roles", "learn.roles",
@@ -1442,7 +1453,7 @@
{ {
"module": "ruleset.store", "module": "ruleset.store",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"improve.validator", "improve.validator",
"ruleset" "ruleset"
@@ -1451,7 +1462,7 @@
{ {
"module": "run", "module": "run",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"reports" "reports"
@@ -1460,7 +1471,7 @@
{ {
"module": "sandbox", "module": "sandbox",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"regress.candidate", "regress.candidate",
@@ -1472,7 +1483,7 @@
{ {
"module": "sandbox.probe", "module": "sandbox.probe",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"sandbox" "sandbox"
] ]
@@ -1480,7 +1491,7 @@
{ {
"module": "sandbox.runner", "module": "sandbox.runner",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"regress.candidate", "regress.candidate",
"regress.recipes", "regress.recipes",
@@ -1491,7 +1502,7 @@
{ {
"module": "scoring", "module": "scoring",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"improve.evolve", "improve.evolve",
@@ -1501,7 +1512,7 @@
{ {
"module": "scoring.project_score", "module": "scoring.project_score",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"scoring" "scoring"
] ]
@@ -1509,7 +1520,7 @@
{ {
"module": "semantic", "module": "semantic",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"cpg.capability", "cpg.capability",
@@ -1538,7 +1549,7 @@
{ {
"module": "semantic.cst", "module": "semantic.cst",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"semantic.ir" "semantic.ir"
] ]
@@ -1546,7 +1557,7 @@
{ {
"module": "semantic.engines", "module": "semantic.engines",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cpg.capability", "cpg.capability",
"semantic", "semantic",
@@ -1556,7 +1567,7 @@
{ {
"module": "semantic.extra", "module": "semantic.extra",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"semantic", "semantic",
"semantic.cst", "semantic.cst",
@@ -1566,7 +1577,7 @@
{ {
"module": "semantic.facts", "module": "semantic.facts",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"hunter_tools", "hunter_tools",
@@ -1590,7 +1601,7 @@
{ {
"module": "semantic.functions", "module": "semantic.functions",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"hunter_tools", "hunter_tools",
"pairs", "pairs",
@@ -1601,7 +1612,7 @@
{ {
"module": "semantic.ir", "module": "semantic.ir",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"hunter_tools", "hunter_tools",
@@ -1619,7 +1630,7 @@
{ {
"module": "semantic.obligations", "module": "semantic.obligations",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"hunter_tools", "hunter_tools",
@@ -1638,7 +1649,7 @@
{ {
"module": "semantic.obligations.check", "module": "semantic.obligations.check",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"semantic.obligations", "semantic.obligations",
@@ -1648,7 +1659,7 @@
{ {
"module": "semantic.obligations.dominance", "module": "semantic.obligations.dominance",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"hunter_tools", "hunter_tools",
@@ -1659,7 +1670,7 @@
{ {
"module": "semantic.obligations.facts", "module": "semantic.obligations.facts",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"model.specs", "model.specs",
"pairs", "pairs",
@@ -1674,7 +1685,7 @@
{ {
"module": "semantic.obligations.intent", "module": "semantic.obligations.intent",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -1682,7 +1693,7 @@
{ {
"module": "semantic.obligations.operations", "module": "semantic.obligations.operations",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"model.candidates", "model.candidates",
"semantic.obligations.check", "semantic.obligations.check",
@@ -1693,7 +1704,7 @@
{ {
"module": "semantic.obligations.policy", "module": "semantic.obligations.policy",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli", "cli",
"semantic.obligations.check" "semantic.obligations.check"
@@ -1702,7 +1713,7 @@
{ {
"module": "semantic.obligations.shapes", "module": "semantic.obligations.shapes",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"semantic.obligations", "semantic.obligations",
"semantic.obligations.operations" "semantic.obligations.operations"
@@ -1711,7 +1722,7 @@
{ {
"module": "semantic.obligations.siblings", "module": "semantic.obligations.siblings",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"semantic.obligations.check" "semantic.obligations.check"
] ]
@@ -1719,7 +1730,7 @@
{ {
"module": "semantic.overlay", "module": "semantic.overlay",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"semantic", "semantic",
"semantic.prove_filter" "semantic.prove_filter"
@@ -1728,7 +1739,7 @@
{ {
"module": "semantic.prove_filter", "module": "semantic.prove_filter",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"semantic" "semantic"
] ]
@@ -1736,7 +1747,7 @@
{ {
"module": "semantic.taint", "module": "semantic.taint",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"semantic.overlay" "semantic.overlay"
] ]
@@ -1751,22 +1762,22 @@
}, },
{ {
"module": "slot_contract", "module": "slot_contract",
"classification": "standalone_capability", "classification": "orphaned",
"reason": "the slot/contract protocol stage_processors implements", "reason": "no import path from an entry point or a python -m module (imported only by unreachable stage_processors); listed as: the slot/contract protocol stage_processors implements",
"importers": [ "importers": [
"stage_processors" "stage_processors"
] ]
}, },
{ {
"module": "stage_processors", "module": "stage_processors",
"classification": "standalone_capability", "classification": "orphaned",
"reason": "deterministic slot-contracted scan stages; pinned by the zero-dependency guard in test_gate", "reason": "no import path from an entry point or a python -m module; listed as: deterministic slot-contracted scan stages; pinned by the zero-dependency guard in test_gate",
"importers": [] "importers": []
}, },
{ {
"module": "stages", "module": "stages",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli" "cli"
] ]
@@ -1774,8 +1785,9 @@
{ {
"module": "tool_hunter", "module": "tool_hunter",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"cli",
"model.endpoint", "model.endpoint",
"plane.budget", "plane.budget",
"plane.tasks.roles", "plane.tasks.roles",
@@ -1785,7 +1797,7 @@
{ {
"module": "verification", "module": "verification",
"classification": "load_bearing", "classification": "load_bearing",
"reason": "reachable from gate, map_gate, pair_gate or the CLI", "reason": "reachable from gate, map_gate, pair_gate, cli",
"importers": [ "importers": [
"calibration", "calibration",
"cli", "cli",
+61 -14
View File
@@ -6,9 +6,12 @@ checkable rather than a thing someone notices two specs later.
A module is: A module is:
load_bearing reachable from a gate, the scan CLI, or a surviving requirement load_bearing reachable by imports from a gate, the CLI, or a module run with ``python -m``
standalone_capability its own entry point and users, not on the scan path standalone_capability reachable the same way, but its own entry point and users, not on the scan path
orphaned no importer, no entry point, no requirement — it should not be in the tree orphaned not reachable from any of those -- it should not be in the tree
Reachability decides the class. ``SPEC_OWNED`` and ``STANDALONE`` only supply the reason text: being named
by a spec does not keep a module nobody imports alive.
Pure stdlib, no imports of the package it audits: it reads the import graph with ``ast`` so a broken module Pure stdlib, no imports of the package it audits: it reads the import graph with ``ast`` so a broken module
is still classifiable. is still classifiable.
@@ -26,7 +29,7 @@ PACKAGE = "openultrasast"
# Entry points a module can be reachable from. The three gates are the contract; the CLI is the product. # Entry points a module can be reachable from. The three gates are the contract; the CLI is the product.
ROOTS = ("gate", "map_gate", "pair_gate", "cli", "__main__") ROOTS = ("gate", "map_gate", "pair_gate", "cli", "__main__")
# Modules that stand alone: their own CLI subcommand or external protocol, deliberately off the scan path. # Reason text for reachable modules, by the requirement that owns them. Not a classification: see audit().
SPEC_OWNED = { SPEC_OWNED = {
"push.cache": "pre-push-safety-net task 6.2: bounded artifact publication and leased eviction; runner integration in 6.4", "push.cache": "pre-push-safety-net task 6.2: bounded artifact publication and leased eviction; runner integration in 6.4",
"push.report": "pre-push-safety-net Req 5.1/5.2/5.5/7.3: compact output and complete artifacts; runner integration pending", "push.report": "pre-push-safety-net Req 5.1/5.2/5.5/7.3: compact output and complete artifacts; runner integration pending",
@@ -81,6 +84,7 @@ SPEC_OWNED = {
"plane.runner": "ai-service-plane Req 4.1-4.4: the ax-task-runner entrypoint (PID 1 of the task image); delivers the output directory", "plane.runner": "ai-service-plane Req 4.1-4.4: the ax-task-runner entrypoint (PID 1 of the task image); delivers the output directory",
} }
# Reachable modules that stand alone: their own CLI subcommand or external protocol, off the scan path.
STANDALONE = { STANDALONE = {
"push_scoring": "pre-push-safety-net task 1.3: frozen-profile diagnostic outcome scorer; python -m openultrasast.push_scoring", "push_scoring": "pre-push-safety-net task 1.3: frozen-profile diagnostic outcome scorer; python -m openultrasast.push_scoring",
"push_inputs": "pre-push-safety-net task 1.2: offline input provenance validator; python -m openultrasast.push_inputs", "push_inputs": "pre-push-safety-net task 1.2: offline input provenance validator; python -m openultrasast.push_inputs",
@@ -140,6 +144,10 @@ def import_graph(root: Path) -> dict[str, set[str]]:
continue continue
if target: if target:
imported.add(target) imported.add(target)
# `from .plane import engine_alerts` imports the submodule `plane.engine_alerts`, not only the
# package; names that are not modules are dropped later because they are not in the graph.
prefix = f"{target}." if target else ""
imported.update(f"{prefix}{alias.name}" for alias in node.names if alias.name != "*")
elif isinstance(node, ast.Import): elif isinstance(node, ast.Import):
for alias in node.names: for alias in node.names:
if alias.name.startswith(f"{PACKAGE}."): if alias.name.startswith(f"{PACKAGE}."):
@@ -148,6 +156,28 @@ def import_graph(root: Path) -> dict[str, set[str]]:
return graph return graph
def main_modules(root: Path) -> set[str]:
"""Modules with a ``__main__`` block: run by name (``python -m``, the plane runner), so they are entry points."""
found: set[str] = set()
for path in sorted(root.rglob("*.py")):
if "__pycache__" in path.parts:
continue
try:
tree = ast.parse(path.read_text())
except (OSError, SyntaxError):
continue
for node in tree.body:
if (
isinstance(node, ast.If)
and isinstance(node.test, ast.Compare)
and isinstance(node.test.left, ast.Name)
and node.test.left.id == "__name__"
and any(isinstance(c, ast.Constant) and c.value == "__main__" for c in node.test.comparators)
):
found.add(module_name(path, root))
return found
def _reachable(graph: Mapping[str, set[str]], roots: Iterable[str]) -> set[str]: def _reachable(graph: Mapping[str, set[str]], roots: Iterable[str]) -> set[str]:
seen: set[str] = set() seen: set[str] = set()
stack = [root for root in roots if root in graph] stack = [root for root in roots if root in graph]
@@ -173,24 +203,33 @@ def audit(root: Path) -> tuple[ModuleAudit, ...]:
for candidate in (target, target.rsplit(".", 1)[0]): for candidate in (target, target.rsplit(".", 1)[0]):
if candidate in importers and candidate != name: if candidate in importers and candidate != name:
importers[candidate].add(name) importers[candidate].add(name)
live = _reachable(graph, ROOTS) run_by_name = main_modules(root)
live = _reachable(graph, (*ROOTS, *sorted(run_by_name)))
results: list[ModuleAudit] = [] results: list[ModuleAudit] = []
for name in sorted(graph): for name in sorted(graph):
if not name: # the package __init__ itself if not name: # the package __init__ itself
continue continue
who = tuple(sorted(importers[name])) who = tuple(sorted(importers[name]))
if name in SPEC_OWNED: listed = SPEC_OWNED.get(name) or STANDALONE.get(name)
# Reachability decides; the lists only supply reason text. A listed module nothing reaches is still
# orphaned -- the list is what hid five dead modules behind "load_bearing" until 2026-10-02.
if name not in live:
reason = "no import path from an entry point or a python -m module"
if who:
reason += f" (imported only by unreachable {', '.join(who)})"
if listed:
reason += f"; listed as: {listed}"
results.append(ModuleAudit(name, "orphaned", reason, who))
elif name in STANDALONE:
results.append(ModuleAudit(name, "standalone_capability", STANDALONE[name], who))
elif name in SPEC_OWNED:
results.append(ModuleAudit(name, "load_bearing", SPEC_OWNED[name], who)) results.append(ModuleAudit(name, "load_bearing", SPEC_OWNED[name], who))
elif name in ROOTS: elif name in ROOTS:
results.append(ModuleAudit(name, "load_bearing", "entry point", who)) results.append(ModuleAudit(name, "load_bearing", "entry point", who))
elif name in STANDALONE: elif name in run_by_name:
results.append(ModuleAudit(name, "standalone_capability", STANDALONE[name], who)) results.append(ModuleAudit(name, "load_bearing", f"python -m openultrasast.{name}", who))
elif name in live:
results.append(ModuleAudit(name, "load_bearing", f"reachable from {', '.join(ROOTS[:3])} or the CLI", who))
elif who:
results.append(ModuleAudit(name, "load_bearing", f"imported by {', '.join(who)}", who))
else: else:
results.append(ModuleAudit(name, "orphaned", "no importer, no entry point, no surviving requirement", who)) results.append(ModuleAudit(name, "load_bearing", f"reachable from {', '.join(ROOTS[:4])}", who))
return tuple(results) return tuple(results)
@@ -211,4 +250,12 @@ def to_dict(results: Iterable[ModuleAudit]) -> dict[str, object]:
} }
__all__ = ["ModuleAudit", "SPEC_OWNED", "STANDALONE", "audit", "import_graph", "module_name", "to_dict"] __all__ = ["ModuleAudit", "SPEC_OWNED", "STANDALONE", "audit", "import_graph", "main_modules", "module_name", "to_dict"]
if __name__ == "__main__": # python -m openultrasast.model.audit [SRC] -- the manifest's regeneration command
import json
import sys
source = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).resolve().parents[1]
print(json.dumps(to_dict(audit(source)), indent=2))
+46 -1
View File
@@ -5,10 +5,13 @@ from __future__ import annotations
import json import json
from pathlib import Path from pathlib import Path
import pytest
SRC = Path("src/openultrasast") SRC = Path("src/openultrasast")
MANIFEST = Path("benchmarks/measurements/2026-09-08-module-audit.json") MANIFEST = Path("benchmarks/measurements/2026-09-08-module-audit.json")
@pytest.mark.xfail(strict=True, reason="five dead modules the fixed audit found; removed in the next commit")
def test_no_module_in_the_tree_is_orphaned() -> None: def test_no_module_in_the_tree_is_orphaned() -> None:
from openultrasast.model.audit import audit from openultrasast.model.audit import audit
@@ -44,4 +47,46 @@ def test_the_manifest_matches_the_tree() -> None:
committed = json.loads(MANIFEST.read_text()) committed = json.loads(MANIFEST.read_text())
current = to_dict(audit(SRC)) current = to_dict(audit(SRC))
assert committed["counts"] == current["counts"], "the tree drifted from its committed audit" assert committed["counts"] == current["counts"], "the tree drifted from its committed audit"
assert committed["orphaned"] == current["orphaned"] == [] assert committed["orphaned"] == current["orphaned"]
def _tree(root: Path, files: dict[str, str]) -> Path:
for name, text in files.items():
path = root / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text)
return root
def test_a_spec_listed_module_nothing_imports_is_still_orphaned(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""Reachability decides; SPEC_OWNED and STANDALONE only supply the reason (the list hid five dead modules)."""
from openultrasast.model import audit as module
src = _tree(tmp_path, {"cli.py": "from . import used\n", "used.py": "", "ghost.py": "", "lonely.py": ""})
monkeypatch.setitem(module.SPEC_OWNED, "ghost", "some spec Req 1: still listed")
monkeypatch.setitem(module.STANDALONE, "lonely", "its own entry point, supposedly")
rows = {row.module: row for row in module.audit(src)}
assert rows["used"].classification == "load_bearing"
assert rows["ghost"].classification == "orphaned"
assert "still listed" in rows["ghost"].reason
assert rows["lonely"].classification == "orphaned"
def test_submodule_imports_and_python_m_modules_count_as_reachable(tmp_path: Path) -> None:
from openultrasast.model.audit import audit
src = _tree(
tmp_path,
{
"cli.py": "def run():\n from .pkg import sub\n",
"pkg/__init__.py": "",
"pkg/sub.py": "",
"tool.py": 'from . import helper\n\nif __name__ == "__main__":\n pass\n',
"helper.py": "",
"dead.py": "from . import deader\n",
"deader.py": "",
},
)
rows = {row.module: row.classification for row in audit(src)}
assert rows["pkg.sub"] == rows["tool"] == rows["helper"] == "load_bearing"
assert rows["dead"] == rows["deader"] == "orphaned"