Release Candidate Hardening: read-only should mean read-only
No new features this round: a security audit, a command safety classification for every subcommand, a backward compatibility matrix, and an API freeze. All groundwork for v3.0.1-rc1, driven by a near-miss that exposed a real design gap.

registry verify sounds read-only. Names like audit, check, doctor, verify, stats, and info are supposed to be safe to run without thinking twice; that's the whole point of naming a command that way. During routine testing, registry verify --json was run against a real machine expecting exactly that: a read-only check. Instead, it attempted a real package install. It failed before persisting anything, and the failure was caught, investigated, and reported immediately, but the important thing was never the failed install. It was the design gap it exposed.
A full audit, not a patch
Every command across the CLI was classified READ ONLY or MUTATING, with a simple rule: a command without an explicit mutating verb must never modify the machine. doctor stays read-only; doctor --fix mutates. verify stays read-only; verify --fix mutates. Two real violations turned up and were fixed: registry verify, which now only attempts an install behind an explicit --install flag, and workspace benchmark, which was silently switching live git identity by default. Both fixes shipped with canary-file regression tests that prove zero installs, zero package removals, and zero configuration writes for every command whose name promises exactly that.
$ devforgekit registry verify --json # read-only by default now
$ devforgekit registry verify --install # explicit opt-in to mutate
$ devforgekit workspace benchmark <name> # read-only
$ devforgekit workspace benchmark --ops switch,restore # explicit opt-inA compatibility matrix that found real bugs
Verifying compatibility meant actually running the CLI, not reading the source and assuming: 228 --help invocations across every command and subcommand, 69 missing-argument error paths, and a full --json validity sweep. That sweep is what found three real, previously-unknown bugs: a --json command that hung indefinitely on a large registry scan, a cluster of package/repair commands with the same unbounded-loop bug, and two commands that silently printed human text instead of valid JSON on an empty result. All three are fixed, each with a regression test, and the full matrix (every command's exit code, JSON support, mutation status, and CI safety) is public in the repository's CompatibilityReport.md.
Freezing what's actually a contract
Every public command, config field, registry schema, environment variable, and output format is now classified Stable, Experimental, or Internal, with Stable meaning no breaking changes before v4. A couple of things were deliberately left Experimental rather than frozen by default: the AI assistant subsystem, still genuinely evolving, and the exact JSON field shapes per command, since no command ever published a real output schema to freeze in the first place. Freezing an accident isn't the same as freezing a design.
What's next
This is verification work, not feature work; the architecture was already finished going into this pass. What was left before v3.0.1-rc1: real hardware and VM installation testing across macOS, Ubuntu, and Windows, then the tag itself, followed by npm and Homebrew distribution going live for the first time. All of it shipped: v3.0.1-rc1 became the real v3.0.1 stable release after a clean verification pass across every channel.