Repository navigation
cmux NEXT: a tab's menu rows and handlers resolve its id on its own machine - #28731
Conversation
… 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
Bugbot needs on-demand usage enabledBugbot 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. |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Not verified: macOS jobs did not run: compile and app tests were skipped on CI passes on Written by Default changesThis pull request changes 18 defaults at
Needs a review. It passes with an independent review receipt on this commit: a comment or review whose first line is Merge receipt: merged as Regenerate the snapshot with Shipped in:
|
|
Found 1 test failure on Blacksmith runners: Failure
|
…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
|
Orphaned: no activity for 13 h, and no lane holds a lease on it. The orphan sweep could not merge |
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
|
Owned by an agent session · session |
|
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
Swift suites were not run: Swift is unavailable in this box. Follow-ups:
|
|
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.
Follow-ups:
|
…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
* 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>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
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:ActionScope.panerefuses the row's action as "no tab".Takes back #27962: only its one-row
scopeMenuAction(menu, action: "palette.toggleTabUnread", toMachine:)call inPaneController.tabMenu.makeContextMenu(machineID:)now scopes every row of that menu, Mark Unread included, so #27962's behaviour is kept and widened (TabAttentionTests.goingIntoARemoteMarkedTabHidesOnlyItsOwnRingstill 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
ActionRegistry.makeContextMenu(..., machineID:)passes the machine to every row's visibility, title and run, including choices submenus and their hover preview (choicePreview, then the themepreviewTarget). Before, onlyscopeMenuActioncould set it, one action at a time.PaneController.tabMenuand the pane toolbar's tab rows and buttons pass their machine.ActionInvocation.onMachine(_:)builds a scoped run.AppActionContext.targetTab(_:_:)resolves oninvocation.targetMachineIDwhen 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, andPinCommands.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.SidebarWorkspace.machineID, as the workspace menu does.TabLookupGuardTests' handler allowance drops six files.Routing doesn't change for a tab that only one machine holds:
ActionRoutingalready 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):
SidebarContextTargetandservices.workspace(id:)still resolve a shared workspace id first-match.choiceStatecheckmarks.TabHandlers.revealandBrowserFitFrameView.performhave no invocation yet.Fixes manaflow-ai/cmuxterm-hq#5338 (the handler part; the items above are its follow-ups).
Tests
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".targetTabassertions (unscoped stays ambiguous; each machine resolves its own tab).MachineScopedMenuTests(CmuxNextActions):TabLookupGuardTestsratchet shrinks.Observed / Not run
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).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