Skip to content

Keep background attention from raising Stage Manager windows - #9776

Merged
austinywang merged 111 commits into
mainfrom
issue-9466-stage-manager-raise
Aug 11, 2026
Merged

austinywang merged 111 commits into
mainfrom
issue-9466-stage-manager-raise

Conversation

@austinywang

@austinywang austinywang commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • keep blocking agent-decision attention in cmux-owned lifecycle, sidebar status, and workspace ordering without asking AppKit for process-level attention
  • preserve terminal BEL audio and visual attention by routing the originating pane through cmux-owned unread/flash state with shouldFocus: false
  • require a concrete terminal surface owner before routing BEL attention, so app-target or stale callbacks cannot guess a workspace

Root cause and architecture

Both FeedCoordinator.surfaceBlockingDecisionAttention and GhosttyApp.ringBell() called NSApplication.requestUserAttention(.informationalRequest) for background activity. On macOS 26 with Stage Manager, that process-level request can promote cmux's entire window set even though the user is working in another application.

This removes process-level AppKit attention from both background paths. Feed attention is lifecycle/sidebar/workspace state. Terminal BEL is split into an audio-only TerminalBellService and a cmux-owned route that resolves the live surface owner, marks inactive panes unread, and flashes without changing selection or focus. The invalid Stage Manager state is unavailable at those boundaries instead of being conditionally suppressed by OS version or focus timing.

Regression evidence and verification

  • Regression red: https://github.com/manaflow-ai/cmux/actions/runs/31148444890 at c2e9a50145 executed the focused suite and failed because the pre-fix Feed path issued one AppKit attention request.
  • Initial fix green: https://github.com/manaflow-ai/cmux/actions/runs/31149265992 at 1d7626f5a0 passed the same selected suite.
  • Current tests exercise Feed needs-input state, terminal BEL unread routing without workspace selection changes, and injected audio behavior. The current fixture deliberately avoids global NSApplication swizzling because Swift Testing suites run in parallel; the historical red run records the pre-fix AppKit call.
  • cmux-policy-check --mode branch --base origin/main is clean at e0bdf48c5a.
  • Swift parsing passed for all changed Swift files, and TerminalBellService.swift typechecked standalone with warnings treated as errors.
  • macOS 26 GUI repro was attempted through https://github.com/manaflow-ai/cmux-loader/actions/runs/31146605098. Provisioning completed after the local wrapper timed out, but the host was unreachable, so no verified cloud video is claimed.
  • No local xcodebuild tests or XCUITests were run, per task constraints. Standalone SwiftPM testing is blocked by the checkout's invalid local GhosttyKit artifact; GitHub Actions owns the app/package test proof.

Audit

  • No user-facing strings changed; localization catalogs were audited and are untouched.
  • No Swift warning-budget or file-length-budget files changed.

Fixes #9466


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Note

Medium Risk
Broad changes to notification navigation, unread projections, Dock focus/open, and terminal input attribution across core macOS UX paths; well-covered by package tests but high interaction surface for regressions.

Overview
Removes reliance on process-level AppKit attention for background activity and keeps bells, unread, and navigation inside cmux-owned state so Stage Manager does not promote the whole window set.

Terminal bells split into audio-only TerminalBellService / TerminalBellPresentation and host-routed visual attention via onVisualBell; explicit terminal input is attributed only after acceptance (onExplicitInput), including copy mode, mobile gestures, and queued socket input, while workspace font-size shortcuts no longer fan out as per-surface explicit input.

Notifications and unread treat per-window Dock surfaces as distinct owners (WindowDockUnreadTarget, FocusedNotificationTarget workspace vs windowDock); jump/mark-oldest and open paths can reveal a Dock, exclude an exact Dock target, and return dockUnavailable when reveal fails. SidebarUnreadModel is refactored with owner-scoped surface projections, summary/surface observers, and synchronous observation teardown; dismissal can clear store-level manual unread on specific surfaces. liveSurfaceOwner separates live ownership from renderable notification opens; Dock session restore/autosave wires notificationStore and manual-unread fingerprints.

CI: e2e executed-test parsing sums every XCTest/Swift Testing summary so a later zero-test host teardown cannot zero out a real run.

Reviewed by Cursor Bugbot for commit af914dd. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Stops Stage Manager from promoting cmux windows by removing process-level AppKit attention and keeping all background attention inside cmux. Terminal bells are audio-only; visual BEL/unread route to the exact live owner (workspace or per‑window Dock) with fail‑closed navigation, precise owner‑scoped open/scroll restore, and clear Dock‑availability errors (fixes #9466).

  • Bug Fixes

    • Docks: preflight reveal and fail closed; focus/open return unavailable/dockUnavailable with a localized “Dock could not be revealed”; notification opens target the exact per‑window Dock via openWindowDockUnread and clear only that surface’s manual unread; hidden workspace‑Dock notifications are ignored; manual unread stays constant‑time, survives owner transfer and snapshot/autosave; precise window‑Dock scroll capture/restore; socket focus results include dockUnavailable.
    • Terminal bells: added audio‑only playback in CmuxTerminal (TerminalBellService + TerminalBellPresentation); route visual BEL via onVisualBell to the live owner (incl. projected/mirrored terminals and sidebar focus); suppress when already focused; bound/coalesced notification‑style flashes.
    • Unread/input: notify owners only after accepted input (onExplicitInput) for copy‑mode, mobile actions, and queued socket input; workspace font‑size shortcuts no longer count as explicit input.
    • Mobile/CI: mobile previews throttle bursts with a coalescer; CI counts all XCTest and Swift Testing run summaries so a later zero‑test teardown can’t erase real executed counts.
  • Refactors

    • Ownership/navigation: split live ownership from renderable opens (liveSurfaceOwner); FocusedNotificationTarget distinguishes workspace vs window‑Dock owners; introduced WindowDockUnreadTarget; focused jump can exclude a specific Dock target; navigation/store seams add window‑Dock unread routes and clearing.
    • Unread/attention: introduced SidebarUnreadModel, owner‑keyed SidebarSurfaceUnreadProjection, SurfaceAttentionModel, and WorkspacePanelUnreadModel, with synchronous teardown via ObservationDeliveryLifetime; snapshots carry latest notification id/time; mobile derives from unread snapshots.
    • Feed attention: introduced FeedAttentionTarget; attention lives in cmux lifecycle/sidebar state—no NSApplication.requestUserAttention.

Written for commit af914dd. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added configurable terminal bells using system sounds or custom audio.
    • Visual bells now mark relevant unfocused surfaces as unread and provide attention flashes without activating the app.
    • Added precise unread navigation for Dock surfaces.
    • Added agent “needs input” attention indicators.
    • Added clear errors when Dock surfaces cannot be revealed or focused.
  • Bug Fixes

    • Surface-specific unread indicators are cleared on dismissal.
    • Unread state persists through Dock transfers and session restoration.
    • Duplicate notification flashes are prevented.
    • Bell notifications no longer trigger while the app and terminal are focused.

@coderabbitai

coderabbitai Bot commented Aug 7, 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 main-actor terminal bell playback, surface-scoped unread tracking, Dock-aware attention routing, fail-closed focus behavior, and expanded lifecycle and routing tests.

Changes

Terminal bell and explicit input

Layer / File(s) Summary
Bell playback and input callbacks
Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Services/Bell/*, Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Surface/*
Adds configurable system/custom bell playback and reports accepted terminal input through surface callbacks.
Bell and attention integration
Sources/GhosttyTerminalView.swift, Sources/Workspace+AttentionFlashRouting.swift, Sources/DockSplitStore+AttentionRouting.swift, Sources/Panels/TerminalPanel.swift
Routes bells to their originating surfaces, marks inactive surfaces unread, dismisses state after accepted input, and coalesces notification flashes.

Unread state and Dock navigation

Layer / File(s) Summary
Surface unread model and storage
Packages/macOS/CmuxNotifications/Sources/CmuxNotifications/*, Sources/TerminalNotificationStore.swift, Sources/DockSplitStore+SurfaceTransfer.swift, Sources/DockSplitStore+Session*
Adds owner-scoped unread projections, surface manual-unread storage, dismissal integration, transfer handling, and session persistence.
Window-Dock navigation and focus
Packages/macOS/CmuxNotifications/Sources/CmuxNotifications/*, Sources/AppDelegate+Notification*, Sources/TerminalController*, Sources/MainWindowFocusController.swift, Packages/macOS/CmuxControlSocket/*
Opens and focuses exact Dock surfaces, supports Dock unread jump fallback, and returns unavailable when a Dock cannot be revealed.

Feed attention lifecycle

Layer / File(s) Summary
Dock-aware Feed attention
Sources/Feed/*, Sources/AppDelegate+DockAttentionRouting.swift, Sources/AgentDeliveryTargetResolution.swift, Sources/Workspace+PanelLifecycle.swift, Sources/DockSplitStore+RestoredAgentLifecycle.swift
Resolves live workspace or Dock ownership, stores panel-stable lifecycle state, preserves overlapping attention, and removes process-level bell requests.

Validation

Layer / File(s) Summary
Routing and attention validation
cmuxTests/DockRuntimeParityTests.swift, cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift, cmuxTests/PiFeedDockOwnershipTests.swift, cmuxTests/WindowDockRoutingSocketTests.swift, cmuxTests/DockSessionPersistenceTests.swift
Covers Dock routing, terminal bells, focus rejection, flash coalescing, Feed ownership, surface transfer, and session restoration.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

  • manaflow-ai/cmux-dev-artifacts#9659: Concerns live surface ownership, notification routing, lifecycle attention, and related regression paths changed here.
  • manaflow-ai/cmux-dev-artifacts#9507: Concerns the modified GhosttyEnsureFocusWindowActivationTests target.
  • manaflow-ai/cmux-dev-artifacts#9527: Concerns execution of the modified activation and attention test suite.

Possibly related PRs

Suggested reviewers: lawrencecchen, azooz2003-bit


Important

Pre-merge checks failed

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

❌ Failed checks (3 errors, 1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Cmux Swift Blocking Runtime ❌ Error MobileWorkspaceListObserver adds an 80 ms NotificationBurstCoalescer; its production scheduler uses DispatchSourceTimer for trailing synchronization, which the rule forbids by default. Replace timer-based coalescing with a post-mutation callback, state transition, or async sequence that emits after indexes update; do not add a delayed scheduler in production.
Cmux Algorithmic Complexity ❌ Error Sources/TerminalNotificationStore.swift:824 rescans the full recency array for every key in clearSurfaceManualUnread; markNotificationFeedUnread batches keys, making cleanup O(K×T) on a socket path. Batch removals by collecting target keys and filtering the recency array once, or maintain a dictionary/Set index that removes each WindowDockUnreadTarget in O(1).
Cmux Architecture Rethink ❌ Error Unread and agent rings can go stale: new observer-backed projections duplicate TerminalNotificationStore/DockSplitStore state, and DockUnreadPanelProjection may create an independent SurfaceAttenti... Keep the stores as the sole sources of truth; make views consume value snapshots, require an injected attention source, and remove imperative observer/token state as the first migration cut.
Docstring Coverage ⚠️ Warning Docstring coverage is 22.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Swift Package Boundaries ❓ Inconclusive Investigation in progress. Need inspect changed production boundaries and package manifests.
✅ Passed checks (20 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #9466 by removing process-level attention and routing background activity through cmux-owned state without activation.
Out of Scope Changes check ✅ Passed The Dock, unread-state, persistence, and focus-routing changes support the stated attention-routing objective and fail-closed behavior.
Cmux Swift Actor Isolation ✅ Passed New mutable models and TerminalBellService are explicitly @MainActor; WindowDockUnreadTarget is nonisolated Sendable; Feed and bell background callbacks hop to MainActor, with no new unsafe Sendabl...
Cmux Browser Automation Off-Main ✅ Passed The diff only adds fail-closed Dock reveal guards to main-actor browser focus commands at TerminalController.swift:8709 and :8874; no worker-lane automation or policy set changed.
Cmux Expensive Synchronous Load ✅ Passed The PR adds no expensive synchronous agent-history or large-file load. Existing RestorableAgentSessionIndex fallbacks are unchanged, and SharedLiveAgentIndex loads via Task.detached.
Cmux Cache Substitution Correctness ✅ Passed Snapshot code reads TerminalNotificationStore directly for global Dock unread state; transfer state is captured at detach and restored explicitly, with no fresh-load substitution found.
Cmux No Hacky Sleeps ✅ Passed The diff contains 83 changed Swift files and no TypeScript, JavaScript, shell, or non-Swift runtime files; this rule is therefore not applicable.
Cmux Swift Concurrency ✅ Passed The PR adds no background Dispatch, new Combine state, or internal completion API; production Tasks are main-actor observer cleanup hops, and detached Tasks are test-only synchronization.
Cmux Swift @Concurrent ✅ Passed The diff adds no @concurrent or nonisolated async declarations. New tasks are @MainActor cleanup or explicit Task.detached test hops; bell and attention work remains synchronous and actor-bound.
Cmux Swiftpm Lockfiles ✅ Passed The PR diff has no Package.swift, Package.resolved, .gitignore, Xcode project/workspace, or workflow changes, so the SwiftPM lockfile policy is not triggered.
Cmux Swift Logging ✅ Passed The PR adds only #if DEBUG cmux diagnostic logs in Feed/AppDelegate; no print, NSLog, file/stdout logging, secret logging, or Logger declaration is added.
Cmux User-Facing Error Privacy ✅ Passed New command/API errors use generic localized Dock text; added Feed diagnostics are DEBUG-only logs, with no forbidden vendor names, raw upstream messages, credentials, tokens, or payloads in user-f...
Cmux Full Internationalization ✅ Passed Production additions contain no new UI copy; new Dock errors reuse existing String(localized:) key, Feed status remains localized, and no catalog or web locale files changed.
Cmux Swiftui State Layout ✅ Passed Changed state models use @Observable; the diff adds no new legacy wrappers, GeometryReader, lazy/list row store references, or render-time state writes. DockPanelView only injects attention into ex...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The diff adds no production standalone windows; new NSWindow instances are test-only fixtures. Sources/cmuxApp.swift is unchanged and lint_auxiliary_window_close_shortcuts.py passes.
Cmux Source Artifacts ✅ Passed All 83 changed paths are Swift source or tests; no artifact-pattern paths, binary files, generated outputs, caches, or build directories were added.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The PR adds no new test/debug seam in production Swift; existing FeedCoordinator hooks and flash counters are not worsened, and TerminalBellService uses ordinary injected dependencies with a public...
Cmux No Ambient Global State ✅ Passed New runtime state is instance-owned by constructable models and injectable TerminalBellService; the diff adds no file-scope API functions, global mutable vars, or singleton declarations.
Description check ✅ Passed The description clearly explains the change, root cause, scope, and verification, with only non-critical template sections omitted.
Title check ✅ Passed The title clearly and concisely describes preventing background attention from raising Stage Manager windows.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-9466-stage-manager-raise

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.

@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 `@cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift`:
- Around line 69-102: The test backgroundAgentAttentionStaysInsideCmux currently
bypasses the blocking ingest path and does not verify AppKit attention behavior.
Update it to submit the permission request through the blocking event ingestion
API, inject or use a spy/stub for NSApplication.requestUserAttention, and assert
that no attention request occurs while preserving the existing sidebar,
lifecycle, and cleanup assertions.

In `@Sources/AppDelegate`+DockAttentionRouting.swift:
- Around line 71-79: Make terminal-bell attention routing fail closed when no
originating surface is provided: in
Sources/AppDelegate+DockAttentionRouting.swift lines 71-79, remove the
fallbackTarget-based surface/tab derivation and require surfaceID before
resolving notificationSurfaceOwner; in Sources/GhosttyTerminalView.swift lines
3104-3107, preserve audio playback for app-target bells but skip pane-attention
requests when the bell lacks a surface identifier.
🪄 Autofix

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 Plus

Run ID: e6039567-7b66-4215-b6a6-23bf199fb7c6

📥 Commits

Reviewing files that changed from the base of the PR and between ce41f15 and a7c7a0b.

📒 Files selected for processing (6)
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Services/Bell/TerminalBellService.swift
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/Services/Bell/TerminalBellServiceTests.swift
  • Sources/AppDelegate+DockAttentionRouting.swift
  • Sources/Feed/FeedCoordinator.swift
  • Sources/GhosttyTerminalView.swift
  • cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift

Comment thread cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift
Comment thread Sources/AppDelegate+DockAttentionRouting.swift Outdated
@austinywang

Copy link
Copy Markdown
Contributor Author

@coderabbitai Re-evaluated the pre-merge “test/debug seam” error against the current code and repository policy. This is not a test-only production hook: the public production TerminalBellService.init() calls the designated initializer to compose the real NSSound.beep / NSSound(contentsOfFile:) adapters. The closures are constructor-injected side-effect dependencies, which is the testability pattern required by cmux-architecture; they contain no debug/test naming, conditional compilation, mutable global override, or static hook. Removing this boundary would force process-global NSSound/AppKit interception—the unsafe pattern deliberately removed from the Swift Testing fixture. cmux-policy-check --mode branch --base origin/main is clean at e0bdf48c5a. All new public symbols have DocC; the designated initializer is package-internal. Please withdraw this false positive.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

service="Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Services/Bell/TerminalBellService.swift"
tests="Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/Services/Bell/TerminalBellServiceTests.swift"

ast-grep outline "$service" --items all --view expanded
printf '\n--- service ---\n'
cat -n "$service"

printf '\n--- tests ---\n'
cat -n "$tests"

printf '\n--- relevant references ---\n'
rg -n -C 3 --glob '*.swift' \
  'TerminalBellService\s*\(|requestUserAttention|NSSound\.(beep|contentsOfFile)' \
  Packages/macOS/CmuxTerminal Sources cmuxTests 2>/dev/null || true

Length of output: 127887


@austinywang The current implementation confirms your explanation.

TerminalBellService.init() composes the production AppKit adapters. The package-internal initializer injects the audio side effects for isolation. The code contains no test-only hook, global override, or conditional test path.

I withdraw the “test/debug seam” finding.

🐇


✏️ Learnings added
Learnt from: austinywang
URL: https://github.com/manaflow-ai/cmux/pull/9776

Timestamp: 2026-08-09T00:04:15.348Z
Learning: In `Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Services/Bell/TerminalBellService.swift`, `TerminalBellService` uses a public convenience initializer to compose production `NSSound.beep()` and `NSSound(contentsOfFile:byReference:)` dependencies. Its package-internal initializer injects `systemBeep` and `soundLoader` closures to isolate AppKit audio side effects in Swift Testing. Treat this constructor injection as the required production testability boundary, not as a test-only or debug hook. Do not recommend process-global AppKit interception for these tests.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

Comment thread cmuxTests/DockRuntimeParityTests.swift Outdated
Comment thread Sources/TerminalNotificationStore.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 `@Sources/TerminalNotificationStore.swift`:
- Around line 696-706: Replace the computed manualUnreadSurfaceKeys rebuild with
a maintained flat Set<SidebarSurfaceUnreadKey> owned alongside
manualUnreadSurfaceIdsByWorkspaceId. Update both indexes together in the manual
unread mutation methods, removing keys when indicators are deleted, and pass the
maintained set directly from refreshUnreadPresentation() to sidebarUnread.apply.
Follow the algorithmic-complexity guidance to avoid scanning all workspaces and
surfaces during refreshes.
🪄 Autofix

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 Plus

Run ID: 1d624d50-83f4-41f9-8e9a-81f53549a4fe

📥 Commits

Reviewing files that changed from the base of the PR and between a7c7a0b and a315547.

📒 Files selected for processing (10)
  • Packages/macOS/CmuxNotifications/Sources/CmuxNotifications/NotificationDismissalHosting.swift
  • Packages/macOS/CmuxNotifications/Sources/CmuxNotifications/NotificationDismissalModel.swift
  • Packages/macOS/CmuxNotifications/Tests/CmuxNotificationsTests/NotificationDismissalModelTests.swift
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/Services/Bell/TerminalBellServiceTests.swift
  • Sources/AppDelegate+DockAttentionRouting.swift
  • Sources/GhosttyTerminalView.swift
  • Sources/TabManager+NotificationDismissalHosting.swift
  • Sources/TerminalNotificationStore.swift
  • cmuxTests/DockRuntimeParityTests.swift
  • cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift

Comment thread Sources/TerminalNotificationStore.swift Outdated
Comment thread cmuxTests/DockRuntimeParityTests.swift
Comment thread cmuxTests/DockRuntimeParityTests.swift
Comment thread Sources/DockSplitStore+AttentionRouting.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: 3

🤖 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 `@cmuxTests/DockRuntimeParityTests.swift`:
- Line 530: Update the panel-close step in DockRuntimeParityTests to assert that
destinationDock.closePanel succeeds and that
notificationStore.hasManualUnread(forTabId: destinationWindowID, surfaceId:
panel.id) is false after closing the panel.

In
`@Packages/macOS/CmuxNotifications/Tests/CmuxNotificationsTests/NotificationNavigationCoordinatorTests.swift`:
- Around line 206-218: The failedWindowDockUnreadFallsThrough test currently
lacks a workspace fallback target. Add an unread workspace target to FakeStore,
invoke jumpToLatestUnread, assert that openRouting recorded routing to the
workspace target after the Dock open fails, and retain the assertion that
clearedWindowDockTargets remains empty.

In `@Sources/Workspace`+AttentionFlashRouting.swift:
- Around line 20-26: In Sources/Workspace+AttentionFlashRouting.swift#L20-L26
and Sources/DockSplitStore+AttentionRouting.swift#L60-L74, keep the
manual-unread guard limited to skipping duplicate unread-state writes; remove
its early return so each notification always reaches
mountedTerminal.triggerFlash(reason: .notificationArrival), allowing
triggerFlash to coalesce overlapping animations.
🪄 Autofix

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 Plus

Run ID: ba2f908f-9b93-4b6a-a559-f723a16a881a

📥 Commits

Reviewing files that changed from the base of the PR and between a315547 and d5362ec.

📒 Files selected for processing (17)
  • Packages/macOS/CmuxNotifications/Sources/CmuxNotifications/NotificationNavigationCoordinator.swift
  • Packages/macOS/CmuxNotifications/Sources/CmuxNotifications/NotificationNavigationStoreReading.swift
  • Packages/macOS/CmuxNotifications/Sources/CmuxNotifications/NotificationOpenRouting.swift
  • Packages/macOS/CmuxNotifications/Sources/CmuxNotifications/WindowDockUnreadTarget.swift
  • Packages/macOS/CmuxNotifications/Tests/CmuxNotificationsTests/FakeOpenRouting.swift
  • Packages/macOS/CmuxNotifications/Tests/CmuxNotificationsTests/NotificationNavigationCoordinatorTests.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface.swift
  • Sources/AppDelegate+NotificationNavSeams.swift
  • Sources/DockSplitStore+AttentionRouting.swift
  • Sources/DockSplitStore+SurfaceTransfer.swift
  • Sources/DockSplitStore.swift
  • Sources/GhosttyTerminalView.swift
  • Sources/TerminalNotificationStore.swift
  • Sources/Workspace+AttentionFlashRouting.swift
  • Sources/Workspace.swift
  • cmuxTests/DockRuntimeParityTests.swift
  • cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift

Comment thread cmuxTests/DockRuntimeParityTests.swift Outdated
Comment thread Sources/Workspace+AttentionFlashRouting.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 `@cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift`:
- Around line 160-202: The tests mutate process-global application state without
isolation. In cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift:160-202,
make terminalBellInNonKeyCmuxWindowMarksPaneUnread async and execute setup,
assertions, and cleanup inside AppContextSerialGate.withExclusiveAppContext; in
cmuxTests/DockSessionPersistenceTests.swift:308-368, likewise make the affected
test async and place its setup, restoration, assertions, and cleanup inside the
gate. Do not rely on .serialized for this isolation.
🪄 Autofix

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 Plus

Run ID: 6a39cba6-e1d2-4a38-aa09-2a24f6bfdd90

📥 Commits

Reviewing files that changed from the base of the PR and between 17e00f2 and faf35dc.

📒 Files selected for processing (4)
  • Packages/macOS/CmuxNotifications/Tests/CmuxNotificationsTests/NotificationNavigationCoordinatorTests.swift
  • cmuxTests/DockRuntimeParityTests.swift
  • cmuxTests/DockSessionPersistenceTests.swift
  • cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift

Comment thread cmuxTests/GhosttyEnsureFocusWindowActivationTests.swift
@austinywang

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…ger-raise

# Conflicts:
#	Sources/DockSplitStore+RestoredAgentLifecycle.swift
#	Sources/DockSplitStore+SessionRestore.swift
#	Sources/DockSplitStore+SessionSnapshot.swift
#	Sources/DockSplitStore+SurfaceTransfer.swift
#	Sources/DockSplitStore.swift
Comment thread Sources/AppDelegate+NotificationNavSeams.swift

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 372ec73. Configure here.

Comment thread Sources/Mobile/MobileWorkspaceEmissionCoalescer.swift
@austinywang
austinywang merged commit 61ca64f into main Aug 11, 2026
36 of 44 checks passed
@artisticmedic

Copy link
Copy Markdown

Thank you!!!

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.

Stage Manager: cmux raises itself to the front while another app is focused (agent notification attention pulls the whole window set forward)

2 participants