Reinstate checks: read on the claude-review model job as v3 - #882
d-morrison wants to merge 2 commits into
Conversation
Closes #833. #832 dropped this scope from the model job to un-break the 17 of 18 repositories pinning claude-code-review.yml@v2 that had not yet granted checks: read at the caller level (#831), but that also reopened the HTTP 403 on GET .../commits/{ref}/check-runs the scope existed to fix in the first place (#829, ucdavis/bcs#964): the reviewer (and any caller-side check-pr-fully-clean.py) can no longer verify CI status and reports an unverifiable diff as blocked, even when every real check is green. Measured on Morrison-Lab/lbt#11 (2026-09-16): content review clean, every substantive CI check green, but require-clean-verdict still failed because claude-review's own token couldn't read check-runs. Reinstating the scope now is a major-tag bump rather than a v2 slide, per the rule this repo's own README and CLAUDE.md already document: adding a job permission breaks every caller lacking the grant at parse time. A caller still pinned at @v2 is unaffected -- it only sees what its pinned tag resolves to. A caller that already grants checks: read (the README, examples/claude-code-review.yml, and website docs have asked for it since #832) moves to @V3 at no cost. Updates run-review-job-split-tests.py's exact-set assertion, its good_wf fixture, and its mutation self-tests to match the new v3 baseline (added-scope now tests an unrelated extra scope instead of checks: read, plus a new dropped-checks mutation guards the other direction), and brings README.md/CLAUDE.md/website docs' model-scope prose in line with the new state. All 243 run-review-job-split-tests.py assertions and all 54 of its --self-test mutation cases pass locally. Cutting the actual v3 tag is left to a maintainer -- this PR only lands the code and docs; see the PR description for the adoption-count caveat noted in #833. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
check-new-line-breaks flagged one line in the new changelog fragment that packed two sentences together. Rewrapped to one clause/sentence per line, matching this repo's own convention (and the rest of the fragment, which was already compliant). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Fixed the The remaining Posted by Claude Code (AI agent) --- not written by a human. |
|
Claude finished review — View run Confirmed unchanged: the Review: PR #882 — Reinstate
|
Built to branch |
Summary
Closes #833.
claude-code-review.yml'sclaude-review(model) job holdschecks: readagain, so the reviewer'sGET /repos/{owner}/{repo}/commits/{ref}/check-runsreads stop 403ing (gha#829, ucdavis/bcs#964). #832 had dropped that scope to un-break the 17 of 18@v2consumers that hadn't yet grantedchecks: readat the caller level (gha#831) — but that also reopened the 403 for everyone, so a review can currently report a genuinely clean, all-green PR as blocked because it can't verify CI status at all, not because anything is actually wrong.Real-world trigger: Morrison-Lab/lbt#11 — content review clean, every substantive CI check green, but
require-clean-verdictfailed because the model job's own token couldn't read check-runs. Retrying the review job produced the identical failure, confirming it's structural rather than transient.Why this is a new major tag, not a
v2slidePer this repo's own documented rule (README's "Widening permissions is a breaking change", and the extensive history already in
claude-code-review.yml's comments): a reusable workflow's job cannot request a permission its caller lacks, or the whole run ends instartup_failurebefore any job begins. Addingchecks: readback is exactly that kind of addition, so it belongs in a new tag a caller opts into, never a silent slide of@v2.@v2is completely unaffected — it only ever sees what its pinned tag resolves to.checks: read(the README,examples/claude-code-review.yml, and website docs have asked for it since fix(claude-code-review): drop the callee's checks: read that startup-fails every caller without it (closes #831) #832, specifically to pre-position callers for this) moves to@v3at zero cost.I have not cut the
v3tag itself — that's a maintainer call, and #833 also asks to "confirm first that consumers have picked up the caller-side grant" before it's worth widely recommending. This PR only lands the code, tests, and docs so that check is unblocked whenever you're ready to look at it.Changes
.github/workflows/claude-code-review.yml:checks: readback on theclaude-reviewjob'spermissions:, comment rewritten with the full v2→v3 history for the next person who touches this..github/workflows/scripts/tests/run-review-job-split-tests.py: the exact-set permission assertion, the syntheticgood_wffixture, and the--self-testmutation suite all updated to the new v3 baseline —added_scopenow tests an unrelated extra scope (security-events: read) instead of reusingchecks: read, since that's no longer an addition; added a mirrordropped_checksmutation to guard the other direction (accidentally losing the scope again).README.md,CLAUDE.md,website/permissions.qmd,website/reference/claude-code-review.qmd,website/workflows.qmd: prose brought in line with the new state (all four copies of the "model-scope parenthetical" the test suite pins).breaking).examples/claude-code-review.ymlandrun-audit-callee-permissions-tests.pyare intentionally untouched (the former already grantschecks: readat the caller level; the latter uses it only as an unrelated synthetic example). No existingchangelog.d/*.mdfile was touched.Test plan
python3 .github/workflows/scripts/tests/run-review-job-split-tests.py— 243/243 assertions passpython3 .github/workflows/scripts/tests/run-review-job-split-tests.py --self-test— 54/54 mutation cases passpython3 .github/workflows/scripts/tests/run-audit-capability-versioning-docs-tests.py— unaffected, still passesclaude-reviewjob's permissions changed, no other job disturbed🤖 Generated with Claude Code