Skip to content

improve and prevent silent thread branch drift and PR fetching#2284

Merged
juliusmarminge merged 14 commits into
pingdotgg:mainfrom
justsomelegs:t3code/git-audit-stability
Jul 22, 2026
Merged

improve and prevent silent thread branch drift and PR fetching#2284
juliusmarminge merged 14 commits into
pingdotgg:mainfrom
justsomelegs:t3code/git-audit-stability

Conversation

@justsomelegs

@justsomelegs justsomelegs commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

What Changed

Improves the local branch mismatch warning in the branch picker.

  • Highlights the branch picker with a warning color when the thread branch and current checkout differ.
  • Adds an inline warning icon to the picker.
  • Shows a popover above the picker explaining the mismatch.
  • Adds actions to either switch the checkout back to the thread branch or update the thread to use the current checkout.
  • Keeps server thread branch metadata from being overwritten when the shared local checkout changes.
  • Tightens PR/status indicator behavior so local checkout PR state is scoped to the relevant thread branch.
  • Improves PR fetching so that forked repos with PR on upstream not origin allow showing PR status in application

Why

When using local checkout mode, the active Git branch can drift away from the branch a thread was last associated with. Previously this was easy to miss and could lead to continuing work on the wrong branch.

This makes the mismatch visible in-place and gives users clear recovery actions without changing branches automatically.

The thread’s associated branch should only change when the user intentionally chooses a branch for the thread, creates/checks out a branch through the picker, or clicks Use current in the warning popover. It should not change just because the shared local checkout moved while viewing an existing server thread.

UI Changes

image image

Screenshots/video to attach:

  • Before screenshot of the old picker state.
  • After screenshot of the warning picker and popover.
  • Short video showing hover/click on the warning icon and the Use current / Switch actions.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Fix thread branch drift and PR matching for local checkouts and worktrees

  • Fixes resolveThreadPr to return the correct PR for dedicated worktrees (ignoring stale branch metadata) and to require gitStatus.refName to match threadBranch for local checkouts.
  • Reworks matchesBranchHeadContext in GitManager.ts to use normalized head identities, correctly rejecting cross-repo PRs in same-repo contexts and vice versa, and tolerating missing GitHub head identity metadata.
  • Adds resolveLocalCheckoutBranchMismatch to detect when the active git checkout differs from the thread's stored branch, and surfaces a warning banner in ChatView.tsx with actions to repair the mismatch or update the thread branch on send.
  • Adds resolveThreadMetadataUpdateForNextTurn to compute minimal thread metadata updates (model and/or branch) before sending a message.
  • Stops auto-syncing branch metadata from checkout in GitActionsControl.tsx when a server thread is active.
  • Risk: branch metadata persistence behavior changes on send when a local checkout mismatch is detected — the thread branch will be silently updated to the current checkout.

Macroscope summarized d3910e1.


Open in Devin Review

Note

Medium Risk
Changes git PR reuse/matching and when thread branch metadata updates from the UI; mistakes could show wrong PRs or leave thread branch out of sync, though behavior is covered by new tests.

Overview
Prevents silent drift between a thread’s stored branch and the shared local checkout, and tightens when PRs and status indicators apply to a thread.

In local checkout mode, the branch picker now detects when the thread branch and current Git checkout differ (resolveLocalCheckoutBranchMismatch), highlights the trigger, and shows a “Branches diverged” panel with Update thread (reassign to checkout) or Switch checkout (checkout the thread branch). GitActionsControl no longer auto-syncs thread branch from live git status while a server-backed thread is active—only draft threads still reconcile from status.

PR indicators (resolveThreadPr) now require the stored thread branch to match git status for local checkouts, but still show PR state for dedicated worktree threads even when thread branch metadata is stale or missing. PR tooltips use a richer PrStatusTooltipContent layout.

On the server, matchesBranchHeadContext is exported and reworked to compare expected vs PR head identity more carefully: reject same-repo PRs for cross-repo head contexts, refuse ambiguous PRs when GitHub omits head repo/owner on cross-repo lookups, and accept cross-repo PR metadata when the checkout remote is the fork. New GitManager tests cover these matching paths and fork PR reuse behavior.

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

@coderabbitai

coderabbitai Bot commented Apr 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: e5f251b5-75fe-4612-83ee-bd416a45058e

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

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 22, 2026
Comment thread apps/server/src/git/Layers/GitManager.ts
@macroscopeapp

macroscopeapp Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

1 blocking correctness issue found. This PR introduces new branch mismatch detection and repair features with significant runtime behavior changes. Four unresolved review comments identify potential bugs in the new logic, including missing query conditions and stale state handling issues that require resolution.

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

Comment thread apps/server/src/git/GitManager.ts
@justsomelegs justsomelegs changed the title improve and prevent silent thread branch drift improve and prevent silent thread branch drift and PR fetching Apr 22, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Heya I will properly review your PRs when we get back from Miami. Seems like some good stuff just don't have capacity to review big PRs while we're here

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 30, 2026
@justsomelegs
justsomelegs force-pushed the t3code/git-audit-stability branch from f1ffd01 to 02bb838 Compare May 1, 2026 22:56
Comment thread apps/server/src/git/GitManager.ts
@juliusmarminge

Copy link
Copy Markdown
Member

either i messed soemthing up when mergin main or i don't understand this PR:

CleanShot.2026-05-02.at.23.02.21.mp4

@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels May 3, 2026
@justsomelegs
justsomelegs force-pushed the t3code/git-audit-stability branch from e0314cf to beb7b1a Compare May 4, 2026 09:20
@vercel

vercel Bot commented May 4, 2026

Copy link
Copy Markdown

@justsomelegs is attempting to deploy a commit to the Ping Labs Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels May 4, 2026
@justsomelegs

Copy link
Copy Markdown
Contributor Author

either i messed soemthing up when mergin main or i don't understand this PR:

CleanShot.2026-05-02.at.23.02.21.mp4

It meant to warn the user when switching branches that the thread was last working on another branch so that they dont accidently try and continue the work on the wrong branch.

just pushed my local version up that is rebased onto main if you wanna try that one out.

Screen.Recording.2026-05-04.101354.mp4

Comment thread apps/web/src/components/BranchToolbarBranchSelector.tsx Outdated
Comment thread apps/web/src/components/BranchToolbarBranchSelector.tsx
Comment thread apps/web/src/components/BranchToolbarBranchSelector.tsx Outdated
Comment thread apps/server/src/git/GitManager.ts
Comment thread apps/server/src/orchestration/decider.ts
@juliusmarminge
juliusmarminge force-pushed the t3code/git-audit-stability branch from f64b18f to 22c6338 Compare July 9, 2026 06:34

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

thread.branch != null && gitCwd !== null

For a dedicated-worktree thread whose branch is null, the PR indicator never appears even though resolveThreadPr was updated to handle that case. The VCS status query at line 427 is gated on thread.branch != null, so gitStatus.data stays null and resolveThreadPr receives gitStatus: null, causing it to return null regardless of hasDedicatedWorktree. This means the PR status indicator is silently missing for exactly the missing-branch dedicated-worktree case this change intended to support. The query condition should also allow fetching when thread.worktreePath != null, e.g. (thread.branch != null || thread.worktreePath != null) && gitCwd !== null.

Suggested change
thread.branch != null && gitCwd !== null
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/Sidebar.tsx around line 428:

For a dedicated-worktree thread whose `branch` is `null`, the PR indicator never appears even though `resolveThreadPr` was updated to handle that case. The VCS status query at line 427 is gated on `thread.branch != null`, so `gitStatus.data` stays `null` and `resolveThreadPr` receives `gitStatus: null`, causing it to return `null` regardless of `hasDedicatedWorktree`. This means the PR status indicator is silently missing for exactly the missing-branch dedicated-worktree case this change intended to support. The query condition should also allow fetching when `thread.worktreePath != null`, e.g. `(thread.branch != null || thread.worktreePath != null) && gitCwd !== null`.

Comment thread apps/web/src/components/ThreadStatusIndicators.tsx
@juliusmarminge
juliusmarminge force-pushed the t3code/git-audit-stability branch from 22c6338 to f762024 Compare July 9, 2026 07:03

@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 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f762024. Configure here.


useEffect(() => {
if (isGitActionRunning || isSelectingWorktreeBase) {
if (isGitActionRunning || isSelectingWorktreeBase || activeServerThread) {

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.

Git actions still sync thread branch

Medium Severity

Live git-status branch reconciliation for server-backed threads is skipped when activeServerThread is set, so checkout can stay on one branch while stored thread metadata keeps another. Stacked git actions still call syncThreadBranchAfterGitActionpersistThreadBranchSync, which can update the server thread branch (for example when a new feature branch is created) without the user choosing Update thread or Switch checkout in the mismatch UI.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f762024. Configure here.

}),
);
}
});

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.

Stale mismatch after checkout switch

Medium Severity

After a successful Switch checkout, the picker label can update via optimistic state while resolveLocalCheckoutBranchMismatch still compares the thread branch to a stale currentGitBranch from VCS status until refresh completes, so the warning styling and popover can remain visible even though checkout already matches the thread branch.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f762024. Configure here.


setThreadBranch(localCheckoutBranchMismatch.currentBranch, null);
setIsBranchMenuOpen(false);
onComposerFocusRequest?.();

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.

Update thread keeps warning visible

Medium Severity

Update thread calls setThreadBranch for server threads, but activeThreadBranchOverride and onActiveThreadBranchOverrideChange are only passed for empty new server threads, so established threads keep showing a branch mismatch until server metadata arrives asynchronously.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f762024. Configure here.

Comment thread apps/web/src/components/BranchToolbarBranchSelector.tsx Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/git-audit-stability branch from 4ccda21 to e30be8e Compare July 22, 2026 22:41
Co-authored-by: codex <codex@users.noreply.github.com>
@juliusmarminge
juliusmarminge force-pushed the t3code/git-audit-stability branch from f51b7de to d3910e1 Compare July 22, 2026 23:08
@juliusmarminge
juliusmarminge merged commit 2d31cb0 into pingdotgg:main Jul 22, 2026
15 checks passed
UNN-Devotek pushed a commit to unn-corp/t3code that referenced this pull request Jul 23, 2026
…otgg#2284)

Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@users.noreply.github.com>
jetblk added a commit to jetblk/t3code that referenced this pull request Jul 23, 2026
…r refresh (#7)

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

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

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

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

* 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>

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

* 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>

---------

Co-authored-by: Theo Browne <me@t3.gg>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@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>
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.

2 participants