Skip to content

[Bug]: Project identity ignores gh repo set-default, so fork PRs don't match fork-based projects #15023

Description

@bompus

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Clone a fork that you develop on as its own project. Set origin to <you>/<repo> and upstream to <org>/<repo>.
  2. Point gh at the fork: gh repo set-default <you>/<repo>. This writes remote.origin.gh-resolved=base.
  3. Add the checkout as a T3 project.
  4. From a branch pushed to origin, create a PR with T3's source-control action, or open an existing fork PR in T3.

Expected behavior

The project's repository is <you>/<repo>, the repository gh resolves for the checkout. T3 links the fork PR to the thread, and the PR page and its actions (merge, close, update branch) work on it.

Actual behavior

The project's repositoryIdentity is github.com/<org>/<repo> with locator.remoteName: "upstream". I see this in the project list on my install.

The gh calls and the project identity pick different repositories:

  • pickPrimaryRemote in apps/server/src/project/RepositoryIdentityResolver.ts takes upstream before origin and does not read remote.*.gh-resolved.
  • gh pr create runs without --repo, and listPullRequestsByHead uses selectGitHubBaseRepository in apps/server/src/sourceControl/GitHubCli.ts, which honors gh repo set-default. So the PR is created on the fork, and branch lookup finds it there.
  • The found PR's repositoryKey comes from its URL (github.com/<you>/<repo>). pullRequestMatchesProject in apps/server/src/orchestration-v2/ThreadPullRequestService.ts compares it with the project identity (github.com/<org>/<repo>), the comparison fails, and the PR is not linked to the thread.
  • requireProject in apps/server/src/pullRequest/PullRequestService.ts uses the identity's repository. A hostless reference to the fork PR fails with "The change request does not belong to the selected project." The PR list for the project reads <org>/<repo>.

I found this by reading main at 3a7058da50. I have not traced it at runtime the way #7382 did.

#7382 is the mirror case: gh resolves to upstream, and PR creation assumes origin. #14843 is a related cleanup report about the primary-remote rule. Neither covers a checkout whose gh default is the fork.

A possible fix is to have RepositoryIdentityResolver apply the same gh-resolved rule as selectGitHubBaseRepository when a mark exists, and keep upstream before origin only when there is none. That would change the project identity for such checkouts, and project grouping (#4880) keys on it. A fork checkout with gh pointed at the fork would stop grouping with upstream, which seems to match what gh repo set-default asks for.

Impact

Major degradation or frequent failure

Version or commit

main at 3a7058da50 (2026-10-02). The project identity above is from T3 Code Nightly on WSL.

Environment

Desktop app connected to a WSL (Ubuntu) environment, gh 2.102.0

Logs or stack traces

The change request does not belong to the selected project.

This string comes from requireProject and is the expected error for a hostless reference. I did not capture it from a running session.

Workaround

Renaming the upstream remote makes origin the identity, but it breaks tooling that expects a remote named upstream. Otherwise, merge fork PRs with gh outside T3.

No activity

Activity on this issue will appear here.

Activity

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

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