fix(claude-native): give the evaluate-policy hook the day-long timeout#2012
Open
tomsen-ai wants to merge 1 commit into
Open
fix(claude-native): give the evaluate-policy hook the day-long timeout#2012tomsen-ai wants to merge 1 commit into
tomsen-ai wants to merge 1 commit into
Conversation
The evaluate-policy command hook had no explicit timeout, so Claude Code's ~60s command-hook default kills the hook subprocess. But a TOOL_CALL/REQUEST policy ASK parks server-side until a human answers (up to the deciding policy's ask_timeout, default one day), and the evaluate-policy client already waits the full day for that verdict — so every admin-policy ASK (e.g. a cost-budget gate) is silently capped at 60s. In acceptEdits/bypassPermissions mode, where PermissionRequest never fires, this evaluate-policy gate is the sole human approval point, so the 60s cap means the policy is decided by the hook-timeout fallback before the operator can respond. The sibling permission_hook already carries timeout=86400 for exactly this reason (see its inline rationale); the AskUserQuestion hook sets its own timeout too. The evaluate-policy hook was the only one of the three command hooks left on the default. Add timeout=86400 so no layer caps the wait before the policy's own ask_timeout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
13 tasks
Contributor
|
@tomsen-ai This PR is a Bug fix, Feature, or UI / frontend change but the Demo section is missing or only contains a placeholder. These change types require a screenshot or screen recording so reviewers can see the new behaviour without checking out the branch. Please update the Demo section with:
Use |
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.
Related issue
N/A
Summary
build_hook_settingsinclaude_native_bridge.py) had no explicittimeout, so Claude Code's ~60s command-hook default kills the hook subprocess. But a TOOL_CALL/REQUEST policy ASK parks server-side until a human answers — up to the deciding policy'sask_timeout(default one day) — and the evaluate-policy client already waits the full day (_EVALUATE_POLICY_TIMEOUT_S = 86400). So every admin-policy ASK (e.g. a cost-budget gate) was silently capped at 60s.acceptEdits/bypassPermissionsmode, wherePermissionRequestnever fires, this evaluate-policy gate is the sole human approval point — so the 60s cap means the hook-timeout fallback decides the policy before the operator can respond.timeout: 86400, matching the siblingpermission_hook(which already carries it for exactly this reason). It was the only one of the three command hooks left on Claude Code's default.ELI5: the hook that waits for a human to approve a policy prompt didn't tell Claude Code how long to wait, so Claude Code killed it after ~60s — long before the person could answer. The permission hook right next to it already says "wait a day"; this one just forgot to.
The real ceiling stays the policy's own
ask_timeout; this just stops the command-hook layer from capping the wait first.Test Plan
test_augment_claude_args_evaluate_policy_hook_has_day_long_timeout: asserts every registered evaluate-policy hook (PreToolUse/PostToolUse/UserPromptSubmit) carriestimeout == 86400. Red onmain(KeyError: 'timeout'— the key is absent), green with the fix.tests/test_claude_native_bridge.pyotherwise unchanged; the twoserve_mcp/relayfailures on my machine are pre-existing (they spawn a real subprocess that doesn't come up in my local sandbox) and reproduce identically with this change stashed — unrelated to this hook change.Demo
Red → green on the unit test. Red run is the pre-fix source with this PR's test: the evaluate-policy hook dict has no
timeoutkey (KeyError), while the siblingpermission_hookalready carries 86400.Type of change
Test coverage
Coverage notes
The new unit test drives
augment_claude_argsand asserts the timeout on every evaluate-policy hook registration; it fails onmainand passes with the fix. The end-to-end "human answers after 60s" path depends on Claude Code's command-hook kill behaviour and isn't unit-testable here, but the fix mirrors the already-shippedpermission_hooktimeout.Changelog
Admin policy approval prompts (e.g. cost-budget gates) in native Claude sessions no longer time out after ~60s before the operator can respond.
🤖 Generated with Claude Code