cmux NEXT: empty workspace groups pin, read pinned and unpin; Pin/Unpin Group takes a pinned state
Fixes https://github.com/manaflow-ai/cmux/issues/22259
Summary
https://github.com/manaflow-ai/cmux/pull/22263 fixed the item-id mapping, but an empty workspace group still could not be pinned in cmux NEXT. Pin exists for exactly that case: a saved group stays, empty, when its workspaces close. Reproduced on a tagged build of feat-cmux-next 941ace32bcd with scripts/cmux-next/group-pin-live.py:
- GUI: Pin Group moved the empty group into Pinned, but its header still offered Pin Group. Clicking it again was refused ("The sidebar did not make this move.") and the group stayed pinned.
- CLI:
cmux workspace group <g> update --pinned true|falseworked for a group with members. - MCP:
workspaceGroup.togglePinhad nopinnedargument (invalid_params).
Cause and fix
SidebarDocProjection.emptyGroupdrew an empty group in Pinned withoutisPinned,parentordepth. It now reads them, as a group with members does.- The reducer's
unpinfound a group's machine only through its workspaces, so Unpin of an empty group was refused withno_machine. This hit both the GUI and the daemon's CLI sync. The group now goes back to the machine section it was pinned from, else to the first machine section (unpin_machine). workspaceGroup.togglePintakes an optionalpinnedbool (CLIworkspace-group toggle-pin --pinned, the MCP tool, scripts): it sets that state instead of toggling. The string is localized in 21 languages, copied fromargument.home.pinned.
Follow-up: the app's sidebar mirror links the pinned reducer FFI. GUI Unpin of an empty group works only after the automatic app FFI repin that app-ffi-release.yml opens once this lands, the same way https://github.com/manaflow-ai/cmux/pull/25170 was followed by https://github.com/manaflow-ai/cmux/pull/25202. The daemon (CLI path) gets the reducer change right away.
Tests
- Reducer:
pin_tests::an_empty_pinned_group_unpins_back_to_its_placeandan_empty_group_made_in_pinned_unpins_to_the_top_of_the_first_machine_section(red at dec72b9361de9, green at the head). - Live daemon and app services:
WorkspaceGroupPinLiveTestscovers menu pin/unpin, the empty group, the CLI update and the MCPpinnedargument. - Live GUI script:
scripts/cmux-next/group-pin-live.py TAG APP OUT.
Observed / Not run
- Observed: the base repro above, on a tagged app driven through its own socket.
- Submitted, results pending: fleet runs
22259-pin-rust-red-dec72b93,22259-pin-rust-green-a3bc1862and22259-pin-live-green-a3bc1862. An earlier red Swift run failed to compile; that test was fixed in dec72b9361de9. - Not run yet: the review subagent, and the tagged dev build
22259-pin-workspace-groupsof the head.
Drop a workspace into a pinned group
The Pinned drop rule from https://github.com/manaflow-ai/cmux/pull/22263 refused every row in Pinned, so nothing could be dragged into a pinned group. It now closes only Pinned's top level. A pinned group's header and the gaps between its members take drops, which add the workspace to the group. Red 323786eae0c24 and green 4d2f584e8ec22: https://github.com/manaflow-ai/cmux/pull/25669#issuecomment-6432156477
Changelog
Fixed: Workspaces can be dragged into a pinned group. An empty workspace group can be pinned and unpinned in the sidebar, and Pin/Unpin Group takes a pinned state from the CLI and MCP.
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.