fix(hooks): session-state exemption checks filePath key for Create tool#971
Conversation
…e tool FP-1 exemption checked only toolArgs['path'] but Copilot CLI Create tool sends the file path as filePath in toolInput/input, not as path in toolArgs. This caused false-positive tentacle denials when writing research reports to .copilot/session-state/*/research/. Now checks all three locations: toolArgs.path, toolInput.filePath, input.filePath.
There was a problem hiding this comment.
Pull request overview
Fixes a false-positive in tentacle enforcement where create/edit operations targeting .copilot/session-state/... were incorrectly blocked because the hook only looked for toolArgs["path"], while the Copilot CLI Create tool commonly reports the path as filePath (in toolInput / input).
Changes:
- Update
TentacleEnforceRule.evaluate()to exempt session-state writes when the path is provided viafilePath. - Update the legacy standalone
hooks/enforce-tentacle.pymirror to apply the same exemption forfilePath.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| hooks/rules/tentacle.py | Extends the session-state exemption to recognize filePath (including merged toolInput) so Create/Edit to session-state isn’t blocked. |
| hooks/enforce-tentacle.py | Mirrors the exemption update for the standalone enforcement script by reading filePath from additional payload locations. |
| if tool_name in ("edit", "create"): | ||
| file_path = (data.get("toolArgs") or {}).get("path", "") | ||
| file_path = ( | ||
| (data.get("toolArgs") or {}).get("path", "") | ||
| or (data.get("toolInput") or {}).get("filePath", "") | ||
| or (data.get("input") or {}).get("filePath", "") | ||
| ) |
| # Note: Create tool sends path as filePath in toolInput/input, not "path" in toolArgs. | ||
| if tool_name in ("edit", "create"): | ||
| file_path = tool_args.get("path", "") | ||
| file_path = ( | ||
| tool_args.get("path", "") | ||
| or tool_args.get("filePath", "") | ||
| or (data.get("input") or {}).get("filePath", "") | ||
| ) |
|
Addressed both review comments: Comment 1 ( Comment 2 (missing regression tests): ✅ Added 2 new Section 19 tests:
Verification: 967/967 tests passed. |
| # Note: Create tool sends path as filePath in toolInput/input, not "path" in toolArgs. | ||
| if tool_name in ("edit", "create"): | ||
| file_path = (data.get("toolArgs") or {}).get("path", "") | ||
| file_path = ( | ||
| (data.get("toolArgs") or {}).get("path", "") | ||
| or (data.get("toolArgs") or {}).get("filePath", "") | ||
| or (data.get("toolInput") or {}).get("filePath", "") | ||
| or (data.get("input") or {}).get("filePath", "") | ||
| ) |
Add Section 19e functional tests verifying that standalone enforce-tentacle.py correctly exempts session-state writes via toolInput.filePath, input.filePath, and toolArgs.filePath.
|
Addressed the latest review comment: Comment 3 (standalone enforce-tentacle.py missing filePath tests): ✅ Added 3 new Section 19e functional tests covering:
Verification: 970/970 tests passed. |
Root Cause
FP-1 session-state exemption (allowing
Create/Editto.copilot/session-state/) checked onlytoolArgs["path"], but Copilot CLICreatetool sends the file path asfilePathintoolInput/input, not aspathintoolArgs.This caused the exemption to never match —
TentacleEnforceRulefalsely deniedCreatecalls writing research reports to.copilot/session-state/*/research/.Changes
hooks/rules/tentacle.pyTentacleEnforceRule.evaluate(): now checkstoolArgs.path,toolArgs.filePath, andinput.filePathhooks/enforce-tentacle.pytoolArgs.path,toolInput.filePath, andinput.filePathVerification
Create→.copilot/session-state/(toolInput.filePath)Create→src/main.py(project code)Create→.copilot/session-state/(oldtoolArgs.path)Closes false positive
TENTACLE REQUIREDdenial when writing research files to session-state.