fix(github): pull requests short of required approvals no longer show as approved#25725

open3
main
fix/issue-25717
opened3d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 14h ago

Problem

When a branch needs more approvals than a PR has, GitHub reports reviewDecision: REVIEW_REQUIRED. T3 Code still showed the PR as "Approved" if any one latest review was an approval. To reproduce on main (becf853def), link nodejs/node#67028 to a thread and open the thread's Pull requests panel. GitHub reports REVIEW_REQUIRED for that PR, with one APPROVED review, yet the row shows the green "Approved" glyph.

Change

toReviewDecisionWithReviews in packages/source-control-github/src/server/gitHubPullRequestJson.ts derives a verdict from the latest reviews when GitHub's summary does not settle it. Before this change it also turned an explicit REVIEW_REQUIRED into "approved". Now an approving review produces "approved" only when GitHub reported no decision at all, which is the case the fallback exists for (for example a bot approval on a branch without review rules). A PR that is short of its required approvals stays "review-required", shown as "Awaiting review". This also covers an approval GitHub does not count toward a review rule, such as one from an app or from a user without write access: it now reads "Awaiting review", which matches GitHub's own status. A changes-requested review still shows as "Changes requested", as before. The list and the linked-PR summary both decode through this function, so the thread panel, the Pull requests page and mobile all pick up the fix.

Scope and approval

Fixes pingdotgg/t3code#25717

Verification

  • vp test run packages/source-control-github/src/server/gitHubPullRequestJson.test.ts: the new test "keeps review required when an approval falls short of the branch's required count" fails on main (expected [ 'approved' ] to deeply equal [ 'review-required' ]) and passes with the fix. The other 50 tests pass, including the existing case where a bot approval with no GitHub decision still reads "approved".

  • vp run check:changed: format, lint, knip, graphql, typecheck (11 packages) and tests pass.

  • Real web app, dev server on a fresh database, both PRs linked to one thread through "Link pull request to thread", then "Show linked pull requests". GitHub values read live via GraphQL:

    PRGitHub reviewDecision / latest reviewsRow label on main (becf853def)Row label with fix (dcbaace321)
    nodejs/node#67028REVIEW_REQUIRED / 1 × APPROVEDApproved (green)Awaiting review (muted)
    juliusmarminge/turbo-respect-pnpm-configs#1 (control, no review rule)null / 1 × APPROVEDApprovedApproved
  • Not checked: before/after screenshots are not attached. The table above records the row labels read from the rendered panel on each side. Mobile was not run; it renders the same server-decoded value.

Model and harness: Claude Opus 5.5 (issue lead, tests, implementation) with GPT-6.1-sol reviews, via Claude Code in T3 Code.

🤖 Generated with Claude Code

Checks

23 successful · 9 skipped
All checks passed
0402298

Added 3 commits

  • Merge remote-tracking branch 'origin/main' into fix/issue-257170402298
  • fix(github): pull requests short of required approvals no longer show as approveddcbaace
  • test(source-control-github): reproduce #25717 review required shown as approvede5eaa82
Synced from GitHub

Approvability

Verdict: Approved at 0402298

Macroscope's review found this PR approvable — This narrowly scoped fix prevents an individual approval from making a pull request appear approved when GitHub reports that required branch approvals are still missing. A focused regression test covers the behavior, with no product-default or static-analysis configuration changes.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire5.0 KiB5.0 KiB0 B (0.0%)6.8 KiB✅
CodexThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
CodexLive turn WebSocket wire1.2 KiB1.2 KiB0 B (0.0%)2.0 KiB✅
CodexLive turn WebSocket decoded20.9 KiB20.9 KiB0 B (0.0%)29.3 KiB✅
CodexLive turn messages220 (0.0%)8✅
ClaudeTotal thread wire5.0 KiB5.0 KiB−7 B (−0.1%)6.8 KiB✅
ClaudeThread snapshot wire3.8 KiB3.8 KiB0 B (0.0%)4.9 KiB✅
ClaudeLive turn WebSocket wire1.2 KiB1.2 KiB−7 B (−0.6%)2.0 KiB✅
ClaudeLive turn WebSocket decoded21.2 KiB21.2 KiB0 B (0.0%)29.3 KiB✅
ClaudeLive turn messages220 (0.0%)8✅

Baseline: daa720a · PR result: 0402298 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

External image Recent review info
External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between daa720a986ca40e59b063206bb03ccef87f008de and 0402298415772c8fbd6fb157a66c71afb9d5b0db.

External image Files selected for processing: 2
  • packages/source-control-github/src/server/gitHubPullRequestJson.test.ts
  • packages/source-control-github/src/server/gitHubPullRequestJson.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

Walkthrough

The decoder now uses an approved latest review as a fallback only when GitHub’s summarized review decision is null. A regression test verifies that REVIEW_REQUIRED remains review-required when the latest review is approved.

Changes: Review decision decoding

Layer / File(s)Summary
Review decision fallback and regression test
packages/source-control-github/src/server/gitHubPullRequestJson.ts, packages/source-control-github/src/server/gitHubPullRequestJson.test.ts
An approved latest review sets the decoded decision to approved only when the summarized decision is null. The test checks that a summarized REVIEW_REQUIRED decision remains review-required.

Priority: External image Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: maria-rcks

Merge Risk: External image Minimal · up to 04022

The change correctly preserves required-review status, with no actionable merge risk established.

Pre-merge checks: Passed 3 · Inconclusive 1

Failed Failed checks: 1 inconclusive

Check nameStatusExplanationResolution
Description checkInconclusiveThe description follows the repository template closely. It has a clear Problem section with a reproduction path and environment (main at becf853def, a nodejs/node PR linked to a thread). The Change s…Add a link to the triaged issue #25717 together with the maintainer approval comment or discussion that approved the direction and scope, or explain why the fix qualifies as a very small, focused bug fix without prior approval. Because this…
Passed Passed checks: 3 passed
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the fix: pull requests with insufficient required approvals no longer appear approved.
Linked Issues checkPassedIssue #25717 requires T3 Code to avoid implying full approval when required approvals are incomplete. The decoder now preserves GitHub's REVIEW_REQUIRED result when an approval exists, and the regre…
Out of Scope Changes checkPassedThe pull request changes only the shared review-decision decoder and its focused regression test. These changes directly address required-review display behavior. The diff does not add changes for che…
Full details: Linked Issues check

Explanation

Issue #25717 requires T3 Code to avoid implying full approval when required approvals are incomplete. The decoder now preserves GitHub's REVIEW_REQUIRED result when an approval exists, and the regression test verifies review-required for that case. The fallback still maps an approval to approved when GitHub reports no decision. This meets the issue's equivalent-status requirement without requiring an approval count.

Full details: Out of Scope Changes check

Explanation

The pull request changes only the shared review-decision decoder and its focused regression test. These changes directly address required-review display behavior. The diff does not add changes for checks, merge queues, or unrelated functionality.

Full details: Description check

Explanation

The description follows the repository template closely. It has a clear Problem section with a reproduction path and environment (main at becf853def, a nodejs/node PR linked to a thread). The Change section explains the fix in toReviewDecisionWithReviews and why the shared decoder reaches the thread panel, Pull requests page, and mobile. The Scope and approval section links the issue (#25717) but does not link a maintainer approval comment or discussion. It only gives a bare issue reference, so the template's approval requirement is not clearly met. The Verification section is strong: it names the focused test and its fail-then-pass result, the full check run, and a live before/after table of row labels. It also states what was not checked (screenshots, mobile). Remaining gaps: no explicit maintainer approval link or comment, and no before/after screenshots, which the template requires for UI changes. The author did note screenshots were not attached and that the table records rendered labels instead.

Resolution

Add a link to the triaged issue #25717 together with the maintainer approval comment or discussion that approved the direction and scope, or explain why the fix qualifies as a very small, focused bug fix without prior approval. Because this changes a user-visible UI label, attach before/after screenshots of the thread panel row (main versus fix) and embed or link them in the Verification section. Mobile was not run, so either run it or keep the note that it was not checked.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.