Show the docked chat and its fresh tab in the click's turn
Leo: "it's so slow to open and close idk if there's some sort of threading issue but it's nigh instant for claude and codex so we nede to be at least as fast"
leo-named-fix
What
A new tab opened from a lone chat docks the chat into a new left column and leaves a fresh tab in its pane (ChatColumnPlacement.route .dockChat ā TabMoves.toNewDockColumn, move-tab-to-column {dock, respawn}). Until now nothing changed on screen until the daemon answered. With this change, on a daemon that takes the column pane's id (tab-column-client-pane-v1, #33184), the change shows in the click's turn:
- The chat moves into a stand-in dock pane under a client-minted pane id. The pane leads the screen's columns, as
commit_tab_dragputs a left dock first. - The chat's old pane shows the fresh tab's stand-in (a terminal under the host id sent with the respawn, or the browser page). It shows only until the daemon's fresh tab arrives.
- When the daemon's pane with that id arrives, it takes the stand-in's
PaneModelover in place (confirmedPane). The intent settles once the daemon's layout places it, as a split does (cx-ry0y). - If the daemon refuses, everything is undone exactly.
This is one new overlay, ProvisionalDock, built beside ProvisionalSplit. It reuses ProvisionalPane, ProvisionalTab, provisionalPanes and awaitsRecords; there is no second mechanism. DockColumnCommand (CmuxNextDaemonService) holds the send, so CmuxNextApp shrinks (app_lines -5). Other cases keep the reply path: a right or band dock, a screen that already has a dock on that edge, a zoomed screen, an older daemon, or a move with no respawn.
Not touched: LinkOpener, PaneBrowserTabOpener, MainPaneLayout, and PaneController's strip-refresh order.
Tests
ProvisionalDockTests (CmuxNextDaemonTests):
- The dock and the fresh tab's stand-in show in the intent's turn, and a refusal restores the pane exactly.
- The daemon's
pane-addedtakes the same model over while the dock places it, and the daemon's layout settles the intent with the fresh tab in place.
Fleet runs are listed below.
Performance
| metric | before | after | delta | harness |
|---|---|---|---|---|
| click to docked chat shown | waits for the daemon's reply and events | the click's turn (store intent) | pending bench | see comment |
risk:normal
Changelog
- Changed: Opening a new tab from a lone chat now docks the chat and shows the new tab right away.
Agent session: agent session
š¤ Generated with Claude Code
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith Ā· Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Shows a chat docked from a new tab in the click's turn instead of after the daemon's reply, and adds the protocol that makes it possible.
move-tab-to-columntakes an optionalpane_id(tab-column-client-pane-v1): the new column's pane carries the caller-minted id, refused withpane_id_existswhen a live or deleted resource has it.DockColumnCommandandProvisionalDockmove the chat into a stand-in left dock pane under that id and show a fresh terminal's stand-in in the old pane, until the daemon's layout places the real pane.DebugInstantCreateBenchand the bench script gain adock_respawncommand measuring the click to the docked chat's first visible frame.- Right and band docks, screens with an existing edge dock, zoomed screens, older daemons, fresh browser tabs, and moves without respawn keep the reply path; a refusal or daemon rejection undoes the overlay exactly.