Repository navigation
fix(next): a stand-in tab or pane closes on the click, never "still opening" - #34367
Conversation
…pening" Closing the dock's fresh-tab stand-in before the daemon confirms now takes it out at once while the chat still docks; the daemon's fresh tab is hidden when it lands and closed, never shown (#33829). Close Pane on a stand-in pane (a dock's, Cmd-N's first pane) waits for the daemon's pane off the key's turn, as a create does, instead of being refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-ed9226b71907d8aaa0b6
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Not verified: macOS jobs did not run: compile and app tests were skipped on CI passes on Written by red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 842ce34 to compare; do not merge until green; see lane-rules Shipped in:
|
|
Found 7 test failures on Blacksmith runners: Failures
|
|
Review (codex gpt-6-astra high, router-review): BLOCK at ee6f658 BLOCK at ee6f658 Visual verdict: no images; Leo tries the build
|
…in the click's turn The close's intent hides the stand-in pane, and the daemon's pane that takes it over, until the daemon's records drop it; a refused close brings it back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-ed9226b71907d8aaa0b6
…ck pane comes first Review of #34367 (P1): the daemon's dock pane and layout can settle the move before the respawned tab arrives. The intent now waits for that tab (up to a snapshot), so a late fresh tab is still hidden and closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-ed9226b71907d8aaa0b6
|
Review (codex, router-review): SHIP at 8cc685e Reviewer: codex gpt-6.1-sol xhigh, fast tier. Follow-ups: 2. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward. SHIP at 8cc685e
Swift tests could not run because Swift is unavailable in this box. Follow-ups:
|
Review of #34367 (P1): the close's overlay took the daemon's pane out of the index, so daemonTarget never saw the adoption and threw once the dock settled; the close was refused and the pane came back. The wait now finds the daemon pane a pending stand-in close hides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-ed9226b71907d8aaa0b6
|
Review (subagent opus-5.5 medium): SHIP at a065072 What holds up:
Findings:
Follow-ups: 1 (intent leaks when the send never runs), 2 (store and connection from different daemons for remote panes), 3 (dock waits until a snapshot when no fresh tab comes), 4 (empty source pane while the fresh tab's close is in flight), 5 (comment or test that a failed fresh-tab close rejects the whole dock). |
|
Review (codex, router-review): SHIP at a065072 Reviewer: codex gpt-6-astra high, fast tier. Follow-ups: 2. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward. SHIP at a065072
Static review completed; tests could not run because Swift is unavailable. Follow-ups:
|
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Swift logic follow-up (tip watcher swift-logic row, STATUS 13027 "SWIFT LOGIC CULPRITS"; lead order). This PR raised
plans/cmux-next/layer-ownership.md says Rust owns every state, list and rule and Swift is the platform shell. Please move the new logic of this PR in a follow-up: to Rust (the crate that owns the area; the owner lists in STATUS 12147-12165 name the target per area), or at least out of the app into its package. If a declaration above is platform code (AppKit, Core Animation, OS calls, strings, tokens, DEBUG tooling), reply here and the table gets a PLATFORM row with your reason instead. The swift-logic row is a report, not a gate: nothing blocks on this comment. |
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo (2026-11-03), about a toast reading "This pane is still opening; try again in a moment.":
A close takes effect on the click, even while a pane or tab is still opening. Before this, two closes of a stand-in still sent its stand-in id, which is refused before it is sent (
PaneNotReady, added in #28331). That showed the toast and brought the closed thing back:ProvisionalDock). When a lone chat is docked left, its old pane shows the fresh terminal's stand-in tab.CancelledCreationcovered only.createTaband.splitPane, so closing that stand-in went to the daemon, failed with the toast, and the daemon's fresh tab still showed when it landed. Fixes Docked chat: closing the fresh stand-in tab before the daemon confirms should cancel the respawn #33829.What changed
DaemonCreations.isPending/cancel(tab:)). Its close keeps the dock (the chat still docks) and sets a newstandInClosedon the intent. From then on the overlay shows the dock without the stand-in. The daemon's fresh tab, found by the terminal id the client minted, is hidden when the records hold it and closed through the existing cancelled-creation close (close-tabs,session_end). The intent stays in the log until that close commits, so the tab does not come back when the dock settles, and not after a snapshot either. If the close fails, the intent is rejected and the records show what the daemon kept..closeStandInPaneintent (DaemonStore.intendStandInPaneClose) takes the stand-in pane out of the layout, columns and panes. The daemon's pane that takes it over (same public pane id, or the pane of Cmd-N's workspace that holds its first tab) stays out too, until the daemon's records drop it. Itsclose-panewaits off the key's turn for that daemon pane (DaemonStore.daemonTarget, the same seam creates use since fix(app): Ctrl-` right after Cmd-N opens its terminal; a create on a pane still opening waits for it (P0 STATUS 2080) #29530), then settles at the reply's event sequence. If the close is refused, the pane comes back. If the stand-in was never made, there is nothing to close. A pane that is its screen's only pane (Cmd-N's lone pane) is not taken out of the records, same as a cancelled split's.8cc685e): the close's own wait for its daemon pane (StandInWait.state) now finds the daemon pane a pending stand-in close hides. Before, the hide took that pane out of the index, so once the dock settled the wait threwPendingPaneNotCreatedand the refused close brought the pane back.ee6f658): if the daemon's dock pane and layout settle the move before the respawned fresh tab arrives, the closed stand-in's intent waits for that tab (up to a snapshot, which holds everything the daemon made). A late fresh tab is still hidden and closed.No close path reaches the "still opening" toast now. The toast text itself stays for the non-close pane verbs that #28331 refuses on a stand-in (zoom, rename, swap), so those refusals still show a message.
Tests
ProvisionalDockTests(store level, no daemon binary):closingTheFreshTabsStandInClosesItAtOnceAndItsDaemonTabNeverShows: the stand-in leaves in the close's turn, the chat stays docked, and nothing is sent yet. When the daemon's dock and fresh tab land, the fresh tab is hidden and its close is sent once. It stays hidden after the move settles, and the intent leaves only when the close commits. No mirror violations. On base,cancel(tab:)returns false and the stand-in stays.aFreshTabThatLandsAfterTheDockSettledStaysClosed: the dock pane and layout arrive as events, the move settles, and then the fresh tab lands. It is hidden and closed (the review's P1).closingTheDocksStandInPaneTakesItOutAtOnceAndItsDaemonPaneNeverShows: right after the close intent, the stand-in pane, its dock column and its chat are gone from the model. The daemon's dock pane under the same public id never shows, including after both replies settle. The intent leaves once a snapshot drops the pane. No mirror violations.daemonTargetfor the stand-in before and after the dock settles and gets the hidden daemon pane both times (the P1 at8cc685e).aRefusedDockAfterItsStandInClosedShowsTheChatOnly: a refused move after the close leaves the chat in its pane, with no stand-in.tooling-testsred: the same 32WebLintPrePushTestsfail by name on #34392, a Swift-only PR with no overlap, so it is a base red.Risk: the overlay changes only for a
.dockTabwhose stand-in was closed and for the new.closeStandInPane. The other intents are untouched; thestandInClosedchecks are false for them.hidePaneis the cancelled split's pane removal moved out unchanged. The hidden-pane tab count now leaves out provisional tabs, which the conservation check already leaves out of the visible count.Follow-ups (not in this PR): #34414, and #34432 (check the native layout of the pane close in a build, the review's P2). Closing Cmd-N's lone stand-in pane while the workspace opens is hidden only in the view, not taken out of the model. Cmd-W on Cmd-N's own first tab while it opens still sends the stand-in. Both need a decision on whether the emptied workspace closes or keeps an empty pane (
EmptyWorkspaceRepair).Agent session: agent session
🤖 Generated with Claude Code