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
202 lines
8.2 KiB
Markdown
202 lines
8.2 KiB
Markdown
---
|
|
name: config-audit:feature-gap
|
|
description: Context-aware feature recommendations — what could enhance your setup and why
|
|
argument-hint: "[path]"
|
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Agent, AskUserQuestion
|
|
model: opus
|
|
---
|
|
|
|
# Config-Audit: Feature Opportunities
|
|
|
|
Context-aware analysis of Claude Code features that could benefit your specific project — with the option to implement selected recommendations on the spot.
|
|
|
|
## What the user gets
|
|
|
|
- Project context detection (language, size, existing configuration)
|
|
- Numbered recommendations grouped by impact (high / worth considering / explore)
|
|
- Each recommendation backed by evidence (Anthropic docs, proven issues)
|
|
- **Interactive selection: "Which would you like to implement?"**
|
|
- Direct implementation with backup for selected items
|
|
|
|
## Implementation
|
|
|
|
### Step 1: Determine target and flags
|
|
|
|
Split `$ARGUMENTS` into a path and flags. Path is the first non-flag argument (default: current working directory). Recognized flags:
|
|
|
|
- `--raw` — pass-through to the scanner; produces v5.0.0 verbatim envelope (bypasses the humanizer). When `--raw` is set, render with v5.0.0 finding-field shape only — humanizer fields are absent in raw output.
|
|
|
|
Tell the user:
|
|
|
|
```
|
|
## Feature Opportunities
|
|
|
|
Analyzing which Claude Code features could benefit your workflow...
|
|
```
|
|
|
|
### Step 2: Create session and run posture
|
|
|
|
Generate session ID (`YYYYMMDD_HHmmss`) if no active session exists.
|
|
|
|
```bash
|
|
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 $?
|
|
```
|
|
|
|
If exit code is non-zero: "Assessment couldn't run. Check that the path exists and contains configuration files."
|
|
|
|
### Step 3: Read posture data and detect project context
|
|
|
|
Read `~/.claude/config-audit/sessions/{session-id}/posture.json` using the Read tool.
|
|
|
|
Extract GAP findings from `scannerEnvelope.scanners` (find scanner with `scanner === 'GAP'`).
|
|
|
|
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
|
|
```
|
|
|
|
### Step 4: Build numbered recommendations
|
|
|
|
Read `${CLAUDE_PLUGIN_ROOT}/knowledge/gap-closure-templates.md` for implementation templates.
|
|
|
|
Group GAP findings by their humanized fields rather than re-deriving tier-to-prose mappings. In default mode (no `--raw`) each finding carries:
|
|
|
|
- `userImpactCategory` (e.g., "Missed opportunity") — the impact bucket
|
|
- `userActionLanguage` (e.g., "Fix soon", "Fix when convenient", "Optional cleanup", "FYI") — the urgency phrasing the rest of the toolchain uses
|
|
- `relevanceContext` ("affects-everyone" / "affects-this-machine-only" / "test-fixture-no-impact") — the scope so the user knows whether the change touches shared config or just their own machine
|
|
|
|
Group findings into three sections by `userActionLanguage`: "Fix this now" + "Fix soon" → **High Impact**, "Fix when convenient" → **Worth Considering**, "Optional cleanup" + "FYI" → **Explore When Ready**. Number sequentially across sections. Skip findings whose `relevanceContext === "test-fixture-no-impact"` unless the user explicitly asked to include fixtures.
|
|
|
|
The humanizer has already replaced jargon-heavy strings with plain-language equivalents in `title`, `description`, and `recommendation` — render those verbatim. Do not paraphrase. Do not introduce inline tier-to-prose tables ("Tier 1 means…"); the categories are pre-translated.
|
|
|
|
If `--raw` was passed, the v5.0.0 envelope is in effect — humanizer fields are absent. Fall back to grouping by `category` ("t1"/"t2"/"t3"/"t4") and render `title` + `recommendation` directly.
|
|
|
|
Render shape (default mode):
|
|
|
|
```markdown
|
|
### High Impact
|
|
|
|
{For each finding where userActionLanguage is "Fix this now" or "Fix soon":}
|
|
|
|
**{N}.** {title}
|
|
→ {description}
|
|
→ {recommendation}
|
|
→ Effort: {from gap-closure-templates.md}
|
|
|
|
### Worth Considering
|
|
|
|
{For each finding where userActionLanguage is "Fix when convenient":}
|
|
|
|
**{N}.** {title}
|
|
→ {description}
|
|
→ {recommendation}
|
|
|
|
### Explore When Ready
|
|
|
|
{For each finding where userActionLanguage is "Optional cleanup" or "FYI":}
|
|
|
|
**{N}.** {title}
|
|
→ {recommendation}
|
|
```
|
|
|
|
Each recommendation MUST have:
|
|
- A number
|
|
- The humanizer-provided `title`
|
|
- The humanizer-provided `description` (where shown)
|
|
- An effort estimate looked up from the templates
|
|
|
|
### Step 5: Ask what to implement
|
|
|
|
```
|
|
AskUserQuestion:
|
|
question: "Which would you like to implement? I'll create a backup first."
|
|
options:
|
|
- "All high impact (1-2)"
|
|
- "Pick specific: e.g. 1,3,5"
|
|
- "None — just wanted to see the recommendations"
|
|
```
|
|
|
|
If "None": show the full report location and exit.
|
|
|
|
If the user picks numbers: parse the selection and proceed to Step 6.
|
|
|
|
### Step 6: Implement selected recommendations
|
|
|
|
For each selected recommendation:
|
|
|
|
1. **Create backup** of any files that will be modified.
|
|
|
|
Do **not** reach for `fix-cli.mjs` here. It is dry-run by default, so calling
|
|
it without `--apply` creates no backup at all and returns `backupId: null` —
|
|
and calling it *with* `--apply` would execute unrelated auto-fixes that the
|
|
user never selected. Copy the files yourself:
|
|
|
|
```bash
|
|
BACKUP_DIR=~/.claude/config-audit/backups/$(date +%Y%m%d_%H%M%S)/files
|
|
mkdir -p "$BACKUP_DIR" 2>/dev/null
|
|
# repeat per file that will be touched:
|
|
cp "<file-to-modify>" "$BACKUP_DIR/" 2>/dev/null; echo $?
|
|
```
|
|
|
|
Tell the user where the copies landed. These are plain file copies — they are
|
|
restored by copying them back, **not** by `/config-audit rollback`, which only
|
|
knows about backups written by `fix` and `implement`.
|
|
|
|
2. **Apply the template** from gap-closure-templates.md. Use the Write or Edit tool to create or modify the relevant configuration file.
|
|
|
|
3. **Show progress** as each item is done:
|
|
```
|
|
Implementing 3 recommendations...
|
|
|
|
✓ 1. permissions.deny — added to .claude/settings.json
|
|
✓ 3. Modular CLAUDE.md — created .claude/rules/testing.md, added @import
|
|
✓ 5. Keybindings — created ~/.claude/keybindings.json
|
|
```
|
|
|
|
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
|
|
```
|
|
|
|
Use the Read tool on `/tmp/config-audit-verify.json` for the new `overallGrade`
|
|
and score — stdout is discarded on purpose (the same envelope is 255 KB).
|
|
|
|
### Step 7: Show results
|
|
|
|
```markdown
|
|
### Done
|
|
|
|
**{N} recommendations implemented** | Backup created
|
|
|
|
{If health grade changed:}
|
|
Health: {old_grade} → {new_grade} (+{delta} points)
|
|
|
|
{Show remaining opportunities if any:}
|
|
{remaining} more opportunities available — run `/config-audit feature-gap` again anytime.
|
|
|
|
**Rollback:** If anything looks wrong, run `/config-audit rollback` to restore.
|
|
```
|
|
|
|
## Implementation Guidelines
|
|
|
|
When implementing recommendations, be smart about context:
|
|
|
|
- **permissions.deny**: Look at the project for common sensitive paths (`.env`, `secrets/`, `.git/config`, `*.pem`). Don't just copy a template blindly — check what actually exists.
|
|
- **hooks**: Start with a simple, useful hook. Don't scaffold 5 hooks at once.
|
|
- **path-scoped rules**: Look at the project's file structure to determine meaningful scopes (e.g., `tests/**/*.ts` vs `src/**/*.ts`).
|
|
- **CLAUDE.md modularization**: Only suggest splitting if the file is over 100 lines. Read it first to find natural section boundaries.
|
|
- **MCP setup**: Only relevant if the user actually has external tools to connect. Ask before creating.
|
|
- **Custom plugin**: Too complex for inline implementation — suggest `/config-audit plan` instead.
|
|
|
|
For items that genuinely need user input (e.g., "which MCP servers do you use?"), ask briefly during implementation rather than skipping them.
|
|
|
|
## Safety
|
|
|
|
- **Backup mandatory** — always create before modifying
|
|
- **Show what's changing** — the user sees each change as it happens
|
|
- **Rollback available** — `/config-audit rollback` at any time
|
|
- **Non-destructive** — only create new files or add to existing; never delete content
|