fix(tabs): Cmd-W right after Cmd-T closes the new tab, not nothing (tip smoke red)

Merged
LA
6d ago
+90-1

Summary

Cmd-T, then Cmd-W soon after, sometimes closed nothing: the New Tab page stayed. This turned the tip smoke red at b732874bf5e3 (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 d15622db704f (2026-11-01) and on the last smoke-green build (7563ccddc8b7).

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 as AgentTabStore.open does, and presses Cmd-W in that same turn, before the strip's observation step.

Fleet command (red at 9fe44fb24ed, green at 2f4997e6ff4):
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.app

  • Red on the base + test only (cf90261ff3f, branch fix/cmdw-stale-standin-red, fleet step 9c180fae, aws-m4pro-1): CmdWOnReplacedStandInTests failed at the Cmd-W check: "Cmd-W closed nothing: the pane holds [...], the New Tab tab is tab_6080d827...". The other 4 suites passed.
  • Green on the head (934d51bf1f0, fleet step dd7aae92, aws-m4pro-8): CmdWOnReplacedStandInTests, CloseTabKeepsPaneTests, RapidCloseTabTests, NewTabReplaceInPlaceTests and TabSpamRaceTests (it covers the intent log) all passed.
  • The first version of the test (9fe44fb24ed) waited for the store to pair the daemon's raw tab-added with the stand-in. On the base run (step ed4e88f8) that wait timed out before the Cmd-W, so that run is no red evidence. 934d51bf1f0 sets the same state without that wait.
  • scripts/cmux-next/prepush-gate.py: no new violations; arch ratchet: no count rises.

Observed / Not run

Observed:

  • Fleet diag journey (smoke journey to the browser page, then 16 Cmd-T/Cmd-W pairs 0-0.25 s apart, hog +15 GB, debug.key, cmux21): pair 2 (Cmd-W about 45 ms after Cmd-T) left the New Tab tab open on the tip build 84b90c53 (2 of 2 rounds) and on the last smoke-green build 45613f0e (1 of 1 round). Pair 1 (Cmd-W at once) closed the stand-in through the cancel path.
  • The tip smoke round's state: Cmd-W ran closeTab (handled_by app), no "closed before created" in new_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.
  • Fix build 027c40e1 (2f4997e6ff4), diag round 1 (cmux24): the round failed earlier, at step 23 ("Cmd-D twice fast": both typed lines went to one new terminal), before the Cmd-T/Cmd-W pairs. That step has failed the same way on several tips before (Oct 31 tip-watcher rounds), and the fix does not touch the split path (.splitPane creations 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.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with 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.