Skip to content

fix(server): a branch's own pull request shows past a hundred same-named fork pull requests - #32796

Open
only21mil wants to merge 2 commits into
pingdotgg:mainfrom
only21mil:fix/server-own-pr-past-fork-heads
Open

only21mil wants to merge 2 commits into
pingdotgg:mainfrom
only21mil:fix/server-own-pr-past-fork-heads

Conversation

@only21mil

@only21mil only21mil commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Problem

A branch's own open pull request disappears from T3 when more than 100 newer pull requests from other forks use the same branch name: expected, the git actions control shows that pull request; actual, it shows none, so its pull request actions are gone too. Busy repositories hit this with common names such as GitHub's web-edit default patch-1; since #33954, a GitHub fork's default branch no longer does when T3 knows that default (origin/HEAD) and the head's owner.

Change

Other heads, or either unknown, read the newest 100 pull requests in any state by bare name, then keep this repository's rows. In GitManager.findLatestPrForHeadContext, when that page comes back full and holds no open match, I look the branch up once more with the existing open-only lookup (findOpenPr), which Create PR already uses, and use its result. A page that is not full, or one with an open match, makes the same single request as today. The provider, its query and the head probe are unchanged. For that default-branch head with a known owner, #33954's lookup returns only the owner's rows, so fallback needs 100 with no open match.

Scope

A bug fix for wrong data: branch status reports no pull request for a branch that has an open one. This is a very small, focused fix for an obvious bug, so it comes without a prior issue. Left as is: a branch whose own pull request is closed or merged, with more than 100 newer same-named pull requests, still shows none unless #33954's lookup covers it.

Against the previous head: for that default-branch head with a known owner, main's owner-qualified probe replaces the bare one this branch fell back from. In the merge conflict I took main's probe call and kept the full-page flag.

Verification

To see it on Linux web: (1) check out a fork of DefinitelyTyped/DefinitelyTyped on patch-1, with that repository as the upstream remote, whose own open pull request is not among GitHub's 100 newest patch-1 pull requests (here #71729); (2) add it as a project in the web client and start a thread; (3) Version Control shows no pull request on main, and #71729 on this branch.

I ran exactly that against real GitHub on main c00a373491 (with #33954), then on this branch merged with it (7c0033048a, local): main shows no pull request for patch-1 and this branch shows #71729; on both, a fork's master shows its #73307. The new test fails on that main and passes here. A maintainer's check covered the earlier head a459d6bda2 on a fork's master.

Before, main c00a373: patch-1 shows no pull request
Before, main c00a373491: patch-1 shows no pull request

After, this branch merged with main (7c0033048a): patch-1 shows #71729
After, this branch merged with main (7c0033048a): patch-1 shows #71729

Not checked:

  • Desktop and mobile: not run; they read the same server branch status.
  • A real provider turn: the thread came from the free Replay (dev) provider; the lookup does not depend on it.
Method, background, GitHub reads, traces, default-branch captures and tests

Each revision ran as its own T3 dev server from source on Linux, in a sandbox named "Test machine", reading GitHub through a read-only GitHub App token. Its web client ran in T3's Browser panel, driven by clicks and typing, and one message to the free Replay (dev) provider created each thread. Both checkouts are shallow clones of real forks whose origin/HEAD points at the fork's default branch master, as a normal clone does.

Busy repositories: DefinitelyTyped/DefinitelyTyped has 15,100 pull requests from heads named master and 5,158 from patch-1 (GitHub's counts read today). There, #73307 and #71729 are outside the 100 newest for their head names today.

#13200 chose the bare-name lookup so that "same-named branches on other forks can no longer crowd out the real match". Once more than 100 newer same-named pull requests exist, that page holds only other forks' rows and nothing matches. Open pull requests are far fewer (12 for master and 18 for patch-1 there today), so the open-only lookup still finds it. The fix makes the lookup #13200 designed hold past its first page, with no new setting, query or UI. It covers every host through the same code; GitHub and Azure DevOps use the 100-row probe. Finding a closed or merged pull request past the first page would need paging the bare branch name across all states, which can mean thousands of rows.

What GitHub returned for the bare-name lookups just before the main server started, read with the same kind of token:

read at 2026-11-12T21:34:42Z
$ gh pr list --repo DefinitelyTyped/DefinitelyTyped --state all --head master --limit 100 --json number
100 results, newest #76133 through #74488; #73307 absent
$ gh pr list --repo DefinitelyTyped/DefinitelyTyped --state open --head master --limit 100 --json number
12 results; #73307 present (position 4)
$ gh pr list --repo DefinitelyTyped/DefinitelyTyped --state all --head patch-1 --limit 100 --json number
100 results, newest #75907 through #72890; #71729 absent
$ gh pr list --repo DefinitelyTyped/DefinitelyTyped --state open --head patch-1 --limit 100 --json number
18 results; #71729 present (position 5)

Each branch-status lookup in each server's own trace: the path it took, its duration, and the calls beneath it. Owner REST lookups are the fork's master; bare GraphQL lookups are patch-1. In this run the master lookup stays one REST call with no fallback on both builds; on patch-1 this branch adds the open-only lookup after the full first page:

== main
2026-11-12T21:35:15Z  owner REST  486 ms  listChangeRequests=1  restSends=1  findOpenPr=0
2026-11-12T21:35:27Z  owner REST  614 ms  listChangeRequests=1  restSends=1  findOpenPr=0
2026-11-12T21:35:53Z  bare GraphQL  6126 ms  listChangeRequests=1  restSends=0  findOpenPr=0
2026-11-12T21:36:01Z  bare GraphQL  4645 ms  listChangeRequests=1  restSends=0  findOpenPr=0
2026-11-12T21:36:06Z  bare GraphQL  4016 ms  listChangeRequests=1  restSends=0  findOpenPr=0
2026-11-12T21:36:35Z  owner REST  475 ms  listChangeRequests=1  restSends=1  findOpenPr=0
== cand
2026-11-12T21:40:34Z  owner REST  539 ms  listChangeRequests=1  restSends=1  findOpenPr=0
2026-11-12T21:40:43Z  owner REST  549 ms  listChangeRequests=1  restSends=1  findOpenPr=0
2026-11-12T21:41:11Z  bare GraphQL  7367 ms  listChangeRequests=2  restSends=0  findOpenPr=1
2026-11-12T21:41:21Z  bare GraphQL  6165 ms  listChangeRequests=2  restSends=0  findOpenPr=1

Main c00a373: the fork's master checkout shows its open pull request #73307
Main c00a373491: the fork's master checkout shows its open pull request #73307

This branch merged with main (7c0033048a, local, not pushed): the fork's master checkout still shows #73307
This branch merged with main (7c0033048a, local, not pushed): the fork's master checkout still shows #73307

Test, a new case in apps/server/src/git/GitManager.test.ts: a fork branch whose all-states page holds 100 closed pull requests from other forks, and whose open lookup returns its own pull request. With main's GitManager.ts (c00a373491) and this branch's test file, on Node 26.12.1 (lines selected by grep -E '^\$ |×|AssertionError|expected|Tests '):

$ git show c00a373491d20ebcef901b81170abfb9f5f757fe:apps/server/src/git/GitManager.ts > apps/server/src/git/GitManager.ts   (main production file, this branch test file kept)
[21:39:46.546] ERROR (#31): Error [AssertionError]: expected null to match object { number: 1, state: 'open' }
  expected: { number: 1, state: 'open' },
     × finds a fork branch's open PR past a full page of other forks' PRs 200ms
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯
AssertionError: expected null to match object { number: 1, state: 'open' }
      Tests  1 failed | 132 skipped (133)

The commit handed over, e6788358f1, has the same tree as 7c0033048a; only its merge message changed. On that merged tree, on Node 26.12.1: GitManager.test.ts passes (133 tests, #33954's cases among them), #33954's GitHubSourceControlProvider.test.ts passes (38 tests), and vp run check:changed c00a373491 passes (format, lint, knip, graphql, typecheck, 135 tests).

Generated with Claude Opus 5.5 in T3 Code Nightly

…med fork pull requests

Branch status looks a branch's pull request up by its bare head name, one
page of 100 across all states, and keeps rows whose head repository matches.
When more than 100 newer pull requests from other forks reuse that head name
(common for `main` or `patch-1` on busy repositories), the page holds only
their rows and the branch's own open pull request never shows.

When an all-states page comes back full and holds no open match, look the
branch up once more among open pull requests only and use that result. Pages
that are not full make no extra request.
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Nov 8, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at a459d6b

Macroscope's review found this PR approvable — This adds an open-PR lookup fallback when same-named fork PRs fill the initial results page. Existing repository matching remains in place, and the additional queries are read-only.

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

@coderabbitai

coderabbitai Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The pull request changes fork pull request lookup to retry with an open-state query when an all-states query returns a full page. A regression test covers finding a matching open pull request from a fork on the subsequent query.

Changes: Fork pull request lookup

Layer / File(s) Summary
Full-page lookup fallback
apps/server/src/git/GitManager.ts, apps/server/src/git/GitManager.test.ts
findLatestPrForHeadContext tracks whether a query returns a full page. If no matching open pull request is found, it calls findOpenPr when a page was full. The regression test checks that the matching fork pull request is returned and that queries use all followed by open.

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

Change: Bug fix

Suggested reviewers: juliusmarminge, saphid

Merge Risk: Minimal · up to a459d

The full-page lookup fallback has a targeted regression test. No actionable issue remains identified before merge.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title names the main change: a branch's own pull request now shows past more than a hundred same-named fork pull requests. The raw summary and objectives confirm the change adds a retry through th…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description covers the template sections. Problem explains the bug and expected behavior. Change describes the fix in findLatestPrForHeadContext and what stays unchanged. Scope states this is a bu…
Full details: Title check

Explanation

The title names the main change: a branch's own pull request now shows past more than a hundred same-named fork pull requests. The raw summary and objectives confirm the change adds a retry through the open-only lookup when the all-states page is full with no open match. The title follows the conventional commit style that the repository template asks for.

Full details: Description check

Explanation

The description covers the template sections. Problem explains the bug and expected behavior. Change describes the fix in findLatestPrForHeadContext and what stays unchanged. Scope states this is a bug fix, explains why no issue is linked, and notes the remaining limitation for closed or merged PRs. Verification gives reproduction steps, observed before and after results, a new test with its failure output, and lists what was not checked. The template's Scope section asks for a linked issue or a reason for none, and the author gives a reason. The description also ends with the model and harness used, as the template requests.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 71c2d3a and a459d6b.

Files selected for processing: 2

  • apps/server/src/git/GitManager.test.ts
  • apps/server/src/git/GitManager.ts

Limit details: You’ve used all 10 included reviews currently available.

@maria-rcks

maria-rcks commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified unchanged head a459d6bda2f517337548c46da71b03d7cb05207d on linux, using the dev web client, playwright with google chrome, real github api responses, and real codex gpt-6.1-sol turns. no mocks, fixtures, or demo data.

reproduced on github/main (cec8d73a1f): a real checkout of micro-jumbo/DefinitelyTyped on master has open draft pr DefinitelyTyped/DefinitelyTyped#73307, but t3 shows no pr and offers "Create PR". github's first 100 all-state master results exclude #73307; its open-only results contain it (11 results total).

on this pr's exact head, the same checkout and thread show #73307 and its title. the websocket branch status changes from pr: null to the correct open draft pr. opening it loads its summary and code file list. real codex turns completed on both servers and returned the same branch and sha.

nearby behavior passed: a different real fork's first-page pr #75865 appears; creating an unpublished branch through the ref picker clears that association and offers "Create PR"; switching back restores #75865.

blacksmith: all 126 git manager tests passed. vp run check:changed HEAD^ passed format, lint, knip, graphql, typechecks and 128 tests. supplied the parent ref after fetching shallow history because the worker initially lacked a main merge base. existing ci has no failing or pending checks. no code changes or pushes were needed.

main: the real master branch offers Create PR and has no pr

pr head: the same checkout and conversation show open draft pr 73307

opening the recovered pr summary and code file list

runtime command and websocket transcript

Not verified

native desktop, ios/android, remote relay/tunnel connections, other source-control hosts, and non-codex providers were not exercised. closed or merged prs hidden beyond the first 100 rows remain outside this fix's stated scope. no external pr creation, push, merge, or review mutations were exercised.

@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

Thank you, Maria, for testing this against real GitHub. That is the one thing the description listed as not checked, since our run used a stub API with fake data. Your run reproduced the bug on main with a real repository: the first 100 all-state master results left out open draft #73307, so T3 showed no PR and offered "Create PR". On this head the same checkout showed #73307 and its title, and branch status went from pr: null to that PR.

Your nearby checks cover the paths this change must leave alone. A fork whose PR is on the first page still shows it (#75865). A new unpublished branch clears the association and offers "Create PR", and switching back restores it.

Noted that desktop, mobile, remote connections, other hosts and other providers were outside this pass. As you say, closed or merged PRs past the first 100 rows stay out of scope, as the description states.

Conflict in apps/server/src/git/GitManager.ts, findLatestPrForHeadContext: took main's headBranchProbe call from pingdotgg#33954, which asks for owner:branch when the head is the default branch, and kept this branch's pageWasFull flag below it, so the open-only fallback runs only after a full probe page with no matching open PR. GitManager.test.ts merged without conflict.
@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

I merged main to clear the conflict with #33954.
In GitManager.ts the lookup now uses main's owner-filtered probe with this PR's full-page check under it; this PR's own one-line probe is gone.
This PR still finds the open pull request for other head names such as patch-1, and for a default-branch head whose owner is unknown.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS 0-9 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants