mpfaffenberger / mpfaffenberger/code_puppy
Hook exit-code semantics are internally inconsistent: engine blocks on exit 1, docs/prompts teach exit 2
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 814
- Forks
- 278
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 76
Description
Files:
code_puppy/hook_engine/executor.py:145—blocked = exit_code == 1code_puppy/hook_engine/executor.py:1-13(module docstring) — "Exit code 1 => block the operation; Exit code 2 => error feedback to Claude"code_puppy/mcp_prompts/hook_creator.py:36— "PreToolUse- Before a tool executes (can block with exit code 2)"code_puppy/mcp_prompts/hook_creator.py:60-71— example hook script usesexit 2to "Block dangerous commands"code_puppy/plugins/claude_code_hooks/register_callbacks.py:85— "exit 1 blocks and exit 2 routes stderr back as a tool error"
Severity: High (correctness)
The engine treats exit 1 as blocking. But the bundled hook-creation prompt (mcp_prompts/hook_creator.py) — the very documentation injected to teach users/LLMs how to write hooks — instructs them to exit 2 to block. A hook written by following that prompt will silently fail to block the dangerous operation it was written to prevent. That's the worst possible failure mode for a safety mechanism.
Note also that Claude Code's own documented convention is exit code 2 = blocking error (stderr fed to Claude), and any non-zero other code = non-blocking error. Since this engine explicitly advertises "Claude Code Hook Compatibility" (executor.py docstring), hooks ported from Claude Code (exit 2 to block) will not block here either.
Suggested fix: Pick one convention (recommend matching Claude Code: exit_code == 2 blocks) and align all three places — executor.py logic + docstring, hook_creator.py prompt, and claude_code_hooks plugin docs. Add a regression test asserting the blocking exit code matches the documented one.
Filed by Zen Reviewer B (code-puppy-60635a)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by comparing the exit-code logic and documentation in code_puppy/hook_engine/executor.py, mcp_prompts/hook_creator.py, and plugins/claude_code_hooks/register_callbacks.py. Trace the existing hook execution path, then add a regression test that verifies the documented blocking code is enforced and confirm all three locations describe the same behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- security, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100