Skip to content

claude-review stub-review flake reproduces 3x with identical permission_denials_count: 1 signature #185

Description

@d-morrison

Context

#173 (closed) tracked the symptom — a push-triggered claude-review run going green with only a stub, no verdict — and #172/#174/#176 added and tested a guard that now correctly fails the check when this happens. This issue is about the root cause the guard is correctly catching, which is still unaddressed.

Reproduction

On PR #180 (a single-file CLAUDE.md prose addition, nothing exotic), three separate claude-review runs across two different commits all failed with the identical fingerprint:

Run Commit is_error num_turns total_cost_usd permission_denials_count Verdict written?
28613551620 b4e0b0e false 4 0.225 1 No
28613787001 b4e0b0e (dispatched) false 4 (not captured) 1 No
28621230060 234aba7 false 4 0.430 1 No

All three: the Claude Code SDK call itself succeeded (is_error: false, real cost, 4 turns — this isn't the quota-exhaustion case, which is total_cost_usd==0 && num_turns==1), but no assistant text block ever contained a Verdict line, so check-review-execution.sh's guard correctly fails the check (working as designed per #172/#176).

Two other runs on the same PR, on an earlier commit (154d970), completed normally with full verdicts — so this isn't universal, but it reproduced identically 3/3 times on later commits.

Hypothesis

permission_denials_count: 1 on every failing run, 0 (implicitly) on the successful ones, suggests a specific tool call gets denied mid-review and derails the agent before it writes a verdict — num_turns=4 in all three failures (vs. presumably more turns in a completed review) is consistent with an early cutoff. Notably, this PR's diff is about WebFetch-ing external URLs (raw.githubusercontent.com, a GitHub Pages doc site) — plausible that the review agent's own fact-checking instructions ("verify against the codebase and its dependencies") prompt it to attempt a fetch that isn't in claude-review.yml's allowedTools, and the resulting denial short-circuits the run instead of being handled gracefully.

Suggested next step

Capture the actual turn-by-turn transcript from a reproducing run (not just the final result object) to confirm what tool call was denied and on which turn. If confirmed as a WebFetch/similar denial, either: allow read-only fact-check tools in the review's allowedTools, or have the agent handle a denial by finishing with whatever verdict it can (as it does successfully in some runs — e.g. run 28612906160 explicitly noted "network access was blocked" and still produced a full verdict), rather than stopping short.

Refs #173 (closed, symptom/guard side of this).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions