Repository navigation
Stagger restored terminal surface spawns - #6149
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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:
📝 WalkthroughWalkthroughIntroduces a ChangesSession-Restore Spawn Pacing
Sequence Diagram(s)sequenceDiagram
rect rgba(173, 216, 230, 0.5)
Note over Workspace: Session Restore
end
participant Workspace
participant TerminalPanel
participant TerminalSurface
participant Scheduler as TerminalSurfaceRestoreSpawnScheduler
participant Delayer as RunLoopTerminalSurfaceRestoreSpawnDelayer
Workspace->>TerminalPanel: newTerminalSurface(runtimeSpawnPolicy: .pacedSessionRestore)
TerminalPanel->>TerminalSurface: init(runtimeSpawnPolicy: .pacedSessionRestore)
Note over TerminalSurface: requiresRestoreSpawnPacing = true
TerminalSurface->>TerminalSurface: createSurface(for: view, source: .normal)
TerminalSurface->>TerminalSurface: shouldPaceRuntimeSurfaceCreation? → true
TerminalSurface->>Scheduler: scheduleRestoredSurfaceSpawn(surfaceId, operation)
Scheduler->>Scheduler: enqueue + start drain Task (once)
loop per queued surface
Scheduler->>TerminalSurface: invoke operation → createSurface(source: .scheduledRestore)
TerminalSurface->>TerminalSurface: create native runtime surface
TerminalSurface->>TerminalSurface: requiresRestoreSpawnPacing = false
alt more surfaces pending
Scheduler->>Delayer: scheduleDelay(for: 125ms)
Delayer-->>Scheduler: timer fires → drainNextReadySpawn
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (2 errors, 1 warning)
✅ Passed checks (18 passed)
✨ Finishing Touches🧪 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 |
…rface-resume # Conflicts: # .github/swift-file-length-budget.tsv
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnScheduler.swift`:
- Around line 15-17: The drain loop in the scheduler repeatedly calls
removeFirst() on the pending array, which shifts all remaining elements each
iteration, creating O(n²) complexity. Replace this with an index-based approach:
maintain an index variable to iterate through the pending array and process
operations at each index position without removing elements during iteration,
then clear the processed elements once the drain loop completes. This avoids
repeated array shifts while maintaining FIFO ordering of the queued operations.
🪄 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: 1be7e990-83c6-4dd1-ba75-4f43fb362029
📒 Files selected for processing (13)
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/ContinuousTerminalSurfaceRestoreSpawnDelayer.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnDelaying.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnScheduler.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeSpawnPolicy.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeSpawnScheduling.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Runtime/TerminalSurfaceRuntimeDependencies.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeLifecycle.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface.swiftPackages/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRestoreSpawnSchedulerTests.swiftSources/GhosttyTerminalView.swiftSources/Panels/TerminalPanel.swiftSources/TerminalSurfaceRuntimeWiring.swiftSources/Workspace.swift
Greptile SummaryThis PR introduces a paced restore-spawn scheduler to serialize native Ghostty terminal surface creation during session restore, preventing simultaneous
Confidence Score: 5/5Safe to merge — the scheduler, its DI seam, and all production wiring are correct with no current defects found on any changed path. The scheduler logic is well-bounded: deduplication via queuedSurfaceIds, a single drain task per cycle, @mainactor isolation throughout, and weak captures at every async boundary. requiresRestoreSpawnPacing clears correctly on the first successful .scheduledRestore creation, and all edge cases (hibernation, teardown, shim-install cancellation, input-demand bypass) are handled with existing guards rather than new timing hacks. The test suite covers the 12-surface burst, coalescing, cadence, and both policy paths deterministically. No files require special attention. Important Files Changed
Reviews (13): Last reviewed commit: "Document pane host attach source bridge" | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface`+RuntimeLifecycle.swift:
- Line 533: The file TerminalSurface+RuntimeLifecycle.swift exceeds the 800-line
threshold and mixes multiple concerns including runtime-surface creation/config
assembly and headless/window lifecycle orchestration. Analyze the file to
identify the major responsibility boundaries, then extract at least one coherent
concern (such as runtime-surface creation logic or lifecycle orchestration
logic) into a separate extension or component file. Ensure each resulting file
or extension focuses on a single clear responsibility and does not exceed 400
lines without clear single responsibility or 800 lines overall, addressing the
concerns that make the runtime path in the createSurface function harder to
safely evolve.
🪄 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: 06f60695-3b85-4216-b584-6196db771d45
⛔ Files ignored due to path filters (1)
.github/swift-file-length-budget.tsvis excluded by!**/*.tsv
📒 Files selected for processing (4)
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RuntimeSurfaceCreationSource.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurface+RestoreSpawnPacing.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeLifecycle.swiftSources/Workspace.swift
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@Packages/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRestoreSpawnSchedulerTests.swift`:
- Around line 102-104: The test is attempting to wait for ids.count delays using
the delayer.waitForDelayCount call, but the scheduler only schedules ids.count -
1 delays, causing the wait to deadlock indefinitely. Change the argument to
delayer.waitForDelayCount from ids.count to ids.count - 1 to match the actual
number of delays the scheduler produces, allowing the test to proceed without
blocking.
🪄 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: 9cd6c9f6-c632-4d8b-afc0-31cf686d48ff
⛔ Files ignored due to path filters (1)
.github/swift-file-length-budget.tsvis excluded by!**/*.tsv
📒 Files selected for processing (4)
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RunLoopTerminalSurfaceRestoreSpawnDelayer.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeLifecycle.swiftPackages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeSurfaceCreation.swiftPackages/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRestoreSpawnSchedulerTests.swift
|
Addressing the Greptile hibernation follow-up on the current head: |
Strategy: -X theirs + cherry-pick fork features back Upstream changes pulled in (highlights): - Stagger restored terminal surface spawns (manaflow-ai#6149) - Configurable Dock max width (manaflow-ai#4385) - Polish canvas minimap navigation (manaflow-ai#6105) - Opt-in AI auto-naming workspaces (manaflow-ai#6071) - Dissolve namespace-enums into value types (manaflow-ai#6126) - Fix stale remote connected state after proxy disconnect (manaflow-ai#4513) - Surface browser Safari (manaflow-ai#6113) - Fix terminal top-row mouse (manaflow-ai#4391) - iOS Shift key support (manaflow-ai#6104) Fork-only features verified intact post-merge: - cmux_term socket handlers: surface.snapshot, screen_text, screen_hash, wait_for_text, wait_for_idle, wait_for_screen_change, wait_for_kind, wait_for_cursor, tui_probe, expect, screen_region (6 handler funcs) - agent-bus: notification.create with $bus dispatch - TerminalSurface.visibleSnapshot() + processHasExited() helpers - skills/cmux-terminal-control/* (13 Python lib files + ORCHESTRATOR_TEMPLATE.md) - HerdrWorkspaceSync + CustomTitleSource.herdrInbound Adapter changes (fork-side): - Drop InternalImportsByDefault from CmuxFeedback/CmuxFeedbackUI packages (default-arg parameter types remained internal-only across modules, blocking FeedbackComposerBridge() construction from cmux app target) - Strip .rawValue from SurfaceKind cases (became plain String) - Add herdrInbound to CustomTitleSource enum - Delete shadowing local enums in ContentView (CommandPaletteOverlayPromotionPolicy, ExtensionSidebarBrowserStackDropPlanner, SidebarDragFailsafePolicy, SidebarDragLifecycleNotification, SidebarMarkdownRenderer, SidebarOutsideDropResetPolicy, SidebarShortcutHintFreezePolicy, SidebarTrailingAccessoryWidthPolicy, SidebarWorkspaceSelectionSyncPolicy, ShortcutHintDebugSettings, ShortcutHintModifierPolicy, FeedbackComposerBridge, FeedbackComposerBridgeError, ExtensionSidebarBrowserStackDropRow, SidebarTabDropIndicatorPredicate, SidebarDropEdge, SidebarDropIndicator) - Delete local TerminalSurfaceClaudeCommandShim (use package's via typealias) - Delete local TerminalSurfaceRuntimeTeardownCoordinator + Request stubs (use package's enqueueRuntimeTeardown public API directly) - Adapt static→instance: CmuxGhosttyConfigSettingEditor.X → ().X, CmuxApplicationSupportDirectories.userDirectories → init(env:).userDirectories - newTerminalSurface/TerminalPanel: thread externalIo: parameter for herdr - Add createReplacementTerminalPanel(in:) overload - Add attachToViewForInputDemand/requestInputDemandSurfaceStartIfNeeded stubs - TerminalSurfaceRuntimeFilesystem.live(): wrap installClaudeCommandShim sync→async - AppDelegate.sortedMainWindowContextsForSessionSnapshot: add includeQuickTerminal param - Wire BackgroundSessionStore + BackgroundSessionsSidebarSection + SidebarSectionDivider in pbxproj (PBXFileReference + PBXBuildFile entries were missing post-merge) - Add SidebarSectionDivider stub View (was referenced but never created) Rebuilt clean against /tmp/cmux-p52 derivedData.
Summary
/usr/bin/login -flpwork startsFixes #6148.
Mechanism
Ghostty's macOS login-shell path intentionally execs
/usr/bin/login -flp <user>, and cmux should not patch the vendored Ghostty source. The cmux-controlled part is session restore: restored terminal surfaces were recreated in a burst, so many login shells could hit PAM and Launch Services simultaneously. This PR marks restored terminal surfaces with a paced runtime spawn policy and serializes native surface creation through a short, injected cadence.Root-Cause Confirmation
ghostty/src/termio/Exec.zigand confirmed the/usr/bin/login -flppath is intentional Ghostty behavior, not the fix target.Workspace.restoreSessionSnapshot/ restored terminal panel creation and confirmed restored terminal surfaces now passruntimeSpawnPolicy: .pacedSessionRestore..immediatedefault and does not route through the restore scheduler.TerminalSurface.createSurface(for:source:)queues restored surfaces before native Ghostty surface creation, so the app layer no longer fans out all restoredloginspawns simultaneously.Testability
The
launchservicesdCPU spike is an OS-level emergent effect and would make a brittle unit test. The deterministic regression guard is the app-layer mechanism: restored surfaces cannot all enter native Ghostty creation at once. A separate failing-test-only commit was not feasible because the scheduler seam and the production wiring have to be introduced together for the package to compile.Testing
swift test --package-path Packages/CmuxTerminaltwelveRestoredSurfaceBurstDrainsOneNativeSpawnPerCadence, which simulates the reported 12-surface restore burst and proves only one native spawn operation is released per cadence.pacedSessionRestoresurfaces enqueue before Ghostty work startsgit diff --checkpython3 scripts/swift_file_length_budget.pylaunchservicesdobservation is intentionally deferred until CI is green and the exact tagged reload command is approved, per the issue workflow.Localization
No user-facing strings were added. The localization audit found only test literals and internal environment/debug values in the Swift diff.
Summary by CodeRabbit
New Features
Tests