fix(cmux-tui): a terminal tab aimed at a pinned dock that takes no tabs opens in a new column right of it (FC-1 follow-up)

LA
4d ago
+266-33

Summary

cmux-tui now opens a terminal tab aimed at a pinned dock that takes no tabs in a new column right of the dock. Before, it refused the tab with dock-column-pinned. The rule lives in one daemon commit point, so every terminal creator gets it: the app's own creators, the CLI, MCP and scripts.

FC-1 (fuzz catalog). Home's dock is pinned in its dock move, and it takes other tabs only after a later column.update {allow_tabs: true}. A person can also close it to tabs. While allow_tabs is off, cmux-tui refused every terminal tab in it. #30676 fixes this for TabLifecycle.newTerminal (New Terminal Tab from a script, the CLI or MCP). The independent review of #30676 found that many other creators still failed in the dock: config commands (ConfigCommandRunner), the account and provider login openers, Duplicate Tab (TabHandlers:80), the page openers, Tab Group's New Tab, agent handlers and Agent Teams (raw connection.newTab).

Fix (per cmux-shared-behavior: one shared point, not a guard per caller). Every terminal tab commits through Mux::commit_resource_topology_operation (cmux-tui/crates/cmux-tui-core/src/mux/resource_topology/topology_operation.rs): the JSON-lines new-tab, tab.create_terminal, and the frontend's creation. There, a tab.create_terminal whose pane is in a pinned column that takes no tabs becomes one pane.split to the right with a viewport width, which makes a new column beside the dock:

  • Beside a lone dock, it uses LONE_DOCK_NEIGHBOR_WIDTH, the same width as a link Home opens there (the daemon's browser rule for a lone dock).
  • Beside a dock with other columns, it uses DEFAULT_VIEWPORT_PANE_WIDTH.
  • The split keeps the focus where it was unless the caller asked, as a tab made in another pane does. The tab's strip slot is dropped. Its caller-chosen terminal id, cwd, env and size go to the split, and a prelaunched host is adopted by its terminal id as before.

New helpers in pinned_columns.rs: pane_in_pinned_column_taking_no_tabs (now also used by ensure_pane_takes_tabs) and terminal_column_beside_closed_dock.

Behavior change: two wire tests asserted the old refusal for terminal tabs (pinned_column_takes_no_new_tab_until_allow_tabs_is_on, a_browser_tab_made_in_a_lone_pinned_dock_opens_in_a_new_column_beside_it). They now assert that no tab enters the dock. Browser and conversation tabs are unchanged: in a dock with a column beside it they are still refused, and from a lone dock the daemon already reroutes them.

Related: #30503 (landed), #30676, #30826.

Owner note: this touches the cmux-tui daemon area of PL-daemon (session cmux-b6; plans/cmux-next/OWNERS.md). Only the creation route changes; no request-speed path changes.

Changelog

  • Fixed: A terminal opened in Home's dock by a config command, a login, Duplicate Tab, a tab group, an agent, the CLI or MCP before Home's dock takes tabs now opens beside it instead of failing.

Testing

Regression tests (red at 34883fd748b, tests only):

  • Rust server::pinned_columns_tests::a_terminal_tab_aimed_at_a_pinned_dock_that_takes_no_tabs_opens_in_a_new_column_right_of_it. It sends new-tab into a lone dock (expects a new column right of the dock at the lone-dock width), then tab.create_terminal into the dock with a column beside it (expects a third column, right of the dock). The dock keeps only its pinned tab.
  • App HomeClosedDockTerminalCreatorsTests. It calls PaneController.newTerminalTab (the config-command and login-opener path) on Home's closed dock, and expects no failure and a real terminal in a column right of the dock.

Fleet:

Base clippy reds (not this PR's)

  • crates/cmux-tui-cloud-conversations/src/environments.rs:89 "this boolean expression can be simplified": from #30357. Its revert #30791 (ready-to-land) removes it.
  • crates/acpmux/src/prompt_provenance.rs:584 "this boolean expression can be simplified": from #30526. The panic agent's #30853 fixes it.
  • crates/cmux-tui/src/link/start_chat_cli.rs:282 "redundant clone": from #30574. The panic agent's #30853 fixes it.
  • The lead's list also named cmux-tui-core/src/mux/resource_topology/topology_operation.rs:601 as a base red (from ebce6312d8f). On this branch that line was this PR's own new code, and 4e49f3862f2 fixed it.

Observed / Not run

  • Observed: the fleet steps above and prepush-gate.py with no new violations.
  • Not run: the full cmux-tui test suite (only pinned_columns_tests), a first-5s bench, a dogfood build. I read, but did not run, the frontend new-tab creation path through cmd_frontend.rs; it commits through the same function.

No capture: the visible result is a terminal in a new column right of Home, as for a person's new terminal from Home.

perf claim: none