feat: add v2 socket methods for full v1 parity#70
Merged
Conversation
Adds the remaining v2 JSON-RPC methods needed before the v1 line protocol can be deleted (PR 1 of the v1-deletion sequence). This PR only adds new v2 adapters; no v1 handler is modified. New surface telemetry methods (off-main parse, main.async mutate, per the socket command threading policy): - surface.report_pwd <- v1 reportPwd - surface.report_shell_state <- v1 reportShellState (reuses SocketFastPathState dedup) - surface.report_git_branch <- v1 reportGitBranch - surface.clear_git_branch <- v1 clearGitBranch - surface.report_pr <- v1 reportPullRequest - surface.clear_pr <- v1 clearPullRequest - surface.report_ports <- v1 reportPorts - surface.clear_ports <- v1 clearPorts New workspace-scoped sidebar metadata methods (mutations off-main + main.async; reads use v2MainSync like sibling read methods): - workspace.set_status <- v1 set_status - workspace.clear_status <- v1 clear_status - workspace.list_status <- v1 list_status - workspace.log <- v1 log - workspace.clear_log <- v1 clear_log - workspace.list_log <- v1 list_log - workspace.set_progress <- v1 set_progress - workspace.clear_progress <- v1 clear_progress - workspace.sidebar_state <- v1 sidebar_state - workspace.clear_agent_pid <- v1 clear_agent_pid New app method: - app.reload_config <- v1 reload_config (uses v2MainSync, matching v1's own call) Already had v2 equivalents before this PR (verified, not touched): - surface.report_tty <- v1 report_tty - surface.ports_kick <- v1 ports_kick Each new method is a thin adapter: parses params with the v2 helpers, resolves workspace/surface by explicit handle the way v2SurfaceReportTTY/v2SurfacePortsKick do, then calls the same TabManager/Workspace APIs the v1 handler calls (updateSurfaceDirectory, updateSurfaceGitBranch, updatePanelPullRequest, shouldReplace* dedup helpers, etc.) so behavior matches v1 without touching any v1 function body. Updated docs/v2-api-migration.md with the new method mappings and a note that v1 removal is planned in a follow-up PR once consumers migrate.
arzafran
added a commit
that referenced
this pull request
Jul 8, 2026
…ath (#72) * fix: mismatched brace/paren in _cmux_start_pr_poll_loop broke bash sourcing _cmux_start_pr_poll_loop opened its backgrounded PR-poll loop with a bare `{` but closed it with `)` (typo introduced in 88d6a2f, March 2026). A `{ ... }` group must close with `}`; mixing it with `)` is a syntax error, and bash apparently fails the syntax check for the entire file, not just the malformed function — sourcing programa-bash-integration.bash in a live shell (bash 3.2 and 5.3 both tested) aborts entirely with 'syntax error near unexpected token )', so no shell-integration function gets defined at all. Found while running `bash -n` as part of verifying an unrelated change (the v1->v2 JSON-RPC migration in the following commits); confirmed present on unmodified origin/main via `git show HEAD`. Fixed by opening a subshell with `(` instead, matching the `( ... ) &` backgrounding pattern already used elsewhere in this same file (e.g. _cmux_run_pr_probe_with_timeout, _cmux_prompt_command's pwd/git-branch probes) — subshells support $! for the backgrounded PID same as job groups do. * refactor: shell integration speaks v2 JSON-RPC on the direct socket path Step 3 of the v1-deletion sequence (see docs/v2-api-migration.md). Converts the direct-socket sends in the zsh and bash shell-integration scripts from v1 space-delimited lines to single-line v2 JSON-RPC frames, mirroring the pattern the REMOTE-relay path in the same scripts already uses (_cmux_relay_rpc "surface.report_tty" etc., added in PR #70's v2 parity methods, commit 475aa2f). Verbs converted (both scripts, kept behaviorally identical to each other): - report_tty -> surface.report_tty {workspace_id, tty_name, surface_id?} - report_shell_state -> surface.report_shell_state {workspace_id, surface_id, state} - report_pwd -> surface.report_pwd {workspace_id, surface_id, path} - report_git_branch -> surface.report_git_branch {workspace_id, surface_id, branch, dirty} - clear_git_branch -> surface.clear_git_branch {workspace_id, surface_id} - report_pr -> surface.report_pr {workspace_id, surface_id, number, url, state, branch} - clear_pr -> surface.clear_pr {workspace_id, surface_id} - ports_kick -> surface.ports_kick {workspace_id, surface_id?, reason} workspace_id/surface_id are sourced from the same env vars the v1 fast path and the v2 relay path already use (PROGRAMA_WORKSPACE_ID falling back to PROGRAMA_TAB_ID, and PROGRAMA_PANEL_ID) via the existing _cmux_relay_workspace_id helper. report_tty preserves the v1 tmux special case of omitting surface_id. Both scripts reuse the existing _cmux_json_escape helper (already used by the relay path) to safely escape quotes/backslashes/control chars in pwd paths and branch names before interpolating them into the JSON frames. Fire-and-forget semantics are unchanged: _cmux_send/_cmux_send_bg never read a response today and still don't after this change; call sites that were synchronous (report_git_branch/clear_git_branch/report_pr, which already run inside an already-backgrounded subshell) stay synchronous, and call sites that were backgrounded stay backgrounded. The relay path itself is untouched.
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
Adds the v2 JSON-RPC socket methods that were still missing v1 equivalents, so a
follow-up PR can delete the old line protocol. This PR only adds new v2 methods —
it does not delete or change any v1 handler's behavior.
Summary
surface.report_pwdreport_pwdmain.asyncmutatesurface.report_shell_statereport_shell_statemain.asyncmutate (reusesSocketFastPathStatededup)surface.report_git_branchreport_git_branchmain.asyncmutatesurface.clear_git_branchclear_git_branchmain.asyncmutatesurface.report_prreport_pr/report_reviewmain.asyncmutatesurface.clear_prclear_prmain.asyncmutatesurface.report_portsreport_portsmain.asyncmutatesurface.clear_portsclear_portsmain.asyncmutateworkspace.set_statusset_statusmain.asyncmutateworkspace.clear_statusclear_statusmain.asyncmutateworkspace.list_statuslist_statusv2MainSync(exact-snapshot read)workspace.loglogmain.asyncmutateworkspace.clear_logclear_logmain.asyncmutateworkspace.list_loglist_logv2MainSync(exact-snapshot read)workspace.set_progressset_progressmain.asyncmutateworkspace.clear_progressclear_progressmain.asyncmutateworkspace.sidebar_statesidebar_statev2MainSync(exact-snapshot read)workspace.clear_agent_pidclear_agent_pidmain.asyncmutateapp.reload_configreload_configv2MainSync(matches v1's own implementation, not a telemetry hot path)Already had v2 equivalents before this PR (verified against the dispatch table, not touched):
surface.report_tty(v1report_tty)surface.ports_kick(v1ports_kick)Each new method is a thin adapter that parses params with the existing v2 helpers
(
v2String/v2UUID/v2Bool/v2Int), resolves the workspace/surface by explicithandle the same way
v2SurfaceReportTTY/v2SurfacePortsKickdo, and then calls theexact same
TabManager/Workspacemodel APIs the v1 handler calls (e.g.updateSurfaceDirectory,updateSurfaceGitBranch,updatePanelPullRequest, theshouldReplace*dedup helpers,SocketFastPathState) — so v1 and v2 produceidentical model mutations without any v1 function body being touched.
Telemetry methods (
report_*/ports/log/progress/status) follow the socket commandthreading policy: params are parsed and validated off-main, then the actual model
mutation is dispatched with
DispatchQueue.main.asyncand the call returns anoptimistic
okresult immediately (mirroring v1's own fire-and-forget "OK" behaviorfor these same commands). Read-only exact-snapshot queries (
list_status,list_log,sidebar_state) use the existingv2MainSyncpattern shared by siblingv2 read methods.
docs/v2-api-migration.mdis updated with the new method mappings and a note thatv1 removal is planned in a follow-up PR once consumers (shell integration,
tests/)migrate to v2.
Test Plan
PROGRAMA_SKIP_ZIG_BUILD=1 xcodebuild -scheme programa -configuration Debug build→ BUILD SUCCEEDEDPROGRAMA_SKIP_ZIG_BUILD=1 xcodebuild -scheme programa-unit -configuration Debug build-for-testing→ TEST BUILD SUCCEEDED