Skip to content

fix(BUG-018): append continue directive to UserPromptSubmit hook (cross-OS)#85

Merged
mlorentedev merged 2 commits into
mainfrom
fix/BUG-018-userpromptsubmit-continue-directive
May 21, 2026
Merged

fix(BUG-018): append continue directive to UserPromptSubmit hook (cross-OS)#85
mlorentedev merged 2 commits into
mainfrom
fix/BUG-018-userpromptsubmit-continue-directive

Conversation

@mlorentedev
Copy link
Copy Markdown
Owner

@mlorentedev mlorentedev commented May 21, 2026

Summary

User hit a SECOND blocker minutes after BUG-017 (PR #84) closed the EPIPE race:

```
UserPromptSubmit operation blocked by hook: ... No stderr output
```

The error MESSAGE changed (no more `printf: write error`), proving BUG-017 landed, but the hook still blocks. Root cause: claude-mem's UserPromptSubmit hook command terminates with `node ... hook claude-code session-init` and does NOT emit Claude Code's `{"continue":true,"suppressOutput":true}` directive.

When `bun-runner.js` receives empty stdin (upstream claude-mem#2188), it prints diagnostic to stdout. Claude Code reads this as non-JSON-directive output → blocks the prompt.

Other claude-mem hooks (SessionStart `start`) already emit the directive: `node ...; echo '{"continue":true,"suppressOutput":true}'`. UserPromptSubmit just didn't get the same treatment upstream.

Empirical validation (this branch, user's Windows)

Manually patched user's local hooks.json with the same logic before this PR shipped → user's new Claude Code session in hive proceeded normally (no UserPromptSubmit block). This PR persists the fix across `/plugin update` upstream reverts via the heal scripts.

Changes

File Change
`scripts/claude-mem-heal.sh::heal_hooks_json` Add second sed substitution after BUG-017 head-n1; switch delimiter from `|` → `#` because `|` appears literally in BUG-017's replacement.
`scripts/claude-mem-heal.ps1::Repair-HooksJson` Add second `.Replace()` after BUG-017 head-n1 patch; separate log line so BUG-017 vs BUG-018 are distinguishable.
`tests/setup-linux.bats` 1 new parity assert: `session-init` + `continue` + `BUG-018` references in both heal scripts.

42 LOC total. Production diff 26 LOC (below spec-gate threshold). Skip SDD per "mechanical mirror" rule.

Test plan

  • `bash -n scripts/claude-mem-heal.sh` → OK
  • sed substitution empirically tested with mock hooks.json → correct JSON-escaped output
  • PSScriptAnalyzer + AST clean on `.ps1`
  • Empirical: user's hooks.json patched manually with identical logic, hive session proceeded normally
  • CI green

Anti-scope

Only UserPromptSubmit is patched here. The OTHER 4 hooks without the directive (Setup, SessionStart-context, PostToolUse, PreToolUse, Stop) stay untouched — only fix what user empirically hit. A future BUG-018b extends if those surface.

Companion PRs

…minators (cross-OS)

User hit a SECOND blocker minutes after BUG-017 (PR #84) closed the EPIPE
race -- and then a THIRD when the Stop hook also failed with the same
"No stderr output" symptom in a 9-loop iteration.

Original BUG-018 narrow scope (only UserPromptSubmit / session-init)
was insufficient: ALL 5 claude-mem hooks that terminate with
`node ... hook claude-code <event>"` lack the {"continue":true} directive
that Claude Code requires after BUG-017's race fix removed the prior
EPIPE-induced false-block:

  - SessionStart context  -> `hook claude-code context`
  - UserPromptSubmit       -> `hook claude-code session-init`
  - PostToolUse            -> `hook claude-code observation`
  - PreToolUse             -> `hook claude-code file-context`
  - Stop                   -> `hook claude-code summarize`

The 6th hook (Setup, `node "$_P/scripts/version-check.js"`) is left
untouched -- it fires only on plugin install/update, not the user hot
path.

Changes:

1. scripts/claude-mem-heal.sh::heal_hooks_json: sed substitution uses
   regex capture `\([a-z][a-z-]*\)` to match any `hook claude-code <X>"`
   terminator and append the directive in a single pass.

2. scripts/claude-mem-heal.ps1::Repair-HooksJson: PowerShell `-replace`
   with the equivalent regex; reports the count of hooks transformed.

3. tests/setup-linux.bats: 1 new parity assert covering the regex-based
   substitution + continue directive + BUG-018 reference in both heal
   scripts.

Empirical (2026-05-21 user's Windows):
- After BUG-017 merged: UserPromptSubmit failed (No stderr output)
- After narrow BUG-018 manual patch: ping/pong worked, but Stop hook
  failed 9 times in a row (Claude Code's CLAUDE_CODE_STOP_HOOK_BLOCK_CAP
  forced override)
- After regex-based patch (this commit) applied locally: all 5 hooks
  now end with the directive; subsequent prompts complete without loop.

This PR persists the fix across `/plugin update` upstream reverts.

Anti-scope: Setup hook (version-check.js) terminator left as-is. Future
BUG-018b can extend if user encounters that hook in practice.

Companion:
  - BUG-017 (PR #84 merged) -- EPIPE race prerequisite
  - upstream issue thedotmack/claude-mem#2607 -- root cause + 3 fix
    options for the cascade pipe; this PR's continue-directive append
    is independent layer addressing claude-mem#2188 (empty-stdin /
    hook protocol mismatch).
@mlorentedev mlorentedev force-pushed the fix/BUG-018-userpromptsubmit-continue-directive branch from 60454a2 to 4d82723 Compare May 21, 2026 19:27
PR #85 had 69 LOC of production diff (heal scripts) which exceeds the
50-LOC spec-gate threshold. CI failed on spec-gate. Add proposal.md,
tasks.md, verification.md describing the regex-based BUG-018 fix that
patches all 5 `hook claude-code <X>` terminators.

No code change; spec-only commit.
@mlorentedev mlorentedev merged commit 1135ad2 into main May 21, 2026
6 checks passed
@mlorentedev mlorentedev deleted the fix/BUG-018-userpromptsubmit-continue-directive branch May 21, 2026 19:36
mlorentedev added a commit that referenced this pull request May 21, 2026
Move from specs/ to specs/archive/ per SDD lifecycle close (the
folder move IS the archive marker; status: archived frontmatter
update deferred to per-spec follow-up if needed).

This session shipped (today, 2026-05-21):
  - AI-014-opencode-windows-bootstrap (PR #78)
  - BUG-014-claude-mem-marketplace-register (PR #75)
  - BUG-016-claude-mem-heal-v13-refresh (PR #83)
  - BUG-017-claude-mem-heal-hooks-json-race (PR #84)
  - BUG-018-userpromptsubmit-continue-directive (PR #85)
  - REFACTOR-003-diff-check-ps1 (PR #82)

Catch-up archive (merged earlier weeks but specs/ folder lingered):
  - BUG-007-remove-github-plugin-broken (PR #65, 2026-05-19)
  - BUG-011-mcp-loop-claude-json-guard (PR #69, 2026-05-20)
  - BUG-012-claude-mem-marketplace-junction (PR #70, 2026-05-20)
  - SDD-005-github-copilot-instructions-sync (PR #62, 2026-05-19)
  - SDD-006-vault-integrity-check (PR #63, 2026-05-19)

Active specs remaining in specs/ (not yet merged):
  - REFACTOR-002-paths-in-env-contract (queued, still draft)
  - WIN-002-windows-smoke-sweep (partial closure via PR #73, full
    clean-VM sweep still open)

33 file moves total (3 files per spec × 11 specs). Zero content change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant