Repository navigation
Fix Hive viewer lifecycle, replay identity, and shared-package integration - #8027
austinywang wants to merge 118 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds macOS Hive support for discovering and pairing computers, viewing remote workspaces and terminals, rendering terminal input/output, exposing a Computers settings section, and wiring services, windows, packages, localization, and tests. ChangesHive computer discovery and pairing
Remote viewer and terminal
Settings and application integration
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Settings as Computers Settings
participant Directory as HiveComputerDirectory
participant Registry as Device Registry
participant Store as Paired Store
participant Presence as Presence Client
Settings->>Directory: refresh()
Directory->>Registry: list devices
Directory->>Store: load paired records
Directory->>Presence: subscribe updates
Directory-->>Settings: merged computer snapshots
sequenceDiagram
participant Settings as Computers Settings
participant Window as HiveViewerWindowController
participant MacSession as HiveRemoteMacSession
participant Terminal as HiveRemoteTerminalSession
participant RemoteMac as Remote Mac
Settings->>Window: show(deviceID:)
Window->>MacSession: create viewer session
MacSession->>RemoteMac: connect and request workspaces
RemoteMac-->>MacSession: workspace list and updates
MacSession->>Terminal: create terminal session
Terminal->>RemoteMac: replay and subscribe render grid
RemoteMac-->>Terminal: render_grid frames
Terminal->>RemoteMac: terminal input
Possibly related issues
Possibly related PRs
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (13 errors, 1 warning)
✅ Passed checks (11 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR adds a macOS viewer for paired remote computers. The main changes are:
Confidence Score: 5/5The latest updates do not add a separate blocking issue.
Important Files Changed
Reviews (10): Last reviewed commit: "Computers: bordered style for the row Op..." | Re-trigger Greptile |
3f4fcfd to
ba4166f
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Actionable comments posted: 15
🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveComputerDirectory.swift`:
- Around line 104-110: Update the listener and live-stream lifecycle handling
around removeListener(id:) and the referenced stream failure/cancellation paths
so loss of authoritative presence resets or expires presenceMap and rebuilds
computer rows with .unknown(...). Perform this invalidation before cancelling or
retrying presenceTask, including subscription failures and EOF, while preserving
normal live updates when the stream remains authoritative.
- Around line 277-280: Update the presence-update flow around the stream loop
and rebuild-related methods to avoid calling rebuild() with a full registry scan
and sort for every frame. Maintain device-ID-indexed row state, update only the
computers affected by each presence update, and publish a coalesced snapshot;
alternatively compute the immutable snapshot off the main actor before
publishing. Preserve existing presenceMap.apply(update) behavior and ensure the
affected-row updates remain consistent with paired records and instance
summaries.
- Around line 117-133: Bind each refresh and pairing flow in
HiveComputerDirectory to one authoritative account scope. Update refresh() to
record the scope owning computers and discard results when the scope changes,
rather than publishing stale data. Update pair(link:) and persistPairing to
reuse the validated scope instead of fetching a new one; registry-row pairing
must fail closed or refresh when its snapshot scope is no longer current.
In `@Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swift`:
- Around line 150-152: Update the `.failed(message:)` assignment in
`HiveRemoteMacSession` to remove the raw
`lastError.map(String.init(describing:))` fallback. Preserve the localized
`MobileShellConnectionError` description, but use the existing generic localized
fallback (such as `Self.noRouteMessage`) for all other errors so upstream
details are not exposed.
- Around line 89-153: Update disconnect() to capture and cancel connectTask,
then await that task’s completion before cancelling eventTask and clearing
client/state. Preserve the existing teardown order after the awaited connection
task so any runConnect() completion, including event-loop startup, is cleaned up
before disconnect() returns.
In `@Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift`:
- Around line 149-154: The terminal.render_grid frame loop must avoid decoding
JSON on the MainActor and repeatedly allocating decoders. In
Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift#L149-L154,
dispatch payload decoding through await Task.detached {
Self.decodeFrame(payload) }.value before applying the frame; in `#L178-L185`, mark
decodeFrame nonisolated and add a private static sharedDecoder reused for
decoding instead of creating JSONDecoder inline.
In `@Packages/macOS/CmuxHive/Sources/CmuxHive/HiveTerminalGridModel.swift`:
- Around line 84-88: Update the row-clearing logic in the frame rendering loop
to call removeAll(keepingCapacity: true) on each existing rowSpans[row] array
instead of assigning an empty array, preserving capacity for subsequent span
appends.
In
`@Packages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveComputerDirectoryTests.swift`:
- Around line 227-235: Update the failure-path test around makeDirectory and
refresh to use one directory with a scripted registry that returns .ok first and
.transientFailure second. Refresh successfully to populate registry rows,
refresh again after the transient failure, and assert lastRefreshFailed is set
while the previously fetched rows remain available instead of expecting
computers to be empty.
- Around line 179-183: Update the persisted-record assertions in the directory
pairing tests, including the additional assertions around the unpairing case, to
load records with stackUserID “user-1” and teamID “team-1” instead of nil
values. Keep the existing emptiness expectations and ensure they query the same
account scope used by directory.pair and unpair operations.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift`:
- Around line 20-32: Update HiveTerminalGridView.body to remove the outer
GeometryReader and construct HiveTerminalGridMetrics inside the Canvas renderer
using Canvas’s provided CGSize parameter instead of proxy.size. Preserve the
existing grid columns, rows, drawing call, and background behavior.
- Around line 152-167: Cache the reference font metrics used by
HiveTerminalGridMetrics.init—referenceAdvance and referenceLineHeight, along
with the fixed referenceSize—at type or module scope so NSFont and
NSLayoutManager are created only once. Update the initializer’s widthLimited,
heightLimited, cellWidth, and lineHeight calculations to reuse those cached
values while preserving the existing sizing bounds and scaling behavior.
- Around line 1-3: Add the AppKit import to HiveTerminalGridView.swift so the
NSFont and NSLayoutManager references used by the view resolve correctly, while
leaving the existing CmuxHive, CMUXMobileCore, and SwiftUI imports unchanged.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift`:
- Around line 59-89: Refactor HiveViewerRootView so detail rendering only looks
up an existing terminal session and never mutates terminalSessions during body
evaluation. Split terminalSession(for:) into a read-only lookup and a creation
method, then trigger creation from selection changes using the appropriate
SwiftUI lifecycle callback while preserving the existing client guard and
session configuration.
In `@Sources/Hive/HiveComputersService.swift`:
- Around line 39-42: Replace the NSLog call in the HiveComputersService error
handler with the project’s existing os.Logger-based logging approach, preserving
the error details and message context. Add the OSLog import if required, and do
not introduce additional ad hoc logging.
In `@Sources/Hive/HiveViewerWindowController.swift`:
- Around line 51-55: Update presentWindow(deviceID:session:) so that when
viewersByDeviceID already contains an existing viewer, it disconnects the
redundant session before bringing the existing window forward and returning.
🪄 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
Run ID: 7674508f-bd3b-4a21-b604-77f362fb83ef
⛔ Files ignored due to path filters (1)
cmux.xcworkspace/contents.xcworkspacedatais excluded by!**/*.xcworkspace/contents.xcworkspacedata
📒 Files selected for processing (48)
Packages/macOS/CmuxHive/Package.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveAccountScope.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveComputer.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveComputerDirectory.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveComputerInstance.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveComputerPresence.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HivePairOutcome.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HivePairingLinkDecoder.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveReconnectBackoff.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteWorkspace.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveSyncRuntime.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveTerminalGridModel.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveComputerDirectoryTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HivePairingLinkDecoderTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveRemoteSessionTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveTerminalGridModelTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/ScriptedHostTransport.swiftPackages/macOS/CmuxHiveUI/Package.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalColor.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalInputView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalKeyMapping.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerWorkspaceList.swiftPackages/macOS/CmuxHiveUI/Tests/CmuxHiveUITests/HiveTerminalKeyMappingTests.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Bindings/ComputersListModel.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Bindings/SettingObservationStarting.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Environment/ComputersSettingsSnapshot.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Environment/SettingsHostActions.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Navigation/SettingsSectionID.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Scene/SettingsWindowScene.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/ComputersSection.swiftResources/Localizable.xcstringsSources/AppDelegate+CloudClients.swiftSources/AppDelegate.swiftSources/CmuxAuxiliaryWindows.swiftSources/Hive/HiveComputersService.swiftSources/Hive/HiveViewerWindowController.swiftSources/HostSettingsActions+Computers.swiftSources/Mobile/Pairing/MobilePairingWindowController.swiftSources/SettingsNavigation.swiftSources/SettingsNavigationTarget+SearchText.swiftSources/SettingsSearchAliases.swiftSources/cmuxApp.swiftcmux.xcodeproj/project.pbxproj
💤 Files with no reviewable changes (1)
- Sources/cmuxApp.swift
Bugbot is paused — on-demand spend limit reachedBugbot 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. |
ae25654 to
19440d2
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (6)
Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swift (2)
89-99: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
disconnect()still doesn't synchronize with an in-flightrunConnect()— unresolved from prior review.
disconnect()cancelsconnectTaskwithout awaiting it.runConnect()(lines 124-149) only checksTask.isCancelledat the top of the route loop, not afterfetchWorkspaces(line 138) resumes successfully. Ifdisconnect()runs whilerunConnect()is suspended there, the resumed task can still setclient,workspaces,phase = .connected, and start a brand-neweventTaskafter the session was told to disconnect — leaving a live socket/poll loop running on a session the app believes is idle.🔒 Proposed fix
public func disconnect() async { connectTask?.cancel() + await connectTask?.value connectTask = nil eventTask?.cancel() eventTask = nil if let client { await client.disconnect() } client = nil phase = .idle }🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swift` around lines 89 - 99, Update disconnect() and the runConnect() flow so disconnect awaits completion of any in-flight connectTask before clearing the client and setting phase to .idle. Ensure runConnect() rechecks cancellation after fetchWorkspaces resumes and before publishing client/workspaces, transitioning to .connected, or starting eventTask, preventing connection state from being installed after disconnect.
150-152: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winFailure message still leaks raw upstream error text — unresolved from prior review.
The
lastError.map(String.init(describing:))fallback prints whatever rawErrorwas thrown (socket/decoding/internal detail) into the user-visible.failed(message:)string, which flows straight intoHiveViewerRootView'sContentUnavailableViewdescription.As per coding guidelines: "User-facing errors, alerts, ... must not expose ... raw upstream messages, identifiers, credentials, tokens, headers, private keys, session IDs, or unredacted payloads."🛡️ Proposed fix
- phase = .failed(message: (lastError as? MobileShellConnectionError)?.localizedDescription - ?? lastError.map(String.init(describing:)) - ?? Self.noRouteMessage) + phase = .failed(message: (lastError as? MobileShellConnectionError)?.localizedDescription + ?? Self.noRouteMessage)🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swift` around lines 150 - 152, Update the failure-message construction in the session failure path to remove the raw lastError String(describing:) fallback. Expose only MobileShellConnectionError.localizedDescription when it is safe and otherwise use Self.noRouteMessage, ensuring .failed(message:) never receives unredacted upstream error details.Source: Coding guidelines
Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift (1)
59-89: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winTerminal session creation still mutates
@Statefrom a helper called duringbodyevaluation — unresolved from prior review.
terminalSession(for:)is invoked fromdetail(part ofbody) and writes intoterminalSessions(line 87) as a side effect of rendering, which SwiftUI can flag as undefined behavior ("Modifying state during view update").As per coding guidelines: "Do not mutate state from `body` or helpers called by `body`... use lifecycle callbacks, model observers, reload completions, or event handlers instead."♻️ Proposed refactor
public var body: some View { NavigationSplitView { HiveViewerWorkspaceList( workspaces: session.workspaces, selection: $selection ) .navigationSplitViewColumnWidth(min: 180, ideal: 230) } detail: { detail } .navigationTitle(session.displayName) .onAppear { session.connect() } .onChange(of: session.workspaces) { _, workspaces in reconcileSelection(workspaces: workspaces) } + .onChange(of: selection) { _, newSelection in + ensureTerminalSession(for: newSelection) + } .task { reconcileSelection(workspaces: session.workspaces) + ensureTerminalSession(for: selection) } } ... - private func terminalSession(for selection: HiveViewerSelection) -> HiveRemoteTerminalSession? { - if let existing = terminalSessions[selection] { return existing } - guard let client = session.client else { return nil } - let terminal = HiveRemoteTerminalSession( - client: client, - workspaceID: selection.workspaceID, - terminalID: selection.terminalID, - retryDelay: HiveReconnectBackoff().delay(attempt:) - ) - terminalSessions[selection] = terminal - return terminal - } + private func terminalSession(for selection: HiveViewerSelection?) -> HiveRemoteTerminalSession? { + guard let selection else { return nil } + return terminalSessions[selection] + } + + private func ensureTerminalSession(for selection: HiveViewerSelection?) { + guard let selection, terminalSessions[selection] == nil, + let client = session.client else { return } + terminalSessions[selection] = HiveRemoteTerminalSession( + client: client, + workspaceID: selection.workspaceID, + terminalID: selection.terminalID, + retryDelay: HiveReconnectBackoff().delay(attempt:) + ) + }🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift` around lines 59 - 89, Remove the terminalSessions mutation from terminalSession(for:) when it is called during detail/body evaluation. Refactor session creation and caching into a lifecycle callback, model observer, reload completion, or event handler, then have terminalSession(for:) only read and return an existing session; preserve the existing client, workspace, terminal, and retry configuration.Source: Coding guidelines
Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift (3)
1-4: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueImport
AppKitexplicitly.
NSFontandNSLayoutManagerare used in this file. Please explicitly importAppKitto ensure these references resolve correctly, rather than relying on transitive imports.♻️ Proposed refactor
public import CmuxHive import CMUXMobileCore public import SwiftUI +public import AppKit🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift` around lines 1 - 4, Update the imports in HiveTerminalGridView to explicitly include AppKit, ensuring the NSFont and NSLayoutManager references resolve directly while preserving the existing imports.
20-32: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winDrop the outer
GeometryReader; useCanvas's own size parameter.
Canvas's renderer closure already receives(inout GraphicsContext, CGSize)— the size parameter here is discarded (_) whileproxy.sizefrom a wrappingGeometryReaderis used instead. TheGeometryReaderis redundant and adds an avoidable layout indirection. As per coding guidelines, avoidGeometryReaderwhen localized background measurement or intrinsic alternatives exist.♻️ Proposed refactor
public var body: some View { - GeometryReader { proxy in - let metrics = HiveTerminalGridMetrics( - columns: grid.columns, - rows: grid.rows, - available: proxy.size - ) - Canvas { context, _ in - draw(in: &context, metrics: metrics) - } - } + Canvas { context, size in + let metrics = HiveTerminalGridMetrics( + columns: grid.columns, + rows: grid.rows, + available: size + ) + draw(in: &context, metrics: metrics) + } .background(HiveTerminalColor.parse(grid.terminalBackground) ?? HiveTerminalColor.fallbackBackground) }🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift` around lines 20 - 32, Remove the outer GeometryReader from HiveTerminalGridView.body and use the Canvas renderer’s CGSize parameter when constructing HiveTerminalGridMetrics. Keep the existing grid columns, rows, drawing call, and background behavior unchanged.Source: Coding guidelines
152-167: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winHoist the reference font measurement out of the per-render init.
referenceFont,referenceAdvance, andreferenceLineHeightonly depend on the constantreferenceSize, yet they're recomputed (including anNSFontallocation and anNSLayoutManager()instantiation) every timeHiveTerminalGridMetricsis built — which happens on every streamed grid update, a rendering hot path. Cache these once and reuse them for the per-call scaling math.♻️ Proposed refactor
let cellWidth: CGFloat let lineHeight: CGFloat let fontSize: CGFloat + + private static let referenceSize: CGFloat = 13 + private static let referenceFont = NSFont.monospacedSystemFont(ofSize: referenceSize, weight: .regular) + private static let referenceAdvance = ("0" as NSString).size(withAttributes: [.font: referenceFont]).width + private static let referenceLineHeight = NSLayoutManager().defaultLineHeight(for: referenceFont) init(columns: Int, rows: Int, available: CGSize) { let columns = max(columns, 1) let rows = max(rows, 1) - // Measure the reference font once; monospaced advances scale linearly - // with point size, so one measurement fits any target size. - let referenceSize: CGFloat = 13 - let referenceFont = NSFont.monospacedSystemFont(ofSize: referenceSize, weight: .regular) - let referenceAdvance = ("0" as NSString).size(withAttributes: [.font: referenceFont]).width - let referenceLineHeight = NSLayoutManager().defaultLineHeight(for: referenceFont) - let widthLimited = available.width / (CGFloat(columns) * referenceAdvance / referenceSize) - let heightLimited = available.height / (CGFloat(rows) * referenceLineHeight / referenceSize) + let sizeFactor = Self.referenceSize + let advance = Self.referenceAdvance + let refLineHeight = Self.referenceLineHeight + let widthLimited = available.width / (CGFloat(columns) * advance / sizeFactor) + let heightLimited = available.height / (CGFloat(rows) * refLineHeight / sizeFactor) - let size = max(min(widthLimited, heightLimited, 20), 4) + let size = max(min(widthLimited, heightLimited, 20), 4) fontSize = size - cellWidth = referenceAdvance * size / referenceSize + cellWidth = advance * size / sizeFactor - lineHeight = referenceLineHeight * size / referenceSize + lineHeight = refLineHeight * size / sizeFactor }🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift` around lines 152 - 167, Move the constant reference font metrics used by HiveTerminalGridMetrics.init(columns:rows:available:) into shared cached static properties, including referenceAdvance and referenceLineHeight, so NSFont and NSLayoutManager are created once. Update the initializer to reuse those cached values for its per-call scaling calculations while preserving the existing sizing and clamping behavior.
🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalInputView.swift`:
- Around line 49-54: Remove the unconditional first-responder assignment from
updateNSView in HiveTerminalInputView; keep updating nsView.actions, but let the
existing mouseDown interaction or a dedicated focus model control terminal focus
instead of using isFocused during SwiftUI render updates.
In
`@Packages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/ComputersSection.swift`:
- Around line 308-314: Update the “Open” Button in the computer row to apply the
existing isPending state via .disabled(isPending), matching the Pair and Unpair
controls and preventing actions while unpairing is in progress.
---
Duplicate comments:
In `@Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swift`:
- Around line 89-99: Update disconnect() and the runConnect() flow so disconnect
awaits completion of any in-flight connectTask before clearing the client and
setting phase to .idle. Ensure runConnect() rechecks cancellation after
fetchWorkspaces resumes and before publishing client/workspaces, transitioning
to .connected, or starting eventTask, preventing connection state from being
installed after disconnect.
- Around line 150-152: Update the failure-message construction in the session
failure path to remove the raw lastError String(describing:) fallback. Expose
only MobileShellConnectionError.localizedDescription when it is safe and
otherwise use Self.noRouteMessage, ensuring .failed(message:) never receives
unredacted upstream error details.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift`:
- Around line 1-4: Update the imports in HiveTerminalGridView to explicitly
include AppKit, ensuring the NSFont and NSLayoutManager references resolve
directly while preserving the existing imports.
- Around line 20-32: Remove the outer GeometryReader from
HiveTerminalGridView.body and use the Canvas renderer’s CGSize parameter when
constructing HiveTerminalGridMetrics. Keep the existing grid columns, rows,
drawing call, and background behavior unchanged.
- Around line 152-167: Move the constant reference font metrics used by
HiveTerminalGridMetrics.init(columns:rows:available:) into shared cached static
properties, including referenceAdvance and referenceLineHeight, so NSFont and
NSLayoutManager are created once. Update the initializer to reuse those cached
values for its per-call scaling calculations while preserving the existing
sizing and clamping behavior.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift`:
- Around line 59-89: Remove the terminalSessions mutation from
terminalSession(for:) when it is called during detail/body evaluation. Refactor
session creation and caching into a lifecycle callback, model observer, reload
completion, or event handler, then have terminalSession(for:) only read and
return an existing session; preserve the existing client, workspace, terminal,
and retry configuration.
🪄 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
Run ID: 18b2f6a8-29de-4ec1-a35b-5a32f39e8e61
⛔ Files ignored due to path filters (1)
cmux.xcworkspace/contents.xcworkspacedatais excluded by!**/*.xcworkspace/contents.xcworkspacedata
📒 Files selected for processing (35)
.github/review-bot-rules/swift-auxiliary-window-close-shortcuts.mdPackages/macOS/CmuxHive/Package.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveComposition.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveComputer.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveComputerDirectory.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveReconnectBackoff.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteWorkspace.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveSyncRuntime.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveTerminalGridModel.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveRemoteSessionTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveTerminalGridModelTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/ScriptedHostTransport.swiftPackages/macOS/CmuxHiveUI/Package.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalColor.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalInputView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalKeyMapping.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerWorkspaceList.swiftPackages/macOS/CmuxHiveUI/Tests/CmuxHiveUITests/HiveTerminalKeyMappingTests.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Environment/SettingsHostActions.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/ComputersSection.swiftResources/Localizable.xcstringsSources/CmuxAuxiliaryWindows.swiftSources/Hive/HiveComputersService.swiftSources/Hive/HiveViewerWindowController.swiftSources/HostSettingsActions+Computers.swiftSources/Mobile/Pairing/MobilePairingWindowController.swiftSources/cmuxApp.swiftcmux.xcodeproj/project.pbxprojscripts/lint_auxiliary_window_close_shortcuts.pytests/test_ci_auxiliary_window_close_shortcuts.sh
💤 Files with no reviewable changes (1)
- Sources/cmuxApp.swift
19440d2 to
4f0f897
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Packages/macOS/CmuxHive/Package.swift (1)
1-59: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winInclude the
Package.resolvedlockfile in the PR diff.The PR introduces new Swift packages (
CmuxHive) and updates package references, but the root XcodePackage.resolved(atcmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved) is missing from the PR stack. As per path instructions, whenever Swift package references change viaPackage.swiftorxcodeproj, the corresponding lockfile must be committed to ensure no unexpected pin changes are hidden.🤖 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/macOS/CmuxHive/Package.swift` around lines 1 - 59, Add the root Xcode SwiftPM lockfile at cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved to the PR, regenerated after the dependency changes in the CmuxHive Package.swift manifest. Ensure it records the resolved revisions for all referenced packages without making unrelated dependency updates.Source: Path instructions
♻️ Duplicate comments (1)
Sources/Hive/HiveViewerWindowController.swift (1)
51-55: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winDisconnect the duplicate session to prevent resource leaks.
If
show(deviceID:)is called rapidly in succession (e.g., from a double-click), multipleHiveRemoteMacSessioninstances will be created concurrently. WhenpresentWindowprocesses the subsequent calls, it finds the existing window and returns early, which abandons the redundantsessionwithout calling itsdisconnect()method. This leaks the underlying network connections and tasks.♻️ Proposed fix
private func presentWindow(deviceID: String, session: HiveRemoteMacSession) { if let existing = viewersByDeviceID[deviceID] { existing.window.makeKeyAndOrderFront(nil) + Task { `@MainActor` in + await session.disconnect() + } return }🤖 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 `@Sources/Hive/HiveViewerWindowController.swift` around lines 51 - 55, Update presentWindow(deviceID:session:) so that when viewersByDeviceID[deviceID] already contains a viewer, the incoming duplicate session is disconnected before returning; preserve the existing window activation behavior.
🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift`:
- Around line 171-175: Validate the decoded replay response’s workspace and
surface IDs against the active session before processing renderGrid in the
MobileTerminalReplayResponse path. Reject mismatched responses and only call
grid.apply(frame) when both identities match the current terminal session,
preserving input targeting through terminalID.
In `@Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteWorkspace.swift`:
- Around line 4-42: Mark the pure value-model types as nonisolated: add it to
HiveRemoteWorkspace and its nested Terminal in
Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteWorkspace.swift (lines 4-42),
HiveTerminalGridModel in
Packages/macOS/CmuxHive/Sources/CmuxHive/HiveTerminalGridModel.swift (line 16),
and HiveViewerSelection in
Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift (lines
109-119). Preserve their existing Sendable, Identifiable, and value-model
behavior.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swift`:
- Around line 17-24: Update the HiveTerminalInputView configuration in
HiveRemoteTerminalPane so input focus is enabled only when terminal.phase equals
.live, and remains disabled for attaching, reattaching, or any other unavailable
state. Use the typed lifecycle state directly and fail closed when a reliable
live signal is absent.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift`:
- Line 12: Update HiveViewerRootView’s workspaces reconciliation flow, including
reconcileSelection and the terminalSessions update path, to identify cached
sessions whose workspaceID/terminalID no longer exists in the live workspaces
and call each session’s detach() before removing its dictionary entry. Preserve
existing selection redirection and retain sessions that still correspond to live
terminals.
---
Outside diff comments:
In `@Packages/macOS/CmuxHive/Package.swift`:
- Around line 1-59: Add the root Xcode SwiftPM lockfile at
cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved to the
PR, regenerated after the dependency changes in the CmuxHive Package.swift
manifest. Ensure it records the resolved revisions for all referenced packages
without making unrelated dependency updates.
---
Duplicate comments:
In `@Sources/Hive/HiveViewerWindowController.swift`:
- Around line 51-55: Update presentWindow(deviceID:session:) so that when
viewersByDeviceID[deviceID] already contains a viewer, the incoming duplicate
session is disconnected before returning; preserve the existing window
activation behavior.
🪄 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
Run ID: dd9e7ab1-06cf-4b35-a610-4c1e1f275879
⛔ Files ignored due to path filters (1)
cmux.xcworkspace/contents.xcworkspacedatais excluded by!**/*.xcworkspace/contents.xcworkspacedata
📒 Files selected for processing (31)
.github/review-bot-rules/swift-auxiliary-window-close-shortcuts.mdPackages/macOS/CmuxHive/Package.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteWorkspace.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveSyncRuntime.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveTerminalGridModel.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveRemoteSessionTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveTerminalGridModelTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/ScriptedHostTransport.swiftPackages/macOS/CmuxHiveUI/Package.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalColor.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalInputView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalKeyMapping.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerWorkspaceList.swiftPackages/macOS/CmuxHiveUI/Tests/CmuxHiveUITests/HiveTerminalKeyMappingTests.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Environment/SettingsHostActions.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/ComputersSection.swiftResources/Localizable.xcstringsSources/CmuxAuxiliaryWindows.swiftSources/Hive/HiveComputersService.swiftSources/Hive/HiveViewerWindowController.swiftSources/HostSettingsActions+Computers.swiftSources/Mobile/Pairing/MobilePairingWindowController.swiftSources/cmuxApp.swiftcmux.xcodeproj/project.pbxprojscripts/lint_auxiliary_window_close_shortcuts.pytests/test_ci_auxiliary_window_close_shortcuts.sh
💤 Files with no reviewable changes (1)
- Sources/cmuxApp.swift
4f0f897 to
df779de
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (7)
Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift (3)
20-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRedundant
GeometryReaderwrappingCanvas.
Canvas's renderer closure already receives(inout GraphicsContext, CGSize); the parameter is discarded (_) whileproxy.sizefrom the outerGeometryReaderis used instead, adding an avoidable layout indirection — unchanged from the prior round.♻️ Proposed refactor
public var body: some View { - GeometryReader { proxy in - let metrics = HiveTerminalGridMetrics( - columns: grid.columns, - rows: grid.rows, - available: proxy.size - ) - Canvas { context, _ in - draw(in: &context, metrics: metrics) - } - } + Canvas { context, size in + let metrics = HiveTerminalGridMetrics( + columns: grid.columns, + rows: grid.rows, + available: size + ) + draw(in: &context, metrics: metrics) + } .background(HiveTerminalColor.parse(grid.terminalBackground) ?? HiveTerminalColor.fallbackBackground) }🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift` around lines 20 - 32, Remove the outer GeometryReader from HiveTerminalGridView.body and use Canvas’s renderer CGSize parameter when constructing HiveTerminalGridMetrics.available. Preserve the existing grid columns, rows, draw call, and background behavior while eliminating the discarded renderer size and redundant layout wrapper.
1-3: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
NSFont/NSLayoutManagerused without anAppKitimport.This file only imports
CmuxHive,CMUXMobileCore, andSwiftUI, yetNSFont.monospacedSystemFont(line 158) andNSLayoutManager()(line 160) are AppKit types.SwiftUIdoes not re-export AppKit types on macOS. A prior review round flagged this exact gap and marked it resolved in a later commit, but the current final file still lacks the import — please confirm this compiles, or addimport AppKit.#!/bin/bash rg -n '^(public )?import AppKit' Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift rg -n '_exported import AppKit' Packages/macOS/CmuxHiveUI Packages/Shared 2>/dev/nullAlso applies to: 158-158, 160-160
🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift` around lines 1 - 3, Add an explicit AppKit import to HiveTerminalGridView alongside its existing imports so the NSFont and NSLayoutManager references compile on macOS; do not rely on SwiftUI re-exporting AppKit.
152-167: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winReference font measurement recomputed on every render.
referenceFont/referenceAdvance/referenceLineHeightonly depend on the constantreferenceSizebut are recomputed — including anNSFontallocation and anNSLayoutManager()instantiation — on everyHiveTerminalGridMetricsinit, which happens on each streamed grid update (a rendering hot path). Cache these once at type scope.As per coding guidelines: "Do not allocate
NumberFormatter,DateFormatter... or similar formatters per call inside loops, row bodies, or concurrent maps; allocate once and reuse."🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift` around lines 152 - 167, Cache the constant reference font metrics used by HiveTerminalGridMetrics.init at type scope, including referenceAdvance and referenceLineHeight (and the reference font if needed), so they are computed once rather than per initialization. Update init to reuse those cached values while preserving the existing size, cellWidth, and lineHeight calculations.Source: Coding guidelines
Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift (2)
163-176: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winReplay path applies frames without validating workspace/surface identity.
requestReplay()decodesMobileTerminalReplayResponseand callsgrid.apply(frame)unconditionally. If the replay payload carries workspace/surface identity, a stale or misrouted response could paint the wrong terminal's grid while input still targetsterminalID. Reject replays whose IDs don't matchworkspaceID/terminalIDbefore applying. Unchanged from the prior round.As per path instructions, correctness-critical workspace/surface identity must be validated against a single authoritative source rather than trusted implicitly.
🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift` around lines 163 - 176, Update requestReplay() to validate the decoded MobileTerminalReplayResponse workspace and surface identifiers against the authoritative workspaceID and terminalID before calling grid.apply(frame). Reject or ignore mismatched replay responses, and only apply the frame when both identities match.Source: Path instructions
149-154: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick winJSON frame decoding still runs on the
@MainActorwith a per-callJSONDecoder.
decodeFrameis a static member of this@MainActorclass, so decodingterminal.render_gridpayloads (line 151) happens on the main actor for every streamed frame — a latency-sensitive path — and allocates a newJSONDecoder()each call (line 184) instead of reusing one. Unchanged from the prior round.As per coding guidelines: "flag changed CPU-heavy, file-I/O-heavy, parsing-heavy, or network-heavy async helpers called from UI isolation without an explicit actor hop."
🔧 Proposed fix
- static func decodeFrame(_ payload: Data) -> MobileTerminalRenderGridFrame? { + private static let sharedDecoder = JSONDecoder() + + nonisolated static func decodeFrame(_ payload: Data) -> MobileTerminalRenderGridFrame? { if let event = try? MobileTerminalRenderGridEvent.decode(payload), let frame = event.frame { return frame } - return try? JSONDecoder().decode(MobileTerminalRenderGridFrame.self, from: payload) + return try? sharedDecoder.decode(MobileTerminalRenderGridFrame.self, from: payload) }and at the call site:
- guard let payload = envelope.payloadJSON, - let frame = Self.decodeFrame(payload), + guard let payload = envelope.payloadJSON, + let frame = await Task.detached { Self.decodeFrame(payload) }.value, frame.surfaceID == terminalID else { continue }Also applies to: 178-185
🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift` around lines 149 - 154, Move terminal.render_grid frame decoding out of the `@MainActor` by making decodeFrame nonisolated and explicitly hopping to a background task or actor from the stream loop before decoding; keep UI updates through grid.apply on the main actor. Reuse a shared JSONDecoder instead of constructing one per decode call, updating decodeFrame and its call site while preserving frame filtering behavior.Source: Coding guidelines
Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swift (1)
17-24: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winInput stays enabled during
.attaching/.reattaching.
isFocused: trueis hardcoded regardless ofterminal.phase, so keystrokes can be captured/sent while the terminal isn't actually live. DriveisFocusedfromterminal.phase == .liveand fail closed otherwise.As per path instructions, correctness-critical input-route enable/disable must be driven by a single authoritative lifecycle source and fail closed when a reliable live signal is missing.
🔧 Proposed fix
HiveTerminalInputView( actions: HiveTerminalInputView.Actions( sendText: { [weak terminal] in terminal?.send(text: $0) }, sendSpecial: { [weak terminal] in terminal?.send(specialKey: $0, modifiers: $1) }, sendControl: { [weak terminal] in terminal?.send(controlCharacter: $0) } ), - isFocused: true + isFocused: terminal.phase == .live )🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swift` around lines 17 - 24, Update the HiveTerminalInputView configuration in HiveRemoteTerminalPane so isFocused is derived from the authoritative terminal lifecycle state, enabling input only when terminal.phase == .live and returning false for every other phase, including attaching and reattaching.Source: Path instructions
Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift (1)
12-12: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winCached terminal sessions for vanished terminals are never detached.
terminalSessionsonly grows;reconcileSelectionredirectsselectionaway from a stale terminal/workspace but leaves that entry'sHiveRemoteTerminalSession(and its background attach/reconnect loop) running indefinitely in the dictionary, unreachable from the UI. Prune entries whose(workspaceID, terminalID)no longer exists whenworkspacesupdates, callingdetach()before removal.Also applies to: 78-107
🤖 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/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift` at line 12, Update reconcileSelection and the workspaces-update reconciliation flow to prune terminalSessions entries whose workspaceID/terminalID pair no longer exists in workspaces. Call detach() on each stale HiveRemoteTerminalSession before removing it from the dictionary, while preserving active sessions and existing selection redirection behavior.
🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swift`:
- Around line 172-185: Update fetchWorkspaces in HiveRemoteMacSession so the
request result decoding and complete workspace/terminal mapping run through a
nonisolated or `@concurrent` helper/off-main service rather than on MainActor.
Await that helper, then return or assign the fully constructed
[HiveRemoteWorkspace] value on the existing actor-isolated path.
In
`@Packages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveTerminalGridModelTests.swift`:
- Line 65: Update the test around the rowSpans style assertion to safely
validate that the collection contains the required second element before
indexing it. Ensure the style assertion can fail normally rather than trapping
when the earlier grid.rows expectation does not guarantee rowSpans.count.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalInputView.swift`:
- Around line 68-76: Update the paste condition in HiveTerminalInputView so it
matches plain Command+V only, rejecting additional Shift, Option, or Control
modifiers while preserving the existing pasteboard lookup and actions?.sendText
behavior.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift`:
- Line 41: Refactor terminal-session handling around detail and
terminalSession(for:) so view rendering only performs lookup and never mutates
terminalSessions. Move session creation into a state-change-driven path
triggered by selection changes or an appropriate .task, while preserving reuse
of existing sessions and ensuring the selected session is available before
detail renders.
- Around line 45-57: Replace the raw Text(message) rendering in the .failed case
of HiveViewerRootView with a product-facing sanitized failure string, avoiding
direct display of MobileShellConnectionError.localizedDescription or
HiveRemoteMacSession descriptions. Keep the existing retry action and
unavailable-content layout unchanged.
---
Duplicate comments:
In `@Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift`:
- Around line 163-176: Update requestReplay() to validate the decoded
MobileTerminalReplayResponse workspace and surface identifiers against the
authoritative workspaceID and terminalID before calling grid.apply(frame).
Reject or ignore mismatched replay responses, and only apply the frame when both
identities match.
- Around line 149-154: Move terminal.render_grid frame decoding out of the
`@MainActor` by making decodeFrame nonisolated and explicitly hopping to a
background task or actor from the stream loop before decoding; keep UI updates
through grid.apply on the main actor. Reuse a shared JSONDecoder instead of
constructing one per decode call, updating decodeFrame and its call site while
preserving frame filtering behavior.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swift`:
- Around line 17-24: Update the HiveTerminalInputView configuration in
HiveRemoteTerminalPane so isFocused is derived from the authoritative terminal
lifecycle state, enabling input only when terminal.phase == .live and returning
false for every other phase, including attaching and reattaching.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift`:
- Around line 20-32: Remove the outer GeometryReader from
HiveTerminalGridView.body and use Canvas’s renderer CGSize parameter when
constructing HiveTerminalGridMetrics.available. Preserve the existing grid
columns, rows, draw call, and background behavior while eliminating the
discarded renderer size and redundant layout wrapper.
- Around line 1-3: Add an explicit AppKit import to HiveTerminalGridView
alongside its existing imports so the NSFont and NSLayoutManager references
compile on macOS; do not rely on SwiftUI re-exporting AppKit.
- Around line 152-167: Cache the constant reference font metrics used by
HiveTerminalGridMetrics.init at type scope, including referenceAdvance and
referenceLineHeight (and the reference font if needed), so they are computed
once rather than per initialization. Update init to reuse those cached values
while preserving the existing size, cellWidth, and lineHeight calculations.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swift`:
- Line 12: Update reconcileSelection and the workspaces-update reconciliation
flow to prune terminalSessions entries whose workspaceID/terminalID pair no
longer exists in workspaces. Call detach() on each stale
HiveRemoteTerminalSession before removing it from the dictionary, while
preserving active sessions and existing selection redirection behavior.
🪄 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
Run ID: 5ba81097-da58-4355-a6fd-7997287d347f
⛔ Files ignored due to path filters (1)
cmux.xcworkspace/contents.xcworkspacedatais excluded by!**/*.xcworkspace/contents.xcworkspacedata
📒 Files selected for processing (33)
.github/review-bot-rules/swift-auxiliary-window-close-shortcuts.mdPackages/macOS/CmuxHive/Package.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveComposition.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteWorkspace.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveSyncRuntime.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveTerminalGridModel.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveRemoteSessionTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveTerminalGridModelTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/ScriptedHostTransport.swiftPackages/macOS/CmuxHiveUI/Package.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalColor.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalInputView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalKeyMapping.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerWorkspaceList.swiftPackages/macOS/CmuxHiveUI/Tests/CmuxHiveUITests/HiveTerminalKeyMappingTests.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Environment/ComputersSettingsSnapshot.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Environment/SettingsHostActions.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/ComputersSection.swiftResources/Localizable.xcstringsSources/CmuxAuxiliaryWindows.swiftSources/Hive/HiveComputersService.swiftSources/Hive/HiveViewerWindowController.swiftSources/HostSettingsActions+Computers.swiftSources/Mobile/Pairing/MobilePairingWindowController.swiftSources/cmuxApp.swiftcmux.xcodeproj/project.pbxprojscripts/lint_auxiliary_window_close_shortcuts.pytests/test_ci_auxiliary_window_close_shortcuts.sh
💤 Files with no reviewable changes (1)
- Sources/cmuxApp.swift
df779de to
ac672db
Compare
…airing Add the account-level device list and pairing half of hive M1 (the remote-workspace viewer follows in the next slice). - New Packages/macOS/CmuxHive: HiveComputerDirectory merges the team device registry (DeviceRegistryService), the local paired-computer store (MobilePairedMacStore in hive-paired-computers.sqlite3), and the presence worker stream (PresenceClient) into value-snapshot rows; HivePairingLinkDecoder applies the Mac-side loopback/account policy over the shared CmxAttachTicketInput grammar. 13 behavior tests. - Settings > Computers section in CmuxSettingsUI: presence indicator, one-click pair from a registry row, pairing-link paste (the macOS counterpart of the phone's QR scan), unpair, refresh, and a shortcut to the existing pairing window. - App wiring: HiveComputersService composition at the root (extracted configureCloudClients keeps AppDelegate.swift under budget), HostSettingsActions+Computers host bridge, settings navigation and search entries, EN+JA localization for all new strings. - Links the existing iOS client packages (already macOS-capable) into the macOS app through CmuxHive; iOS targets unchanged. Part of #8001 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…arget HiveComputersService.swift imports both modules directly, but only CmuxHive was a declared product dependency, so the linker did not reliably pull their static archives into the app dylib (undefined symbols for DeviceRegistryService / PresenceClient / MobilePairedMacStore on CI). Declare the products the app imports, on both the cmux and cmuxTests targets. Part of #8001 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…he app target" This reverts commit 509b1e3.
… CmuxHive The app-side HiveComputersService named DeviceRegistryService / PresenceClient / MobilePairedMacStore directly, which required declaring CmuxMobileShell and CmuxMobilePairedMac as app-target package products. That perturbed Xcode's package-product linkage graph: with the products declared, CmuxAgentChat symbols moved out of the app binary's exports and the cmuxTests bundle (which resolves them via bundle_loader) failed to link on CI; without them, HiveComputersService.o itself had undefined symbols. Fix the class of problem instead of the instance: a new HiveComposition factory inside CmuxHive names the concrete client-stack types, and the app's composition root supplies configuration only (URLs, token closures, device identity, loopback policy). The app target now imports and links nothing below CmuxHive, so the pre-existing app/test linkage graph is untouched (the product-dependency commit is reverted). Also: HiveReconnectBackoff (instantiable bounded backoff shared by the directory's presence resubscribe), and internal-import tightening that clears public-import warnings. Part of #8001 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adding CmuxHive (whose closure includes CmuxAgentChat via CmuxMobileShell) to both the app and test targets makes Xcode build CmuxAgentChat as part of a dynamic package framework instead of statically into the app binary, so the app stops exporting its symbols and the test bundle — which imports CmuxAgentChat but had no product dependency of its own, resolving via bundle_loader — fails to link (every undefined symbol on CI is a CmuxAgentChat one). Declare the product on cmuxTests like the other shared packages so the test bundle links it directly. Part of #8001 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The only way to pair Mac-to-Mac was "Show Pairing Code…", which opens the iPhone QR window — a Mac has no camera pointed at it. Add a Copy Pairing Link button to the Pair This Mac row: it mints the same attach payload the QR encodes (Tailscale-only v2 grammar; dev builds fall back to an all-routes ticket so two tagged builds on one machine can pair over loopback), puts it on the clipboard, and shows inline feedback. Paste it into "Add by Pairing Link" on the other Mac. Part of #8001 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mac-to-Mac pairing is the copy-link flow; the QR window is an iPhone concern and stays reachable from Settings > Mobile. Part of #8001 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cmux.xcodeproj/project.pbxproj (1)
8514-8523: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAdd the root Xcode lockfile for these package refs.
cmux.xcodeproj/project.pbxproj:8514-8523addsCmuxHiveandCmuxHiveUI, butcmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolvedis not in the diff. Commit that lockfile alongside the project change so package resolution stays consistent.🤖 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 `@cmux.xcodeproj/project.pbxproj` around lines 8514 - 8523, Commit the root Swift Package Manager lockfile alongside the new CmuxHive and CmuxHiveUI product dependencies. Update the workspace Package.resolved to record both local package references and their resolved dependencies, keeping it consistent with the XCSwiftPackageProductDependency entries in the project configuration.Source: Path instructions
♻️ Duplicate comments (1)
Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift (1)
171-175: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winReject incomplete or mismatched replay responses.
requestReplay()succeeds whenrenderGridis absent, after which the caller marks the session.livewith an empty grid and stops retrying. Require a full frame before returning, and retain the previously requested workspace/surface identity checks before applying it.🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift` around lines 171 - 175, Update requestReplay() to reject responses without renderGrid by treating them as failures so callers do not mark an empty session live. Before applying the frame, preserve and enforce the existing workspace and surface identity checks, and only return successfully after receiving a complete matching replay frame.
🤖 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/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift`:
- Around line 104-120: Replace the untracked Task in sendInput with a
session-owned, cancellable input worker that serializes requests in submission
order and is cancelled by detach(). Route all three terminal send APIs through
this worker, and update its failure handling so delivery errors are surfaced
through the session’s live-phase/error mechanism instead of being silently
discarded with try?.
In `@Packages/macOS/CmuxHive/Sources/CmuxHive/HiveTerminalGridModel.swift`:
- Around line 68-79: Update HiveTerminalGridModel.apply(_:) to track the latest
applied stateSeq and reject non-full frames whose frame.stateSeq is less than or
equal to the stored sequence. Continue accepting full frames regardless of
sequence so replay or host restarts can reset state, and update the stored
sequence whenever a frame is applied.
In `@Packages/macOS/CmuxHive/Tests/CmuxHiveTests/ScriptedHostTransport.swift`:
- Around line 78-84: Update ScriptedHostTransport’s killConnection() to set
isClosed = true before resuming current receiveWaiters, so connection
termination persists when no receiver is waiting. Preserve the existing waiter
cleanup and nil-resumption behavior; rely on connect() to clear isClosed during
reconnection.
In `@Packages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swift`:
- Around line 64-83: Update the span rendering flow around style.invisible so
background painting, including custom and inverse backgrounds, occurs before
concealed spans skip glyph rendering. Preserve the existing return behavior for
invisible text after the background rectangle is drawn.
---
Outside diff comments:
In `@cmux.xcodeproj/project.pbxproj`:
- Around line 8514-8523: Commit the root Swift Package Manager lockfile
alongside the new CmuxHive and CmuxHiveUI product dependencies. Update the
workspace Package.resolved to record both local package references and their
resolved dependencies, keeping it consistent with the
XCSwiftPackageProductDependency entries in the project configuration.
---
Duplicate comments:
In `@Packages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swift`:
- Around line 171-175: Update requestReplay() to reject responses without
renderGrid by treating them as failures so callers do not mark an empty session
live. Before applying the frame, preserve and enforce the existing workspace and
surface identity checks, and only return successfully after receiving a complete
matching replay frame.
🪄 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
Run ID: 90123b3a-d9c8-4f70-b9d0-b8fb52291668
⛔ Files ignored due to path filters (1)
cmux.xcworkspace/contents.xcworkspacedatais excluded by!**/*.xcworkspace/contents.xcworkspacedata
📒 Files selected for processing (31)
.github/review-bot-rules/swift-auxiliary-window-close-shortcuts.mdPackages/macOS/CmuxHive/Package.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteMacSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteTerminalSession.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveRemoteWorkspace.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveSyncRuntime.swiftPackages/macOS/CmuxHive/Sources/CmuxHive/HiveTerminalGridModel.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveRemoteSessionTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/HiveTerminalGridModelTests.swiftPackages/macOS/CmuxHive/Tests/CmuxHiveTests/ScriptedHostTransport.swiftPackages/macOS/CmuxHiveUI/Package.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveRemoteTerminalPane.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalColor.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalGridView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalInputView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveTerminalKeyMapping.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerRootView.swiftPackages/macOS/CmuxHiveUI/Sources/CmuxHiveUI/HiveViewerWorkspaceList.swiftPackages/macOS/CmuxHiveUI/Tests/CmuxHiveUITests/HiveTerminalKeyMappingTests.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Environment/SettingsHostActions.swiftPackages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/ComputersSection.swiftResources/Localizable.xcstringsSources/CmuxAuxiliaryWindows.swiftSources/Hive/HiveComputersService.swiftSources/Hive/HiveViewerWindowController.swiftSources/HostSettingsActions+Computers.swiftSources/Mobile/Pairing/MobilePairingWindowController.swiftSources/cmuxApp.swiftcmux.xcodeproj/project.pbxprojscripts/lint_auxiliary_window_close_shortcuts.pytests/test_ci_auxiliary_window_close_shortcuts.sh
💤 Files with no reviewable changes (1)
- Sources/cmuxApp.swift
# Conflicts: # cmux.xcodeproj/project.pbxproj
|
Cursor review 5139234314 is addressed at HEAD
The three inline findings from this review were each explicitly replied to and resolved after GitHub confirmed the replies. CodeRabbit is paused and Greptile skipped the oversized diff, so neither is treated as approval. Production viewer admission remains fail-closed ( |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
There are 3 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit dc47afa. Configure here.
10e5f21 to
6bdaa9e
Compare
|
This is a broad Hive M1 feature with substantial package churn, so I’m leaving it open for team design and review. |

Refs #8001. This PR is not approved for automatic merge or issue closure: it relocates shared mobile/iOS packages, and live Mac-to-Mac acceptance remains unverified.
Current status
This adds the gated Hive remote-Mac viewer foundation, Settings > Computers pairing, native mirror-workspace integration, and an auxiliary viewer. The previous description's claims that end-to-end acceptance was fully met and iOS code was untouched were inaccurate and are superseded here.
Production viewer admission remains deliberately unavailable (
Sources/Hive/HiveComputersService.swift,viewerTransportAvailable == false). A numeric or named Tailscale route alone is not cryptographic peer identity; legacy bearer transport remains fail-closed. This PR must not be used to claim live two-Mac viewing is ready, or to close #8001, until that boundary is implemented and dogfooded.Latest review/CI checkpoint —
48d27063f748d27063f75d601d347ef88729ee0eadb079ef3c, including the replay coordinator, synchronous disconnect admission revocation, app-host test serialization, and the Iroh lane-quota assertion correction. Currentorigin/mainis5939eaf985911cfbec5c8b4d61d563dd52b1ef1b; the branch includes it through merge commit48d27063f7.34203733933at6eb3532205had a genuine lane-quota assertion failure (5expected versus7implemented) plus widespread AppKit-state failures/timeouts in parallel app-host execution. The new head is awaiting its own required CI result; no assertion failure is being declared fixed until that run is green.--no-dev-backend; the final-head tagged build is required after this push. Offline mode proves compilation/startup only becausecmux-dev-backend-1still fails DNS resolution; it cannot prove authenticated two-Mac viewer behavior.5139234314receives a top-level response below. CodeRabbit is paused and Greptile skipped the oversized diff; neither is represented as final-head approval.CmuxHivesuite, 8-testCmuxHiveUIsuite, and ten repeats of the focused replay/disconnect/coordinator regressions pass. Rebind/readiness tests validate the new seams; they do not claim a red native two-Mac route-churn reproduction.parallelizable="NO": these suites shareNSApplication, windows, and process-wide services, so serial execution within one test process protects GUI correctness at some intra-shard throughput cost. The six CI shards remain parallel across isolated runners.MobileCoreRPCClient.retire()blocks new transport admission/dials but does not retroactively cancel an RPC already using an installed transport. Disconnect tests therefore assert synchronous Hive admission revocation and no new connection allocation, while allowing an already-installed request to finish during asynchronous teardown.Changes
ifexpression, preserving filtering semantics while fixing the concrete app-host ViewBuilder compiler failure.Verification
258b0a6de31225122f7cd571f52bb7bbe34eda1e, and both suites were rerun from that source.9260576134.python3 scripts/swift_file_length_budget.pyinvocation fails because that script is absent from this checkout and main. No budget TSV was modified; tracked-file budget-row compliance cannot be certified by substituting line counting for the missing tool.Explicit trade-offs and remaining acceptance work
cmux-dev-backend-1did not resolve. The documented offline mode can validate native compilation/startup only, not backend-dependent flows. The tagged cloud build succeeded in 586 seconds. Two fleet launches verified the exact tag, workspace listing, and running terminal via the debug socket. Screenshot capture failed: the default provider lacks its bundle/authentication; the installed alternate driver does not support the requested screenshot tool. No credentials or privacy permissions were changed. Final HEAD CI status is recorded in the final audit comment.2f8091f080exposed a ViewBuilderVoidexpression error. Its compiler fix and the six newly posted Cursor findings were collected in one additional push (9260576134), retaining separate test/fix commits. This further push responds to concrete new CI/review evidence; it is not a claim of one total push.hiveScopeargument in the existing sidebar scale-test harness. The test-only correctiona03fef5387supplies its own TabManager scope, exactly like production, and leaves the file at 514 lines. It changes no assertions or runtime source. Another hosted CI run verifies this head; another tagged app build would not test anything new. This additional push is limited to the concrete compiler failure.34191663075ata03fef5387passed package tests but exposed CLI helper test-membership errors, removed catalog test APIs, two new warning buckets, and five Release-only debug-log errors. These were batched in278af106ec, merged with main71eb616d6f, and published together atf6bb617c7b. That head subsequently passed package/build-and-lag verification but recorded a legacy Claude-hook process timeout in app-host shard 6; the next full-head CI run is checked independently. No timeout was raised or assertion removed to mask it. The test ports retain the four behavioral contracts at canonical catalog, provider receipt-policy, and rename-coordinator boundaries; they do not restore a second optimistic catalog state path. A remote executable probe confirmed that the old raw unquoted attach-command assertion fails while effective parsed arguments, the login-shell wrapper, and client-list runner/parser pass. Production quoting is unchanged. The shared legacy XCTest CLI integration harness is retained to avoid an unrelated harness-wide migration; the catalog tests use Swift Testing.c8d136cca6fix batch and258b0a6de3main merge. They were published together, preserving test/fix ordering. This is an additional evidence-driven push, not a claim of one total push across the interrupted session.Austin must review/dogfood and merge this PR; do not self-merge it or close the linked issue.
Automated summaries (advisory; maintained status above is authoritative)
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Adds a gated macOS remote-Mac viewer for #8001: paired Macs appear under Settings > Computers and their workspaces render as native mirror workspaces with live input, replay identity validation, and reconnect handling. Production viewer admission stays disabled (
viewerTransportAvailable == false), so live two-Mac use is not yet ready.New Features
CmxPairingCodevalues, and offers per-computer window or sidebar presentation.hive.open,hive.render_probe, andhive.sidebar_probeRPCs for headless verification.Migration
Packages/iOStoPackages/Shared, with standaloneCmuxHiveandCmuxHiveUICI gates.Written for commit cdd9bb5. Summary will update on new commits.
Summary by CodeRabbit
Note
High Risk
Large cross-platform package moves plus new auth/route/pairing and remote-terminal RPC paths; production viewer admission is intentionally gated off but the surface area touches tokens, Tailscale trust, and account-scoped pairing.
Overview
Introduces
CmuxHive(and CI forCmuxHiveUI) as the macOS layer for Settings › Computers: merge team registry, local paired-computer SQLite, and presence; pair by registry row, 6-digitCmxPairingCode, or pasted attach link; and run remote Mac viewer sessions (workspace list, shared render-grid router, terminal replay/input, bounded reconnect). Control socket addshive.open,hive.render_probe, andhive.sidebar_probe.Shared mobile stack moves Mac-consumed packages from
Packages/iOStoPackages/Shared(shell, RPC, shell model, paired Mac, terminal kit, etc.) with updated SwiftPM paths, iOS workflow gates, and test-determinism allowlist entries.CmxPairingCodeand registry instance labels /isOwnedByCurrentUsersupport code-based rendezvous;MobileShellRouteAuthPolicygainsStackAuthChannelTrustso the Mac viewer may send Stack auth over verified Tailscale tunnel hosts while iOS stays loopback-only. Mac viewer Tailscale dials use a dedicatedHiveTailscaleByteTransportFactory(transport-admission path; legacy bearer routes remain fail-closed per PR intent).Smaller deltas: public render-grid width APIs,
TerminalKeyboardDockPathSelectionfor iOS keyboard-dock routing, review-bot pointer toCmuxAuxiliaryWindows.swift, and a doc-only tweak toCLIError.Reviewed by Cursor Bugbot for commit cdd9bb5. Bugbot is set up for automated code reviews on this repo. Configure here.