Skip to content

test(cli): subprocess integration tests for opencode acp#28265

Open
kitlangton wants to merge 2 commits into
devfrom
worktree-cli-acp-builder
Open

test(cli): subprocess integration tests for opencode acp#28265
kitlangton wants to merge 2 commits into
devfrom
worktree-cli-acp-builder

Conversation

@kitlangton
Copy link
Copy Markdown
Contributor

@kitlangton kitlangton commented May 19, 2026

Summary

Adds the second long-lived-command builder to the cli-process harness:
opencode.acp(opts) spawns the real CLI in JSON-RPC-over-stdio mode and
returns a duplex handle (send/receive/close/exited) scoped to the
test's lifetime. Stdin EOF triggers a clean shutdown; the scope finalizer
falls back to SIGTERM after 2s for a hung child.

ACP frames each JSON-RPC message as one ndjson line on stdout. The builder
forks a scope-bound Stream.fromReadableStream + splitLines pipeline that
feeds parsed responses into a Queue.unbounded, so tests can yield* acp.receive
without worrying about backpressure or framing.

Two smoke tests:

  • `initialize` round-trip — sends the protocol handshake from `src/acp/README.md` and asserts the response advertises the same protocolVersion and a non-empty agentCapabilities block.
  • Clean shutdown on stdin EOF — proves the scope finalizer's `stdin.end()` triggers a graceful exit, not a SIGTERM-fallback exit.

Why this matters

Nothing currently exercises the ACP stdin/stdout protocol end-to-end. A regression that broke the framing, the handshake, the agent capabilities block, or the stdin-EOF clean-shutdown path would slip through every other test tier. The handshake test alone catches a huge class of "ACP doesn't even start" regressions that today only manifest when a user wires up an editor integration and it fails silently.

Stacked on #28263

This branches off the serve-builder branch since auto-merge on #28263 is still waiting on Windows checks. Once #28263 merges, the diff here shrinks to just the acp changes (the serve changes will already be in dev).

Test plan

  • `bun run test test/cli/acp/acp-process.test.ts` — 2/2 pass locally in ~4s
  • `bun run test test/cli/` — 323/323 pass, no regressions
  • `bun run typecheck` clean

Stack

  1. test(cli): subprocess integration tests for opencode acp #28265 👈 current
  2. test(cli): help-text snapshots for every CLI command #28267

Adds the second long-lived-command builder to the cli-process harness:
`opencode.acp(opts)` spawns the real CLI in JSON-RPC-over-stdio mode
and returns a duplex handle (`send`/`receive`/`close`/`exited`) scoped
to the test's lifetime. Stdin EOF triggers a clean shutdown; the scope
finalizer also falls back to SIGTERM after 2s for a hung child.

ACP frames each JSON-RPC message as one ndjson line on stdout. The
builder forks a scope-bound `Stream.fromReadableStream` + `splitLines`
pipeline that feeds parsed responses into a `Queue.unbounded`, so tests
can `yield* acp.receive` without worrying about backpressure or framing.

Two smoke tests:
- `initialize` round-trip — sends the protocol handshake from the ACP
  README and asserts the response advertises the same protocolVersion
  and a non-empty agentCapabilities block.
- Clean shutdown on stdin EOF — proves the scope finalizer's stdin.end()
  triggers a graceful exit, not a SIGTERM-fallback exit.
Replaces raw Promise.race + setTimeout in the acp builder's release
finalizer with an Effect.gen that expresses the graceful-then-SIGTERM
race using Effect.timeoutOrElse(Duration.seconds(2)). Same behavior,
no leaked timer, consistent with the serve builder.
@kitlangton kitlangton force-pushed the worktree-cli-acp-builder branch from e38f49f to 8513472 Compare May 19, 2026 01:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant