Skip to content

Stagger restored terminal surface spawns - #6149

Merged
austinywang merged 22 commits into
mainfrom
issue-6148-stagger-surface-resume
Jun 15, 2026
Merged

austinywang merged 22 commits into
mainfrom
issue-6148-stagger-surface-resume

Conversation

@austinywang

@austinywang austinywang commented Jun 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • pace native Ghostty runtime creation only for terminal surfaces restored from a saved session
  • keep ordinary/new terminal surface creation immediate
  • inject a restore-spawn scheduler so restored terminals queue deterministically before /usr/bin/login -flp work starts
  • add package regression coverage for scheduler cadence, duplicate readiness coalescing, restore-path queuing, requeue behavior when the view is not ready, immediate-spawn bypass, and the reported 12-surface restore burst

Fixes #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

  • Inspected ghostty/src/termio/Exec.zig and confirmed the /usr/bin/login -flp path is intentional Ghostty behavior, not the fix target.
  • Traced cmux session restore through Workspace.restoreSessionSnapshot / restored terminal panel creation and confirmed restored terminal surfaces now pass runtimeSpawnPolicy: .pacedSessionRestore.
  • Confirmed normal/new terminal creation still uses the .immediate default and does not route through the restore scheduler.
  • Confirmed TerminalSurface.createSurface(for:source:) queues restored surfaces before native Ghostty surface creation, so the app layer no longer fans out all restored login spawns simultaneously.

Testability

The launchservicesd CPU 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/CmuxTerminal
    • includes twelveRestoredSurfaceBurstDrainsOneNativeSpawnPerCadence, which simulates the reported 12-surface restore burst and proves only one native spawn operation is released per cadence
    • includes restore-path queuing coverage proving .pacedSessionRestore surfaces enqueue before Ghostty work starts
    • includes immediate-spawn bypass coverage proving ordinary terminals still avoid the restore queue
  • git diff --check
  • python3 scripts/swift_file_length_budget.py
  • Local mechanism inspection confirmed the root cause and app-layer fan-out fix. Dev-build/manual launchservicesd observation 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

    • Session restore now paces native terminal surface creation via a controlled FIFO queue with a short inter-spawn delay, reducing “login-shell stampede” effects during large restores and improving responsiveness.
    • Added a configurable runtime spawn policy for terminals (immediate vs paced session restore), including wiring through workspace restore and terminal panel/surface construction.
    • Input-demand attachment now takes a dedicated path when a surface already exists, ensuring correct behavior for immediate user input.
  • Tests

    • Added deterministic tests covering restore spawn scheduling, cadence/coalescing, and policy behavior.

@vercel

vercel Bot commented Jun 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Canceled Canceled Jun 15, 2026 11:08am
cmux-staging Building Building Preview, Comment Jun 15, 2026 11:08am

@coderabbitai

coderabbitai Bot commented Jun 15, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Introduces a TerminalSurfaceRestoreSpawnScheduler that serializes native terminal surface creation during session restore using a configurable 125ms inter-spawn delay and surface-ID coalescing. A new runtimeSpawnPolicy parameter (.immediate / .pacedSessionRestore) threads from Workspace through TerminalPanel, TerminalSurfaceRuntimeWiring, and TerminalSurface.init down to a RuntimeSurfaceCreationSource-aware createSurface overload that gates paced surfaces into the scheduler and clears pacing state on scheduled completion. Refactors native surface creation into a createNativeRuntimeSurface(...) helper that assembles configuration, environment variables, and C-string marshaling; adds input-demand-triggered attachment and source-threaded Claude shim readiness decisions. Tests validate sequential drain, coalescing, creation-order enforcement, and policy-driven bypass.

Changes

Session-Restore Spawn Pacing

Layer / File(s) Summary
Delay timer protocols and RunLoop implementation
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnDelayCancelling.swift, Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnDelaying.swift, Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/Duration+TimeInterval.swift, Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RunLoopTerminalSurfaceRestoreSpawnDelay.swift, Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RunLoopTerminalSurfaceRestoreSpawnDelayer.swift
Defines TerminalSurfaceRestoreSpawnDelayCancelling (cancel handle), TerminalSurfaceRestoreSpawnDelaying (timer scheduling protocol), and Duration.timeInterval helper; provides RunLoopTerminalSurfaceRestoreSpawnDelay (Timer-backed cancel handle) and RunLoopTerminalSurfaceRestoreSpawnDelayer (production one-shot RunLoop timer conformance).
Spawn policy enum, scheduling protocol, and creation source
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeSpawnPolicy.swift, Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeSpawnScheduling.swift, Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RuntimeSurfaceCreationSource.swift
Adds TerminalSurfaceRuntimeSpawnPolicy (.immediate / .pacedSessionRestore), the @MainActor TerminalSurfaceRuntimeSpawnScheduling protocol, and RuntimeSurfaceCreationSource (.normal / .scheduledRestore / .inputDemand).
TerminalSurfaceRestoreSpawnScheduler FIFO drain loop
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnScheduler.swift
Implements the @MainActor FIFO scheduler: coalesces duplicate surface IDs, enqueues operations, starts a single drain Task, processes entries one-by-one with configurable inter-spawn cooldowns via the injected delayer, and clears state in finishDraining().
TerminalSurface state, init, and dependency wiring
Packages/CmuxTerminal/Sources/CmuxTerminal/Runtime/TerminalSurfaceRuntimeDependencies.swift, Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface.swift
Adds restoreSpawnScheduler, requiresRestoreSpawnPacing, and restoredRuntimeSurfaceStartQueued to TerminalSurface; extends TerminalSurfaceRuntimeDependencies with restoreSpawnScheduler; extends TerminalSurface.init with runtimeSpawnPolicy and derives the pacing flag from it.
Restore-spawn pacing decision and enqueueing
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurface+RestoreSpawnPacing.swift
Adds shouldPaceRuntimeSurfaceCreation(source:) (checks pacing requirement, source, and surface state) and enqueueRestoredRuntimeSurfaceCreation(for:) (guards duplicate enqueueing, schedules restore spawn with weak view/window re-validation).
Runtime lifecycle pacing routing and source-aware creation
Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeLifecycle.swift
Routes background-start through source: .normal entry; new createSurface(for:source:) overload intercepts paced surfaces and enqueues them, bypassing immediate creation; clears pacing flag on .scheduledRestore and .inputDemand completion; delegates core creation to createNativeRuntimeSurface(...).
Native runtime surface creation assembly and config
Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeSurfaceCreation.swift
Builds ghostty_surface_config_s and constructs environment variables (CMUX identifiers, port range, Claude shim paths, hooks, shell integration); resolves working directory and initial input; marshals C strings and returns created surface plus runtime input. Includes withOptionalCString and makeGhosttySurface helpers.
Input-demand attachment and Claude shim readiness
Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+InputDemandLifecycle.swift, Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+ClaudeCommandShimLifecycle.swift
Adds attachToViewForInputDemand(_:) for immediate user-input-driven surface creation with source .inputDemand, bypassing the restore queue; adds claudeCommandShimStateForSurface(view:source:) to manage shim installation and readiness, threading the creation source through shim state decisions.
App-level scheduler instantiation and spawn-policy propagation
Sources/GhosttyTerminalView.swift, Sources/TerminalSurfaceRuntimeWiring.swift, Sources/Panels/TerminalPanel.swift, Sources/Workspace.swift
Creates process-wide terminalSurfaceRestoreSpawnScheduler static on GhosttyApp; threads runtimeSpawnPolicy through TerminalSurfaceRuntimeWiring, TerminalPanel, and Workspace initializers; session restore calls newTerminalSurface with .pacedSessionRestore; input-demand path uses attachToViewForInputDemand.
TerminalSurfaceRestoreSpawnScheduler tests and test doubles
Packages/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRestoreSpawnSchedulerTests.swift
Adds TerminalSurfaceRestoreSpawnSchedulerTests with ManualRestoreSpawnDelayer (continuation-based blocking), RecordingRestoreSpawnScheduler, and fake collaborators covering sequential drain, coalescing, creation order, re-queuing on unready view, and immediate-policy bypass.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • manaflow-ai/cmux#6055: Both PRs modify terminal surface creation during session restore by changing Sources/Workspace.swift's newTerminalSurface(...) wiring (main PR adds runtimeSpawnPolicy to pace restored spawns; related PR adds cwd-inheritance flags to fix Cmd+T cwd).

Suggested reviewers

  • lawrencecchen

Poem

🐇 Hop by hop, not all at once,
shells line up and skip the stunts.
No stampede to launchservicesd,
each login waits its turn, undistressed.
125ms between each spawn,
the CPU breathes — the lag is gone! 🌿


Important

Pre-merge checks failed

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

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Concurrency ❌ Error PR introduces fire-and-forget Tasks with real lifecycle not stored/tracked: (1) TerminalSurface+ClaudeCommandShimLifecycle uses Task { @mainactor } awaiting installTask within regular method, not... Store the fire-and-forget Tasks or use async continuation/structured concurrency instead. Pattern #2 in ClaudeCommandShimLifecycle should store Task or await it, and Pattern #1 should document Timer boundary exception clearly if intentio...
Cmux Swift @Concurrent ❌ Error File I/O-heavy async work in claudeCommandShimStateForSurface lacks @concurrent annotation; the @MainActor method at line 4 spawns Task.detached with nonisolated async closure performing file opera... Mark the async closure at line 24 as @concurrent: let installOperation: @concurrent @Sendable () async -> ClaudeCommandShim?
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (18 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Stagger restored terminal surface spawns' directly and clearly describes the main change: implementing a staggered spawning mechanism for restored terminal surfaces.
Description check ✅ Passed The PR description comprehensively covers the summary, testing approach, and mechanism. It provides context on the root cause, confirms the fix approach, and describes test coverage including the 12-surface burst test.
Linked Issues check ✅ Passed The PR directly addresses #6148 by implementing staggered native surface spawning through a paced scheduler. The changes implement deterministic serialization of restored terminal creation with a 125ms cadence, preventing concurrent /usr/bin/login invocations that overwhelmed launchservicesd.
Out of Scope Changes check ✅ Passed All changes are directly related to introducing restore-spawn pacing and staggering mechanisms. No unrelated modifications to unrelated features or systems are present.
Cmux Swift Actor Isolation ✅ Passed All new public protocols/implementations are explicitly @MainActor-annotated; all value-type enums are Sendable; all methods using the scheduler are @MainActor; closures are properly typed @escapin...
Cmux Swift Blocking Runtime ✅ Passed No blocking synchronization patterns introduced. Timer-based pacing uses RunLoop callbacks, not sleep/semaphore/locks. Test scaffolding uses allowed CheckedContinuation patterns.
Cmux Expensive Synchronous Load ✅ Passed PR adds pacing scheduler (not a synchronous loader) for terminal spawn sequencing. No expensive loaders like RestorableAgentSessionIndex.load() on main actor or interactive paths. The scheduler use...
Cmux Cache Substitution Correctness ✅ Passed PR introduces restore spawn pacing without cache substitution issues. All restored surface checks are fresh (UUID, surface == nil, attachedView, window state), the scheduler maintains transient que...
Cmux No Hacky Sleeps ✅ Passed This check applies only to TypeScript, JavaScript, shell, and build/runtime scripts; Swift timing is explicitly out of scope and covered by a separate check. PR contains only Swift code changes.
Cmux Algorithmic Complexity ✅ Passed Scheduler uses O(1) Set membership tests, linear single-pass drain via monotonic index; PATH.split().contains() is per-surface O(bounded_constant), not per-batch rescans; no violations of nested co...
Cmux Swift File And Package Boundaries ✅ Passed PR maintains clear file and package boundaries per .github/review-bot-rules/swift-file-package-boundaries.md. All new production files are under 400 lines with single clear responsibilities; the...
Cmux Swift Logging ✅ Passed No violations of swift-logging.md rules found: no print/debugPrint/dump/NSLog in production code; environment variables guarded with #if DEBUG; no unredacted secrets or personal data logging; no fi...
Cmux User-Facing Error Privacy ✅ Passed PR adds only internal mechanisms (protocols, schedulers, timers) for pacing terminal spawns; no user-facing errors, alerts, or sensitive information exposed per policy.
Cmux Full Internationalization ✅ Passed PR adds only internal protocol/enum definitions with documentation comments, test fixtures, and parameter forwarding. No user-facing UI text, alerts, messages, or localization-dependent strings are...
Cmux Swiftui State Layout ✅ Passed PR adds terminal restore spawn scheduling at model layer without violating SwiftUI state patterns. New properties (restoreSpawnScheduler, requiresRestoreSpawnPacing) are not @Published; no new Obse...
Cmux Architecture Rethink ✅ Passed This PR introduces a required platform bridge to serialize macOS /usr/bin/login spawns via time-cadenced delivery, not a symptom patch hiding bad state. Clear ownership: TerminalSurface owns pacing...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR adds scheduling and lifecycle protocols for terminal spawn pacing; no NSWindow, NSPanel, NSWindowController, SwiftUI Window, or WindowGroup types introduced or materialized.
Cmux Source Artifacts ✅ Passed All 21 files added/modified are hand-written Swift source, tests, and extensions with clear product purpose; no artifacts, logs, build output, or scratch directories detected.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-6148-stagger-surface-resume

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In
`@Packages/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

📥 Commits

Reviewing files that changed from the base of the PR and between e8c137e and b32899d.

📒 Files selected for processing (13)
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/ContinuousTerminalSurfaceRestoreSpawnDelayer.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnDelaying.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnScheduler.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeSpawnPolicy.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeSpawnScheduling.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Runtime/TerminalSurfaceRuntimeDependencies.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeLifecycle.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface.swift
  • Packages/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRestoreSpawnSchedulerTests.swift
  • Sources/GhosttyTerminalView.swift
  • Sources/Panels/TerminalPanel.swift
  • Sources/TerminalSurfaceRuntimeWiring.swift
  • Sources/Workspace.swift

@greptile-apps

greptile-apps Bot commented Jun 15, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a paced restore-spawn scheduler to serialize native Ghostty terminal surface creation during session restore, preventing simultaneous /usr/bin/login PAM and Launch Services bursts. Normal terminal creation remains immediate; only session-restored surfaces route through the new FIFO queue with a 125ms inter-spawn delay backed by a main run-loop timer (replacing the previously-flagged ContinuousClock().sleep).

  • Adds TerminalSurfaceRestoreSpawnScheduler with a full DI seam (TerminalSurfaceRestoreSpawnDelaying/TerminalSurfaceRestoreSpawnDelayCancelling), manual test doubles, and deterministic tests including the reported 12-surface burst scenario.
  • Extracts native surface config assembly into TerminalSurface+RuntimeSurfaceCreation.swift, adds RuntimeSurfaceCreationSource to carry spawn-policy context through the creation call chain, and adds requestInputDemandSurfaceStartIfNeeded() so user-driven input bypasses restore pacing.
  • Cancels the Claude command shim completion task on teardown/hibernation to prevent stale post-teardown surface creation attempts.

Confidence Score: 5/5

Safe 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

Filename Overview
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRestoreSpawnScheduler.swift New FIFO restore-spawn scheduler; head-index drain, deduplication via Set, and post-spawn cooldown are correct; @mainactor isolation throughout is sound.
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RunLoopTerminalSurfaceRestoreSpawnDelayer.swift Production run-loop timer correctly replaces the previously flagged ContinuousClock().sleep; redundant timer.invalidate() in the one-shot callback is harmless but misleading.
Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RestoreSpawnPacing.swift Pacing guard conditions (requiresRestoreSpawnPacing, restoredRuntimeSurfaceStartQueued, attachedView === view) correctly protect against duplicate enqueuing and stale-view callbacks.
Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RuntimeSurfaceCreationSource.swift Clean enum with priority-based promotion used to escalate creation source through async shim-install and headless window paths; semantics are correct.
Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+ClaudeCommandShimLifecycle.swift Shim install lifecycle correctly tracks pending creation source; new claudeCommandShimCompletionTask cancellation prevents stale post-teardown calls.
Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeSurfaceCreation.swift Extraction of native surface config assembly; strdup pair now correctly frees keyPtr before continue on null valuePtr.
Sources/Workspace.swift Only restored sessions receive runtimeSpawnPolicy: .pacedSessionRestore; new-terminal creation keeps the .immediate default.
Sources/GhosttyTerminalView.swift Singleton scheduler wired into terminalSurfaceRuntimeDependencies; liveSurfaceForInput uses attachToViewForInputDemand to bypass restore pacing on interactive input.
Sources/AppDelegate.swift Removed stale requestBackgroundSurfaceStartIfNeeded() call; new requestInputDemandSurfaceStartIfNeeded() correctly positioned inside text-send path.
Packages/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRestoreSpawnSchedulerTests.swift Comprehensive deterministic tests covering cadence, coalescing, late enqueue, 12-surface burst, and both policy paths.

Reviews (13): Last reviewed commit: "Document pane host attach source bridge" | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In
`@Packages/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

📥 Commits

Reviewing files that changed from the base of the PR and between b32899d and 845445a.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (4)
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RuntimeSurfaceCreationSource.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurface+RestoreSpawnPacing.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeLifecycle.swift
  • Sources/Workspace.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In
`@Packages/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

📥 Commits

Reviewing files that changed from the base of the PR and between 37bad38 and ea30193.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (4)
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/RunLoopTerminalSurfaceRestoreSpawnDelayer.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeLifecycle.swift
  • Packages/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeSurfaceCreation.swift
  • Packages/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRestoreSpawnSchedulerTests.swift

@austinywang

austinywang commented Jun 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Addressing the Greptile hibernation follow-up on the current head: requiresRestoreSpawnPacing is only initialized from runtimeSpawnPolicy == .pacedSessionRestore and is cleared after the first successful .scheduledRestore or .inputDemand native surface creation in TerminalSurface+RuntimeLifecycle.swift. That means post-hibernation respawns of a successfully restored terminal do not re-enter the restore queue; if initial native creation fails before a surface exists, keeping the flag true is intentional so the retry remains paced instead of joining a concurrent restore burst.

@austinywang
austinywang merged commit 5c84fde into main Jun 15, 2026
24 checks passed
hhsw2015 pushed a commit to hhsw2015/cmux that referenced this pull request Jun 15, 2026
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.

This branch was successfully deployed

1 active deployment
Preview – cmux — 2bed889a Deployed Jun 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

High CPU: simultaneous surface resume stampedes /usr/bin/login -flp, pinning launchservicesd (240–320%)

1 participant