Skip to content

Add workspace-only focus history setting - #8654

Merged
lawrencecchen merged 15 commits into
mainfrom
feat-history-navigation-scope
Jul 22, 2026
Merged

lawrencecchen merged 15 commits into
mainfrom
feat-history-navigation-scope

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

Adds an App setting that switches focus-history navigation between panes/tabs/workspaces and workspaces only. The runtime reads the setting on every history action, so changing it applies immediately without clearing recorded history. Dock-focused history shortcuts fall through to workspace navigation in workspace-only mode.

Tests:

  • swift test in Packages/macOS/CmuxWorkspaces
  • swift test in Packages/macOS/CmuxSettings
  • swift test in Packages/macOS/CmuxSettingsUI
  • tagged cloud build histws
  • GUI preflight: setting search, live toggle, same-workspace skip, cross-workspace back/forward

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


Summary by cubic

Adds a setting to scope focus-history navigation. Default is workspaces only; changes apply instantly across the app and Dock, and Dock back/forward falls back to workspace navigation when pane/tab history is off.

  • New Features
    • Setting: “Include Panes and Tabs in Focus History” (app.focusHistoryIncludesPanesAndTabs, default off) in CmuxSettings/CmuxSettingsUI; searchable with curated synonyms and localized (EN/JA).
    • CmuxWorkspaces: FocusHistoryModel accepts a live navigationScope (FocusHistoryNavigationScope) read on each action. Workspaces-only mode skips same-workspace entries, collapses menu items to workspaces, uses the workspace’s remembered panel, and preserves forward workspace history after pane focus.
    • Runtime: TabManager, Workspace, and DockSplitStore derive scope from settings and bump focusHistoryRevision when it changes; restored/detached workspaces and the window Dock inherit the setting; Dock focus-history shortcuts fall back to workspace navigation in workspaces-only mode.
    • Tests: Coverage for defaults, settings-row anchor/search, menu collapse and remembered panel, scope-change invalidation, Dock fallback, and propagation to restored/detached/window Dock; legacy pane-history tests explicitly set pane/tab scope.
    • cmux.json/schema: added app.focusHistoryIncludesPanesAndTabs mapping, schema entry, and default template.

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

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added a Focus History Scope setting to control whether focus back/forward includes panes & tabs or only switches between workspaces (default: workspaces only).
    • Updated the settings UI and search synonyms, with localized English/Japanese title and subtitles.
  • Bug Fixes
    • Focus-history navigation and related Dock shortcuts now correctly follow the selected scope, updating back/forward availability accordingly.
  • Tests
    • Added/updated unit and UI tests to verify the new default, scope switching behavior, and settings-row anchoring/restoration.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds a configurable focus-history scope setting, exposes it in App settings, applies it to workspace and dock navigation, routes related shortcuts accordingly, and adds model, catalog, UI, and session coverage.

Changes

Focus history scope

Layer / File(s) Summary
Setting contract and settings UI
Packages/macOS/CmuxSettings/..., Packages/macOS/CmuxSettingsUI/..., Resources/Localizable.xcstrings
Adds the setting, exposes it in App settings and curated search, localizes it, and updates settings coverage tests.
Navigation scope model
Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Navigation/..., Packages/macOS/CmuxWorkspaces/Tests/.../FocusHistoryModelTests.swift
Adds navigation scopes and filters same-workspace entries during recording and back/forward traversal in workspace-only mode.
Settings wiring and shortcut routing
Sources/TabManager.swift, Sources/Workspace.swift, Sources/DockSplitStore.swift, Sources/DockSplitStore+ShortcutCommands.swift, Sources/AppDelegate+DockShortcutRouting.swift
Propagates the setting through workspace and dock construction, configures focus history, and rejects dock focus-history shortcuts when pane/tab history is disabled.
Integration navigation validation
cmuxTests/FocusHistoryScopeTests.swift, cmux.xcodeproj/project.pbxproj
Verifies scope behavior, setting changes, and restored workspace propagation through the application test target.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SettingsUI
  participant TabManager
  participant Workspace
  participant DockSplitStore
  participant FocusHistoryModel
  User->>SettingsUI: disable pane and tab focus history
  SettingsUI->>TabManager: update setting
  TabManager->>FocusHistoryModel: use workspacesOnly scope
  TabManager->>Workspace: provide settings source
  Workspace->>DockSplitStore: create with settings
  DockSplitStore->>FocusHistoryModel: use configured scope
  User->>DockSplitStore: invoke focus-history shortcut
  DockSplitStore->>FocusHistoryModel: navigate back or forward
  FocusHistoryModel-->>DockSplitStore: skip same-workspace entries
Loading

Suggested reviewers: austinywang


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Full Internationalization ❌ Error New setting strings exist only in en/ja; the touched catalog supports 20 locales, so translations are missing for 18 locales. Add translated xcstrings entries for all existing catalog locales (ar, bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, zh-Hant) or remove unsupported locales.
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 New settings/history paths stay on @MainActor; the UserDefaults observer uses .main + MainActor.assumeIsolated, and no new background access or mutable Sendable sharing appears.
Cmux Swift Blocking Runtime ✅ Passed PR adds no blocking waits/sleeps/syncs/locks; changed runtime code uses settings closures and notifications, and the new test file has no banned primitives.
Cmux Browser Automation Off-Main ✅ Passed Only focus-history/Dock shortcut plumbing changed; browser automation policy/router/tests already keep waiting browser.* commands on the socket worker.
Cmux Expensive Synchronous Load ✅ Passed Touched code only adds settings-backed focus-history scope; no new RestorableAgentSessionIndex.load() call was added to a main/interactive path, and the existing load stays in the cached loader/f...
Cmux Cache Substitution Correctness ✅ Passed The setting is read live via a closure on each history action, with init seeding and didChange-driven invalidation; no cached value replaces authoritative reads in history paths.
Cmux No Hacky Sleeps ✅ Passed Cumulative diff adds only Swift code plus pbxproj/xcstrings metadata; no TS/JS/shell/runtime script sleeps, delays, polling, or timer hacks were introduced.
Cmux Algorithmic Complexity ✅ Passed No new unbounded scans or hot-path rescans were introduced; focus-history work stays capped at 50 items and the new dock/settings checks are O(1).
Cmux Swift Concurrency ✅ Passed Diff is a one-line TabManager type-annotation change; no new DispatchQueue, Combine, completion-handler, or fire-and-forget Task patterns were introduced.
Cmux Swift @Concurrent ✅ Passed No changed Swift code introduces invalid @concurrent/nonisolated async usage; the new focus-history wiring is synchronous and @MainActor-bound.
Cmux Swift Package Boundaries ✅ Passed PASS: the history algorithm and scope enum live in CmuxWorkspaces; app-target edits are settings/UI/shortcut wiring and host composition only.
Cmux Swiftpm Lockfiles ✅ Passed PASS: The only Xcode project diff adds a test file; no Package.swift, .gitignore, Package.resolved, or package-reference changes were present.
Cmux Swift Logging ✅ Passed Touched focus-history/settings hunks add no print/debugPrint/NSLog/Logger; only pre-existing debug-only NSLog and an unchanged file-scoped Logger remain.
Cmux User-Facing Error Privacy ✅ Passed The only production diff is a type qualification in TabManager.swift; it adds no user-facing errors, alerts, or recovery copy.
Cmux Swiftui State Layout ✅ Passed PASS: The new settings row uses @State with @Observable DefaultsValueModel; no new ObservableObject/@published, GeometryReader, lazy-row store refs, or render-time writes were introduced.
Cmux Architecture Rethink ✅ Passed PASS: The diff adds a settings-backed scope bridge and derived revision bump only; no sleeps, polling, locks, or split ownership of focus history were introduced.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR only changes settings, focus-history, and tests; no new or modified standalone NSWindow/NSPanel/WindowGroup/NSWindowController code or cmuxAuxiliaryWindowIdentifiers registrations were intro...
Cmux Source Artifacts ✅ Passed All changed paths are intentional source, test, localization, or project files; none match artifact/temp/build/cache patterns.
Cmux No Test Or Debug Seam In Production Source ✅ Passed New focus-history code is runtime plumbing; no added #if DEBUG test seam or debug/ForTesting-style member appeared in modified production files, and existing test helpers predate it.
Cmux No Ambient Global State ✅ Passed New focus-history state is instance-scoped and injected through TabManager/Workspace/DockSplitStore; no new file-scope mutable globals or singleton APIs were added.
Title check ✅ Passed The title is concise and accurately captures the main change: adding a workspace-only focus history setting.
Description check ✅ Passed The description covers what changed, why, testing performed, and includes the required review-trigger and checklist content.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-history-navigation-scope

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 22, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a setting that limits focus-history navigation to workspaces. The main changes are:

  • Adds the setting to the app UI, search, JSON configuration, schema, and localized strings.
  • Applies the selected scope to workspace and Dock focus-history navigation.
  • Reads the setting on each history action so changes take effect immediately.
  • Adds tests for defaults, live toggling, navigation behavior, and settings propagation.

Confidence Score: 5/5

This looks safe to merge.

  • The Japanese setting text is valid and complete at the current head.
  • The setting key and default agree across the catalog, UI, JSON mapping, schema, and template.
  • Settings propagation covers regular, restored, detached, workspace Dock, and window Dock paths.
  • No blocking issue related to the earlier review findings remains in the updated code.

Important Files Changed

Filename Overview
Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/Navigation/FocusHistoryModel.swift Adds scope-aware recording, availability checks, menu snapshots, and back/forward navigation.
Sources/TabManager.swift Injects the live setting into focus history and propagates it to restored and detached workspaces.
Sources/DockSplitStore.swift Applies the injected focus-history setting to Dock navigation.
Packages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/AppSection.swift Adds the localized focus-history scope toggle to App settings.
Resources/Localizable.xcstrings Adds complete English and Japanese text for the setting and both scope descriptions.
Sources/CmuxSettingsJSONPathSupport.swift Registers the setting's JSON mapping and supported configuration path.

Reviews (14): Last reviewed commit: "Import Foundation in history scope tests" | Re-trigger Greptile

Comment thread Resources/Localizable.xcstrings
Comment thread cmuxTests/TabManagerSessionSnapshotTests.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: 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 `@cmuxTests/TabManagerSessionSnapshotTests.swift`:
- Around line 138-151: Update
testRestoredWorkspaceDockUsesInjectedFocusHistorySetting to inject false for
focusHistoryIncludesPanesAndTabs instead of true, and assert the restored
workspace dock reports false. Keep the existing injected
UserDefaultsSettingsClient and snapshot/restore flow unchanged so the test
distinguishes injected settings from the default.
🪄 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: d8fe91ea-5715-460c-b7bd-7f0f98691562

📥 Commits

Reviewing files that changed from the base of the PR and between 498d663 and 905d20e.

📒 Files selected for processing (3)
  • Sources/TabManager+DetachedWorkspace.swift
  • Sources/TabManager.swift
  • cmuxTests/TabManagerSessionSnapshotTests.swift

Comment thread cmuxTests/TabManagerSessionSnapshotTests.swift Outdated
@cursor

cursor Bot commented Jul 22, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

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

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

@cursor

cursor Bot commented Jul 22, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

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

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

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