config-audit/commands
Kjell Tore Guttormsen 1543830c52 feat(commands): a write that leaves the repo says so before you approve it (M-BUG-41)
The chain observed configuration across repos but presented every write it then
proposed as though it landed where the session stands. STATE named two arms;
measuring found five, and two of them are worse than the two already known:

- implement — the approval prompt named NO path at all, only a count, so a plan
  editing ~/.claude/CLAUDE.md and one editing ./CLAUDE.md produced byte-identical
  prompts.
- rollback — the file list rendered `.claude/settings.json`, a repo-relative
  FORM, while the restore writes to the absolute original. The other arms were
  silent; this one pointed the wrong way.
- fix — paths were visible but unclassified, and --global mixed machine-wide and
  project rows into one unmarked table.

The gate's strength comes from the target's scope class, never from the command
asking: five command-owned policies would drift apart the way five copies of the
lever table did. SCOPE_CLASSES is one source for class, gate, wording and
predicate; templates render `disclosures[]` from the CLI instead of restating
what a class means.

Two orderings in that table are load-bearing, and both were measured:

- plugin-managed before user-scope. Both ~/.claude/config-audit/ and the legacy
  ~/.config-audit/ are live, and every command writes session state there. The
  other order fires the gate on every write ever made and gets it switched off,
  which is worse than no gate.
- user-scope before cross-repo. ~/.claude/.git EXISTS, so a plain .git-upward
  walk answers "another repo" for ~/.claude/CLAUDE.md and silently downgrades
  the strongest gate on the subtraction axis's primary target to disclosure.

disclose is not require-ok: campaign export is cross-repo by design, so the gate
there says so rather than refusing. Distinct from require-target-dir.mjs, which
asks whether a scan ROOT is readable (exit 3) — a different invariant, left
unmerged along with its four inline copies.

Also structural, both found while building this: the hand-maintained GUARDED
list in the unknown-flag sweep now derives its completeness from the directory
(measured complete at 14 of 14 first, so nothing was hiding — but the 15th CLI
would have been swept by nothing); and prose shape-guards use whitespace-
tolerant patterns, after one went red against a command file that did say the
right thing, line-wrapped.

Gated: implement, fix, rollback, plan, campaign export. Suite 1596 -> 1625/0,
frozen v5.0.0 and default-output baselines 0 changed files. No new GAP dimension,
no lever, no finding code — utilization denominators untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013941cEohSD5Aw56FVAtBgZ
2026-08-10 05:40:12 +02:00
..
analyze.md fix(commands): stop assuming shell state survives between blocks 2026-08-01 20:12:17 +02:00
campaign.md feat(commands): a write that leaves the repo says so before you approve it (M-BUG-41) 2026-08-10 05:40:12 +02:00
cleanup.md fix(commands): close the promises the command templates could not keep 2026-07-31 21:27:07 +02:00
config-audit.md fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
discover.md fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
drift.md fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
feature-gap.md fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
fix.md feat(commands): a write that leaves the repo says so before you approve it (M-BUG-41) 2026-08-10 05:40:12 +02:00
help.md fix(commands): wire knowledge-refresh into router + help 2026-06-23 10:31:05 +02:00
implement.md feat(commands): a write that leaves the repo says so before you approve it (M-BUG-41) 2026-08-10 05:40:12 +02:00
interview.md fix(commands): stop assuming shell state survives between blocks 2026-08-01 20:12:17 +02:00
knowledge-refresh.md fix(commands): stop answering questions the caller did not ask 2026-08-01 21:26:39 +02:00
manifest.md feat(scanners): model/effort routing becomes a lever, not a 25th dimension (C4) 2026-08-10 05:07:23 +02:00
optimize.md fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
plan.md feat(commands): a write that leaves the repo says so before you approve it (M-BUG-41) 2026-08-10 05:40:12 +02:00
plugin-health.md fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
posture.md fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
rollback.md feat(commands): a write that leaves the repo says so before you approve it (M-BUG-41) 2026-08-10 05:40:12 +02:00
status.md fix(commands): close the promises the command templates could not keep 2026-07-31 21:27:07 +02:00
tokens.md fix(commands): router dogfood — five seam defects, plus the placeholder class 2026-08-09 21:18:05 +02:00
whats-active.md feat(scanners): model/effort routing becomes a lever, not a 25th dimension (C4) 2026-08-10 05:07:23 +02:00