Skip to content

Fork conversations across agent harnesses - #9025

Closed
austinywang wants to merge 188 commits into
mainfrom
issue-9016-cross-harness-fork
Closed

austinywang wants to merge 188 commits into
mainfrom
issue-9016-cross-harness-fork

Conversation

@austinywang

@austinywang austinywang commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • show every installed fork-capable harness in the Fork Conversation picker
  • keep plain and default forks on the current harness and configured destination
  • convert a source conversation into one compact User and Assistant message through a pluggable transfer service
  • route command palette and terminal context-menu forks through one shared request executor

Installed harnesses

Discovery covers Claude Code, Codex, Grok, OpenCode, OMP, Campfire, Pi, Amp, Cursor, Gemini, Kiro, Antigravity, Rovo Dev, Hermes Agent, Copilot, CodeBuddy, Factory, Qoder, and Kimi Code. Only executables found in configured or standard search paths appear. Ollama is excluded because deterministic launch requires a model argument.

This machine discovers Claude Code, Codex, Grok, OpenCode, OMP, Campfire, Pi, Amp, Cursor, Gemini, Hermes Agent, and Kimi Code.

Design

  • AgentConversationForkRequest owns harness plus destination for every UI entrypoint.
  • Current Harness emits no command override, preserving native same-harness fork and resume behavior.
  • CmuxConversationTransfer owns role labeling, opening-plus-latest compaction, and a 24,000-byte UTF-8 bound.
  • Source adapters read direct JSONL files, OpenCode SQLite, Hermes SQLite, Rovo Dev, and Antigravity storage without exposing storage details to the picker.
  • Executable identity, source panel, storage generation, and conversation fingerprint are pinned and revalidated before handoff.
  • The receiving harness opens first, waits for its editable prompt, names the exact recipient executable, and requires Control-] confirmation before submitting the compact message.

Floating command palette

#8351 by @lawrencecchen remains open. This PR does not stack on it because a merge-tree trial produced broad conflicts from unrelated stale branch state. The declarative command-argument model is the compatibility seam, so the same harness and destination steps can render in the current sheet or that floating window after it lands.

#8653 by @lawrencecchen supplied prior art for transcript adapters and fork routing. This branch reimplements the flow on current main with deterministic source binding and the shared transfer package.

Verification

  • CMUXAgentLaunch: 322 tests passed
  • CmuxCommandPalette: 89 tests passed
  • CmuxConversationTransfer: 7 tests passed
  • AgentConversationTransferSourceTests: 37 tests passed
  • AgentConversationCrossHarnessForkTests: 70 tests passed
  • CLIOmpHookBindingTests: 8 tests passed
  • final-head workspace-rotation regression: 1 focused app-host test passed
  • Kiro discovery regression: red test-only commit, then 37 transfer-source tests passed
  • Pi registration regression: 8 focused tests passed
  • final tagged macOS build fksame succeeded at ac00f543e1
  • tagged palette probe resolved the active Codex snapshot and exposed Fork Conversation to the Right
  • git diff --check, policy checks, and all 10 review threads are clean/resolved

The speculative merge gate ran at https://github.com/manaflow-ai/cmux/actions/runs/31127039990. Workflow guard, remote daemon, web typecheck, React, web database migrations, tests-build-and-lag, and the feature-specific conversation-transfer stage passed. The aggregate app-host check failed across broad current-main tests. A clean origin/main run reproduced the same three Kimi failures at the same assertions, confirming those failures are inherited.

Closes #9016

@coderabbitai

coderabbitai Bot commented Jul 28, 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

This PR adds cross-harness conversation forking with transcript export, compaction, retention-aware loading, target-harness selection, workspace routing, finite-choice command-palette input, transcript popover support, localization, and Xcode package/source integration.

Changes

Cross-harness conversation forking

Layer / File(s) Summary
Conversation transfer package
Packages/macOS/CmuxConversationTransfer/...
Defines normalized conversation models, role filtering, bounded compaction, localized formatting, sanitization, service errors, and unit coverage.
Transcript sources and retention loading
Sources/AgentConversationSource.swift, Sources/SessionIndexView.swift, Sources/RovoDevTranscriptPreview.swift, Sources/SessionTranscriptRetention.swift, Sources/SessionTranscriptLatestCollector.swift, Packages/macOS/CMUXAgentLaunch/.../HermesAgentIndex.swift
Adds ordered transcript adapters, indexed-entry resolution, prefix/opening-user/latest retention, provider-specific latest parsing, and transcript-path/database-source handling.
Finite-choice command palette
Packages/macOS/CmuxCommandPalette/..., Sources/CommandPalette/..., Sources/ContentView.swift
Adds finite-choice models and collection state, argument-aware command handlers, a choice-selection mode and view, fork command arguments, and associated debug/reset behavior.
Fork requests and workspace execution
Sources/AgentConversationForkRequest.swift, Sources/AgentConversationForkTargetHarness.swift, Sources/AgentConversationExportService.swift, Sources/Workspace+AgentConversationForkRequest.swift, Sources/Workspace.swift, Sources/Workspace+ForkConversationContextMenu.swift, Sources/ContentView+ForkAgentConversation.swift, Sources/GhosttyNSView+ForkConversationContextMenu.swift, cmuxTests/AgentConversationCrossHarnessForkTests.swift
Routes native and cross-harness forks through request-based execution, transcript handoff, startup overrides, split/new-tab/new-workspace destinations, validation, cancellation handling, and cross-harness tests.
Workspace observation and transcript UI support
Sources/SelectedWorkspaceDirectoryObserver.swift, Sources/SelectedWorkspaceDirectorySnapshot.swift, Sources/SessionTranscriptPopoverCoordinator.swift, Sources/SessionTranscriptPopoverHost.swift, Sources/PopoverAnchorView.swift, Sources/SessionIndexView.swift
Adds selected-workspace directory observation and transcript popover lifecycle components, and updates the preview sizing model.
Localization and project integration
Resources/Localizable.xcstrings, cmux.xcodeproj/project.pbxproj, Sources/RestorableAgentSession.swift, Sources/SessionRestorableAgentSnapshot+Commands.swift, Sources/SessionIndexModels.swift, Sources/SessionIndexStore.swift
Adds fork and argument strings, registers the new package and sources, propagates transcript paths, supports configurable OpenCode snapshot paths, and exposes indexed search for resolution.

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

Possibly related PRs

  • manaflow-ai/cmux#8680: Both changes update transcript loading and retention behavior in SessionIndexView.swift, including provider-specific tail scanning.

Suggested reviewers: lawrencecchen


Important

Pre-merge checks failed

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

❌ Failed checks (4 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Concurrency ❌ Error The PR adds a new app-state observer using Combine publishers, AnyPublisher, sink, and receive(on: DispatchQueue.main) in SelectedWorkspaceDirectoryObserver.swift. Replace the publisher chain with Observation/async-driven state updates (or an async stream) and remove the new Combine-backed observer.
Cmux Swift Package Boundaries ❌ Error App-target Sources now hosts reusable transcript/index parsing logic (SessionTranscriptLoader, SessionIndexJSONLReader, retention helpers) instead of a small SwiftPM target. Extract the transcript-loading/parsing layer into a SwiftPM package target (e.g. CMUXAgentLaunch or a new CmuxTranscriptLoading), starting with SessionIndexJSONLReader and SessionTranscriptRetention.
Cmux Full Internationalization ❌ Error New .xcstrings keys like forkConversation and alert.forkConversation.failed are only translated in en/ja, but the catalog already supports many more locales. Add translated entries for every existing locale in Resources/Localizable.xcstrings for each new/changed key, or remove unsupported locales from the catalog.
Cmux No Ambient Global State ❌ Error New static let live singletons in AgentConversationExportService.swift:6 and AgentConversationSource.swift:84 add ambient runtime wiring. Remove the static live instances and inject concrete registry/service instances from the app or workspace seam; keep only local/private helpers.
Docstring Coverage ⚠️ Warning Docstring coverage is 5.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (20 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy #9016 by adding cross-harness forking, preserving native same-harness paths, and supporting split/new-tab/new-workspace destinations.
Out of Scope Changes check ✅ Passed No clear out-of-scope code changes stand out; the added infrastructure supports transcript export, compaction, and fork routing.
Cmux Swift Actor Isolation ✅ Passed PASS: new value models/protocols are top-level/nonisolated, and UI-bound stores/coordinators remain explicitly @MainActor; no off-main UI access was added.
Cmux Swift Blocking Runtime ✅ Passed No new blocking/sleep/sync primitives were introduced in changed non-test Swift files; diff searches found no added semaphores, waits, sleeps, or main.sync.
Cmux Browser Automation Off-Main ✅ Passed No browser-automation socket commands or worker-routing files changed; the diff only touches fork/command-palette code, so the off-main wait rule isn’t implicated.
Cmux Expensive Synchronous Load ✅ Passed Blocking transcript/db parsing is detached off MainActor, and fork/export paths await async loaders or cached lookups rather than doing sync history loads in UI hooks.
Cmux Cache Substitution Correctness ✅ Passed The new transcript/snapshot path keeps cold fallback and freshness checks: direct file reads gate on fileExists, and indexed lookup/search uses mtime-checked caches or fresh resolution.
Cmux No Hacky Sleeps ✅ Passed All changed files are Swift; no non-Swift runtime scripts or build files add sleeps, delays, polling, or waits.
Cmux Algorithmic Complexity ✅ Passed The new scans are bounded (2-choice palette args, 500/1000 turn caps, 2000-entry resolution limit) and linear; no nested full-collection rescans or hot-path re-sorts were added.
Cmux Swift @Concurrent ✅ Passed Heavy async paths were offloaded: export and resolution entrypoints are @concurrent, and transcript loading uses Task.detached; no invalid @concurrent+actor-isolation pairing found.
Cmux Swiftpm Lockfiles ✅ Passed No cmux-owned .gitignore, Package.resolved, or Xcode package-reference files changed in the actual diff, so the SwiftPM lockfile policy isn’t violated.
Cmux Swift Logging ✅ Passed PASS: The PR only adds unified Logger usage in two new files, with nonisolated private let loggers and private redaction; no print/NSLog changes in runtime code.
Cmux User-Facing Error Privacy ✅ Passed The new fork-failure alert is generic; no user-facing error copy exposes vendor names, raw upstream errors, or secrets.
Cmux Swiftui State Layout ✅ Passed Added SwiftUI state uses @Observable/value snapshots; no new ObservableObject/@published, lazy-row store refs, layout-shifting GeometryReader, or render-time state writes were introduced.
Cmux Architecture Rethink ✅ Passed PASS: the new observers/coordinators are explicit bridges with single owners; no new sleeps, polling, locks, or duplicate fork entrypoints were introduced.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed No standalone NSWindow/NSPanel/NSWindowController/WindowGroup was added or changed; the PR only touches views, popovers, menus, and request routing, so the rule isn’t triggered.
Cmux Source Artifacts ✅ Passed All changed paths are intentional source/test files; none match hidden scratch, logs, caches, build output, or other artifact directories.
Cmux No Test Or Debug Seam In Production Source ✅ Passed No new test-only seam was added: debug helpers were extracted into a dedicated debug file and are used by existing DEBUG logging; other changed sources only add product behavior.
Title check ✅ Passed The title clearly and concisely summarizes the PR's primary change: enabling conversation forks across agent harnesses.
Description check ✅ Passed The description clearly covers the scope, design, testing, verification results, and linked issue, but omits the template's Demo Video, review trigger, and checklist sections.
✨ 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 issue-9016-cross-harness-fork

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: 8

🤖 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/AgentConversationForkRequest.swift`:
- Around line 30-32: Replace the rawValue comparison in usesNativeFork(for:)
with a typed conversion from RestorableAgentKind to TargetHarness. Add an
initializer or equivalent explicit switch over RestorableAgentKind that returns
the matching TargetHarness or nil, and use that result alongside the existing
.current check so future enum cases require an explicit mapping decision.

In `@Sources/AgentConversationSource.swift`:
- Around line 72-75: Update AgentConversationSourceAdapter.read and every
adapter implementation to use `@concurrent` nonisolated async, ensuring delegated
SessionTranscriptLoader.load and SessionIndexStore.resolveConversationEntry work
executes concurrently off the caller’s executor. Preserve the existing return
and throwing behavior; alternatively encapsulate this work in an owned
background actor/service.

In `@Sources/ContentView.swift`:
- Around line 9086-9099: Update commandPaletteArgumentInstruction to use
String.localizedStringWithFormat instead of String(format:) when applying the
localized instruction format, preserving the existing format string and
arguments so step numbers receive locale-aware formatting.
- Around line 7742-7760: The fork conversation command and its dialog argument
strings lack translations across all supported locales. Update the localization
entries for command.forkAgentConversation.title,
commandPalette.argument.instruction, the forkConversation argument labels, and
all forkConversation harness options in Resources/Localizable.xcstrings so each
of the 21 supported locales has a translation, preserving the existing English
and Japanese values.

In `@Sources/GhosttyNSView`+ForkConversationContextMenu.swift:
- Around line 59-90: Extract the duplicated destination-item construction into a
helper such as makeDestinationSubmenu(representedObjectFor:) that creates each
destination item, assigns forkCurrentAgentConversation(_:), self, and the
supplied represented object. Replace both the current-harness submenu
construction and the per-harness loop in the menu-building method with this
helper, preserving the current-harness default-destination state configuration
and each cross-harness AgentConversationForkRequest.
- Around line 60-63: Update the Localizable.xcstrings catalog entry for
terminalContextMenu.forkConversationWith to include translations or appropriate
localization states for all 20 supported locales, matching the existing catalog
conventions; alternatively remove unsupported unused locale entries so the
catalog accurately reflects supported localization coverage.

In `@Sources/Workspace`+AgentConversationForkRequest.swift:
- Around line 16-38: The fork failure paths in forkAgentConversation, including
the export catch and missing startup input validation, currently return false
without user-facing feedback. Add an appropriate user-visible failure
notification for these paths and ensure the context-menu invocation also
surfaces failures, while preserving the existing false return behavior and
success flow.
- Around line 22-24: Update the error logging in the conversation export failure
path to avoid exposing error.localizedDescription with public privacy. Keep the
snapshot kind logging unchanged, but mark the dynamic error description as
private or otherwise redact it according to the project’s logging conventions.
🪄 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 Plus

Run ID: 0f6ed85a-0745-4943-8fae-363f7bd899db

📥 Commits

Reviewing files that changed from the base of the PR and between fe57d57 and 8930b3e.

⛔ Files ignored due to path filters (1)
  • cmux.xcworkspace/contents.xcworkspacedata is excluded by !**/*.xcworkspace/contents.xcworkspacedata
📒 Files selected for processing (46)
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/Vault/Providers/HermesAgent/HermesAgentIndex.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/Vault/Providers/HermesAgent/HermesAgentIndexTests.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Handling/CommandPaletteCommandContribution.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Handling/CommandPaletteHandlerRegistry.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteArgumentCollection.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteChoiceArgument.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteCommand.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteMode.swift
  • Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteArgumentCollectionTests.swift
  • Packages/macOS/CmuxConversationTransfer/Package.swift
  • Packages/macOS/CmuxConversationTransfer/README.md
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationCompaction.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationFormatting.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationRole.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationTransferPolicy.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationTransferService.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationTurn.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/RoleLabeledConversationFormatter.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/TailPreservingConversationCompactor.swift
  • Packages/macOS/CmuxConversationTransfer/Tests/CmuxConversationTransferTests/ConversationTransferServiceTests.swift
  • Resources/Localizable.xcstrings
  • Sources/AgentConversationExportService.swift
  • Sources/AgentConversationForkRequest.swift
  • Sources/AgentConversationSource.swift
  • Sources/CommandPalette/CommandPaletteArgumentChoiceView.swift
  • Sources/CommandPalette/CommandPaletteDebugFormatting.swift
  • Sources/CommandPalette/CommandPaletteOverlayContainerView.swift
  • Sources/CommandPalette/WeakWindowReference.swift
  • Sources/ContentView+ForkAgentConversation.swift
  • Sources/ContentView.swift
  • Sources/GhosttyNSView+ForkConversationContextMenu.swift
  • Sources/RestorableAgentSession.swift
  • Sources/SelectedWorkspaceDirectoryObserver.swift
  • Sources/SessionIndexModels.swift
  • Sources/SessionIndexStore+ConversationResolution.swift
  • Sources/SessionIndexStore.swift
  • Sources/SessionIndexView.swift
  • Sources/SessionRestorableAgentSnapshot+Commands.swift
  • Sources/SessionTranscriptPopoverHost.swift
  • Sources/SessionTranscriptRetention.swift
  • Sources/Workspace+AgentConversationForkRequest.swift
  • Sources/Workspace+ForkConversationContextMenu.swift
  • Sources/Workspace.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/AgentConversationCrossHarnessForkTests.swift
  • cmuxTests/CommandPaletteSearchEngineTests.swift

Comment thread Sources/AgentConversationForkRequest.swift Outdated
Comment thread Sources/AgentConversationSource.swift
Comment thread Sources/ContentView.swift
Comment thread Sources/ContentView.swift
Comment thread Sources/GhosttyNSView+ForkConversationContextMenu.swift Outdated
Comment thread Sources/GhosttyNSView+ForkConversationContextMenu.swift Outdated
Comment thread Sources/Workspace+AgentConversationForkRequest.swift
Comment thread Sources/Workspace+AgentConversationForkRequest.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

Caution

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

⚠️ Outside diff range comments (2)
Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteChoiceArgument.swift (1)

18-21: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Enforce non-empty, unique choice values.

An empty choices array enters argument-selection mode with no selectable row, so the command cannot complete. Duplicate values are also unsafe because CommandPaletteArgumentChoiceView uses choice.value as the row ID while selection matches by that same value. Reject invalid declarations at construction/registration and cover both cases with tests.

🤖 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
`@Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteChoiceArgument.swift`
around lines 18 - 21, The CommandPaletteChoiceArgument initializer currently
accepts empty or duplicate choices, causing invalid selection state and
non-unique row IDs. Update CommandPaletteChoiceArgument initialization or
registration to reject empty choices and duplicate choice.value entries, then
add tests covering both invalid declarations while preserving valid choice
handling.
Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteArgumentCollection.swift (1)

37-47: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject duplicate argument names before using them as dictionary keys.

values is keyed by argument.name, so duplicate names are ambiguous. Selecting the first declaration can make a later declaration appear collected and return .completed without presenting it. Validate uniqueness during collection construction (or make construction fail) and add a regression test.

🤖 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
`@Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteArgumentCollection.swift`
around lines 37 - 47, Validate that argument names are unique when constructing
the argument collection, before collection logic uses them as dictionary keys;
reject or fail construction for duplicates so later declarations cannot be
treated as already collected. Update the relevant initializer or factory near
the validation of arguments and add a regression test covering duplicate names.
🤖 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/CommandPalette/CommandPaletteDebugFormatting.swift`:
- Around line 26-31: Update commandPaletteDiagnosticKeyEventSummary and
commandPaletteDiagnosticTextPreview to avoid including user-entered character
content in diagnostics. Replace character previews with redacted metadata only,
such as whether each value is present and its byte count, while preserving the
existing event type, key code, and modifier metadata.

---

Outside diff comments:
In
`@Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteArgumentCollection.swift`:
- Around line 37-47: Validate that argument names are unique when constructing
the argument collection, before collection logic uses them as dictionary keys;
reject or fail construction for duplicates so later declarations cannot be
treated as already collected. Update the relevant initializer or factory near
the validation of arguments and add a regression test covering duplicate names.

In
`@Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteChoiceArgument.swift`:
- Around line 18-21: The CommandPaletteChoiceArgument initializer currently
accepts empty or duplicate choices, causing invalid selection state and
non-unique row IDs. Update CommandPaletteChoiceArgument initialization or
registration to reject empty choices and duplicate choice.value entries, then
add tests covering both invalid declarations while preserving valid choice
handling.
🪄 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 Plus

Run ID: 6b12fef6-1b3f-4418-89b5-a9dd72fd1ba5

📥 Commits

Reviewing files that changed from the base of the PR and between be0533e and c912873.

📒 Files selected for processing (23)
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/Vault/Providers/HermesAgent/HermesAgentIndex.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteArgumentCollection.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteArgumentSelectionResult.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteChoice.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Values/CommandPaletteChoiceArgument.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationCompacting.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationCompaction.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationTransferError.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationTransferService.swift
  • Sources/AgentConversationForkRequest.swift
  • Sources/AgentConversationForkTargetHarness.swift
  • Sources/CommandPalette/CommandPaletteDebugFormatting.swift
  • Sources/ContentView.swift
  • Sources/PopoverAnchorView.swift
  • Sources/SelectedWorkspaceDirectoryObserver.swift
  • Sources/SelectedWorkspaceDirectorySnapshot.swift
  • Sources/SessionIndexView.swift
  • Sources/SessionTranscriptLatestCollector.swift
  • Sources/SessionTranscriptPopoverCoordinator.swift
  • Sources/SessionTranscriptPopoverHost.swift
  • Sources/SessionTranscriptRetention.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/AgentConversationCrossHarnessForkTests.swift
💤 Files with no reviewable changes (3)
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationCompaction.swift
  • Sources/SessionTranscriptRetention.swift
  • Packages/macOS/CmuxConversationTransfer/Sources/CmuxConversationTransfer/ConversationTransferService.swift

Comment thread Sources/CommandPalette/CommandPaletteDebugFormatting.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

Caution

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

⚠️ Outside diff range comments (1)
Sources/SessionIndexView.swift (1)

1272-1369: 🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

Unbounded full-file scans introduced by the new "opening + latest" retention mode. The cross-harness-fork retention feature (retention.keepsLatestTurns) reads potentially the entire transcript file for the generic JSONL agents and adds a second unbounded scan for antigravity's opening-turn lookup, instead of reusing the bounded tail-paging already implemented elsewhere in this same PR.

  • Sources/SessionIndexView.swift#L1272-L1369: finishLine()/the streaming loop never sets didHitTurnLimit when retention.keepsLatestTurns, so Claude/Codex/Grok/registered transcripts are always read forward to EOF to find the "latest N" turns; consider a tail-based read strategy analogous to fromTailPages instead of a full forward scan.
  • Sources/SessionIndexView.swift#L1409-L1419: the additional SessionIndexJSONLReader().fromStart(url:) call to find the opening user turn has no byte bound; consider using the existing maxBytes overload with a generous cap and treating a miss as best-effort, rather than scanning the whole history file.
  • Sources/SessionIndexJSONLReader.swift#L11-L17: the new fromStart(url:body:) overload itself is the unbounded primitive enabling the above; if callers need a true full scan it's fine as a utility, but its cross-harness-fork usage should be bounded.
🤖 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/SessionIndexView.swift` around lines 1272 - 1369, Bound the
cross-harness-fork transcript reads instead of scanning full files: in
Sources/SessionIndexView.swift:1272-1369, replace the keepsLatestTurns forward
streaming path with the existing bounded tail-page strategy analogous to
fromTailPages, preserving latest-turn ordering and retention behavior; in
Sources/SessionIndexView.swift:1409-1419, call the bounded maxBytes overload for
the opening user-turn lookup with a generous cap and treat misses as
best-effort; in Sources/SessionIndexJSONLReader.swift:11-17, retain
fromStart(url:body:) only for intentional full scans and ensure this feature
uses the bounded overload.
🤖 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/SessionIndexView.swift`:
- Around line 1409-1419: Bound the opening-turn lookup in the
retention.keepsLatestTurns branch by using the existing maxBytes-capable
SessionIndexJSONLReader.fromStart overload instead of the unbounded overload.
Reuse the appropriate existing byte limit, while preserving the session ID and
agent matching logic and best-effort assignment to openingUser.

---

Outside diff comments:
In `@Sources/SessionIndexView.swift`:
- Around line 1272-1369: Bound the cross-harness-fork transcript reads instead
of scanning full files: in Sources/SessionIndexView.swift:1272-1369, replace the
keepsLatestTurns forward streaming path with the existing bounded tail-page
strategy analogous to fromTailPages, preserving latest-turn ordering and
retention behavior; in Sources/SessionIndexView.swift:1409-1419, call the
bounded maxBytes overload for the opening user-turn lookup with a generous cap
and treat misses as best-effort; in Sources/SessionIndexJSONLReader.swift:11-17,
retain fromStart(url:body:) only for intentional full scans and ensure this
feature uses the bounded overload.
🪄 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 Plus

Run ID: 89ed76a0-2342-41ed-bc38-cfec5a684af3

📥 Commits

Reviewing files that changed from the base of the PR and between c912873 and 17f8262.

📒 Files selected for processing (11)
  • Resources/Localizable.xcstrings
  • Sources/AgentConversationForkTargetHarness.swift
  • Sources/AgentConversationSource.swift
  • Sources/CommandPalette/CommandPaletteDebugFormatting.swift
  • Sources/ContentView.swift
  • Sources/GhosttyNSView+ForkConversationContextMenu.swift
  • Sources/RovoDevTranscriptPreview.swift
  • Sources/SessionIndexJSONLReader.swift
  • Sources/SessionIndexView.swift
  • Sources/Workspace+AgentConversationForkRequest.swift
  • cmuxTests/AgentConversationCrossHarnessForkTests.swift

Comment thread Sources/SessionIndexView.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.

Caution

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

⚠️ Outside diff range comments (1)
Sources/AgentConversationForkTargetHarness.swift (1)

16-21: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep harness brand names out of localization.

Claude Code, Codex, and OpenCode are product names; render them as literals rather than translatable catalog values.

Proposed fix
 case .claude:
-    String(localized: "forkConversation.harness.claude", defaultValue: "Claude Code")
+    "Claude Code"
 case .codex:
-    String(localized: "forkConversation.harness.codex", defaultValue: "Codex")
+    "Codex"
 case .opencode:
-    String(localized: "forkConversation.harness.opencode", defaultValue: "OpenCode")
+    "OpenCode"

Based on learnings: brand/product name literals should not be wrapped in String(localized:).

🤖 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/AgentConversationForkTargetHarness.swift` around lines 16 - 21,
Update the harness-name mapping in the relevant switch so the .claude, .codex,
and .opencode cases return their product names as plain string literals,
removing the String(localized:) wrappers while preserving the displayed names.

Source: Learnings

🤖 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 `@Sources/AgentConversationForkTargetHarness.swift`:
- Around line 16-21: Update the harness-name mapping in the relevant switch so
the .claude, .codex, and .opencode cases return their product names as plain
string literals, removing the String(localized:) wrappers while preserving the
displayed names.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f1e8b3ca-619f-432b-b357-4ccc81dcd0f1

📥 Commits

Reviewing files that changed from the base of the PR and between 17f8262 and e5d1b3f.

📒 Files selected for processing (6)
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Context/CommandPaletteContextKeys.swift
  • Sources/AgentConversationForkTargetHarness.swift
  • Sources/ContentView.swift
  • Sources/GhosttyNSView+ForkConversationContextMenu.swift
  • Sources/Workspace+AgentConversationForkRequest.swift
  • cmuxTests/AgentConversationCrossHarnessForkTests.swift

@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Jul 29, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

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

Fork conversations across agent harnesses (Codex <-> Claude Code and others)

3 participants