Repository navigation
Conversation
…ield they read #186, the half the owner chose to ship. Both guards read tool_input.command and, when it was missing, treated the command as empty and allowed it, so a Claude Code update that renamed the field would have switched them off silently. They now deny a well-formed event with no tool_name, or a Bash event with no string tool_input.command, with a reason that names #186 and the way out. It is a deny decision, so it holds on Claude Code versions without onFailure. Decisions recorded in each docstring: unparseable input still fails open (a3, g22); a Write/Edit event with no file_path still fails open, since that check is advisory; root-of-trust-guard keeps its own copy of the check so a stubbed sibling cannot remove it; issue-guard is unchanged (not a security boundary, and only spawned for gh commands). Twelve battery cases (a123-a129, b39-b43), 334 in all; five mutants run through HOOK_DIR each fail the cases aimed at them (LEDGER). Field names checked against the hooks docs; every Bash call of this session ran through the edited guards with no refusal. TROUBLESHOOTING names the new refusal as a third cause. CHANGELOG v2.9.1 (untagged), guide and CITATION at 2.9.1, guide re-rendered and restamped.
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2b23f8eb08
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| - **`can't open file …/.claude/hooks/<name>.py`: the hook script is missing.** Usually a branch switch or an old checkout removed `.claude/hooks/` while the session still holds the settings that point there. Claude cannot repair this from inside the session, because the repair is itself a blocked call. From a terminal, run `git checkout -- .claude/hooks` (or switch back with `git switch -`), then start a new session. Tracked in [#180](https://github.com/pedrohcgs/claude-code-my-workflow/issues/180). | ||
| - **`python3: command not found`, or a Microsoft Store message: no working `python3`.** On Windows, the python.org installer provides `python` and `py` but not `python3`, and the `python3` that ships with Windows opens the Store. Make `python3 --version` work in Git Bash, for example with the Microsoft Store's Python, which provides `python3`. Tracked in [#179](https://github.com/pedrohcgs/claude-code-my-workflow/issues/179). | ||
| - **`Claude Code sent … so this guard cannot read the command` (only Bash is refused): the hook payload changed.** Since v2.9.1, `git-guardrails` and `root-of-trust-guard` refuse an event that lacks the field they read, rather than read it as an empty command and allow it. Seeing this means a Claude Code update renamed or dropped that field. Look for an update to the template's `.claude/hooks/`. Until then, run the command in a terminal, or switch the project's hooks off with `"disableAllHooks": true` in `.claude/settings.local.json`, and turn them back on once the hooks are updated. Tracked in [#186](https://github.com/pedrohcgs/claude-code-my-workflow/issues/186). |
There was a problem hiding this comment.
Distinguish which missing field blocks edit tools
The parenthetical is true only when tool_input.command is missing. If the payload change removes or renames tool_name, git-guardrails.py rejects the event before checking its tool type, and its matcher also covers Write, Edit, and MultiEdit, so all of those tools are refused as well. In that failure mode this troubleshooting entry misstates the scope of the lockout; distinguish the missing-command case from the missing-tool-name case.
Useful? React with 👍 / 👎.
Summary
git-guardrails.pyandroot-of-trust-guard.pyreadtool_input.command. When that field was missing they treated the command as empty and allowed it. A Claude Code update that renamed the field would therefore have switched both guards off, and nobody would have seen it. This is the half of #186 the owner chose to ship: no run log, no session-start check, no settings change.tool_name, or a Bash event with no stringtool_input.command. The reason names Hook health: nothing notices a wired hook that runs but no longer does anything (port clo-author 26.09's hook log and SessionStart check?) #186 and the way out ("disableAllHooks": truein.claude/settings.local.jsonuntil the hooks are updated).onFailure.file_pathstill fails open, because that check is advisory;root-of-trust-guardkeeps its own copy of the check, so a stubbed or broken sibling cannot remove it;issue-guardis unchanged: it is not a security boundary, and Claude Code starts it only forghcommands.v2.9.1(fix-only, untagged); the guide and CITATION are at 2.9.1. TROUBLESHOOTING names the new refusal as a third cause.Verification
Battery: twelve new cases, a123–a129 and b39–b43, controls included; 334 cases in all, ALL PASS.
Mutants: five, run through
HOOK_DIR, and each fails the cases aimed at it:commandRecorded in the LEDGER, with the guard rows' N and FPR updated (78/78 with 0/51; 80/80 with 0/31).
Live: every Bash call made while writing this change ran through the edited guards in the working tree, and none was refused. The field names match the PreToolUse input in the hooks docs (read 2026-11-06).
./scripts/backtest.shpasses, with 245 portability cases.