feat!: remove the v1 line-based socket protocol#75
Merged
Conversation
v2 JSON-RPC is now the only socket protocol. All consumers were migrated first (CLI in #74, shell integration in #72, tests in #71/#73; the remote daemon was already v2-only), so this deletes the v1 line dispatch itself and everything that only existed to serve it. - TerminalController.processCommand now dispatches JSON unconditionally; a non-JSON line gets a terse v1_removed error instead of being routed to the old space-delimited command switch. - Deletes the v1 switch (~90 cases) and every handler function that becomes unreferenced, plus their v1-only parsing helpers (parseOptions/parseOptionsNoStop, resolveTabForReport, withReportTargetSurface, upsertSidebarMetadata/clearSidebarMetadata/ listSidebarMetadata, schedulePanelMetadataMutation, parseReadScreenArgs). Debug handlers that v2's debug.* methods reuse as their implementation core (setShortcut, simulateShortcut, activateApp, isTerminalFocused, readTerminalText, renderStats, layoutDebug, bonsplit/empty-panel/flash counters, focusFromNotification, panelSnapshot(Reset), captureScreenshot) are kept, since they're still live v2 entry points, not v1 relics. Self.socketFastPathState and tailTerminalLines/ readTerminalTextBase64(terminalPanel:) stay too - v2 surface-telemetry and screen-read methods depend on them directly. - auth was already a connection-level preamble (authResponseIfNeeded, handled before any protocol dispatch) supporting both a raw auth-plus-password line and v2 auth.login; only the CLI's raw-line call needed migrating, which this does (auth.login now). - Removes the now-unreachable isV2:false focus-intent allowlist (focusIntentV1Commands) and updates the one unit test that exercised it directly to cover the v2 equivalent instead. - Docs: v2-api-migration.md collapses to a short removal note plus the v1->v2 name mapping (kept for reference); socket-focus-steal-audit.todo.md and agent-browser-port-spec.md get historical annotations; CLAUDE.md's socket-threading-policy examples are reworded to v2 method names. TerminalController.swift: 12834 -> 9615 lines (-3219). Net repo diff: +156/-3410 across 7 files. Breaking change: any external script or tool that still speaks the old space-delimited socket protocol directly (rather than through the CLI) will now get a v1_removed JSON error instead of a response. Use the CLI or the v2 JSON-RPC protocol described in docs/v2-api-migration.md.
2 tasks
arzafran
added a commit
that referenced
this pull request
Jul 8, 2026
The macOS Compatibility smoke test still sent raw v1 lines (ping, send) and failed on main after the v1 protocol removal (#75) with a v1_removed error — the one consumer the migration inventory missed because it greps workflows for test paths, not inline socket writes. Ported to system.ping and surface.send_text.
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
Programa's terminal socket has spoken two protocols side by side: an old space-delimited
line protocol ("v1") and a newer JSON-RPC protocol ("v2"). Every consumer — the CLI, the
shell integration, the automated tests, and the remote daemon — now speaks v2 exclusively,
so this PR deletes the old protocol and everything that only existed to serve it.
Breaking change for anyone with custom scripts: if you (or a script, alias, or tool)
talk to Programa's socket directly with the old space-delimited commands (
list_windows,focus_window "id",report_pwd ..., etc.) instead of through theprogramaCLI, thosecommands will now get a JSON error (
v1_removed) instead of a response. Everyone using theprogramaCLI is already unaffected — it moved to v2 in #74.Summary
TerminalController.processCommandnow dispatches JSON unconditionally. A non-JSON linegets a terse
v1_removedJSON error pointing at the v2 protocol instead of being routedinto the old ~90-case command switch.
gone, along with their v1-only argument-parsing helpers (
parseOptions/parseOptionsNoStop,resolveTabForReport,withReportTargetSurface,upsertSidebarMetadata/clearSidebarMetadata/listSidebarMetadata,schedulePanelMetadataMutation,parseReadScreenArgs, plus two small structs used onlyby
read_screenargument parsing).setShortcut,simulateShortcut,activateApp,isTerminalFocused,readTerminalText,renderStats,layoutDebug,bonsplitUnderflowCount/resetBonsplitUnderflowCount,emptyPanelCount/resetEmptyPanelCount,focusFromNotification,flashCount/resetFlashCounts,panelSnapshot/panelSnapshotReset,captureScreenshot— each ofv2's
debug.*methods calls straight into these as its implementation core, so the oldv1-named function stayed even though its switch
caseline is gone.Self.socketFastPathState(the shell-activity dedup state) andtailTerminalLines/readTerminalTextBase64(terminalPanel:...)— used directly byv2SurfaceReportShellStateandv2SurfaceReadText/screen-snapshot code respectively.authwas never actually a v1 switch command in the way the rest ofthe protocol was —
authResponseIfNeededinterceptsauth <password>(v1-style line) andauth.login(v2 JSON-RPC) as a connection-level preamble before any protocol dispatch,and both paths already did real password verification. The only wrinkle: the v1 switch had
a fallback
case "auth"that answered "OK: Authentication not required" for the (fairlycommon) case where the CLI has a locally-resolvable password but the server's access mode
doesn't actually require one — deleting the switch would have made the CLI's raw
auth <password>line hit the newv1_removederror and fail auth in that case. Fixed bymigrating the CLI's auth call (
CLI/programa.swift) from the rawauth <password>line toauth.login— the v2 protocol already has a symmetric fallback case for the "not required"scenario (v2's
auth.logincase returnsauthenticated: true, required: false), so no newserver-side method was needed, only the client-side call.
isV2: falsebranch's backing data (focusIntentV1Commands) from thesocket focus-mutation policy, since no code path can produce
isV2: falsefor a realcommand anymore. Updated the one unit test that exercised that branch by v1 command name to
cover the v2 equivalent instead (
window.focus,debug.shortcut.simulate).docs/v2-api-migration.mdcollapses from a migration-tracking doc into a short"v1 was removed" note that keeps the v1->v2 method-name mapping table for anyone reading old
scripts or commits.
docs/socket-focus-steal-audit.todo.mdanddocs/agent-browser-port-spec.md(both are audit/planning docs from the earlier migration)get a short annotation marking their v1-specific sections historical, without rewriting
their audit trail.
CLAUDE.md's socket-threading-policy examples are reworded from v1command names (
report_*) to their v2 equivalents (surface.report_*) — the policy itselfis unchanged, it always governed v2 telemetry too.
Line delta:
Sources/TerminalController.swiftgoes from 12834 to 9615 lines (-3219).Net repo diff: +156 / -3410 across 7 files.
Test Plan
xcodebuild ... -scheme programa-- BUILD SUCCEEDEDxcodebuild ... -scheme programa-cli-- BUILD SUCCEEDEDxcodebuild ... -scheme programa-unit build-for-testing-- TEST BUILD SUCCEEDEDprogramaTests/for every deleted function name -- the handful of matches areall unrelated identically-named methods on other types (
TabManager.closeWorkspace,KeyboardShortcutSettings.setShortcut,AppDelegate.moveWorkspaceToWindow, etc.), notcalls into the deleted
TerminalControllerwrappers (which wereprivateto thatfile, so cross-file access was never possible) -- confirmed by the test target
compiling cleanly.
programaTests/TerminalControllerSocketSecurityTests.swift: updatedtestSocketCommandPolicyDistinguishesFocusIntent(see above); lefttestPasswordModeRejectsUnauthenticatedCommandsuntouched since it only exercises thepre-protocol auth gate, which is unaffected by this change.
tests_v2/is the CI gate for full runtime verification (never run locally per repopolicy). Traced through the relevant tests by hand:
test_cli_global_flags_and_v1_error_contract.py'spingcalls already go through the CLI's v2system.ping, and its implicit auth call(via
SocketPasswordResolver) now goes through the migratedauth.loginpath -- bothunaffected by the v1 deletion.
Not merging -- please review.