Skip to content

cmux NEXT: a tab's menu rows and handlers resolve its id on its own machine - #28731

Merged
teamleaderleo merged 8 commits into
feat-cmux-nextfrom
lane/ao-tab-machine-scope
Nov 1, 2026
Merged

teamleaderleo merged 8 commits into
feat-cmux-nextfrom
lane/ao-tab-machine-scope

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

A forked or SSH machine keeps this Mac's tab ids. #28382 made a bare locateTab(id) refuse an id that two machines share, but only one row of a tab's right-click menu (Mark Unread) carried its machine. Every other row was still built, titled, hidden and run with a bare id, and so were the pane toolbar's "…" rows and the handlers they reach. So on a remote tab whose id this Mac shares:

  • Pin reads "Pin/Unpin Tab" instead of "Unpin Tab".
  • Remove Icon, Remove from Group, Back to Pinned Page and Disconnect Remote Tab show or hide by the wrong lookup.
  • ActionScope.pane refuses the row's action as "no tab".
  • Moves, Pin undo and the icon history could act through this Mac.

Takes back #27962: only its one-row scopeMenuAction(menu, action: "palette.toggleTabUnread", toMachine:) call in PaneController.tabMenu. makeContextMenu(machineID:) now scopes every row of that menu, Mark Unread included, so #27962's behaviour is kept and widened (TabAttentionTests.goingIntoARemoteMarkedTabHidesOnlyItsOwnRing still drives that row).

This is PR 2 of the plan on manaflow-ai/cmuxterm-hq#5338 (handlers carry the machine). It was unblocked when #27962 landed.

What changes

  • Menus: ActionRegistry.makeContextMenu(..., machineID:) passes the machine to every row's visibility, title and run, including choices submenus and their hover preview (choicePreview, then the theme previewTarget). Before, only scopeMenuAction could set it, one action at a time. PaneController.tabMenu and the pane toolbar's tab rows and buttons pass their machine. ActionInvocation.onMachine(_:) builds a scoped run.
  • Lookups: AppActionContext.targetTab(_:_:) resolves on invocation.targetMachineID when it is set, else falls back to the unscoped lookup. These use it: daemonTab, actionTabs, ActionScope.pane, paneController (only that machine's panes), the Pin title, the Remove Icon, Remove from Group, Back to Pinned Page and Disconnect Remote Tab visibility, targetContext, and PinCommands.
  • Moves: AppServices.workspaceID(ofTab: TabModel) finds a tab's workspace by model identity. It is used for the Home check (TabPromotion.refusal), movingTabs, Move to New Workspace/Window (origin, landing window, reveal), the new workspace's name and the incognito checks. landingWindow(tabWorkspace:workspaceID:) takes the resolved workspace.
  • Pins and icons: a hidden tab's pin, and its undo, go to the tab's own daemon. The icon history resolves on the daemon captured when the picker opened.
  • Sidebar: a tab row's menu takes its machine from the row's SidebarWorkspace.machineID, as the workspace menu does.
  • Ratchet: TabLookupGuardTests' handler allowance drops six files.

Routing doesn't change for a tab that only one machine holds: ActionRouting already sent a tab target to the daemon that holds it. With the machine set, a row whose machine disconnects while the menu is open is refused ("The target machine is no longer connected."), as Mark Unread already was.

Not in this PR (follow-ups on the issue):

  • Forks keep workspace ids too: SidebarContextTarget and services.workspace(id:) still resolve a shared workspace id first-match.
  • AgentTabs is keyed by bare chat id (AgentChatCopy).
  • choiceState checkmarks.
  • TabHandlers.reveal and BrowserFitFrameView.perform have no invocation yet.

Fixes manaflow-ai/cmuxterm-hq#5338 (the handler part; the items above are its follow-ups).

Tests

  • Red first (commit 1, test only): TabLookupTests/aRemoteTabMenuResolvesItsOwnMachinesTab. Its fixture is a pinned remote tab plus this Mac's unpinned tab with the same id. The remote menu's Pin row must read "Unpin Tab". On base the title lookup has no machine, the id is ambiguous, and the row reads "Pin/Unpin Tab".
  • Green: that test plus targetTab assertions (unscoped stays ambiguous; each machine resolves its own tab).
  • MachineScopedMenuTests (CmuxNextActions):
    • every row of a machine-scoped menu carries the machine, and so do its visibility check and a choices submenu's run and hover preview;
    • an unscoped menu names no machine.
  • The TabLookupGuardTests ratchet shrinks.

Observed / Not run

  • Ran here: scripts/cmux-next/prepush-gate.py: no new violations, and the arch ratchet doesn't rise (App lines net 0, with the helper in CmuxNextActions).
  • Review: independent Codex gpt-6-astra (high, fast). Rounds at 9c9fe38, 862f9b7, 168ffbf and 21368eb blocked; each finding is fixed in its own commit. The delta review gives SHIP at bb6b163.
  • Not run locally: the Swift suites (this host doesn't build Swift). PR CI's suites run them at the head.

Changelog

Fixed: right-click menus and the pane's "…" on a tab of a forked or SSH machine act on and read that machine's tab, not a same-id tab on this Mac.

No capture: the only visible change is a row's title or visibility on a remote tab whose id this Mac also has. The tests above cover it.

Agent session: agent session

🤖 Generated with Claude Code

teamleaderleo and others added 2 commits October 31, 2026 01:43
… Mac shares its id

Red on base: the remote pinned tab's Pin row reads Pin Tab, because the
row's title lookup carries no machine and the shared id is ambiguous.
Refs manaflow-ai/cmuxterm-hq#5338.

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

A forked or SSH machine keeps this Mac's tab ids. Only Mark Unread was
scoped to the row's machine; every other row built, titled, hid and ran
with a bare id, which #28382 made refuse as ambiguous.

- makeContextMenu takes the target's machineID; every row's visibility,
  title and run carry it (choices submenus too). The tab menu passes it.
- AppActionContext.targetTab(_:_:) resolves on invocation.targetMachineID
  when set; daemonTab, actionTabs, the Pin title, Remove Icon, Remove from
  Group, Disconnect Remote Tab visibility and targetContext use it.
- ActionScope.pane resolves a tab target on the invocation's machine.
- TabLookupGuardTests' handler ratchet drops the five migrated files.

Fixes manaflow-ai/cmuxterm-hq#5338 (handler part; AgentTabs keying stays).

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

cursor Bot commented Oct 31, 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 added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

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

Review e4f2dc3: 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=pr28731 -f ref=lane/ao-tab-machine-scope -f platform=macos -f backend_mode=local

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

CI passes on 6234bbe771 (run 41264493265 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.

Default changes

This pull request changes 18 defaults at 6234bbe77171 (what everyone gets without configuring anything):

  • tunable-source.CmuxNextApp/Drag/TabMoves.swift:newWorkspaceName: "ededeea7a5d2a5b537ccbcb8a49b3764a33852d42accd80559b0bc38d7324bc1" -> "d05b27a54325f522e7764175ae9aacdc12372a0e606b27a52f289689a4fd87f8"
  • tunable-source.CmuxNextApp/Drag/TabMoves.swift:toWorkspace: "061a0c5553d8264d5fb81fce4b2d41189e7144a6e9cd6f6fbb1322775b590ae5" -> "9958ee0410093e09cc5054b469427b3601cd163e5ccc500d2e4ae71157037ca0"
  • tunable-source.CmuxNextApp/Drag/TabPromotion.swift:refusal: "b541848528bdc2804fe2d8091b1bc82b4225c2c91c4614ba384e2bca0fba2762" -> "721a6b480ac3f079d9ea68f469337d4ff23fbfd84083cc4dd59b23a3a8d3cb57"
  • tunable-source.CmuxNextApp/Handlers/IconMenuVisibility.swift:install: "5fc90cd067ce8db07c71f12a6d4bfe1950e2593c139822912ef5dd956f27ffd3" -> "1f52a3c0e8be0523b6c9e6aee9b5743b50955658a81e80877da11f1fe29d9e9f"
  • tunable-source.CmuxNextApp/Handlers/SSHTargetHandlers.swift:bind: "9c48d11c8a1da6b8220e33d0b8787581aebb9d263e4ad797457ee3de20158878" -> "d51fdb9fa70f94be62da2195f1bcec05cfbebeebb340e3a8a26f3ed16858c834"
  • tunable-source.CmuxNextApp/Handlers/TabGroupHandlers.swift:bind: "e0343254d68a41315bfe3fab11eb168f9c82688395d0fcb7979da7398f3c553c" -> "b3fa989e74362a0a117abbd34dd7d7d8943fe63ead9a90eacde6c39f6a6e5c17"
  • tunable-source.CmuxNextApp/Handlers/TabHandlers+More.swift:moveToNewWorkspace: "2ac849a764fe5e81f25b01ff201f1ae035f26f3e7b0b260f3cd3e30deb4b695b" -> "aa873685f9ccd36579a9f3ec9eaf53e394c0ebd40b2e87b8e7f7d02c5d82bb39"
  • tunable-source.CmuxNextApp/Handlers/TabHandlers+More.swift:revealer: "fdd2fb688d5622b5e3dc4ed5865a7b10ff2ce2d8a1201ec89f399eb56290e21b" -> "28ef054f11d3a10bb13004ae03c5805d030d4f0a657b876f54718f374a7767e5"
  • tunable-source.CmuxNextApp/Handlers/TabHandlers.swift:bindMetadata: "74249371ddeccd94cfe3edc05b77ecbaba1e6e38a99651ee70bd368901b82fae" -> "23a9f5b3c8ad26c688211e4d6b51b392d08e7bd11b95880193849ee46d2f4b9b"
  • tunable-source.CmuxNextApp/Handlers/TabHandlers.swift:otherView: "ae751dbf73a407856892da84e019396e099cbe695541fb1da04fde054536ad4f" -> "d955e1b65d3d3bf50868cd9f9b5cbcde8974fce223fd525456b9f6d2912b66f0"
  • tunable-source.CmuxNextApp/Handlers/TabHandlers.swift:switchView: "c4eda9a136dda6ab38a8eaa714140d2c6be67162413b0c952a46d7ab40e69308" -> "cdea832e2b18f78c4d6d6094328c6af264ae2306b419e7f1016dfbf5e8a28c00"
  • tunable-source.CmuxNextApp/Handlers/TabIconHandlers.swift:change: "453b131fc9ad490f88fd3e14f908b9c5b12180ae0e0552314e1431ec6aed3865" -> "c92da7572dde395a2c6bcb6c6e9c331995cb6722cda6306b34b03e3a1cf8ac2b"
  • tunable-source.CmuxNextApp/Handlers/TabIconHandlers.swift:history: "e16258be051c7dbaf29cee687f0de68a9d620a3a2085928563ab170121464015" -> "6b65f14f85aa73542e25a6062e91ec55a2c173a40a676d1d02e5d4caed901ae5"
  • tunable-source.CmuxNextApp/Handlers/ThemeHandlers.swift:bind: "7f5f17abb36012b87946baa038db593a98311930f8972723afb49fd66190f360" -> "a8860609f9b0c165d35f7a872dd76892e360908f7750dcfef5376bbd893e5020"
  • tunable-source.CmuxNextApp/Handlers/ThemeHandlers.swift:previewTarget: "ccf50ec249b6d8d97fa921f2603fec522779ec59f87c6c9b4d0ff4fa9339ba0f" -> "52f5db5bf0745f3b838b568c40191ef41b1fad34dc1c909567d6d6e485b2ee49"
  • tunable-source.CmuxNextApp/Handlers/WorkspaceSetVerbs.swift:bind: "9b83289b88c6a2de9e2570d64dd94a7886da73c679c7ec927ed174b20b73a0d1" -> "31d0a701e6cb4e269a897a18033ca55bd24f60dce5067236b8bc7014d0d97952"
  • tunable-source.CmuxNextApp/Handlers/WorkspaceStructureHandlers.swift:movePane: "50bdd0fe0abb2f05fbe0c8c92edeb739e944063a93fde80d070370263fc9efe3" -> "aadd114efb57fa7f819372adea42d09edff03e14c25cf82349c12431ef6265fd"
  • tunable-source.CmuxNextApp/Pins/PinnedPage.swift:bind: "a810ad4762342f905c31221ccd02ad507676a5c75d6e003ba60c00624c461307" -> "eae512fa3766dc7333496d9625391e4ce72aaf6addd9dc9f4ea6533cdb056909"

Needs a review. It passes with an independent review receipt on this commit: a comment or review whose first line is Review (<reviewer>): SHIP at 6234bbe77171b0e7b30ab45bf24c2c2529504ed5, from a member, not a self-review (the newest verdict naming the head decides; a later BLOCK beats an earlier SHIP), or with an approving review on this commit from @lawrencecchen or @austinywang (the call owners in .github/defaults-call-owners.json, never the author). A receipt posted as a review re-runs this check; after a plain comment, re-run it. The needs a call label alone does not pass, and a new push needs a new receipt.

Merge receipt: merged as 82e70cabf13e with these defaults changed, WITHOUT a SHIP receipt or an approving call owner review on its head.

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

Shipped in:

@blacksmith-sh

blacksmith-sh Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

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

teamleaderleo and others added 2 commits October 31, 2026 02:04
…reviews too

Review of 9c9fe38 (Codex gpt-6-astra) blocked on three gaps:
- AppActionContext.paneController matched the tab id in every window; with
  a target machine it now matches only that machine's panes (renameTab and
  every ctx.tab caller).
- The sidebar tab menu took its machine from daemon(forWorkspace:), which
  is local-first; it now reads the row's own SidebarWorkspace.machineID,
  as the workspace menu does.
- A choices submenu's hover preview (terminal theme) carried no machine;
  the coordinator and choicePreview/previewTarget now pass it.

MachineScopedMenuTests: every row, the visibility check, a choices run and
its preview carry the menu's machine; an unscoped menu names none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-a6ffa6000a8c39df50a6
…lve the tab on its machine

Second review (Codex gpt-6-astra at 862f9b7) found more bare-id lookups on
the tab menu's paths:
- PinCommands.setTabPinned/apply take the invocation's machine (the undo too).
- PinnedPage's visibility uses targetTab.
- TabIconHandlers.history resolves on the tab's own machine (undo included);
  its ratchet allowance goes.
- PaneToolbar's buttons, its … tab rows and their availability carry the
  pane's machine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-a6ffa6000a8c39df50a6
… stay on its machine

Third review (Codex gpt-6-astra at 168ffbf):
- Moves re-resolved the daemonTab-selected tab's workspace by bare id.
  AppServices.workspaceID(ofTab: TabModel) finds it by model identity;
  TabPromotion.refusal, movingTabs, moveToNewWorkspace's origin and landing
  window, revealer, newWorkspaceName and toWorkspace's incognito check use it.
  landingWindow(tabWorkspace:workspaceID:) takes the resolved workspace.
- PinCommands sends a hidden tab's pin (and its undo) to the tab's own daemon,
  not the active one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-a6ffa6000a8c39df50a6
Fourth review (Codex gpt-6-astra at 21368eb): the machine came from the
captured TabModel, which a snapshot can replace while the picker is open;
use the Target's captured daemon instead.

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

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra, high, fast; delta over the full review at 21368eb): SHIP at bb6b163

@cmux-bot cmux-bot Bot removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Orphaned: no activity for 13 h, and no lane holds a lease on it. The orphan sweep could not merge feat-cmux-next in: conflicts in Packages/macOS/CmuxNext/Sources/CmuxNextApp/SidebarContextMenus.swift. Listed for a lane to resolve.

Conflicts: SidebarContextMenus takes base (the sidebar tab-row menu is gone);
PaneToolbar keeps base's hoisted tab rows and scopes them to the pane's machine;
TabLookupGuardTests keeps the PR's allowance, and the two new bare lookups in
TabHandlers (Edit Source / Open as Page) resolve through ctx.targetTab.

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

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at e4f2dc3

Reviewer: codex gpt-6-astra high, fast tier.

Follow-ups: 3. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at e4f2dc3

Visual verdict: no images; Leo tries the build

  1. [P1] [follow-up] PinnedPage.swift:19: Back to Pinned Page still uses an unscoped browser cache. With a local browser loaded and a remote pinned tab sharing its ID, the newly scoped handler resolves the remote tab, but reset calls existingBrowser(tab.id) and navigates the local browser. Scope the cached browser lookup by machine before loading the URL.

  2. [P2] [follow-up] ThemeCoordinator.swift:291: Set Terminal Theme → More… drops the machine for previews. PaletteArgumentFlow.withPreview forwards only the target, and PaletteSourcesBridge calls pickerPreview without its machine. With duplicate IDs, hovering can preview the local terminal while committing changes the remote terminal. Carry the machine through the palette preview callback too.

  3. [P2] [follow-up] selection.json:2: No screenshots were supplied; menu appearance remains visually unverified.

Swift suites were not run: Swift is unavailable in this box.

Follow-ups:

  • Scope Back to Pinned Page’s browser-cache lookup.
  • Preserve machine identity through palette theme previews.
  • Visually verify the remote tab menus in a build.

@teamleaderleo
teamleaderleo merged commit 82e70ca into feat-cmux-next Nov 1, 2026
125 of 134 checks passed
@teamleaderleo
teamleaderleo deleted the lane/ao-tab-machine-scope branch November 1, 2026 02:35
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at 6234bbe

Reviewer: codex gpt-6.1-sol xhigh, fast tier.

Follow-ups: 1. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at 6234bbe

Visual verdict: no images; Leo tries the build

No correctness regressions found. Source audit passed; native Swift tests were not run on Linux.

  1. [P2] [follow-up] review/images/README.txt:2: No native screenshots were supplied for the changed menus.

Follow-ups:

  • Capture and verify remote-tab menus with duplicate local and remote tab IDs.

teamleaderleo pushed a commit that referenced this pull request Nov 1, 2026
…usal

#28731 made TabPromotion.refusal(tab:services:) take a TabModel and added the
machine-scoped workspaceID(ofTab:) overload; the merged Move Tab to Space
still passed tab.id, which no longer compiles (review BLOCK at 05a7b45).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-fc739fd2f4e557ae7189
teamleaderleo added a commit that referenced this pull request Nov 1, 2026
* cmux: add first-class space CLI commands

Agent-Session: https://cmux.com/deeplink/agent?id=aid-db09c90b64b7e4792ce2

* cmux: expose tab space move through action catalog

Agent-Session: https://cmux.com/deeplink/agent?id=aid-db09c90b64b7e4792ce2

* cmux: localize move tab to space action

Agent-Session: https://cmux.com/deeplink/agent?id=aid-db09c90b64b7e4792ce2

* cmux: fix space help string

Agent-Session: https://cmux.com/deeplink/agent?id=aid-db09c90b64b7e4792ce2

* Preserve catalog space commands alongside positional aliases

Agent-Session: https://cmux.com/deeplink/agent?id=aid-db09c90b64b7e4792ce2

* Complete space action pipeline and help surface

Agent-Session: https://cmux.com/deeplink/agent?id=aid-db09c90b64b7e4792ce2

* test(cli): a flag is never a positional space name (red)

cmux space rename --name Office and the other flag forms must keep the
generic catalog route instead of targeting a space named after the flag;
options after a positional form must reach the action.

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

* fix(cli): space positional forms read only the leading non-option words (green)

cmux space rename --name Office targeted a space named --name. The
positional forms now match only the words before the first option, as the
generic <noun> <verb> route reads them, and pass the options after them to
the action. The space forms move to cli/app/space.rs.

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

* fix(next): Move Tab to Space moves only the tab

tab.moveToSpace pinned the tab's whole workspace to the space, taking
every sibling tab along. A tab alone in its workspace still takes the
workspace (a pin, as Move Workspace to Space does); a tab with siblings
moves into a new workspace (TabMoves.toNewWorkspace, the path Move Tab to
New Workspace uses) that is pinned to the space. Home's own tab is refused
as for Move Tab to New Workspace, and a workspace already pinned to the
space is refused as Move Workspace to Space refuses it.

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

* fix(next): Move Tab to Space in fewer App lines

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

* fix(next): Move Tab to Space stays off the tab menu; exports list it

tab.moveToSpace had neither a tab-menu placement nor an exemption, so the
surface parity check had no decision for it. The tab menu's Move folder keeps
Move Tab to Workspace…; this one is palette, CLI and MCP only
(pointerMenuTrim). action-surfaces.json, actions.md counts and the web
next-docs references (bun web/scripts/export-next-docs.ts) list it.

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

* fix(next): Move Tab to Space refuses Home's tab and says it waits for the daemon

Home's own tab is refused whether or not it is alone (a lone Home tab
could pin Home into another space). The action changes nothing locally
before the pin answers, so it is a .waiting(.daemonEcho) effect, not
.applied. The flag-form tests use real catalog names (space delete,
space switch).

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

* arch-ratchet: app_lines exception for Move Tab to Space (+24, reviewed)

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

* test(cli): space tests read a missing args as empty

run_action leaves args out when an action takes none, so space switch's
expected {} never matched (the original #28175 test was red at its head for
this). Both space tests now read a missing args as {}.

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

* fix(next): Move Tab to Space passes the tab model to TabPromotion.refusal

#28731 made TabPromotion.refusal(tab:services:) take a TabModel and added the
machine-scoped workspaceID(ofTab:) overload; the merged Move Tab to Space
still passed tab.id, which no longer compiles (review BLOCK at 05a7b45).

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

* fix(next): Move Tab to Space reads a workspace's space pin through RoomMembership.pinned

Base keys RoomMembership.pins by session then key now; pins[qualified] no
longer compiles (review BLOCK at 7d3f53a). Same read as Move Workspace
to Space.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Leo Li <t@e>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 6234bbe7 Deployed Nov 1, 2026 by teamleaderleo via wait for same-key tree publisher #92941
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.

1 participant