fix(commands): router dogfood — five seam defects, plus the placeholder class
Dogfooding `/config-audit` (the router) against the repo, fasit written before any run (docs/router-fasit.local.md, untouched). Every claim below is measured behaviour, not a reading of the source. 1. Bare `<target-path>` inside the step-3 fence is a shell REDIRECTION, not an argument. Measured in zsh: both CLIs failed before starting, no output file was written, and the echoed status was 1 — inside the band the router's own gate calls "continue normally". Quoting makes an unsubstituted placeholder reach argv, so it fails in the CLI where the exit code means something. Swept the whole class: 30 sites across 12 further command files, since a defect in one file is a class until the opposite is measured. New guard: command-placeholder-shell-safety.test.mjs. 2. The orchestrator's exit code was discarded. Two commands on one line share a single trailing `echo $?`, which reports only the last: measured, an orchestrator exit 3 echoed as posture's 0, so the "3 -> stop" gate could never fire. Both statuses are now captured and echoed. 3. "Running 12 configuration scanners" — the orchestrator registers 16. The new test binds the narrated count to the registry so the next scanner added cannot re-stale it silently. 4. The Area Breakdown table hardcoded 7 rows; posture emits 9 quality areas. Token Efficiency (a B on this repo) and Plugin Hygiene never reached the user. Rows added, and the row set is now asserted against lib/scoring.mjs. Label aligned: "MCP Servers" -> "MCP", as posture emits it. 5. Step 6 rendered "the headline line from the humanized stderr scorecard" and forbade deriving a replacement — while step 3 sent posture's stderr to /dev/null, as UX rule 2 requires, and the prose is absent from the JSON payload (measured). The slot could only be improvised. posture's stderr now goes to a file in the session dir, as commands/posture.md already did; the user still never sees raw scanner output. Also: `grep -q -- "--raw"` matched any argument CONTAINING --raw (measured on `--rawdog` and on a path with --raw in it) — anchored to whole arguments. SCOPE_FLAGS renamed SCOPE_FLAG, since zsh does not word-split and the plural invited the M-BUG-45 shape. command-shell-state-shape.test.mjs only recognised line-initial assignments, so it reported the idiomatic `node …; STATUS=$?` capture as never assigned. Widened to assignments after a separator; verified it still fails on a real cross-block reference before trusting it. Suite 1477 -> 1483, 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:
parent
ca199cc5f6
commit
0b763f25c1
16 changed files with 320 additions and 41 deletions
|
|
@ -177,7 +177,7 @@ them in one call (idempotent — already-tracked repos are skipped, not reset):
|
|||
# Re-derive here: each fenced block is its own Bash call, so a TODAY set
|
||||
# in an earlier block is empty by the time this one runs.
|
||||
TODAY=$(date +%F)
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/campaign-write-cli.mjs add <path1> <path2> ... \
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/campaign-write-cli.mjs add "<path1>" "<path2>" ... \
|
||||
--reference-date "$TODAY" \
|
||||
--output-file ~/.claude/config-audit/sessions/campaign-write.json 2>/dev/null; echo $?
|
||||
```
|
||||
|
|
@ -211,9 +211,9 @@ On approval:
|
|||
# Re-derive here: each fenced block is its own Bash call, so a TODAY set
|
||||
# in an earlier block is empty by the time this one runs.
|
||||
TODAY=$(date +%F)
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/campaign-write-cli.mjs set-status <path> <status> \
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/campaign-write-cli.mjs set-status "<path>" "<status>" \
|
||||
--reference-date "$TODAY" \
|
||||
[--findings '{"critical":0,"high":0,"medium":0,"low":0}'] [--session <id>] \
|
||||
[--findings '{"critical":0,"high":0,"medium":0,"low":0}'] [--session "<id>"] \
|
||||
--output-file ~/.claude/config-audit/sessions/campaign-write.json 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -83,33 +83,41 @@ This is a silent infrastructure step — do NOT show output to the user.
|
|||
|
||||
### Step 3: Run scanners and posture assessment
|
||||
|
||||
Tell the user: **"Running 12 configuration scanners..."**
|
||||
Tell the user: **"Running 16 configuration scanners..."**
|
||||
|
||||
Run both scanners and posture in a single Bash command. Default mode runs the humanizer, so each finding in `scan-results.json` carries `userImpactCategory`, `userActionLanguage`, and `relevanceContext` alongside the v5.0.0 fields. If the user passed `--raw`, thread it through to both CLIs to get v5.0.0 verbatim output.
|
||||
|
||||
```bash
|
||||
RAW_FLAG=""
|
||||
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
||||
# Set to the scope flags the detected scope calls for, otherwise leave empty.
|
||||
# A placeholder in square brackets does not start with a dash, so both CLIs'
|
||||
# arg loops would take it as the TARGET PATH instead of a flag.
|
||||
SCOPE_FLAGS="" # e.g. SCOPE_FLAGS="--full-machine" or SCOPE_FLAGS="--global"
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/scan-orchestrator.mjs <target-path> --output-file ~/.claude/config-audit/sessions/{session-id}/findings/scan-results.json $SCOPE_FLAGS $RAW_FLAG >/dev/null 2>/dev/null; node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs <target-path> --output-file ~/.claude/config-audit/sessions/{session-id}/posture.json $SCOPE_FLAGS $RAW_FLAG 2>/dev/null; echo $?
|
||||
if echo "$ARGUMENTS" | grep -qE -- '(^| )--raw( |$)'; then RAW_FLAG="--raw"; fi
|
||||
# Set to the ONE scope flag the detected scope calls for, otherwise leave empty.
|
||||
# Exactly one token: zsh does not word-split an unquoted expansion, so a variable
|
||||
# holding "--flag value" would reach argv as a single unrecognised argument.
|
||||
# A placeholder in square brackets does not start with a dash either, so both
|
||||
# CLIs' arg loops would take it as the TARGET PATH instead of a flag.
|
||||
SCOPE_FLAG="" # e.g. SCOPE_FLAG="--full-machine" or SCOPE_FLAG="--global"
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/scan-orchestrator.mjs "<target-path>" --output-file ~/.claude/config-audit/sessions/{session-id}/findings/scan-results.json $SCOPE_FLAG $RAW_FLAG >/dev/null 2>/dev/null; ORCH_STATUS=$?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs "<target-path>" --output-file ~/.claude/config-audit/sessions/{session-id}/posture.json $SCOPE_FLAG $RAW_FLAG >/dev/null 2>~/.claude/config-audit/sessions/{session-id}/posture-stderr.txt; POSTURE_STATUS=$?
|
||||
echo "$ORCH_STATUS $POSTURE_STATUS"
|
||||
```
|
||||
|
||||
Use `--full-machine` for `full` scope, `--global` for `home` scope. For `repo` and `current`, pass the resolved path directly.
|
||||
|
||||
Check the echoed exit code:
|
||||
- `0`, `1`, or `2` → continue normally
|
||||
- `3` → tell user: "Scanner encountered an unexpected error. Try `/config-audit posture` for a quick check instead." and stop.
|
||||
Two exit codes are echoed — the orchestrator's first, posture's second. They must be read **independently**; a single trailing `echo $?` would report only the last command, hiding an orchestrator failure behind posture's success.
|
||||
|
||||
- both in `0`, `1`, `2` → continue normally
|
||||
- **either** is `3` → tell user: "Scanner encountered an unexpected error. Try `/config-audit posture` for a quick check instead." and stop.
|
||||
|
||||
Posture's stderr goes to a **file**, not `/dev/null`: it carries the humanized scorecard headline that step 6 renders, and that headline exists nowhere in the JSON payload. Writing it to a file keeps UX rule 2 intact (the user still never sees raw scanner output) while leaving the text readable.
|
||||
|
||||
### Step 4: Analyze results
|
||||
|
||||
Tell the user: **"Scanners complete. Preparing your results..."**
|
||||
|
||||
Read BOTH output files using the Read tool:
|
||||
Read all three output files using the Read tool:
|
||||
- `~/.claude/config-audit/sessions/{session-id}/findings/scan-results.json`
|
||||
- `~/.claude/config-audit/sessions/{session-id}/posture.json`
|
||||
- `~/.claude/config-audit/sessions/{session-id}/posture-stderr.txt` — the humanized scorecard. Take the `Health: {grade} ({score}/100) — {prose}` headline from it; that prose is not in either JSON payload.
|
||||
|
||||
Extract these metrics from the JSON:
|
||||
|
||||
|
|
@ -150,7 +158,7 @@ Present results using this template. The humanizer has already replaced jargon-h
|
|||
|
||||
**Health: {overallGrade}** | {qualityAreaCount} areas scanned
|
||||
|
||||
{Use the headline line from the humanized stderr scorecard — it carries grade-context prose already. Avoid hardcoding a separate per-grade prose ladder.}
|
||||
{Use the `Health: …` headline read from `posture-stderr.txt` in step 4 — it carries grade-context prose already. Avoid hardcoding a separate per-grade prose ladder. If that file is missing or empty, say the grade plainly without inventing prose for it.}
|
||||
|
||||
Scanned {files_scanned} files | {real_finding_count} findings ({severity_breakdown})
|
||||
{If test_fixture_count > 0: "({test_fixture_count} additional findings in test fixtures were excluded.)"}
|
||||
|
|
@ -164,9 +172,11 @@ Scanned {files_scanned} files | {real_finding_count} findings ({severity_breakdo
|
|||
| Settings | {grade} | {count} | {status} |
|
||||
| Hooks | {grade} | {count} | {status} |
|
||||
| Rules | {grade} | {count} | {status} |
|
||||
| MCP Servers | {grade} | {count} | {status} |
|
||||
| MCP | {grade} | {count} | {status} |
|
||||
| Imports | {grade} | {count} | {status} |
|
||||
| Conflicts | {grade} | {count} | {status} |
|
||||
| Token Efficiency | {grade} | {count} | {status} |
|
||||
| Plugin Hygiene | {grade} | {count} | {status} |
|
||||
|
||||
{For the status column, use the humanized title from the most-severe finding in that area, or a one-phrase plain-language summary. Findings carry userImpactCategory which already groups by impact bucket — use that vocabulary, not raw scanner names.}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
|||
# the orchestrator's arg loop takes it as the SCAN TARGET and silently scans a
|
||||
# path that does not exist.
|
||||
SCOPE_FLAGS="" # e.g. SCOPE_FLAGS="--full-machine" or SCOPE_FLAGS="--global"
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/scan-orchestrator.mjs <target-path> --output-file ~/.claude/config-audit/sessions/{session-id}/findings/scan-results.json $SCOPE_FLAGS $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/scan-orchestrator.mjs "<target-path>" --output-file ~/.claude/config-audit/sessions/{session-id}/findings/scan-results.json $SCOPE_FLAGS $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Check exit code: 0/1/2 → normal. 3 → "Discovery encountered an error. Try a narrower scope."
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Tell the user: **"Saving current configuration as baseline..."**
|
|||
```bash
|
||||
RAW_FLAG=""
|
||||
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/drift-cli.mjs <path> --save --name <baseline-name> --json $RAW_FLAG 2>/dev/null
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/drift-cli.mjs "<path>" --save --name "<baseline-name>" --json $RAW_FLAG 2>/dev/null
|
||||
```
|
||||
|
||||
`--save` writes its human confirmation to **stderr**, which `2>/dev/null` discards — pass `--json` so the `{saved, name, path}` object lands on stdout. Read stdout for confirmation. Tell the user:
|
||||
|
|
@ -50,7 +50,7 @@ Tell the user: **"Comparing current configuration against baseline..."**
|
|||
```bash
|
||||
RAW_FLAG=""
|
||||
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/drift-cli.mjs <path> --baseline <name> --output-file /tmp/config-audit-drift.json $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/drift-cli.mjs "<path>" --baseline "<name>" --output-file /tmp/config-audit-drift.json $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Exit codes: `0` = stable/improving, `1` = degrading (both normal — present the result either way), `3` = a real error.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ Generate session ID (`YYYYMMDD_HHmmss`) if no active session exists.
|
|||
mkdir -p ~/.claude/config-audit/sessions/{session-id}/findings 2>/dev/null
|
||||
RAW_FLAG=""
|
||||
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs <target-path> --output-file ~/.claude/config-audit/sessions/{session-id}/posture.json $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs "<target-path>" --output-file ~/.claude/config-audit/sessions/{session-id}/posture.json $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
If exit code is non-zero: "Assessment couldn't run. Check that the path exists and contains configuration files."
|
||||
|
|
@ -55,8 +55,8 @@ Extract GAP findings from `scannerEnvelope.scanners` (find scanner with `scanner
|
|||
|
||||
Detect project context:
|
||||
```bash
|
||||
test -f <target-path>/package.json && echo "has_package_json" || echo "no_package_json"
|
||||
ls <target-path>/*.py <target-path>/requirements.txt <target-path>/pyproject.toml 2>/dev/null | head -3
|
||||
test -f "<target-path>"/package.json && echo "has_package_json" || echo "no_package_json"
|
||||
ls "<target-path>"/*.py "<target-path>"/requirements.txt "<target-path>"/pyproject.toml 2>/dev/null | head -3
|
||||
```
|
||||
|
||||
### Step 4: Build numbered recommendations
|
||||
|
|
@ -159,7 +159,7 @@ Implementing 3 recommendations...
|
|||
|
||||
4. **Verify** by re-running posture:
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs <target-path> --json --output-file /tmp/config-audit-verify.json >/dev/null 2>/dev/null
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs "<target-path>" --json --output-file /tmp/config-audit-verify.json >/dev/null 2>/dev/null
|
||||
```
|
||||
|
||||
Use the Read tool on `/tmp/config-audit-verify.json` for the new `overallGrade`
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
|||
# A placeholder in square brackets does not start with a dash, so the arg loop
|
||||
# would take it as the scan/fix TARGET instead of a flag.
|
||||
GLOBAL_FLAG=""
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/scan-orchestrator.mjs <path> --output-file /tmp/config-audit-fix-scan.json $GLOBAL_FLAG $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/scan-orchestrator.mjs "<path>" --output-file /tmp/config-audit-fix-scan.json $GLOBAL_FLAG $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Exit code 3 → tell user: "Scanner error. Try `/config-audit posture` to check your configuration."
|
||||
|
|
@ -56,7 +56,7 @@ Run fix planner silently. The fix-cli emits humanized prose to stderr in default
|
|||
# Re-assign here: each fenced block is its own Bash call, so the value
|
||||
# set in Step 1 is empty by the time this block runs.
|
||||
GLOBAL_FLAG="" # --global when the user asked for global scope
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/fix-cli.mjs <path> $GLOBAL_FLAG --output-file /tmp/config-audit-fix-plan.json 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/fix-cli.mjs "<path>" $GLOBAL_FLAG --output-file /tmp/config-audit-fix-plan.json 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Exit codes: 0 = plan produced, 2 = one or more fixes failed (apply step only), 3 = argument or tool error. On 3, show the stderr message — an unknown flag is rejected by design, not silently ignored.
|
||||
|
|
@ -110,7 +110,7 @@ If confirmed, apply:
|
|||
# Re-assign here: each fenced block is its own Bash call, so the value
|
||||
# set in Step 1 is empty by the time this block runs.
|
||||
GLOBAL_FLAG="" # --global when the user asked for global scope
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/fix-cli.mjs <path> --apply $GLOBAL_FLAG --output-file /tmp/config-audit-fix-applied.json 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/fix-cli.mjs "<path>" --apply $GLOBAL_FLAG --output-file /tmp/config-audit-fix-applied.json 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Read `/tmp/config-audit-fix-applied.json` with the Read tool to get applied/failed counts and the backup ID. Exit code 2 means at least one fix failed — report it; `failed[]` carries the reason per fix.
|
||||
|
|
@ -120,7 +120,7 @@ Read `/tmp/config-audit-fix-applied.json` with the Read tool to get applied/fail
|
|||
Run a quick posture check to measure improvement:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs <path> --json --output-file /tmp/config-audit-fix-posture.json >/dev/null 2>/dev/null
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs "<path>" --json --output-file /tmp/config-audit-fix-posture.json >/dev/null 2>/dev/null
|
||||
```
|
||||
|
||||
Use the Read tool on `/tmp/config-audit-fix-posture.json` and take `overallGrade`
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ is measurable — a delta computed after the fact has no source and must not be
|
|||
invented. To offer one, measure first in Step 1 and again here:
|
||||
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs <target-path> --output-file /tmp/config-audit-implement-posture.json 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs "<target-path>" --output-file /tmp/config-audit-implement-posture.json 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Then Read `/tmp/config-audit-implement-posture.json`. Both the `--output-file` and
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ Tell the user: **"Building token-source manifest for `<path>`..."**
|
|||
```bash
|
||||
RAW_FLAG=""
|
||||
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/manifest.mjs <path> --output-file /tmp/config-audit-manifest.json $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/manifest.mjs "<path>" --output-file /tmp/config-audit-manifest.json $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
**Exit code handling:**
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ GLOBAL_FLAG=""
|
|||
if echo "$ARGUMENTS" | grep -q -- "--global"; then GLOBAL_FLAG="--global"; fi
|
||||
SUBTRACT_FLAG=""
|
||||
if echo "$ARGUMENTS" | grep -q -- "--subtract"; then SUBTRACT_FLAG="--subtract"; fi
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/optimize-lens-cli.mjs <target-path> --output-file ~/.claude/config-audit/sessions/{session-id}/optimize-lens.json $GLOBAL_FLAG $SUBTRACT_FLAG 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/optimize-lens-cli.mjs "<target-path>" --output-file ~/.claude/config-audit/sessions/{session-id}/optimize-lens.json $GLOBAL_FLAG $SUBTRACT_FLAG 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Exit code 0 is normal. Only exit code 3 is a real error → "The lens couldn't run.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ Run silently for each plugin. Default mode writes a humanized JSON payload to `-
|
|||
```bash
|
||||
RAW_FLAG=""
|
||||
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/plugin-health-scanner.mjs <path> --output-file /tmp/config-audit-plugin-health.json $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/plugin-health-scanner.mjs "<path>" --output-file /tmp/config-audit-plugin-health.json $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Read `/tmp/config-audit-plugin-health.json` with the Read tool. Exit codes 0, 1 and 2 are normal; only 3 is a real error.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ Run silently — JSON goes to a file, the humanized scorecard prints to stderr (
|
|||
```bash
|
||||
RAW_FLAG=""
|
||||
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs <target-path> --output-file /tmp/config-audit-posture.json $RAW_FLAG >/dev/null 2>/tmp/config-audit-posture-stderr.txt; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs "<target-path>" --output-file /tmp/config-audit-posture.json $RAW_FLAG >/dev/null 2>/tmp/config-audit-posture-stderr.txt; echo $?
|
||||
```
|
||||
|
||||
Both paths are fixed literals, repeated literally in every later step: each
|
||||
|
|
@ -101,7 +101,7 @@ Avoid hardcoded grade-to-prose ladders here — the humanized scorecard headline
|
|||
|
||||
Run drift comparison silently:
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/drift-cli.mjs <target-path> --output-file /tmp/config-audit-posture-drift.json 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/drift-cli.mjs "<target-path>" --output-file /tmp/config-audit-posture-drift.json 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Use the Read tool on `/tmp/config-audit-posture-drift.json` and append a "Configuration Drift" section showing what changed since the last baseline. Both scanners report to stderr in default mode, which `2>/dev/null` discards — the payload is the only readable output.
|
||||
|
|
@ -110,7 +110,7 @@ Use the Read tool on `/tmp/config-audit-posture-drift.json` and append a "Config
|
|||
|
||||
Run plugin health scanner silently:
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/plugin-health-scanner.mjs <target-path> --output-file /tmp/config-audit-posture-plh.json 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/plugin-health-scanner.mjs "<target-path>" --output-file /tmp/config-audit-posture-plh.json 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
Use the Read tool on `/tmp/config-audit-posture-plh.json` and append a "Plugin Health" section, using its `plugins[]` rows for per-plugin grades.
|
||||
|
|
@ -121,7 +121,7 @@ Use the Read tool on `/tmp/config-audit-posture-plh.json` and append a "Plugin H
|
|||
|
||||
If a config-audit session exists, save results:
|
||||
```bash
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs <target-path> --json --output-file ~/.claude/config-audit/sessions/<session-id>/posture.json >/dev/null 2>/dev/null
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/posture.mjs "<target-path>" --json --output-file ~/.claude/config-audit/sessions/<session-id>/posture.json >/dev/null 2>/dev/null
|
||||
```
|
||||
|
||||
This is a second scan on purpose: the session file stores the raw v5.0.0 shape,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ GLOBAL_FLAG="" # --global
|
|||
CACHE_FLAG="" # --no-exclude-cache
|
||||
JSON_FLAG="" # --json
|
||||
TELEMETRY_FLAG="" # --with-telemetry-recipe
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/token-hotspots-cli.mjs <path> --output-file /tmp/config-audit-tokens.json $GLOBAL_FLAG $CACHE_FLAG $JSON_FLAG $TELEMETRY_FLAG $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/token-hotspots-cli.mjs "<path>" --output-file /tmp/config-audit-tokens.json $GLOBAL_FLAG $CACHE_FLAG $JSON_FLAG $TELEMETRY_FLAG $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
`--json` and `--with-telemetry-recipe` must be threaded here, not just
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
|
|||
# arg loop would take it as the TARGET PATH instead of a flag.
|
||||
VERBOSE_FLAG="" # --verbose
|
||||
SUGGEST_FLAG="" # --suggest-disables
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/whats-active.mjs <path> --output-file /tmp/config-audit-whats-active.json $VERBOSE_FLAG $SUGGEST_FLAG $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
node ${CLAUDE_PLUGIN_ROOT}/scanners/whats-active.mjs "<path>" --output-file /tmp/config-audit-whats-active.json $VERBOSE_FLAG $SUGGEST_FLAG $RAW_FLAG >/dev/null 2>/dev/null; echo $?
|
||||
```
|
||||
|
||||
**Exit code handling:**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue