fix(guard): allow Agent/Task dispatch on prompt+hard steps - #94
Merged
Conversation
Tri-* workflows (tri-review, tri-debug, tri-security, tri-dispatch) instruct the calling model to hand off to an external-model subagent so the verdict isn't written by Claude itself. Commit 7b5fd2b fixed the prompt text to say "DISPATCH, DO NOT ANSWER"; the guard still blocked the Agent/Task tool that the instructions require, so the whole dispatch path was dead. Add Agent and Task to the prompt+hard allowlist. Write/Edit/Bash remain blocked so the main model cannot cheat by fabricating a review — it must go through a subagent whose tools are independently gated.
Mirror the Go-level guard_test.go change: flip prompt+hard+Task from expect-block to expect-allow, add prompt+hard+Agent → allow. Keeps the shell smoke suite in sync with the Go unit tests.
Three findings from pr-review-toolkit (2026-04-17): - test-analyzer: pin command+hard+Agent/Task as block so a future refactor can't silently extend the prompt carve-out to command steps (dispatch is a prompt-step privilege; command steps are engine-driven). - test-analyzer: add prompt+hard+Edit and prompt+hard+WebFetch to the shell smoke suite — the PR body names these as anti-cheat must-holds, the Go suite had them but the shell mirror did not. - comment-analyzer: drop the guard.go comment's final sentence recommending enforce: soft as the escape hatch for subagent tool needs. That workaround would also unlock the main agent's Write/Edit/Bash, which is exactly what this PR is designed to prevent. Keep the re-entry note (verified accurate by the silent-failure reviewer).
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.
Summary
prompt+hardallowlist excludedAgent/Task, sotri-review/tri-debug/tri-security/tri-dispatchworkflows couldn't hand off to external-model subagents even though their prompts instruct the calling model to do exactly that.DISPATCH, DO NOT ANSWERpreamble; this PR makes the guard actually permit the dispatch.Write/Edit/Bash/WebFetchremain blocked onprompt+hardso the main Claude model cannot fabricate a review by writing the verdict itself — determinism is preserved, tri-* keeps its multi-model property.Changes
src/cmd/guard.go— addAgentandTaskto theprompt+hardallowlist (+12 lines, including an inline comment that documents the anti-cheat rationale and flags that subagent tool calls re-enter the guard with the same session state).src/cmd/guard_test.go— flip the priorprompt+hard+Task → blockcase to→ allow (subagent dispatch)and add a matchingprompt+hard+Agent → allowcase. Anti-cheat tests (prompt+hard+Write/Edit/Bash/WebFetch → block) are untouched and still pass.Test plan
make test— 359 tests pass across 6 packages, 0 failuresgo vet ./...— cleangofmt -l .— cleanprompt+hard+Write → block,prompt+hard+Edit → block,prompt+hard+Bash → block,prompt+hard+WebFetch → blockall still pass/devkit:tri-reviewend-to-end on a real diff to confirm Codex/Gemini dispatch succeeds. If the subagent's ownBashcall (to hitcodex-companion.mjs/gemini-companion.mjs) is also blocked by this guard because it re-enters with the same session state, a follow-up will addtranscript_path-based subagent detection.Caveat
This fix unblocks the main-agent → subagent dispatch layer. If subagent tool calls hit the same guard with the same session state, their
Bashcalls may still block. The fix above is intentionally minimal; the subagent-context-detection work is a separate concern and can be added without reverting this change.