Skip to content

Fix crash diagnostic window restore - #6596

Merged
austinywang merged 27 commits into
mainfrom
issue-6593-crash-window
Jun 22, 2026
Merged

austinywang merged 27 commits into
mainfrom
issue-6593-crash-window

Conversation

@austinywang

@austinywang austinywang commented Jun 22, 2026 •

Copy link
Copy Markdown
Contributor

Closes #6593

Repro / investigation

  • Read issue Getting a crash window #6593 via gh issue view; the report is cmux 0.64.16 (96) on macOS 26.5.1 after DMG update/relaunch opening an extra window rooted at .../state/cmux/crash, and closing that window does not stick.
  • Reproduced the behavior through code-path/session-state coverage rather than a cloud-mac GUI VM: crash-storage files could route through default-terminal/external-open handling, and persisted session snapshots rooted at cmux crash storage restored as normal windows.
  • I did not use cloud-mac for this pass because the restore/open-routing state exercises the bug mechanism directly.

Root cause

  • Ghostty crash reports live under cmux-owned crash storage (~/.local/state/cmux/crash, or $XDG_STATE_HOME/cmux/crash).
  • cmux did not special-case those paths in open routing or session persistence, so a diagnostic terminal rooted at .../state/cmux/crash could become ordinary restorable app state.
  • Once persisted, startup restore and close/save flows could revive the diagnostic window after relaunch. A crash-only autosave also needed to preserve the manual-restore backup instead of letting the next startup treat the missing primary snapshot as stale state.

Fix

  • Added a shared crash-storage policy for default and XDG crash directories.
  • Reject cmux crash-storage files/directories in LaunchServices external-open routing and default-terminal executable routing, including symlink-resolved file-open handling.
  • Prune plain local terminal workspaces rooted only in cmux crash storage during startup restore, manual-restore backup sync/fallback load, session save, and crash-diagnostic window close paths.
  • Preserve real user state while pruning: workspaces/panels with scrollback, text box drafts, custom titles, pinning, unread state, git branch, notifications, environment/status/log state, canvas panes, or remote/tmux state are kept.
  • Track the special “primary snapshot was removed because only crash diagnostics remained” case so the manual-restore backup is not erased on the next launch; clear that marker when a valid primary snapshot is saved/loaded or an unusable primary appears.

Tests / validation

  • Added behavior-level regression coverage for default-terminal crash report opens, app snapshot pruning, crash workspace pruning, symlink policy, newest crash-report selection, preservation of workspaces with user state, and the crash-only primary-removal marker.
  • Wired the new test file and new app source file into cmux.xcodeproj.
  • Local non-build guards run: git diff --check, ./scripts/check-pbxproj.sh, ./scripts/lint-pbxproj-test-wiring.sh, python3 scripts/check-package-resolved-policy.py, python3 scripts/swift_file_length_budget.py, and xcrun swiftc -parse -parse-as-library Sources/AppDelegate.swift Sources/AppDelegate+CrashSessionSnapshotRemoval.swift Sources/SessionPersistencePolicy+CrashStorage.swift cmuxTests/CrashDiagnosticSessionPolicyTests.swift.
  • Per task constraint, I did not run reload.sh, launch a dev app, or run bare xcodebuild. CI is the app/test build gate.

Localization

  • No user-facing strings, settings text, menus, docs, command/help text, alerts, or tooltips were added or changed.
  • Localization audit: changed Swift/test files were reviewed for newly introduced bare English; only internal defaults keys and test fixture text were added.

@vercel

vercel Bot commented Jun 22, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jun 22, 2026 2:37pm
cmux-staging Building Building Preview, Comment Jun 22, 2026 2:37pm

@coderabbitai

coderabbitai Bot commented Jun 22, 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

Adds a new SessionPersistencePolicy+CrashStorage.swift extension that detects cmux crash-storage paths and prunes crash-diagnostic windows from session snapshots. The pruning is wired into AppDelegate's startup, restore, save, and window-close flows. External file/directory open requests and TerminalDefaultFileOpenRequest are filtered to reject crash-storage URLs. GhosttyCrashBreadcrumb is updated to scan multiple crash directories. Tests and Xcode project entries are added.

Changes

Crash-Diagnostic Window Pruning

Layer / File(s) Summary
Crash storage path detection utilities
Sources/SessionPersistencePolicy+CrashStorage.swift
Adds static methods to compute default and XDG-state-aware crash directory URLs with deduplication, provides isCmuxCrashStorageURL / isCmuxCrashStoragePath predicates using cached path-component prefix matching, and internal helpers for path standardization, component extraction, and nil-or-blank checks.
Crash-diagnostic window and workspace pruning logic
Sources/SessionPersistencePolicy+CrashStorage.swift
Implements pruningCmuxCrashDiagnosticWindows, pruningCmuxCrashDiagnosticWorkspaces, and isCmuxCrashDiagnosticWorkspace. Classifies workspaces by checking that all panels are plain local terminals with directories inside crash storage, remaps selectedWorkspaceIndex, rewrites workspaceGroups anchors, and returns (snapshot?, removedAny).
GhosttyCrashBreadcrumb multi-directory crash detection
Sources/GhosttyCrashBreadcrumb.swift
Delegates default crash directory resolution to SessionPersistencePolicy.cmuxCrashDirectoryURLs(), adds defaultCrashDirectoryURLs property, and introduces a pendingCrash(in: crashDirectoryURLs: [URL]) overload that scans all directories and selects the newest crash report before applying guards. Single-directory overload now delegates to multi-directory version.
Session snapshot lifecycle pruning in AppDelegate
Sources/AppDelegate.swift
Prunes crash-diagnostic windows during startup snapshot loading and manual-restore cache synchronization, restorePreviousSessionSnapshot, and introduces buildSessionSnapshotResult returning (snapshot, removedCrashDiagnosticState). saveSessionSnapshot widens removeWhenEmpty using that flag.
External open filtering and window unregistration
Sources/AppDelegate.swift, Sources/AppDelegate+CmuxSSHURL.swift
Filters crash-storage paths from externalOpenDirectories and externalOpenFileURLs. TerminalDefaultFileOpenRequest returns nil for crash-storage URLs. Window unregistration determines whether closing window is crash-diagnostic, skips history recording for those windows, and sets removeWhenEmpty: true accordingly. recordClosedWindowHistoryIfNeeded derives workspaceIds from the pruned snapshot.
Tests and Xcode project wiring
cmuxTests/CrashDiagnosticSessionPolicyTests.swift, cmux.xcodeproj/project.pbxproj
Adds CrashDiagnosticSessionPolicyTests covering file-open rejection for crash paths and symlinks, snapshot exclusion of crash windows, workspace pruning with index preservation, symlink non-resolution during classification, and multi-directory breadcrumb selection. Registers both new files in the Xcode build graph.

Sequence Diagram(s)

sequenceDiagram
    participant AppDelegate
    participant SessionPersistencePolicy
    participant GhosttyCrashBreadcrumb
    participant FileSystem

    rect rgba(135, 206, 250, 0.5)
        Note over AppDelegate,SessionPersistencePolicy: Startup / Restore
        AppDelegate->>SessionPersistencePolicy: pruningCmuxCrashDiagnosticWindows(from: snapshot)
        SessionPersistencePolicy->>FileSystem: standardize & compare path components
        FileSystem-->>SessionPersistencePolicy: crash directory match result
        SessionPersistencePolicy-->>AppDelegate: (prunedSnapshot, removedCrashDiagnosticState)
    end

    rect rgba(144, 238, 144, 0.5)
        Note over AppDelegate,SessionPersistencePolicy: External Open / File Request
        AppDelegate->>SessionPersistencePolicy: isCmuxCrashStoragePath(directory)
        SessionPersistencePolicy-->>AppDelegate: true → filter out directory
        AppDelegate->>SessionPersistencePolicy: isCmuxCrashStorageURL(fileURL)
        SessionPersistencePolicy-->>AppDelegate: true → skip file URL
    end

    rect rgba(255, 182, 193, 0.5)
        Note over GhosttyCrashBreadcrumb,SessionPersistencePolicy: Multi-directory crash detection
        GhosttyCrashBreadcrumb->>SessionPersistencePolicy: cmuxCrashDirectoryURLs()
        SessionPersistencePolicy-->>GhosttyCrashBreadcrumb: [defaultURL, xdgURL, ...]
        GhosttyCrashBreadcrumb->>FileSystem: scan each directory for ghosttycrash files
        FileSystem-->>GhosttyCrashBreadcrumb: latest crash per directory
        GhosttyCrashBreadcrumb-->>GhosttyCrashBreadcrumb: select newest across all directories
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • manaflow-ai/cmux#4982: Both PRs modify restorePreviousSessionSnapshot and the session-restore flow in AppDelegate.swift, with this PR's crash-storage pruning layering directly on top of that restore logic.
  • manaflow-ai/cmux#5914: Both PRs modify AppDelegate.prepareStartupSessionSnapshotIfNeeded to change how the startup session snapshot and manual-restore cache are loaded, adding crash-diagnostic pruning alongside other snapshot recovery improvements.

Poem

🐇 A bunny hops past the crash heap,
Pruning bad windows while others sleep,
Symlinks resolved, but dirs stay true,
No ghost crash haunts the session queue!
Each snapshot clean, each breadcrumb fresh —
The rabbit tidies up the mesh. 🌿

🚥 Pre-merge checks | ✅ 22 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (22 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: preventing crash diagnostic windows from being restored during app relaunch, which directly addresses the root cause and fix described in the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed PR introduces no Swift 6 actor isolation violations. New SessionPersistencePolicy extension uses only static nonisolated functions; GhosttyCrashBreadcrumb properly marks enum nonisolated with @conc...
Cmux Swift Blocking Runtime ✅ Passed All production Swift files in the PR introduce no new blocking or timing-based synchronization. The three production files modified (AppDelegate+CmuxSSHURL.swift, GhosttyCrashBreadcrumb.swift, Sess...
Cmux Expensive Synchronous Load ✅ Passed The PR adds crash-storage path validation checks that use cached path-component string comparisons, not expensive agent-history loads or unbounded filesystem scans. The existing resolvingSymlinksIn...
Cmux Cache Substitution Correctness ✅ Passed The pathCache in SessionPersistencePolicy+CrashStorage.swift is a local-scoped intra-function performance optimization (avoids redundant string parsing during single snapshot evaluation), not a glo...
Cmux No Hacky Sleeps ✅ Passed The custom check applies only to TypeScript, JavaScript, shell, and non-Swift build/runtime scripts. All PR changes are Swift code, which is explicitly out of scope (covered by swift-blocking-runti...
Cmux Algorithmic Complexity ✅ Passed All nested loops operate on collections with explicit documented bounds: maxWindowsPerSnapshot (12) and maxWorkspacesPerWindow (128). Total complexity is O(c) where c = 12×128 per save. Path cachin...
Cmux Swift Concurrency ✅ Passed PR introduces modern Swift concurrency: Task.detached with awaited result, @concurrent/@sendable with compiler version checks, proper async functions, and stored Task with lifecycle management. No...
Cmux Swift @Concurrent ✅ Passed PR correctly applies @concurrent annotation to the new nonisolated async pendingCrashFromDefaultStorage function that performs file I/O, with proper @Sendable fallback for older Swift versions, and...
Cmux Swift File And Package Boundaries ✅ Passed New SessionPersistencePolicy+CrashStorage.swift is 296 lines under the 400-line threshold with single responsibility; AppDelegate.swift additions are 110 net lines under the 250-line threshold for...
Cmux Swiftpm Lockfiles ✅ Passed PR adds only Swift source files to Xcode project with correct project.pbxproj updates; no external SwiftPM dependencies or Package.resolved changes were made, so policy conditions do not apply.
Cmux Swift Logging ✅ Passed No logging violations found: zero print/debugPrint/dump/NSLog statements added in production code across all five modified Swift files; changes focus on crash storage policy and snapshot pruning wi...
Cmux User-Facing Error Privacy ✅ Passed PR contains no user-facing errors exposing vendor names, internal providers, environment variables, credentials, or sensitive information; all implementation details remain in source code.
Cmux Full Internationalization ✅ Passed No user-facing strings were introduced; all new code is internal API or test code. No localization files were modified. Existing localized strings continue using proper String(localized:) API.
Cmux Swiftui State Layout ✅ Passed PR contains no SwiftUI View changes; modifications are AppKit/Foundation utilities for crash storage handling. No new ObservableObject, @Published, @State, @Observable, or GeometryReader patterns i...
Cmux Architecture Rethink ✅ Passed PR implements a pure-function correctness fix with clear ownership (SessionPersistencePolicy extension), no timing/blocking/locks, no new state/observers, and applies sanitization at documented sna...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR does not add or materially change standalone cmux-owned windows. Changes are limited to: (1) rejecting crash storage paths in file/directory open routing, (2) pruning crash-diagnostic windows fr...
Cmux Source Artifacts ✅ Passed All changed files are intentional source artifacts: hand-written Swift source code (SessionPersistencePolicy+CrashStorage.swift), test files (CrashDiagnosticSessionPolicyTests.swift), modifications...
Cmux No Test Or Debug Seam In Production Source ✅ Passed PR introduces no test/debug seams in production source. New file SessionPersistencePolicy+CrashStorage.swift (296 lines) contains only production functions. Zero test-seam patterns found in added l...
Description check ✅ Passed The pull request description comprehensively covers all required sections: summary of changes and rationale, testing methodology, validation checks, and a detailed checklist.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-6593-crash-window

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.

@greptile-apps

greptile-apps Bot commented Jun 22, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where Ghostty crash reports stored under cmux's own crash directory (~/.local/state/cmux/crash or $XDG_STATE_HOME/cmux/crash) could open as ordinary terminal windows and then be persisted in session snapshots, causing them to reappear after every relaunch.

  • New crash-storage policy (SessionPersistencePolicy+CrashStorage.swift): centralises crash-directory detection (default + XDG paths), provides isCmuxCrashStoragePath, isCmuxCrashStorageURL, and pruningCmuxCrashDiagnosticWindows with workspace-state preservation (scrollback, text-box drafts, custom titles, pinning, notifications, git branch, remote/tmux state, canvas panes, etc.).
  • Routing guards: crash-storage paths are now rejected in TerminalDefaultFileOpenRequest.init (both pre- and post-symlink-resolution) and in the Finder-service external-open filter.
  • Startup restore and session save: buildSessionSnapshotResult prunes crash-diagnostic windows per-window and tracks whether any were removed; a crashOnlyPrimarySnapshotRemovalMarker in UserDefaults prevents the manual-restore backup from being erased when the primary snapshot was deliberately deleted because it contained only crash diagnostics.

Confidence Score: 4/5

Safe to merge after addressing the window-close misclassification; the rest of the fix is well-structured and covered by tests.

The startup-restore, session-save, routing-guard, and marker-management paths all look correct and are backed by behavioral tests. One concrete defect exists in the window-close path: closingWindowIsCrashDiagnostic is evaluated from a snapshot built with includeScrollback: false, so a crash-directory workspace where the user accumulated terminal scrollback will have terminal.scrollback = nil, terminalCarriesRestorableUserState returns false, the workspace is misclassified as purely diagnostic, and recordClosedWindowHistoryIfNeeded is never called — the user's undo-close entry with their terminal history is silently lost. The PR explicitly promises scrollback-containing workspaces are preserved; this code path violates that contract for the closed-window history case.

Sources/AppDelegate.swift — the closingWindowIsCrashDiagnostic computation in windowWillClose uses includeScrollback: false, which needs attention.

Important Files Changed

Filename Overview
Sources/AppDelegate.swift Session save and window-close paths refactored to prune crash-diagnostic windows. The isCrashDiagnostic check at window close uses includeScrollback: false, causing scrollback-carrying crash workspaces to be misclassified as diagnostic and their undo-close history entry to be silently dropped. All other changes (startup restore fallback, per-window pruning in buildSessionSnapshotResult, maxWindowsPerSnapshot cap, marker management) look correct.
Sources/SessionPersistencePolicy+CrashStorage.swift New file (343 lines, one clear responsibility): crash-storage detection and snapshot pruning logic. Path component comparison, path caching, workspace-state preservation checks, group re-anchoring, and XDG-aware directory enumeration all look correct. No actor isolation or blocking concerns; all methods are static and pure.
Sources/AppDelegate+CrashSessionSnapshotRemoval.swift New 48-line file: manual-restore backup sync and crash-only-primary marker helpers. Marker read/write methods are nonisolated static (UserDefaults is thread-safe). The sync logic correctly preserves a stale backup when the current primary is all-crash-diagnostic. No issues found.
Sources/GhosttyCrashBreadcrumb.swift Refactored to support multiple crash directories (default + XDG); pendingCrash(in:) picks the latest report across all directories via .max. The @concurrent/@Sendable conditional annotation for Swift 6.2+ is correct and the inner Task.detached preserves the original behavior on older compilers.
Sources/AppDelegate+CmuxSSHURL.swift Two guards reject crash-storage paths in TerminalDefaultFileOpenRequest.init — one on the pre-resolved URL and one on the symlink-resolved URL, providing correct two-layer protection. Minor: each guard triggers a fresh cmuxCrashDirectoryURLs computation, but this is called only at file-open time and the overhead is negligible.
cmuxTests/CrashDiagnosticSessionPolicyTests.swift Good behavioral coverage: file-open routing, symlink rejection, snapshot pruning (empty workspace, scrollback preservation, text-box-draft preservation, cross-directory latest-report selection, marker lifecycle). No test coverage for the window-close includeScrollback: false misclassification path.
cmux.xcodeproj/project.pbxproj New source and test files correctly wired into both the app target and the test target. Incidental indentation normalization of three existing entries. No missing or duplicate entries.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Window/File Open] -->|file URL| B{isCmuxCrashStorageURL?}
    B -->|yes| C[Reject – return nil]
    B -->|no| D[Normal open routing]

    E[App Startup] --> F[syncManualRestoreSnapshotCachePruningCrashDiagnostics]
    F -->|primary loaded| G[pruningCmuxCrashDiagnosticWindows]
    G -->|has non-crash windows| H[Save pruned → manual-restore backup]
    G -->|all-crash| I[Keep old backup as-is, clear crashOnly marker]
    F -->|primary missing + marker set| J[Keep backup for next-launch restore]
    F -->|primary unusable| K[Clear crashOnly marker]

    E --> L[loadStartupSessionSnapshotPruningCrashDiagnostics]
    L -->|primary loaded & pruned OK| M[Use pruned snapshot]
    L -->|primary all-crash| N[Fall back to manual-restore backup]
    L -->|primary missing + marker| N

    O[Window Close] --> P{isCrashDiagnostic? includeScrollback:false}
    P -->|yes – all crash| Q[Skip undo-close history, removeWhenEmpty=true, preserveBackup marker]
    P -->|no| R[recordClosedWindowHistoryIfNeeded includeScrollback:true]

    S[Session Save] --> T[buildSessionSnapshotResult includeScrollback:false]
    T --> U[pruningCmuxCrashDiagnosticWindows per window]
    U -->|removedCrashDiagnosticState| V[persistSessionSnapshot, markCrashOnly if empty]
    U -->|kept non-crash windows| W[Save normal snapshot, clear crashOnly marker]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Window/File Open] -->|file URL| B{isCmuxCrashStorageURL?}
    B -->|yes| C[Reject – return nil]
    B -->|no| D[Normal open routing]

    E[App Startup] --> F[syncManualRestoreSnapshotCachePruningCrashDiagnostics]
    F -->|primary loaded| G[pruningCmuxCrashDiagnosticWindows]
    G -->|has non-crash windows| H[Save pruned → manual-restore backup]
    G -->|all-crash| I[Keep old backup as-is, clear crashOnly marker]
    F -->|primary missing + marker set| J[Keep backup for next-launch restore]
    F -->|primary unusable| K[Clear crashOnly marker]

    E --> L[loadStartupSessionSnapshotPruningCrashDiagnostics]
    L -->|primary loaded & pruned OK| M[Use pruned snapshot]
    L -->|primary all-crash| N[Fall back to manual-restore backup]
    L -->|primary missing + marker| N

    O[Window Close] --> P{isCrashDiagnostic? includeScrollback:false}
    P -->|yes – all crash| Q[Skip undo-close history, removeWhenEmpty=true, preserveBackup marker]
    P -->|no| R[recordClosedWindowHistoryIfNeeded includeScrollback:true]

    S[Session Save] --> T[buildSessionSnapshotResult includeScrollback:false]
    T --> U[pruningCmuxCrashDiagnosticWindows per window]
    U -->|removedCrashDiagnosticState| V[persistSessionSnapshot, markCrashOnly if empty]
    U -->|kept non-crash windows| W[Save normal snapshot, clear crashOnly marker]
Loading

Reviews (11): Last reviewed commit: "fix: restore backup after closing crash ..." | Re-trigger Greptile

Comment thread Sources/SessionPersistence.swift Outdated
Comment thread Sources/SessionPersistence.swift Outdated

@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: 2

🤖 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 `@Sources/AppDelegate`+CmuxSSHURL.swift:
- Around line 194-195: The crash-storage exclusion check using
SessionPersistencePolicy.isCmuxCrashStorageURL() is currently applied to
standardizedURL before symlinks are resolved, which allows symlinks pointing
into crash storage to bypass the check. Move the symlink resolution using
resolvingSymlinksInPath() before the guard statement, then apply the
SessionPersistencePolicy.isCmuxCrashStorageURL() check to the symlink-resolved
URL instead of standardizedURL to ensure symlinks are properly validated.

In `@Sources/SessionPersistence.swift`:
- Around line 2163-2166: The anchorWorkspaceId assignment in the code around the
anchorMemberIndex update should be modified to reference the actual kept
anchor's workspace ID instead of the originalAnchorWorkspaceId when the original
anchor has been pruned. After determining the anchorMemberIndex using the
flatMap and fallback to 0, set anchorWorkspaceId to the workspaceId of the
member at that index in keptMembers. This ensures consistency between
anchorMemberIndex and anchorWorkspaceId when the original anchor is no longer in
the kept members list.
🪄 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: a6004eaf-b5ad-42c2-9b29-c2ecd4d9b085

📥 Commits

Reviewing files that changed from the base of the PR and between 6222142 and d05e9c6.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (6)
  • Sources/AppDelegate+CmuxSSHURL.swift
  • Sources/AppDelegate.swift
  • Sources/GhosttyCrashBreadcrumb.swift
  • Sources/SessionPersistence.swift
  • cmuxTests/SessionPersistenceTests.swift
  • cmuxTests/WindowAndDragTests.swift

Comment thread Sources/AppDelegate+CmuxSSHURL.swift Outdated
Comment thread Sources/SessionPersistence.swift Outdated

@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 `@Sources/SessionPersistencePolicy`+CrashStorage.swift:
- Around line 227-230: The compactMap loop over groups repeatedly filters the
same originalWorkspaces and keptWorkspaces collections, resulting in O(groups ×
workspaces) complexity. Before the compactMap operation on groups, create two
dictionaries that map group IDs to their respective workspace members (one for
originalWorkspaces grouped by groupId and one for keptWorkspaces grouped by
groupId). Then replace the filter operations inside the compactMap with direct
dictionary lookups using group.id as the key to achieve constant-time access
instead of repeated collection scans.
🪄 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: 73d9b811-de0e-46a9-a6db-63371a0f5227

📥 Commits

Reviewing files that changed from the base of the PR and between c91106c and 7df66dc.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (3)
  • Sources/SessionPersistencePolicy+CrashStorage.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/CrashDiagnosticSessionPolicyTests.swift

Comment thread Sources/SessionPersistencePolicy+CrashStorage.swift Outdated
@austinywang

Copy link
Copy Markdown
Contributor Author

Addressed the CodeRabbit Cmux Swift @Concurrent note in b0353d5 by using @Concurrent on compiler >= 6.2 with the existing @sendable fallback for older compilers. The current CodeRabbit and Greptile checks are green; the remaining docstring item is CodeRabbit's optional generated warning and this change adds no public package API requiring DocC coverage.

@austinywang
austinywang merged commit c39e4f7 into main Jun 22, 2026
30 checks passed

This branch was successfully deployed

1 active deployment
Preview – cmux — 0d56dd3f Deployed Jun 22, 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.

Getting a crash window

1 participant