feat(contributor-scan): 1.1 regions from entry points, 1.2 the repository driver

Pair scoring could rely on a labelled function; a contributor cannot supply one
-- which code is risky is the question they are asking. Regions now come from
entry points, with a file-level fallback that says it is one, and each carries
only the families its shape and language admit. Ranking uses what
EntryPointRecord already decided (access_level, trust_boundary) rather than a
second opinion computed from the same evidence.

A family is offered only where its arbiter could answer: access_control needs a
handler, so a library file with no entry point is not asked about obligations it
has no siblings to be inconsistent with.

The driver makes the two costs that were free at pair scale explicit. ONE CPG
per repository, reused across regions -- a build is 5-30s on a forty-line
excerpt and per-region builds would make this unusable. And a budget that is a
TOTAL for the run rather than the enumerator's per-region cap of eight, spent
highest-rank-first, with whatever it does not reach counted into
regions_unjudged. A tool that silently analyses a tenth of a repository and
reports a clean result is worse than one that says what it skipped.

Two flaws the tests caught, both mine and both about ownership: the budget
counted calls by reading a client's own usage log, so it silently never tripped
for a client that keeps none -- the driver now counts its own spend through a
wrapper; and the driver trusted its caller to have sorted, when the order the
budget is spent in belongs to whoever holds the budget.

The third was worse and only surfaced because a test failed for the right
reason: the driver passed candidates=() and never enumerated, so a repository
scan would have reported only what the arbiters establish unaided and never
populated the suspicion band -- which supplied 15 of 26 findings in the pair
measurement. It enumerates now.

Sibling audit (Req 8.5) done before writing: family routing lives in exactly one
production place, pipeline._arbitrate, dispatching on spec type. regions_for
returns family names and the driver resolves specs, so that stays true.

750 passing, mypy clean over 96 files, gates byte-identical, zero orphans.

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-09 07:28:30 +02:00
co-authored by Claude Opus 5
parent 64a27c4e30
commit 8663c1a5b3
8 changed files with 605 additions and 14 deletions
@@ -1,13 +1,13 @@
{
"counts": {
"load_bearing": 86,
"load_bearing": 88,
"standalone_capability": 7
},
"generated": "2026-09-08 (regenerated after the detector pipeline was wired)",
"generated": "2026-09-09 (regenerated after contributor-scan group 1 added regions and the repo driver)",
"kept_with_a_lever_stripped": {
"improve/evolve.py + improve/validator.py": "the design's Removed list named these whole, but each is a mix: the mechanism lever (removed) and the deterministic rule-status improve loop that `ousast improve` still runs from benchmark evidence, which has no LLM in it and is not what this feature supersedes. Deleting the files would have taken a retained capability with them."
},
"modules": 93,
"modules": 95,
"note": "Classification of every source module after the group-1 subtraction. load_bearing = reachable from a gate, the CLI, or named by a surviving requirement; standalone_capability = its own entry point or protocol, deliberately off the scan path; orphaned = no importer, no entry point, no surviving requirement -- removed, never carried.",
"orphaned": [],
"removed_in_this_pass": {
@@ -336,6 +336,8 @@
"model.execution",
"model.judge",
"model.pipeline",
"model.regions",
"model.scan",
"model.specs",
"model.taint"
],
@@ -357,20 +359,25 @@
{
"classification": "load_bearing",
"importers": [
"cli"
"cli",
"model.scan"
],
"module": "model.candidates",
"reason": "reachable from gate, map_gate, pair_gate or the CLI"
},
{
"classification": "load_bearing",
"importers": [],
"importers": [
"model.pipeline"
],
"module": "model.config_value",
"reason": "model-grounded-detection Req 6.3: constant abstraction for the configuration families"
},
{
"classification": "load_bearing",
"importers": [],
"importers": [
"model.pipeline"
],
"module": "model.dominance",
"reason": "model-grounded-detection Req 6.2: guard dominance, the arbiter for bugs that never crash"
},
@@ -400,6 +407,7 @@
"model.execution",
"model.judge",
"model.pipeline",
"model.scan",
"model.taint"
],
"module": "model.ladder",
@@ -407,16 +415,32 @@
},
{
"classification": "load_bearing",
"importers": [],
"importers": [
"model.scan"
],
"module": "model.pipeline",
"reason": "model-grounded-detection Req 8: the enumerator proposes, the LLM answers, the model disposes"
},
{
"classification": "load_bearing",
"importers": [
"model.scan"
],
"module": "model.regions",
"reason": "contributor-scan Req 2: regions from entry points, with the families each admits"
},
{
"classification": "load_bearing",
"importers": [],
"module": "model.report",
"reason": "model-grounded-detection Req 9.3/11.1: per-slice reporting with the overfitting gap"
},
{
"classification": "load_bearing",
"importers": [],
"module": "model.scan",
"reason": "contributor-scan Req 3: the repository driver -- one CPG, one budget, ranked spend"
},
{
"classification": "load_bearing",
"importers": [
@@ -424,6 +448,8 @@
"model.dominance",
"model.judge",
"model.pipeline",
"model.regions",
"model.scan",
"model.taint"
],
"module": "model.specs",
@@ -443,6 +469,7 @@
"importers": [
"cli",
"model.candidates",
"model.scan",
"model.specs"
],
"module": "model.taxonomy",