From e1c962046e39d90d0dd4bb88459c5e6457528008 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 18 Sep 2026 18:30:01 -0700 Subject: [PATCH 1/3] refactor: extract main window registry index --- Sources/AppDelegate.swift | 63 +++++++++----------------------- Sources/MainWindowRegistry.swift | 60 ++++++++++++++++++++++++++++++ cmux.xcodeproj/project.pbxproj | 60 ++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 46 deletions(-) create mode 100644 Sources/MainWindowRegistry.swift diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index 2d62aa3a112e..5439154f7a66 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -1074,7 +1074,12 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent } #endif - var mainWindowContexts: [ObjectIdentifier: MainWindowContext] = [:] + private let mainWindowRegistry = MainWindowRegistry() + + /// Compatibility view for existing routing and lifecycle callers. + var mainWindowContexts: [ObjectIdentifier: MainWindowContext] { + mainWindowRegistry.contexts + } private var mainWindowControllers: [MainWindowController] = [] /// Tracks the cascade point for new windows, matching Ghostty's upstream algorithm. @@ -4907,12 +4912,11 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent fileExplorerState: FileExplorerState? = nil, cmuxConfigStore: CmuxConfigStore? = nil ) { - let key = ObjectIdentifier(window) forgetRecoverableMainWindowRoute(windowId: windowId) #if DEBUG let priorManagerToken = debugManagerToken(self.tabManager) #endif - if let existing = mainWindowContexts[key] { + if let existing = mainWindowRegistry.context(for: window) { tabManager.window = window tabManager.windowId = existing.windowId existing.window = window @@ -4981,7 +4985,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent workspaceTerminalFontSizeArbiter: workspaceTerminalFontSizeArbiter ) - mainWindowContexts[key] = context + mainWindowRegistry.insert(context, for: window) context.closeObserver = WindowCloseObserver(window: window) { [weak self] in self?.unregisterMainWindow($0) } } commandPaletteWindowStore.registerWindow(windowId) @@ -6213,33 +6217,15 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent } private func reindexMainWindowContextIfNeeded(_ context: MainWindowContext, for window: NSWindow) { - let desiredKey = ObjectIdentifier(window) - if mainWindowContexts[desiredKey] === context { - context.window = window - return - } - - let contextKeys = mainWindowContexts.compactMap { key, value in - value === context ? key : nil - } - for key in contextKeys { - mainWindowContexts.removeValue(forKey: key) - } - - if let conflicting = mainWindowContexts[desiredKey], conflicting !== context { - context.window = window - return + if mainWindowRegistry.reindex(context, for: window) { + notifyMainWindowContextsDidChange() } - - mainWindowContexts[desiredKey] = context - context.window = window - notifyMainWindowContextsDidChange() } func contextForMainTerminalWindow(_ window: NSWindow, reindex: Bool = true) -> MainWindowContext? { guard isMainTerminalWindow(window) else { return nil } - if let context = mainWindowContexts[ObjectIdentifier(window)] { + if let context = mainWindowRegistry.context(for: window) { context.window = window return context } @@ -6274,12 +6260,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent private func unregisterMainWindowContext(for window: NSWindow) -> MainWindowContext? { guard let removed = contextForMainTerminalWindow(window, reindex: false) else { return nil } removed.teardownWindowDock() - let removedKeys = mainWindowContexts.compactMap { key, value in - value === removed ? key : nil - } - for key in removedKeys { - mainWindowContexts.removeValue(forKey: key) - } + mainWindowRegistry.removeReferences(to: removed) rememberRecoverableMainWindowRoute(windowId: removed.windowId, tabManager: removed.tabManager, window: removed.window) removeMobileWorkspaceListObserverIfUnused(for: removed.tabManager) notifyMainWindowContextsDidChange() @@ -6289,12 +6270,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent // Internal (not private): see notifyMainWindowContextsDidChange. func discardOrphanedMainWindowContext(_ context: MainWindowContext, allowWindowlessFallback: Bool = false) { context.teardownWindowDock() - let contextKeys = mainWindowContexts.compactMap { key, value in - value === context ? key : nil - } - for key in contextKeys { - mainWindowContexts.removeValue(forKey: key) - } + mainWindowRegistry.removeReferences(to: context) rememberRecoverableMainWindowRoute(windowId: context.windowId, tabManager: context.tabManager, window: context.window) removeMobileWorkspaceListObserverIfUnused(for: context.tabManager) notifyMainWindowContextsDidChange() @@ -6320,7 +6296,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent } private func mainWindowId(for window: NSWindow) -> UUID? { - if let context = mainWindowContexts[ObjectIdentifier(window)] { + if let context = mainWindowRegistry.context(for: window) { return context.windowId } guard let rawIdentifier = window.identifier?.rawValue, @@ -16064,13 +16040,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent ) debugDetachedContextWindows.append(detachedWindow) - let contextKeys = mainWindowContexts.compactMap { key, value in - value === context ? key : nil - } - for key in contextKeys { - mainWindowContexts.removeValue(forKey: key) - } - mainWindowContexts[ObjectIdentifier(detachedWindow)] = context + mainWindowRegistry.removeReferences(to: context) + mainWindowRegistry.insert(context, for: detachedWindow) context.window = window return true } @@ -17393,7 +17364,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent #endif func isMainTerminalWindow(_ window: NSWindow) -> Bool { - if mainWindowContexts[ObjectIdentifier(window)] != nil { + if mainWindowRegistry.context(for: window) != nil { return true } guard let raw = window.identifier?.rawValue else { return false } diff --git a/Sources/MainWindowRegistry.swift b/Sources/MainWindowRegistry.swift new file mode 100644 index 000000000000..c603a9b7a75f --- /dev/null +++ b/Sources/MainWindowRegistry.swift @@ -0,0 +1,60 @@ +import AppKit + +/// Owns the identity index that maps terminal windows to their main-window contexts. +@MainActor +final class MainWindowRegistry { + typealias Context = AppDelegate.MainWindowContext + + private(set) var contexts: [ObjectIdentifier: Context] = [:] + + /// Returns the context currently indexed for `window`. + func context(for window: NSWindow) -> Context? { + contexts[ObjectIdentifier(window)] + } + + /// Returns the context currently indexed under `key`. + func context(for key: ObjectIdentifier) -> Context? { + contexts[key] + } + + /// Inserts `context` under the window's identity key. + func insert(_ context: Context, for window: NSWindow) { + contexts[ObjectIdentifier(window)] = context + } + + /// Removes every key currently referring to `context`. + @discardableResult + func removeReferences(to context: Context) -> [ObjectIdentifier] { + let keys = contexts.compactMap { key, value in + value === context ? key : nil + } + for key in keys { + contexts.removeValue(forKey: key) + } + return keys + } + + /// Rebinds a context to a window while preserving duplicate-window conflict behavior. + /// + /// Returns `true` only when a new index entry was installed. A conflicting entry leaves + /// the context unindexed under the requested key, matching the prior AppDelegate logic. + @discardableResult + func reindex(_ context: Context, for window: NSWindow) -> Bool { + let desiredKey = ObjectIdentifier(window) + if contexts[desiredKey] === context { + context.window = window + return false + } + + removeReferences(to: context) + + if let conflicting = contexts[desiredKey], conflicting !== context { + context.window = window + return false + } + + contexts[desiredKey] = context + context.window = window + return true + } +} diff --git a/cmux.xcodeproj/project.pbxproj b/cmux.xcodeproj/project.pbxproj index c0e450261217..2c93b1940bc0 100644 --- a/cmux.xcodeproj/project.pbxproj +++ b/cmux.xcodeproj/project.pbxproj @@ -776,6 +776,8 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources 1A0B0C0D0E0F101112132013 /* CmuxIrohTransport in Frameworks */ = {isa = PBXBuildFile; productRef = 1A0B0C0D0E0F101112132012 /* CmuxIrohTransport */; }; 1A0B0C0D0E0F101112132014 /* CmuxIrohTransport in Frameworks */ = {isa = PBXBuildFile; productRef = 1A0B0C0D0E0F101112132012 /* CmuxIrohTransport */; }; E7E00000000000000000000B /* CmuxLifecycleEventPublishing.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7E00000000000000000000C /* CmuxLifecycleEventPublishing.swift */; }; + E7D100000000000000000003 /* CmuxMainRunLoopStallMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7D100000000000000000004 /* CmuxMainRunLoopStallMonitor.swift */; }; + E7D100000000000000000005 /* CmuxMainThreadTurnProfiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7D100000000000000000006 /* CmuxMainThreadTurnProfiler.swift */; }; 2F0C07000000000000000002 /* CmuxMainWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F0C07000000000000000001 /* CmuxMainWindow.swift */; }; D36090010000000000000005 /* CmuxMainWindowConstrainFrameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D36090010000000000000006 /* CmuxMainWindowConstrainFrameTests.swift */; }; D36090020000000000000005 /* CmuxMainWindowFullScreenCapabilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D36090020000000000000006 /* CmuxMainWindowFullScreenCapabilityTests.swift */; }; @@ -866,6 +868,7 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources C7A508000000000000000002 /* CmuxTopSnapshotScopeCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A508000000000000000001 /* CmuxTopSnapshotScopeCache.swift */; }; C7A5090000000000000005A2 /* CmuxTopSnapshotScopeCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A5090000000000000005A1 /* CmuxTopSnapshotScopeCacheTests.swift */; }; C7A509000000000000000002 /* CmuxTopSnapshotScopeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A509000000000000000001 /* CmuxTopSnapshotScopeTests.swift */; }; + E7D100000000000000000001 /* CmuxTypingTiming.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7D100000000000000000002 /* CmuxTypingTiming.swift */; }; CDFEED0300000000CDFEED03 /* CmuxUpdater in Frameworks */ = {isa = PBXBuildFile; productRef = CDFEED0200000000CDFEED02 /* CmuxUpdater */; }; CDFEED0600000000CDFEED06 /* CmuxUpdaterUI in Frameworks */ = {isa = PBXBuildFile; productRef = CDFEED0500000000CDFEED05 /* CmuxUpdaterUI */; }; 9520A0029520A0029520A002 /* CmuxVaultAgentRegistration+Hermes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9520B0029520B0029520B002 /* CmuxVaultAgentRegistration+Hermes.swift */; }; @@ -930,6 +933,7 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources A91C0D100000000000000002 /* CompletedRestoredAgentInputRoutingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A91C0D100000000000000001 /* CompletedRestoredAgentInputRoutingTests.swift */; }; 3023A1013023A1013023A101 /* ConfigSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3023B1013023B1013023B101 /* ConfigSettingsView.swift */; }; 3023A1003023A1003023A100 /* ConfigSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3023B1003023B1003023B100 /* ConfigSource.swift */; }; + E7E100000000000000000001 /* ConfiguredGroupActionAsyncWorkspaceObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7E100000000000000000002 /* ConfiguredGroupActionAsyncWorkspaceObserver.swift */; }; D1F0A01100000000000000B1 /* ConnectivityInvalidationSubscriberCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F0A01100000000000000B2 /* ConnectivityInvalidationSubscriberCoordinator.swift */; }; C0DE43000000000000000005 /* ContentView+AgentChatCommandPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DE43000000000000000006 /* ContentView+AgentChatCommandPalette.swift */; }; C0DEA7710000000000000001 /* ContentView+AuthCommandPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DEA7710000000000000002 /* ContentView+AuthCommandPalette.swift */; }; @@ -1061,6 +1065,9 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources FEED0000000000000000F011 /* FeedPanelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEED0000000000000000F010 /* FeedPanelViewModel.swift */; }; FEED0000000000000000F013 /* FeedPermissionActionPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEED0000000000000000F012 /* FeedPermissionActionPolicy.swift */; }; FEED0000000000000000F00B /* FeedPreviewWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEED0000000000000000F00A /* FeedPreviewWindowController.swift */; }; + FEE012340000000000000001 /* FeedSidebarUITestCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE012340000000000000002 /* FeedSidebarUITestCoordinator.swift */; }; + FEE012340000000000000003 /* FeedSidebarUITestPushClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE012340000000000000004 /* FeedSidebarUITestPushClient.swift */; }; + FEE012340000000000000005 /* FeedSidebarUITestRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE012340000000000000006 /* FeedSidebarUITestRecorder.swift */; }; FEED0000000000000000F009 /* FeedSidebarUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEED0000000000000000F008 /* FeedSidebarUITests.swift */; }; FEED0000000000000000F00F /* FeedTextEditorDebugWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEED0000000000000000F00E /* FeedTextEditorDebugWindowController.swift */; }; D0B1001AA1B2C3D4E5F60001 /* FileDropHintBadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B1001BA1B2C3D4E5F60001 /* FileDropHintBadgeView.swift */; }; @@ -1324,6 +1331,7 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources 2F0C05000000000000000002 /* MainWindowFocusController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F0C05000000000000000001 /* MainWindowFocusController.swift */; }; 6512F0C06512F0C06512F002 /* MainWindowFocusRestoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6512F0C06512F0C06512F001 /* MainWindowFocusRestoreTests.swift */; }; B37A00000000000000000005 /* MainWindowFocusTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B37A00000000000000000006 /* MainWindowFocusTypes.swift */; }; + D4A100000000000000000001 /* MainWindowRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4A100000000000000000002 /* MainWindowRegistry.swift */; }; 40ED33F6C1CEB26EAE7C9476 /* MainWindowSelfSizingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 570ED364A7E41085FB2D31FE /* MainWindowSelfSizingTests.swift */; }; A6D1F0300000000000000002 /* MainWindowVisibilityController+Lifecycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D1F0300000000000000001 /* MainWindowVisibilityController+Lifecycle.swift */; }; 2F0C06000000000000000002 /* MainWindowVisibilityController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F0C06000000000000000001 /* MainWindowVisibilityController.swift */; }; @@ -1837,6 +1845,7 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources A5001601 /* SentryHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001600 /* SentryHelper.swift */; }; FE003106 /* SessionAgentPresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE003006 /* SessionAgentPresentation.swift */; }; A9F200000000000000000008 /* SessionAgentSessionPanelSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9F100000000000000000008 /* SessionAgentSessionPanelSnapshot.swift */; }; + E7E300000000000000000001 /* SessionAutosaveCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7E300000000000000000002 /* SessionAutosaveCoordinator.swift */; }; A74770010000000000000005 /* SessionConfigFrameEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74770010000000000000006 /* SessionConfigFrameEntry.swift */; }; A74770010000000000000007 /* SessionConfigFrameRing.swift in Sources */ = {isa = PBXBuildFile; fileRef = A74770010000000000000008 /* SessionConfigFrameRing.swift */; }; C71500020000000000000001 /* SessionContentWidthModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71500010000000000000001 /* SessionContentWidthModifier.swift */; }; @@ -1895,6 +1904,7 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources 806600000000000000000002 /* SessionRestorableAgentSnapshotPermissionModeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 806600000000000000000001 /* SessionRestorableAgentSnapshotPermissionModeTests.swift */; }; C54860090000000000000001 /* SessionRestoreIdentityExclusions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C54860090000000000000002 /* SessionRestoreIdentityExclusions.swift */; }; A50016B1A1B2C3D4E5F60718 /* SessionSnapshotDebugBenchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50016B0A1B2C3D4E5F60718 /* SessionSnapshotDebugBenchmark.swift */; }; + D9E700000000000000000001 /* SessionSnapshotPersistenceWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9E700000000000000000002 /* SessionSnapshotPersistenceWriter.swift */; }; D86840000000000000000007 /* SessionSplitContainerLayoutCodec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D86840000000000000000008 /* SessionSplitContainerLayoutCodec.swift */; }; D86840000000000000000009 /* SessionSplitContainerSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8684000000000000000000A /* SessionSplitContainerSnapshot.swift */; }; FE00310B /* SessionTranscriptPopoverLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE00300B /* SessionTranscriptPopoverLayout.swift */; }; @@ -2253,6 +2263,9 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources B8835A000000000000000003 /* TerminalClipboardInputSequencerTests+Replay.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8835A000000000000000004 /* TerminalClipboardInputSequencerTests+Replay.swift */; }; B8835700000000000000000D /* TerminalClipboardInputSequencerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8835700000000000000000E /* TerminalClipboardInputSequencerTests.swift */; }; B88357000000000000000013 /* TerminalClipboardRequestSurfaceIdentity.swift in Sources */ = {isa = PBXBuildFile; fileRef = B88357000000000000000014 /* TerminalClipboardRequestSurfaceIdentity.swift */; }; + E7C100000000000000000003 /* TerminalCmdClickUITestConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7C100000000000000000004 /* TerminalCmdClickUITestConfiguration.swift */; }; + E7C100000000000000000001 /* TerminalCmdClickUITestCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7C100000000000000000002 /* TerminalCmdClickUITestCoordinator.swift */; }; + E7C100000000000000000005 /* TerminalCmdClickUITestManifestWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7C100000000000000000006 /* TerminalCmdClickUITestManifestWriter.swift */; }; C2577000A1B2C3D4E5F60718 /* TerminalCmdClickUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2577001A1B2C3D4E5F60718 /* TerminalCmdClickUITests.swift */; }; F87910190000000000000001 /* TerminalConfigurationReloadCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F87910190000000000000002 /* TerminalConfigurationReloadCoordinator.swift */; }; F87930000000000000000001 /* TerminalConfigurationReloadEnqueueResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = F87930000000000000000002 /* TerminalConfigurationReloadEnqueueResult.swift */; }; @@ -2531,7 +2544,9 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources E30760000000000000000002 /* TmuxWorkspacePaneOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30760000000000000000001 /* TmuxWorkspacePaneOverlayView.swift */; }; D3284001A1B2C3D4E5F60718 /* TraditionalChineseIMENumpadRegressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3284002A1B2C3D4E5F60718 /* TraditionalChineseIMENumpadRegressionTests.swift */; }; 468100000000000000000003 /* TypingHotPathRegressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 468100000000000000000004 /* TypingHotPathRegressionTests.swift */; }; + D9A1B2C3D4E5000000000001 /* UITestDiagnosticsWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A1B2C3D4E5000000000002 /* UITestDiagnosticsWriter.swift */; }; A5001501 /* UITestRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001511 /* UITestRecorder.swift */; }; + E7F100000000000000000001 /* UITestSocketSanityCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7F100000000000000000002 /* UITestSocketSanityCoordinator.swift */; }; A500120D /* UpdateLogStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001223 /* UpdateLogStore.swift */; }; F2000000A1B2C3D4E5F60718 /* UpdatePillReleaseVisibilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2000001A1B2C3D4E5F60718 /* UpdatePillReleaseVisibilityTests.swift */; }; C0B4D9B0A1B2C3D4E5F60718 /* UpdatePillUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0B4D9B1A1B2C3D4E5F60718 /* UpdatePillUITests.swift */; }; @@ -3592,6 +3607,8 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = C0DE34020000000000000004 /* CmuxHelpResource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/CmuxHelpResource.swift; sourceTree = ""; }; C0DE46010000000000000002 /* CMUXInstalledExtensionSidebarHostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CMUXInstalledExtensionSidebarHostView.swift; sourceTree = ""; }; E7E00000000000000000000C /* CmuxLifecycleEventPublishing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxLifecycleEventPublishing.swift; sourceTree = ""; }; + E7D100000000000000000004 /* CmuxMainRunLoopStallMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/CmuxMainRunLoopStallMonitor.swift"; sourceTree = ""; }; + E7D100000000000000000006 /* CmuxMainThreadTurnProfiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/CmuxMainThreadTurnProfiler.swift"; sourceTree = ""; }; 2F0C07000000000000000001 /* CmuxMainWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/CmuxMainWindow.swift; sourceTree = ""; }; D36090010000000000000006 /* CmuxMainWindowConstrainFrameTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxMainWindowConstrainFrameTests.swift; sourceTree = ""; }; D36090020000000000000006 /* CmuxMainWindowFullScreenCapabilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxMainWindowFullScreenCapabilityTests.swift; sourceTree = ""; }; @@ -3647,6 +3664,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = C7A508000000000000000001 /* CmuxTopSnapshotScopeCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopSnapshotScopeCache.swift; sourceTree = ""; }; C7A5090000000000000005A1 /* CmuxTopSnapshotScopeCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopSnapshotScopeCacheTests.swift; sourceTree = ""; }; C7A509000000000000000001 /* CmuxTopSnapshotScopeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopSnapshotScopeTests.swift; sourceTree = ""; }; + E7D100000000000000000002 /* CmuxTypingTiming.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/CmuxTypingTiming.swift"; sourceTree = ""; }; 7E7E6EF344A568AC7FEE3715 /* cmuxUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = cmuxUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 9520B0029520B0029520B002 /* CmuxVaultAgentRegistration+Hermes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CmuxVaultAgentRegistration+Hermes.swift"; sourceTree = ""; }; 858200000000000000000005 /* CmuxVaultAgentRegistration+RegisteredResumeKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CmuxVaultAgentRegistration+RegisteredResumeKind.swift"; sourceTree = ""; }; @@ -3706,6 +3724,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = A91C0D100000000000000001 /* CompletedRestoredAgentInputRoutingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletedRestoredAgentInputRoutingTests.swift; sourceTree = ""; }; 3023B1013023B1013023B101 /* ConfigSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings/ConfigSettingsView.swift; sourceTree = ""; }; 3023B1003023B1003023B100 /* ConfigSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings/ConfigSource.swift; sourceTree = ""; }; + E7E100000000000000000002 /* ConfiguredGroupActionAsyncWorkspaceObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "App/ConfiguredGroupActionAsyncWorkspaceObserver.swift"; sourceTree = ""; }; D1F0A01100000000000000B2 /* ConnectivityInvalidationSubscriberCoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConnectivityInvalidationSubscriberCoordinator.swift; sourceTree = ""; }; C0DE43000000000000000006 /* ContentView+AgentChatCommandPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+AgentChatCommandPalette.swift"; sourceTree = ""; }; C0DEA7710000000000000002 /* ContentView+AuthCommandPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+AuthCommandPalette.swift"; sourceTree = ""; }; @@ -3836,6 +3855,9 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = FEED0000000000000000F010 /* FeedPanelViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FeedPanelViewModel.swift; sourceTree = ""; }; FEED0000000000000000F012 /* FeedPermissionActionPolicy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FeedPermissionActionPolicy.swift; sourceTree = ""; }; FEED0000000000000000F00A /* FeedPreviewWindowController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FeedPreviewWindowController.swift; sourceTree = ""; }; + FEE012340000000000000002 /* FeedSidebarUITestCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/UITests/FeedSidebarUITestCoordinator.swift"; sourceTree = ""; }; + FEE012340000000000000004 /* FeedSidebarUITestPushClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/UITests/FeedSidebarUITestPushClient.swift"; sourceTree = ""; }; + FEE012340000000000000006 /* FeedSidebarUITestRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/UITests/FeedSidebarUITestRecorder.swift"; sourceTree = ""; }; FEED0000000000000000F008 /* FeedSidebarUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedSidebarUITests.swift; sourceTree = ""; }; FEED0000000000000000F00E /* FeedTextEditorDebugWindowController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FeedTextEditorDebugWindowController.swift; sourceTree = ""; }; D0B1001BA1B2C3D4E5F60001 /* FileDropHintBadgeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDropHintBadgeView.swift; sourceTree = ""; }; @@ -4097,6 +4119,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = 2F0C05000000000000000001 /* MainWindowFocusController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindowFocusController.swift; sourceTree = ""; }; 6512F0C06512F0C06512F001 /* MainWindowFocusRestoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindowFocusRestoreTests.swift; sourceTree = ""; }; B37A00000000000000000006 /* MainWindowFocusTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindowFocusTypes.swift; sourceTree = ""; }; + D4A100000000000000000002 /* MainWindowRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindowRegistry.swift; sourceTree = ""; }; 570ED364A7E41085FB2D31FE /* MainWindowSelfSizingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindowSelfSizingTests.swift; sourceTree = ""; }; A6D1F0300000000000000001 /* MainWindowVisibilityController+Lifecycle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "App/MainWindowVisibilityController+Lifecycle.swift"; sourceTree = ""; }; 2F0C06000000000000000001 /* MainWindowVisibilityController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/MainWindowVisibilityController.swift; sourceTree = ""; }; @@ -4602,6 +4625,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = A5001600 /* SentryHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryHelper.swift; sourceTree = ""; }; FE003006 /* SessionAgentPresentation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionAgentPresentation.swift; sourceTree = ""; }; A9F100000000000000000008 /* SessionAgentSessionPanelSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionAgentSessionPanelSnapshot.swift; sourceTree = ""; }; + E7E300000000000000000002 /* SessionAutosaveCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionAutosaveCoordinator.swift; sourceTree = ""; }; A74770010000000000000006 /* SessionConfigFrameEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionConfigFrameEntry.swift; sourceTree = ""; }; A74770010000000000000008 /* SessionConfigFrameRing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionConfigFrameRing.swift; sourceTree = ""; }; C71500010000000000000001 /* SessionContentWidthModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/SessionContentWidthModifier.swift; sourceTree = ""; }; @@ -4660,6 +4684,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = 806600000000000000000001 /* SessionRestorableAgentSnapshotPermissionModeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionRestorableAgentSnapshotPermissionModeTests.swift; sourceTree = ""; }; C54860090000000000000002 /* SessionRestoreIdentityExclusions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionRestoreIdentityExclusions.swift; sourceTree = ""; }; A50016B0A1B2C3D4E5F60718 /* SessionSnapshotDebugBenchmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/SessionSnapshotDebugBenchmark.swift; sourceTree = ""; }; + D9E700000000000000000002 /* SessionSnapshotPersistenceWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionSnapshotPersistenceWriter.swift; sourceTree = ""; }; D86840000000000000000008 /* SessionSplitContainerLayoutCodec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionSplitContainerLayoutCodec.swift; sourceTree = ""; }; D8684000000000000000000A /* SessionSplitContainerSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionSplitContainerSnapshot.swift; sourceTree = ""; }; FE00300B /* SessionTranscriptPopoverLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionTranscriptPopoverLayout.swift; sourceTree = ""; }; @@ -5011,6 +5036,9 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = B8835A000000000000000004 /* TerminalClipboardInputSequencerTests+Replay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TerminalClipboardInputSequencerTests+Replay.swift"; sourceTree = ""; }; B8835700000000000000000E /* TerminalClipboardInputSequencerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalClipboardInputSequencerTests.swift; sourceTree = ""; }; B88357000000000000000014 /* TerminalClipboardRequestSurfaceIdentity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalClipboardRequestSurfaceIdentity.swift; sourceTree = ""; }; + E7C100000000000000000004 /* TerminalCmdClickUITestConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/UITests/TerminalCmdClickUITestConfiguration.swift"; sourceTree = ""; }; + E7C100000000000000000002 /* TerminalCmdClickUITestCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/UITests/TerminalCmdClickUITestCoordinator.swift"; sourceTree = ""; }; + E7C100000000000000000006 /* TerminalCmdClickUITestManifestWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/UITests/TerminalCmdClickUITestManifestWriter.swift"; sourceTree = ""; }; C2577001A1B2C3D4E5F60718 /* TerminalCmdClickUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalCmdClickUITests.swift; sourceTree = ""; }; F87910190000000000000002 /* TerminalConfigurationReloadCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalConfigurationReloadCoordinator.swift; sourceTree = ""; }; F87930000000000000000002 /* TerminalConfigurationReloadEnqueueResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalConfigurationReloadEnqueueResult.swift; sourceTree = ""; }; @@ -5289,7 +5317,9 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = E30760000000000000000001 /* TmuxWorkspacePaneOverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TmuxWorkspacePaneOverlayView.swift; sourceTree = ""; }; D3284002A1B2C3D4E5F60718 /* TraditionalChineseIMENumpadRegressionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TraditionalChineseIMENumpadRegressionTests.swift; sourceTree = ""; }; 468100000000000000000004 /* TypingHotPathRegressionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingHotPathRegressionTests.swift; sourceTree = ""; }; + D9A1B2C3D4E5000000000002 /* UITestDiagnosticsWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/UITests/UITestDiagnosticsWriter.swift"; sourceTree = ""; }; A5001511 /* UITestRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestRecorder.swift; sourceTree = ""; }; + E7F100000000000000000002 /* UITestSocketSanityCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/UITests/UITestSocketSanityCoordinator.swift"; sourceTree = ""; }; A5001223 /* UpdateLogStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Update/UpdateLogStore.swift; sourceTree = ""; }; F2000001A1B2C3D4E5F60718 /* UpdatePillReleaseVisibilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdatePillReleaseVisibilityTests.swift; sourceTree = ""; }; C0B4D9B1A1B2C3D4E5F60718 /* UpdatePillUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdatePillUITests.swift; sourceTree = ""; }; @@ -6853,6 +6883,21 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = F4350A130000000000000001 /* AppBundleIconPersistencePolicy.swift */, D1320AA0D1320AA0D1320AA4 /* AppIconDockTilePlugin.swift */, A5001090 /* AppDelegate.swift */, + E7E100000000000000000002 /* ConfiguredGroupActionAsyncWorkspaceObserver.swift */, + E7D100000000000000000002 /* CmuxTypingTiming.swift */, + E7D100000000000000000004 /* CmuxMainRunLoopStallMonitor.swift */, + E7D100000000000000000006 /* CmuxMainThreadTurnProfiler.swift */, + D9E700000000000000000002 /* SessionSnapshotPersistenceWriter.swift */, + E7E300000000000000000002 /* SessionAutosaveCoordinator.swift */, + FEE012340000000000000002 /* FeedSidebarUITestCoordinator.swift */, + D4A100000000000000000002 /* MainWindowRegistry.swift */, + E7C100000000000000000002 /* TerminalCmdClickUITestCoordinator.swift */, + E7C100000000000000000004 /* TerminalCmdClickUITestConfiguration.swift */, + E7C100000000000000000006 /* TerminalCmdClickUITestManifestWriter.swift */, + FEE012340000000000000004 /* FeedSidebarUITestPushClient.swift */, + FEE012340000000000000006 /* FeedSidebarUITestRecorder.swift */, + D9A1B2C3D4E5000000000002 /* UITestDiagnosticsWriter.swift */, + E7F100000000000000000002 /* UITestSocketSanityCoordinator.swift */, C51A740000000000000000A2 /* AppDelegate+SimulatorShortcutRouting.swift */, D35B00000000000000000011 /* TerminalController+BrowserDesignMode.swift */, D35B00000000000000000014 /* TerminalController+AgentPromptDelivery.swift */, @@ -9339,6 +9384,8 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = C0DE34020000000000000002 /* CmuxHelpResource.swift in Sources */, C0DE46010000000000000001 /* CMUXInstalledExtensionSidebarHostView.swift in Sources */, E7E00000000000000000000B /* CmuxLifecycleEventPublishing.swift in Sources */, + E7D100000000000000000003 /* CmuxMainRunLoopStallMonitor.swift in Sources */, + E7D100000000000000000005 /* CmuxMainThreadTurnProfiler.swift in Sources */, 2F0C07000000000000000002 /* CmuxMainWindow.swift in Sources */, CA1F0A01CA1F0A01CA1F0A01 /* CmuxModalAlertPresentation.swift in Sources */, C54860110000000000000001 /* CmuxNavigationResolution.swift in Sources */, @@ -9379,6 +9426,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = C7A512000000000000000002 /* CmuxTopProcessSnapshotCache.swift in Sources */, C7A501000000000000000002 /* CmuxTopSnapshot.swift in Sources */, C7A508000000000000000002 /* CmuxTopSnapshotScopeCache.swift in Sources */, + E7D100000000000000000001 /* CmuxTypingTiming.swift in Sources */, 9520A0029520A0029520A002 /* CmuxVaultAgentRegistration+Hermes.swift in Sources */, 858200000000000000000006 /* CmuxVaultAgentRegistration+RegisteredResumeKind.swift in Sources */, 9520A0059520A0059520A005 /* CmuxVaultAgentRegistry+ProcessMatching.swift in Sources */, @@ -9404,6 +9452,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = C1713002C1713002C1713002 /* CommandPaletteShortcutRouting.swift in Sources */, 3023A1013023A1013023A101 /* ConfigSettingsView.swift in Sources */, 3023A1003023A1003023A100 /* ConfigSource.swift in Sources */, + E7E100000000000000000001 /* ConfiguredGroupActionAsyncWorkspaceObserver.swift in Sources */, D1F0A01100000000000000B1 /* ConnectivityInvalidationSubscriberCoordinator.swift in Sources */, C0DE43000000000000000005 /* ContentView+AgentChatCommandPalette.swift in Sources */, C0DEA7710000000000000001 /* ContentView+AuthCommandPalette.swift in Sources */, @@ -9503,6 +9552,9 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = FEED0000000000000000F011 /* FeedPanelViewModel.swift in Sources */, FEED0000000000000000F013 /* FeedPermissionActionPolicy.swift in Sources */, FEED0000000000000000F00B /* FeedPreviewWindowController.swift in Sources */, + FEE012340000000000000001 /* FeedSidebarUITestCoordinator.swift in Sources */, + FEE012340000000000000003 /* FeedSidebarUITestPushClient.swift in Sources */, + FEE012340000000000000005 /* FeedSidebarUITestRecorder.swift in Sources */, FEED0000000000000000F00F /* FeedTextEditorDebugWindowController.swift in Sources */, D0B1001AA1B2C3D4E5F60001 /* FileDropHintBadgeView.swift in Sources */, D0B10020A1B2C3D4E5F60001 /* FileDropOverlayView.swift in Sources */, @@ -9673,6 +9725,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = 895500000000000000000003 /* MainWindowController.swift in Sources */, 2F0C05000000000000000002 /* MainWindowFocusController.swift in Sources */, B37A00000000000000000005 /* MainWindowFocusTypes.swift in Sources */, + D4A100000000000000000001 /* MainWindowRegistry.swift in Sources */, A6D1F0300000000000000002 /* MainWindowVisibilityController+Lifecycle.swift in Sources */, 2F0C06000000000000000002 /* MainWindowVisibilityController.swift in Sources */, 730600020000000000000002 /* MainWindowVisibleFrameFitRescue.swift in Sources */, @@ -10019,6 +10072,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = A5001601 /* SentryHelper.swift in Sources */, FE003106 /* SessionAgentPresentation.swift in Sources */, A9F200000000000000000008 /* SessionAgentSessionPanelSnapshot.swift in Sources */, + E7E300000000000000000001 /* SessionAutosaveCoordinator.swift in Sources */, A74770010000000000000005 /* SessionConfigFrameEntry.swift in Sources */, A74770010000000000000007 /* SessionConfigFrameRing.swift in Sources */, C71500020000000000000001 /* SessionContentWidthModifier.swift in Sources */, @@ -10066,6 +10120,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = 0A1107110000000000000022 /* SessionRestorableAgentSnapshot+Commands.swift in Sources */, C54860090000000000000001 /* SessionRestoreIdentityExclusions.swift in Sources */, A50016B1A1B2C3D4E5F60718 /* SessionSnapshotDebugBenchmark.swift in Sources */, + D9E700000000000000000001 /* SessionSnapshotPersistenceWriter.swift in Sources */, D86840000000000000000007 /* SessionSplitContainerLayoutCodec.swift in Sources */, D86840000000000000000009 /* SessionSplitContainerSnapshot.swift in Sources */, FE00310B /* SessionTranscriptPopoverLayout.swift in Sources */, @@ -10305,6 +10360,9 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = B8835A000000000000000001 /* TerminalClipboardInputSequencer+State.swift in Sources */, B88357000000000000000005 /* TerminalClipboardInputSequencer.swift in Sources */, B88357000000000000000013 /* TerminalClipboardRequestSurfaceIdentity.swift in Sources */, + E7C100000000000000000003 /* TerminalCmdClickUITestConfiguration.swift in Sources */, + E7C100000000000000000001 /* TerminalCmdClickUITestCoordinator.swift in Sources */, + E7C100000000000000000005 /* TerminalCmdClickUITestManifestWriter.swift in Sources */, F87910190000000000000001 /* TerminalConfigurationReloadCoordinator.swift in Sources */, F87930000000000000000001 /* TerminalConfigurationReloadEnqueueResult.swift in Sources */, F87920000000000000000005 /* TerminalConfigurationReloadPhase.swift in Sources */, @@ -10537,7 +10595,9 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = B35751000000000000000002 /* TmuxResumeParser.swift in Sources */, E30760050000000000000002 /* TmuxWorkspacePaneOverlayRenderState.swift in Sources */, E30760000000000000000002 /* TmuxWorkspacePaneOverlayView.swift in Sources */, + D9A1B2C3D4E5000000000001 /* UITestDiagnosticsWriter.swift in Sources */, A5001501 /* UITestRecorder.swift in Sources */, + E7F100000000000000000001 /* UITestSocketSanityCoordinator.swift in Sources */, A500120D /* UpdateLogStore.swift in Sources */, A5001208 /* UpdateTitlebarAccessory.swift in Sources */, C2035A070000000000000001 /* URLRequest+BrowserFailedNavigation.swift in Sources */, From b6d250d224748c213b0a364818652e75199b8eec Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 18 Sep 2026 18:32:26 -0700 Subject: [PATCH 2/3] refactor: give main window context independent model ownership --- Sources/AppDelegate.swift | 56 +--------------------------- Sources/CmuxMainWindowContext.swift | 57 +++++++++++++++++++++++++++++ Sources/MainWindowRegistry.swift | 2 +- cmux.xcodeproj/project.pbxproj | 4 ++ 4 files changed, 64 insertions(+), 55 deletions(-) create mode 100644 Sources/CmuxMainWindowContext.swift diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index 5439154f7a66..3cfc6b1496e9 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -593,60 +593,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent MacSentryStartupPolicy.isRunningUnderXCTest(environment: env) } - @MainActor - final class MainWindowContext { - let windowId: UUID - let tabManager: TabManager - let sidebarState: SidebarState - let sidebarSelectionState: SidebarSelectionState - var fileExplorerState: FileExplorerState? - let keyboardFocusCoordinator: MainWindowFocusController - var cmuxConfigStore: CmuxConfigStore? - var closeObserver: WindowCloseObserver? - weak var window: NSWindow? - /// Per-window Dock owned by this context and torn down with it. - var windowDock: DockSplitStore? - private let workspaceTerminalFontSizeArbiter: - WorkspaceTerminalFontSizeArbiter - /// Window-scoped font-size queue. Requests contain stable workspace ids; - /// teardown cancels the queue before any surface owner is released. - lazy var workspaceTerminalFontSizeCoordinator = - WorkspaceTerminalFontSizeCoordinator( - tabManager: tabManager, - arbiter: workspaceTerminalFontSizeArbiter - ) -#if DEBUG - var debugWorkspaceTerminalFontSizeEnqueueResultOverride: Bool? -#endif - - init( - windowId: UUID, - tabManager: TabManager, - sidebarState: SidebarState, - sidebarSelectionState: SidebarSelectionState, - fileExplorerState: FileExplorerState?, - cmuxConfigStore: CmuxConfigStore?, - window: NSWindow?, - workspaceTerminalFontSizeArbiter: - WorkspaceTerminalFontSizeArbiter - ) { - self.windowId = windowId - self.tabManager = tabManager - self.sidebarState = sidebarState - self.sidebarSelectionState = sidebarSelectionState - self.fileExplorerState = fileExplorerState - self.cmuxConfigStore = cmuxConfigStore - self.window = window - self.workspaceTerminalFontSizeArbiter = - workspaceTerminalFontSizeArbiter - self.keyboardFocusCoordinator = MainWindowFocusController( - windowId: windowId, - window: window, - tabManager: tabManager, - fileExplorerState: fileExplorerState - ) - } - } + /// Compatibility name for the independently owned main-window model. + typealias MainWindowContext = CmuxMainWindowContext struct ScriptableMainWindowState { let windowId: UUID diff --git a/Sources/CmuxMainWindowContext.swift b/Sources/CmuxMainWindowContext.swift new file mode 100644 index 000000000000..7c2e844f5e64 --- /dev/null +++ b/Sources/CmuxMainWindowContext.swift @@ -0,0 +1,57 @@ +import AppKit + +/// Owns the models and resource handles scoped to a single main window. +@MainActor +final class CmuxMainWindowContext { + let windowId: UUID + let tabManager: TabManager + let sidebarState: SidebarState + let sidebarSelectionState: SidebarSelectionState + var fileExplorerState: FileExplorerState? + let keyboardFocusCoordinator: MainWindowFocusController + var cmuxConfigStore: CmuxConfigStore? + var closeObserver: WindowCloseObserver? + weak var window: NSWindow? + /// Per-window Dock owned by this context and torn down with it. + var windowDock: DockSplitStore? + private let workspaceTerminalFontSizeArbiter: + WorkspaceTerminalFontSizeArbiter + /// Window-scoped font-size queue. Requests contain stable workspace ids; + /// teardown cancels the queue before any surface owner is released. + lazy var workspaceTerminalFontSizeCoordinator = + WorkspaceTerminalFontSizeCoordinator( + tabManager: tabManager, + arbiter: workspaceTerminalFontSizeArbiter + ) +#if DEBUG + var debugWorkspaceTerminalFontSizeEnqueueResultOverride: Bool? +#endif + + init( + windowId: UUID, + tabManager: TabManager, + sidebarState: SidebarState, + sidebarSelectionState: SidebarSelectionState, + fileExplorerState: FileExplorerState?, + cmuxConfigStore: CmuxConfigStore?, + window: NSWindow?, + workspaceTerminalFontSizeArbiter: + WorkspaceTerminalFontSizeArbiter + ) { + self.windowId = windowId + self.tabManager = tabManager + self.sidebarState = sidebarState + self.sidebarSelectionState = sidebarSelectionState + self.fileExplorerState = fileExplorerState + self.cmuxConfigStore = cmuxConfigStore + self.window = window + self.workspaceTerminalFontSizeArbiter = + workspaceTerminalFontSizeArbiter + self.keyboardFocusCoordinator = MainWindowFocusController( + windowId: windowId, + window: window, + tabManager: tabManager, + fileExplorerState: fileExplorerState + ) + } +} diff --git a/Sources/MainWindowRegistry.swift b/Sources/MainWindowRegistry.swift index c603a9b7a75f..d5a892de4fdf 100644 --- a/Sources/MainWindowRegistry.swift +++ b/Sources/MainWindowRegistry.swift @@ -3,7 +3,7 @@ import AppKit /// Owns the identity index that maps terminal windows to their main-window contexts. @MainActor final class MainWindowRegistry { - typealias Context = AppDelegate.MainWindowContext + typealias Context = CmuxMainWindowContext private(set) var contexts: [ObjectIdentifier: Context] = [:] diff --git a/cmux.xcodeproj/project.pbxproj b/cmux.xcodeproj/project.pbxproj index 2c93b1940bc0..c2c85f21736b 100644 --- a/cmux.xcodeproj/project.pbxproj +++ b/cmux.xcodeproj/project.pbxproj @@ -780,6 +780,7 @@ C0DE71B10000000000000001 /* AppDelegate+AgentChatNotifications.swift in Sources E7D100000000000000000005 /* CmuxMainThreadTurnProfiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7D100000000000000000006 /* CmuxMainThreadTurnProfiler.swift */; }; 2F0C07000000000000000002 /* CmuxMainWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F0C07000000000000000001 /* CmuxMainWindow.swift */; }; D36090010000000000000005 /* CmuxMainWindowConstrainFrameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D36090010000000000000006 /* CmuxMainWindowConstrainFrameTests.swift */; }; + D4A200000000000000000001 /* CmuxMainWindowContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4A200000000000000000002 /* CmuxMainWindowContext.swift */; }; D36090020000000000000005 /* CmuxMainWindowFullScreenCapabilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D36090020000000000000006 /* CmuxMainWindowFullScreenCapabilityTests.swift */; }; 799F1BEF876006EEB8CD1035 /* CMUXMobileCore in Frameworks */ = {isa = PBXBuildFile; productRef = EFB18E3B3099DFE2ECA3C263 /* CMUXMobileCore */; }; EFB18E3C0000000000000001 /* CMUXMobileCore in Frameworks */ = {isa = PBXBuildFile; productRef = EFB18E3B3099DFE2ECA3C263 /* CMUXMobileCore */; }; @@ -3611,6 +3612,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = E7D100000000000000000006 /* CmuxMainThreadTurnProfiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Debug/CmuxMainThreadTurnProfiler.swift"; sourceTree = ""; }; 2F0C07000000000000000001 /* CmuxMainWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/CmuxMainWindow.swift; sourceTree = ""; }; D36090010000000000000006 /* CmuxMainWindowConstrainFrameTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxMainWindowConstrainFrameTests.swift; sourceTree = ""; }; + D4A200000000000000000002 /* CmuxMainWindowContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxMainWindowContext.swift; sourceTree = ""; }; D36090020000000000000006 /* CmuxMainWindowFullScreenCapabilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxMainWindowFullScreenCapabilityTests.swift; sourceTree = ""; }; CA1F0A02CA1F0A02CA1F0A02 /* CmuxModalAlertPresentation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxModalAlertPresentation.swift; sourceTree = ""; }; C54860110000000000000002 /* CmuxNavigationResolution.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxNavigationResolution.swift; sourceTree = ""; }; @@ -6891,6 +6893,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = E7E300000000000000000002 /* SessionAutosaveCoordinator.swift */, FEE012340000000000000002 /* FeedSidebarUITestCoordinator.swift */, D4A100000000000000000002 /* MainWindowRegistry.swift */, + D4A200000000000000000002 /* CmuxMainWindowContext.swift */, E7C100000000000000000002 /* TerminalCmdClickUITestCoordinator.swift */, E7C100000000000000000004 /* TerminalCmdClickUITestConfiguration.swift */, E7C100000000000000000006 /* TerminalCmdClickUITestManifestWriter.swift */, @@ -9387,6 +9390,7 @@ C0DE71B10000000000000002 /* AppDelegate+AgentChatNotifications.swift */ = {isa = E7D100000000000000000003 /* CmuxMainRunLoopStallMonitor.swift in Sources */, E7D100000000000000000005 /* CmuxMainThreadTurnProfiler.swift in Sources */, 2F0C07000000000000000002 /* CmuxMainWindow.swift in Sources */, + D4A200000000000000000001 /* CmuxMainWindowContext.swift in Sources */, CA1F0A01CA1F0A01CA1F0A01 /* CmuxModalAlertPresentation.swift in Sources */, C54860110000000000000001 /* CmuxNavigationResolution.swift in Sources */, C54860120000000000000001 /* CmuxNavigationSurfaceDescriptor.swift in Sources */, From 97a4f2b369bc18e006f466cd009e0c2b5daca93b Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 18 Sep 2026 18:35:05 -0700 Subject: [PATCH 3/3] refactor: route test window mutations through registry --- Sources/AppDelegate.swift | 7 +++++++ Sources/MainWindowRegistry.swift | 10 +++++++++- cmuxTests/AppDelegateMainWindowTestingSupport.swift | 3 ++- cmuxTests/WorkspaceRecoveryTests.swift | 5 ++++- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index 3cfc6b1496e9..1a1b73bb93e8 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -4828,6 +4828,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent NotificationCenter.default.post(name: .mainWindowContextsDidChange, object: self) } +#if DEBUG + /// Inserts a windowless test context without exposing the registry storage. + func insertMainWindowContextForTesting(_ context: MainWindowContext, key: ObjectIdentifier) { + mainWindowRegistry.insert(context, for: key) + } +#endif + func ensureMobileWorkspaceListObserver(for tabManager: TabManager) { let id = ObjectIdentifier(tabManager) let configStore = mainWindowContext(for: tabManager)?.cmuxConfigStore diff --git a/Sources/MainWindowRegistry.swift b/Sources/MainWindowRegistry.swift index d5a892de4fdf..b89edc80aad3 100644 --- a/Sources/MainWindowRegistry.swift +++ b/Sources/MainWindowRegistry.swift @@ -19,7 +19,15 @@ final class MainWindowRegistry { /// Inserts `context` under the window's identity key. func insert(_ context: Context, for window: NSWindow) { - contexts[ObjectIdentifier(window)] = context + insert(context, for: ObjectIdentifier(window)) + } + + /// Inserts `context` under an already-resolved identity key. + /// + /// The key overload keeps test-only windowless contexts on the same mutation + /// path without exposing the registry's backing dictionary to callers. + func insert(_ context: Context, for key: ObjectIdentifier) { + contexts[key] = context } /// Removes every key currently referring to `context`. diff --git a/cmuxTests/AppDelegateMainWindowTestingSupport.swift b/cmuxTests/AppDelegateMainWindowTestingSupport.swift index a36b7c7a4aed..a8eba4e77e67 100644 --- a/cmuxTests/AppDelegateMainWindowTestingSupport.swift +++ b/cmuxTests/AppDelegateMainWindowTestingSupport.swift @@ -64,7 +64,7 @@ extension AppDelegate { fileExplorerState: FileExplorerState? = nil ) -> UUID { tabManager.windowId = windowId - mainWindowContexts[ObjectIdentifier(tabManager)] = MainWindowContext( + let context = MainWindowContext( windowId: windowId, tabManager: tabManager, sidebarState: SidebarState(), @@ -75,6 +75,7 @@ extension AppDelegate { workspaceTerminalFontSizeArbiter: workspaceTerminalFontSizeArbiter ) + insertMainWindowContextForTesting(context, key: ObjectIdentifier(tabManager)) // Context-based tests exercise observer pipelines without a live phone // subscriber; force presence on so the graph attaches (pre-gate // behavior). This is deliberately sticky across tests: any test that diff --git a/cmuxTests/WorkspaceRecoveryTests.swift b/cmuxTests/WorkspaceRecoveryTests.swift index 7ddeba4b8b42..aa32fcd8da1d 100644 --- a/cmuxTests/WorkspaceRecoveryTests.swift +++ b/cmuxTests/WorkspaceRecoveryTests.swift @@ -189,7 +189,10 @@ struct WorkspaceRecoveryTests { workspaceTerminalFontSizeArbiter: appDelegate.workspaceTerminalFontSizeArbiter ) - appDelegate.mainWindowContexts[ObjectIdentifier(sourceContext)] = sourceContext + appDelegate.insertMainWindowContextForTesting( + sourceContext, + key: ObjectIdentifier(sourceContext) + ) appDelegate.tabManager = sourceManager let destinationManager = TabManager(autoWelcomeIfNeeded: false)