Fix the triage bot's blocked test runs, and drop the dead Write() rules - #4704
Merged
Conversation
Write(path) rules are not matched by the file permission check - only Edit(path) rules are, and those cover every file-editing tool including Write. The two Edit rules already grant the clone and scratch paths, so the Write entries granted nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The change is a small, localized allowlist cleanup with no functional code-path modifications beyond removing redundant entries and adding clarifying commentary.
Pull request overview
Removes two redundant Write(path) allowlist entries from the triage bot tooling, relying solely on the existing Edit(path) scopes for file modifications and documenting why Write(...) should not be reintroduced.
Changes:
- Dropped
Write({EDIT_SCOPE})andWrite({SCRATCH_SCOPE})entries fromALLOWED_TOOLS. - Added an inline comment explaining that
Edit(path)already covers file-editing tools and to avoid re-addingWrite(path)rules.
File summaries
| File | Description |
|---|---|
| tools/triage_daemon.py | Removes redundant allowlist entries and documents the intended permission-scoping approach. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Running a targeted test was still denied despite the ./run_all rule being present. The rule was not the problem: Claude Code prompts on a `cd` combined with an output redirect, because it cannot tell which directory the redirect target resolves against once the `cd` has run. The skill's recipe was exactly that shape - `cd coverage && ./run_all --test X > log 2>&1` - so it was refused under dontAsk no matter what was allowed. run_all has to execute with coverage/ as the working directory, so the cd cannot simply be dropped. tools/triage_test.sh keeps both the cd and the redirect inside the script, leaving one plain command for the permission check to match. It prints the exit status and the tail of the log, and exits with the test run's own status. Also drops the coverage/run_all rules added earlier: those forms cannot work at runtime, since run_all sources setup.csh and resolves unit_test.py relative to coverage/. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Follow-up to #4703, two fixes to the triage bot's permissions.
Test runs were still being denied
The bot reported
./run_all --test solisdenied even thoughBash(./run_all*)was allowed. The rule was never the problem. Per the permissions docs, acdcombined with an output redirect prompts, "because Claude Code can't determine which directory the redirect target resolves against after thecdruns" — and the skill's recipe was exactly that shape:So it was refused under
dontAskregardless of what was in the allowlist.run_allhas to execute withcoverage/as the working directory, so thecdcan't simply be dropped.tools/triage_test.sh(new) keeps both thecdand the redirect inside the script, leaving one plain command for the permission check to match:It prints the exit status and the last 30 lines of the log, and exits with the test run's own status. The skill now tells the bot to use it and says why, so it doesn't improvise the denied form again.
Also drops the
coverage/run_allrules added in #4703 — those forms can't work at runtime anyway, sincerun_allsourcessetup.cshand resolvesunit_test.pyrelative tocoverage/— and switches the remainingrun_allrules to the word-boundary form (Bash(./run_all *)rather thanBash(./run_all*), which would also match./run_all_anything).Dead Write() rules
Write(path)rules are not matched by the file permission check — onlyEdit(path)rules are, and anEditrule covers every file-editing tool,Writeincluded. The twoWrite(...)entries granted nothing; theEdit(...)rules beside them already cover the clone and the scratch directory. Removed, with a comment so they don't come back.Testing
Ran the wrapper end to end against a real test module (
tools/triage_test.sh units <log>): exit 0, log written, pass/fail summary in the printed tail.pre-commitpasses on all three files.🤖 Generated with Claude Code