Skip to content

cmux NEXT: new tabs from an agent chat open on the right, after that pane's selected tab (fixes #23105 regression) - #23882

Closed
teamleaderleo wants to merge 6 commits into
feat-cmux-nextfrom
fix/new-tab-in-pane
Closed

teamleaderleo wants to merge 6 commits into
feat-cmux-nextfrom
fix/new-tab-in-pane

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Leo on nightly 3a63d6d (2026-10-21): "THIS ADDING TABS: IT SWITCHES AROUND AND DOESN'T REALLY GET ADDED". Lucas: tabs "disappear inside of chats". Then Leo: "DEFAULT ON THE RIGHT ... EVERYBODY IS SAYING OPEN DEFAULT ON THE RIGHT".

Regressing PR: #23105 (2a7eec5, main pane layout). Since then chat docks are common. Cmd-T and + in a docked chat's pane went to the strip pane on its right, but NewTabSlot still anchored the tab's slot on the chat pane's selected tab. So the placement was held in the chat's pane, never found the tab there, and the tab landed at the end of the strip pane, out of view.

Rules:

  • Cmd-T, + and Option-+ (newTab.ofKind) in an agent chat's pane follow layout.linkPlacement (read through services.linkOpener.placement()):
    • split-right / new-column (the default): the tab opens on the right, in the strip pane ChatColumnPlacement.route picks (the most recent one). It lands right after that pane's selected tab, selected and focused, and no other tab moves in either pane. From a lone chat, a terminal or browser tab still docks the chat as on base. A New Tab page opens in a new split on the right and the chat stays where it is.
    • same-pane: the tab stays in the chat's pane, right after its selected tab, selected.
  • Any other pane (terminal, browser, page) keeps its new tab, as before.
  • Home's pinned dock (no +) still opens beside it.
  • Scripts, CLI and MCP, and the other ChatColumnPlacement.route callers (newSurface, openBrowser, link opens), are unchanged.

Change:

  • ChatColumnPlacement.newTabStays(in:services:) is the one seam: it decides whether a person's new tab stays in its pane. TabLifecycle.newTabOfPaneKind computes it once and passes it to newTerminal and newBrowser as staysInPane, and uses it for pages too.
  • A tab routed to another pane takes that pane's slot (NewTabSlot.rebased).

Tests: NewTabStaysInItsPaneTests (daemon-backed, 5 tests) builds an agent chat dock left of a strip pane, with focus in the dock.

  • With the default, Cmd-T and Option-+ each add exactly one tab to the strip pane, right after its selected tab. The tab is selected, focus is in the strip, and the dock is unchanged.
  • With same-pane, both add the tab to the dock right after its selected tab, and the strip is unchanged.
  • Cmd-T in a terminal pane keeps the tab there, right after the terminal.

Fleet: the app compile check and the suite (5/5) passed at the head.

Known gap, not a regression: after a lone chat's first New Tab page splits right, the chat is not docked. A later Cmd-T in the chat then stays in its pane, as on base.

No capture: the before/after recordings from the fleet repro show a private host; the tests pin the behaviour.

Leo-ask: ask-504ac4c80e

Agent session: cosmic-gray

🤖 Generated with Claude Code

Leo 2026-10-21 on nightly: "THIS ADDING TABS: IT SWITCHES AROUND AND DOESN'T REALLY GET
ADDED". Since #23105 chats dock, and ChatColumnPlacement sent a docked chat's Cmd-T and +
to the strip column on its right, and moved a lone chat into a new left dock, so the new
tab never showed where it was added. A pane whose strip takes new tabs now keeps its new
tab (right after the selected one, selected); only Home's pinned dock, which takes none,
still opens the page beside it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d2d-622e-7433-aed6-f3c248542f5d&host=cosmic-gray
@teamleaderleo teamleaderleo added the risk:low Risk tier (docs/ci/risk-tiers.md) label Oct 22, 2026
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 270ea5b: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr23882 -f ref=fix/new-tab-in-pane -f platform=macos -f backend_mode=local

red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 44fc3d3 to compare; do not merge until green; see lane-rules

@github-actions github-actions Bot added risk:normal Risk tier (docs/ci/risk-tiers.md) and removed risk:low Risk tier (docs/ci/risk-tiers.md) labels Oct 22, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Found 11 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp_ho69oxj/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpgkbvdtjh/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs
test_base_passes (main.NoticesPairTests.test_base_passes)/
test_base_passes (main.NoticesPairTests.test_base_passes)
View Logs
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules)/
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules)
View Logs
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules) (job='web-bundles')/
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules) (job='web-bundles')
View Logs

...and 1 more test failures. View all on Blacksmith

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next crash-class rules / cmux-next crash-class rules is red on 9 of 9 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-ej0lx created for this PR by the cmux coordinator.

newTabOfPaneKind computes once whether a person's new tab stays in the
pane it was asked from (ChatColumnPlacement.newTabStays) and passes it to
newTerminal and newBrowser as staysInPane, so New <Kind> Tab (Option-click
on the +), and the terminal fallback in a build without the New Tab page,
no longer route terminal and browser tabs to the strip column beside a
chat dock. Other callers of ChatColumnPlacement.route are unchanged.

Adds a test for Option-click + on a browser tab in the dock, and skips
both tests in a build without the New Tab page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d2d-622e-7433-aed6-f3c248542f5d&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next crash-class rules / cmux-next crash-class rules is red on 11 of 11 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent subagent): SHIP at 174c55f

  • Fleet compile check (cmux-ci compile-check --app, job df38f02edfa234d12d7b7012): passed.
  • Fleet suite NewTabStaysInItsPaneTests (step 2c23f220c22e409a7e0ff7a2 on aws-m4pro-4): 2/2 passed (cmdTInADockedChatsPaneAddsOneTabAfterTheSelectedOne, optionPlusOnABrowserTabInADockAddsOneTabAfterTheSelectedOne).
  • Review, correctness first: every path a person uses to add a tab in a pane whose strip takes tabs keeps the tab there: Cmd-T (page, or terminal with tabs.terminalFirst), +, Option-+ terminal and browser tabs, and the no-New-Tab-page terminal fallback. Home's pinned dock still routes. Script, CLI and MCP paths are unchanged, and so are other callers of ChatColumnPlacement.route (newSurface, openBrowser, link opens). Both tests fail on base.
  • Non-blocking notes: ChatDockRules still refuses dragging tools into a chat dock and its comment says the dock holds only chats, which now disagrees with new tabs landing there. With tabs.terminalFirst, a lone chat's Cmd-T opens a terminal tab beside the chat instead of docking it.

The one seam for the coming "Open new tabs and links" setting (#23886) is ChatColumnPlacement.newTabStays(in:).

…e's slot

Leo 2026-10-21: "DEFAULT ON THE RIGHT". Cmd-T, + and Option-+ in an agent
chat's pane follow layout.linkPlacement through one seam,
ChatColumnPlacement.newTabStays(in:services:): split-right and new-column
(the default) open the tab on the right, same-pane keeps it in the chat's
pane. Every other pane keeps its new tab.

What Leo hit ("IT SWITCHES AROUND AND DOESN'T REALLY GET ADDED"): a tab
routed from the chat dock to the strip pane kept the chat pane's slot, so
it was held in the chat's pane and then landed at the strip's end. It now
takes the strip pane's slot (NewTabSlot.rebased): right after that pane's
selected tab, selected and focused. A lone chat's New Tab page opens in a
new split on its right; the chat stays.

Tests: Cmd-T and Option-+ from a docked chat land after the strip's
selected tab with focus there and the dock unchanged; with same-pane they
stay in the dock; Cmd-T in a terminal pane stays in it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d2d-622e-7433-aed6-f3c248542f5d&host=cosmic-gray
The on-the-right tests focus the dock before the press, so the strip's
focus afterwards proves the new tab moved it. The terminal-pane test
opens a terminal tab (the app's first tab here is a conversation) and
checks the new tab lands right after it, before a page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d2d-622e-7433-aed6-f3c248542f5d&host=cosmic-gray
@teamleaderleo teamleaderleo changed the title cmux NEXT: Cmd-T and + add the tab to the pane they were pressed in (fixes #23105 regression) cmux NEXT: new tabs from an agent chat open on the right, after that pane's selected tab (fixes #23105 regression) Oct 22, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent subagent): SHIP at 0c121c8

  • Fleet compile check (cmux-ci compile-check --app, job 2fd34f4d05a62b2b4c44a0ac): passed.
  • Fleet suite NewTabStaysInItsPaneTests: 5/5 passed at this head.
    • Cmd-T and Option-+ from a docked chat open on the right, after the strip's selected tab, with focus moved there from the dock.
    • With same-pane, both stay in the dock.
    • Cmd-T in a terminal pane stays in it.
  • Review, correctness first:
    • Docked chat: every path for a person checks out (terminal, browser, page and agent kinds) under both placements.
    • Lone chat: terminal and browser tabs dock the chat as on base. A page splits right, and the chat stays.
    • Other panes: Home's pinned dock still opens beside it. Non-chat panes keep their tab.
    • Unchanged callers: scripts, CLI, MCP and the other ChatColumnPlacement.route callers behave as on base.
    • Tests: the on-the-right tests fail on base, where the tab lands at the strip's end.
  • Non-blocking follow-up: after a lone chat's first page splits right, the chat is not docked. A later Cmd-T in the chat then stays in its pane, as on base.

This supersedes the earlier receipt at 174c55f (the spec changed to "on the right by default").

…tab-in-pane

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextApp/Handlers/TabLifecycle.swift
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Orphaned: no activity for 16 h, and no lane holds a lease on it. Adopted by the orphan sweep: merged feat-cmux-next in at 270ea5b. A later pass queues it for the merge hub if it is reviewed, small and red only on base reds.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next / cmux-next checks (god files, concurrency, crash safety, l10n) › Checks job structure is red on 20 of 20 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by nx-chat on big-red · took over from session 01a15d2d

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Stale (13d, conflicts); rebuild fresh from feat-cmux-next if still wanted

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 270ea5be Deployed Oct 22, 2026 by teamleaderleo via namespace autofix #1500
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant