[Bug]: Shared-worktree threads show conflicting branches without a warning
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
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/web
Steps to reproduce
- Start thread A in a worktree on branch
feature/a. - Create or attach thread B to the same existing worktree.
- In thread B, create or switch the physical worktree to branch
feature/b. - Keep both threads active and switch between them in the sidebar.
- Compare each sidebar branch label with the branch shown in the composer toolbar.
A real occurrence on the latest nightly produced two running Codex sessions with this state:
thread A: branch=feature/a, worktreePath=<shared-worktree>
thread B: branch=feature/b, worktreePath=<shared-worktree>
provider cwd for both threads: <shared-worktree>
physical Git HEAD: feature/a
The event history showed both records repeatedly retaining different branch values while pointing at the same worktreePath.
Expected behavior
When a worktree is shared, T3 should make it clear that its live Git HEAD is checkout-scoped rather than thread-scoped. A thread whose recorded branch differs from the shared worktree HEAD should receive the same visible mismatch protection as a local-checkout thread before another turn can be sent.
T3 should not present the recorded sidebar branch and live toolbar branch as two equally-current values without a warning.
Actual behavior
The sidebar renders each thread’s persisted thread.branch, while the composer toolbar renders the physical worktree’s live Git branch. The labels can therefore show opposite branches as users switch between sibling threads.
More importantly, both provider sessions use the same physical cwd, so a thread labeled feature/b can continue editing or commit while the worktree is actually checked out on feature/a.
resolveLocalCheckoutBranchMismatch currently returns null whenever activeWorktreePath !== null, so no mismatch warning is shown for this case. The server-side dedicated-worktree drift fix also deliberately skips shared worktrees, leaving this exact state uncovered.
Impact
Major degradation or frequent failure
Version or commit
0.0.32-nightly.20260806.1014 (a483337a02d4)
Environment
macOS desktop app, Codex provider, GPT-5.6 Sol. Two running threads attached to one Codex-managed Git worktree.
Logs or stack traces
# Sanitized projection/runtime evidence
thread A saved branch=feature/a worktree=<same path> runtime cwd=<same path>
thread B saved branch=feature/b worktree=<same path> runtime cwd=<same path>
git -C <same path> branch --show-current
feature/a
Workaround
Stop one thread and move it to a separate physical worktree before continuing. Verify uncommitted changes before switching the shared checkout.
Proposed focused fix
Generalize the existing branch-mismatch detection so it also covers worktree-backed threads. For worktree mismatches, warn that the checkout is shared/current and do not offer an automatic restore action that could disrupt sibling threads. Sending the next turn can use the existing metadata update path to acknowledge the live branch.
Related but not duplicate:
- #2284 handles local-checkout drift.
- #5159 follows drift only for dedicated worktrees and intentionally skips shared worktrees.
- #4356 fixed accidental worktree reuse during ordinary new-thread creation; explicit shared-worktree threads remain supported.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing resolveLocalCheckoutBranchMismatch and the existing dedicated-worktree drift handling, then follow the metadata update path used when sending the next turn. Reproduce two threads sharing one worktree with different recorded branches; done means the stale thread shows a shared-checkout mismatch warning without offering automatic restoration, and the live branch can be acknowledged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, typescript
- Domain
- desktop, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100