config-audit/tests/scanners
Kjell Tore Guttormsen 9ae4be26d2 feat(scanners): model/effort routing becomes a lever, not a 25th dimension (C4)
New GAP finding CA-GAP-028: authored subagents exist and not one of them names
`model:` or `effort:`, so every delegated task runs on the main conversation's
model (`model` defaults to `inherit`). Cites BP-MODEL-001/002, landed in C1.
`whats-active` and `manifest` now carry `model`/`effort` per agent.

Shipped as a conditional LEVER rather than a 25th dimension, and the choice was
made by measurement: as a t3 dimension the agent-less marketplace-medium fixture
would count it vacuously-present, moving the denominators 41->42 and utilization
44->45 — which flips `segment` "Developing"->"Competent" in the frozen v5.0.0
posture baseline, a field strip-retired-gap.mjs does not mask. A lever never
enters those denominators. The general rule is now an invariant in CLAUDE.md.

One check across both axes, not one per axis: it fires only when neither is used
anywhere, so a deliberate everything-on-one-model policy stays silent. Cost is
recall, chosen for precision.

Found by dogfooding, fixed red-first: `model: inherit` is the documented default
spelled out, so it must not count as routing — otherwise a config opts out of the
opportunity without changing anything real.

Two pre-existing defects surfaced and closed on the way:
- The humanizer guard asserted TRANSLATIONS.GAP.static EQUALS the dimension
  titles, which forbade humanizing any lever — all three existing levers fell
  through to the generic "feature opportunity" default, wrong for a budget lever.
  Guard now requires coverage of every emittable title, seen red against those
  three before the entries were written.
- Two hand-written copies of the lever list (finding-codes guard, humanizer
  guard) merged into one exported LEVERS registry carrying code AND title.
- suppression-validation pinned CA-GAP-028 as an unoccupied number; C4 claimed
  it. Fixed structurally with a derived first-free id, not by picking a new
  literal — same class as #60's "bump this again".

Suite 1596/0. Frozen v5.0.0 snapshots untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq3nye21RVYk4pZLeT8pGz
2026-08-10 05:07:23 +02:00
..
accurate-tokens.test.mjs test: isolate HOME in all CLI-spawning tests (close leak class) 2026-06-18 18:17:09 +02:00
agent-listing-scanner.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
cache-prefix.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
campaign-cli.test.mjs feat(campaign): machine-wide always-loaded token roll-up — pure layer (v5.9 B2a) 2026-06-23 16:57:31 +02:00
campaign-export-cli.test.mjs feat(campaign): plan export + execution-by-reuse (v5.7 Fase 2 Block 4c) 2026-06-23 10:08:04 +02:00
campaign-write-cli.test.mjs fix(commands): stop answering questions the caller did not ask 2026-08-01 21:26:39 +02:00
claude-md-linter.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
cli-humanizer.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
cli-missing-target-rejection.test.mjs fix(scanners): a target path that does not exist is an error, not a grade 2026-08-09 21:18:18 +02:00
cli-pipe-integrity.test.mjs fix(scanners): stop discarding our own stdout when it is a pipe 2026-07-31 21:40:15 +02:00
cli-unknown-flag-rejection.test.mjs fix(scanners): close the CLI argument class across all fourteen CLIs 2026-08-09 21:42:00 +02:00
collision.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
conflict-detector.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
disabled-in-schema.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
drift-cli.test.mjs fix(commands): close the promises the command templates could not keep 2026-07-31 21:27:07 +02:00
feature-gap-scanner.test.mjs feat(scanners): model/effort routing becomes a lever, not a 25th dimension (C4) 2026-08-10 05:07:23 +02:00
finding-code-coverage.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
finding-id-stability.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
fix-cli.test.mjs fix(fix): validate the arguments, back up renames, and verify the scope it fixed 2026-07-31 18:41:27 +02:00
fix-engine.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
fix-verify-instance-identity.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
gap-agent-model-routing.test.mjs feat(scanners): model/effort routing becomes a lever, not a 25th dimension (C4) 2026-08-10 05:07:23 +02:00
hook-additional-context.test.mjs feat(hooks): additionalContext injection advisory + filter-before lever (v5.10 B5) [skip-docs] 2026-06-23 20:28:33 +02:00
hook-validator.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
import-resolver.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
knowledge-refresh-cli.test.mjs feat(knowledge): model + effort routing enter the register, dated [skip-docs] 2026-08-10 04:36:09 +02:00
lint-default-output.test.mjs test(snapshots): make byte/snapshot tests hermetic + re-seed baseline 2026-06-18 12:26:00 +02:00
manifest.test.mjs feat(scanners): model/effort routing becomes a lever, not a 25th dimension (C4) 2026-08-10 05:07:23 +02:00
mcp-config-validator.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
mcp-deferral.test.mjs feat(tokens): MCP tool-schema deferral check + CLI-over-MCP lever (v5.10 B4) 2026-06-23 19:59:14 +02:00
optimization-lens-scanner.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
optimize-lens-cli.test.mjs fix(acr): optimize lens scopes out plugin-bundled CLAUDE.md + unique candidate paths (M-BUG-11) 2026-06-30 06:44:36 +02:00
output-file-robustness.test.mjs fix(commands): stop answering questions the caller did not ask 2026-08-01 21:26:39 +02:00
output-style-scanner.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
plugin-health-scanner.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
posture-grade-stability.test.mjs feat(skill-listing): add CA-SKL-002 aggregate listing-budget check 2026-06-18 18:06:17 +02:00
posture-humanizer.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
posture.test.mjs test: isolate HOME in all CLI-spawning tests (close leak class) 2026-06-18 18:17:09 +02:00
published-ids-on-real-output.test.mjs test(scanners): assert the published IDs off real output, by title 2026-08-09 23:34:02 +02:00
rollback-engine.test.mjs fix(rollback): restore the backup path contract the engine and the commands disagreed on 2026-07-31 17:23:30 +02:00
rollback-paths.test.mjs fix(rollback): restore the backup path contract the engine and the commands disagreed on 2026-07-31 17:23:30 +02:00
rules-validator.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
scan-orchestrator-humanizer.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
scan-orchestrator.test.mjs feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command 2026-04-08 08:58:35 +02:00
self-audit.test.mjs feat(config-audit): self-audit --check-readme flag (v5 F6) [skip-docs] 2026-05-01 07:09:26 +02:00
settings-validator.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
skill-listing-scanner.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
token-hotspots-cli.test.mjs test: isolate HOME in all CLI-spawning tests (close leak class) 2026-06-18 18:17:09 +02:00
token-hotspots-deferral.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00
token-hotspots.test.mjs fix(scanners)!: a finding ID names the check, not the emission (M-BUG-28) 2026-08-09 23:26:36 +02:00