pingdotgg / pingdotgg/t3code

[Bug]: Shared-worktree threads show conflicting branches without a warning

Open
#5,496 0 comments 0 reactions 0 assignees View on GitHub

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
  1. Start thread A in a worktree on branch feature/a.
  2. Create or attach thread B to the same existing worktree.
  3. In thread B, create or switch the physical worktree to branch feature/b.
  4. Keep both threads active and switch between them in the sidebar.
  5. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.