Skip to content

Show fork commands when context menu can fork - #5200

Closed
lawrencecchen wants to merge 6 commits into
mainfrom
task-fork-options-command-palette
Closed

lawrencecchen wants to merge 6 commits into
mainfrom
task-fork-options-command-palette

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jun 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Use the same forkable-agent snapshot source for command palette visibility as the right-click tab menu.
  • Allow probe-free fork snapshots to show and execute immediately while preserving the probe gate for local direct OpenCode.

Testing

  • ./scripts/reload.sh --tag forkpal, passed
  • Not run: Xcode unit tests locally, local test actions are prohibited on this Mac.

Issues

  • Related: plain-text task, cmd-shift-p sometimes hides fork options while right-click shows them

Note

Medium Risk
Touches fork availability, immediate execution, and session resume bindings across palette and workspace lifecycle; probe gating for local OpenCode is preserved but behavior changes for other agent types.

Overview
Fixes Cmd+Shift+P sometimes hiding fork commands while the tab context menu still offered them by routing palette visibility and execution through workspace.forkableAgentSnapshot(forPanelId:) (restored → live index → per-panel fork fallback cache) instead of only restored snapshots.

Probe-free agents (e.g. Codex, remote OpenCode, omo) now show in the palette and can fork immediately; the palette seeds its cache from the fallback while a background probe still runs. Probe-required local direct OpenCode stays gated until verification succeeds.

After any fork (split, new tab, or new workspace), the app records the fork snapshot on the new panel and writes an auto-resume surface binding from the fork command so chained forks and session restore work before a live agent scan lands. Fallback entries are cleared on panel close and session reset.

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


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.


Summary by cubic

Aligns the command palette with the tab context menu so fork commands appear and run when a probe‑free forkable snapshot exists. Also persists fork startup bindings so restored sessions auto‑resume and can be forked again immediately.

  • Bug Fixes
    • Use workspace.forkableAgentSnapshot(forPanelId:) to decide palette visibility and selection, and persist the fork snapshot and startup binding in new panels so they can fork again right away and auto‑resume on restore.
    • Show and execute fork commands immediately for probe‑free snapshots; seed the palette with the fallback snapshot while a probe runs, and clean up stored snapshots on panel close.
    • Keep probe gating for probe‑required snapshots (e.g., local OpenCode), with new regression tests covering visibility, immediate execution paths, chained forks, and restore auto‑resume.

Written for commit 87933a1. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Command palette now shows forked-agent entries using a fallback snapshot before probe verification, enabling faster immediate forks (including immediate re-forks).
  • Bug Fixes

    • More consistent detection and caching of fork availability to avoid stale or missing entries.
    • Fallback snapshot handling prefers verified matches but reliably falls back when verification isn’t yet available.
  • Tests

    • Updated and added tests to validate probe-free fallback visibility and immediate-fork behavior.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@vercel

vercel Bot commented Jun 2, 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 2, 2026 11:47am
cmux-staging Building Building Preview, Comment Jun 2, 2026 11:47am

@coderabbitai

coderabbitai Bot commented Jun 2, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR re-sources forkable-agent fallback snapshots from workspace.forkableAgentSnapshot(forPanelId:), requires .supportedWithoutProbe for fallback visibility, records per-panel forked fallback snapshots at fork creation and continuation, alters cache update logic on probe mismatch, and returns fallback snapshots for immediate forks when probe verification fails. Tests updated accordingly.

Changes

Forkable-Agent Fallback Snapshot Handling

Layer / File(s) Summary
Fallback snapshot availability gating and source
Sources/ContentView.swift, Sources/ContentView+ForkAgentConversation.swift
Fallback snapshot acceptance now requires .supportedWithoutProbe. Fallback snapshots are sourced via workspace.forkableAgentSnapshot(forPanelId:) in ContentView and fork flows instead of direct restored-snapshot dictionary access.
Cache and state updates for supported-without-probe availability
Sources/ContentView.swift
Refactored .supportedWithoutProbe handling: cached snapshot/fingerprint insertion is conditional on probe-match and existing cache; supported-panel set, remote-context flag, and had-fallback bookkeeping are updated without the previous "remove all state on probe mismatch" behavior.
Immediate fork snapshot selection with fallback handling
Sources/ContentView+ForkAgentConversation.swift
Immediate-fork selection computes probeResultMatches and returns a verified cached snapshot only if probe matches and verification succeeds; otherwise returns the provided fallbackSnapshot with usedFallbackSnapshot: true instead of nil.
Workspace fallback state, recording, and fork wiring
Sources/Workspace.swift, Sources/Workspace+PanelLifecycle.swift
Adds forkedAgentFallbackSnapshotsByPanelId, clears/filters it on reset/valid-surface changes, extends AgentConversationForkWorkspaceLaunch with forkedAgentSnapshot, records fallback snapshots at fork creation and continuation, prefers SharedLiveAgentIndex snapshot when available, and removes per-panel fallback state when discarding panel lifecycle state.
Test expectations and new tests
cmuxTests/CommandPaletteSearchEngineTests.swift, cmuxTests/WorkspaceUnitTests.swift
Tests updated to expect probe-free fallback snapshots to be visible and usable before palette probe verification; added test to reject probe-required fallbacks before probe verification; added unit test for immediate re-forking from a freshly created fork panel and a test helper for agent auto-resume settings.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • manaflow-ai/cmux#4852: Overlaps with changes to immediate-fork snapshot helper, probe/fallback matching, and cache/fingerprint rules in ContentView.swift and ContentView+ForkAgentConversation.swift.
  • manaflow-ai/cmux#4888: Aligns with the switch to workspace.forkableAgentSnapshot(forPanelId:) and .supportedWithoutProbe predicate for fork conversation gating.

🐰 I nudged a snapshot into place,
A soft fallback for a hurried race,
When probes frown, the fork proceeds,
Recorded steps for future needs,
A happy hop through code and space. 🥕


Caution

Pre-merge checks failed

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

  • Ignore

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

Check name Status Explanation Resolution
Cmux Full Internationalization ❌ Error 18 new user-facing fork conversation strings lack translations for all 19 supported locales; keys have only 2-7/19 translations instead of the required complete set. Add complete translations for all 18 fork conversation keys across all 19 supported locales in Resources/Localizable.xcstrings.
Cmux Architecture Rethink ❌ Error forkedAgentStartupBinding hardcodes autoResume: true for all forked panels, violating AgentSessionAutoResumeSettings ownership of auto-resume state, introducing a new mutable cache owner. Use AgentSessionAutoResumeSettings.isEnabled() instead of true to preserve source-of-truth setting ownership across persist/restore lifecycle.
Docstring Coverage ⚠️ Warning Docstring coverage is 17.24% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Swift @Concurrent ❓ Inconclusive No result was produced after verification. Marking as INCONCLUSIVE. Re-run the check or adjust instructions to produce a final result.
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: showing fork commands in the command palette when the context menu can fork.
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 No Swift 6 actor isolation violations. New properties store Sendable types in @MainActor Workspace. New enums explicitly marked Sendable. All methods properly isolated.
Cmux Swift Blocking Runtime ✅ Passed No blocking/timing patterns introduced. New fork code uses only dictionary storage, conditionals, and object creation.
Cmux No Hacky Sleeps ✅ Passed PR contains only Swift source and test file changes. The check applies only to TypeScript, JavaScript, shell, and build/runtime scripts; Swift sleeps are covered by a separate rule.
Cmux Algorithmic Complexity ✅ Passed All new code involves O(1) dictionary/set lookups per panel in command palette hot paths and one-pass filtering; no nested full-collection scans introduced.
Cmux Swift Concurrency ✅ Passed Tasks stored in @State with proper cancellation; DispatchSourceTimer tied to CheckedContinuation for process timeouts; new Combine for SwiftUI sidebar UI (allowed boundary).
Cmux Swift File And Package Boundaries ✅ Passed PR adds +3 and +41 lines to existing oversized files, well under 250-line threshold. No new files. Focused fork snapshot state management fits existing Workspace scope.
Cmux Swift Logging ✅ Passed All NSLog calls in production code are guarded with #if DEBUG, which is an explicitly allowed exception per swift-logging.md rules for debug-only diagnostics.
Cmux User-Facing Error Privacy ✅ Passed No new user-facing errors or alerts expose sensitive data. PR changes are internal snapshot caching and fork selection logic with no user-visible message or error content violations.
Cmux Swiftui State Layout ✅ Passed @State properties used correctly; storage follows existing patterns; state mutations only in private functions; LazyVStack uses value snapshots per rules.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR modifies command palette forking logic and workspace state. No standalone cmux windows, NSWindow, NSPanel, NSWindowController, SwiftUI Window/WindowGroup created or changed.
Description check ✅ Passed The PR description includes all required sections: summary with what changed and why, testing details with verification steps, and a comprehensive checklist with most items addressed.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch task-fork-options-command-palette

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Sources/ContentView+ForkAgentConversation.swift (1)

44-55: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the helper-based snapshot source in the execution path.

Line 44 still pulls the fallback from restoredAgentSnapshotsByPanelId. That leaves visibility and execution on different snapshot sources, so a probe-free fork command can be shown and still fail/beep on first execution when workspace.forkableAgentSnapshot(forPanelId:) has data but the dictionary does not.

Suggested fix
-        let fallbackSnapshot = currentContext.workspace.restoredAgentSnapshotsByPanelId[panelId]
+        let fallbackSnapshot = currentContext.workspace.forkableAgentSnapshot(forPanelId: panelId)
🤖 Prompt for 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.

In `@Sources/ContentView`+ForkAgentConversation.swift around lines 44 - 55, The
fallback snapshot must come from the workspace helper to ensure consistent
snapshot source; replace the use of
currentContext.workspace.restoredAgentSnapshotsByPanelId[panelId] with the
helper currentContext.workspace.forkableAgentSnapshot(forPanelId: panelId) so
that Self.commandPaletteImmediateForkExecutionSnapshotSelection(...) receives
the helper-provided fallbackSnapshot; update the variable assignment for
fallbackSnapshot (and any related usages in this block) to call
forkableAgentSnapshot(forPanelId:) instead of indexing
restoredAgentSnapshotsByPanelId to avoid mismatched visibility/execution
sources.
cmuxTests/CommandPaletteSearchEngineTests.swift (1)

802-856: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Cover the probe-free OpenCode execution branch too.

Lines 802-856 only prove immediate execution for .codex and rejection for direct local OpenCode. The changed behavior also depends on probe-free OpenCode snapshots being executable without a verified probe, so a regression in the launcher == "omo"/.supportedWithoutProbe path would still pass here because that shape is only covered by the visibility test.

➕ Suggested regression test
+    func testImmediateForkExecutionUsesProbeFreeOpenCodeFallbackBeforeProbeVerification() {
+        let workspaceId = UUID()
+        let panelId = UUID()
+        let fallback = SessionRestorableAgentSnapshot(
+            kind: .opencode,
+            sessionId: "fallback-omo-session",
+            workingDirectory: "/tmp/opencode repo",
+            launchCommand: AgentLaunchCommandSnapshot(
+                launcher: "omo",
+                executablePath: "/usr/local/bin/cmux",
+                arguments: ["/usr/local/bin/cmux", "omo"],
+                workingDirectory: "/tmp/opencode repo",
+                environment: nil,
+                capturedAt: 123,
+                source: "environment"
+            )
+        )
+
+        let snapshot = ContentView.commandPaletteImmediateForkExecutionSnapshot(
+            workspaceId: workspaceId,
+            panelId: panelId,
+            isRemoteTerminal: false,
+            supportedPanelKeys: [],
+            supportedRemoteContextsByPanelKey: [:],
+            snapshotFingerprintsByPanelKey: [:],
+            fallbackSnapshot: fallback,
+            cachedSnapshot: nil
+        )
+
+        XCTAssertEqual(snapshot?.sessionId, fallback.sessionId)
+    }
🤖 Prompt for 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.

In `@cmuxTests/CommandPaletteSearchEngineTests.swift` around lines 802 - 856, Add
a test that asserts probe-free OpenCode snapshots (launcher == "omo") are
accepted by commandPaletteImmediateForkExecutionSnapshot: create a fallback
SessionRestorableAgentSnapshot with kind .opencode and an
AgentLaunchCommandSnapshot whose launcher is "omo" (matching the
supportedWithoutProbe path), call
ContentView.commandPaletteImmediateForkExecutionSnapshot with that fallback and
nil cachedSnapshot, then XCTAssertEqual(snapshot?.sessionId,
fallback.sessionId); mirror naming and setup from
testImmediateForkExecutionUsesProbeFreeFallbackSnapshotBeforeProbeVerification
and ensure the test covers the probe-free OpenCode branch.
🤖 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.

Outside diff comments:
In `@cmuxTests/CommandPaletteSearchEngineTests.swift`:
- Around line 802-856: Add a test that asserts probe-free OpenCode snapshots
(launcher == "omo") are accepted by
commandPaletteImmediateForkExecutionSnapshot: create a fallback
SessionRestorableAgentSnapshot with kind .opencode and an
AgentLaunchCommandSnapshot whose launcher is "omo" (matching the
supportedWithoutProbe path), call
ContentView.commandPaletteImmediateForkExecutionSnapshot with that fallback and
nil cachedSnapshot, then XCTAssertEqual(snapshot?.sessionId,
fallback.sessionId); mirror naming and setup from
testImmediateForkExecutionUsesProbeFreeFallbackSnapshotBeforeProbeVerification
and ensure the test covers the probe-free OpenCode branch.

In `@Sources/ContentView`+ForkAgentConversation.swift:
- Around line 44-55: The fallback snapshot must come from the workspace helper
to ensure consistent snapshot source; replace the use of
currentContext.workspace.restoredAgentSnapshotsByPanelId[panelId] with the
helper currentContext.workspace.forkableAgentSnapshot(forPanelId: panelId) so
that Self.commandPaletteImmediateForkExecutionSnapshotSelection(...) receives
the helper-provided fallbackSnapshot; update the variable assignment for
fallbackSnapshot (and any related usages in this block) to call
forkableAgentSnapshot(forPanelId:) instead of indexing
restoredAgentSnapshotsByPanelId to avoid mismatched visibility/execution
sources.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 482ddaed-0106-4e06-94c0-3bd17f046d2b

📥 Commits

Reviewing files that changed from the base of the PR and between 6c5ffc5 and 8430521.

📒 Files selected for processing (4)
  • Sources/ContentView+ForkAgentConversation.swift
  • Sources/ContentView.swift
  • Sources/Workspace.swift
  • cmuxTests/CommandPaletteSearchEngineTests.swift

@greptile-apps

greptile-apps Bot commented Jun 2, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes Cmd+Shift+P sometimes hiding fork commands while the right-click tab menu still offered "Fork Conversation" by aligning the command palette's visibility and execution path with workspace.forkableAgentSnapshot(forPanelId:) — the same three-tier lookup (restored snapshot → live index → forked fallback) already used by the right-click menu. After any fork, the launch snapshot is seeded into the new panel via recordForkedAgentFallbackSnapshot so chained forks work before live agent detection catches up.

  • New snapshot tier: forkedAgentFallbackSnapshotsByPanelId bridges the gap between panel creation and SharedLiveAgentIndex registration; cleared on panel close and workspace reset, but not on agent death.
  • Probe gating relaxed for probe-free snapshots: .supportedWithoutProbe agents (Codex, remote OpenCode, launcher-backed OpenCode) show and execute fork commands immediately; a background probe still upgrades the cache. Local direct OpenCode (.requiresProbe) remains gated until the probe confirms.
  • Tests updated: revised CommandPaletteSearchEngineTests assert the new visibility expectations; new WorkspaceUnitTests cover chained same-session forks and startup-binding persistence across session restore."

Confidence Score: 4/5

Safe to merge with awareness that the fallback snapshot remains live until panel close even after the forked agent dies.

The core logic change is well-tested: new unit tests cover chained forks, startup-binding persistence, probe-free visibility, and the probe-required gate. The three-tier lookup is symmetric with the right-click path. The main open concern is that forkedAgentFallbackSnapshotsByPanelId has no signal from agent termination, so the fork UI can remain visible for a panel whose agent has already exited, and executing the fork would pass a stale session ID to the binary.

Sources/Workspace.swift — recordForkedAgentFallbackSnapshot and forkableAgentSnapshot establish the new tier; the fallback lifetime and the unconditional surfaceResumeBindingsByPanelId write are the areas worth a second read.

Important Files Changed

Filename Overview
Sources/Workspace.swift Adds forkedAgentFallbackSnapshotsByPanelId as a third snapshot tier in forkableAgentSnapshot, plus recordForkedAgentFallbackSnapshot/forkedAgentStartupBinding helpers. Lifecycle is bounded only by panel close or workspace reset — no signal from agent termination.
Sources/ContentView.swift Command palette refresh now seeds .supportedWithoutProbe panels immediately from the fallback snapshot before probe confirmation, and unconditionally inserts the panel key; eviction logic for this branch is intentionally removed.
Sources/ContentView+ForkAgentConversation.swift Fork execution now uses forkableAgentSnapshot (three-tier lookup) and calls recordForkedAgentFallbackSnapshot on new-workspace forks; .supportedWithoutProbe snapshots bypass the probe gate for immediate execution.
Sources/Workspace+PanelLifecycle.swift Panel close now clears forkedAgentFallbackSnapshotsByPanelId, completing the panel-lifecycle cleanup for the new tier.
cmuxTests/WorkspaceUnitTests.swift Adds testForkedSplitCanBeForkedAgainImmediately and testForkedSplitPersistsForkStartupBindingBeforeLiveScan covering chained forks and startup-binding persistence; adds a helper for UserDefaults teardown.
cmuxTests/CommandPaletteSearchEngineTests.swift Renames and reverses visibility assertions for probe-free snapshots to match new behavior; adds a separate test confirming probe-required snapshots (local OpenCode) remain gated.

Sequence Diagram

sequenceDiagram
    participant User
    participant CmdPalette as Command Palette
    participant CView as ContentView
    participant WS as Workspace
    participant LiveIndex as SharedLiveAgentIndex

    User->>CmdPalette: Open (Cmd+Shift+P)
    CmdPalette->>CView: refreshCommandPaletteForkableAgentAvailabilityIfNeeded
    CView->>WS: forkableAgentSnapshot(forPanelId:)
    WS-->>CView: 1. restoredAgentSnapshotsByPanelId
    WS-->>CView: 2. SharedLiveAgentIndex.snapshot()
    WS-->>CView: 3. forkedAgentFallbackSnapshotsByPanelId
    CView->>CView: commandPaletteSnapshotForkAvailability()
    alt supportedWithoutProbe (Codex / remote OpenCode)
        CView->>CView: Insert panelKey immediately
        CView->>CView: Seed cache with fallback snapshot
        CView-->>CmdPalette: Fork commands visible NOW
        CView->>CView: Start background probe (upgrades cache)
    else requiresProbe (local OpenCode)
        CView->>CView: Wait for probe result
        CView-->>CmdPalette: Fork commands hidden until probe succeeds
    end
    User->>CmdPalette: Execute Fork Conversation
    CmdPalette->>WS: forkAgentConversation / forkAgentConversationToNewTab
    WS->>WS: Create new panel (newPanelId)
    WS->>WS: recordForkedAgentFallbackSnapshot(snapshot, panelId: newPanelId)
    WS-->>User: New forked panel (agent launching)
    Note over WS,LiveIndex: Agent registers with SharedLiveAgentIndex
    LiveIndex-->>WS: objectWillChange fires
    WS->>WS: forkableAgentSnapshot() returns live snapshot (tier 2)
Loading

Reviews (2): Last reviewed commit: "Persist fork startup binding for restore" | Re-trigger Greptile

@cubic-dev-ai cubic-dev-ai 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.

No issues found across 4 files

Re-trigger cubic

coderabbitai[bot]
coderabbitai Bot previously requested changes Jun 2, 2026

@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/Workspace.swift`:
- Around line 17727-17741: The forkedAgentStartupBinding function currently
forces autoResume: true when creating a SurfaceResumeBindingSnapshot; instead
preserve the saved policy by using the auto-resume flag from the
SessionRestorableAgentSnapshot (e.g. replace autoResume: true with autoResume:
snapshot.autoResume or the appropriate saved property on
SessionRestorableAgentSnapshot), so the synthesized fork binding respects the
original panel/user auto-resume setting.
🪄 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: 12861c37-5bdb-43f9-97e4-b9ffea794272

📥 Commits

Reviewing files that changed from the base of the PR and between 1436a36 and 87933a1.

📒 Files selected for processing (2)
  • Sources/Workspace.swift
  • cmuxTests/WorkspaceUnitTests.swift

Comment thread Sources/Workspace.swift
Comment on lines +17727 to +17741
if let binding = forkedAgentStartupBinding(snapshot) {
surfaceResumeBindingsByPanelId[panelId] = binding
}
}

private func forkedAgentStartupBinding(_ snapshot: SessionRestorableAgentSnapshot) -> SurfaceResumeBindingSnapshot? {
guard let command = snapshot.forkCommand else { return nil }
return SurfaceResumeBindingSnapshot(
name: snapshot.agentDisplayName,
kind: snapshot.kind.rawValue,
command: command,
cwd: snapshot.workingDirectory,
checkpointId: snapshot.sessionId,
source: "agent-hook",
autoResume: true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not force forked panels into auto-resume.

Line 17741 hardcodes autoResume: true for every synthesized fork startup binding. Because this binding is now persisted for restore, any forked panel will relaunch on next app start even when the source panel or user setting had agent auto-resume disabled. Preserve the existing auto-resume policy instead of unconditionally opting in here.

🤖 Prompt for 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.

In `@Sources/Workspace.swift` around lines 17727 - 17741, The
forkedAgentStartupBinding function currently forces autoResume: true when
creating a SurfaceResumeBindingSnapshot; instead preserve the saved policy by
using the auto-resume flag from the SessionRestorableAgentSnapshot (e.g. replace
autoResume: true with autoResume: snapshot.autoResume or the appropriate saved
property on SessionRestorableAgentSnapshot), so the synthesized fork binding
respects the original panel/user auto-resume setting.

@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 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 87933a1. Configure here.

if let cachedSnapshot = verifiedCachedSnapshot(expectedFingerprint: fallbackFingerprint) {
)
if probeResultMatches,
let cachedSnapshot = verifiedCachedSnapshot(expectedFingerprint: fallbackFingerprint) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seeded fallback misreported as verified cached snapshot

Low Severity

In refreshCommandPaletteForkableAgentAvailabilityIfNeeded, the .supportedWithoutProbe case now pre-seeds the cache with the fallback snapshot (inserting panelKey into supportedPanelKeys and setting snapshotsByPanelKey/snapshotFingerprintsByPanelKey). When commandPaletteImmediateForkExecutionSnapshotSelection later runs, probeResultMatches returns true against this pre-seeded data, and verifiedCachedSnapshot finds the seeded fallback, returning it with usedFallbackSnapshot: false. In forkFocusedAgentConversation, this incorrect flag is written to resultHadFallbackByPanelKey, which can prevent future probe re-triggering if the background probe is cancelled before completion (e.g., on palette dismissal).

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 87933a1. Configure here.

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="cmuxTests/WorkspaceUnitTests.swift">

<violation number="1" location="cmuxTests/WorkspaceUnitTests.swift:5786">
P2: Codex hook-state behavior is tested without isolating `CMUX_AGENT_HOOK_STATE_DIR`, so this test can leak into real user hook-state files and become non-hermetic.

(Based on your team's feedback about isolating Codex hook state in tests.) [FEEDBACK_USED].</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

XCTAssertEqual(binding.command, snapshot.forkCommand)

let restored = Workspace()
restored.restoreSessionSnapshot(savedSnapshot)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Codex hook-state behavior is tested without isolating CMUX_AGENT_HOOK_STATE_DIR, so this test can leak into real user hook-state files and become non-hermetic.

(Based on your team's feedback about isolating Codex hook state in tests.) .

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At cmuxTests/WorkspaceUnitTests.swift, line 5786:

<comment>Codex hook-state behavior is tested without isolating `CMUX_AGENT_HOOK_STATE_DIR`, so this test can leak into real user hook-state files and become non-hermetic.

(Based on your team's feedback about isolating Codex hook state in tests.) .</comment>

<file context>
@@ -5739,6 +5739,65 @@ final class WorkspacePanelGitBranchTests: XCTestCase {
+            XCTAssertEqual(binding.command, snapshot.forkCommand)
+
+            let restored = Workspace()
+            restored.restoreSessionSnapshot(savedSnapshot)
+            let restoredPanelId = try XCTUnwrap(restored.focusedPanelId)
+            let restoredPanel = try XCTUnwrap(restored.terminalPanel(for: restoredPanelId))
</file context>

@lawrencecchen
lawrencecchen dismissed coderabbitai[bot]’s stale review June 6, 2026 11:35

CodeRabbit now posts non-blocking comment reviews (request_changes_workflow=false, #5538).

@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026

This branch was successfully deployed

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

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants