Skip to content

Sync Claude task tools to workspace todos - #8965

Open
austinywang wants to merge 118 commits into
mainfrom
issue-8960-task-tools-todos
Open

austinywang wants to merge 118 commits into
mainfrom
issue-8960-task-tools-todos

Conversation

@austinywang

@austinywang austinywang commented Jul 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • install an async Claude PostToolUse bridge for TaskCreate, TaskUpdate, TaskGet, and TaskList
  • reconcile the authoritative session, team, or configured shared task directory into both Feed and workspace todos
  • preserve task identity, filter deleted tasks, and use activeForm for in-progress summaries
  • cover prefixed/unprefixed task layouts plus built-CLI hook delivery to both consumers

Testing

  • /usr/bin/arch -arm64 swift test in Packages/macOS/CMUXAgentLaunch (253 tests)
  • python3 tests/test_claude_wrapper_hooks.py
  • ./scripts/lint-pbxproj-test-wiring.sh
  • ./scripts/check-pbxproj.sh
  • app-host integration is wired into the focused GitHub Actions gate; no local app build was run

Closes #8960

Cross-process synchronization rationale

Claude Code starts each asynchronous task hook as an independent CLI process. A Swift actor can serialize state only inside one process, so it cannot prevent an older hook process from publishing after a newer one. The task-sync path therefore uses a portable macOS lockf(1) file-command lease beside the durable hook-state store (/usr/bin/lockf -k -s -t ...) to cover exactly one authoritative snapshot read plus its Feed and workspace deliveries. The scan is bounded (512 root entries, 512 task entries, and 64 KiB per task file), there is no sleep or polling, and closing the lease pipe releases the lock if a hook process exits. This is cross-process transaction ordering, not ongoing in-process mutable state.


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


Summary by cubic

For #8960, Claude task hooks now reconcile authoritative task snapshots into Feed and workspace todos instead of leaving workspace checklists empty. Task updates stay live-only in Feed (no longer appended to disk history), and reconciliation replaces only items owned by that task list.

Details

  • Covers PostToolUse task events and TaskCompleted for session, configured, and automatic-team lists across Claude profiles and relay scopes.
  • Persists task-list destinations, team bindings, generation fences, ownership claims, and cleanup state so ended sessions, deleted teams, restarts, and owner replacements cannot resurrect stale items.
  • Resolves automatic-team membership from Claude team config, validates task identity and ownership, and rejects checklist capacity overflows before Feed so a rejection cannot advance either consumer alone.
  • Probes live surface and workspace identity before delivery so a task hook running after its pane moved workspaces is not blocked by a stale recorded surface.
  • Skips malformed or deleted tasks, preserves activeForm, and bounds filesystem scans, file sizes, and snapshot text.
  • Adds workspace.todo.reconcile to replace one owner's items while preserving unrelated todos, IDs, and attachments.
  • Adds focused hook, workspace-todo, CMUXAgentLaunch, and bundled-wrapper coverage to CI.

Migration

  • Callers of workspace.todo.reconcile must provide a non-empty owner_id between 1 and 500 characters.

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

Review in cubic

Summary by CodeRabbit

  • New Features

    • Claude task activity now synchronizes with Feed and workspace todo lists.
    • Team and personal task lists are automatically associated with workspaces.
    • Added workspace todo reconciliation for externally managed items while preserving unrelated todos.
    • In-progress tasks can display active wording.
    • Task ownership and synchronization state persist across sessions.
    • Claude task tools now trigger automatic synchronization.
  • Bug Fixes

    • Improved cleanup for deleted or completed tasks, teams, and workspaces.
    • Added validation, ambiguity handling, capacity limits, and deadline protection.
  • Documentation

    • Added localized workspace-todo validation messages.

Note

Medium Risk
Large new cross-process hook and durable-state machinery mutates workspace todos and Feed; mitigated by deadlines, coalescing, and fail-closed rollback, but edge cases around team delete and owner replacement remain sensitive.

Overview
Adds a claude-hook task-sync pipeline that reads Claude’s on-disk task store and keeps Feed and workspace checklists aligned via workspace.todo.reconcile, with a validate-only pass before Feed so capacity rejections cannot diverge the two views.

The work is split into orchestrated paths for configured lists, automatic team bindings, personal/session lists, and TeamDelete, backed by new session-store state: scoped coalescing claims, cross-process task-sync locks, destination/team proofs, list retirement, and bounded legacy-owner cleanup with rollback when delivery fails.

Hook routing now probes live surface/workspace identity when a pane may have moved workspaces, instead of failing closed on a stale recorded surface alone.

CI adds focused regressions for automatic team sync, task-sync hooks, and workspace todo snapshots, and includes CmuxWorkspaces in the app-host build list.

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

@coderabbitai

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

Claude task tools now trigger asynchronous synchronization. The implementation loads bounded task snapshots, resolves personal and team ownership, publishes Feed data, and reconciles workspace todos with durable ownership and cleanup state.

Changes

Claude task synchronization

Layer / File(s) Summary
Task models and snapshot loading
Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/..., Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/...
Adds Claude task models, canonical path resolution, bounded snapshot loading, task identity matching, team binding resolution, deadlines, filesystem validation, active-form handling, and tests.
Owner-scoped checklist reconciliation
Packages/macOS/CmuxWorkspaces/..., Packages/macOS/CmuxControlSocket/..., Sources/..., Resources/Localizable.xcstrings
Adds checklist ownership persistence, atomic owner-scoped reconciliation, workspace control commands, validation, localized errors, and tests.
Task-sync hook and durable state
CLI/...
Adds task-sync dispatch, locking, task-list and team-binding persistence, snapshot delivery, workspace reconciliation, cleanup, telemetry, and response deadlines.
Hook wiring and regression coverage
Resources/bin/cmux-claude-wrapper, cmux.xcodeproj/project.pbxproj, cmuxTests/..., tests/..., .github/workflows/ci.yml
Adds asynchronous Claude task hooks, target registration, delivery fixtures, end-to-end coverage, automatic-team coverage, wrapper assertions, and CI test filters.

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

Sequence Diagram(s)

sequenceDiagram
  participant Claude
  participant ClaudeWrapper
  participant CMUXCLI
  participant TaskStore
  participant Feed
  participant WorkspaceTodo
  Claude->>ClaudeWrapper: emit TaskCreate, TaskUpdate, TaskGet, TaskList, or TeamDelete
  ClaudeWrapper->>CMUXCLI: invoke hooks claude task-sync asynchronously
  CMUXCLI->>TaskStore: resolve and load task snapshot under deadline and lock
  TaskStore-->>CMUXCLI: return tasks and ownership state
  CMUXCLI->>Feed: publish TodoWrite task snapshot
  CMUXCLI->>WorkspaceTodo: reconcile owner-scoped checklist
  WorkspaceTodo-->>CMUXCLI: return per-workspace results
  CMUXCLI-->>ClaudeWrapper: acknowledge task-sync hook
Loading

Suggested reviewers: lawrencecchen, azooz2003-bit


Important

Pre-merge checks failed

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

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Blocking Runtime ❌ Error CLI/cmux.swift adds production blocking pipe I/O (readData(ofLength: 1)) and two lockProcess.waitUntilExit() calls for the new lockf synchronization path. Replace synchronous pipe and process waits with nonblocking, event-driven or cancellation-aware lock/process completion handling; retain cross-process ordering without blocking the CLI runtime.
Cmux Architecture Rethink ❌ Error Production task-sync adds withClaudeTaskSyncLock using /usr/bin/lockf/flock around snapshot, Feed, workspace delivery, and persistence to repair a cross-process shared-state race. Move ordering into one authoritative app-host/control-service transaction with snapshot versions and stale-commit rejection, then remove the CLI task-sync lock lease.
Docstring Coverage ⚠️ Warning Docstring coverage is 18.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (22 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation recognizes Claude task tools, reads authoritative snapshots, preserves task identity, handles deletion, and updates workspace todos as required by [#8960].
Out of Scope Changes check ✅ Passed The changes support the linked issue through task synchronization, reconciliation, ownership, delivery, persistence, localization, and regression tests without unrelated code.
Cmux Swift Actor Isolation ✅ Passed No violation found: package/app settings do not default these declarations to MainActor, new Sendable types are value models, and UI reconciliation is explicitly @MainActor; no async service protoc...
Cmux Browser Automation Off-Main ✅ Passed The PR changes no browser automation policy, processV2Command, worker-router, or policy-test files; added socket work is workspace.todo.reconcile, so the browser rule is not triggered.
Cmux Expensive Synchronous Load ✅ Passed Task snapshot/team scans run only in the separate CLI hook path, not @MainActor; scans are bounded to 512 entries/64 KiB, while the @MainActor socket path only mutates in-memory todos.
Cmux Cache Substitution Correctness ✅ Passed No fresh-read substitution is present: task snapshots reread disk, team bindings use generation checks, and retained proofs are limited to documented cleanup.
Cmux No Hacky Sleeps ✅ Passed The changed shell wrapper only adds an async PostToolUse hook; scans found no new sleep, timer, polling, backoff, or fixed-delay synchronization. Other non-Swift changes are CI YAML and tests.
Cmux Algorithmic Complexity ✅ Passed No unbounded nested scan was introduced: workspace batches cap at 64 and use workspacesById, checklist work caps at 50, and task/team scans cap at 512 entries with bounded file sizes.
Cmux Swift Concurrency ✅ Passed The PR adds no new Dispatch queues, Combine state, completion-handler async APIs, or unmanaged Tasks. Task-sync execution is synchronous and uses deadline-bounded lockf/process I/O; existing async...
Cmux Swift @Concurrent ✅ Passed The PR adds no @concurrent or nonisolated async declarations; task-sync file I/O and parsing are synchronous CLI code, while the only changed MainActor path adds activeForm decoding.
Cmux Swift Package Boundaries ✅ Passed Independent Claude task loading, team resolution, workstream models, socket contracts, and checklist reconciliation are in CMUXAgentLaunch/CmuxControlSocket/CmuxWorkspaces with isolated package tes...
Cmux Swiftpm Lockfiles ✅ Passed No cmux-owned .gitignore ignores Package.resolved; the branch changes 0 manifests or lockfiles, and its Xcode diff adds only source references with no package-reference changes.
Cmux Swift Logging ✅ Passed The PR adds no direct print, debugPrint, dump, NSLog, Logger, or file/stdout diagnostics; printClaudeHookAck is intended CLI hook output, and telemetry records bounded state/errors without task con...
Cmux User-Facing Error Privacy ✅ Passed New socket errors only validate the owner field; task-sync emits {} and raw failures stay in internal telemetry, so no prohibited vendor, secret, session, or payload data reaches users.
Cmux Full Internationalization ✅ Passed New owner_id messages use String(localized:defaultValue:); both catalog keys have translated values for all 20 supported locales, with no web or metadata locale changes.
Cmux Swiftui State Layout ✅ Passed The checked-out PR diff changes only ClaudeTaskRootResolver.swift; it contains no SwiftUI views, state wrappers, layout readers, lazy rows, or render-time state mutation.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR adds no NSWindow, NSPanel, NSWindowController, SwiftUI Window, or close-shortcut code; the auxiliary-window lint passes for all 35 registered identifiers.
Cmux Source Artifacts ✅ Passed The 56 changed paths are source, tests, scripts, configs, localization, or project files; all are regular text files with existing parent directories, and no artifact paths, binaries, or scratch di...
Cmux No Test Or Debug Seam In Production Source ✅ Passed The PR adds no DEBUG/test-build guards or test/debug-named production members; the filesystem abstraction is used by the runtime loader, while test scaffolding remains under Tests/.
Cmux No Ambient Global State ✅ Passed No new file-scope functions or mutable variables were found; new behavior is on constructable CMUXCLI/loaders/resolvers, and added static members are constants. No singleton declarations were added.
Title check ✅ Passed The title clearly and concisely describes the primary change: syncing Claude task tools to workspace todos.
Description check ✅ Passed The description includes a complete summary, testing details, rationale, linked issue, and implementation scope; optional template sections are not included.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-8960-task-tools-todos

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.

@greptile-apps

greptile-apps Bot commented Jul 26, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds Claude task-store synchronization into Feed and owner-scoped workspace todos.

  • Installs asynchronous Claude task hooks and resolves session, configured-list, and team task stores.
  • Adds bounded task snapshot loading, durable task ownership and destination records, cross-process ordering, and cleanup handling.
  • Adds the workspace.todo.reconcile socket API with owner-scoped atomic replacement and persistence.
  • Extends focused CI and regression coverage for task synchronization and workspace checklist reconciliation.

Confidence Score: 4/5

The PR does not appear safe to merge until task synchronization prevents an accepted Feed update from diverging from a rejected workspace reconciliation.

The current delivery path acknowledges the new Feed snapshot before attempting atomic workspace reconciliation; when the combined checklist exceeds its cap or another reconciliation error occurs, the workspace preserves its previous rows and the hook provides no rollback for the already-committed Feed state.

Files Needing Attention: CLI/CMUXCLI+ClaudeTaskSync.swift

Important Files Changed

Filename Overview
CLI/CMUXCLI+ClaudeTaskSync.swift Implements the task synchronization pipeline, but Feed commits before workspace reconciliation and can therefore diverge from a rejected checklist update.
Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReconciliation.swift Adds atomic owner-scoped replacement that preserves unrelated rows and rejects collisions or combined checklists above the cap.
Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator+WorkspaceTodoSetOpen.swift Adds validated batched workspace todo reconciliation with per-workspace results.
Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift Loads bounded authoritative Claude task snapshots while filtering invalid and deleted task records.
CLI/ClaudeHookSessionStoreFile.swift Extends durable hook state with task bindings, destinations, retirement state, coalescing claims, and cross-process synchronization.
Resources/bin/cmux-claude-wrapper Installs and dispatches asynchronous Claude task synchronization hooks.
Sources/TerminalController+ControlWorkspaceTodoBatchMutation.swift Connects batched control-socket reconciliation to owner-scoped workspace checklist mutation.

Reviews (13): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread CLI/CMUXCLI+ClaudeTaskSync.swift Outdated
Comment thread CLI/CMUXCLI+ClaudeTaskSync.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLI/CMUXCLI`+ClaudeTaskSync.swift:
- Around line 74-91: Align the Feed telemetry payload with the workspace
checklist limit by applying the existing 50-item bound when building
feedSnapshot in the task-sync flow. Update the todos mapping used by
sendFeedTelemetry while preserving the existing claudeTaskFeedDictionary
transformation and checklist behavior.

In `@cmuxTests/ClaudeHookLiveDeliveryTargetTestSupport.swift`:
- Around line 151-177: Update the test support around mutationSeen and the
mock-server handler to track feed.push and workspace.todo.set deliveries
separately. Wait for both method-specific events before asserting completion,
ensuring the test cannot finish after only the Feed destination has been
delivered.
🪄 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: ee37fe9f-e011-43de-8a6a-05d49b3daf7d

📥 Commits

Reviewing files that changed from the base of the PR and between aac2351 and 445d86a.

📒 Files selected for processing (15)
  • .github/workflows/ci.yml
  • CLI/CMUXCLI+ClaudeTaskSync.swift
  • CLI/FeedEventClassifier.swift
  • CLI/cmux.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/Workstream/WorkstreamPayload.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/Workstream/WorkstreamStore.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/ClaudeTaskSnapshotLoaderTests.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/Workstream/WorkstreamStoreTests.swift
  • Resources/bin/cmux-claude-wrapper
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/ClaudeHookLiveDeliveryTargetTestSupport.swift
  • cmuxTests/ClaudeTaskSyncHookTests.swift
  • cmuxTests/FeedEventClassificationTests.swift
  • tests/test_claude_wrapper_hooks.py

Comment thread CLI/CMUXCLI+ClaudeTaskSync.swift Outdated
Comment thread cmuxTests/ClaudeHookLiveDeliveryTargetTestSupport.swift Outdated
@austinywang

Copy link
Copy Markdown
Contributor Author

Review disposition for Greptile’s summary-only >50 concern: consciously rejected for this PR. The 50-item ceiling is the existing product-wide WorkspaceChecklistItem.maxChecklistItems invariant used by manual, UI, and socket checklist mutations; raising it is a separate product/performance decision outside issue #8960 (whose reported plan has 13 tasks). This change does not silently truncate: Feed receives the complete authoritative snapshot, while workspace reconciliation fails atomically and preserves the prior checklist if the shared cap would be exceeded. Package and app-host regressions cover that fail-closed behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator`+WorkspaceTodoSetOpen.swift:
- Around line 121-126: Update the owner_id validation in the WorkspaceTodo
control command coordinator to obtain both caller-visible error messages from
the relevant control-context string structure instead of English literals. Add
the new strings to that context and resolve them at the app boundary with
String(localized:defaultValue:), while ensuring this package does not call
String(localized:) directly.

In
`@Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistReconciliationTests.swift`:
- Around line 6-57: Add a focused test alongside
reconcileReplacesOnlyTheMatchingOwner that directly calls
replaceChecklist(with:) on a checklist containing an existing owned item, then
asserts the replacement preserves that item’s ownerID. Avoid using
reconcileChecklist in this test so owner preservation is verified by
replaceChecklist itself.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a87ba8b8-c106-4410-bdeb-268351a9a28c

📥 Commits

Reviewing files that changed from the base of the PR and between 445d86a and d2cc1f7.

📒 Files selected for processing (27)
  • .github/workflows/ci.yml
  • CLI/CMUXCLI+ClaudeTaskSync.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskRecord.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskRootResolver.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoaderError.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/Workstream/WorkstreamPayload.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/ClaudeTaskSnapshotLoaderTests.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator+WorkspaceTodo.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator+WorkspaceTodoSetOpen.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoContext.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoSetResolution.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorWorkspaceTodoSetOpenTests.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorWorkspaceTodoTests.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlWorkspaceTodoContextTestStubs.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistItem.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReconciliation.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistReconciliationTests.swift
  • Sources/SessionPersistence+Todos.swift
  • Sources/TerminalController+ControlWorkspaceTodoBatchMutation.swift
  • Sources/TerminalController+ControlWorkspaceTodoContext.swift
  • Sources/Workspace+Todos.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/ClaudeHookLiveDeliveryTargetTestSupport.swift
  • cmuxTests/ClaudeTaskSyncHookTests.swift
  • cmuxTests/WorkspaceTodoSnapshotTests.swift

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift (1)

75-75: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject duplicate existing checklist IDs before building the dictionary.

Dictionary(uniqueKeysWithValues:) traps for duplicate keys. restoredChecklist preserves stored item IDs without uniqueness validation, so a malformed restored checklist can crash before returning the atomic rejection already covered for replacement IDs.

Add existing-ID uniqueness validation before this initializer and add a regression test for a persisted duplicate owned ID.

🤖 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/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift`
at line 75, Validate that the existing checklist items have unique IDs before
constructing existingById with Dictionary(uniqueKeysWithValues:). If duplicate
owned IDs are found, reject the replacement atomically using the existing
failure path rather than allowing the initializer to trap; add a regression test
covering a persisted checklist with duplicate owned IDs.
🤖 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/CMUXCLI`+ClaudeTaskSync.swift:
- Around line 202-204: Update claudeTaskChecklistOwnerID(sessionID:) to ensure
the generated “claude:” owner ID is at most 500 characters, enforcing the
493-character sessionID limit before checklist reconciliation. Preserve valid
identifiers and ensure overlong values are rejected or bounded before Feed
telemetry and workspace.todo.reconcile are invoked.

In
`@Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift`:
- Around line 124-132: Validate the filename-to-task-ID binding in the
snapshot-loading loop before appending a todo: require record.id to be a valid
path component and require the JSON filename stem to equal record.id. Reuse the
same identity-validation behavior as taskFile(in:matches:decoder:), then
continue for invalid or mismatched files while preserving the existing
canonicalState and nonEmptyTaskText checks.

In `@Resources/Localizable.xcstrings`:
- Around line 234342-234375: The new localization keys
socket.workspace.todo.reconcile.invalidOwnerIDLength and
socket.workspace.todo.reconcile.missingOwnerID currently include only en and ja;
add translated stringUnit entries for every other locale already present in
Resources/Localizable.xcstrings, preserving the existing messages and translated
state.

---

Outside diff comments:
In
`@Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift`:
- Line 75: Validate that the existing checklist items have unique IDs before
constructing existingById with Dictionary(uniqueKeysWithValues:). If duplicate
owned IDs are found, reject the replacement atomically using the existing
failure path rather than allowing the initializer to trap; add a regression test
covering a persisted checklist with duplicate owned IDs.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 501e949c-d968-4ad0-aad0-abb322356007

📥 Commits

Reviewing files that changed from the base of the PR and between 9f0c47f and f218f7f.

📒 Files selected for processing (37)
  • .github/workflows/ci.yml
  • CLI/CMUXCLI+ClaudeTaskSync.swift
  • CLI/cmux.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskIdentity.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskRecord.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskRootResolver.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshot.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoaderError.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/Workstream/WorkstreamPayload.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/Workstream/WorkstreamStore.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/ClaudeTaskSnapshotLoaderTests.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/Workstream/WorkstreamStoreTests.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator+WorkspaceTodo.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator+WorkspaceTodoSetOpen.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoContext.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoSetResolution.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoStrings.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorWorkspaceTodoSetOpenTests.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorWorkspaceTodoTests.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlWorkspaceTodoContextTestStubs.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistItem.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReconciliation.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Session/RestoredPanelTitleBoundaryTests.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistReconciliationTests.swift
  • Resources/Localizable.xcstrings
  • Resources/bin/cmux-claude-wrapper
  • Sources/SessionPersistence+Todos.swift
  • Sources/TerminalController+ControlWorkspaceTodoBatchMutation.swift
  • Sources/TerminalController+ControlWorkspaceTodoContext.swift
  • Sources/Workspace+Todos.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/ClaudeHookLiveDeliveryTargetTestSupport.swift
  • cmuxTests/ClaudeTaskSyncHookTests.swift
  • cmuxTests/WorkspaceTodoSnapshotTests.swift
  • tests/test_claude_wrapper_hooks.py

Comment thread CLI/CMUXCLI+ClaudeTaskSync.swift Outdated
Comment thread Resources/Localizable.xcstrings Outdated
Comment thread CLI/CMUXCLI+ClaudeTaskSync.swift Outdated
@austinywang

Copy link
Copy Markdown
Contributor Author

Review follow-up: 1e23136 also fixes CodeRabbit’s outside-diff duplicate-persisted-ID finding. On the test-only HEAD, WorkspaceChecklistReconciliationTests crashed with “Fatal error: Duplicate values for key”; replaceChecklist now rejects the corrupted persisted identity set atomically with duplicateId, and the focused reconciliation suite passes 7/7.

@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 `@Resources/Localizable.xcstrings`:
- Around line 234578-234588: Update the zh-Hans and zh-Hant stringUnit values
for the invalid owner_id message to use the natural wording “owner_id 缺失或无效” and
“owner_id 缺失或無效”, respectively, while leaving their translated states unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c680074d-d2d4-46ff-b81c-fd5d14b2c800

📥 Commits

Reviewing files that changed from the base of the PR and between f218f7f and df8c994.

📒 Files selected for processing (7)
  • CLI/CMUXCLI+ClaudeTaskSync.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/ClaudeTaskSnapshotLoaderTests.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistReconciliationTests.swift
  • Resources/Localizable.xcstrings
  • cmuxTests/ClaudeTaskSyncHookTests.swift

Comment thread Resources/Localizable.xcstrings

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

Stale Bugbot comment from a previous run.

Comment thread CLI/CMUXCLI+ClaudeTaskSync.swift Outdated

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

Stale Bugbot comment from a previous run.

Comment thread CLI/CMUXCLI+ClaudeTaskSync+TeamDelete.swift
Comment thread CLI/CMUXCLI+ClaudeTaskSync+AutomaticTeam.swift Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

Fix All in Cursor

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

Reviewed by Cursor Bugbot for commit d368660. Configure here.

Comment thread CLI/CMUXCLI+ClaudeTaskSync+PersonalList.swift Outdated
@austinywang

Copy link
Copy Markdown
Contributor Author

Review-thread audit re-checked at HEAD ec3764862f5bf2b21080b5be19dc65d627711a39 (September 8, 2026).

All 55 review threads have an explicit Austin reply; unresolved: 0; unanswered: 0. fix means the ask changed behavior or coverage; already-fixed means the current implementation already satisfied it; disagree means the ask was rejected after verifying the intended invariant.

comment ID author file:line ask disposition commit SHA
3653435866 greptile-apps CLI/CMUXCLI+ClaudeTaskSync.swift:99 Replacement deletes unrelated todos fix 877de62
3653435896 greptile-apps CLI/CMUXCLI+ClaudeTaskSync.swift:90 Task snapshot truncates at fifty fix 877de62
3653449265 coderabbitai CLI/CMUXCLI+ClaudeTaskSync.swift:91 Feed snapshot is unbounded while the workspace checklist is capped at 50. disagree 0b093d9
3653449267 coderabbitai cmuxTests/ClaudeHookLiveDeliveryTargetTestSupport.swift:177 Make completion signaling prove both destinations were delivered. already-fixed 0b093d9
3732596331 coderabbitai Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator+WorkspaceTodoSetOpen.swift:126 Localize the new socket error messages through the control context. fix fb4d3b9
3732596333 coderabbitai Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistReconciliationTests.swift:58 Add a direct replaceChecklist owner-preservation test. fix fb4d3b9
3732855469 coderabbitai CLI/CMUXCLI+ClaudeTaskSync.swift:204 Bound owner_id before sending checklist reconciliation. fix 1e23136
3732855474 coderabbitai Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift:132 Validate the filename-to-task-ID invariant. fix 1e23136
3732855483 coderabbitai Resources/Localizable.xcstrings:234375 Add translations for every supported locale. fix 1e23136
3732905319 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:117 Shared task list support incomplete High Severity fix 1e23136
3732905323 cursor Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift:132 Filename identity check missing Medium Severity fix 1e23136
3732905330 cursor Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift:97 Duplicate IDs crash replace Medium Severity fix 1e23136
3732976047 coderabbitai Resources/Localizable.xcstrings:264761 Use natural Chinese wording for invalid owner_id. already-fixed 2dfb599
3732977933 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:54 Teammate task sync blocked as stale High Severity already-fixed af280d5
3733176588 cursor cmuxTests/ClaudeTaskSyncHookTests.swift:476 Missing agent-id team binding High Severity already-fixed dcd65a8
3733176597 cursor cmuxTests/ClaudeTaskSyncHookTests.swift:524 Completed lists stay in workspace Medium Severity already-fixed dcd65a8
3735594255 coderabbitai CLI/cmux.swift:334 Avoid depending on an unavailable /usr/bin/lockf utility. disagree ce11690
3735594263 coderabbitai CLI/cmux.swift:623 Normalize taskListID before building lookup storage keys. already-fixed e36f831
3735594274 coderabbitai CLI/cmux.swift:828 Use EINVAL for an empty workspace list. already-fixed e36f831
3735594304 coderabbitai CLI/cmux.swift:2259 Do not throw after saveUnlocked succeeds. fix 2894c10
3735594312 coderabbitai CLI/cmux.swift:5989 Capture the authentication error before acknowledging. already-fixed ec37648
3735594315 coderabbitai CLI/CMUXCLI+ClaudeTaskSync.swift:587 Add includeFallbackDestinations to clearLegacyClaudeTaskChecklistOwnerIfNeeded. already-fixed f3a2448
3735594321 coderabbitai cmuxTests/ClaudeAutomaticTeamTaskSyncHookTests.swift:6 Consider marking this suite .serialized. already-fixed 2e3a7d0
3735594332 coderabbitai cmuxTests/ClaudeAutomaticTeamTaskSyncHookTests.swift:732 Return the hook process result from runHook. already-fixed dcd65a8
3735594337 coderabbitai Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTeamConfiguration.swift:10 Treat members as optional when decoding Claude team configs. already-fixed ec37648
3735594348 coderabbitai Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTeamTaskListBinding.swift:58 Enforce the binding invariants on the Codable decode path. already-fixed ec37648
3735594365 coderabbitai Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTeamTaskListResolution.swift:15 Drop the redundant memberwise initializer. already-fixed 2e3a7d0
3735594371 coderabbitai Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTeamTaskListResolver.swift:329 Fail closed when both the config lead session and the hook session are absent. already-fixed dcd65a8
3735594384 coderabbitai Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/DisappearingTaskDirectoryFileManager.swift:67 Document the call-count coupling to the loader. already-fixed ec37648
3742010714 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:231 TeamDelete leaves session task bindings High Severity already-fixed e36f831
3742081630 coderabbitai cmuxTests/ClaudeAutomaticTeamTaskSyncHookTests.swift:599 Resolve the jsonObject call in ClaudeAutomaticTeamTaskSyncHookTests.swift. already-fixed f3a2448
3742081635 coderabbitai Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshot.swift:12 Remove the redundant memberwise initializer. already-fixed f3a2448
3742081639 coderabbitai Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTeamTaskListBinding.swift:107 Fail closed when both sessionID and leaderSessionID are absent. already-fixed ec37648
3742081642 coderabbitai Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReconciliation.swift:33 Reject duplicate persisted IDs across the complete checklist. already-fixed ec37648
3742081648 coderabbitai Resources/Localizable.xcstrings:268978 Use an explicit English range. already-fixed 2dfb599
3742156140 cursor cmuxTests/ClaudeTaskSyncHookTests.swift:72 Personal move leaves stale todos High Severity already-fixed dcd65a8
3742156145 cursor Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistReconciliationTests.swift:125 Unrelated duplicate IDs accepted Medium Severity already-fixed ec37648
3742156150 cursor Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/ClaudeTeamTaskListResolverTests.swift:78 Empty session matches leaderless binding Medium Severity already-fixed ec37648
3742156152 cursor Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/ClaudeTaskSnapshotLoaderTests.swift:538 Text overflow tests contradict loader Medium Severity already-fixed dcd65a8
3742233272 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:573 Stale personal todos survive pane moves Medium Severity already-fixed 9df3b3f
3742233275 cursor Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/ClaudeTaskSnapshotLoader.swift:444 Text limits abort neighbor directory scans Medium Severity already-fixed 9df3b3f
3742297392 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:398 Empty team bindings never removed Medium Severity already-fixed e36f831
3742374617 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:525 Personal destinations leak after deletion Medium Severity already-fixed e36f831
3742374622 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:396 Cleanup feed failure blocks personal sync Medium Severity already-fixed aa88a56
3742410104 cursor cmuxTests/ClaudeTaskSyncHookTests.swift:984 Empty Feed rejection breaks team cleanup High Severity already-fixed dcd65a8
3742410106 cursor cmuxTests/ClaudeTaskSyncHookTests.swift:1229 Completed lists keep destination proofs Medium Severity already-fixed dcd65a8
3848401288 greptile-apps CLI/CMUXCLI+ClaudeTaskSync.swift:844 Over-cap snapshots split task views already-fixed 5d48e58
3959332786 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:966 Stale hooks wipe live Feed todos High Severity already-fixed e36f831
3959332796 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:1523 Failed team cleanup skips SessionEnd retry Medium Severity already-fixed e36f831
3959504329 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:341 TeamDelete Feed failure orphans todos High Severity already-fixed 391123f
3959504341 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:198 Configured list skips personal cleanup Medium Severity already-fixed ec37648
3960073030 cursor CLI/CMUXCLI+ClaudeTaskSync.swift:575 TeamDelete fallback skips cleanup retry Medium Severity fix e2f8db0
3961575656 cursor CLI/CMUXCLI+ClaudeTaskSync+TeamDelete.swift:366 Fallback TeamDelete skips retirement Medium Severity already-fixed d368660
3961575666 cursor CLI/CMUXCLI+ClaudeTaskSync+AutomaticTeam.swift:44 Personal todos cleared before delivery Medium Severity fix d368660
3962275110 cursor CLI/CMUXCLI+ClaudeTaskSync+PersonalList.swift:244 Personal bind keeps rejected team source Medium Severity fix 2f2519a

This branch was successfully deployed

2 active deployments
Preview – cmux166 — ec376486 Deployed Sep 9, 2026 by vercel[bot]
Preview – cmux41 — ec376486 Deployed Sep 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Workspace todos never populate from Claude Code: ingestion is keyed on TodoWrite, which Claude Code no longer emits (now TaskCreate/TaskUpdate)

2 participants