-
Notifications
You must be signed in to change notification settings - Fork 16.3k
fix(team-init): emit PreToolUse deny in hookSpecificOutput shape#1971
Open
heslanx wants to merge 1 commit into
Open
fix(team-init): emit PreToolUse deny in hookSpecificOutput shape #1971heslanx wants to merge 1 commit into
heslanx wants to merge 1 commit into
Conversation
The check-gstack.sh hook generated by gstack-team-init printed permissionDecision at the top level. Claude Code's PreToolUse decision control only reads hookSpecificOutput.permissionDecision (with hookEventName), so the deny was silently ignored and the required-mode gate never actually blocked skill usage when gstack was missing. Use the same hookSpecificOutput shape adopted for careful/freeze in garrytan#1509, and add a test that executes the generated hook in both scenarios (gstack missing -> structured deny; installed -> {}).
Merging to main in this repository is managed by Trunk.
- To merge this pull request, check the box to the left or comment
/trunk mergebelow.
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here
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.
Problem
The
check-gstack.shenforcement hook generated bybin/gstack-team-init requiredprints its deny decision as a top-levelpermissionDecision:{"permissionDecision":"deny","message":"gstack is required but not installed. ..."}Claude Code's PreToolUse decision control only reads
hookSpecificOutput.permissionDecision(withhookEventName: "PreToolUse") — the deprecated top-level fields aredecision/reason, notpermissionDecision/message. The output is therefore treated as a no-op, and the required-mode gate never actually blocks skill usage when gstack is missing. Teams adoptinggstack-team-init requiredget an enforcement hook that silently enforces nothing.Found via
codex reviewwhile rolling team mode out across our org's repos; verified against Claude Code's hook output validation (it rejectshookSpecificOutputwithouthookEventNameand ignores unknown top-level fields).Fix
Emit the deny in the supported shape — the same one #1509 adopts for
careful/freeze:{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"gstack is required but not installed. See stderr for install instructions."}}The stderr install instructions are unchanged.
Tests
Added a test that runs
gstack-team-init requiredand then executes the generated hook in both scenarios:HOMEwithout gstack → structuredhookSpecificOutputdenyHOMEwith gstack installed →{}no-opNote (out of scope)
The settings matcher generated by team-init only gates the
Skilltool, so plainRead/Edit/Bashwork proceeds without gstack. If the intent of required mode is to gate all AI-assisted work, a catch-all matcher might be worth considering — left out of this PR since it's a design decision (andteam-mode.test.tspinsmatcher === 'Skill'). Happy to follow up if there's interest.🤖 Generated with Claude Code