v0.3.5 — guard parity, Windows guard hook, and a plugin data-loss fix
A branch-coverage pass turned up six real bugs. All six are fixed here, and every one is pinned by a test that fails if it comes back.
Security
The guard's fallback matcher no longer under-blocks. guard-hook.js carries its own copy of the never-touch glob logic so the guard still works when never-touch.js cannot be loaded — but it was a looser reimplementation, and every gap was a silent hole. It had no {a,b} alternation, so a neverTouch of *.{pem,key} was entirely unenforced whenever the fallback was live. It also did not trim the glob, strip a leading /, or skip an empty one. It is now a faithful copy, and a parity test across the shipped defaults fails on any future divergence.
The guard hook runs on Windows. Its command carried the guard's config in a POSIX VAR=value prefix that cmd.exe cannot parse, so it was skipped there entirely. The deny rules left behind cover Read/Edit/Write/Grep/Glob but not Bash, while the allowlist grants Bash(cat *) — so cat .env was unguarded on Windows alone, and the README's claim that .env is covered was false on one of three platforms. The config now travels in a file that the hook reads from argv; an unreadable one fails closed, like every other unparsable input.
Data loss
The plugin hook could lose crash events permanently. It wrote to a pipe and then called process.exit(0), discarding everything past the buffer — one minified stack trace in error is enough. Claude Code received invalid JSON and dropped the briefing, and markRead() had already advanced the cursor, so those events were gone for good. The cursor now moves only once the bytes are actually flushed, and never when the write failed.
describeEvent threw on a command that would not coerce. Because the throw came before markRead, the cursor never advanced and every later prompt in that repo retried and failed identically. Every field is coerced safely now — and flattened to one line, since error is raw output from the crashed program and the briefing is line-oriented text.
Correctness
reproTimeoutMswas read offopts, which only ever carriescwd, so the re-run timeout was hard-wired to 30 s and every override was silently ignored. The test suite went from 45 s to 17 s.- A failed commit told you it left you on the branch "(--no-commit)" when
autoCommitwas on. It now names the actual reason.
Also
- The Claude Code plugin is documented as a first-class install path, with update instructions for both channels.
- 243 → 306 tests.
prompt.jsbranch coverage 59.8% → 98.3%;recovery.jsat 100% lines.
Install: npm install -g claude-phantom · Plugin: /plugin marketplace add waazy-w/claude-phantom