Skip to content

Interactive run transport pillar 4: opencode ACP — live local-model switching; milestone complete - #7

Merged
njfife merged 9 commits into
mainfrom
worktree-opencode-transport-p4
Jul 9, 2026
Merged

Interactive run transport pillar 4: opencode ACP — live local-model switching; milestone complete#7
njfife merged 9 commits into
mainfrom
worktree-opencode-transport-p4

Conversation

@njfife

@njfife njfife commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Summary

The final transport pillar: opencode runs become interactive, putting all four providers (copilot, codex, claude, opencode) on the TransportSession seam. opencode speaks standard ACP, so pillar 1's AcpSession gained a small provider profile instead of a fourth session class — copilot behavior stays bit-identical (test-pinned), opencode opts into the extras.

  • Live per-session model switching over ACP (session/set_config_option), hosted ↔ LM Studio local models, no respawn — the SUPER-HARD local-model requirement's interactive leg, verified end-to-end on real hardware: a hosted turn planted a codeword, the chat switched to a local qwen3.6-27b mid-conversation (through a killed-child recovery + session/load), and the local model recalled it.
  • Native live metering: usage_update drives the context bar with the real window size and real cost; agent_thought_chunk renders the thinking row.
  • Fail-honest everywhere: a completed turn with zero text + zero output tokens (unloaded local model) renders a notice row instead of a fake success; zero-output completions no longer record works in the capability ledger (isWorksEvidence); set_config_option errors fail open (turn proceeds on the harness's current model) with the attribution gap explicitly ledgered in DECISIONS.
  • Cancel intent is remembered session-side (opencode reports end_turn after session/cancel) — live-verified rescuing a turn hung on a dead LM Studio backend, with the interrupted gate correctly suppressing the empty-turn notice.
  • Permission cards surface for outside-cwd writes with opencode's own options (verified approve→file on disk).
  • Riders from the pillar-3 review: JsonRpcClient dead-stdin write guards + stdin error listener, claude array-form tool_result detail, FRESH_VERIFY_MS 500→1000ms.

Live verification (computer-use matrix)

hosted turn (real 200K window, thinking row) / local turn / hosted→local mid-chat switch with context intact / permission card approve / hung-backend rescue via Stop / continuity / restart revival / fallback + recovery (one-shot -s resume kept context) / copilot regression smoke. Live-caught extras: set_config_option -32602 fail-open verified against a real rejection; LM Studio serves the loaded model for any requested id (recorded); opencode's built-in lmstudio catalog is static registry defaults (env quirk, follow-up noted).

Review

Whole-branch review: "with fixes" → the ledger false-works finding fixed (isWorksEvidence, RED→GREEN tests) with the fail-open half explicitly deferred + ledgered; re-review: ready to merge. One task-level fix loop earlier (thinking row force-closed on errored turns).

Spec: docs/superpowers/specs/2026-07-09-interactive-transport-pillar4-opencode-design.md · Plan: docs/superpowers/plans/2026-07-09-interactive-transport-pillar4-opencode.md

🤖 Generated with Claude Code

Nathan Font-Fife and others added 9 commits July 9, 2026 14:34
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…il; FRESH_VERIFY_MS 1000

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ures

- Add THINKING_ROW_PREFIX export for reasoning tool rows
- Add usageUpdateCost() to extract cost.amount from usage_update events
- Extend mapAcpUpdate with optional provider param (copilot | opencode)
- Add usage_update case: maps to usage.updated with contextUsedTokens and contextWindow
- Add agent_thought_chunk case: maps to a running thinking tool row
- Copilot profile returns [] for both opencode-only kinds (bit-identical behavior)
- Create docs/research/opencode-acp-1.17.11.txt with live-captured frames

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tent, empty-turn notice

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… transport seam

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e; milestone complete

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…RIFY_MS rationale; attribution-gap note

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 9, 2026 21:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Completes the interactive transport “pillar 4” by bringing opencode onto the existing TransportSession seam via a provider-profiled AcpSession, enabling interactive local/hosted model switching and opencode-specific ACP update handling while keeping copilot’s ACP behavior unchanged by default.

Changes:

  • Extend AcpSession with a provider profile (copilot vs opencode) to support opencode’s ACP extras (usage/cost updates, thinking row, per-session model switching, empty-turn notice, cancel-intent mapping).
  • Route opencode through the interactive-first transport path (with one-shot fallback) and tighten capability-ledger “works” evidence to exclude zero-output completions when usage indicates no output.
  • Harden JSON-RPC writes against dead stdin, and improve Claude tool result detail extraction for array-form payloads; adjust Claude fresh-spawn verify timing.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/main/runtime/ipc.ts Adds opencode to interactive-first routing and adjusts capability-ledger “works” stamping via isWorksEvidence.
src/main/runtime/capabilities/ledger.ts Introduces isWorksEvidence to avoid recording “works” on zero-output completions with explicit usage.
src/main/runtime/capabilities/ledger.test.ts Adds unit coverage for isWorksEvidence behavior.
src/main/runtime/capabilities/jsonRpc.ts Adds stdin error listener and centralizes guarded writes to avoid EPIPE crashes on dying children.
src/main/runtime/capabilities/jsonRpc.test.ts Adds regression tests for notify-after-exit no-op and stdin error listener registration.
src/main/runtime/acp/sessionManager.ts Expands provider union to include opencode and instantiates AcpSession with OPENCODE_PROFILE.
src/main/runtime/acp/mapClaude.ts Extracts tool result detail from Claude array-form tool_result.content.
src/main/runtime/acp/mapClaude.test.ts Adds fixture test for array-form tool_result detail extraction.
src/main/runtime/acp/mapAcp.ts Adds opencode-gated mappings (usage_update, agent_thought_chunk) plus helpers for cost/thinking row ID.
src/main/runtime/acp/mapAcp.test.ts Adds tests covering opencode-only ACP update mappings and cost extraction helper.
src/main/runtime/acp/claudeSession.ts Increases FRESH_VERIFY_MS to 1000ms for cold-start headroom.
src/main/runtime/acp/claudeSession.test.ts Updates constant expectation for FRESH_VERIFY_MS.
src/main/runtime/acp/acpSession.ts Implements provider-profiled ACP session: opencode spawn profile, model switching via session/set_config_option, cancel-intent mapping, thinking row lifecycle, cost capture, and empty-turn notice.
src/main/runtime/acp/acpSession.test.ts Adds tests for profile constants and empty-turn notice predicate.
docs/superpowers/specs/2026-07-09-interactive-transport-pillar4-opencode-design.md Documents the verified opencode ACP surface and the provider-profile approach.
docs/superpowers/plans/2026-07-09-interactive-transport-pillar4-opencode.md Captures the full implementation plan and fixture frames used to drive changes/tests.
docs/research/opencode-acp-1.17.11.txt Adds the live-captured opencode ACP frames referenced by tests/spec.
docs/DECISIONS.md Records pillar 4 completion details, known attribution gap, and roadmap status update.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@njfife
njfife merged commit 32c1886 into main Jul 9, 2026
1 check passed
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.

2 participants