config-audit/commands/optimize.md
Kjell Tore Guttormsen 000e47f9d2 feat(scanners): the subtraction axis can now remove what it proposes (SUB-WRITE)
`optimize --subtract` has only ever proposed. `--apply` executes the blocks the
operator picks, behind a backup whose coverage is verified and a scope gate the
engine enforces rather than describes.

The open design decision from plan §C6 was settled by two measurements, not by
taste. It is NOT a fix-engine action: the subtraction axis appears nowhere in
scan-orchestrator or optimization-lens-scanner, so verifyFixes' re-scan would
mark every removal `verified` whether or not it happened -- a success-shaped
no-op, the same shape that made restoreBackup silently do nothing. It is NOT a
plan/implement step either: that pipeline needs a finding code, and OPT declares
exactly one, for the deterministic check.

The approval artifact is written by main context, not by the lens agent. That is
where the operator's decision actually happens, and it keeps the feature off the
still-unmeasured agent write surface (M-BUG-18 lists optimize as open).

Three properties are load-bearing, and each was seen red against its own defect:
removals validate against the ORIGINAL content and apply in descending line
order; the range check is not redundant with the text check (`line: 0` makes
`slice(-1, 0)` empty, so an empty text MATCHES and `splice(-1, 1)` deletes the
file's last line); and createBackup skips a nonexistent path while still
returning an id, so manifest coverage is asserted before a byte changes.

Two guards were green on their own defect and were fixed after measuring:
`/\b80\s*%\b/` never matches "80% of the file" -- `%` is a non-word character, so
the trailing `\b` demands a word character next. And the caller-arm sweep passed
vacuously against HEAD, iterating an empty list; only the added non-emptiness
assertion caught it.

The floor is repeated, not moved: floor-exclusion still vetoes before anything is
proposed, and the engine refuses a load-bearing block again so a hand-built
approval cannot route around it. `mv` to `_archive/` is a file-level rule and
does not apply to a block excision -- the timestamped backup is the recovery
artifact, and a second copy with no restorer would be worse than none.

strongestGate moves into write-scope.mjs so the gate ordering has one owner.

Dogfooded DRY-RUN against the real ~/.claude/CLAUDE.md: 29 candidates, gate
refused all 29 with exit 0 until the scope was approved, then 29/29 spans
validated with nothing written. ~789 tokens, ~18% of the file -- corroborating
the #40 fasit's ~850, and well short of what a deletion feature is tempted to
promise.

Suite 1625 -> 1659/0. Frozen v5.0.0 and default-output baselines untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017A6vrtPKsVuM4DJ27p7jzw
2026-08-10 06:10:42 +02:00

232 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: config-audit:optimize
description: Optimization lens — config that works but would fit a better mechanism (procedure→skill, lifecycle→hook, path→rule, never→permission)
argument-hint: "[path]"
allowed-tools: Read, Write, Glob, Grep, Bash, Agent
model: opus
---
# Config-Audit: Optimization Lens
The "is the config **optimal?**" axis (vs. the health scanners' "is it
**correct?**"). It finds configuration that *works* but uses a mechanism a
better one would fit — and frames every one as a *Missed opportunity*, never a
mistake.
Mechanism-fit rules come from the provenance-stamped best-practices register
(`knowledge/best-practices.json`); only CONFIRMED rules are surfaced. The motor
is hybrid: a cheap deterministic pre-filter finds candidates, then the opus
`optimization-lens-agent` judges each in context (precision-gated).
## What the user gets
- **Procedures → skills** (deterministic, CA-OPT-001)
- **Lifecycle phrasing → hooks** (BP-MECH-001)
- **Unscoped path-specific instructions → path-scoped rules** (BP-MECH-002)
- **Absolute "never" prohibitions → permissions / hooks** (BP-MECH-004)
- **`--subtract`:** instructions that no longer earn their always-loaded rent (BP-SUB-001)
Each finding cites its register rule + source URL. A clean CLAUDE.md returns "no
opportunities" — that is a good result, not a failure.
## Implementation
### Step 1: Determine target
Split `$ARGUMENTS` into a path (first non-flag argument; default: current working
directory) and flags. Recognized flags: `--global` (include the user `~/.claude`
cascade in discovery), `--subtract` (add the subtraction axis, below) and
`--apply` (execute approved removals — Step 7).
`--apply` only means anything alongside `--subtract`. If it is present without
it, say so and continue with the ordinary lens run:
```
`--apply` executes approved subtraction removals, so it needs `--subtract` too.
Running the ordinary lens; re-run with `--subtract --apply` to remove anything.
```
**`--subtract` — the inverse question.** Every other lens asks what to *add* or
*move*; this one asks what no longer earns its always-loaded rent. It is opt-in
because it asks something different, and because deleting is not undoable by
reading. Pair it with `--global` to reach the user-level CLAUDE.md, where the
always-loaded cost actually sits (it loads in every repo, every session).
If `--subtract` is present, say so up front:
```
Also running the subtraction axis — instructions that cost tokens every turn
without telling me anything I couldn't work out. Load-bearing local facts
(remotes, versions, paths, policy) are excluded before anything is judged.
```
Tell the user:
```
## Optimization Lens
Looking for configuration that works but would fit a better Claude Code mechanism...
```
### Step 2: Run the lens CLI
Generate a session ID (`YYYYMMDD_HHmmss`) if no active session exists.
```bash
mkdir -p ~/.claude/config-audit/sessions/{session-id} 2>/dev/null
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 $?
```
Exit code 0 is normal. Only exit code 3 is a real error → "The lens couldn't run.
Check that the path exists and contains a CLAUDE.md."
### Step 3: Read the payload
Read `~/.claude/config-audit/sessions/{session-id}/optimize-lens.json` with the
Read tool. It has `deterministic` (already-confirmed OPT findings), `candidates`
(pre-filter candidates with register provenance), `register`, and `counts`.
Under `--subtract` it also has a `subtract` block (`candidates`, `register`) and
`counts.subtractCandidates`. Each subtraction candidate spans `line``endLine`
(a whole block). Include the whole `subtract` block when spawning the agent.
**Early exit:** if `counts.deterministic === 0` and `counts.candidates === 0`
(and, under `--subtract`, `counts.subtractCandidates === 0`), skip the agent and
tell the user plainly:
```
✓ No mechanism-fit opportunities found.
Your CLAUDE.md holds facts, not procedures/automation/prohibitions that would be
better as skills, hooks, rules, or permissions. Nothing to change here.
```
Then go to Step 5.
### Step 4: Spawn the precision gate
Tell the user what's happening and set expectations:
```
Found {counts.candidates} candidate line(s) + {counts.deterministic} deterministic finding(s).
Asking the optimization-lens agent to judge each in context (~20-40 seconds)...
```
Spawn the `optimization-lens-agent` (Agent tool) with:
- the full payload from Step 3 (deterministic + candidates + register),
- the session directory path so it can write `optimization-lens-report.md`.
The agent reads the actual CLAUDE.md, drops low-confidence candidates, and keeps
only genuine opportunities — each citing its register rule + source.
### Step 5: Present results
Read the agent's `optimization-lens-report.md` and present it formatted
(markdown tables / grouped sections). Follow the UX rules: never show raw JSON or
scanner progress; lead with a one-sentence summary of what was found before the
detail. Make clear these are LOW-severity *opportunities*.
If the agent kept nothing from the candidates (all dropped) but there were
deterministic findings, show those; if it kept nothing at all, show the clean
result from Step 3.
### Step 7: Apply approved removals (`--subtract --apply` only)
Skip this step entirely unless BOTH flags are present and the agent kept at
least one subtraction finding. Removal is the only thing this plugin does that
takes configuration away, so nothing here happens without a named choice.
**7a — show what is on the table, with honest sizing.** List the kept
subtraction findings numbered, each with its file, line span and first line of
text. Do not imply a bigger win than there is:
```
Removing all of these saves roughly {n} tokens per turn — on a typical
always-loaded CLAUDE.md that is around a fifth of the file, not most of it.
```
Ask which to remove: numbers, `all`, or `none`. `none` ends the command.
**7b — write the approval file.** With the **Write** tool, write the operator's
choice to `~/.claude/config-audit/sessions/{session-id}/subtraction-approved.json`
(absolute path — a relative one resolves against the user's CWD). Take `file`,
`line`, `endLine` and `signalText` verbatim from the Step 3 payload; `text` must
be the `signalText` byte-for-byte, because the engine refuses a removal whose
text no longer matches the file:
```json
{ "sessionId": "{session-id}",
"removals": [ { "file": "...", "line": 12, "endLine": 15, "text": "..." } ] }
```
**7c — dry run first.** Always. It costs one call and proves the spans still
match before anything is written:
```bash
node ${CLAUDE_PLUGIN_ROOT}/scanners/subtraction-write-cli.mjs --approved ~/.claude/config-audit/sessions/{session-id}/subtraction-approved.json --repo "<target-path>" --dry-run --output-file ~/.claude/config-audit/sessions/{session-id}/subtraction-dryrun.json 2>/dev/null; echo $?
```
Read the payload. Exit 3 is a real error (bad or unreadable approval file).
Report any `refused` entry with its `reason` before going further —
`block-mismatch` means the file changed since the scan (re-run the lens),
`floor` means the block is load-bearing and will never be removable.
**7d — the scope gate.** If the dry-run payload has `requiresApproval: true`,
show every line in `disclosures` verbatim and ask for an explicit go-ahead. This
is the machine-wide case (`~/.claude/CLAUDE.md`): the change costs — and saves —
in every project, on every turn, so it is not the same decision as editing the
CLAUDE.md in front of you. Without a clear yes, stop here.
**7e — apply.** Same command without `--dry-run`, adding `--approve-scope` only
if the operator gave that go-ahead in 7d:
```bash
node ${CLAUDE_PLUGIN_ROOT}/scanners/subtraction-write-cli.mjs --approved ~/.claude/config-audit/sessions/{session-id}/subtraction-approved.json --repo "<target-path>" --output-file ~/.claude/config-audit/sessions/{session-id}/subtraction-result.json 2>/dev/null; echo $?
```
**7f — report.** From the result payload, tell the user: what was removed (file
+ line span + the text, from `applied`), what was refused and why (`refused`
with `reason`), and how to undo it:
```
Backed up as {backupId} — `/config-audit rollback {backupId}` restores every
file exactly as it was.
```
Never report a run as successful when `counts.applied` is 0.
### Step 8: Next steps
End with context-sensitive next steps, explaining WHY each is useful:
- `/config-audit plan` — turn the kept opportunities into an action plan with
backups before you change anything.
- `/config-audit feature-gap` — the complementary lens: features you *don't* use
yet (this command is about mechanisms you *do* use that could fit better).
- Re-run `/config-audit optimize` anytime after editing CLAUDE.md.
## Notes
- This command is **agent-driven and not byte-stable** — its output is a
human-facing report, deliberately outside the deterministic snapshot suite.
- `--subtract` **proposes; only `--apply` writes**, and only blocks the operator
named. Every removal is preceded by a backup whose manifest is verified to
cover the file being written, and `/config-audit rollback` restores it.
- **Removal is not a `fix` action and not a `plan`/`implement` step**, by
measurement rather than preference: the subtraction axis never enters the
orchestrated envelope, so `fix`'s re-scan verification would mark every
removal verified whether or not it happened, and the findings pipeline would
require a finding code — which names a deterministic check, not a prose
judgement. `subtraction-write-cli.mjs` owns the execution instead.
- The subtraction floor is deterministic and runs *before* the agent, so a
load-bearing block is never a candidate. It errs toward keeping: on a
well-maintained config this axis is mostly a no-op, and that is a good result.
- The deterministic half (CA-OPT-001) also rides in the normal orchestrated
audit; this command adds the prose-judgment half on top.
- Without `--apply`, no files are modified. To act on a mechanism-fit finding,
use `/config-audit plan``/config-audit implement` (backup + rollback) or
edit by hand.