Repository navigation
Fix tab moves while terminals reconnect after restart - #27243
Conversation
After a daemon restart a placed tab can lack its runtime surface while its terminal adopts (R41). tab.move of such a tab is rejected with layout-conservation-violation. Regression test for #25999. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After a daemon restart a tab is placed in its pane before its terminal adopts, so it has no runtime surface yet (R41; a host-lost tab is the same). tab.move of such a tab was rejected with layout-conservation-violation: - move_tab_in_state returned early for a tab missing from state.surfaces, so the live move did nothing while the reducer moved the tab, and the placements disagreed. - The layout projection built tab content only from runtime surfaces, so the reducer saw the pane list a tab without content and rejected a move into another pane. move_tab_in_state now needs only a placement, and the projection describes an unmaterialized tab by its durable content identity with no runtime. Fixes #25999 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-tab-move-adoption
|
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)
web and size checks: green Shipped in:
|
|
Bead |
|
Found 3 test failures on Blacksmith runners: Failures
|
…-tab-move-adoption
…-tab-move-adoption
…-tab-move-adoption
…-tab-move-adoption
…-tab-move-adoption
|
Review (review_final_adoption, independent correctness): SHIP at cad12a1 Fresh independent review against On this exact head I ran the focused layout, wire and real restart/adoption recovery suites on rbx: 26 passed. The pre-push gate, normal push hook and whitespace check passed. Tagged fleet build The remaining failing tests are inherited: the signing-hook test on this head matches the base failure; the GPL crate-list failure matches base. The repository's per-test classifier returns The head Rust panic ratchet and current base run have identical underlying findings: |
…-tab-move-adoption
|
Review (review_final_adoption, independent correctness): SHIP at 426b668 Fresh independent review of the complete seven-file patch against e05d495 found no concrete correctness blockers. It covered shared and wire move paths, durable plans, reducer staging/rollback, adoption completion and runtime placement insertion, including the newly merged locking, settlement and reconnect code. Registry → connection → state serialization remains intact; settlement precedes projection and adoption materializes the current content placements. The reviewer performed source review and |
…-tab-move-adoption
|
Review (review_final_adoption, independent correctness): SHIP at 693a7da Fresh independent correctness review against db183fa found no concrete PR-caused blocker. The reviewer re-read the entire seven-file patch, current move/wire validation, layout projection, durable plans, rollback, adoption insertion, and relevant upstream template-key, PTY reclaim and server-origin changes. The key repair preserves durable identity; adoption and moves retain registry → pinned-state serialization, and adoption honors the current placements. The reviewer performed source review and |
|
CI attribution for
The exact PR head passed all 27 focused regression/layout/adoption tests on rbx. Tagged fleet build |
…-tab-move-adoption
|
Review (review_final_adoption, independent correctness): SHIP at 9254d56 Fresh independent correctness review against 3465552 found no concrete blocker. The reviewer re-read the full seven-file patch, current move/wire validation, durable plans, reducer staging/rollback and adoption materialization, including newly merged PTY-reclaim poison recovery and app event/subscription changes. Move/adoption serialization and insertion into current placements remain sound; unknown wire IDs remain rejected. The reviewer performed source review and |
|
Verification update for
|
…-tab-move-adoption
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. |
|
Review (review_final_adoption, independent correctness): SHIP at c30737e Fresh independent review against 0e2fb2e found no concrete correctness or repository-rule blockers. The reviewer re-read the full seven-file patch and current shared/wire move, reducer projection/staging, durable plan/rollback and adoption materialization, including newly merged kept-tab/reaper changes. Move/adoption serialization and durable placement identity remain sound; the two regressions cover the mutation and wire precheck. The reviewer performed read-only source review and |
|
Review (review_final_adoption, independent correctness): SHIP at fde79e2 Fresh independent review against 3cf858d found no concrete correctness or repository-rule blockers. The reviewer re-read the complete seven-file patch and current wire/shared move, reducer projection, durable staging/rollback, adoption runtime insertion and undo paths. Newly merged startup adoption scheduling, durable unplaced-terminal reaping and locking preserve placement identity and move/adoption serialization. The reviewer performed source review and |
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Terminal tabs can be moved or reordered immediately after a daemon restart, while their terminal hosts are still being adopted. Both
tab.moveand themove-tabsocket command used by dragging now require a committed placement rather than a runtime surface. Layout validation includes the tab's durable content identity before that surface exists.Fixes #25999.
Verification
The regression covers same-pane reorder and cross-pane movement without a runtime surface, checks for invariant rejection, and compares durable layout with memory. A second regression exercises the
move-tabwire command and retains rejection of unknown IDs.The same focused fleet command failed before the fix at
f3b9eb6f3d1a566ac2939208613ac258bca1244b(1 failed) and passed after the fix at23ff5996d35c42bbcfdb1ba2f924357ae70cc569(1 passed):cmux-ci run --class isolated --script scripts/ci/cmux-tui-rust-check.sh \ --ref SHA --arg test \ --arg moves_of_a_tab_without_a_runtime_surface_follow_the_reducer \ --key issue25999-proof-SHA --no-supersede --timeout 3600Observed / Not run
Verified head:
fde79e2fac12ca95e12e24844e3b4a254254cc5e, with base3cf858d6e06c599c88b45182b81d014906cd5ea8merged. GitHub reports it mergeable. All pushes were ordinary pushes, with no force or verification bypass.29 focused tests passed on rbx at this exact head, with Ghostty checked out at its committed pin. They include both regressions, layout properties and actual daemon restart/adoption recovery:
rbx --lane issue-25999-tab-move-adoption -- \ cargo nextest run --locked --workspace --exclude acpmux --no-fail-fast \ -E 'test(layout_invariants::tests) | test(cmux_next_move_tab_moves_a_tab_without_a_runtime_surface) | test(adoption)'The unrelated acpmux package is excluded because its test-list harness requires Node on rbx.
The exact head passed the executed CI static checks, fleet Release compiler and app compile gateway, same-tree daemon tests, and fast gates. No current failing check remains. Skipped jobs are not counted as executed coverage.
Fresh independent correctness review of this exact head found no blockers. It covered both move entrypoints, durable staging/rollback, current adoption insertion, locking, reaping and undo. The reviewer performed source review, not independent runtime testing.
Tagged fleet build succeeded and is published: job
6f3d5455f597185cb87e5098, tagissue-25999-tab-move-adoption9, explicit local backend. Artifact SHA-25634e0eab2e4ee6728534a4eada33863bb82d9313838975b73e161ed9f984a0425; workspace cleanup, Tag Opener health, tag registration and matching artifact manifest verified.git diff --checkand the scoped prepush gate passed. The CI static job above also executed on this head. No native build or heavy test ran on the person's Mac.The regressions simulate pending adoption by removing the runtime surface; the recovery suite separately exercises actual daemon restarts. The tagged app was not launched: no GUI interaction, live GUI restart or shared Cloud backend verification is claimed. No UI strings or localization catalogs changed.
Try it
The rbx command above deterministically exercises the adoption window and real restart recovery. The tagged build
issue-25999-tab-move-adoption9is available for local daemon/layout dogfood; shared Cloud behavior is unverified. UseCMUX_TAG=issue-25999-tab-move-adoption9 scripts/cmux-debug-cli.shfor isolated automation. Immediately after a daemon restart, move or reorder a terminal tab: the move should commit while the terminal reconnects, withoutlayout-conservation-violation.Changelog
Fixed: Terminal tabs can be moved immediately after reconnecting to a restarted daemon.
No capture: daemon layout behavior with no native UI changes.
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Fixes #25999: terminal tabs can now be moved or reordered immediately after a daemon restart, while their terminals are still being adopted.
Two causes made the live move disagree with the layout reducer:
move_tab_in_statereturned early for a tab without a runtime surface, and the layout projection built tab content only from runtime surfaces. The move path — bothtab.moveand themove-tabsocket command the app's drag sends — now requires only a placement, and the projection describes unmaterialized tabs by their durable content identity with no runtime.move-tabwire command for a tab without a runtime surface.Written for commit fde79e2. Summary will update on new commits.