Skip to content

Resolve last-turn diffs in a persistent Rust sidecar - #8255

Closed
lawrencecchen wants to merge 142 commits into
mainfrom
feat-trajectory-last-turn
Closed

lawrencecchen wants to merge 142 commits into
mainfrom
feat-trajectory-last-turn

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Replaces prompt-time Git snapshots with on-demand agent trajectory patches.

Swift now sends only the agent provider and session ID. The Rust diff sidecar resolves the latest Codex, Claude, or OpenCode turn, verifies its repository, and serves the resulting patch through the existing diff session protocol. The viewer treats agentTurn as a first-class source and does not rewrite it when repository UI state changes.

The packaged native bridge now owns one lazy-started Rust process for the app lifetime. Newline-delimited requests share its private stdin/stdout pipes, Rust multiplexes up to four jobs by request ID, cancellation aborts only the matching job, and the next request restarts the child after a crash. No HTTP listener or filesystem socket is used.

This removes the Git stash baseline, untracked-file hashing, JSON and SQLite baseline storage, legacy migration, pruning, and prompt-hook snapshot work. Hook state becomes visible before auxiliary work, and stale cleanup cannot clear a running replacement on the same panel.

Rust is pinned to 1.97.0 with edition 2024. Direct crates and Cargo.lock are current for Rust 1.97. The obsolete fs2 dependency is replaced by stable std::fs::File locking.

Supersedes #8205. Builds on the merged Rust-sidecar prerequisite #7804.

Validation:

  • cargo update --verbose: zero direct updates remaining
  • cargo test --all-features --no-fail-fast: 26 passed
  • cargo clippy --all-targets --all-features -- -D warnings: passed
  • cargo build --release --all-features: passed
  • bun test test/app.test.tsx: 16 passed
  • bun run typecheck: passed
  • bun run lint:ci: passed
  • Real trajectory experiments: Codex 48.6 MB in 40 ms, Claude 4.5 MB in 14 ms, OpenCode SQLite in 10 ms
  • Old git stash create alone: 110 to 140 ms per hook, before untracked-file work
  • Tagged UI preflight: a real Codex session cleared Loading diff and rendered 13 changed files
  • Persistent transport experiment: 50 handshakes averaged 0.302 ms each versus 11.031 ms with process-per-request
  • Tagged lifecycle preflight: two 13-file last-turn diffs reused one PID; after forced termination, the next diff started a new PID and rendered all 13 files
  • Tagged cloud build: https://github.com/manaflow-ai/cmux/actions/runs/29480701050

Regression commits remain test-first, then fix, in the PR history.


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


Summary by cubic

Switches last‑turn diffs to typed agent trajectory patches resolved by a persistent Rust sidecar over stdio. Adds immediate single‑skeleton loading with worker‑gated renderer init, trusted session reuse, and removes prompt‑time Git snapshotting.

  • New Features

    • Added typed agentTurn { provider, session_id } diffs with optional viewerInstanceId; patches stream from Rust trajectory.rs via rusqlite (Rust 1.97.1, worker_threads = 2).
    • One long‑lived sidecar over stdio with request multiplexing, per‑request cancel, non‑blocking reply draining, async exit signaling, and crash restart; browser.navigate accepts expected_operation_id.
    • Immediate loading attaches before browser setup and keeps one skeleton until the renderer is ready; pending opens are isolated per page and bound to operation IDs; deferred navigations reuse a trusted session without re‑registration.
    • Asset cache self‑heals using .cmux-asset-manifest.json; a new pruner removes stale asset directories.
    • Web workers synchronize render options and gate renderer readiness with an init timeout and a fallback phase if the pool fails.
  • Bug Fixes

    • Serialized diff scheme callbacks on the main actor, versioned task registrations, and rejected reused task identities; preserved rendered errors and retired the skeleton after navigation.
    • Enforced trajectory root authorization (including non‑Git) and rejected cross‑repo resolutions; clearer CLI errors when --agent/--session or a typed sidecar are missing; --last-turn works without a repo/cwd and preserves agent identity; Codex patch sources inherit the active turn identity.
    • Published sidebar agent activity before slow turn snapshots and preserved active state during stale cleanup.
    • Bounded sidecar/trajectory work (transcript/patch sizes and concurrency) and awaited sidecar process exit asynchronously.

Written for commit 2600f24. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added typed “agentTurn” diffs using agent/session history (Codex, Claude, OpenCode) with required session payloads.
    • Extended diff CLI with --agent, --session, and --target-surface (supports browser.navigate + expected URL).
    • Improved diff viewer loading with prewarming, skeleton overlay, and renderer-ready notifications.
  • Bug Fixes
    • “Last turn” now reliably fails with a clear error when required agent/session details (or typed sidecar support) are missing.
    • More robust diff viewer session lifecycle and request handling.
  • Chores / Tests
    • Updated diff sidecar Rust toolchain/runtime, asset manifest support, and significantly expanded trajectory/session integration tests.

@coderabbitai

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

The diff viewer’s last-turn source now carries provider and session identity to the Rust sidecar. The sidecar resolves latest-turn patches from Codex, Claude, and OpenCode storage, while CLI, UI, asset handling, lifecycle behavior, RPC transport, and regression tests are updated.

Changes

Agent-turn diff flow

Layer / File(s) Summary
Agent-turn contracts and CLI wiring
Native/DiffSidecar/src/protocol.rs, CLI/..., Sources/..., webviews/...
Last-turn sources now use agentTurn with provider and session ID; CLI parsing, viewer launch arguments, persistent sidecar transport, and repo selection handling carry and validate this identity.
Provider trajectory resolution
Native/DiffSidecar/src/trajectory.rs, Native/DiffSidecar/tests/trajectory.rs
The sidecar reconstructs latest-turn patches from Codex JSONL, Claude transcripts, and OpenCode SQLite data with path, size, and payload validation.
Sidecar sessions and streaming RPC
Native/DiffSidecar/src/server.rs, Sources/Panels/DiffSidecarBridge.swift, Native/DiffSidecar/tests/server_integration.rs
Agent-turn session opening resolves and authorizes repositories, writes resolved patches, and supports persistent newline-delimited RPC requests, cancellation, and updated locking.
Viewer runtime, assets, and application state
CLI/CMUXCLI+DiffViewerBundledAssets.swift, CLI/cmux_open.swift, Sources/Panels/*, scripts/compress-markdown-viewer-assets.sh, Sources/ContentView.swift
Viewer navigation, prewarming, scheme-task lifecycle, asset manifests, content keys, reusable preparation paths, and command-palette caching are updated.
Lifecycle behavior and regression coverage
CLI/cmux.swift, Sources/Workspace+PanelLifecycle.swift, cmuxTests/*, webviews/test/*
Codex hook terminal handling and panel-scoped runtime cleanup change, while CLI, webview, navigation, trajectory, and RPC tests validate the new flows.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant DiffCLI
  participant DiffSidecar
  participant AgentStorage
  participant DiffViewer
  User->>DiffCLI: select last-turn with agent and session
  DiffCLI->>DiffSidecar: open agentTurn session
  DiffSidecar->>AgentStorage: resolve latest-turn trajectory
  AgentStorage-->>DiffSidecar: unified patch and repository root
  DiffSidecar->>DiffViewer: return session and patch
Loading

Possibly related issues

  • manaflow-ai/cmux-dev-artifacts#4295: Relates to RestorableAgentKind availability and diff-viewer test/build updates.
  • manaflow-ai/cmux-dev-artifacts#4242: Relates to diff-viewer loading-page and renderer-readiness integration.
  • manaflow-ai/cmux-dev-artifacts#4244: Relates to the typed diff loading-page-before-session flow.
  • manaflow-ai/cmux-dev-artifacts#4307: Relates to cmux diff --last-turn provider mapping and OpenCode spelling.

Possibly related PRs

  • manaflow-ai/cmux#8205: Reorganizes related prompt-session terminal and stale-handling baseline behavior.
  • manaflow-ai/cmux#7804: Introduces the typed Rust diff-sidecar protocol and transport surface extended here.
  • manaflow-ai/cmux#7554: Shares the browser prewarm infrastructure later refactored into a keyed multi-entry pool.

Important

Pre-merge checks failed

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

❌ Failed checks (3 errors, 1 warning)

Check name Status Explanation Resolution
Cmux User-Facing Error Privacy ❌ Error A user-facing CLIError says 'Last-turn diffs require the Rust diff sidecar,' exposing an internal implementation name. Rewrite that error in product terms, e.g. 'Last-turn diffs require the agent trajectory service,' and avoid internal component names.
Cmux Full Internationalization ❌ Error User-facing CLI diff help/error copy changed, but Resources/Localizable.xcstrings only provides en and ja for cli.diff.usage and cli.diff.error.*, not all supported locales. Add translated entries for every supported locale in Resources/Localizable.xcstrings for the changed cli.diff.usage and cli.diff.error.* keys.
Cmux No Ambient Global State ❌ Error AppDelegate adds a production diffViewerProcesses map retaining viewer subprocesses, which is new app-delegate runtime state. Move viewer-process retention into a dedicated manager/actor injected at the app seam; keep AppDelegate as a thin launcher/forwarder.
Docstring Coverage ⚠️ Warning Docstring coverage is 23.81% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (21 passed)
Check name Status Explanation
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 New UI helpers stay on @MainActor types, and shared mutable state is isolated in @MainActor BrowserPrewarmedWebViewPool and actors; no new unsafe Sendable refs.
Cmux Swift Blocking Runtime ✅ Passed The new Swift runtime code is actor/async-based; I found no introduced semaphores, main-syncs, or blocking waits in the touched production changes.
Cmux Browser Automation Off-Main ✅ Passed browser wait/callback methods stay in the socket-worker router, the main switch excludes them, browser.navigate uses explicit @MainActor prewarm, and DockSocketLifecycleTests runs it on the worker...
Cmux Expensive Synchronous Load ✅ Passed The new diff-viewer path uses SharedLiveAgentIndex.shared.freshSnapshot/scheduleRefreshIfStale, and cache reloads run off-main via Task.detached; no new direct `RestorableAgentSessionIndex.lo...
Cmux Cache Substitution Correctness ✅ Passed AppDelegate now uses SharedLiveAgentIndex.freshSnapshot, which explicitly reloads the live index; remaining caches are transient UI/build caches, not persistence/history paths.
Cmux No Hacky Sleeps ✅ Passed Only a Swift test changed; no TS/JS/shell/runtime sleep or polling logic was added in covered languages.
Cmux Algorithmic Complexity ✅ Passed New scans are linear or bounded (e.g., pool capacity 2, transcript byte limits); no nested full-collection rescans in hot production paths.
Cmux Swift Concurrency ✅ Passed Added async uses are boundary-scoped (AppKit startup/termination and WebKit callbacks); no new background DispatchQueue or Combine app state was introduced.
Cmux Swift @Concurrent ✅ Passed No changed Swift async helper violated the rule; heavy work hops to detached tasks/actors, and the new UI-bound calls are intentionally on MainActor.
Cmux Swift Package Boundaries ✅ Passed PASS: the reusable trajectory/protocol logic lives in Native/DiffSidecar; Sources/ changes are app/UI/launch glue around the new sidecar flow.
Cmux Swiftpm Lockfiles ✅ Passed PR has no .gitignore, Package.swift, or Package.resolved changes; the Xcode project diff only removes/adds Swift source files and no SwiftPM package refs, so no lockfile rule is triggered.
Cmux Swift Logging ✅ Passed The checked-out change is test-only and adds no disallowed logging in runtime Swift code.
Cmux Swiftui State Layout ✅ Passed The actual commit only changes an iOS test file; no SwiftUI view/state/layout code is in the diff, so the rule doesn’t apply.
Cmux Architecture Rethink ✅ Passed The diff adds required bridge/coordinator code, but the loading handoff keeps a clear owner and no new polling/lock/sleep workaround that widens bad-state representability.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The new SpinnerGalleryDebugWindowController uses stable id cmux.spinnerGallery and is registered in cmuxAuxiliaryWindowIdentifiers; the lint script covers this pattern.
Cmux Source Artifacts ✅ Passed No hidden scratch/build-output paths are present; changed generated assets and lockfiles are intentional repo-owned inputs per the rule.
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS — The PR diff adds no new DEBUG/test-only seams in production Sources; the only ForTests helper I found in ContentView predates and is unchanged.
Title check ✅ Passed The title matches the main change: moving last-turn diff resolution into a persistent Rust sidecar.
Description check ✅ Passed The description covers summary, testing, and review trigger, but it omits the demo video and checklist sections from the template.
✨ 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 feat-trajectory-last-turn

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.

@socket-security

socket-security Bot commented Jul 16, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​rustls@​0.23.428210093100100
Addedcargo/​tokio-tungstenite@​0.30.09910093100100

View full report

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 54d0cced5d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread CLI/cmux_open.swift Outdated
Comment thread Native/DiffSidecar/src/trajectory.rs Outdated
@greptile-apps

greptile-apps Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces prompt-time Git snapshots with on-demand agent trajectory patches delivered by a persistent Rust sidecar over stdio multiplexing. Swift sends only the agent provider and session ID; the Rust trajectory.rs module resolves the latest Codex, Claude, or OpenCode turn, verifies the repo root, and streams the patch through the existing diff session protocol. The DiffSidecarBridge now owns one long-lived DiffSidecarProcessSupervisor actor for the app lifetime instead of spawning a child per request, and the diff-open UX path attaches an immediate skeleton overlay before the CLI runs.

  • Persistent sidecar transport: DiffSidecarProcessSupervisor multiplexes up to four concurrent requests over a single stdin/stdout pair with per-request cancellation frames, a non-blocking DiffSidecarFrameWriter, and automatic crash restart on the next request.
  • Agent trajectory resolution: trajectory.rs locates Codex (SQLite), Claude (JSONL + subagent transcripts), and OpenCode (SQLite) sessions, enforces repo-root authorization, and validates session IDs against path-separator injection.
  • Immediate loading UX: A prewarmed loading page with a skeleton overlay is attached before the async snapshot race, and the WorkerRendererPhase state machine gates the diff renderer on worker-pool readiness with a 1-second main-thread fallback.

Confidence Score: 4/5

The core transport and trajectory logic is well-structured; one production Swift seam added for test observation needs to be moved out of Sources before shipping.

The DiffViewerAssetStreamLimiter.waitUntilQueued(count:) method and its queueCountWaiters infrastructure are #if DEBUG-gated additions in Sources/Panels/BrowserPanel.swift with no production caller — they exist only to let BrowserPanelTests synchronize on internal queue depth. Moving this observation point to the test target is a straightforward fix with no behavior change.

Files Needing Attention: Sources/Panels/BrowserPanel.swift — the DiffViewerAssetStreamLimiter actor contains a #if DEBUG-guarded test seam that should live in the test target instead.

Important Files Changed

Filename Overview
Sources/Panels/BrowserPanel.swift Replaces NSLock/NSCondition scheme-task tracking with a @MainActor DiffViewerSchemeTaskLifecycle and DiffViewerAssetStreamLimiter actor. The stream limiter introduces a #if DEBUG-gated waitUntilQueued test seam in production Sources that violates the repo's no-test-debug-seam rule.
Sources/Panels/DiffSidecarBridge.swift Replaces per-request child process with a persistent DiffSidecarProcessSupervisor actor; adds checked-continuation multiplexing, per-request cancellation, and non-blocking frame writing via DiffSidecarFrameWriter. Synchronous termination handle correctly separated for app-exit use.
Native/DiffSidecar/src/trajectory.rs New file implementing agent trajectory resolution for Codex, Claude, and OpenCode. Session ID validation correctly rejects path separators and dot-only names. Cancellation checks are threaded through long scans. Bounds on transcript bytes, patch bytes, and directory entries look appropriate.
Native/DiffSidecar/src/server.rs Restructures RPC transport to newline-delimited multiplexed requests over a persistent stdin/stdout pair. Adds per-request abort handles, a JoinSet for concurrent dispatch, a response mpsc channel, and agent-turn authorization. fs2 replaced by std::fs::File locking with correct fail-closed semantics.
Sources/AppDelegate.swift Diff-open path refactored to attach an immediate loading skeleton first, then race a 1-second freshSnapshot deadline before launching the CLI. DiffSidecarBridge.shutdown() added on app termination. valueBeforeDiffViewerDeadline is a dedicated cancellation-aware timeout with test coverage.
webviews/src/App.tsx Adds DiffRendererProvider with worker-pool lifecycle gating, rendererPhase state, and a fallback main-thread render path. Repo select hidden for agentTurn sources. viewerInstanceId threaded through session close.
webviews/src/worker-renderer-lifecycle.ts New module implementing a 1-second deadline for worker pool initialization with a main-thread fallback phase. setTimeout is cleared in finally and the abstraction is unit-tested.
Sources/Panels/BrowserPanel+PrewarmedWebViewAdoption.swift Adds DiffViewerLoadingPage, DiffViewerImmediateLoadingPresentation, and DiffViewerInitialLoadingPresentation for the immediate skeleton overlay system. Prewarm pool refill after a diff-loading claim is a clean optimization.
Sources/SharedLiveAgentIndex.swift Adds freshSnapshot that runs a live process-backed reload and coalesces concurrent callers via freshSnapshotRefreshTask. Task is properly cancelled in deinit.

Sequence Diagram

sequenceDiagram
    participant AppDelegate
    participant BrowserPanel
    participant DiffSidecarBridge
    participant DiffSidecarProcessSupervisor
    participant RustSidecar
    participant TrajectoryRS

    AppDelegate->>BrowserPanel: openBrowserOnRight(loadingURL)
    AppDelegate->>SharedLiveAgentIndex: freshSnapshot(1s deadline)
    SharedLiveAgentIndex-->>AppDelegate: SessionRestorableAgentSnapshot
    AppDelegate->>AppDelegate: launchDiffViewerProcess(--agent, --session)

    Note over DiffSidecarProcessSupervisor,RustSidecar: Lazy-started, reused across requests

    DiffSidecarBridge->>DiffSidecarProcessSupervisor: run(request)
    DiffSidecarProcessSupervisor->>RustSidecar: stdin frame (newline-delimited JSON)
    RustSidecar->>TrajectoryRS: resolve_last_turn_patch
    TrajectoryRS-->>RustSidecar: ResolvedTurnPatch (repo_root + patch)
    RustSidecar->>DiffSidecarProcessSupervisor: stdout frame (newline-delimited JSON)
    DiffSidecarProcessSupervisor-->>DiffSidecarBridge: Data response
    DiffSidecarBridge-->>BrowserPanel: diff session opened
    BrowserPanel->>BrowserPanel: closeDiffViewerLoadingOverlay
Loading

Reviews (70): Last reviewed commit: "fix: resolve final merge gate failures" | Re-trigger Greptile

Comment thread Sources/RestorableAgentTypes.swift
Comment thread Native/DiffSidecar/src/trajectory.rs

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

🤖 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 `@CLI/cmux_open.swift`:
- Line 1538: In the last-turn diff source handling near the current throw,
replace CLIError with EmptyDiffSourceError so completeDeferredDiffViewerSource
can catch it and continue the fallback loop on legacy hosts. Keep the separate
CLIError behavior in writeGitDiffViewerHTMLSet for explicit --last-turn requests
unchanged.

In `@CLI/cmux.swift`:
- Line 35297: Remove the duplicate diff command usage entry from the cmux help
output, keeping the existing documentation entry near line 35176 and deleting
the redundant entry shown here.

In `@Native/DiffSidecar/src/server.rs`:
- Around line 1129-1130: Update the lock-result handling in the lease-state
check so any outcome other than successfully acquiring the exclusive lock
preserves the file, including TryLockError::Error. Keep the existing WouldBlock
behavior indicating an active lease, and ensure only a successful lock
acquisition reports the lease as inactive.

In `@Native/DiffSidecar/src/trajectory.rs`:
- Around line 325-334: Update claude_transcript_cwd and the underlying
for_json_lines traversal so processing stops immediately after the first valid
cwd is found, rather than continuing through the transcript; preserve the
existing Option<PathBuf> result and error propagation. Alternatively, reuse cwd
extraction within claude_last_turn_patch so the transcript is scanned only once.
- Around line 460-465: Update the prompt-tracking logic around current_prompt
and patch so a latest user prompt without promptId clears the prior patch and
fails closed instead of retaining the preceding turn. Ensure malformed JSONL
prompt lines are detected and handled as invalid latest-turn input rather than
silently ignored or returning stale data. Add regressions covering both missing
promptId and malformed latest prompt lines.
- Around line 501-504: Update the create-file determination in the trajectory
diff-generation logic to rely exclusively on the explicit `"type": "create"`
value, removing the `oldLines == 0` fallback. Add a regression test covering an
insertion-only edit to an existing file and verify it is not emitted as a
new-file diff.

In `@Sources/AppDelegate.swift`:
- Around line 6059-6061: Update the agent-turn routing around
normalizedOpenDiffViewerPath so a missing snapshot.workingDirectory and
launchCommand.workingDirectory does not prevent the path from executing when
provider/session identity is valid. Pass fallbackCwd only as the CLI working
directory, while preserving the original snapshot source values and relying on
the structured identity for repository resolution.
🪄 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: a7facda4-56ab-4e01-b714-2c1d99efddb2

📥 Commits

Reviewing files that changed from the base of the PR and between ebee659 and 54d0cce.

⛔ Files ignored due to path filters (2)
  • Native/DiffSidecar/Cargo.lock is excluded by !**/*.lock
  • webviews/src/diff/generated/protocol.ts is excluded by !**/generated/**
📒 Files selected for processing (26)
  • CLI/CMUXCLI+DiffSidecar.swift
  • CLI/CMUXCLI+TypedDiffViewer.swift
  • CLI/cmux.swift
  • CLI/cmux_open.swift
  • Native/DiffSidecar/Cargo.toml
  • Native/DiffSidecar/rust-toolchain.toml
  • Native/DiffSidecar/src/lib.rs
  • Native/DiffSidecar/src/protocol.rs
  • Native/DiffSidecar/src/server.rs
  • Native/DiffSidecar/src/trajectory.rs
  • Native/DiffSidecar/tests/server_integration.rs
  • Native/DiffSidecar/tests/trajectory.rs
  • Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs
  • Sources/AppDelegate.swift
  • Sources/OpenDiffViewerAgentBaselineLookup.swift
  • Sources/OpenDiffViewerAgentContextRequest.swift
  • Sources/RestorableAgentTypes.swift
  • Sources/Workspace+PanelLifecycle.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/AgentHibernationTests.swift
  • cmuxTests/CLICodexHookTimeoutRegressionTests.swift
  • cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift
  • cmuxTests/CMUXOpenCommandTests.swift
  • scripts/ci/cmux-unit-test-timings.json
  • webviews/src/App.tsx
  • webviews/test/app.test.tsx
💤 Files with no reviewable changes (5)
  • Sources/OpenDiffViewerAgentContextRequest.swift
  • scripts/ci/cmux-unit-test-timings.json
  • Sources/OpenDiffViewerAgentBaselineLookup.swift
  • cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift
  • cmux.xcodeproj/project.pbxproj

Comment thread CLI/cmux_open.swift Outdated
Comment thread CLI/cmux.swift
Comment thread Native/DiffSidecar/src/server.rs Outdated
Comment thread Native/DiffSidecar/src/trajectory.rs Outdated
Comment thread Native/DiffSidecar/src/trajectory.rs Outdated
Comment thread Native/DiffSidecar/src/trajectory.rs Outdated
Comment thread Sources/AppDelegate.swift Outdated
@lawrencecchen
lawrencecchen force-pushed the feat-trajectory-last-turn branch from 54d0cce to 259ea62 Compare July 16, 2026 07:39

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 259ea6223f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Native/DiffSidecar/src/trajectory.rs Outdated
@lawrencecchen lawrencecchen changed the title Resolve last-turn diffs from agent trajectories Resolve last-turn diffs in a persistent Rust sidecar Jul 16, 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: 9

♻️ Duplicate comments (1)
CLI/cmux.swift (1)

35297-35297: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove duplicate command documentation.

The diff command usage is listed twice in the cmux help output (here and at line 35176). Consider removing this redundant entry to keep the help text clean.

♻️ Proposed refactor
-          diff [patch-file|-] [--source <unstaged|staged|branch|last-turn>] [--agent <codex|claude|opencode>] [--session <id>] [--cwd <path>] [--base <ref>] [--focus <true|false>] [--no-focus] [--title <text>] [--layout <split|unified>] [--font-size <points>] (open patch input or git source in a browser split)
🤖 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 `@CLI/cmux.swift` at line 35297, Remove the duplicate diff command usage entry
from the cmux help output, keeping the canonical entry near line 35176 and
deleting the later duplicate shown in the diff.
🤖 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 `@Native/DiffSidecar/src/server.rs`:
- Around line 354-360: Update the cancel-frame handling in the RPC request
parsing flow so a missing or empty requestId produces the same invalidRequest
response used for other malformed frames instead of propagating an error through
frame?. Preserve valid cancel frames as RpcRequestRead::Cancel and keep the
persistent RPC session running.

In `@Native/DiffSidecar/src/trajectory.rs`:
- Around line 349-354: Update the task_started handling in the trajectory
event-processing logic to require a present turn_id; when it is missing, clear
current_turn and patch, then return TrajectoryError::Invalid instead of
preserving prior state. Keep the existing initialization and successful
early-return behavior unchanged for events that include turn_id.
- Around line 155-184: Update the trajectory selection logic around
read_hook_record, database_record, transcript, and repo_root to choose one
authoritative record atomically: use the hook only when both transcript_path and
cwd are present, otherwise require and use both fields from the database record.
Remove the independent per-field fallback chains so transcript and repository
root can never be combined from different sources.
- Around line 141-148: Update validate_session_id to reject path-bearing session
IDs before they are used as directory components: permit only the providers’
identifier character set, or equivalently require a single normal path component
with no separators, absolute-path semantics, or traversal segments. Preserve the
existing empty, length, and control-character validation and return
TrajectoryError::Invalid for disallowed values.
- Around line 604-624: Update relative_patch_path and the code that writes Git
patch headers to Git-quote every path component or complete relative path before
interpolation, escaping spaces, quotes, backslashes, tabs, newlines, and other
required characters while preserving valid UTF-8. Ensure all emitted headers use
the encoded path so filenames cannot inject additional headers, while retaining
the existing path validation behavior.

In `@Sources/Panels/DiffSidecarBridge.swift`:
- Around line 211-216: Align the encoded response-size limit used by
DiffSidecarBridge and the sidecar trajectory framing logic. Update the visible
maximumResponseBytes contract and the corresponding limit in trajectory.rs to
the same value, ensuring valid responses are not rejected as invalidResponse and
no separate conflicting patch-size limit remains.
- Around line 25-29: Update DiffSidecarBridge.shutdown so it no longer launches
an unretained Task.detached operation; make shutdown caller-owned and awaitable
by exposing an async shutdown operation that directly awaits
sidecarProcess.shutdown, preserving the utility priority only if the surrounding
API requires it.
- Around line 402-405: Update outputDidEnd(_:) so a matching stdout EOF always
transitions the bridge to a failed/stopped state, including when
process?.isRunning is true; remove the running-process guard while retaining the
generation check and existing processExited error propagation, ensuring
outputTask is cleared through stopProcess.

In `@Sources/RestorableAgentTypes.swift`:
- Around line 103-111: Update diffTrajectoryProvider for the .opencode case to
return the contract-required "openCode" string instead of rawValue, while
preserving rawValue for .codex and .claude and nil for all other providers.

---

Duplicate comments:
In `@CLI/cmux.swift`:
- Line 35297: Remove the duplicate diff command usage entry from the cmux help
output, keeping the canonical entry near line 35176 and deleting the later
duplicate shown in the diff.
🪄 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: 51d3b435-eece-4051-9bc1-12d6648594c6

📥 Commits

Reviewing files that changed from the base of the PR and between 54d0cce and 259ea62.

⛔ Files ignored due to path filters (2)
  • Native/DiffSidecar/Cargo.lock is excluded by !**/*.lock
  • webviews/src/diff/generated/protocol.ts is excluded by !**/generated/**
📒 Files selected for processing (28)
  • CLI/CMUXCLI+DiffSidecar.swift
  • CLI/CMUXCLI+TypedDiffViewer.swift
  • CLI/cmux.swift
  • CLI/cmux_open.swift
  • Native/DiffSidecar/Cargo.toml
  • Native/DiffSidecar/rust-toolchain.toml
  • Native/DiffSidecar/src/lib.rs
  • Native/DiffSidecar/src/main.rs
  • Native/DiffSidecar/src/protocol.rs
  • Native/DiffSidecar/src/server.rs
  • Native/DiffSidecar/src/trajectory.rs
  • Native/DiffSidecar/tests/server_integration.rs
  • Native/DiffSidecar/tests/trajectory.rs
  • Resources/markdown-viewer/webviews-app/chunks/diffSurface.mjs
  • Sources/AppDelegate.swift
  • Sources/OpenDiffViewerAgentBaselineLookup.swift
  • Sources/OpenDiffViewerAgentContextRequest.swift
  • Sources/Panels/DiffSidecarBridge.swift
  • Sources/RestorableAgentTypes.swift
  • Sources/Workspace+PanelLifecycle.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/AgentHibernationTests.swift
  • cmuxTests/CLICodexHookTimeoutRegressionTests.swift
  • cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift
  • cmuxTests/CMUXOpenCommandTests.swift
  • scripts/ci/cmux-unit-test-timings.json
  • webviews/src/App.tsx
  • webviews/test/app.test.tsx
💤 Files with no reviewable changes (5)
  • Sources/OpenDiffViewerAgentBaselineLookup.swift
  • Sources/OpenDiffViewerAgentContextRequest.swift
  • scripts/ci/cmux-unit-test-timings.json
  • cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift
  • cmux.xcodeproj/project.pbxproj

Comment thread Native/DiffSidecar/src/server.rs
Comment thread Native/DiffSidecar/src/trajectory.rs
Comment thread Native/DiffSidecar/src/trajectory.rs Outdated
Comment thread Native/DiffSidecar/src/trajectory.rs
Comment thread Native/DiffSidecar/src/trajectory.rs Outdated
Comment thread Sources/Panels/DiffSidecarBridge.swift
Comment thread Sources/Panels/DiffSidecarBridge.swift
Comment thread Sources/Panels/DiffSidecarBridge.swift Outdated
Comment thread Sources/RestorableAgentTypes.swift
@cursor

cursor Bot commented Jul 16, 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.

@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

Caution

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

⚠️ Outside diff range comments (1)
CLI/cmux_open.swift (1)

3642-3648: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve agentProvider when building alternate-repository contexts.

This fresh context copies sessionId but drops agentProvider. Selecting an alternate repository’s last-turn page therefore emits an incomplete sessionSource, preventing provider-specific sidecar resolution.

🐛 Proposed fix
                 let pageContext = DiffSourceContext(
                     workspaceId: selectedContext.workspaceId,
                     surfaceId: selectedContext.surfaceId,
                     sessionId: selectedContext.sessionId,
                     repoRoot: option.repoRoot,
-                    branchBaseRef: source == .branch ? repoBranchBaseRef : selectedContext.branchBaseRef
+                    branchBaseRef: source == .branch ? repoBranchBaseRef : selectedContext.branchBaseRef,
+                    agentProvider: selectedContext.agentProvider
                 )

Based on the PR contract that provider and session identity must reach the Rust sidecar.

🤖 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 `@CLI/cmux_open.swift` around lines 3642 - 3648, Update the DiffSourceContext
construction for alternate-repository contexts to also copy
selectedContext.agentProvider, alongside workspaceId, surfaceId, and sessionId.
Preserve the existing repository and branch selection logic so provider and
session identity both reach the Rust sidecar.
🤖 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 `@CLI/cmux_open.swift`:
- Around line 6774-6779: Replace the hard-link-first logic in the bundled asset
cache population flow with an unconditional file copy, removing the Darwin.link
path and its fallback branching. Ensure each cache entry receives an independent
inode so later in-place .deflate rewrites cannot mutate existing
content-addressed assets or active viewers.

In `@cmuxTests/CMUXOpenCommandTests.swift`:
- Around line 1172-1173: Update the mock handling for browser.navigate in the
regression test to capture its parameters, then assert that the requested URL
matches redirectURL and that navigation targets the surface returned by
browser.open_split. Ensure the assertions validate both the destination URL and
target surface rather than accepting every navigation request.

---

Outside diff comments:
In `@CLI/cmux_open.swift`:
- Around line 3642-3648: Update the DiffSourceContext construction for
alternate-repository contexts to also copy selectedContext.agentProvider,
alongside workspaceId, surfaceId, and sessionId. Preserve the existing
repository and branch selection logic so provider and session identity both
reach the Rust sidecar.
🪄 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: 720ce371-1721-4dd8-bf5e-e6d97acb52aa

📥 Commits

Reviewing files that changed from the base of the PR and between 259ea62 and 5417bf8.

📒 Files selected for processing (6)
  • CLI/CMUXCLI+DiffViewerBundledAssets.swift
  • CLI/cmux_open.swift
  • Sources/ContentView.swift
  • cmuxTests/CLIMockSocketServerSupport.swift
  • cmuxTests/CMUXOpenCommandTests.swift
  • scripts/compress-markdown-viewer-assets.sh

Comment thread CLI/cmux_open.swift
Comment thread cmuxTests/CMUXOpenCommandTests.swift
@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.

…turn

# Conflicts:
#	Sources/Panels/BrowserPanel.swift
#	Sources/Panels/DiffCommentsBridge.swift
#	Sources/RestorableAgentSession.swift
#	Sources/TerminalController.swift
@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.

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

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

@cursor

cursor Bot commented Jul 25, 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.

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

1 similar comment
@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.

@lawrencecchen
lawrencecchen force-pushed the feat-trajectory-last-turn branch from 6834f09 to 8b97a9b Compare July 25, 2026 00:30
@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.

@lawrencecchen
lawrencecchen force-pushed the feat-trajectory-last-turn branch from 8b97a9b to 670d27a Compare July 25, 2026 00:34
@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.

lawrencecchen added a commit that referenced this pull request Jul 25, 2026
@lawrencecchen
lawrencecchen force-pushed the feat-trajectory-last-turn branch from 3e55ccd to 1ad0354 Compare July 25, 2026 01:19
lawrencecchen added a commit that referenced this pull request Jul 25, 2026
@lawrencecchen
lawrencecchen force-pushed the feat-trajectory-last-turn branch from 1ad0354 to 2600f24 Compare July 25, 2026 01:39
@cursor

cursor Bot commented Jul 25, 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 added a commit that referenced this pull request Jul 25, 2026
@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.

2 participants