Skip to content

Fix iOS workspace selection after Iroh reconnect - #9979

Merged
azooz2003-bit merged 2 commits into
mainfrom
feat-ios-workspace-selection-reconnect
Aug 11, 2026
Merged

azooz2003-bit merged 2 commits into
mainfrom
feat-ios-workspace-selection-reconnect

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Aug 11, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Preserve the selected iOS workspace when an Iroh event stream reconnects to the same Mac and build.
  • Connection teardown cleared the live foreground Mac identity before redial, so recovery looked like a Mac switch and selected the first workspace. The reconnect now compares against the retained recovery pairing key, including the build tag. Real Mac or build switches still reset selection.

Testing

  • Test-only commit reproduced hevy-cli changing to cmux-master: https://github.com/manaflow-ai/cmux/actions/runs/31466803835
  • Focused sameMacEventStreamRecoveryPreservesSelectedWorkspace test passed on the AWS M4 Pro.
  • Package conventions lint and the requested iPad routing job passed: https://github.com/manaflow-ai/cmux/actions/runs/31467488901
  • The same workflow's package and iPhone jobs reached the ten-minute job limit and were canceled, so its aggregate job failed without a test assertion failure.
  • Cloud macOS and iOS builds succeeded. The isolated iOS simulator paired and rendered both cmux-master and Hevy CLI. The exact reconnect UI path remains unverified because Computer Use could not safely target this Simulator window while another agent's Simulator window was focused.

Demo Video

  • No video. This is a state-management change with no UI changes, and the exact simulator reconnect path could not be safely driven under the current shared Simulator window state.

Review Trigger (Copy/Paste as PR comment)

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

Checklist

  • I tested the change locally. Local cmux test runs are prohibited; the focused test ran on the AWS M4 Pro.
  • I added or updated tests for behavior changes.
  • I updated docs/changelog if needed. No user-facing behavior or configuration documentation changed.
  • I requested bot reviews after my latest commit. No manual review trigger was sent; CodeRabbit and Cursor ran automatically.
  • All code review bot comments are resolved. Automatic reviews reported no actionable comments.
  • All human review comments are resolved. No human review comments exist.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The mobile shell now uses a retained recovery target when the live foreground identity is cleared during reconnects. Tests configure multiple workspaces and verify that the selected workspace persists after Iroh transport recovery.

Changes

Reconnection recovery

Layer / File(s) Summary
Multi-workspace liveness support
Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/MobileShellRenderGridLivenessTestSupport.swift
The liveness router supports configurable workspace IDs and generates workspace-list entries with workspace-specific metadata and selection state.
Recovery-aware connection ownership
Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift
Connection setup snapshots a foreground key that falls back to the retained recovery target during reconnects.
Workspace preservation validation
Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/IrohConnectionRecoveryOwnerTests.swift
The recovery test verifies that the selected hevy-cli workspace remains selected after transport closure and replacement connection establishment.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RecoveryTest
  participant MobileShellComposite
  participant IrohTransport
  participant WorkspaceRouter
  RecoveryTest->>WorkspaceRouter: configure and select hevy-cli
  RecoveryTest->>IrohTransport: close active transport
  IrohTransport->>MobileShellComposite: establish replacement connection
  MobileShellComposite->>WorkspaceRouter: preserve selected workspace
  WorkspaceRouter-->>RecoveryTest: report hevy-cli as selected
Loading

Possibly related PRs

Suggested reviewers: lawrencecchen, austinywang


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Cmux Swift Actor Isolation ❓ Inconclusive Investigation is still in progress. Inspect the production Swift diff and actor-isolation rule before deciding.
✅ Passed checks (24 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Blocking Runtime ✅ Passed The production diff only adds a computed MacPairingKey and uses it for connection setup; the added-line scan found no blocking or timing primitives. Other changes are test scaffolding.
Cmux Browser Automation Off-Main ✅ Passed The PR changes only iOS reconnect logic and tests; the cumulative diff contains no browser.* socket commands or WebKit/AppKit routing changes.
Cmux Expensive Synchronous Load ✅ Passed The production change only adjusts reconnect identity selection; no expensive synchronous agent-history load or interactive-path file parsing appears in the described diff.
Cmux Cache Substitution Correctness ✅ Passed The diff changes in-memory reconnect/workspace ownership, not a fresh disk, database, history, undo, or persistence read; the retained key updates with foreground changes and clears on sign-out.
Cmux No Hacky Sleeps ✅ Passed The aggregate PR diff contains only three Swift files. The rule scopes TypeScript, JavaScript, shell, and non-Swift runtime scripts, so this check is not applicable.
Cmux Algorithmic Complexity ✅ Passed The production diff adds only constant-time key selection and construction in MobileShellComposite.swift; the only collection map/scan changes are test-only scaffolding.
Cmux Swift Concurrency ✅ Passed The PR adds a synchronous MacPairingKey helper and actor-based async test setup; added lines contain no Dispatch queues, Combine state, completion-handler API, or fire-and-forget Task.
Cmux Swift @Concurrent ✅ Passed The added property is synchronous inside @MainActor; the new async test is @MainActor-bound, and router helpers are actor-isolated. No changed nonisolated async or invalid @concurrent usage exists.
Cmux Swift Package Boundaries ✅ Passed The production diff adds a private 14-line selector inside @MainActor MobileShellComposite, tied to connection lifecycle state; it adds no reusable/public domain logic or new boundary-sensitive fea...
Cmux Swiftpm Lockfiles ✅ Passed The full PR range changes only iOS source and test files; it has no Package.swift, Package.resolved, .gitignore, Xcode project, workflow, or dependency changes requiring lockfile updates.
Cmux Swift Logging ✅ Passed The two-commit diff adds recovery logic and test fixtures only; it adds or materially changes no print, debugPrint, dump, NSLog, ad hoc logging, or sensitive-data logging.
Cmux User-Facing Error Privacy ✅ Passed The production diff only adds recovery-key selection and internal comments; it adds or changes no user-facing errors, alerts, output, API bodies, or recovery copy.
Cmux Full Internationalization ✅ Passed The production diff adds only recovery-key logic and comments; all other changes are tests/fixtures. No user-facing text, localization keys, catalogs, or web locale data changed.
Cmux Swiftui State Layout ✅ Passed The PR changes no SwiftUI view or layout code. It adds a computed pairing key to the existing @Observable model and actor-only test fixtures; no forbidden state, geometry, lazy-row store, or render...
Cmux Architecture Rethink ✅ Passed The production diff adds a computed recovery key over existing state and uses it at connect setup; it adds no timing, blocking, duplicate owner, or lifecycle wiring. Polling remains test-only.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR changes only iOS connection-recovery logic and test fixtures; it adds no user-visible NSWindow, NSPanel, NSWindowController, Window, or WindowGroup code.
Cmux Source Artifacts ✅ Passed All three changed paths are Swift source or test-support files under Packages/iOS; no artifact directories, logs, screenshots, caches, build output, or dependency checkouts enter the diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The only changed file is production Swift. The PR adds a private recovery key used by connect, with no DEBUG/test guard, test-named member, widened visibility, or test wrapper.
Cmux No Ambient Global State ✅ Passed The production diff adds only private instance property foregroundOrRecoveryMacKey inside MobileShellComposite and updates one instance method; it adds no ambient global state or singleton.
Title check ✅ Passed The title clearly and concisely describes the main change: preserving iOS workspace selection after an Iroh reconnect.
Description check ✅ Passed The description explains the cause, fix, testing, limitations, and checklist status, with a justified omission of a demo video for this state-management change.
✨ 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 feat-ios-workspace-selection-reconnect

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant