feat(humanizer): update action command templates [skip-docs]

Wave 5 Step 15. Threads --raw plumbing through all seven action
command templates and adds a shape test covering structural plumbing
plus help.md's plain-language vocabulary.

- commands/fix.md: --raw flag parsed; fix-plan rendering groups by
  userActionLanguage; humanized title/description/recommendation are
  rendered verbatim from the cross-referenced scan envelope.
- commands/rollback.md: terminology pass — "manifest" → "list of
  changes" in user-facing copy; the file name manifest.yaml is kept
  as the machine contract; --raw threaded through.
- commands/plan.md: --raw forwarded to the planner-agent's prompt;
  agent now instructed to group actions by userImpactCategory and
  lead with userActionLanguage; bash block added for flag parsing.
- commands/implement.md: --raw forwarded to the implementer-agent's
  prompt; progress-log lines now reference the humanized titles
  already present in the action plan.
- commands/cleanup.md: --raw accepted as no-op (cleanup is
  file-management only, no findings prose); bash block added.
- commands/help.md: full plain-language pass — "PreToolUse" and
  "frontmatter" jargon removed from user-facing copy; new
  vocabulary table surfaces the humanized userImpactCategory and
  userActionLanguage labels ("Configuration mistake", "Conflict",
  "Wasted tokens", "Missed opportunity", "Dead config" / "Fix this
  now", "Fix soon", "Fix when convenient", "Optional cleanup",
  "FYI"); --raw documented as global pass-through flag.
- commands/interview.md: --raw accepted as no-op; "unused hooks"
  question phrased as "unused automation that runs at specific
  events" in user-facing copy.

tests/commands/action-commands-shape.test.mjs (new, +6 tests, 780 → 786):
  - structural: bash block + Read tool + --raw/$ARGUMENTS plumbing
    across all 7 files
  - help.md vocabulary: ≥3 userImpactCategory labels and ≥3
    userActionLanguage phrases present
  - help.md jargon: no bare "PreToolUse" or "frontmatter" in copy
This commit is contained in:
Kjell Tore Guttormsen 2026-05-01 19:50:47 +02:00
commit 347d4a2c4c
8 changed files with 228 additions and 40 deletions

View file

@ -13,13 +13,23 @@ Manage and clean up accumulated config-audit sessions in `~/.claude/config-audit
```
/config-audit cleanup
/config-audit cleanup --raw # pass-through accepted; no-op (cleanup is file-management only, no findings prose)
```
## Implementation Steps
0. **Parse flags**:
```bash
RAW_FLAG=""
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
```
`--raw` is accepted for CLI surface consistency but is a no-op here — cleanup manages session directories on disk, it does not produce findings prose.
1. **List all sessions**:
- Glob `~/.claude/config-audit/sessions/*/state.yaml`
- For each session, read state.yaml and extract:
- Use the Read tool on each session's state.yaml and extract:
- Session ID
- Created timestamp
- Current phase
@ -27,7 +37,7 @@ Manage and clean up accumulated config-audit sessions in `~/.claude/config-audit
2. **Calculate disk usage**:
- Use `du -sh ~/.claude/config-audit/sessions/{session-id}/` for each session
- Calculate total usage
- Calculate the total amount of disk space used
3. **Display session table**:
```

View file

@ -15,6 +15,7 @@ Auto-fix deterministic configuration issues. Scans, plans fixes, backs up origin
- `$ARGUMENTS` may contain:
- A target path (default: current working directory)
- `--dry-run`: Show fix plan without applying
- `--raw`: Pass-through to scanners; produces v5.0.0 verbatim envelope (bypasses the humanizer) for byte-stable diff tooling
## Implementation
@ -28,44 +29,50 @@ Tell the user:
Scanning for auto-fixable issues...
```
Run scanners silently:
Parse flags and run scanners silently. Default mode emits humanized JSON — each finding carries `userImpactCategory`, `userActionLanguage`, and `relevanceContext` alongside the v5.0.0 fields:
```bash
node ${CLAUDE_PLUGIN_ROOT}/scanners/scan-orchestrator.mjs <path> --output-file /tmp/config-audit-fix-scan-$$.json [--global] 2>/dev/null; echo $?
RAW_FLAG=""
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
node ${CLAUDE_PLUGIN_ROOT}/scanners/scan-orchestrator.mjs <path> --output-file /tmp/config-audit-fix-scan-$$.json [--global] $RAW_FLAG 2>/dev/null; echo $?
```
Exit code 3 → tell user: "Scanner error. Try `/config-audit posture` to check your configuration."
### Step 2: Plan fixes
Run fix planner silently:
Run fix planner silently. The fix-cli emits humanized prose to stderr in default mode and v5.0.0-shape JSON to stdout when `--json` is set; we use `--json` here for structured data and let the humanizer-aware rendering layer (this command's prose output below) supply the plain-language wording from the scan envelope above:
```bash
node ${CLAUDE_PLUGIN_ROOT}/scanners/fix-cli.mjs <path> --json 2>/dev/null
```
Read the JSON output. Categorize fixes into auto-fixable and manual.
Read the JSON output using the Read tool. Cross-reference each fix-plan entry against the humanized scan envelope (`/tmp/config-audit-fix-scan-$$.json`) by finding ID to recover the humanized `title`/`description`/`recommendation` plus `userImpactCategory`/`userActionLanguage` for grouping.
### Step 3: Present fix plan
Show what will be fixed and what needs manual attention:
Show what will be fixed and what needs manual attention. Group by `userActionLanguage` so the urgency phrasing stays consistent with the rest of the toolchain:
```markdown
### Fix Plan
**Auto-fixable ({N} issues):**
**Auto-fixable ({N} issues), grouped by impact:**
{For each userActionLanguage bucket in priority order — "Fix this now" → "Fix soon" → "Fix when convenient" → "Optional cleanup" → "FYI":}
#### {userActionLanguage}
| # | ID | Issue | File |
|---|-----|-------|------|
| 1 | CA-SET-003 | Add $schema to settings.json | .claude/settings.json |
| 2 | ... | ... | ... |
| 1 | {id} | {humanized title} | {file} |
**Manual ({M} issues — require human judgment):**
**Manual ({M} issues — require human judgment), grouped by impact:**
{Same userActionLanguage grouping. Render humanized title and recommendation verbatim — the humanizer already produced plain-language strings, do not paraphrase.}
| # | ID | Issue | Recommendation |
|---|-----|-------|----------------|
| 1 | CA-CML-003 | CLAUDE.md exceeds 200 lines | Split content into @imports or .claude/rules/ |
| ... | ... | ... | ... |
| 1 | {id} | {humanized title} | {humanized recommendation} |
```
### Step 4: Confirm with user

View file

@ -1,7 +1,7 @@
---
name: config-audit:help
description: Show all available config-audit commands
allowed-tools: Read
allowed-tools: Read, Bash
model: sonnet
---
@ -11,6 +11,19 @@ model: sonnet
Just run `/config-audit` — it auto-detects your project scope and runs a full audit. No setup needed.
The default output is written in plain language: each finding is grouped by impact ("Configuration mistake," "Conflict," "Wasted tokens," "Missed opportunity," "Dead config") and led with an urgency phrase ("Fix this now," "Fix soon," "Fix when convenient," "Optional cleanup," "FYI").
If you prefer the v5.0.0 verbatim output (technical IDs, raw severity, no plain-language wording), pass `--raw` to any command — it's threaded through every CLI in the toolchain. Use the Read tool on the saved JSON to consume it programmatically.
```bash
# Examples — every command accepts --raw for byte-stable v5.0.0 output
RAW_FLAG=""
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
# /config-audit posture --raw
# /config-audit tokens --raw
# /config-audit fix --raw
```
## All Commands
### Core
@ -22,15 +35,15 @@ Just run `/config-audit` — it auto-detects your project scope and runs a full
| `/config-audit tokens` | Opus-4.7 token hotspots; optional `--accurate-tokens` API calibration |
| `/config-audit manifest` | Ranked table of every system-prompt token source |
| `/config-audit feature-gap` | Deep analysis of features you're not using |
| `/config-audit fix` | Auto-fix deterministic issues with backup |
| `/config-audit rollback` | Restore configuration from a backup |
| `/config-audit fix` | Auto-fix deterministic issues; a copy of every changed file is saved first so you can roll back with one command |
| `/config-audit rollback` | Restore configuration from a saved copy |
### Planning & Implementation
| Command | Description |
|---------|-------------|
| `/config-audit plan` | Generate prioritized action plan from audit findings |
| `/config-audit implement` | Execute action plan with automatic backup + verification |
| `/config-audit implement` | Execute action plan; a copy of every changed file is saved first, and a verification pass runs after |
| `/config-audit interview` | Set preferences to customize the action plan _(optional)_ |
### Monitoring
@ -38,7 +51,7 @@ Just run `/config-audit` — it auto-detects your project scope and runs a full
| Command | Description |
|---------|-------------|
| `/config-audit drift` | Compare current config against a saved baseline |
| `/config-audit plugin-health` | Audit plugin structure and frontmatter quality |
| `/config-audit plugin-health` | Audit plugin structure and the metadata block at the top of each command/agent file |
| `/config-audit whats-active` | Show active plugins/skills/MCP/hooks/CLAUDE.md with token estimates |
### Utility
@ -55,6 +68,25 @@ Just run `/config-audit` — it auto-detects your project scope and runs a full
| `/config-audit discover` | Run only the discovery phase (find config files) |
| `/config-audit analyze` | Run only the analysis phase (generate report) |
## Plain-language vocabulary
The toolchain uses these terms when describing findings:
| User-facing label | What it means |
|-------------------|---------------|
| Fix this now | Something is broken or risky and should be addressed immediately |
| Fix soon | High-priority issue worth scheduling this week |
| Fix when convenient | Real issue but not urgent |
| Optional cleanup | Tidy-up that improves polish but isn't required |
| FYI | Informational; no action expected |
| Configuration mistake | A configuration file has an error or omission |
| Conflict | Two configuration sources disagree |
| Wasted tokens | Configuration is loading content that costs tokens without payback |
| Missed opportunity | A Claude Code feature you aren't using that could help your project |
| Dead config | Configuration that has no effect (e.g., a permission that's also denied) |
Use `--raw` if you'd rather see the v5.0.0 verbatim output (technical IDs and raw severity).
## Scope Override
By default, `/config-audit` auto-detects scope from your current directory:

View file

@ -14,13 +14,22 @@ Execute the action plan with full backup, verification, and rollback support.
- Must have completed Phase 4 (plan)
- Action plan at `~/.claude/config-audit/sessions/{session-id}/action-plan.md`
## Arguments
- `$ARGUMENTS` may contain `--raw` to forward to the implementer-agent's instructions; in `--raw` mode the agent renders v5.0.0 verbatim severity prefiks instead of humanized `userActionLanguage` urgency phrasing.
## Implementation
### Step 1: Load and verify
### Step 1: Parse flags, load and verify
```bash
RAW_FLAG=""
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
```
Find the most recent session with a plan. If none: "No action plan found. Run `/config-audit plan` first."
Read the action plan and count actions. Tell the user:
Use the Read tool on the action plan and count actions. Tell the user:
```
## Implementing Action Plan
@ -62,16 +71,20 @@ Agent(subagent_type: "config-audit:implementer-agent")
prompt: |
Execute action: {action-id}
File: {file-path}, Type: {create|modify|delete}
Mode: $RAW_FLAG (empty = humanized progress prose; "--raw" = v5.0.0 verbatim)
Details: {changes}
Verify backup exists, make change, validate syntax.
Append result to: ~/.claude/config-audit/sessions/{session-id}/implementation-log.md
When logging progress, use the humanized title/userActionLanguage
fields from the action plan (the planner already rendered them) —
do not re-derive severity prose. Append result to:
~/.claude/config-audit/sessions/{session-id}/implementation-log.md
```
Show progress between groups:
Show progress between groups using the humanized titles already present in the action plan:
```
Action 1/N: {title} — done
Action 2/N: {title} — done
Action 1/N: {humanized title} — done
Action 2/N: {humanized title} — done
...
```

View file

@ -1,7 +1,7 @@
---
name: config-audit:interview
description: Phase 3 - Interactive interview to gather user preferences
allowed-tools: Read, Write, Edit, AskUserQuestion
allowed-tools: Read, Write, Edit, AskUserQuestion, Bash
model: sonnet
---
@ -17,10 +17,21 @@ AskUserQuestion requires synchronous terminal interaction and does not work when
## Prerequisites
- Must have completed Phase 2 (analysis)
- Read analysis from `~/.claude/config-audit/sessions/{session-id}/analysis-report.md`
- Use the Read tool on the analysis at `~/.claude/config-audit/sessions/{session-id}/analysis-report.md`
## Arguments
- `$ARGUMENTS` may contain `--raw` — pass-through accepted for CLI surface consistency. Interview is interactive prose only (no scanner output, no findings prose), so `--raw` is a no-op here.
## Implementation Steps
0. **Parse flags**:
```bash
RAW_FLAG=""
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
```
1. **Load session state**: Verify analysis phase completed, read analysis report for context
2. **Conduct interview inline**: Use AskUserQuestion tool directly (NOT via Task). Adapt questions based on analysis findings.
3. **Save interview results**: Write to `~/.claude/config-audit/sessions/{session-id}/interview.md`
@ -29,10 +40,10 @@ AskUserQuestion requires synchronous terminal interaction and does not work when
## Interview Questions
Ask these using AskUserQuestion (skip questions that don't apply based on analysis):
Ask these using AskUserQuestion (skip questions that don't apply based on analysis). Where the analysis report references finding IDs, use the humanized title from the report rather than re-deriving prose:
1. **Config Style** — Centralized vs Distributed vs Hybrid organization
2. **Unused Hooks** — Wire up, review individually, delete, or leave (only if found)
2. **Unused automation that runs at specific events** — Wire up, review individually, delete, or leave (only if the analysis report flagged one)
3. **Duplicate Permissions** — Remove from local, consolidate, or keep (only if found)
4. **Modular Rules** — Use .claude/rules/ pattern? Yes/No
5. **Path-Scoped Rules** — Which patterns (tests, src, config, docs) — only if Q4=Yes

View file

@ -1,7 +1,7 @@
---
name: config-audit:plan
description: Phase 4 - Generate prioritized action plan with risk assessment
allowed-tools: Read, Write, Glob, Grep, Agent
allowed-tools: Read, Write, Glob, Grep, Agent, Bash
model: opus
---
@ -14,11 +14,15 @@ Generate a prioritized action plan based on analysis results.
- Must have completed Phase 2 (analysis)
- Phase 3 (interview) is optional — plan works with or without it
## Arguments
- `$ARGUMENTS` may contain `--raw` to forward to the planner-agent's instructions; in `--raw` mode the agent renders v5.0.0 verbatim severity prefiks instead of humanized `userActionLanguage` urgency phrasing.
## Implementation
### Step 1: Verify session state
Find the most recent session with analysis completed. If none found: "No analysis results found. Run `/config-audit` first to scan your configuration."
Find the most recent session with analysis completed using the Read tool on `~/.claude/config-audit/sessions/*/state.yaml`. If none found: "No analysis results found. Run `/config-audit` first to scan your configuration."
### Step 2: Tell the user what's happening
@ -29,7 +33,12 @@ Building a prioritized plan based on your analysis results...
Actions are ordered by impact, with risk assessment and dependency tracking.
```
### Step 3: Spawn planner agent
### Step 3: Parse flags and spawn planner agent
```bash
RAW_FLAG=""
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
```
Tell the user: **"Generating your action plan (this takes about 30 seconds)..."**
@ -40,8 +49,18 @@ Agent(subagent_type: "config-audit:planner-agent")
Generate action plan based on:
- Analysis: ~/.claude/config-audit/sessions/{session-id}/analysis-report.md
- Interview: ~/.claude/config-audit/sessions/{session-id}/interview.md (if exists)
Create prioritized plan with:
- Risk assessment per action (low/medium/high)
Mode: $RAW_FLAG (empty = humanized; "--raw" = v5.0.0 verbatim severity prefiks)
Create a prioritized plan that consumes the humanized finding fields:
- Group actions by userImpactCategory (e.g., "Configuration mistake",
"Conflict", "Wasted tokens", "Missed opportunity", "Dead config")
- Lead each action with userActionLanguage ("Fix this now," "Fix soon,"
"Fix when convenient," "Optional cleanup," "FYI") rather than raw
severity. The humanizer already replaced jargon-heavy
title/description/recommendation strings with plain-language
equivalents — render them verbatim, do not paraphrase.
- Surface relevanceContext when it isn't "affects-everyone" so the
user knows whether a fix touches shared config or just their machine
- Include risk assessment per action (low/medium/high)
- Rollback strategy
- Dependency ordering
- Effort estimates

View file

@ -13,12 +13,19 @@ Restore configuration files from a previous backup. Without arguments, lists ava
## Arguments
- `$ARGUMENTS` may contain a backup ID (format: `YYYYMMDD_HHMMSS`)
- `--raw`: pass-through flag accepted for CLI surface consistency. Rollback is file restoration only (no scanner output, no findings prose), so `--raw` is a no-op here, but the flag is still parsed so users get uniform behaviour across the toolchain.
## Behavior
### List mode (no argument)
List available backups from `~/.claude/config-audit/backups/`:
Parse flags and list available backups from `~/.claude/config-audit/backups/`:
```bash
RAW_FLAG=""
if echo "$ARGUMENTS" | grep -q -- "--raw"; then RAW_FLAG="--raw"; fi
ls -1 ~/.claude/config-audit/backups/
```
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@ -33,11 +40,11 @@ List available backups from `~/.claude/config-audit/backups/`:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
Read each backup's `manifest.yaml` to extract file list and timestamps.
Use the Read tool on each backup's `manifest.yaml` (the list of changes captured at backup time) to extract the file list and timestamps.
### Restore mode (with backup ID)
1. Read manifest from `~/.claude/config-audit/backups/{backup-id}/manifest.yaml`
1. Read the list of changes from `~/.claude/config-audit/backups/{backup-id}/manifest.yaml` using the Read tool
2. Show files that will be restored — ask for confirmation:
```
AskUserQuestion:
@ -46,10 +53,10 @@ Read each backup's `manifest.yaml` to extract file list and timestamps.
- "Yes, restore"
- "Cancel"
```
3. For each file in manifest:
a. Read backup file from `~/.claude/config-audit/backups/{backup-id}/files/{safeName}`
b. Write to original path
c. Verify checksum matches manifest
3. For each file in the list of changes:
a. Read the backup file from `~/.claude/config-audit/backups/{backup-id}/files/{safeName}`
b. Write to the original path
c. Verify the checksum matches the recorded value in the list of changes
4. Show result:
```
Restored 3 files from backup 20260403_163045

View file

@ -0,0 +1,89 @@
/**
* Wave 5 Step 15 Action-command-template shape tests.
*
* Verifies that the 7 action command templates have the correct structural
* shape after the humanizer integration:
*
* - All 7 files: contain a Bash invocation block, reference the Read tool,
* and contain the `--raw` flag (or the literal `"$ARGUMENTS"` string) so
* `--raw` plumbing is uniform across the toolchain.
*
* - help.md additionally: removes the most obviously technical jargon
* ("PreToolUse" / "frontmatter" mentions in the user-facing prose) and
* introduces a plain-language vocabulary table referencing the
* humanized userImpactCategory and userActionLanguage labels.
*/
import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const COMMANDS_DIR = resolve(__dirname, '..', '..', 'commands');
const ACTION_FILES = [
'fix.md',
'rollback.md',
'plan.md',
'implement.md',
'cleanup.md',
'help.md',
'interview.md',
];
const RAW_OR_ARGUMENTS_REGEX = /--raw|"\$ARGUMENTS"/;
const BASH_BLOCK_REGEX = /```bash\b/;
const READ_TOOL_REGEX = /\bRead\s+tool\b|allowed-tools:.*\bRead\b/;
async function readCommand(name) {
return await readFile(resolve(COMMANDS_DIR, name), 'utf-8');
}
test('Action: every file contains a Bash invocation block', async () => {
for (const name of ACTION_FILES) {
const content = await readCommand(name);
assert.match(content, BASH_BLOCK_REGEX, `${name} missing bash block`);
}
});
test('Action: every file references the Read tool', async () => {
for (const name of ACTION_FILES) {
const content = await readCommand(name);
assert.match(content, READ_TOOL_REGEX, `${name} missing Read tool reference`);
}
});
test('Action: every file contains --raw or "$ARGUMENTS" (pass-through plumbing)', async () => {
for (const name of ACTION_FILES) {
const content = await readCommand(name);
assert.match(content, RAW_OR_ARGUMENTS_REGEX, `${name} missing --raw / $ARGUMENTS plumbing`);
}
});
test('help.md: introduces plain-language vocabulary referencing humanized categories', async () => {
const content = await readCommand('help.md');
// At least three of the userImpactCategory labels should appear
const labels = ['Configuration mistake', 'Conflict', 'Wasted tokens', 'Missed opportunity', 'Dead config'];
const present = labels.filter(l => content.includes(l));
assert.ok(present.length >= 3, `help.md must surface ≥3 humanized impact labels; found ${present.length}: ${present.join(', ')}`);
// At least three of the userActionLanguage phrases should appear
const actions = ['Fix this now', 'Fix soon', 'Fix when convenient', 'Optional cleanup', 'FYI'];
const presentActions = actions.filter(a => content.includes(a));
assert.ok(presentActions.length >= 3, `help.md must surface ≥3 humanized action phrases; found ${presentActions.length}: ${presentActions.join(', ')}`);
});
test('help.md: no bare "PreToolUse" jargon in user-facing copy', async () => {
const content = await readCommand('help.md');
// Allow the word in code/quoted contexts but the body table descriptions should not lean on it.
// Heuristic: no occurrence of "PreToolUse" outside of code spans / quoted blocks.
// Simple check: no "PreToolUse" anywhere except in any backtick span — since this file is doc-only,
// require zero occurrences.
assert.doesNotMatch(content, /\bPreToolUse\b/, 'help.md user copy must not lean on "PreToolUse" jargon — use plain language');
});
test('help.md: no bare "frontmatter" jargon in user-facing copy', async () => {
const content = await readCommand('help.md');
assert.doesNotMatch(content, /\bfrontmatter\b/, 'help.md user copy must not lean on "frontmatter" jargon — use plain language ("metadata block at the top of each file")');
});