fix(commands): close the promises the command templates could not keep
DEL B chunk `interview` (+ discover/status/cleanup/help). Fasit written before the run predicted 8 defects and refuted 4 candidates; all 8 confirmed, all 4 refutations held, and three predictions turned out too narrow. - M-BUG-36: `drift --list` reached the command as 0 bytes. drift-cli accepted --output-file but list mode ignored it, and the listing goes to stderr, which the command discards per ux-rules rule 2. Fixing the caller alone would not have helped. - M-BUG-37: feature-gap's "Create backup" step ran fix-cli without --apply. Dry-run is the default, so no backup existed (backupId: null) while the command went on to edit config believing it could roll back. - M-BUG-38: fix-cli told users to recover with scanners/rollback-cli.mjs, which does not exist. Dead reference in the one message read after a bad fix. - M-BUG-21 fourth arm: five templates carried literal [--global]/[--full-machine] inside executable bash blocks. A bracketed placeholder does not start with a dash, so every scanner's arg loop takes it as the scan target. - interview and analyze never said which session they act on; interview could rewind a finished session; cleanup interpolated an unvalidated id into rm -rf (an empty id deletes every session); status advertised a `resume` command that does not exist and documented an `all` argument it never parsed. TDD: 9 red tests first, including a machine sweep for dead /config-audit references and for bracketed flags in bash blocks. Suite 1432 -> 1441/0. Frozen v5.0.0 snapshots untouched; --raw/--json contracts unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UGvA1uUQn2hPBPMaCKK6x3
This commit is contained in:
parent
001090261e
commit
b85919f2ec
17 changed files with 318 additions and 28 deletions
41
CHANGELOG.md
41
CHANGELOG.md
|
|
@ -8,6 +8,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
- **`M-BUG-36` — `/config-audit drift --list` showed nothing.** `drift-cli.mjs` accepted
|
||||
`--output-file` but list mode ignored it, and the listing itself goes to **stderr**, which
|
||||
`commands/drift.md` discards with `2>/dev/null` (ux-rules rule 2). The command received **0 bytes**
|
||||
and could render no baselines at all. List mode now honours `--output-file`; `--raw`/`--json` stdout
|
||||
is unchanged and byte-stable. Fourth instance of the stderr-only class after `M-BUG-33`.
|
||||
- **`M-BUG-37` — `/config-audit feature-gap` promised a backup it never made.** Step 6's
|
||||
"Create backup" ran `fix-cli.mjs <path> --json`, but fix-cli is **dry-run by default**: no backup was
|
||||
written and `backupId` came back `null`, after which the command edited the user's configuration
|
||||
believing it could be restored. Passing `--apply` would have been worse — it executes unrelated
|
||||
auto-fixes the user never selected. The step now copies the files itself and states plainly that
|
||||
plain copies are restored by copying them back, not by `/config-audit rollback` (`M-BUG-31` class).
|
||||
- **`M-BUG-38` — `fix-cli.mjs` sent users to a script that does not exist.** After applying fixes it
|
||||
printed `Rollback: node scanners/rollback-cli.mjs <id>`; there is no `rollback-cli.mjs` — only
|
||||
`rollback-engine.mjs`, driven by `/config-audit rollback`. A dead reference in the one message a
|
||||
user reaches for after a bad fix. Now points at the command.
|
||||
- **`M-BUG-21` (fourth arm) — command templates fed bracketed placeholder flags to the arg loops.**
|
||||
Five templates (`config-audit.md`, `discover.md`, `fix.md`, `tokens.md`, `whats-active.md`) carried
|
||||
literal `[--global]` / `[--full-machine]` / `[--verbose]` inside executable bash blocks. A bracketed
|
||||
placeholder does not start with `-`, so every scanner's `else if (!args[i].startsWith('-'))` branch
|
||||
takes it as the **scan target** — silently scanning a path that does not exist. Replaced with empty
|
||||
shell variables that expand to nothing when the flag does not apply.
|
||||
- **`/config-audit interview` and `analyze` never said which session they act on.** Both referenced
|
||||
`{session-id}` with no resolution rule, while every other session-aware command globs
|
||||
`sessions/*/state.yaml` and takes the most recent. Two runs could write to two different sessions.
|
||||
Both now resolve the session explicitly and exit when none exists.
|
||||
- **`/config-audit interview` could rewind a finished session.** The mandated state write had no bound,
|
||||
so running the optional interview against a session that had already reached `implement` reset
|
||||
`current_phase` and re-added phases. It now appends `interview` only if absent and leaves the
|
||||
furthest phase reached intact.
|
||||
- **`/config-audit cleanup` interpolated an unvalidated id into `rm -rf`.** An empty or malformed
|
||||
`{session-id}` expands the path to `sessions//`, deleting **every** session. The id must now match
|
||||
`^[0-9]{8}_[0-9]{6}$` or come verbatim from the directory listing; anything else is refused and
|
||||
reported.
|
||||
- **`/config-audit status` advertised a command that does not exist.** It documented
|
||||
`/config-audit resume {session-id}`; there is no `resume` command. Replaced with how session
|
||||
selection actually works. A test now fails on any `/config-audit <word>` reference in `commands/`
|
||||
without a matching file.
|
||||
- **`/config-audit status all` was documented but never parsed.** The flag-parse step knew only
|
||||
`--raw`. It now parses `all` and routes to the all-sessions table.
|
||||
|
||||
### Fixed (previously)
|
||||
- **`M-BUG-21` (third arm) — `plugin-health-scanner.mjs` swallowed unknown flags, and the wrong
|
||||
target looked *green*.** The same `else if (!args[i].startsWith('-')) targetPath = args[i]` loop:
|
||||
`--output-file /tmp/x.json` was dropped and `/tmp/x.json` became the scan target. Where `drift`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue