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: v1initializewith at-or-below negotiation, newline-delimited JSON-RPC framing, stdout-only protocol bytes, stderr diagnostics, batch rejection, unknown-method rejection before dispatch, andrealm/toolcarrying the ToolCall map unchanged todispatcher.calltest/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:
- 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) - 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) - Task 3: Session lifecycle drive with dispatcher-equal outcomes (TOOL-05) —
test/acp/agent.test.tsonly (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 logictest/acp/agent.test.ts— Nine TOOL-05 cases driving the adapter over PassThrough streams against makeHarness
Decisions Made
realm/toolparams envelope is{ tool: ToolCall }(plan discretion: exact envelope layout, carrying the whole map unchanged). The replyresultis 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 >= 1selects 1 (highest supported at or below the request); lower or non-integer values get-32602. - Tests wait on stream
dataevents via registered waiters with per-testtimeout: 10_000guards; no wall-clock sleeps.new Promiseexecutor form is used because the tsconfig lib (ES2023) predatesPromise.withResolvers(ES2024). - The module-local
isRecordguard follows the existingsrc/runtime/hardening.ts/src/runtime/libpod-client.tsprecedent 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/toolreachesdispatcher.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.tsreferences no guarded symbol and calls no dispatcher member exceptcall. - 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