Skip to content

cmux NEXT: a lone chat's link opens only in the pane on the right, never first in the main pane - #32871

Merged
cmux-bot[bot] merged 3 commits into
feat-cmux-nextfrom
lane/dock-chat-handoff
Nov 3, 2026
Merged

cmux-bot[bot] merged 3 commits into
feat-cmux-nextfrom
lane/dock-chat-handoff

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

leo-named-fix

Leo (2026-11-03): "and also the browser/tab opening animation still plays on the main pane before going". Earlier (2026-10-21): "the opening up a new link from a given main pane without any other splits it plays the opening animation on the main window...".

What was wrong

From a lone agent chat, a link's tab is made unselected in the chat's pane and kept out of its strip (OutboundTab) while the chat docks left (MainPaneLayout.dockChat); the pane, holding the tab, then slides in from the right as the content handoff. PaneController.observe applies the workspace layout before the strip, so a tab that moved away leaves the strip in the same turn its new pane shows. Two other strip paths did not: syncStripFromStore (called by OutboundTab.finish when dockChat's wait for the moved chat hears the store, which can come before the pane's own observation) and tabItemChanged (a loading page's title/favicon change). Either could list and select the new tab while the layout still had the pane full width as the main pane, so its open played there first, and only the layout apply after it moved the pane to the right.

Fix

PaneController.layoutFirst(): when the record's tabs changed since the strip took them (stripIsStale), those two paths apply the workspace layout first (no-op when unchanged), then skip the strip apply if that apply tore the pane down. Nested calls from WorkspaceContentController.apply -> syncStaleStrips end at once (the tree is unchanged).

plans/cmux-next/arch-exceptions/dock-chat-strip-order.json: app_lines +8 (the helper and its doc comment), with the review receipt.

Prior art kept: #24577 (OutboundTab), #28127, #23969 / revert #24292 (the hold and its edge cases are untouched), the handoff motion (ChatDockLinkSplitMotionTests).

Risk

Normal. Touches when a strip sync applies the layout; the only new work is one LayoutMapping.map on a stale strip sync. No change to OutboundTab's hold rules or to the layout motion.

Verification

Red/green: swift test --filter DockChatStripOrderTests (commit a75a88e is the test alone; the fix follows). Fleet results posted as a comment below.

Observed / Not run

  • Observed: a correctness review (subagent) read the diff and gave SHIP at 7abad93.
  • Not run here: a DEV build run of the flow. The root cause comes from reading the code (observation order), not from a frame capture.

Changelog

  • Fixed: a link opened from a lone agent chat no longer plays its tab-open animation in the main pane before it moves to the right pane.

Agent session: agent session

🤖 Generated with Claude Code


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


Summary by cubic

A link opened from a lone agent chat now appears in the right pane only after the chat docks, instead of briefly opening in the full-width main pane.

  • Strip syncs apply the workspace layout first when the pane’s tabs have changed.
  • Adds a regression test for the dock-and-link handoff.

Written for commit 3ff78da. Summary will update on new commits.

View guided diff Turn on auto-fix

teamleaderleo and others added 3 commits November 3, 2026 02:16
…the layout has the dock (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ed9226b71907d8aaa0b6
…ver first in the main pane

A strip sync from outside the pane's observation (the dock's wait for the
moved chat ending the OutboundTab hold, a tab item change) applied the
store's tabs before the workspace applied the store's layout, so the link's
tab showed and opened in the full-width main pane for that turn, before the
layout moved the pane to the right. Every strip sync now applies the
workspace layout first when the pane's tabs changed (StripAfterLayout),
as the pane's own observation already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ed9226b71907d8aaa0b6
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

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

Review 3ff78da: 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=pr32871 -f ref=lane/dock-chat-handoff -f platform=macos -f backend_mode=local

Shipped in:

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 3, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at 3ff78da

Reviewer: codex gpt-6.1-sol xhigh, fast tier.

Follow-ups: 1. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at 3ff78da
Visual verdict: no images; Leo tries the build

No correctness defects found by inspection. Native tests couldn’t run here: Linux, no Swift toolchain.

  1. [P2] [follow-up] Packages/macOS/CmuxNext/Sources/CmuxNextApp/PaneController.swift:433 — Missing native capture leaves the animation visually unverified; check the lone-chat link flow in a DEV build.

Follow-ups:

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, sweep, via the review router; full diff from merge base 79b76ff to this head): SHIP at 3ff78da

No P1/P2 findings.

@cmux-bot cmux-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmux-bot approves 3ff78da: an independent review passed this exact head (router-review receipt by teamleaderleo). A push needs a new review; a later BLOCK at this head dismisses this approval.

@cmux-bot
cmux-bot Bot merged commit 0a5822d into feat-cmux-next Nov 3, 2026
165 of 177 checks passed
@cmux-bot
cmux-bot Bot deleted the lane/dock-chat-handoff branch November 3, 2026 02:46
lawrencecchen added a commit that referenced this pull request Nov 3, 2026
…packages (tip arch red after 79b76ff) (#32928)

* base red: move the App lines of #28068, #32722 and #32851 into their packages (tip arch red after 79b76ff)

The tip arch ratchet counts CmuxNextApp +51 over the last green arch tip
c5d7e8d. #32858 takes #32752's +27; #32871's +8 has its exception.
This takes the other three culprits, each by a move of its own code path
with no change in behavior:

- #32851 (+1): the kind of a tab that opens beside a chat (browser,
  local terminal, or document for the Changes page) is
  RightColumnPlacement.Kind(opening:document:) in CmuxNextAgentPane.
- #32722 (+5): a Cloud machine's workspace row (id, name, resource_id)
  is WorkspaceModel.cloudMachineWorkspaceRow in CmuxNextControl.
- #28068 (+15): the half-created workspace close that its create path
  runs through (WorkspaceCreation.withTerminal and its logger) is
  EmptyWorkspaceRepair.withTerminal in CmuxNextWorkspaceRepair, next to
  populating(_:_:), which every caller already wraps it in. Same log
  subsystem and category.

* cloud.machines: map workspace rows with a closure (no key path to a main-actor property)

* cloud.machines workspace row: package access with package imports (the compile refused public over internal imports)
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Fleet verification at head 3ff78da2404ca68c63abc80df36a033399af0016:

  • Compile check (CmuxNext): passed (274 s).
  • Red at the test-only commit a75a88efda69dc605859543fa8aa503c585db662: DockChatStripOrderTests fails with DockChatStripOrderTests.swift:80: Expectation failed: (panes() → 1) == 2. The link's tab showed in the main pane's strip while the layout still had one pane (run).
  • Green at the head: DockChatStripOrderTests 1/1, SideOpenStripTests 11/11, ChatDockLinkSplitMotionTests 11/11 and MainPaneLayoutTests 6/6 all pass in the Swift Testing pass (run).

Every suite row also says failed (exit 1) at the head. That exit comes from the XCTest pass, which runs zero tests here: its runner (xctest -XCTest '') aborts with signal 6 about 9 minutes in, after CoreData's AddressBook XPC store errors in the runner's session. It aborts the same way at the base 79b76ff1ed327c8028ee1b2c0784d77b6a57bc04 on the same runner class. There ChatDockLinkSplitMotionTests 11/11 and MainPaneLayoutTests 6/6 pass in the Swift Testing pass, and each row still says failed (exit 1) (base run). On a mini, the same base suite ran with no abort and passed. So the crash depends on the runner host's session and is already on base. This diff does not cause it, and it touches nothing there.

Review: router-review (gpt-6.1-sol xhigh) SHIP at the head, with one follow-up: try the lone-chat link flow in a DEV build.

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 3ff78da2 Deployed Nov 3, 2026 by teamleaderleo via namespace autofix #12848
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