Skip to content

feat: surface.wait — server-owned pattern/exit waits on the socket - #172

Merged
arzafran merged 4 commits into
mainfrom
feat/166-surface-wait
Jul 21, 2026
Merged

feat: surface.wait — server-owned pattern/exit waits on the socket#172
arzafran merged 4 commits into
mainfrom
feat/166-surface-wait

Conversation

@arzafran

Copy link
Copy Markdown
Member

What this does

Agents no longer poll read_text to know when a sibling surface is done. surface.wait blocks (with timeout) server-side until output matches a pattern or the child process exits, answering in one round trip with a no-missed-events guarantee (condition check + watcher install happen in a single main-queue hop).

Scope is task 1 of #166: pattern + exit conditions, wait-surface CLI verb, socket docs, tests_v2 coverage. Agent-state waits and agent.prompt follow once #164's state model lands.

Review order

  1. Sources/TerminalController+SurfaceWait.swift — registry + wait implementation (threading rationale in the header comment)
  2. CLI/programa.swiftwait-surface verb + client minimumReceiveTimeout so long waits survive the 15s default read timeout
  3. docs/v2-api-migration.md, tests_v2/test_surface_wait.py

Test plan

  • programa and programa-cli schemes build
  • tests_v2 subset on CI (runs on main post-merge per landing plan)

Refs #166

arzafran added 4 commits July 21, 2026 16:38
Server-owned, event-driven wait on a terminal surface: block the calling
socket connection (with a timeout) until output matches a regex pattern
or the surface's child process exits, in one request/response round trip
instead of the caller polling surface.read_text in a loop.

- exit is fully event-driven, hooked off the existing
  GHOSTTY_ACTION_SHOW_CHILD_EXITED action via a new SurfaceExitWaitRegistry
- pattern polls the surface's live text on a short internal timer (Ghostty
  has no push-based content-changed callback); still a single call from the
  caller's perspective
- the already-satisfied check and watcher install happen in one main-thread
  hop, so a marker printed (or a process exit) racing the call can't be missed
- each socket connection runs on its own thread, so blocking for the wait's
  duration never stalls main or other connections
@arzafran
arzafran merged commit 0870ad4 into main Jul 21, 2026
3 checks passed
@arzafran
arzafran deleted the feat/166-surface-wait branch July 21, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant