fix(web): sidebar follows a worktree thread's live branch - #8126
Draft
sethwebster wants to merge 1 commit into
Draft
fix(web): sidebar follows a worktree thread's live branch#8126sethwebster wants to merge 1 commit into
sethwebster wants to merge 1 commit into
Conversation
Plan item: resolve the sidebar's branch label from live git status for worktree threads. Sidebar rows render the persisted `thread.branch`, which nothing ever reconciles against git. The thread view resolves the same value through `resolveBranchToolbarValue`, which prefers the live `gitStatus.refName`. So once a worktree's checked-out branch diverges from the stamp, the two views disagree and the sidebar keeps showing a branch the thread left. A worktree belongs to exactly one thread, so its checked-out ref is that thread's branch — `resolveSidebarThreadBranchLabel` adopts it for worktree rows and falls back to the stamp on detached HEAD. The shared local checkout is left alone: its ref belongs to whichever thread last switched it, so adopting it would relabel every row in the project. The rows already subscribe to `vcsEnvironment.status` for the mismatch warning, so the live ref costs no extra query. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What Changed
Sidebar rows resolve their branch label through a new
resolveSidebarThreadBranchLabel, which adopts the livegitStatus.refNamefor worktree threads and falls back to the stampedthread.branchon detached HEAD. Local-checkout rows are unchanged.Applied to the three places that previously read
thread.branchdirectly: the thread row label, the hover tooltip, and the search-result row (which shares that tooltip).+91 / −4 across three files, one of them the test.
Why
Sidebar rows render the persisted
thread.branch. The thread view resolves the same value throughresolveBranchToolbarValue, which prefers the livegitStatus.refName. Because the server only follows drift at turn completion, the two disagree in the window between a mid-turngit checkoutand the end of that turn, and indefinitely for a checkout never followed by a turn.So the moment a worktree's checked-out branch diverges from the stamp, the two views disagree: the toolbar follows reality while the sidebar keeps showing a branch the thread has already left.
A worktree belongs to exactly one thread, so whichever ref is checked out there is that thread's branch. The shared local checkout is the opposite — its ref belongs to whichever thread last switched it — so those rows keep the branch of record and let the existing mismatch warning explain the difference.
The rows already subscribe to
vcsEnvironment.statusfor that warning (Sidebar.tsx:792and:1622), so reading the live ref costs no additional query.Scope and non-goals
In scope: the web sidebar's branch display for worktree threads.
Explicit non-goals:
thread.branchstays stale inprojection_threads, so mobile's thread list (apps/mobile/src/features/threads/thread-list-items.tsx:465) and PR matching still read the old value. Fixing that needs a server-side branch-update event, which [Bug]: Worktree threads lose their PR badge once the agent switches branches inside the worktree #4831 noted does not exist..gitwatcher inapps/server/src; local status is only re-read on an in-app git action, an explicitvcsRefreshStatus, or the end-of-turnCheckpointReactor. The 30s loop refreshes remote status only. This PR makes the sidebar agree with the thread view, not update sooner — so it does not fix [Bug]: Branch name in session screen is not reactive #7409, whose repro is a baregit checkoutin the terminal panel.Related work
projection_threads.branch.Sidebar.logic.tsfor a different problem and predates theSidebarV2.tsx→Sidebar.tsxrename.Decisions
refNameon the shared local checkout would relabel every row in a project whenever one thread switched branches.Implementation checklist
resolveSidebarThreadBranchLabelwith worktree/local split and detached-HEAD fallbackVerification
vp test run apps/web/src/components/Sidebar.logic.test.ts— 110 passed, 5 newtsgo --noEmitonapps/web— cleanvp lint --report-unused-disable-directiveson the three changed files — cleanvp fmt --checkon the three changed files — cleanbranch: agent/renamed-during-runfor the worktree thread andbranch: mainfor the local oneUI Changes
A worktree thread stamped
t3code/rework-branch-toolbarwhose worktree was switched toagent/renamed-during-run, next to a local-checkout thread onmainas a control. Same fixture, same viewport; only the build differs.Before, the worktree row shows the stale stamp. After, it shows the branch the worktree is actually on. The local-checkout row reads
mainin both, confirming shared checkouts are untouched.Security and compatibility
No contract, schema, or server change; no new network calls; no auth or trust-boundary surface. Purely which of two already-present client values is rendered. Fully backward compatible — a client without this change simply keeps showing the stamped branch.
Deviations
Adversarial review found three defects in this change as written. Recorded here rather than silently amended:
resolveSidebarThreadBranchLabel's comment claims a worktree belongs to exactly one thread. It does not —new-thread-on-branch(Sidebar.tsx:3109) carriesworktreePathinto a second thread anduseHandleNewThread.ts:403persists it. The server guards this with an explicitworktreeIsSharedcheck; this change has no equivalent, so two threads sharing a worktree would both be relabeled from one thread's checkout.isTemporaryWorktreeBranch(packages/shared/src/git.ts:107) so it does not race the first-turn auto-rename. This change adopts any non-null ref, so a row can briefly render at3/<hex>placeholder.copy-branch, andnew-thread-on-branchstill key offthread.branch. Worse,resolveDisplayedThreadPrrequiresrefName === thread.branch, so a drifted row now prints branch B while hiding branch B's PR badge.Scope is being reconsidered in light of the existing server-side drift-follow.
Checklist
Made with Claude Opus 5 in the Claude Code harness.
Note
Fix sidebar to show a worktree thread's live branch instead of stamped branch
resolveSidebarThreadBranchLabelin Sidebar.logic.ts to compute the displayed branch label. For dedicated worktrees it uses the current git ref (gitStatus.refName) when available, falling back to the stampedthread.branch; for shared local checkouts it usesthread.branch.SidebarThreadRow,SidebarSearchResultRow, andSidebarThreadTooltiprender the computedbranchLabelinstead of always usingthread.branch. The tooltip hides the branch row when the label is null.thread.branchwill see the new value.Macroscope summarized 7dca192.