mirror of
https://github.com/thedotmack/claude-mem.git
synced 2026-07-08 15:34:27 +08:00
* fix(hooks): drop pipe `break` that triggers EACCES on Windows/Cygwin
Hook/MCP plugin-root resolution piped a candidate list into a `while`
loop that `break`s on the first match:
_P=$({ printf ...; ls -dt ...; printf ...; } | while read _R; do
... && { printf '%s\n' "$_Q"; break; }; done)
On Cygwin/MSYS shells (Git-Bash on Windows) the early `break` closes
the pipe's read end while the producer subshell is still writing the
remaining candidate lines. The next `printf`/`ls` then writes to a
broken pipe, which Cygwin surfaces as EACCES rather than EPIPE:
printf: write error: Permission denied
...failing the hook. It is a pipe-lifetime race, not a path/username
encoding problem — it reproduces 40/40 once CLAUDE_PLUGIN_ROOT is set
(so the first candidate matches and `break` fires immediately, leaving
the most pending producer output).
Fix: don't `break`. Drain every candidate (only a handful) and print
the FIRST match exactly once via a `_F` guard, so the producer always
completes and no broken-pipe write happens. First match still wins, so
the contractual fallback ORDER is unchanged. The change is POSIX-clean
(no bashisms), so the `mcp` host's `sh -c` launcher is fixed too.
Patched the single source of truth (src/build/hook-shell-template.ts)
and regenerated the three host-managed files; verified all 15 command
strings still match the canonical generator byte-for-byte, and that the
regenerated commands produce 0/30 EACCES under both bash and sh with
CLAUDE_PLUGIN_ROOT set.
Fixes #2707. Related #2709.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(hooks): reset _F before the resolution loop
Review follow-up. The first-match guard reads `[ -z "$_F" ]` before _F
is ever assigned. The `while` loop runs in the pipe's subshell, which
inherits the parent shell's variables, so an inherited non-empty `_F`
(e.g. an exported var in the host environment) would make the guard
false on every iteration: nothing prints, `_P` stays empty, and the
hook exits "not found".
Prefix the command substitution with `_F=;` so the guard always starts
from a known-empty state. Regenerated the three host-managed files;
canonical generator check still matches byte-for-byte, and the command
resolves correctly under bash and sh even with `_F=1` exported.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(sqlite): remove dead legacy migration system (migrations.ts)
migration001..010 + the migrations[] array were orphaned by the #534
MigrationRunner refactor — zero importers. Build + full test suite
show no regression (11 pre-existing flaky fails identical on main).
* build: regenerate bundles + restore canonical hook JSONs for template fix
---------
Co-authored-by: Steven Moreno <steven.moreno@kpginc.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: wangchenguang <darion.yaphets@gmail.com>