Skip to content

[Bug]: “New worktree” default is ignored and new threads silently reuse the active worktree #4356

Description

@Xanacas

Before submitting

  • I searched existing issues and found related reports, but this issue identifies the inconsistent thread-creation paths and the resulting safety problem.
  • I included enough detail to reproduce and investigate the bug.

Area

apps/web, thread creation, worktree isolation, checkpoint diffs

Summary

The New threads setting explicitly asks users to choose the default workspace mode for newly created draft threads. Its available options are currently:

  • Local
  • New worktree

When New worktree is selected, not every New Thread entry point honors that setting. Several contextual entry points silently copy the active thread's existing branch, worktreePath, and environment mode into the new draft.

This is not merely a feature request or a proposed behavior change. It is a bug: the UI explicitly says New worktree, but some New Thread actions create a second thread in the current worktree instead.

Steps to reproduce

  1. Open Settings → New threads.
  2. Select New worktree as the default workspace mode.
  3. Start a worktree-backed thread and leave it running.
  4. Create another thread using a contextual/global New Thread entry point, such as the keyboard shortcut, command palette action in the active project, or the Sidebar V2 New Thread button in a single-project setup.
  5. Send the first message in the new thread.
  6. Inspect the two thread records or provider working directories.

Expected behavior

Every ordinary New Thread entry point should honor the configured New worktree default and create a fresh isolated worktree.

The new draft should not inherit an existing worktreePath, and the first-turn bootstrap should execute prepareWorktree.

Actual behavior

Depending on the New Thread entry point, the new draft inherits the active thread's existing worktreePath.

Once that path is present, the first-turn bootstrap assumes the worktree already exists and does not invoke the Git worktree creator. Both agents can then run concurrently in the exact same directory.

The behavior is inconsistent across entry points:

  • some project-specific creation paths honor New worktree and create an isolated worktree;
  • the global New Thread command/shortcut can reuse the active worktree;
  • the command palette can reuse the active worktree when creating a thread in the current project;
  • the Sidebar V2 New Thread action can reuse the active worktree in a single-project setup.

All of these are presented as New thread, so the user is not informed that one of them may create another writer in an existing workspace.

Concrete failure mode

In one observed case:

  1. A migration thread was running in a T3-managed worktree.
  2. A second, read-only investigation thread was created from the active context while New worktree was the configured default.
  3. Both thread records contained the exact same worktreePath from their initial thread.created events.
  4. The migration thread ran git merge origin/main while the investigation turn was active.
  5. The investigation thread's checkpoint UI attributed the resulting 112-file diff (+10,163 / -802) to the read-only assistant response.

The investigation agent itself had only executed read commands (rg, sed, git log, and git status).

This happens because turn checkpoints capture the entire worktree state, not writes attributable to one agent process. Shared worktrees therefore also make checkpoint restore/revert potentially destructive to another active thread's work.

Current implementation behavior

On current main (1c9a6de26e when verified):

  • apps/web/src/lib/chatThreadActions.ts builds contextual thread options by copying the active thread's worktreePath.
  • apps/web/src/hooks/useHandleNewThread.ts gives explicitly passed contextual options precedence over defaultThreadEnvMode.
  • apps/web/src/components/ChatView.tsx only creates bootstrap.prepareWorktree when the draft has no existing worktreePath.

The Git worktree creator is not failing or selecting a duplicate path. It is never invoked because the new thread has already inherited an existing path.

Proposed fix

All ordinary New Thread entry points must consistently apply the configured default workspace mode.

When the setting is New worktree:

  • do not propagate the active thread's worktreePath;
  • create a fresh T3-managed worktree on first send;
  • make this consistent across global buttons, project buttons, shortcuts, command palette, Sidebar V1, and Sidebar V2.

Reusing an existing worktree should be an explicit user decision. It could be exposed through actions such as:

  • Command Palette: New thread in current worktree;
  • right-click an existing thread: New thread in this worktree.

If T3 wants worktree reuse to be configurable as the normal default, Settings could add a third clearly named option alongside the existing choices:

  • Local
  • New worktree
  • Current/existing worktree

That would preserve the useful ability to share a workspace while making it explicit and keeping New worktree semantically correct.

If another thread is currently writing in the selected existing worktree, T3 should ideally warn the user or prevent concurrent writers.

Why this matters

Worktrees are the isolation boundary that makes parallel agent execution safe. Silently sharing them can cause:

  • one thread's changes to appear under another thread's response;
  • misleading changed-file counts and turn diffs;
  • mixed or conflicting edits;
  • branch movement caused by another agent during a turn;
  • unsafe checkpoint reverts that overwrite or clean another thread's work.

The risk is especially high because the current Settings UI explicitly promises New worktree, while the affected creation paths silently do something else.

Acceptance criteria

  • Every ordinary New Thread entry point honors defaultThreadEnvMode.
  • With New worktree selected, new drafts never inherit the active thread's worktreePath.
  • Sending the first message creates a fresh T3-managed worktree for Git-backed projects.
  • Behavior is consistent across shortcuts, command palette, Sidebar V1, and Sidebar V2.
  • Reusing a worktree requires an explicitly named action or a separately configured Current/existing worktree default.
  • The reuse action clearly identifies the target worktree/thread.
  • T3 warns about or guards against multiple concurrent writers in one worktree.
  • Tests cover all New Thread entry points, isolated creation, and explicit worktree reuse.

Related issues

Workaround

Create new threads only through an entry point known to honor the New worktree setting, then verify that the draft says New worktree rather than Worktree before sending the first message.

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