Repository navigation
fix(tabs): Cmd-W right after Cmd-T closes the new tab, not nothing (tip smoke red) - #31837
Merged
Merged
Conversation
… closes the store's tab (red) Tip smoke red at b732874 (STATUS 4852): Cmd-T on a browser page, then Cmd-W; the New Tab page stayed. The strip shows the store one observation step late, so a Cmd-W in that step names the stand-in (pending_tab_...) that the store already replaced, and Close Tab closes nothing. Fleet diag (hog +15 GB, Cmd-W 30 ms after Cmd-T): fails on the tip 84b90c53 and on the last smoke-green build 45613f0e (7563ccd). Red expected on the base: the tab stays.
…ses the store's tab (green) The strip shows the store one observation step late. In the step after the daemon's reply replaced Cmd-T's stand-in (pending_tab_...) with the store's tab, the strip still selected the stand-in, the store no longer listed it, and PaneController.tab(_:) found nothing: Close Tab (and every action on the selected tab) did nothing, silently. The intent log now keeps, for the last 64 confirmed creations, which daemon surface each stand-in tab became, and PaneController.tab(_:) resolves a stand-in id the pane no longer lists to that tab while the pane lists it (DaemonCreations.replacement(ofStandIn:in:)). A cancelled or refused stand-in still resolves to nothing. CmuxNextApp lines: +0 (one line changed).
…ing on the daemon's pairing The first version waited for the store to pair the daemon's raw tab-added with the stand-in (ProvisionalTab.matched); on the base run (step ed4e88f8, aws-m4pro-1) that wait timed out, so the test failed before its Cmd-W. The daemon's tab is now listed first and the reply's turn names it, which replaces the stand-in the same way; the Cmd-W assertion is unchanged.
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. |
lawrencecchen
temporarily deployed
to
ci-routing-agent
November 2, 2026 05:02 — with
GitHub Actions
Inactive
Contributor
|
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)
Shipped in:
|
Contributor
Author
|
Review (smoke-cmdw reviewer): SHIP at 934d51b Non-blocking notes:
|
|
Found 6 test failures on Blacksmith runners: Failures
|
This was referenced Nov 2, 2026
Merged
lawrencecchen
added a commit
that referenced
this pull request
Nov 2, 2026
…(follow-up #31837) (#31918) * test(tabs): Cmd-W on a replaced browser stand-in asks the browser tab's page first (red) Follow-up of #31837 (reviewer note, lead: data-loss risk). In the step after the reply replaced a browser stand-in, Close Tab looks up the page that decides the close (beforeunload) by the strip's id, the stand-in's, which no page has: the page is never asked. Red expected on #31837's head: pageDecidesClose is asked about the stand-in id only. * fix(tabs): Cmd-W on a replaced stand-in acts on its tab's id, so a browser page decides its close (green) AppActionContext.tab(_:) returns the id of the tab PaneController.tab(_:) resolves (#31837) for the strip's selected id: in the step after a reply replaced a stand-in, Close Tab, its beforeunload check (CloseUndoToasts.livePageDecidesClose, cache.browsers) and pageClosing use the store tab's id, not the stand-in's. Any other selected id is unchanged. CmuxNextApp lines: +0 (one line changed). * test(tabs): Close Other Tabs in the replaced-stand-in step keeps the selected tab (red at 92644d5) Review BLOCK of #31918 at 92644d5: with ctx.tab(_:) returning the store tab's id, the strip (which still lists the stand-in) counted the stand-in as another tab, and its close resolved to the tab the person kept. * fix(tabs): only the close resolves a replaced stand-in's id; every strip-keyed action keeps the strip id (review BLOCK) Takes back 92644d5's change to AppActionContext.tab(_:): about 25 actions key on the strip id (Close Other Tabs, find, reload, ctx.terminal, multi-selection Cmd-W, empties/PaneCloseAim, close to the right/left), and the strip does not list the store tab in that step. CloseUndoToasts.close(_:) now maps each closing id to the tab PaneController.tab(_:) resolves after the pending-creation filter, so the page that decides the close (livePageDecidesClose, cache.browsers, pageClosing) is the store tab's: Cmd-W, the close button and the close commands. CmuxNextApp lines: +0. --------- Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Summary
Cmd-T, then Cmd-W soon after, sometimes closed nothing: the New Tab page stayed. This turned the tip smoke red at b732874 (STATUS 4852, step 66 "Cmd-W closes that tab").
Cmd-T shows the New Tab page as a stand-in tab (
pending_tab_...). When the daemon's reply comes, the store replaces the stand-in with its own tab in one step. The pane's strip follows the store one observation step later. A Cmd-W in that step reads the strip's selected id, which is still the stand-in.PaneController.tab(_:)found no tab with that id, so Close Tab (and every other action on the selected tab) did nothing, with no message.The fix: the store's intent log keeps, for the last 64 confirmed creations, which daemon surface each stand-in tab became.
PaneController.tab(_:)resolves a stand-in id that the pane no longer lists to that tab while the pane lists it (DaemonCreations.replacement(ofStandIn:in:)). A stand-in that is still shown keeps the cancel path ("closed before created"); a cancelled or refused stand-in still resolves to nothing. CmuxNextApp lines: +0 (one line changed).This race is old: it is not a commit in the tip range. The same failure shows at d15622d (2026-11-01) and on the last smoke-green build (7563ccd).
Testing
Regression test (committed red before the fix):
CmdWOnReplacedStandInTests(CmuxNextAppTests, live same-tree cmux-tui). It shows a New Tab stand-in, lets the daemon make the tab (hidden behind the stand-in), runs the reply's turn asAgentTabStore.opendoes, and presses Cmd-W in that same turn, before the strip's observation step.Fleet command (red at 9fe44fb, green at 2f4997e):
cmux-ci run --class light --script scripts/ci/package-test-lane.sh --ref SHA --arg=suite --arg=Packages/macOS/CmuxNext --arg=CmdWOnReplacedStandInTests,CloseTabKeepsPaneTests,RapidCloseTabTests,NewTabReplaceInPlaceTests --env CMUX_CI_XCODE_APP=/Applications/Xcode_26.6.appfix/cmdw-stale-standin-red, fleet step 9c180fae, aws-m4pro-1):CmdWOnReplacedStandInTestsfailed at the Cmd-W check: "Cmd-W closed nothing: the pane holds [...], the New Tab tab is tab_6080d827...". The other 4 suites passed.CmdWOnReplacedStandInTests,CloseTabKeepsPaneTests,RapidCloseTabTests,NewTabReplaceInPlaceTestsandTabSpamRaceTests(it covers the intent log) all passed.scripts/cmux-next/prepush-gate.py: no new violations; arch ratchet: no count rises.Observed / Not run
Observed:
closeTab(handled_by app), no "closed before created" innew_tab_key_log, the page then reported ready at +134 ms and stayed; 25 s later the pane still had the New Tab tab selected..splitPanecreations are not recorded). More rounds on this build are queued through the mini scheduler.Not run: real HID Cmd-W rounds (the smoke's real-key rounds stop earlier at the New Column item, STATUS 1712/1724).
Changelog
Fixed: Cmd-W right after Cmd-T closes the new tab every time, instead of sometimes doing nothing.
Proof
No capture: no visible UI change; the evidence is the regression test and the fleet journey above.
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Fixes a race where Cmd-W right after Cmd-T closed nothing, leaving the New Tab page open.
Cmd-T shows the New Tab page as a stand-in tab. When the daemon's reply arrives, the store replaces the stand-in with its own tab, but the pane's strip only catches up one observation step later. A Cmd-W in that step still targets the stand-in id, which the store no longer lists, so Close Tab silently found no tab.
The intent log now keeps, for the last 64 confirmed creations, which daemon surface each stand-in became.
PaneController.tab(_:)resolves a stand-in id the pane no longer lists to that tab while the pane lists it. Cancelled or refused stand-ins still resolve to nothing.Also adds a regression test that replays the racy turn and verifies Cmd-W closes the created tab.
Written for commit 934d51b. Summary will update on new commits.