feat(hooks): PostToolBatch lane (default-off) + schema-driven render migrations - #115
Merged
Merged
Conversation
…migrations Adds the new Claude Code PostToolBatch event as a default-off recall lane (simba.hooks.post_tool_batch): a mandatory client-side payload trim bounds the tool_calls batch before any query is built or daemon call is made, then a compact recall query (tool names, input heads, error-looking response fragments) drives the same recall/format machinery pre_tool_use.py uses. Migrates two render surfaces off schema variants Claude Code has since dropped or added: PreToolUse no longer emits additionalContext for the claude client (it silently drops -- the PostToolBatch lane is its replacement), and Stop/SubagentStop render additionalContext via hookSpecificOutput instead of the legacy top-level stopReason. Both migrations are client-gated on the resolved SIMBA_CLIENT so Codex keeps its byte-identical legacy shapes until its own schema tolerance is verified. Registered PostToolBatch in .claude-plugin/hooks.json only (no Codex equivalent exists). TDD red-first throughout; full suite + ruff clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adopts Claude Code's new
PostToolBatchhook event (fires once per tool-call round, before the next model call; supportsadditionalContext) and completes the schema-driven render migrations the new hook schema forced.Leg 1 — PostToolBatch lane (default-OFF)
.claude-plugin/hooks.json(Codex has no such event; its config verified untouched by test).hooks/post_tool_batch.pycanonical module;hooks.post_tool_batch_enabled(default False — unmeasured lever) andhooks.post_tool_batch_max_payload_kb(default 256)....[simba: truncated]. The daemon never receives an unbounded batch payload — batchtool_responses can be large by design and this repo just spent a week killing unbounded inputs.{"hookSpecificOutput": {"hookEventName": "PostToolBatch", "additionalContext": ...}}envelope. When disabled: immediate empty result, zero daemon calls.Leg 2 — PreToolUse render migration (client-gated)
The new schema removed
additionalContextfrom the PreToolUse variant. For claude clients, PreToolUse renders no longer emit it (deny/rewrite/empty + top-levelsystemMessageremain); the recall-context production layer is untouched and the injection re-homes to the PostToolBatch lane. Codex output preserved byte-for-byte.Leg 3 — Stop/SubagentStop additionalContext migration (client-gated)
Stop-feedback moves from the top-level
stopReasonworkaround to the documentedhookSpecificOutput.additionalContextchannel ("Feedback for the model; the conversation continues") for claude clients; Codex keepsstopReasonbyte-for-byte.Tests
Red-first: payload trim (under-cap identity, over-cap ≤ cap with markers), disabled-lane inertness (recall stub raises if called), enabled-lane envelope shape, per-client before/after render assertions for all three migrations. Full suite exit 0, ruff clean.