acpmux --group: a variant of a group's name joins that group; a refused group exits 2 as usage.group_name
Fixes manaflow-ai/cmuxterm-hq#4976
For Leo's ask to productionize the acpmux daemon ("do we have more productionized stuff wrt the daemon ... let's go set up more fellas on it"). This finishes what #24581 left open: acpmux new --group makes a stray sidebar group when a name is typed a little differently, and its refusal skips the usage envelope.
What
- The app matches a group by its label, not its exact string.
--group "gui push","GUI push "or" Gui Push\n"now joins the existing "GUI push" group, and a re-homed lane finds its old row in that group. A group with exactly that name still wins over a case variant, and a new group gets the trimmed name. Before, any variant made a second "GUI push" group next to the first (group.name == name). - The group helpers move out of CmuxNextApp.
validGroupName,group(named:accepting:in:),predecessor(named:inGroup:in:)and the newsameGroupNameare pure sidebar-tree functions. They move fromAgentSessionWorkspacetoSidebarEdits+NamedGroup.swiftin CmuxNextSidebar, next toSidebarEdits.canMove, which they use. CmuxNextApp shrinks by 35 lines (arch-ratchetapp_lines). - A refused
--groupis a usage error. A blank or id-shaped--group(grp_ā¦,ws_ā¦, a UUID) used to exit 1 as a runtime error. It now exits 2 withdetail: group_nameanddata.reason: usage.group_namein the--jsonenvelope, still before any session is made. - Docs. The
--grouphelp, the acpmux skill and the README say that the name is matched ignoring case and outer spaces, and that an id is refused with exit 2.
Test
Red commit 48f6920beb1 adds only tests:
cd cmux-tui && cargo test -p acpmux --lib -- a_group_is_a_human_label_and_never_an_object_id: the refusal must classify as exit 2 withusage.group_name. Green at head 96ee0624f71:test result: ok. 39 passed; 0 failedwitha_group_is_a_human_label_and_never_an_object_id ... ok(fast-checks run 41159694793). Red: not run. The broker refused the run at the red commit twice (GitHub quota 403, then busy). The reviewer confirmed by reading that it fails on base, where the refusal is a plainbail!that classifies as exit 1 /error.AgentSessionGroupJoinTests.theSameLabelTypedAnotherWayJoinsTheGroup(CmuxNextAppTests): case and whitespace variants joing1and find the predecessor row, "GUI pushes" does not match, and an exact name beats a case variant, both for the group and for the re-homed row (added after review, 96ee0624f71). On base, every variant returns nil. This lane VM has no fleet client, so the Swift suites run only in this PR's CI at its head.
Observed / Not run
- Observed:
prepush-gate.pyreports no new violations; rustfmt is clean on the changed Rust files. - Not run: a tagged-build launch of
acpmux new --group "gui push"into a sidebar that already has "GUI push". The Swift change is covered by the unit test above, not by a capture.
No capture: the sidebar looks the same; the only change is which existing group a scripted --group open joins.
Default changes: the defaults guard lists the moved functions of AgentSessionWorkspace.swift (a tunable source) by hash. No setting, key or flag default changes: the functions moved to SidebarEdits+NamedGroup.swift, and only group-name matching changed.
Review
Independent review (Codex gpt-6-astra, high): BLOCK at 1627fa5b2a3 for a missed test caller (AgentSessionGroupPlacementTests still called AgentSessionWorkspace.group) and for predecessor not preferring the exactly named group. Both were fixed in 96ee0624f71, and the delta review gave SHIP at 96ee0624f711220dc483e532f90117a8e86cfef1.
Changelog
- Fixed:
acpmux new --groupjoins the existing sidebar group when the name differs only in case or outer spaces, instead of making a second group.
Agent session: agent session
š¤ Generated with Claude Code