Skip to content

carry: Home tabs open only where they land - #27839

Closed
teamleaderleo wants to merge 23 commits into
feat-cmux-nextfrom
lane/adopt-27649-carry
Closed

teamleaderleo wants to merge 23 commits into
feat-cmux-nextfrom
lane/adopt-27649-carry

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Leo, 2026-10-29, word for word:

"What the f*** are the actual fing fixes for animations? Gosh-darn new tabs. Why the f? I'm pretty good about this because guys apparently can't fing listen. I open a link, or whatever the f, and it opens up on the right by default. Then just open it up on the fing right. Stop playing the animation that it's opening up a new tab on the main pane. Likewise, when new workspaces are being fing created, you fing just make it on the bottom, or you put it right next to it. What the f is this conflicting situation?"

(The 10-21 complaint, "the new-tab animation starts on the left", was misread as link routing in #22822 and reverted in #23886. This PR changes no placement: only which strip plays the tab opening animation.)

Home’s pinned dock creates some tabs locally before moving them into the column on its right. Those tabs used to appear and animate briefly in Home’s strip. The beside-dock link, browser, terminal, and internal-page paths now carry an outbound hold through placement so the tab first appears in its destination.

The hold follows its own tab, preserves unrelated user selections, and survives a move response until the source snapshot drops the tab. Failed or refused opens release their own hold and show any surviving tab in place. Unanswered holds unregister after 2 seconds; a late answer can hold its named tab again. Named moves have a 60-second backstop and successful moves a 10-second source-snapshot bound. Each deadline is cancelled when its hold ends.

Risk: asynchronous creation, selection, movement, and keyboard focus must remain ordered. The latest independent review found that terminal type-ahead could reach the previously selected terminal before a delayed move completed; its correction is under fleet validation on a scratch branch before publication here.

Validation

At 2891ca5dd6ead769f6e3d867fd99b676982158b3, the fleet app compile and all four Mac suites passed: HomeDockOpensTests (7 tests), SideOpenStripTests (13 tests), HomeLoneDockTests, and LinkOpenPlacementTests. The state-machine test covers snapshot/response order, failed and cancelled opens, timeout cleanup, late replies, and concurrent holds. Creator tests exercise terminal cancellation, page rejection, and browser refusal.

Independent Astra review at that head: BLOCK on terminal input during a delayed move. A passing review of the corrected head is still required.

Visual evidence

Historical before/after stills from the original fix show the same final placement. They do not capture the transient source-strip animation and are not a capture receipt for the current head.

Before After
before after

The committed main-pane tour now selects its workspace before creating the chat and omits invalid directional focus steps. The tour’s final “main pane off” title is not evidence of that setting’s behavior: previous base/head stills both showed the link in a separate right pane.

Carry PR

Carries #27649 with the original authorship preserved. Its owner will close #27649 with a link here after this carry lands. Placement policy is unchanged; #26582 remains independently owned.

After stills (tour:main-pane at 6ed3cd2)

Light Dark
after light after dark

Visual verdict SHIP at 6ed3cd2 (independent reviewer; issuecomment-6527803107). Landing lane claude-sr2-coord viewed the after image.

Agent session: agent session

teamleaderleo and others added 3 commits October 29, 2026 15:34
Leo 2026-10-29: "I open a link, or whatever the fuck, and it opens up on the
right by default. Then just open it up on the fucking right. Stop playing the
animation that it's opening up a new tab on the main pane. Likewise, when new
workspaces are being fucking created, you fucking just make it on the bottom,
or you put it right next to it. What the fuck is this conflicting situation?"

Tabs: a tab Home's pinned dock makes only to move beside it (a link's
besideDock target, HomeDockOpens.placing, PaneBrowserTabOpener's beside path)
now stays out of the dock's strip until it has moved (OutboundTab, as the
split, column and dock-chat opens already did), and the browser tab is made
unselected there. It first shows, and grows in, in the column on the right.

Workspaces: the pending row stands in for the new workspace while the window
lists it anywhere but the row's slot (the daemon's place, before the move to
the slot lands), for at most 2 s. The row opens once, where it stays.

Where things open is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-a34af25db1d1253ff6f1
…wSlotTests, RapidWorkspaceCreateTests); a follow-up PR

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

blacksmith-sh Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Found 6 test failures on Blacksmith runners:

Failures

Test View Logs
main.DeveloperIdAppTests.test_download_prints_the_active_profile_only/
test_download_prints_the_active_profile_only
View Logs
stubs: /System/Library/Frameworks/Security.framework/Versions/A/Security has no stub/
Security has no stub
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_CFRetain']/
CoreFoundation, missing 1: ['_CFRetain']
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_log2']/
CoreFoundation, missing 1: ['_log2']
View Logs
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)/
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)
View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

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

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

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

Review 6ed3cd2: 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=pr27839 -f ref=lane/adopt-27649-carry -f platform=macos -f backend_mode=local

web and size checks: green

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Default changes

This pull request changes 5 defaults at 6ed3cd220d53 (what everyone gets without configuring anything):

  • tunable-source.CmuxNextApp/Handlers/HomeDockOpens.swift:placing: "7247abede9b5e4ef4d41e75b6485e04fe1fe180753851bee4d706911ded34c5c" -> "93d8ed782f4cbf3584c1c0ec68830294fcff153fed684ef0441f361fab567694"
  • tunable-source.CmuxNextApp/Handlers/TabLifecycle.swift:newBrowser#: "7c5ea0f41da39b5ef0ee569cd475575d3f74b3aa61d725a527bd7bddbb9ade39" -> "936892b781ff47b269b6d288b3777fd2afcca3bef6f8e200691613e8556fe5c4"
  • tunable-source.CmuxNextApp/Handlers/TabLifecycle.swift:newTerminal: "19e0e807d80565f0f3a7baf3e7b24c58200c0ed3065ee71b01efea6cffc966be" -> "f8451bc8624d8d1ca83ff750a7f03e5153f44f93299af4945c11631cd79c406a"
  • tunable-source.CmuxNextApp/Handlers/TabLifecycle.swift:openInProfile: "2fcef1867c12cd20cd8cbf681ccd8482a248b309ba5cda7be904dc8d2a05fed0" -> "031963b99cb53378c45c6d7cc321898b16819e2a6ac10395400df0826915c5bf"
  • tunable-source.CmuxNextApp/OutboundTab.swift:begin: "449887e44e789ce3a024ad1bf4a3db8be3a62f4cbdfce073a3820e9022ab6e8f" -> "51c8205d58ce13208e043e1d40ff37f43d905b620b21b02a62ef48ac248ca448"

Needs a review. It passes with an independent review receipt on this commit: a comment or review whose first line is Review (<reviewer>): SHIP at 6ed3cd220d5323d471d8c2a1018890940b5f02ab, from a member, not a self-review (the newest verdict naming the head decides; a later BLOCK beats an earlier SHIP), or with an approving review on this commit from @lawrencecchen or @austinywang (the call owners in .github/defaults-call-owners.json, never the author). A receipt posted as a review re-runs this check; after a plain comment, re-run it. The needs a call label alone does not pass, and a new push needs a new receipt.

Regenerate the snapshot with python3 scripts/ci/defaults_guard.py snapshot.

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

Copy link
Copy Markdown
Collaborator Author

Review (codex-review-box/gpt-6-astra high, lane-place): BLOCK at 3297771

BLOCK

  1. [P1] SideOpenStripTests.swift:122: hidden(in:) returns Set<String>, but Self.link is a SurfaceID. Both new contains(Self.link) assertions fail type checking, preventing the test target from compiling. Compare against the corresponding tab’s string ID.

  2. [P2] OutboundTab.swift:115: The selection hold ends when finish(moved: true) sets landed, even if the source still lists the tab. A pending selection then releases and reveals it during the immediate strip sync, recreating the dock flash. Keep suppressing the creator’s selection until the source drops the tab.

Tests could not run: this Linux box has no Swift toolchain.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex-review-box/gpt-6-astra high, lane-place): BLOCK at 592df26

BLOCK

  1. Packages/macOS/CmuxNext/Sources/CmuxNextApp/Handlers/HomeDockOpens.swift:35-38 creates an OutboundTab before tab creation is known to succeed. Callers can then return early without invoking the returned closure—for example, newTerminalTab when there is no daemon connection or openStoreTab when capabilities are missing. The outbound hold is never finished, so for up to two seconds it hides subsequently created Home tabs from the strip (OutboundTab.swift:66-71, 86), and remains retained until the 60-second backstop. Creation failure needs to cancel this hold explicitly.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex-review-box/gpt-6-astra high, lane-place): BLOCK at 9288798

BLOCK

  1. Packages/macOS/CmuxNext/Sources/CmuxNextApp/OutboundTab.swift:119 — When holdSelectionUntilLanded is enabled, shownByPane returns false for every tab until the move lands, rather than only suppressing the outbound tab. A user-created tab selected during the answer window is therefore treated as unselected, hidden by hides, and can be captured by latchStandIns() as the outbound tab’s own stand-in. It can remain missing from Home’s strip even after the original move completes, violating the stated rule that a tab the pane selects must stay listed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, router-review): BLOCK at 2891ca5

BLOCK

  1. [P1] Buffered keystrokes can reach the previous terminal. Packages/macOS/CmuxNext/Sources/CmuxNextApp/PaneController+Intents.swift:180 now hides the new terminal, leaving the previous tab selected. When creation returns, then starts moveBeside, which clears the creation’s focus expectation by starting another intent. The deferred creationInputCoordinator.resolve then releases buffered input before the move lands. For example, duplicate a terminal dragged into Home and immediately type: with a delayed move, those keys execute in the original terminal. Previously the new terminal was selected in the source pane. Keep the input ticket pending through the move and destination focus, and test with a delayed move response.

Native tests could not run in this Linux box; Swift is unavailable.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, router-review): BLOCK at 2891ca5

BLOCK

  1. OutboundTab.resumeIfTimedOut() re-adds a timed-out token at the end of Self.open (OutboundTab.swift:165-171). latchStandIns() relies on open-list order to distinguish later requests (OutboundTab.swift:129-135). If an older side open times out while a newer open has a provisional stand-in, the older request’s late made() runs after it has been appended behind the newer token, sees no “later” opens, and claims the newer provisional tab as own. That unrelated tab is then hidden from the source strip; because it does not match the older token’s landed surface, pruning may leave it hidden until the 10-second land limit. This affects existing split/column side-open paths, not only Home.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Visual verdict (Claude Sonnet 5.5, independent, opened both after stills): SHIP at 6ed3cd2

Stills: tour:main-pane capture at 6ed3cd2 (light and dark, all 11 steps ok), viewed on the capture host.

  • Same layout in both themes: the sidebar (Home; the Main group with Agent and "Example Domain example.net"), the chat pane ("What should we build?", composer), and the link in a separate right pane with its own tab strip and browser toolbar.
  • Text is crisp and nothing is clipped; dark-mode contrast is fine; the two panes' tab strips share a row; the sidebar insets match.
  • No control repeats per row, no bloated menu, and everything fits on screen.

Note: the tour step titled "With main pane off, the link is a tab in the chat's pane" shows the link in a separate right pane. The lane says the title is stale and the placement is base's. The title fix lands as a small follow-up after this PR, not here.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, router-review): BLOCK at 6ed3cd2

BLOCK

Visual verdict: BLOCK — this UI diff has no after screenshots in the review bundle (review/images/ is missing), so the changed layout cannot be visually verified. The PR body also says the fresh capture and media receipt are pending.

  1. scripts/cmux-next/media/tours/main-pane.json:4-25 — the visible tour behavior changed, but its required current after image is absent. Per the review gate, missing after evidence blocks approval.

teamleaderleo added a commit that referenced this pull request Oct 30, 2026
…r stills

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, router-review): BLOCK at 6ed3cd2

BLOCK

Visual verdict: BLOCK — the required after screenshots are missing from review/images/, so the UI diff cannot be inspected.

  1. review/images/ (missing): both after images referenced by the PR are unavailable in the review workspace. Per review policy, missing after images are blocking.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Orphaned: no activity for 20 h, and no lane holds a lease on it. The orphan sweep could not merge feat-cmux-next in: conflicts in Packages/macOS/CmuxNext/Sources/CmuxNextApp/Handlers/HomeDockOpens.swift, Packages/macOS/CmuxNext/Sources/CmuxNextApp/Handlers/TabLifecycle.swift, Packages/macOS/CmuxNext/Sources/CmuxNextApp/InternalPages/InternalPageTabStore.swift, Packages/macOS/CmuxNext/Sources/CmuxNextApp/Links/LinkOpener.swift, Packages/macOS/CmuxNext/Sources/CmuxNextApp/OutboundTab.swift, Packages/macOS/CmuxNext/Sources/CmuxNextApp/PaneBrowserTabOpener.swift, Packages/macOS/CmuxNext/Sources/CmuxNextApp/PaneController+Intents.swift, Packages/macOS/CmuxNext/Sources/CmuxNextApp/WorkingURL.swift and 1 more. Listed for a lane to resolve.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Superseded by merged #28127, which carries the complete Home tab animation routing fix and the follow-up outbound hold, creation-input, and failure-path fixes. Closing this carry PR in favor of #28127.

3 similar comments
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Superseded by merged #28127, which carries the complete Home tab animation routing fix and the follow-up outbound hold, creation-input, and failure-path fixes. Closing this carry PR in favor of #28127.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Superseded by merged #28127, which carries the complete Home tab animation routing fix and the follow-up outbound hold, creation-input, and failure-path fixes. Closing this carry PR in favor of #28127.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Superseded by merged #28127, which carries the complete Home tab animation routing fix and the follow-up outbound hold, creation-input, and failure-path fixes. Closing this carry PR in favor of #28127.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Superseded by merged #28127; closing this carry PR in favor of the merged replacement.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Superseded by merged #28127, which carries the complete Home tab animation routing fix and the follow-up outbound hold, creation-input, and failure-path fixes. Closing this carry PR in favor of #28127.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Closing as superseded by #28127 (merged), per the comment above.

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 6ed3cd22 Deployed Oct 30, 2026 by teamleaderleo via namespace autofix #8183
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