Repository navigation
Description
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
- Open a project whose folder is a git checkout on
feature/A, wherefeature/Ahas an open MR/PR. - Start a thread from the composer in the project folder (no worktree). The thread is saved with
branch: feature/A. - Ask the agent to review another MR. It runs
git checkout feature/Bin the project folder during the first turn. - Let the turn finish, then look at the thread's row in the sidebar.
Expected behavior
The row shows feature/B and feature/B's MR, since the thread is now working there.
Actual behavior
The row keeps showing feature/A and feature/A's MR. git branch --show-current in the project folder returns feature/B. The reflog shows the agent's checkout about 30 seconds after the thread started.
Later messages only fix it sometimes. In my case, 4 threads in 4 clones of the same repo all ran this flow within 3 minutes:
| Thread | Branch saved at start | Agent checkout | Later turns | Row today |
|---|---|---|---|---|
| 1 | 15:15:00 feature/A1 |
15:15:37 → feature/B1 |
turn 2 at 16:07 corrected it | correct |
| 2 | 15:16:07 feature/A2 |
15:17:14 → feature/B2 |
none | stale |
| 3 | 15:17:12 feature/A3 |
15:17:47 → feature/B3 |
turn 2 at 15:30 did not correct it | stale |
| 4 | 15:18:09 feature/A4 |
15:18:35 → feature/B4 |
turn 2 at 15:32 did not; turn 3 at 16:48 did | correct |
Impact
Major degradation or frequent failure
Version or commit
T3 Code (Beta) 0.1.7 desktop. Code paths unchanged on main @ c73b38b.
Environment
Linux 6.14 (Ubuntu), Claude agent, GitLab-hosted repo (MRs)
Cause (from reading main @ c73b38b)
- The branch is saved once, when the thread starts (
ThreadLaunchService.ts:470-478). WorktreeBranchSyncsees the checkout but only updates threads that have aworktreePath.getThreadWorktreePathsfilters withjson_extract(payload_json, '$.worktreePath') IS NOT NULL(ProjectionStore.ts:6768), so threads in the project folder never match.- The turn-end refresh reads the live branch and then stops when it differs from the saved one:
if (!thread || thread.branch !== local.refName) return;(RunFinalizationService.ts:105-111). It also stops early when the new branch is the default branch (local.isDefaultRef). - The only remaining fix-up runs in the client when a message is sent (
useThreadLifecycle.tsx:534-538viaresolveLocalCheckoutBranchMismatch). It compares against whatever git status the browser has cached, which explains the inconsistent results above. The client's live sync skips threads that have already started (GitActionsControl.tsx:1082).
The MR badge is looked up from the saved branch, so it goes stale along with it.
Suggested fix
In RunFinalizationService.refresh, when the live branch differs from thread.branch and the run is still the thread's current run, dispatch thread.metadata.update with branch: local.refName, expectedBranch: thread.branch and expectedWorktreePath: thread.worktreePath. Do this for the thread whose turn just ended, not for every thread sharing the folder. That way older threads in the same project keep the branch they actually worked on, which is presumably why WorktreeBranchSync leaves project-folder threads alone. Then let the existing MR lookup run on the new branch.
Related: #11078 and its fix PR #15989 (agent moves to another worktree; I couldn't tell whether "in-place branch reconciliation" there covers threads with no worktree), #28463 (worktree branch rename), #31177 (agent-launched project-folder threads saved with no branch), #7409.
Activity