Skip to content

cmux NEXT: vertical tabs per workspace or for all workspaces - #32127

Merged
teamleaderleo merged 15 commits into
feat-cmux-nextfrom
vtabs-settings
Nov 2, 2026
Merged

teamleaderleo merged 15 commits into
feat-cmux-nextfrom
vtabs-settings

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds vertical tabs to cmux NEXT. Each workspace can turn vertical tabs on or off from its tab menu, and tabs.verticalTabs remains an off-by-default setting that can make vertical tabs the default for all workspaces. The strip and list share one menu, and the sidebar does not list the same workspace tabs twice.

Leo's ask (2026-10-21): “I DIDNT FING MEAN AS A GLOBAL DEFAULT I MEANT JUST HAVING THE VERTICAL TAB FING OPTION AND THEN BEING ABLE TO SET IT AS A DEFAULT FOR ALL WORKSPACERS”.

Verification

  • Fleet cmux-ci compile-check passed for exact head a32b50df134304a02b38f21cdc663795cc98d3b3 (CmuxNext and cmux-tui).
  • Exact-head settings export regeneration passed its tests; no generated diff remained. The fleet artifact upload returned cache_http_400 after the script exited 0.
  • Added focused settings, menu, sidebar, layout and view tests.

Changelog

  • Added: vertical tabs per workspace or for all workspaces, with collapse and hover expansion.

Leo-ask: ask-c1e514d084

Agent session: agent session

@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review ba62977: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr32127 -f ref=vtabs-settings -f platform=macos -f backend_mode=local

Not verified: macOS jobs did not run: compile and app tests were skipped on ba62977433; ci-status is green without them.

CI passes on ba62977433 (run 41458283858 attempt 1).
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped (the macos job needs both to succeed). Re-run CI once they pass, before merging.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

web and size checks: green

Default changes

This pull request changes 42 defaults at ba62977433f1 (what everyone gets without configuring anything):

  • setting.agentPane.display.inspector.placement: "overlay" -> (none)
  • setting.agentPane.display.sessionInfo.placement: (none) -> "overlay"
  • setting.tabs.verticalTabs: (none) -> false (a new setting, off by default: passes on its own)
  • setting.tabs.verticalTabsExpandOnHover: (none) -> true
  • tunable-source.CmuxNextActions/ActionCatalog.swift:groups: "113dd35bf041b63519f36d7a0c7410356c30d069aaaea237f849424c367e46cd" -> "4b76e16808a818817996540c655a0eb6348f32a3c06ac9066cc397a69d7b2caf"
  • tunable-source.CmuxNextActions/ActionSurfaceCatalog+Menus.swift:layoutPlacements: "8b64c25d164605360d891a4f9a0f73037775e0c507ce178e0c33f90ddd53ebb2" -> "8f3cbbb63a2b91819e86fb7402c1ea94335205e68b035ba885ae9eef003dfd85"
  • tunable-source.CmuxNextActions/ActionSurfaceCatalog+MenusContent.swift:contentPlacements: "3b0d88b7d10a596aeda013c348a50cb863f2373ecf706b759db2b033b7160adf" -> "a15b8477781fba460dddc7424ada8d02e39c9b550830c2663cde5707761b6a84"
  • tunable-source.CmuxNextActions/Catalog/VerticalTabsActionCatalog.swift:moveAllTabsToNewWorkspaceLabel: (none) -> "e6c455ad945168c6a21af9baf6798f7861b4003d460972f04d7115316eb3c18f"
  • tunable-source.CmuxNextActions/Catalog/VerticalTabsActionCatalog.swift:reopenClosedTabLabel: (none) -> "dd67d60025bc85f5ce87c112f9b7a704383f882c811919c988ea92bc9106b1f9"
  • tunable-source.CmuxNextActions/Catalog/VerticalTabsActionCatalog.swift:t: (none) -> "27cd1c0558ab9648bbbbf4e9a7ad39daaec1cac7c80881783d9eded50ad3e7d8"
  • tunable-source.CmuxNextApp/AppActions.swift:bind: "61229607c4bb8a83a7cc5a07e48e964a7252b012dbbbd32e4ae1384acc872d76" -> "d0500555d840444ecd1e9eb484921a12e17d4bbda1a129653064ee0dd9e8effc"
  • tunable-source.CmuxNextApp/Control/DebugPaneChrome.swift:report: "b563ac6c2a62ba512eb221078887386de8accb6c00446e2155dd822154f5af78" -> "224f001dc9959dd924186847995dee09f5f8519d0a31c43a593c7159404ab055"
  • tunable-source.CmuxNextApp/Handlers/PaneTabBarHandlers.swift:bind: "afc3e2ba25754e7cf1741d430c18aab6178471c177eb33c42771417a2cd22ea7" -> "94261299e75ad077d017b25243aa3457511e2bd3ab421d539d408058b2cde5f6"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:allWorkspaces: (none) -> "1c1bcf02eada9089918bc409f3108aaa6958a40668b11c6433fbd8174b09a1bd"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:bind: (none) -> "718d6c34d7c89e68574d34f88a25137528580efaf0b9aeaac8a9d67771c63739"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:collapse: (none) -> "f3d6b133cec73fdf7685beca786cc39cea3f698892143e22f461c85d658d64da"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:expand: (none) -> "2a19aa916ac0bf25a949b2fb78f89668e849d9bd89e52b20efc82cd793d42bfa"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:expandOnHover: (none) -> "466704f3dcc22ae03e6fb76e95406db350e5d21e6b427a4303e2d60a21d33faa"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:make: (none) -> "9ef5d5bc25c3666cf25213b1bec8fb204af1098e05ec2f0e735b907a34c3353e"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:takesVerticalTabs: (none) -> "930c94d8101ce06d31636658ca032462298cec53cf74639407fb3f309ea30e7d"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:toggle: (none) -> "bcd3f2ab65632a0c9c945ad3fc4bc9ce1f52e01f5c584484436f47d4985a28db"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:turnOff: (none) -> "a9512b67b29e8a834f2be50accf9a2f6beee8da84c6f1f9b03c3d7c301db980c"
  • tunable-source.CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift:workspaceID: (none) -> "a1e9d2dcfa2b6a59997aaf4b743f8ee27e0acac9ac4a43f5d51a2e44d9f12a58"
  • tunable-source.CmuxNextSettings/CmuxConfigSnapshot.swift:parse: "d1ee289af2553fdd99aedad540a615ab3ea745334082a2b96fd840189e6876f0" -> "3f9fa63a6916222b8b6b870d1980fb326c704b4e1ad031f48138f6464be597db"
  • tunable-source.CmuxNextSettings/Schema/SettingsSchema+Tabs.swift:verticalTabs: (none) -> "2a80c8e705b3357246953df0f778389e832f2cb3702b2edb1b9645e032d0785f"
  • tunable-source.CmuxNextSettings/Schema/SettingsSchema.swift:general: "e0d86ac73defb44fad6367ae7fad91e23a4a2bf1e0660458ac1a9554ac4e4b4e" -> "35c98f915591ded6fea555b45270c14b0741b228753ebfd6720a058734cea68c"
  • tunable-source.CmuxNextSettings/VerticalTabsSetting.swift:configPath: (none) -> "5ffbbe35451e43db4ac637fd868bd24fce5a16a52ef9167ebf3e160ba37a0fab"
  • tunable-source.CmuxNextSettings/VerticalTabsSetting.swift:expandOnHoverFallback: (none) -> "cff9479f81e03e425ed2de92a3a9c667c037f955ab1e938c0faaa93a44bd93b9"
  • tunable-source.CmuxNextSettings/VerticalTabsSetting.swift:expandOnHoverPath: (none) -> "e6a19c7fef3c98b63275b2c40a9b19ec76fe352354a7f95ea762898c1a19b4be"
  • tunable-source.CmuxNextSettings/VerticalTabsSetting.swift:fallback: (none) -> "38dbe72247055f2e74d5d6dcda69a54e48f37e63b0359d223f25deeb3f6002a0"
  • tunable-source.CmuxNextSettings/VerticalTabsSetting.swift:parse: (none) -> "4f50baa60e5a18b25f879f68709a911bf62f94ec854fe5201976dd0b23f9d9d9"
  • tunable-source.CmuxNextSettings/VerticalTabsSetting.swift:parseExpandOnHover: (none) -> "305c9f3e46a99133a5f93ff9157ca6a6420417ea7be4c0cb91678097b8fb88a9"
  • tunable-source.CmuxNextSettings/VerticalTabsSetting.swift:parseToggle: (none) -> "c2568fb12fc494c2919416e553ff34604eafc41baac6c8adca700fda31d85f1a"
  • tunable-source.CmuxNextTabs/TabTunables.swift:all: "981c902ef9120f2e3e0d60dc9d8ba4f19939fdf096a10d78b78099428c73bcf2" -> "386baa3d7f437201bb7392c907c12ce9753a44841d95eccf5deef0a36426b9fe"
  • tunable-source.CmuxNextTabs/Vertical/VerticalTabTunables.swift:all: (none) -> "17d85e084f78c6565e6599e7cd6c5ef541984cf6e1ce00dc56c08ef03372b19a"
  • tunable-source.CmuxNextTabs/Vertical/VerticalTabTunables.swift:collapsedWidth: (none) -> "2fa9dcf965aa56594a10dbf47ec2249c5608f1ec7b44ed3d026b51e5cf055fed"
  • tunable-source.CmuxNextTabs/Vertical/VerticalTabTunables.swift:expandedWidth: (none) -> "da775ff5c40e9edc288a32efa7616496baf196ed09245f572cc09de05eae3c3f"
  • tunable-source.CmuxNextTabs/Vertical/VerticalTabTunables.swift:groupLineWidth: (none) -> "a7ef0c46e04ba81d0269a910cb4492a472b371d81da7c08c4bb61c4c88b85f34"
  • tunable-source.CmuxNextTabs/Vertical/VerticalTabTunables.swift:hoverExpandDelay: (none) -> "aa40e93ad94cc02b394577e1377cc3445514511070c2e5cd3c3b7e7e8c2b7540"
  • tunable-source.CmuxNextTabs/Vertical/VerticalTabTunables.swift:points: (none) -> "3a6c96aae622a98c13fdfb1f0f5d0d2fabd0364fdc8e055a54ffdc352a6a483c"
  • tunable-source.CmuxNextTabs/Vertical/VerticalTabTunables.swift:rowSpacing: (none) -> "67b08066a1a829e6f454567942c563cf5f00221c155f436e7f01af9ac748b5ef"
  • tunable.tabs.vertical.hoverExpandDelay: (none) -> 0.3

Signed off on this commit by review (Claude Opus 5.5 medium).

Merge receipt: merged as a9c5b0d7f92f with these defaults changed, signed off by review (Claude Opus 5.5 medium).

Regenerate the snapshot with python3 scripts/ci/defaults_guard.py snapshot.

Shipped in:

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, sweep, via the review router; full diff from merge base 7ea60b1 to this head): BLOCK at 4eb7add

No P1/P2 findings.

Leo asked: “I DIDNT FUCKING MEAN AS A GLOBAL DEFAULT I MEANT JUST HAVING THE VERTICAL TAB FUCKING OPTION AND THEN BEING ABLE TO SET IT AS A DEFAULT FOR ALL WORKSPACERS”. Vertical tabs are available as an option, per-workspace choices persist, and the all-workspaces default remains off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-2fba32c80c8682a93d18
@cursor

cursor Bot commented Nov 2, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo teamleaderleo changed the title cmux NEXT: vertical tabs setting and per-workspace choice cmux NEXT: vertical tabs per workspace or for all workspaces Nov 2, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, next-review): BLOCK at 8c7f7c6

BLOCK at 8c7f7c6
Visual verdict: no images; Leo tries the build

  1. [P1] [blocking] SidebarLayout.swift:177: This head cannot compile: SidebarTabDisclosure and SidebarWorkspaceTabsToggle have no definitions, and SidebarSectionsPreferences.showWorkspaceTabs does not exist. The new sidebar tests also reference absent SidebarRowKey.tab and tabDisclosure. Remove the stale integration or supply its missing dependencies.

  2. [P1] [blocking] Localizable.xcstrings:73893: Restore settings.choice.diffSplit. Renaming it to settings.computerUse.enabled duplicates the existing key at line 84451 and removes the diff-layout translations. The repository’s duplicate-key checker rejects this catalog.

  3. [P1] [blocking] PaneController+Intents.swift:430: Preserve daemon.machineID through both menus built by TabStripMenu.make. The previous menu supplied it; the replacement drops it. When connected machines share pane IDs after a fork, unscoped lookup returns nil, breaking existing actions such as Split Right and Hide Tab Bar.

  4. [P2] [follow-up] VerticalTabsHandlers.swift:101: Build the More submenu from registry.contextMenuEntries, as before. Reading directly from the catalog ignores saved pane/new-tab menu customizations, restoring hidden entries and discarding user arrangements.

  5. [P2] [follow-up] vertical-tabs.json:12: Capture the expanded, collapsed, and hover-expanded native UI and its menu. No after images were available to verify rendering.

@blacksmith-sh

blacksmith-sh Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Found 8 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmprgncl845/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpz0vmvlmw/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
the real tree is clean/the real tree is clean View Logs
the real tree is clean/the real tree is clean View Logs

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

@cursor

cursor Bot commented Nov 2, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (Claude Opus 5.5 medium): SHIP at ba62977

I read the full diff from merge-base 5f937c4 to this exact head, plus the PaneController apply/observe, PaneTabBarHandlers, and fullscreen paths. The feature meets the ask: vertical tabs are a per-workspace option, and tabs.verticalTabs remains off by default. No blocking findings.

Follow-ups:

  1. Route page fullscreen transitions through showStrip(hidden:vertical:) so the vertical list hides and restores with the page.
  2. Remove the redundant hidesStrip assignment before showStrip in PaneController.apply.
  3. Convert the four new synchronous vertical-tabs handlers to bindEffect for the action-wait guardrail.
  4. Reconcile menu/palette clearing workspace choices with Settings, CLI, and MCP changes.
  5. Consider refusing vertical tabs when Hide Tab Bar is active, and document the iOS parity omission.

The exporter test red is base-owned: CloudApprovalAnsweredElsewhereTests.swift cannot find CloudAppOpFailure, and this PR changes no Cloud files. The fleet compile-check for this exact head passed CmuxNext and cmux-tui.

@lawrencecchen

Copy link
Copy Markdown
Contributor

The tip arch-ratchet red from this PR (stateful_singletons +1, assume_isolated_outside_adapters +2, observer_sites +1, app_lines +273 over its parent) is fixed forward in #32414: the vertical tabs store is built once in AppServices and injected, the list uses MenuTracking, and the logic moves to CmuxNextSettings, CmuxNextActions and CmuxNextTabs with the same behavior.

lawrencecchen added a commit that referenced this pull request Nov 2, 2026
…ted; its logic moves out of the App (#32127 arch rows) (#32414)

* base red: vertical tabs' store is built once in AppServices and injected; its logic moves out of the App (#32127 arch rows)

Fixes the feat tip arch-ratchet red from #32127 (a9c5b0d, STATUS 6861). Over its parent, #32127 raised four rows:
stateful_singletons +1, assume_isolated_outside_adapters +2, observer_sites +1 and app_lines +273. The tip verdict
named only the first one.

- stateful_singletons: `WorkspaceVerticalTabs.shared` is gone. AppServices constructs one store
  (`workspaceVerticalTabs`, next to `paneTabBars`) and passes it to the actions and to each pane's snapshot.
- assume_isolated_outside_adapters, observer_sites: the vertical list follows the end of its menu through
  CmuxNextCompat's MenuTracking, as the strip's TabMenuTracking does. It has no deinit, as TabStripView has none:
  leaving the window cancels its observation tasks, and DemandTimer and MenuTracking clean up when they are released.
- app_lines -273: the store, PaneVerticalTabs and the actions (VerticalTabsActions with a VerticalTabsHost that
  AppActionContext implements) move to CmuxNextSettings, with their two strings. The tab bar's empty-area menu becomes
  ActionRegistry.makeTabStripMenu in CmuxNextActions. The list's show and layout move to VerticalTabListView in
  CmuxNextTabs. The sibling per-pane stores PaneTabBarChoices and PaneFullWidthTabs move to CmuxNextSettings too.
  Behavior stays the same. apply() no longer sets hidesStrip before showStrip sets it to the same value.

arch-ratchet --base 3b6996e --head a9c5b0d: refused (the four rows above).
arch-ratchet --base c9835aa --head this commit: no rise; stateful_singletons -1, assume_isolated_outside_adapters -2,
observer_sites -1, app_lines -273.

* base red vtabs: the moved vertical tabs and tab bar stores and actions stay on the main actor in CmuxNextSettings (nonisolated by default)

* base red vtabs: the two setting rows bind typed effects in CmuxNextSettings (the App's throwing run: bind is App-only); a managed setting refuses as before
cmux-bot Bot pushed a commit that referenced this pull request Nov 2, 2026
…d from #32127) (#32439)

WindowCleanupCoverageTests fails at the tip: #32127 added VerticalTabListViewTests, which
makes an NSWindow per test without .closesItsWindows and only ordered it out. Each test now
closes its window in its teardown (closeAfterTest), and the suite takes the trait.
lawrencecchen added a commit that referenced this pull request Nov 2, 2026
…tension (#32456)

* cmux-next tests: VerticalTabListViewTests closes its windows (base red from #32127)

WindowCleanupCoverageTests fails at the tip: #32127 added VerticalTabListViewTests, which
makes an NSWindow per test without .closesItsWindows and only ordered it out. Each test now
closes its window in its teardown (closeAfterTest), and the suite takes the trait.

* test(next): the window cleanup scan must see tests in an extension of a type without .closesItsWindows (fails: the scan skips extensions)

* test(next): the window cleanup scan counts a top-level extension's tests as its type's suite

WindowCleanupCoverageTests read only struct/class/enum/actor declarations, so tests in a
top-level extension were invisible: a suite whose tests live in `extension Parent { ... }`
could open windows while Parent lacks .closesItsWindows, and the scan said nothing. The scan
now reads top-level extensions too, collects the types declared with the trait across every
test file, and reports an extension holding tests whose type is not one of them.
lawrencecchen added a commit that referenced this pull request Nov 3, 2026
… (ActionSurfaceParityTests) (#33092)

everyTargetKindMenuShowsItsActions failed at ActionSurfaceParityTests.swift:79
with gaps newTab.default (tab) and reopenClosedBrowserPanel (tab). a9c5b0d
(#32127, vertical tabs) added the tab bar's empty-area menu
(ActionMenuContext.tabStrip, whose target is the pane) and placed both there,
as Chrome's and Edge's tab strip menus do. A placement replaces an action's
menu exemption, so both lost theirs (newTab.default's duplicateOfDefault was
removed; reopenClosedBrowserPanel's noObject no longer applies), and the
parity rule found a tab action placed only in a pane menu.

The rows work: the app passes the pane, and newTab.default's handler takes a
pane target as its place (TabLifecycle.newTabOfPaneKind, namesPane);
Reopen Closed Tab reopens the key window's newest closed group whatever the
target. What the rule could not say is that the tab bar's rows act on what
its pane holds. ActionMenuContext.contentKinds now says it, for the tab bar
only ([.tab]); every other menu keeps the rule as it was (a pane's own menu
still does not count for a tab action).

Culprit: a9c5b0d (#32127).
Red: fleet job 2bf90b6c18ca136f3fb6c15d at feat 11dfe91.
@lawrencecchen

Copy link
Copy Markdown
Contributor

Swift-logic note (REWRITE R-SWIFT-MIRRORS): this PR added VerticalTabListLayout to CmuxNextTabs (+218 counted lines): which rows the vertical list shows (pinned grid, groups, separator, new tab) and their geometry. The rows will come from the Rust client core as one tab_strip row window for the strip and the list (wave W3.1, target 11-08), and the geometry joins the tab strip layout in cmux-motion (rust-migration B10). The list view's drawing and pointer code is platform and is classed so in #33986.

Why this matters: the tip's swift_logic_lines report (scripts/cmux-next/swift-logic-lines.py) has been red since 2026-11-02, and this PR is one of the rises. The project rule is that Rust owns state, lists and rules, and Swift is the platform shell (plans/cmux-next/layer-ownership.md; the cmux-next-feature skill: "Move as much as possible into Rust"). For new code of this kind, please put the rule in Rust (a crate the app links through cmux-app-ffi, or the daemon) and keep only the platform call in Swift. If a part truly must stay in Swift, add its row to plans/cmux-next/swift-logic-classes.tsv in the same PR, with the reason.

Nothing to change in this merged PR. REWRITE R-SWIFT-MIRRORS tracks the move (design: https://cmux-orchestrator-1.tail137216.ts.net/resize-videos/rewrites/R-SWIFT-MIRRORS/DESIGN.md, section 11).

lawrencecchen added a commit that referenced this pull request Nov 3, 2026
…ic red since 25c69ee (#33986)

* swift-logic-classes: classify the false counts of the tip's swift-logic red since 25c69ee

The tip watcher's swift_logic_lines row has been red since 2026-11-02
05:38Z (last green 25c69ee: 415218). Part of the rise is not new
Swift logic: declarations whose reviewed row did not follow a module
move, and view, strings, tunables and debug code that the default rule
counts in full because no row lists it. This commit corrects the table
only (no code change). Each row carries its reason.

- 24 rows follow their declaration's module move (class, shares and
  reason kept): DesktopNotifier and NotificationPermission* to
  CmuxNextNotifications (#32438), LinkHintController to CmuxNextBrowser
  (#32537), FirstFrameGate, LinkDragItem, LinkDropPlan, StaticURL,
  PageInstallCounter, AgentDialogLine, NewTabLayoutChoice,
  RunningPrograms, AgentChatMute, CloudAppOp*, PaneFullWidthTabs,
  PaneTabBarChoices, WindowRegistryStore. LOGIC rows stay LOGIC.
- 3 stale rows follow a move that also changed the kind (enum to
  struct): WhatsNewTunables, NewTabTunables, NotificationPermissionStrings;
  the stale CloudMoveStrings enum row is replaced by its struct.
- 48 new PLATFORM rows: the vertical tab list's AppKit drawing, pointer,
  accessibility and pane extensions (#32127; its row layout math,
  VerticalTabListLayout, stays counted), Core Animation avatar looks
  (#33395), view hosts (BrowserPageBars, TerminalStatusLabel,
  SidebarContainerView+PaneReach, AgentPaneView+MoveCover), the person
  click check of consent prompts, the glyph bitmap cache, the thin Swift
  side of the Rust Cloud start rules (CloudStartCore), the at-cap dialog
  spec, localized strings, Debug Settings tunables, and DEBUG, bench or
  DEV playground and fixture code.

Not changed: every real rise stays counted (for example
NativeDeviceEnrollment, NativeCloudLinkChild, GitHubConnections,
VerticalTabListLayout, DisplayBackdropBinding, CreationInputBuffer);
REWRITE R-SWIFT-MIRRORS names the wave that removes each. The green
reference 415218 is not changed.

swift_logic_lines at 2b3d7cd (python3 -I scripts/cmux-next/
swift-logic-lines.py --rev 2b3d7cd --json, then with --table of
this commit): 431786 -> 427957 (-3829). mirror_lines 71688 unchanged.
table_rows_missing 36 -> 8 (stale rows of deleted declarations);
table_rows_invalid 0. scripts/cmux-next/tests/test_swift_logic_lines.py:
16 tests OK.

* swift-logic-classes: the review's three rows count their rules; reasons say what the code is

Review of #33986 (FIX at cb155fb, comment 6610083921): three rows
put a rule under PLATFORM. Each now counts it:

- RefusalStrings+Spaces: MIXED 0/46. Its spaceDelete (lines 14-19) is a
  Swift copy of the daemon's own rule (cmux-tui-core
  state/room_delete.rs:148 and personal_mutations.rs:241: the default
  room cannot be deleted), so its share is MIRROR and it counts in
  mirror_lines; the localized strings stay platform.
- TerminalStatusLabel: MIXED 65/0. Lines 17-23, 46-47, 49-76 and 88-131
  (81 of 125) are the reveal-wait state machine.
- LinkHintController: MIXED 35/0. #32537 moved and rewrote it; who gets
  each key while the page answers (hold, release, replay marks, key
  kinds, the 500 ms answer bound, outcome handling: about 87 of 251
  lines) is logic for REWRITE R-INPUT.

Text: the reasons of the strings and tunables rows say what the code is
and cite the table's own precedent rows, not a "table rule" no document
has; the AgentPaneView #1 row of AgentPaneView+MoveCover describes the
Chromium move it holds; LinkHintStrings moved to its own file, not to
another module; CloudStartCore's reason names its one hand-copied
fallback line. Three stale rows follow their moved code:
PersonalGroupLifecycle (LOGIC, now a struct in CmuxNextAppCore), the
NSResponder extension (PLATFORM, now in CmuxNextFocusUI), and
DiffTabReuse (LOGIC, now enum DiffTabChange and an extension of
DiffOpenSource in CmuxNextDiff; both rows LOGIC).

swift_logic_lines at 2b3d7cd with this table: 428126 (base table
431786; the first version of this PR 427957); mirror_lines 71694.
At feat f07e8d9: 433351 -> 429651. table_rows_missing 5,
invalid 0; scripts/cmux-next/tests/test_swift_logic_lines.py: OK.

* swift-logic-classes: LinkHintController counts the key routing its reason names; textInputHasKeyboard is listed

Re-review of #33986 (FIX at 791c494, comment 6611048817):

- LinkHintController: MIXED 35/0 -> 57/0. The reason already named
  hold, release, replay marks, key kinds, the answer bound and outcome
  handling as logic; those are lines 22-24, 28-31, 34-35, 45-46,
  52-77, 79-85, 98-105, 107-130, 132-140, 142-149, 180-200, 202-210
  and 217-237: 144 of 251 lines. The reason now lists them.
- extension NSWindow in CmuxNextFocusUI/TypedTextInput.swift (#31865):
  new LOGIC row. textInputHasKeyboard is the rule which input has the
  person's keyboard; the view-shaped default (an NSWindow extension)
  counted its 13 lines as 0.
- Reasons cite repository facts only (crates, files, PRs), not plan
  names outside the repository; the strings rows no longer quote a
  row count that changes.

swift_logic_lines at 2b3d7cd with this table: 428194 (base table
431786). At feat f07e8d9: 429719. mirror_lines 71694 / 71698.
table_rows_missing 5, invalid 0. scripts/cmux-next/tests/
test_swift_logic_lines.py: OK.
@lawrencecchen

Copy link
Copy Markdown
Contributor

Swift logic follow-up (tip watcher swift-logic row, STATUS 13027 "SWIFT LOGIC CULPRITS"; lead order).

This PR raised swift_logic_lines by +565 at its merge commit a9c5b0d: scripts/cmux-next/swift-logic-lines.py before and after the merge, with the same table (the tip's, c6be943). The largest declarations of the rise:

  • struct VerticalTabListLayout in Packages/macOS/CmuxNext/Sources/CmuxNextTabs/Vertical/VerticalTabListLayout.swift: +218 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)
  • enum VerticalTabsHandlers in Packages/macOS/CmuxNext/Sources/CmuxNextApp/VerticalTabs/VerticalTabsHandlers.swift: +75 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)
  • class WorkspaceVerticalTabs in Packages/macOS/CmuxNext/Sources/CmuxNextApp/VerticalTabs/WorkspaceVerticalTabs.swift: +60 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)
  • struct VerticalTabDrop in Packages/macOS/CmuxNext/Sources/CmuxNextTabs/Vertical/VerticalTabDrop.swift: +47 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)

plans/cmux-next/layer-ownership.md says Rust owns every state, list and rule and Swift is the platform shell. Please move the new logic of this PR in a follow-up: to Rust (the crate that owns the area; the owner lists in STATUS 12147-12165 name the target per area), or at least out of the app into its package. If a declaration above is platform code (AppKit, Core Animation, OS calls, strings, tokens, DEBUG tooling), reply here and the table gets a PLATFORM row with your reason instead.

The swift-logic row is a report, not a gate: nothing blocks on this comment.

This branch was previously deployed

3 inactive (2 outdated) deployments
ci-routing-agent — ba629774 Deployed Nov 2, 2026 by teamleaderleo via wait for same-key tree publisher #101575
artifacts — 1478d62d Deployed Nov 2, 2026 by teamleaderleo via publish tree-addressed cmux-tui #101410
sentry-dsyms — 1478d62d Deployed Nov 2, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #101410
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants