config-audit/commands/analyze.md
Kjell Tore Guttormsen 09f817977c fix(commands): stop assuming shell state survives between blocks
Dogfooding `plan` + `implement` against a throwaway config surfaced one root
defect with many arms: the command templates treat consecutive fenced blocks as
one shell. They are not. Every ```bash fence runs as its own Bash call in its own
process, so a variable set in one block is empty in the next, and `$$` is a
different PID (measured: 21710 vs 22109).

The planner agent confirmed the sharpest arm at runtime, reporting that
`Mode: $RAW_FLAG` "arrived literally unsubstituted" — `--raw` was documented in
three command files while being functionally dead. A machine sweep found the same
root in 20 places across 9 files, well past the two the written fasit predicted:

  - `$RAW_FLAG` read from non-shell agent prompts (analyze, plan, implement)
  - `$TMPFILE` read across blocks (tokens, manifest, whats-active,
    plugin-health) — each command could not read the file it had just written
  - `$GLOBAL_FLAG` across blocks (fix)
  - `$TODAY` never assigned in any block (campaign), passing
    `--reference-date ""` to a write CLI in six places
  - three `$$` temp paths handed to the Read tool (fix), which expands neither

All now follow the hardened drift.md pattern: a fixed literal path, or a
re-derivation inside each block that needs it.

Also fixed, all confirmed against ground truth rather than inferred:

  - `implement` printed a rollback ID it never captured (the timestamp lived only
    inside a command substitution) — the one message a user reads after a bad run
  - `plan` reported "No analysis results found" for valid sessions, because Read
    was pointed at a glob it cannot expand; now uses Glob and verifies the
    analysis report exists before spawning the agent
  - five phase commands wrote state.yaml with two of four required fields; since
    the agent writes all four, a follow-up write silently deleted the rest
  - `implement` promised rollback deletes created files; rollback deliberately
    leaves them (M-BUG-26 still open) — the doc, not the engine, was wrong
  - `implement` claimed a score delta with no pre-change measurement
  - `verifier-agent` was told to write a report it has no tool to write
  - dead `Task` tool name in always-loaded rule context; planner-agent template
    demonstrated the inline file content its own line 110 forbids

The sweeps land as tests/commands/command-shell-state-shape.test.mjs, verified
red before the fix and proven able to fail by reintroducing the defect. Two
existing tests asserted the old bash-block mechanism rather than the intent and
were updated. Suite 1449/0; frozen v5.0.0 snapshots and all scanner code
untouched.

Not fixed, deliberately: neither command scope-gates its actions to the audit
target. The generated plan included an edit to a real file under ~/.claude,
outside the throwaway target, because the skill/agent scanners are machine-wide.
That is a design change, not a side fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195udHgCcFegzm7ecKku2Yc
2026-08-01 20:12:17 +02:00

4.1 KiB

name description allowed-tools model
config-audit:analyze Phase 2 - Generate analysis report with hierarchy map and issue detection Read, Write, Edit, Glob, Grep, Agent opus

Config-Audit: Analysis (Phase 2)

Generate comprehensive analysis report from discovery findings.

Prerequisites

  • Must have completed Phase 1 (discovery)
  • Findings must exist in ~/.claude/config-audit/sessions/{session-id}/findings/

Arguments

  • $ARGUMENTS may contain --raw to forward to the analyzer agent's instructions; in --raw mode the agent renders v5.0.0 verbatim severity prefiks instead of humanized userActionLanguage urgency phrasing.

Implementation

Step 1: Resolve the session and verify its state

Find the session first — never guess which one {session-id} refers to:

Glob: ~/.claude/config-audit/sessions/*/state.yaml
Sort by modification time — the most recently modified session wins

Every {session-id} below is that session's id. Read its state.yaml using the Read tool and verify discovery phase completed. If the Glob returns nothing, or discovery hasn't completed, tell the user: "Discovery hasn't been run yet. Start with /config-audit discover or just run /config-audit for a full audit."

Step 2: Tell the user what's happening

## Analyzing Configuration

Reading your scan findings and generating a detailed analysis report...
This includes hierarchy mapping, conflict detection, and prioritized recommendations.

Step 3: Spawn analyzer agent

Tell the user: "Generating analysis (this takes about 30 seconds)..."

Check whether $ARGUMENTS contains --raw. Carry the answer yourself: the agent prompt below is not a shell, so a variable assigned in a bash block cannot be referenced from it. Substitute {mode} literally with --raw or humanized.

Agent(subagent_type: "config-audit:analyzer-agent")
  model: sonnet
  prompt: |
    Analyze all findings in: ~/.claude/config-audit/sessions/{session-id}/findings/
    Mode: {mode} ("humanized" = humanized; "--raw" = v5.0.0 verbatim severity prefiks)
    Generate comprehensive report covering:
    1. Executive summary with key metrics, grouped by userImpactCategory
    2. Hierarchy map visualization
    3. Conflict detection across config layers
    4. CLAUDE.md quality assessment
    5. Security issues (secrets, permissions)
    6. Top 10 prioritized recommendations — lead each item with the
       finding's 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.
    Return the complete report as your final message. Do not write it
    to a file — the orchestrating command saves it to the session directory.

Step 4: Save the report

The agent returns the complete report as its final message — the Claude Code subagent harness instructs agents not to write report/analysis files themselves, so the command must persist it. Write the returned report verbatim (no edits, no truncation) to ~/.claude/config-audit/sessions/{session-id}/analysis-report.md using the Write tool. Downstream phases (plan, interview, status) read this file.

Step 5: Present summary

After saving the report, show a brief summary:

### Analysis Complete

Report generated with:
- {N} conflicts detected
- {N} optimization opportunities
- {N} security notes
- Top recommendation: {first recommendation}

Full report: `~/.claude/config-audit/sessions/{session-id}/analysis-report.md`

### What's next

- **`/config-audit plan`** — Turn findings into a prioritized action plan
- **`/config-audit fix`** — Auto-fix deterministic issues right away

Step 6: Update state

Update state.yaml with all four fields .claude/rules/state-management.md requires: current_phase: "analyze", completed_phases (append analyze to the existing array — read it first), next_phase: "plan", and updated_at. A write that names only two of the four silently deletes the other two.