Skip to content

Fix grouped workspaces in All Computers - #9509

Merged
azooz2003-bit merged 8 commits into
mainfrom
feat-ios-all-computers-groups
Aug 6, 2026
Merged

azooz2003-bit merged 8 commits into
mainfrom
feat-ios-all-computers-groups

Conversation

@azooz2003-bit

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

Copy link
Copy Markdown
Collaborator

Fixes the All Computers workspace list flattening when a secondary Mac appears.

  • Preserve every secondary Mac group snapshot and aggregate group IDs and anchors per Mac
  • Keep grouped rendering independent from foreground-only reorder and create guards
  • Isolate device-local collapse state per Mac and translate aggregate IDs before RPC mutations

Tests: red/green aggregation regression, All Computers view regression, 197 model tests, shell build, and scoped group-mutation test.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixes grouped workspaces in All Computers by rendering groups from every Mac and keeping same‑ID groups distinct. Preserves device‑local collapse state and translates aggregate group IDs to Mac‑local IDs for all RPC mutations.

  • Bug Fixes

    • Preserve each Mac’s group snapshot across refresh and secondary promotion; All Computers shows all groups.
    • Keep collapse state per Mac using stable collapseStateID; migrate legacy raw‑ID entries only when uniquely attributable, ignore ambiguous cases.
    • Translate aggregated group_id values to Mac‑local IDs for create, move, and rename RPC calls.
  • Refactors

    • Derive groups from every Mac and namespace group and anchor workspace IDs; add ownership to MobileWorkspaceGroupPreview (remoteGroupID, macDeviceID, macInstanceTag) and drive workspace/group order from precomputed Mac display order.
    • Introduce SecondaryWorkspaceSnapshot and shared group resolution; accept empty or missing group lists and preserve prior groups when omitted.
    • Decouple rendering from mutation gates and rename UI guard to canMutateForegroundGroupsForSelection; grouped sections remain when unfiltered.

Written for commit 5c4587f. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Workspace groups now appear across multiple Macs, including in the “All Computers” view.
    • Grouped sections remain visible in unfiltered workspace lists.
    • Workspace and group actions use the correct Mac-specific context.
  • Bug Fixes

    • Workspace refreshes now preserve and clear group information accurately.
    • Collapse preferences remain independent across Macs and migrate existing settings safely.
    • Improved secondary workspace promotion and group synchronization.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds Mac-scoped workspace group aggregation, structured secondary workspace snapshots, remote group ID mapping for mutations, owner-scoped collapse persistence, and grouped-section rendering for multi-Mac selection.

Changes

Workspace group state

Layer / File(s) Summary
Mac-scoped aggregation and collapse state
Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceAggregation.swift, Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceGroupPreview.swift, Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceGroupCollapseStore.swift, Packages/iOS/CmuxMobileShellModel/Tests/CmuxMobileShellModelTests/*
Workspace groups now aggregate across Macs with scoped IDs and retained RPC identifiers. Collapse preferences use device- and instance-scoped keys.
Secondary workspace snapshots
Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/SecondaryWorkspaceSnapshot.swift, Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/SecondaryWorkspaceFetchAttempt.swift, Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift, Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+SecondaryPromotion.swift
Secondary refresh and promotion flows carry workspace groups in structured snapshots and preserve prior groups when group metadata is absent.
Remote mutations and grouped rendering
Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+WorkspaceActions.swift, Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+WorkspaceCreateRequest.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/*, Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/MobileShellWorkspaceCapabilityTests.swift, Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceMacSelectionTests.swift, ios/cmuxUITests/cmuxUITests.swift
Workspace and group actions use remote identifiers. Grouped sections remain renderable for all-computer selection, while mutations require foreground-group capability. Preview fixtures and UI tests cover groups from multiple Macs.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SecondaryMac
  participant MobileShellComposite
  participant MobileWorkspaceAggregation
  participant WorkspaceListView
  SecondaryMac->>MobileShellComposite: return workspace and group snapshot
  MobileShellComposite->>MobileWorkspaceAggregation: derive Mac-scoped workspace groups
  MobileWorkspaceAggregation-->>WorkspaceListView: provide grouped workspace sections
  WorkspaceListView->>MobileShellComposite: request foreground group mutation
  MobileShellComposite->>SecondaryMac: send remote group identifier
Loading

Possibly related PRs

Suggested reviewers: lawrencecchen


Important

Pre-merge checks failed

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

❌ Failed checks (3 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Actor Isolation ❌ Error New private static remoteWorkspaceGroups is pure but inherits @MainActor from MobileShellComposite; it processes Sendable RPC values and returns value models. Mark remoteWorkspaceGroups as nonisolated private static (or move it to a nonisolated value utility) and keep actor-bound state checks in the instance helper.
Cmux Cache Substitution Correctness ❌ Error Secondary refresh and promotion fall back from fresh workspace.list groups to workspacesByMac/priorSecondaryGroups; no freshness marker exists, and a cold cache falls to [] before persisted collaps... Retain cached groups only with a verified generation or timestamp, and perform a fresh group read when the cache is cold or the response omits groups; otherwise mark the snapshot incomplete and block stale group persistence/mutations.
Cmux Algorithmic Complexity ❌ Error WorkspaceListView.swift:708 scans all workspaces with first(where:) for each group header; the new All Computers gate expands this to O(groups×workspaces), including ~1000-workspace lists. Build a workspace-ID dictionary once per grouped snapshot and read anchor capabilities by key instead of scanning workspaces for each group header.
Docstring Coverage ⚠️ Warning Docstring coverage is 27.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (21 passed)
Check name Status Explanation
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 PR adds no blocking or timing primitive to runtime Swift. The existing Task.sleep is unchanged in a DEBUG preview fixture, and new waitForExistence calls are XCTest-only.
Cmux Browser Automation Off-Main ✅ Passed The PR changes only iOS workspace/group code and tests; TerminalController.swift and ControlCommandExecutionPolicy.swift are unchanged, with no browser socket routing or WebKit wait changes.
Cmux Expensive Synchronous Load ✅ Passed The PR adds workspace/group aggregation and bounded UserDefaults collapse-state handling; no agent-history loader, transcript scan, broad file scan, or new synchronous JSON/file load appears in pro...
Cmux No Hacky Sleeps ✅ Passed The PR range changes 19 .swift files and no TypeScript, JavaScript, shell, or build/runtime scripts; the rule explicitly excludes Swift timing primitives.
Cmux Swift Concurrency ✅ Passed The grouped-workspace diff adds no Dispatch, Combine, completion-handler, or fire-and-forget Task patterns; its only concurrency marker is @MainActor on an XCTest UI test, an allowed boundary.
Cmux Swift @Concurrent ✅ Passed The PR adds no @concurrent or nonisolated async production work; existing async code remains unchanged. The new XCTest is explicitly @MainActor, and the model test async function is test-only coord...
Cmux Swift Package Boundaries ✅ Passed All changed production Swift is in existing SwiftPM targets; pure aggregation and collapse logic is in the tested CmuxMobileShellModel package, while shell changes are lifecycle/RPC composition.
Cmux Swiftpm Lockfiles ✅ Passed PR diff against mainline contains no Package.swift, Package.resolved, .gitignore, workflow, or Xcode package-reference changes.
Cmux Swift Logging ✅ Passed The feature diff adds no print, debugPrint, dump, NSLog, ad hoc diagnostics, or Logger changes; affected file-scoped Logger declarations are unchanged from the feature base.
Cmux User-Facing Error Privacy ✅ Passed Production additions contain no new user-facing errors, alerts, command output, or raw error propagation; changes only handle internal group IDs, snapshots, collapse state, and rendering.
Cmux Full Internationalization ✅ Passed Feature commits add no production UI copy; the only literals are in a #if DEBUG layout fixture or XCTest, and no localization catalogs, web messages, or locale files changed.
Cmux Swiftui State Layout ✅ Passed The SwiftUI diff only removes the foreground rendering gate and updates local preview fixtures; it adds no ObservableObject/@published, GeometryReader, store-bearing row subtree, or render-time sta...
Cmux Architecture Rethink ✅ Passed The diff adds no timing, polling, locks, observers, duplicate wiring, or new lifecycle owners. It keeps per-Mac state authoritative and uses pure aggregation plus the existing collapse store.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR changes only iOS models, shell, UI, and tests; no standalone window code was added or changed, and scripts/lint_auxiliary_window_close_shortcuts.py passes.
Cmux Source Artifacts ✅ Passed All 19 changed paths are Swift source or tests; no artifact directories or binary files were added. The screenshot is runtime XCTAttachment code in an intentional UI regression test.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The PR adds no DEBUG/test build guards or test/debug-named members; its fixture edits remain inside an existing DEBUG-only preview file, and remoteWorkspaceGroupID has production RPC callers.
Cmux No Ambient Global State ✅ Passed The diff adds no global mutable state, singleton, or free-function API. New behavior is on existing types; SecondaryWorkspaceSnapshot is a constructable data model, and defaultsKey is a static cons...
Title check ✅ Passed The title clearly identifies the primary fix for grouped workspaces in All Computers.
Description check ✅ Passed The description explains the changes and testing, but it omits the template checklist and demo video section.
✨ Finishing Touches 💡 1
📝 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-all-computers-groups

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceGroupCollapseStore.swift`:
- Around line 77-84: Update the migration logic around the owner-scoped group
handling to migrate a legacy raw rpcGroupID key only when exactly one live group
matches that ID. When multiple owners match, remove or ignore the ambiguous
legacy key and preserve each group’s existing isCollapsed value; also fail
closed when authoritative identity is unavailable. Add a regression test
covering duplicate rpcGroupID values during upgrade.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 88092490-815f-4665-934b-1a4ea6d7d5f8

📥 Commits

Reviewing files that changed from the base of the PR and between 7693b19 and cc142b8.

📒 Files selected for processing (17)
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+SecondaryPromotion.swift
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+WorkspaceActions.swift
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+WorkspaceCreateRequest.swift
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/SecondaryWorkspaceFetchAttempt.swift
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/SecondaryWorkspaceSnapshot.swift
  • Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/MobileShellWorkspaceCapabilityTests.swift
  • Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceAggregation.swift
  • Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceGroupCollapseStore.swift
  • Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceGroupPreview.swift
  • Packages/iOS/CmuxMobileShellModel/Tests/CmuxMobileShellModelTests/MobileWorkspaceAggregationTests.swift
  • Packages/iOS/CmuxMobileShellModel/Tests/CmuxMobileShellModelTests/MobileWorkspaceGroupCollapseStoreTests.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView+DragDrop.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView+MacSelection.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceMacSelectionScope.swift
  • Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceMacSelectionTests.swift

@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceAggregation.swift (1)

126-132: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Build group membership from the same IDs used by headers.

derivedWorkspaces scopes workspace.groupID, but derivedGroups scopes the header with group.remoteGroupID ?? group.id. When those values differ, MobileWorkspaceListItem.items cannot find the workspace’s group in its lookup table, so the grouped list breaks down in larger Mac-local groupings. Use one source-of-truth group key for both workspaces and groups, or update the derived group header to the same RPC/local ID that member workspaces reference. Also add a coverage case where MobileWorkspaceGroupPreview.id and remoteGroupID differ.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceAggregation.swift`
around lines 126 - 132, The workspace membership key in
MobileWorkspaceAggregation must match the group header key used by
derivedGroups: align workspace.groupID and the group.remoteGroupID ?? group.id
source-of-truth so MobileWorkspaceListItem.items can resolve memberships. Update
MobileWorkspaceAggregation.swift lines 126-132 accordingly, and add coverage in
MobileWorkspaceAggregationTests.swift lines 214-275 where
MobileWorkspaceGroupPreview.id differs from remoteGroupID.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceAggregation.swift`:
- Around line 126-132: The workspace membership key in
MobileWorkspaceAggregation must match the group header key used by
derivedGroups: align workspace.groupID and the group.remoteGroupID ?? group.id
source-of-truth so MobileWorkspaceListItem.items can resolve memberships. Update
MobileWorkspaceAggregation.swift lines 126-132 accordingly, and add coverage in
MobileWorkspaceAggregationTests.swift lines 214-275 where
MobileWorkspaceGroupPreview.id differs from remoteGroupID.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5a0f0d60-ffaa-4cb1-8c56-c475d0f51d6f

📥 Commits

Reviewing files that changed from the base of the PR and between 548db3e and beea291.

📒 Files selected for processing (5)
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift
  • Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceAggregation.swift
  • Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceGroupCollapseStore.swift
  • Packages/iOS/CmuxMobileShellModel/Tests/CmuxMobileShellModelTests/MobileWorkspaceAggregationTests.swift
  • Packages/iOS/CmuxMobileShellModel/Tests/CmuxMobileShellModelTests/MobileWorkspaceGroupCollapseStoreTests.swift

@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ios/cmuxUITests/cmuxUITests.swift`:
- Around line 347-372: Strengthen
testWorkspaceGroupsStayVisibleForAllComputersAcrossMultipleMacs by selecting and
asserting the All Computers scope explicitly, then verify each group and anchor
workspace through authoritative structured Mac/instance identifiers:
seed-group-0 under preview-macbook-pro/nightly and seed-group-1 under
preview-studio/stable. Keep the screenshot capture after these ownership
assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cb57cfc3-7983-48b9-9cc2-300fb18fa9ab

📥 Commits

Reviewing files that changed from the base of the PR and between beea291 and 5c4587f.

📒 Files selected for processing (2)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListLayoutPreviewView.swift
  • ios/cmuxUITests/cmuxUITests.swift

Comment thread ios/cmuxUITests/cmuxUITests.swift
@azooz2003-bit
azooz2003-bit merged commit e1a59bd into main Aug 6, 2026
12 checks passed
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