Skip to content

Stabilize PR status lookups and provider session lifecycle#4281

Merged
juliusmarminge merged 3 commits into
mainfrom
t3code/audit-sidebar-git-queries
Jul 22, 2026
Merged

Stabilize PR status lookups and provider session lifecycle#4281
juliusmarminge merged 3 commits into
mainfrom
t3code/audit-sidebar-git-queries

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Jul 22, 2026

Copy link
Copy Markdown
Member

Summary

  • Cache GitHub PR lookups with refresh invalidation and preserve the last known PR during transient failures.
  • Normalize Git remotes and improve GitHub/VCS status handling.
  • Simplify provider session lifecycle transitions and remove obsolete pending-start behavior and tests.

Testing

  • Not run (no test results provided).

Note

Medium Risk
Changes visible PR badge behavior on errors and caches PR association separately from other status fields; incorrect sticky fallback rules could show wrong PRs until upstream/remote keys change.

Overview
PR status now uses a separate slow cache for hosting-provider PR lookups (ahead/behind still refresh on the fast status cadence). Transient gh failures return the last known PR instead of clearing the badge, with guards so retargeted upstreams, repointed remotes, or fork changes do not show a stale association.

Explicit invalidateStatus (user refresh, git actions) bumps a PR lookup epoch so live lookups run immediately; VcsStatusBroadcaster.refreshStatus calls that full invalidation instead of only local/remote caches.

GitHub PR list decoding tolerates older gh (< 2.47) payloads missing headRepository.nameWithOwner / owner login by reconstructing owner/repo when possible.

ensureRemote reuses an existing remote when URLs match after shared normalizeGitRemoteUrl (ssh/https, ports, .git, casing). Branch head context tracks headRemoteUrlKey for the sticky-PR matching rules.

Reviewed by Cursor Bugbot for commit c0b9cee. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Stabilize PR status lookups with caching, fallback state, and provider session lifecycle fixes

  • Adds a PR lookup cache in GitManager.ts keyed by branch/upstream/epoch with a 2-minute TTL for hits and 20-second TTL for failures, replacing raw findLatestPr calls on every remote status read.
  • On transient lookup failures, retains the last known PR per branch rather than clearing it, and bumps a per-cwd epoch on explicit invalidation to force a fresh lookup.
  • VcsStatusBroadcaster.refreshStatus now calls a single invalidateStatus instead of separate local/remote invalidations, ensuring the PR cache epoch is also bypassed on manual refresh.
  • Relaxes GitHubPullRequestSchema to tolerate older gh output that omits headRepository.nameWithOwner, reconstructing it from owner login and repo name when available.
  • GitVcsDriver.ensureRemote now uses shared normalizeGitRemoteUrl to recognize equivalent remotes across http/ssh variants, schemes, ports, and .git suffix differences.
  • Behavioral Change: default-branch PR lookups now only return open PRs; previously closed PRs on the default branch could surface in status.

Macroscope summarized c0b9cee.

- Cache GitHub PR lookups while preserving the last known result on failures
- Support older gh repository response fields
- Reuse remotes across SSH and HTTPS URL variants
- Route refreshes through full VCS status invalidation
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 865d26b7-02be-4d57-9d62-3427ef7e1529

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/audit-sidebar-git-queries

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 22, 2026
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
// ensureRemote reuses an existing remote instead of adding an ssh/https
// duplicate (git@host:owner/repo, ssh://git@host/owner/repo,
// https://host/owner/repo all compare equal).
const scpLike = /^(?:ssh:\/\/)?(?:[^@/:]+@)([^:/]+)[:/](.+)$/.exec(normalized);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium vcs/GitVcsDriverCore.ts:248

normalizeRemoteUrl treats the port in an SSH URL as part of the repository path. ssh://git@github.com:22/owner/repo.git normalizes to github.com/22/owner/repo, while the equivalent https://github.com/owner/repo.git normalizes to github.com/owner/repo. As a result, ensureRemote fails to match the existing remote and adds a duplicate whenever the SSH URL explicitly includes a port.

The scpLike regex captures host:port/path in group 2 instead of excluding the port. It needs to separate an optional :port from the host before constructing host/path.

-  const scpLike = /^(?:ssh:\/\/)?(?:[^@/:]+@)([^:/]+)[:/](.+)$/.exec(normalized);
+  const scpLike = /^(?:ssh:\/\/)?(?:[^@/:]+@)([^:/]+)(?::\d+)?[:/](.+)$/.exec(normalized);
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/server/src/vcs/GitVcsDriverCore.ts around line 248:

`normalizeRemoteUrl` treats the port in an SSH URL as part of the repository path. `ssh://git@github.com:22/owner/repo.git` normalizes to `github.com/22/owner/repo`, while the equivalent `https://github.com/owner/repo.git` normalizes to `github.com/owner/repo`. As a result, `ensureRemote` fails to match the existing remote and adds a duplicate whenever the SSH URL explicitly includes a port.

The `scpLike` regex captures `host:port/path` in group 2 instead of excluding the port. It needs to separate an optional `:port` from the host before constructing `host/path`.

Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
Comment thread apps/server/src/git/GitManager.ts Outdated
Comment thread apps/server/src/vcs/VcsStatusBroadcaster.test.ts
@macroscopeapp

macroscopeapp Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

1 blocking correctness issue found. This PR introduces new caching and fallback behavior for PR status lookups, representing significant runtime changes rather than simple fixes. Two unresolved review comments also identify potential bugs in the new logic that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

…fallback, complete mocks

- Replace the hand-rolled normalizeRemoteUrl in GitVcsDriverCore with the
  shared normalizeGitRemoteUrl, which correctly drops explicit ssh ports
  (ssh://git@host:22/owner/repo now matches https://host/owner/repo).
- Key the last-known-PR fallback by (cwd, branch) only so an upstream
  change (e.g. first push -u) does not orphan the sticky value.
- Implement invalidateStatus in the remaining GitWorkflowService/GitManager
  test mocks; the missing method made the background-refresh server test
  hang for 120s in CI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread apps/server/src/git/GitManager.ts
…upstream

The last-known-PR fallback (added to avoid blanking the badge on a transient
gh failure) is keyed by branch only, so a retarget to a different
upstream/fork mid-failure could surface a PR that no longer matches the
current head. Track the upstream the fallback was resolved against and
withhold it when both the cached and current upstreamRef are known and
differ, while still tolerating an upstream merely appearing or disappearing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON, but a cloud agent failed to start.

Reviewed by Cursor Bugbot for commit c0b9cee. Configure here.

// without invalidating the fallback when it still targets the same repo.
if (lastKnown.headRemoteUrlKey !== null || current.headRemoteUrlKey !== null) {
return lastKnown.headRemoteUrlKey === current.headRemoteUrlKey ? lastKnown.pr : null;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sticky PR dropped on null URL key

Medium Severity

resolveLastKnownPr clears sticky PR badges prematurely. Transient failures (e.g., git config read errors, gh API issues) can cause headRemoteUrlKey mismatches or null values. The function's strict headRemoteUrlKey comparison then incorrectly invalidates the remembered PR, even if the branch's remote identity is unchanged, affecting fork workflows.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c0b9cee. Configure here.

@juliusmarminge
juliusmarminge merged commit 376c149 into main Jul 22, 2026
16 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/audit-sidebar-git-queries branch July 22, 2026 15:49
UNN-Devotek pushed a commit to unn-corp/t3code that referenced this pull request Jul 23, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)
cursor Bot pushed a commit to aaditagrawal/t3code that referenced this pull request Jul 25, 2026
…dotgg#2284) (#184)

* Sidebar v2 beta: flat thread list with a server-backed settled lifecycle (pingdotgg#4026)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
(cherry picked from commit 32c6012)

* fix(settings): validate the add-provider wizard step before advancing (pingdotgg#2813) (pingdotgg#3100)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit 282ecb3)

* fix(claude): isolate capability probe from user MCP servers (pingdotgg#4015)

Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit aa5ec80)

* Preserve connecting status while a turn starts (pingdotgg#4101)

Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit 783692a)

* fix(server): stop restoring stale OpenCode models (pingdotgg#4095)

Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit 4e09cdd)

* [codex] keep scoped package references as text (pingdotgg#4167)

Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
(cherry picked from commit c7b21ff)

* fix(web): default provider selection for users without Codex (pingdotgg#4117)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit b6e1b39)

* Unify temporary worktree branch naming (pingdotgg#4278)

(cherry picked from commit 571a8b4)

* fix(web): use message-square icon for settled icon-less project threads in sidebar v2 (pingdotgg#4279)

(cherry picked from commit 020179c)

* Stabilize sidebar settling animations (pingdotgg#4280)

(cherry picked from commit 18b4688)

* Restore Copy Link in chat link context menu (pingdotgg#4161)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
(cherry picked from commit e5fba26)

* fix(desktop): handle EPIPE errors on stdout/stderr to prevent crash dialog (pingdotgg#4213)

(cherry picked from commit f74eb62)

* Preserve draft thread highlighting during promotion (pingdotgg#4283)

Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit 18fa89c)

* Move mobile working timer into the thread timeline (pingdotgg#4285)

(cherry picked from commit 7e2bb47)

* Stabilize PR status lookups and provider session lifecycle (pingdotgg#4281)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 376c149)

* fix: open command palette instead of custom dialog for new thread picker in SidebarV2 (pingdotgg#4269)

(cherry picked from commit 9fe4832)

* fix(server): don't drop sticky PR fallback when remote URL can't be resolved (pingdotgg#4289)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 9a0a071)

* feat(web): copy branch name via right-click in the branch selector (pingdotgg#4275)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 78a0ea5)

* Add remote server updates and standalone service management (pingdotgg#4286)

Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit ab4a883)

* Refine light-mode sidebar surfaces (pingdotgg#4268)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit 593289c)

* fix(mobile): don't mark Android VPN/Tailscale as offline when connected (pingdotgg#3949)

(cherry picked from commit bc9428a)

* improve and prevent silent thread branch drift and PR fetching (pingdotgg#2284)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@users.noreply.github.com>
(cherry picked from commit 2d31cb0)

* fix(sync): restore fork migration IDs under Sidebar v2 settled

Upstream pingdotgg#4026 replaced Migrations.ts with linear upstream numbering and
dropped fork-only migrations (NormalizeLegacyProviderKinds,
RepairProposedPlanColumns, BackfillForkProviderInstanceIds). Restore the
fork registry and append ProjectionThreadsSettled as ID 36.

Co-authored-by: aaditagrawal <aaditagrawal@users.noreply.github.com>

---------

Co-authored-by: Theo Browne <me@t3.gg>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <maria@kuuro.net>
Co-authored-by: Leonel Rivas <encriptandost@gmail.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Jaret Bottoms <jaretbottoms@gmail.com>
Co-authored-by: Ishan <ishansachu1@gmail.com>
Co-authored-by: Yukun Shan <92423096+nateEc@users.noreply.github.com>
Co-authored-by: Maxwell Young <maxtheyoung@gmail.com>
Co-authored-by: Miklós Fazekas <mfazekas@szemafor.com>
Co-authored-by: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com>
Co-authored-by: Henry Zhang <113233555+caezium@users.noreply.github.com>
Co-authored-by: Rushikesh Gaikwad <81632222+Wraient@users.noreply.github.com>
Co-authored-by: legs <145564979+justsomelegs@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: aaditagrawal <aaditagrawal@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant