config-audit/tests
Kjell Tore Guttormsen c76dc537ce fix(scanners): a target path that does not exist is an error, not a grade
Surfaced by the router dogfood: quoting the placeholder stopped the shell from
swallowing it, which moved the failure down into the CLIs — and revealed that
most of them never check the target at all. Measured:

  node scanners/posture.mjs /nonexistent/path/xyz --output-file …
  exit 0
  Health: B (86/100) — Good shape — a few items to address

Nothing in that output distinguishes it from a real audit: well-formed
envelope, all 10 areas present, 16 opportunities reported. A typo'd path did
not fail — it flattered.

Exit 3 is the right code by the plugin's own contract: 0/1/2 are PASS/WARNING/
FAIL about a configuration that WAS examined, and every command template gates
on exactly that distinction, so a bad path flowed through the whole workflow as
a clean result.

This was a consistency gap, not a design question. Measured across the nine
target-taking CLIs, four already did it right with the same message and the
same exit code (manifest, token-hotspots-cli, whats-active, optimize-lens-cli);
five did not (scan-orchestrator and drift-cli exit 1, posture,
plugin-health-scanner and fix-cli exit 0). The five now share
lib/require-target-dir.mjs, which carries that exact behaviour. The four with
inline copies are left alone — consolidating them is a cleanup, not part of
this fix.

The guard is asserted over ALL nine CLIs, so a new one cannot join the wrong
half, and a third case is covered: a target that exists but is a regular file.
A valid target — including an empty directory — is explicitly unaffected.

Suite 1483 -> 1486, frozen v5.0.0 snapshots untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YDAwy1ZXRpZxht1wyCeSbF
2026-08-09 21:18:18 +02:00
..
agents feat(humanizer): update agent system prompts [skip-docs] 2026-05-01 19:53:59 +02:00
commands fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
fixtures feat(optimize): add --subtract, the subtraction axis, behind a deterministic floor 2026-07-31 16:24:51 +02:00
helpers feat(scanner): add AGT agent-listing always-loaded budget finding (v5.9 B1) 2026-06-23 15:02:59 +02:00
hooks feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command 2026-04-08 08:58:35 +02:00
knowledge fix(tokens): refresh stale "Opus 4.7" framing to model-neutral + Opus 4.8 anchor 2026-06-18 15:27:36 +02:00
lib fix(knowledge): freshness can no longer be green on outdated evidence 2026-08-03 11:36:57 +02:00
scanners fix(scanners): a target path that does not exist is an error, not a grade 2026-08-09 21:18:18 +02:00
scenarios feat(humanizer): scenario read-test corpus + runner (SC-4) [skip-docs] 2026-05-01 18:16:23 +02:00
snapshots fix(acr): honest absence-state copy for two GAP enhancement findings (M-BUG-15) 2026-06-30 12:57:40 +02:00
json-backcompat.test.mjs feat(ost): v5.6 C — output-style scanner (CA-OST, count 13→14) 2026-06-20 21:02:44 +02:00
lint-default-output.mjs feat(humanizer): forbidden-words lint runner + test wrapper (SC-3) [skip-docs] 2026-05-01 18:11:15 +02:00
lint-forbidden-words.json feat(humanizer): forbidden-words data file (tier1/2/3) 2026-05-01 16:53:37 +02:00
raw-backcompat.test.mjs feat(ost): v5.6 C — output-style scanner (CA-OST, count 13→14) 2026-06-20 21:02:44 +02:00
scenario-read-test.mjs feat(humanizer): scenario read-test corpus + runner (SC-4) [skip-docs] 2026-05-01 18:16:23 +02:00
scenario-read-test.test.mjs feat(humanizer): scenario read-test corpus + runner (SC-4) [skip-docs] 2026-05-01 18:16:23 +02:00
snapshot-default-output.test.mjs test(snapshots): make byte/snapshot tests hermetic + re-seed baseline 2026-06-18 12:26:00 +02:00