Skip to content

Keep ssh-tmux mirror bookkeeping focus-neutral - #7742

Merged
austinywang merged 6 commits into
mainfrom
issue-7733-7737-mirror-selection-steal
Jul 9, 2026
Merged

austinywang merged 6 commits into
mainfrom
issue-7733-7737-mirror-selection-steal

Conversation

@austinywang

@austinywang austinywang commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • route remote-tmux create, close, reorder, and full topology rebuilds through one @MainActor focus-neutral mutation transaction
  • preserve pane/tab selection, selected workspace, app activation, and owning window visibility/key state across mirror bookkeeping
  • suppress selection activation and deferred focus reconciliation while bookkeeping is active; only an already-key foreground mirror whose selected tab was removed reconciles to its natural successor
  • propagate surface.create focus intent end-to-end: background requests use tmux new-window -d, while explicit focus requests correlate tmux's stable new window id and focus only after its mirror tab exists

Root cause

Mirror topology synchronization used Bonsplit's ordinary user-interaction mutation APIs. Those APIs select newly created/reordered tabs, choose adjacent tabs during close, run applyTabSelection, and schedule AppKit focus reconciliation. As a result, bookkeeping with no focus intent could change selection and make a hidden dedicated mirror window visible/key.

The fix establishes one invariant at the shared mutation boundary: remote mirror bookkeeping cannot run focus/activation side effects, and its user-visible state is restored from one snapshot. Explicit focus is a separate post-bookkeeping action tied to the created tmux window id.

Verification

  • added a test-only first commit proving the regression before the fix
  • added Swift Testing coverage that background mirror tab creation preserves pane/surface selection
  • added coverage that closing a background mirror surface preserves selection and keeps a hidden window hidden/non-key without a transient key notification
  • added command-builder coverage for detached background creation and stable-id explicit-focus creation
  • scripts/check-pbxproj.sh
  • ./scripts/lint-pbxproj-test-wiring.sh
  • Swift parser pass over all changed Swift files
  • python3 scripts/swift_file_length_budget.py passes; RemoteTmuxControlConnection.swift shrinks from 1,177 lines at the PR base to 1,175, all new files stay below 500, and neither budget TSV changes
  • no user-facing strings were introduced, so no localization catalogs changed

Local app builds/tests were intentionally not run per the issue constraints; GitHub CI is the compile/test gate.

Closes #7733
Closes #7737


Note

Medium Risk
Touches AppKit window/key restoration and broad focus/selection gates in Workspace during mirror churn; incorrect snapshot restore could still steal focus or leave selection wrong, but scope is mirror-specific with new regression tests.

Overview
Remote tmux mirror topology sync (create/close/reorder/rebuild) now runs inside a single focus-neutral transaction that snapshots and restores tab/pane selection, workspace selection, and window visibility/key state, while blocking applyTabSelection, focusPanel, and deferred focus reconcile during the mutation.

New-tab routing gains a focus flag end-to-end: background creates send new-window -d so tmux does not steal the active window; focused creates use -P -F '#{window_id}' via sendNewWindow, with local focus applied only after the mirror tab exists (focusWindowWhenAvailable). Pending new-window callbacks are failed on reconnect/stop like activity queries.

handleMirrorNewTabRequested moves to RemoteTmuxController+Decisions with sessionMirror(workspaceId:) lookup; command send helpers move to RemoteTmuxControlConnection+Commands. Tests cover detached vs focused command strings and lifecycle focus preservation.

Reviewed by Cursor Bugbot for commit 5ecd937. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Improved remote tmux mirror “new tab/window” creation behavior with support for background vs focused creation and correct placement semantics.
  • Bug Fixes
    • Prevented new-window requests from hanging by reliably resolving pending completions across error paths and reconnect/teardown.
    • Reduced focus/activation churn during mirror mutations by preserving and restoring selection, pane focus, and window key/visibility state more consistently.
    • Kept hidden mirror windows non-key and not visible during background-close sequences.
  • Tests
    • Added/updated mirror lifecycle and new-tab placement regression coverage.

@vercel

vercel Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Canceled Canceled Jul 9, 2026 9:12pm
cmux-staging Building Building Preview, Comment Jul 9, 2026 9:12pm

@coderabbitai

coderabbitai Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds completion-based remote tmux new-window handling, focus-aware command generation and routing, a mutation coordinator and snapshot to suppress focus and selection side effects during background mirror mutations, workspace and session-mirror wiring, project registration, and tests for the updated command flags and lifecycle behavior.

Changes

Remote tmux mirror focus-neutral mutation flow

Layer / File(s) Summary
New-window control command roundtrip
Sources/RemoteTmuxControlCommandKind.swift, Sources/RemoteTmuxControlConnection+CommandResults.swift, Sources/RemoteTmuxControlConnection.swift, Sources/RemoteTmuxControlConnection+Commands.swift
Adds .newWindow(UUID), resolves pending completions with parsed window ids or nil on success and error paths, adds sendNewWindow, and fails pending requests on reset, cancellation, and reconnect.
Focus-aware command generation and routing
Sources/RemoteTmuxController+Decisions.swift, Sources/RemoteTmuxController.swift, Sources/Workspace.swift
Adds mirror new-tab handling, reworks newWindowCommand with focus, changes the generated tmux command forms for background and focused creation, removes the old routing method, and adds workspace mirror lookup and focus forwarding.
Mirror mutation coordinator and snapshot
Sources/RemoteTmuxMirrorMutationCoordinator.swift, Sources/RemoteTmuxMirrorMutationSnapshot.swift, cmux.xcodeproj/project.pbxproj
Introduces the mutation coordinator with snapshot-based suppression and restore behavior, adds workspace helpers for running remote tmux mutations and removing display panes, and registers the new source files in the Xcode project.
Workspace focus-suppression wiring
Sources/Workspace.swift
Adds the shared mutation coordinator property, guards focus and selection entry points while suppression is active, routes display-pane creation and tab reordering through the coordinator, removes the reorder flag model, and updates related documentation comments.
Explicit focus deferral and pane removal
Sources/RemoteTmuxSessionMirror.swift
Adds pending explicit focus storage, wraps topology rebuild in the mutation coordinator, applies deferred focus after rebuild, and switches pane removal to the remote-tmux display-pane helper.
Command flag and lifecycle tests
cmuxTests/RemoteTmuxMirrorNewTabPlacementTests.swift, cmuxTests/RemoteTmuxNewWindowCwdTests.swift, cmuxTests/RemoteTmuxMirrorLifecycleTests.swift
Updates command-string expectations for detached and focused creation, adds coverage for background creation flags, and extends lifecycle tests with window-focus and visibility regressions.

Estimated code review effort: 4 (Complex) | ~60 minutes
Suggested reviewers: lawrencecchen

🚥 Pre-merge checks | ✅ 4 | ❌ 21

❌ Failed checks (1 warning, 20 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Swift Actor Isolation ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Blocking Runtime ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Browser Automation Off-Main ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Expensive Synchronous Load ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Cache Substitution Correctness ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux No Hacky Sleeps ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Algorithmic Complexity ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Concurrency ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift @Concurrent ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift File And Package Boundaries ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swiftpm Lockfiles ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Logging ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux User-Facing Error Privacy ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Full Internationalization ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swiftui State Layout ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Architecture Rethink ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Auxiliary Window Close Shortcuts ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Source Artifacts ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux No Test Or Debug Seam In Production Source ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux No Ambient Global State ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes and tests address both linked issues by preserving background selection and preventing hidden mirror windows from becoming visible or key.
Out of Scope Changes check ✅ Passed The added mutation helpers, controller routing, and tests all support the mirror focus-neutrality goals and do not appear unrelated.
Title check ✅ Passed The title matches the main change: making ssh-tmux mirror bookkeeping focus-neutral.
Description check ✅ Passed The description covers the change, rationale, and verification well and is mostly aligned with the template.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-7733-7737-mirror-selection-steal

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR keeps remote tmux mirror bookkeeping from changing user focus. The main changes are:

  • Adds a focus-neutral mirror mutation transaction.
  • Restores pane, tab, workspace, and AppKit window state after mirror updates.
  • Sends background tmux window creates with detached selection behavior.
  • Correlates focused creates by tmux window id before focusing the mirror tab.
  • Adds tests for mirror lifecycle, placement, and cwd command building.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
Sources/RemoteTmuxSessionMirror.swift Runs mirror rebuilds inside the focus-neutral transaction and defers explicit focus until the mirrored tab exists.
Sources/RemoteTmuxMirrorMutationCoordinator.swift Adds the shared transaction boundary for remote tmux mirror UI bookkeeping.
Sources/RemoteTmuxMirrorMutationSnapshot.swift Captures and restores user-visible selection and window state around mirror mutations.
Sources/RemoteTmuxController+Decisions.swift Builds separate tmux new-window commands for background and explicit-focus requests.
Sources/RemoteTmuxControlConnection+Commands.swift Adds command helpers for regular sends and new-window result callbacks.
Sources/RemoteTmuxControlConnection+CommandResults.swift Parses new-window command results and clears pending callbacks on failure.
Sources/Workspace.swift Routes mirror create, close, reorder, and focus suppression through the shared transaction.
cmux.xcodeproj/project.pbxproj Wires the new Swift source files into the Xcode project.
cmuxTests/RemoteTmuxMirrorLifecycleTests.swift Adds lifecycle coverage for background mirror creation and hidden-window close behavior.
cmuxTests/RemoteTmuxMirrorNewTabPlacementTests.swift Updates placement tests for detached background creates and focused stable-id creates.
cmuxTests/RemoteTmuxNewWindowCwdTests.swift Updates cwd command expectations for detached background tmux window creation.

Reviews (3): Last reviewed commit: "refactor: extract remote tmux command se..." | Re-trigger Greptile

Comment thread Sources/RemoteTmuxSessionMirror.swift
Comment thread Sources/RemoteTmuxSessionMirror.swift

This branch was successfully deployed

1 active deployment
Preview – cmux — 5ecd937e Deployed Jul 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant