Repository navigation
Conversation
…action-required The REST half of listWorkflowRunsRequiringApproval wrapped every failure, rate limits and host pauses included, as a read error. The provider only passes rate limits through, so a paused read became the "Workflow approval status" action-required placeholder and woke PR watches on green heads. Rate-limit and pause errors now keep their tags. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Rate-limited workflow-approval reads now retain their rate-limit status instead of appearing to require action. The change uses existing handling without altering approval permissions or workflow execution. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
|
Note Written by Verified in a real dev environmentpartial verification of neighboring behavior at i created a real repository project and threads through the web app and completed real codex server traces confirm the workflow approval rest read reached github and returned http 200 on both revisions. runtime transcript. blacksmith-check: 148 focused api/provider tests passed. Not verifiedthe core rate-limit fix remains unverified against real github. main did not reproduce the original bug: all observed workflow approval reads returned http 200 with quota remaining. neither a rate-limit refusal nor a host pause occurred, so i could not prove the pr's refusal propagation or the watcher skipping that sweep. the successful reads and tests above do not prove that case. the pr's codex session reported its pull-request read tool unavailable, so agent-side pr reading was not verified. native desktop and mobile clients were not exercised on this linux vm. |
|
Note 🤖 Opus 5.5 replying on behalf of Victor. Thanks for running this in a real dev environment. Your run shows the change leaves the normal path alone. With real workflow approval reads returning HTTP 200, the checks popover, detail refresh, and watch and stop watching behave on You're right that the refusal path itself is still unproven against real GitHub. Main didn't reproduce it for you because every approval read had quota left, and the bug only shows when GitHub refuses part of a burst. The PR's evidence for that path is the test that fails on the base and passes with the fix, plus the loopback stub that answers with GitHub's secondary rate-limit 403. The description lists a live sweep with the fix as not checked. The agent-side pull request read tool being unavailable is outside this change, which only touches one error mapping in the REST read. |
…ead-keeps-rate-limit
EvidenceOpen Pull requests, search #32990, and open its detail panel while a proxy returns a rate-limit 403 only for the action_required workflow-approval REST read. Both sides use fresh isolated state, Chromium at 1280×800, and light theme. scenarios:prove exited 0.
Scenario source · Proxy driver Not shown:
|




Problem
When GitHub refuses the workflow-run read for a fork pull request because of a rate limit, T3 adds a "Workflow approval status" check that is awaiting action. Every real check can be green, and the pull request panel shows "1 check awaiting action". This shows up when many watches re-read at once and GitHub answers part of the burst with a secondary rate limit or a host pause.
Change
listWorkflowRunsRequiringApprovalreads in two halves. The GraphQL half already lets rate-limit errors through; the REST half wrapped every failure as a read error, rate limits and host pauses included.GitHubPullRequestProvideronly passesGitHubApiRateLimitErrorandSourceControlRateLimitPausedErrorthrough and turns every other failure into the "could not determine" placeholder, so a refused read became that placeholder. The REST half now keeps those two errors as they are; every other failure still becomes a read error and still shows the placeholder. A rate-limited read now fails as rate-limited, the same as a rate-limited detail read, and the panel reports the rate limit.Scope
This is a bug fix: the panel shows a wrong status, "1 check awaiting action", where GitHub actually refused the read for a rate limit. It is a small fix for an obvious bug, so it has no issue: the provider already handles rate limits on this read, but that branch could never match for the REST half. It changes one error mapping and adds one test; workflow approval, the placeholder for other failures and the approve action's other errors are unchanged.
This is a regression from #16320: before it, this read went through the gh CLI and a rate limit reached the provider's rate-limit branch.
Verification
To see it on Linux web:
Before, main 2b07556: 1 check awaiting action, Workflow approval status awaiting action
After, head d5411fc: GitHub API rate limit exceeded, with Retry
Retry then shows the real checks, here and merged with main. Details below.
Re-checked against main 476fc9b on 2026-11-12: the new test fails there without the change and passes with it; the branch merges cleanly. A maintainer's real run on d5411fc covered the normal path (approval reads answered HTTP 200); the refusal path is the one re-checked here.
Not checked: desktop and mobile (same server data), and a refusal GitHub itself sent (the proxy stands in).
Method, test output, Retry, the head merged with main, and the proxy log
Related: #24599 changes how the watch reports workflows really waiting for approval and makes it ignore this placeholder check, so it no longer wakes an agent with "checks failed"; #26561 adds approval for same-repository pull requests.
Method: a T3 test server per revision ("Test machine", fresh state, a read-only GitHub App token) reading real GitHub. In the web client, in T3's Browser panel, I opened this pull request (a fork pull request whose checks all pass) from the Pull requests view. Stand-in: a pass-through proxy between the server and api.github.com forwards every request unchanged except one, the workflow-run read for this head (
actions/runs?head_sha=d5411fc…&status=action_required). It answers that read with a secondary rate-limit refusal instead of sending it: HTTP 403 andretry-after: 60, as GitHub's REST rate-limit docs describe, with the message GitHub's own throttling plugin uses ("You have exceeded a secondary rate limit. Please wait a few minutes before you try again."). It is not a refusal GitHub sent. Order: main2b07556d71, then this headd5411fcaf4, then this head merged locally with that main (0ffb47cbb4, not pushed). For Retry, the proxy was switched to pass that read through and I waited out the 60 seconds.After Retry with the read passing, head d5411fc: 24 of 31 passing, no Workflow approval status row
After, head merged with main 0ffb47cbb4: GitHub API rate limit exceeded, with Retry
After Retry with the read passing, head merged with main 0ffb47cbb4: 24 of 31 passing, no Workflow approval status row
packages/source-control-github/src/server/GitHubPullRequestApi.test.ts, "keeps $_tag when the workflow run read is rate-limited", one row per error, run on the merged tree: with main'sGitHubPullRequestApi.tsboth rows fail; with the fix all 155 tests in the API and provider files pass.vp run check:changed 2b07556d71on the merged tree, Node 26.12.1: format, lint, graphql, knip, typecheck (11 packages) and tests pass.Test before, on the merged tree with main's
GitHubPullRequestApi.ts:Test after, with the fix:
Proxy log, main
2b07556d71(the refused read, then a second workflow-run read for this head, passed through):Proxy log, head
d5411fcaf4(refused, then passed through on Retry):Proxy log, head merged with main
0ffb47cbb4(refused, then passed through on Retry):Generated with Claude Opus 5.5 in T3 Code Nightly