Skip to content

feat(workspace): reuse an open project tab on New Tab and add Merge Project Tabs #913

Closed

Description

@Juliusolsson05

Motivation

A workspace ends up with several project tabs for the same folder. Observed on 2026-09-11: three agent-code tabs created on Sept 3, 7 and 10, each holding a different generation of agents, with worktree agents spread across them. The Dispatch index, the row project filters and the bulk modals then show three "agent-code" projects for one repository, and any "every agent in this project" action has to be repeated per tab.

The cause is that the New Tab flow never dedupes: ⌘T plus the path picker creates a fresh tab every time, even for a folder that is already open. The operator control path already has the right rule (projects.open reuses an existing tab with that exact directory unless createDuplicate is explicit); the keyboard path predates that decision. Window adoption appends a closed window's tabs without root dedupe, so it can also leave duplicates behind.

Intended behavior

  1. Reuse on open. When the path picker's folder is already held by an open tab, the picker says so and its primary action becomes "go to tab" (activate it); "new tab anyway" stays one click away for the cases where a second tab of one repository is wanted on purpose. Resume flows are unchanged in this issue.
  2. Merge Project Tabs command. Choose a target tab and the tabs to fold into it (defaulting to every tab that shares a working directory with the target). Everything moves under the target without touching any process: source grid panes and detached agents become Dispatch agents of the target, buried records and Dispatch row project filters are re-pointed, tiled-tab and spotlight/reader references to the removed tabs are cleared, then the emptied tabs are removed. A confirmation lists what moves. No session is killed, reloaded or re-spawned.

Acceptance criteria

  • With a tab already holding a session in the chosen folder, the picker offers "go to tab" and "new tab anyway"; the first activates without spawning, the second spawns a new tab as today. A folder not held by any tab behaves exactly as today.
  • The operator projects.open and the picker share one "tabs holding this directory" rule.
  • Merging N tabs into a target leaves every session owned (same owned-session set before and after), removes the sources, re-points detached, buried and row-filter references, keeps the target's grid untouched, and never calls kill/spawn/reload.
  • Merging refuses a target that is among the sources or an unknown tab.
  • Deterministic unit tests for the merge planner and the directory rule; the command catalog baseline updated; tsc clean on both projects.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions