Skip to content

Phase 05 Plan 04: ACP v1 Stdio Adapter Summary ​

ACP v1 stdio agent with the realm/tool Realm extension routing all six ToolCall maps unchanged to ToolDispatcher.call, covered by nine TOOL-05 cases over in-memory streams

Performance ​

  • Duration: single execution session (no wall-clock tracking; verification gates owned by orchestrator)
  • Started: 2026-10-22
  • Completed: 2026-10-22
  • Tasks: 3
  • Files modified: 2 (both created)

Accomplishments ​

  • src/acp/agent.ts: v1 initialize with at-or-below negotiation, newline-delimited JSON-RPC framing, stdout-only protocol bytes, stderr diagnostics, batch rejection, unknown-method rejection before dispatch, and realm/tool carrying the ToolCall map unchanged to dispatcher.call
  • test/acp/agent.test.ts: nine TOOL-05 cases — v1 reply shape, never-batched lifecycle lines, close-on-stdin-end, six-tool unchanged routing, code-faithful refusals, unknown-method rejection, ordered lifecycle drive with dispatcher-equal outcomes, shared displayStatus label, required-mode refusal equality
  • No new npm dependency; package.json untouched

Task Commits ​

No commits were made in this execution: the shared constraints for this assignment forbid git commands, so per-task commits are owned by the orchestrator. Task-to-file mapping for the orchestrator to commit:

  1. Task 1: v1 initialize over stdio with the batch rule (P5-D3, P5-D10) — src/acp/agent.ts (framing, initialize, batch rule, lifecycle) + test/acp/agent.test.ts (initialize, batch, close cases)
  2. Task 2: realm/tool extension carrying the six tools (P5-D10, P5-D11) — src/acp/agent.ts (realm/tool branch) + test/acp/agent.test.ts (six-tool routing, refusal, rejection cases)
  3. Task 3: Session lifecycle drive with dispatcher-equal outcomes (TOOL-05) — test/acp/agent.test.ts only (drive, label, required-mode refusal cases; adapter module unchanged)

Files Created/Modified ​

  • src/acp/agent.ts — ACP v1 stdio agent; parses envelopes, answers initialize, routes realm/tool to ToolDispatcher.call; holds no tool logic
  • test/acp/agent.test.ts — Nine TOOL-05 cases driving the adapter over PassThrough streams against makeHarness

Decisions Made ​

  • realm/tool params envelope is { tool: ToolCall } (plan discretion: exact envelope layout, carrying the whole map unchanged). The reply result is the ToolOutcome itself, so refusals surface catalogue codes with no adapter-added mapping.
  • Batch arrays received on a line are rejected with -32600; sequential per-line handling guarantees one reply line per request line, which is what the never-batched test asserts.
  • Version negotiation: any integer protocolVersion >= 1 selects 1 (highest supported at or below the request); lower or non-integer values get -32602.
  • Tests wait on stream data events via registered waiters with per-test timeout: 10_000 guards; no wall-clock sleeps. new Promise executor form is used because the tsconfig lib (ES2023) predates Promise.withResolvers (ES2024).
  • The module-local isRecord guard follows the existing src/runtime/hardening.ts / src/runtime/libpod-client.ts precedent for parsing untrusted boundary bytes (stdin JSON, daemon replies).

Deviations from Plan ​

None - plan executed exactly as written. No auto-fixes, no architectural changes, no new files beyond the two the plan names.

Threat Flags ​

None beyond the plan's threat register. Implementation notes for the mapped mitigations:

  • T-05-07 (mitigate): only realm/tool reaches dispatcher.call, and the embedded map is passed as received; unknown methods, malformed lines, and batch arrays are rejected before any dispatch. Proven by the unknown-method/malformed-line case asserting zero dispatcher calls.
  • T-05-08 (accept): lifecycle messages are never batched; each request line yields exactly one reply line in order. Proven by the three-line batch-rule case and the ordered lifecycle drive.

Issues Encountered ​

None. Typecheck and tests were not run here (shared constraints forbid it); the orchestrator runs npx tsc -p tsconfig.json && node --test dist/test/acp/agent.test.js plus the TOOL-05 title grep as gates.

Stub Tracking ​

No stubs. No hardcoded empty values, placeholders, TODOs, or unwired data sources in either file.

User Setup Required ​

None - no external service configuration required.

Next Phase Readiness ​

  • Ready for plan 05-06 equivalence proof: the adapter returns the dispatcher's own ToolOutcome values, so MCP/ACP outcome equality compares directly after transport-envelope stripping.
  • Ready for the P5-D12 static no-logic guard: src/acp/agent.ts references no guarded symbol and calls no dispatcher member except call.
  • Live ACP client acceptance remains live-gated (OQ-P5-03), consistent with the phase verification boundary.

Phase: 05-omp-plugin-mcp-and-acp-surfacesCompleted: 2026-10-22

AGPL-3.0-only. Copyright (C) 2026 Spectrum Web Co/swcstudiospace.