config-audit/scanners
Kjell Tore Guttormsen cefa751990 feat(campaign): machine-wide always-loaded token roll-up — pure layer (v5.9 B2a)
Extend the campaign ledger with a machine-wide always-loaded token bill, the
pure data-model + aggregation half of B2. Deliberately does NOT do live I/O:
the cross-repo readActiveConfig sweep that populates real numbers is B2b.

Design — shared layer counted ONCE, structurally:
- Ledger root gets an optional `sharedGlobal` summary (the always-loaded layer
  paid in every repo: global CLAUDE.md + agent listing + global MCP + unscoped
  global rules + active plugins' always components), stored ONCE via the new
  setSharedGlobal().
- Each repo entry gets an optional `tokens` summary (its PER-REPO delta only),
  set via the new setRepoTokens(); addRepo now seeds `tokens: null` (mirrors
  findingsBySeverity).
- rollUp() stays PURE and gains a `tokens` aggregate: machineWide = sharedGlobal
  + Σ(per-repo deltas), so the shared layer is counted exactly once by
  construction — the structural guard against the historic double-count bug.
  Plus a `byRepo` table ranked DESC by always-loaded cost ("most expensive
  repos") with a deterministic name tie-break.

Summary shape mirrors manifest's summarizeByLoadPattern exactly
({always|onDemand|external|unknown: {tokens,count}}) so B2b wires in trivially.

Keeps rollUp pure (no filesystem I/O) → byte-stable, respects the THIN campaign
motor invariant. Chosen over the plan's literal "run readActiveConfig inside
rollUp" which would break both (operator-approved deviation).

- 8 new ledger tests incl. the counted-once regression guard + byRepo ranking.
- Updated addRepo shape test (+tokens:null) and campaign-cli EMPTY_ROLLUP.
- No frozen snapshot affected (campaign is v5.7, absent from v5.0.0 baselines).
  Suite green: 1189 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:57:31 +02:00
..
lib feat(campaign): machine-wide always-loaded token roll-up — pure layer (v5.9 B2a) 2026-06-23 16:57:31 +02:00
agent-listing-scanner.mjs feat(scanner): add AGT per-agent description bloat advisory (v5.9 B1-rest) 2026-06-23 16:27:24 +02:00
cache-prefix-scanner.mjs fix(tokens): refresh stale "Opus 4.7" framing to model-neutral + Opus 4.8 anchor 2026-06-18 15:27:36 +02:00
campaign-cli.mjs feat(campaign): cross-repo prioritized backlog (v5.7 Fase 2 Block 4b) 2026-06-23 02:44:21 +02:00
campaign-export-cli.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.mjs feat(campaign): /config-audit campaign — human-approved write-CLI + command (v5.7 Fase 2 Block 3c) 2026-06-22 17:25:15 +02:00
claude-md-linter.mjs feat(rul,cml): durability findings — config lost after compaction (v5.5.0 / A) 2026-06-20 11:20:04 +02:00
collision-scanner.mjs feat(config-audit): cross-plugin collision scanner COL (v5 N6) [skip-docs] 2026-05-01 07:46:15 +02:00
conflict-detector.mjs fix(permissions): param-aware DIS dead-allow + CNF conflict matching 2026-06-18 13:06:20 +02:00
disabled-in-schema-scanner.mjs feat(dis): flag forbidden-param permission rules CC silently ignores 2026-06-19 14:04:25 +02:00
drift-cli.mjs feat(humanizer): forbidden-words lint runner + test wrapper (SC-3) [skip-docs] 2026-05-01 18:11:15 +02:00
feature-gap-scanner.mjs feat(feature-gap): recommend disableBundledSkills under skill-listing pressure 2026-06-18 21:38:19 +02:00
fix-cli.mjs feat(humanizer): forbidden-words lint runner + test wrapper (SC-3) [skip-docs] 2026-05-01 18:11:15 +02:00
fix-engine.mjs fix(hkv,rul): add 3 verified hook events; correct globs-rule wording 2026-06-20 09:56:00 +02:00
hook-validator.mjs fix(hkv): remove post-session — it is a runner hook, not a settings event 2026-06-20 10:12:52 +02:00
import-resolver.mjs feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command 2026-04-08 08:58:35 +02:00
knowledge-refresh-cli.mjs feat(knowledge): knowledge-refresh — living register, deterministic stale core + web poll (v5.7 Chunk 3) 2026-06-21 19:22:57 +02:00
manifest.mjs feat(mft): v5.6 B1 — load-pattern accounting in manifest 2026-06-20 17:48:55 +02:00
mcp-config-validator.mjs fix(mcp-config-validator): remove invented trust field (verify-first) 2026-06-18 14:22:56 +02:00
optimization-lens-scanner.mjs feat(opt): optimization lens CA-OPT-001 (procedure→skill) — v5.7 Fase 1 Chunk 2a 2026-06-20 23:10:03 +02:00
optimize-lens-cli.mjs feat(opt): optimization lens Chunk 2b — opus prose-judgment analyzer + /config-audit optimize 2026-06-21 14:01:18 +02:00
output-style-scanner.mjs feat(ost): v5.6 C — output-style scanner (CA-OST, count 13→14) 2026-06-20 21:02:44 +02:00
plugin-health-scanner.mjs feat(plh): flag plugin-agent frontmatter Claude Code ignores (v5.5.0 / E) 2026-06-20 11:11:12 +02:00
posture.mjs feat(humanizer): forbidden-words lint runner + test wrapper (SC-3) [skip-docs] 2026-05-01 18:11:15 +02:00
rollback-engine.mjs feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command 2026-04-08 08:58:35 +02:00
rules-validator.mjs feat(rul,cml): durability findings — config lost after compaction (v5.5.0 / A) 2026-06-20 11:20:04 +02:00
scan-orchestrator.mjs feat(scanner): add AGT agent-listing always-loaded budget finding (v5.9 B1) 2026-06-23 15:02:59 +02:00
self-audit.mjs feat(skill-listing): add SKL scanner for the skill-listing token budget 2026-06-18 17:36:28 +02:00
settings-validator.mjs feat(set): validate autoMode structure + flag it in shared settings (CA-SET) 2026-06-19 22:14:26 +02:00
skill-listing-scanner.mjs refactor(skl): extract skill-listing budget to shared lib (single source of truth) 2026-06-18 21:23:01 +02:00
token-hotspots-cli.mjs fix(tokens): refresh stale "Opus 4.7" framing to model-neutral + Opus 4.8 anchor 2026-06-18 15:27:36 +02:00
token-hotspots.mjs feat(tok,acr): v5.6 B2 — load-pattern column in token-hotspots 2026-06-20 20:21:01 +02:00
whats-active.mjs feat(humanizer): wire humanizer into 6 remaining CLIs with --raw 2026-05-01 17:47:09 +02:00