refactor: reject bare indexes for window/workspace/pane/surface targets - #149
Merged
Conversation
…ts (#132) Indexes shift when panes and workspaces open or close, so any agent holding one can silently hit the wrong target. Targets must now be a UUID or a short ref (workspace:2, surface:4). - CLI: normalizeHandle, resolveWorkspaceId, and resolveSurfaceId no longer resolve an all-digits argument by position; they fail with an error naming the accepted formats and the list command that shows refs. - Help text: <id|ref|index> becomes <id|ref> everywhere (56 strings), the usage banner drops the indexes clause, and the stale focus-window example no longer shows --window 0. - tests_v2/cmux.py resolvers raise the same error for int arguments; the five test files that passed positional ints now resolve real ids from the list calls first. Unchanged on purpose: placement options (reorder --index, move-surface --index), browser tab ordinals and find-nth (browser-DOM conventions), tmux-compat numeric targets (protocol-mandated), and the index field in list output (tmux compat consumes it). Verified against a tagged debug build: index args now fail with the new error; test_tab_dragging (15/15), test_ctrl_socket (5/5), test_close_workspace_selection and test_close_surface_selection all pass.
…apis # Conflicts: # TODO.md
11 tasks
arzafran
added a commit
that referenced
this pull request
Jul 21, 2026
surface.focus rejected bare indices in #149; both the VM script and the extracted CI script still passed 0, so the workspace bootstrap died before any test ran. list_surfaces rows are (index, id, focused) — pass the id.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Closes the last Phase 1 P0. Anywhere a command targets a window, workspace, pane, or surface, you now pass a UUID or a short ref (workspace:2, surface:4) — never a bare position number. Positions shift the moment something opens or closes, so an agent holding one could act on the wrong pane; now it gets a clear error telling it what to use instead.
Closes #132.
Summary
CLI/programa.swift): the three shared resolvers (normalizeHandle,resolveWorkspaceId,resolveSurfaceId) no longer resolve all-digit arguments positionally via<kind>.list; they throw"<kind>: bare indexes are no longer accepted; use a UUID or short ref like <kind>:2 (see <list command>)". All ~40 target-taking commands inherit the change through these chokepoints.<id|ref|index>occurrences become<id|ref>, the usage banner drops the "or indexes" clause, and the stalefocus-window --window 0example is fixed.tests_v2/cmux.py): the three_resolve_*_idhelpers raise the same error for int arguments, so any straggler test fails loudly with guidance instead of silently mistargeting.test_tab_dragging,test_visual_screenshots,test_close_workspace_selection,test_close_surface_selection,test_ctrl_socket) now resolve real ids from list calls at each site.Explicitly unchanged: placement options (
reorder-workspace --index,move-surface --index/--before/--after),browser tab <index>andbrowser find nth(browser-DOM ordinals, a different convention), tmux-compat numeric targets (protocol-mandated, isolated dispatch path), and theindexfield in list output (tmux compat consumes it). The v2 socket handlers needed no changes — they already require refs/UUIDs for identity; theirindexparams are placement-only. cmd+1..9 switching is an in-process AppKit path and is unaffected.Test Plan
select-workspace --workspace 0fails with the new error naming the formatstest_tab_dragging.py15/15,test_ctrl_socket.py5/5,test_close_workspace_selection.pyandtest_close_surface_selection.pyall green against the tagged buildtest_visual_screenshots.pyon the VM/e2e lane (screenshot suite; not run locally by policy)