Skip to content

Changed-files card shows another branch's commits after a branch switch, and ignores edits the agent made in its own EnterWorktree worktree #27336

Closed as duplicate

Description

@alcosml

What happened

After a turn finished, the thread's changed-files card ("Open diff") listed edits to files the agent never touched. These were real code changes, not whitespace. It happened on two consecutive turns of the same thread. The agent confirmed that none of the listed changes were its own. Its real edits were in a separate worktree and did not appear in the card at all.

Diagnosis

Two problems combine here.

1. Checkpoints stay on the thread's original cwd after the agent moves into its own worktree.
The thread was started on the project's main checkout, so worktreePath is null. The provider is a Claude Agent SDK based instance. Mid-thread, the agent called the SDK's EnterWorktree tool, which created <repo>/.claude/worktrees/fix-review-notes, and it made all of its edits there. T3 Code was not aware of the move. The checkpoint scope's cwd remained the main checkout, so every later checkpoint, and every changed-files card, diffed the main checkout instead of the place the agent was working. The agent's actual edits never showed up. #11078 describes the same "T3 Code doesn't follow EnterWorktree" gap, but only for the sidebar branch label.

2. A branch switch in the checkpointed checkout is counted as agent-authored changes.
During the turn, the main checkout's HEAD moved from branch A (feature/alpha-…, owned by another thread's PR) to a different branch. The reflog shows checkout: moving from feature/alpha-widget to worktree-fix-review-notes. The next capture then reported 7 changed files. Those 7 files are exactly the files touched by the 2 commits in endHead..startHead, meaning the commits on the branch that was left behind.

The cause is in GitVcsDriver.checkpoints.listAuthoredPaths (apps/server/src/vcs/GitVcsDriver.ts, v0.1.5). It adds the paths from

git log --format= --diff-merges=remerge <endHead>..<startHead>

to the "authored" set. That range is intended to keep conflict fixes when HEAD moves backwards. For a plain branch switch, however, it is the whole of the departed branch's own commits, so isGitImport (apps/server/src/checkpointing/Diffs.ts) never filters those files out. CheckpointService.capture then reports them as the turn's changes. The "pulls and rebases no longer flood a turn's changed files" protection from #17161 therefore does not cover git checkout <other-branch>.

The second incident (2 unrelated project metadata files) was also a change in the main checkout outside the agent's worktree. Its exact source could not be recovered because a later git reset cleared it.

No commits touching this logic landed on main after v0.1.5, so the bug appears to be unfixed.

Steps to reproduce

Variant A (branch switch only):

  1. Clone a repo and create two branches, a and b, from main. Add a commit on a that edits x.txt. Check out a.
  2. Open the repo in T3 Code without a worktree. Start a thread and complete one turn so that a checkpoint exists.
  3. In the next turn, ask the agent to run only git checkout b and to make no edits.
  4. When the turn finishes, the changed-files card lists x.txt as modified by the agent. Expected: no card, because the change came from git.

Variant B (agent-created worktree):

  1. Start a thread on the main checkout (no T3 worktree) with a Claude-based provider.
  2. Ask the agent to use EnterWorktree and edit a file inside that worktree.
  3. The changed-files card does not show the agent's edit. Instead it shows whatever changed in the main checkout during the turn, such as another thread's work or a branch switch.

Version

0.1.5 (desktop app). The triage CLI is also 0.1.5.

Environment

Windows 11 (10.0.26300) x64, Node v26.12.1, T3 Code desktop app 0.1.5. Provider: a custom Claude Agent SDK instance (claudeAgent driver), runtime mode full-access.

Evidence

# Checkpoints for the affected thread (orchestration_v2_projection_checkpoints); scope cwd = main checkout
ordinal 1  2026-10-29T16:33:08Z  files: 0
ordinal 2  2026-10-29T16:41:09Z  files: 7   <- incident 1
ordinal 3  2026-10-29T16:57:25Z  files: 2   <- incident 2
thread payload: "worktreePath": null

# Main checkout reflog
2026-10-30 00:36:27 +0800  checkout: moving from feature/alpha-widget to worktree-fix-review-notes
2026-10-30 00:49:54 +0800  reset: moving to HEAD

# git worktree list (excerpt)
<repo>                                         1a2b3c4d5e [worktree-fix-review-notes]
<repo>/.claude/worktrees/fix-review-notes   6f7a8b9c0d [feature/beta-sync-fix]

# Files in ordinal 2 == files of the left-behind commits
$ git log --format= --name-only 1a2b3c4d5e..9e8d7c6b5a | sort -u   -> the same 7 paths as the checkpoint

# Provider event log: the agent called EnterWorktree {name: 'fix-review-notes'}
Image Image

Related issues

#22315 covers diffs colliding across chats in a shared checkout. This case is a single thread, and the trigger is a branch switch plus an agent-created worktree. #25452 covers fast-forward pulls attributed to the agent through the timestamp path. This report is about the endHead..startHead range on a branch switch. #11078 covers the sidebar not following EnterWorktree. Same root gap, but here it affects checkpoints and diffs. #17161 is the earlier fix for pulls and rebases.

Fix applied or workaround

Nothing was changed on the machine. Workaround: start isolated threads in a T3-managed worktree instead of letting the agent call EnterWorktree from the main checkout.

Filed by

Claude Code (claude-opus-5-5) via t3 triage

Activity

  1. danddanddand commented on Nov 1, 2026

    @danddanddand
    Contributor

    Another reproduction of part 2, from a common workflow: the thread started on its T3 worktree branch (created from main), and the user asked the agent to fix an existing MR, so the agent ran git checkout <mr-branch> in the thread's worktree. The MR branch was 11 commits behind that main. The changed-files card listed 402 files (+13k / −1.5k). About 388 of them were those 11 upstream commits shown in reverse: a recent E2E-test pruning came back as +13k, and recently added CI files showed as deletions. The agent had edited 14 files.

    I checked this against #27370's conditions: both checkpoints are on named branches, the branches differ, and the branch the turn left still points at the start commit. So #27370 would hide the upstream files. ✅

    It doesn't fix everything, though. 3 of the agent's 14 files had also been changed by the MR's own commits from before the turn. They're authored, so they stay in the card, but they're still compared against the starting tree from the old branch. One test file the MR had added shows as +163 / −0, when the agent changed +74 / −3. That's the "old side comes from the wrong branch" case that #23299 handles. It may be worth noting on #27370 that it fixes the noise but not the line counts for files on the new branch that the agent then edits.

  2. juliusmarminge commented on Nov 13, 2026

    @juliusmarminge
    Member

    This is the same problem as #8204, so I'm closing it in favour of that one. If it is different, say how and it will be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions