fix(hooks): capture Stop turn ends#773
Conversation
|
Hi @pg-adm1n Thanks! Did you test on manually? Are we sure that feature? |
|
Hi @mksglu — yes, tested manually on Claude Code (beyond the unit tests). Here's the runtime evidence that the Setup — point the Claude Code runtime at this branchnpm run build && npm link # `context-mode` now resolves to this checkoutClaude Code "Stop": [{ "hooks": [{ "type": "command", "command": "context-mode hook claude-code stop" }] }]
|
|
@mksglu Validation completed according to the maintainer review requirements. VerdictThe behavior is valuable and functionally validated, but this PR needs an update before merge because GitHub reports After the conflict is resolved, I would re-run the same 3OS validation before final merge. What this PR meaningfully fixesThis PR treats Claude Code That distinction matters for context-mode because The intended invariant is:
Git archaeology checkedI checked the existing hook history and related adapter behavior before accepting the change. The important precedent is already present in the repo:
So this PR aligns Claude Code with the existing Kimi/Codex invariant instead of assigning session-close meaning to Stop. Validation performedGitHub status:
Targeted tests passed:
Live Claude Code validationPer maintainer requirements, live validation used Claude Haiku. Linux:
macOS:
Windows:
This proves the actual Claude Code hook path works on Linux, macOS, and Windows, not only the unit-test path. Remaining update neededThe PR is worth merging after the merge conflict is resolved and the same 3OS live validation is re-run. |
|
Hi @pg-adm1n, thank you for contributing this PR. I validated the change according to the maintainer review requirements. The behavior looks valuable and worth merging: the Claude Code The only blocker I see right now is that the PR has merge conflicts ( Could you please resolve the conflicts? After that, we can re-run the same validation and move this toward merge. |
Summary
Adds Claude Code
Stophook support and aligns Stop-hook persistence semantics across Claude Code and Codex.Stopin generated hook config and the shippedhooks/hooks.jsonhooks/stop.mjsto capture assistant turn-end state asturn_end{}so Claude Code is never asked to continuehooks/codex/stop.mjsfromsession_endtoturn_endRoot cause
Claude Code now exposes a
Stophook, but context-mode did not ship or register a Claude Code Stop runtime. That meant assistant turn-end state was not captured for Claude Code sessions.Codex already registered a Stop hook, but the runtime wrote
session_end. Stop fires at the end of an assistant turn, not at actual process/session shutdown, sosession_endwas too strong and could pollute lifecycle timelines.Fix
turn_endwithstop_hook_activeand a boundedlast_assistant_messagepayload.context-mode hook claude-code stopthrough the CLI dispatcher.turn_endwhile preserving its existing{}response behavior.cli.bundle.mjs,server.bundle.mjs,hooks/session-db.bundle.mjs,hooks/session-extract.bundle.mjs) afternpm run build.Affected platforms
turn_endfromsession_endTest plan
git diff --checknpm run buildnpx vitest run tests/adapters/claude-code.test.ts tests/hooks/claude-stop.test.ts tests/adapters/codex.test.ts tests/hooks/kimi-hooks.test.ts --testNamePattern "Stop|stop|generateHookConfig|hooks/hooks.json"— 20 passed / 136 skippedTMP_HOME=$(mktemp -d) && env -u CONTEXT_MODE_PLATFORM HOME="$TMP_HOME" npm test— 184 files passed, 4207 passed / 28 skippedNote: the isolated
HOME/unsetCONTEXT_MODE_PLATFORMkeeps local Codex/Claude session state from influencing project-dir detection during the full test run.Checklist
npm testpassesnpm run buildpassesnextbranch