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
This commit is contained in:
Kjell Tore Guttormsen 2026-08-09 21:18:18 +02:00
commit c76dc537ce
7 changed files with 219 additions and 0 deletions

View file

@ -10,6 +10,7 @@
import { resolve } from 'node:path';
import { writeOutputFile } from './lib/write-output.mjs';
import { requireTargetDir } from './lib/require-target-dir.mjs';
import { runAllScanners } from './scan-orchestrator.mjs';
import { planFixes, applyFixes, verifyFixes } from './fix-engine.mjs';
import { createBackup } from './lib/backup.mjs';
@ -66,6 +67,11 @@ async function main() {
const resolvedPath = resolve(targetPath);
if (!(await requireTargetDir(resolvedPath))) {
process.exitCode = 3;
return;
}
if (!machineMode) {
process.stderr.write(`Config-Audit Fix CLI v2.1.0\n`);
process.stderr.write(`Target: ${resolvedPath}\n`);