Skip to content
Merged
4 changes: 3 additions & 1 deletion docs/DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

## Current phase

**✅ Interactive run transport — pillar 4, opencode ACP** (`2e7fe3a` + live fixes): opencode runs are INTERACTIVE — the LAST pillar; every provider now runs on the TransportSession seam. opencode speaks standard ACP (`opencode acp`), so pillar 1's AcpSession gained a provider PROFILE instead of a fourth class: shared streaming/tool-rows/permissions/cancel/revival, plus opencode-gated extras — usage_update drives the live context bar with the REAL window size (200K/262K observed live) and real cost, agent_thought_chunk renders the thinking row. HEADLINE: per-session model switching over ACP via session/set_config_option (configId 'model'), hosted ↔ LM Studio LOCAL models, live, no respawn — the SUPER-HARD local-model requirement's interactive leg, verified end-to-end (hosted turn → switch → local qwen3.6-27b recalled the hosted turn's codeword, through a killed-child recovery + session/load). Cancel intent is remembered session-side (opencode reports end_turn after session/cancel) — verified live rescuing a turn hung on a dead LM Studio backend, and the interrupted gate correctly suppressed the empty-turn notice. Fail-honest: a completed turn with zero text and zero output tokens (unloaded local model) renders a notice row instead of a fake success (probe-fixture + unit-tested; live re-trigger impossible while ANY model is loaded — LM Studio serves the loaded model for any requested id, recorded). set_config_option fail-open verified live (-32602 on uncataloged id → turn proceeds on the harness's current model). Known attribution gap (deferred): a fail-open model switch runs on the harness's CURRENT model but the ledger attributes the outcome to the REQUESTED model — fix rides with the no-fake-pixels sweep (needs the session to surface applied-model truth). Zero-output completions no longer record 'works' (isWorksEvidence). Permission cards surface for outside-cwd writes (external_directory, opencode's own options); cwd writes auto-allow per opencode's defaults. Riders landed: JsonRpcClient dead-stdin guards, claude array-form tool_result detail, FRESH_VERIFY_MS→1000ms. Copilot regression smoke green (shared class). Env quirk worth a follow-up: opencode's built-in lmstudio catalog is static registry defaults (no live localhost scan) — a local `lmstudio-local` provider entry in opencode.json (added with owner approval, backup kept) exposes actually-loaded models. Spec: `docs/superpowers/specs/2026-07-09-interactive-transport-pillar4-opencode-design.md`. **The interactive-transport roadmap item is COMPLETE.**

**✅ Interactive run transport — pillar 3, claude stream-json** (`949cddb`): claude runs are INTERACTIVE — token streaming via stream_event deltas, permission cards built from claude's own can_use_tool requests INCLUDING its permission_suggestions ("Allow edits for session" = setMode acceptEdits echoed back verbatim via updatedPermissions — live-verified to suppress the next same-mode prompt), tool rows from tool_use/tool_result blocks, Stop = control_request interrupt (error_during_execution signature → canceled), YOLO = live set_permission_mode with the spawn carrying --allow-dangerously-skip-permissions (verified both directions on ONE child PID — no respawn). Long-lived `claude --print --input/output-format stream-json --permission-prompt-tool stdio` child per chat behind the same TransportSession seam via a new StreamJsonClient (typed frames — claude is NOT JSON-RPC). Revival: --resume fast-fails (~1.3s) on bogus ids → connect races a 2s window and THROWS into the one-shot fallback (context doctrine); restart revival verified (no history replay). Model/effort are spawn-bound: mid-chat model switches respawn-with-resume transparently (verified Sonnet→Opus: new PID with --model opus --resume <id>, context intact). NEW surfaces: REAL cost (result.total_cost_usd → Inspector cost row accumulated real dollars) and live context metering (message_start/result usage → usage.updated). Riders landed: fallback turns demote contextLive (the `~` honesty marker returns — verified visible), and BOTH claude + codex watchdogs now measure inactivity, not turn duration. Verified live (computer-use matrix, all 10 items): approve / suggestion-escalation / deny (incl. claude's own acceptEdits + sandbox-safe semantics — no card when claude itself doesn't require one) / YOLO toggle / interrupt mid-stream / continuity / restart revival / model-switch respawn / fallback + ~ return + recovery / real cost + live context + thinking row (appears, collapses). Live verification caught one real bug the 165-test suite could not: claude's tool_result completions carry no title and the upsertTool spread erased the running row's title (fixed 949cddb). Spec: `docs/superpowers/specs/2026-07-09-interactive-transport-pillar3-claude-design.md`.

**✅ Interactive run transport — pillar 2, codex app-server** (`636ebe7`): codex runs are INTERACTIVE with TOKEN STREAMING (item/agentMessage/delta — no more single-blob replies). Per-chat `codex app-server` session behind the same TransportSession seam (thread/start|resume → turn/start per send; run resolves on the turn/completed notification with a 30-min watchdog). Approvals render as permission cards built from the server's own availableDecisions (accept / acceptForSession / execpolicy-amendment / cancel — echoed verbatim, NAC invents nothing); fileChange rows carry per-change diff text (live-probed: the diff lives on `changes[]`, not the item); Stop = turn/interrupt. Per-turn model+effort ARE honored (unlike copilot's pillar-1 limitation) so codex ledger verdicts stay live. NEW: real token metering — thread/tokenUsage/updated drives a genuinely live Inspector context bar for codex chats (contextK/windowK stop being estimates; the `~` drops). Fallback floor: one-shot codexArgs path incl. `codex exec resume` for revival failures, with a render-only notice row; the chat recovers to interactive on the next send. Verified live (computer-use matrix): approval options / deny / streaming / interrupt / continuity / restart revival (no history double-append — the `replaying` guard holds) / fallback + recovery / diff-on-expand / real context numbers (claude chats keep the `~`). Live verification caught three real bugs the suite could not: declined items report `status:'declined'` (rendered ✓ as if run), Stop left the interrupted command's row spinning forever (endTurn now sweeps open rows to failed), and the fileChange diff field didn't exist where the mapper looked. Spec: `docs/superpowers/specs/2026-07-09-interactive-transport-pillar2-codex-design.md`.
Expand Down Expand Up @@ -51,7 +53,7 @@
- ✅ **Pillar 1 — copilot ACP** (PR #3/#4, merged): permission cards, tool rows, real cancel, native + restart continuity, replay-clean. Live-verified.
- ✅ **Pillar 2 — codex app-server**: token streaming, server-defined approval cards, diff-carrying edit rows, turn/interrupt, real token metering. Live-verified.
- ✅ **Pillar 3 — claude stream-json**: streaming, suggestion-derived permission cards, live YOLO mode-switching, respawn-with-resume model switches, real cost + live context. Live-verified.
- **Pillar 4 — opencode acp** (next; last pillar).
- **Pillar 4 — opencode acp**: provider-profiled AcpSession, live model switching incl. LM Studio locals, real window+cost, thinking rows. Live-verified. **Milestone complete — all four providers interactive.** Next roadmap item: #2 no-fake-pixels sweep.
2. **No-fake-pixels sweep** — remove seed demo chats on fresh state; real Inspector context-window/cost rows (contextK + $0.42 are fake); agent picker wiring (`--agent`); closes M0-5 error/empty states.
3. **Context library polish** — edit notes; mid-conversation re-seed on attachment change; per-harness-native injection.
4. **Packaging** (electron-builder) — after #1 makes daily-driving real. Known constraint: registry/adapters assume PATH access, which Finder-launched packaged apps don't inherit.
Expand Down
10 changes: 10 additions & 0 deletions docs/research/opencode-acp-1.17.11.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
opencode 1.17.11 ACP frames, live-captured 2026-07-09

{"sessionId":"ses_0b781c29cffeuHhwhwfFSxeRlQ","configOptions":[{"id":"model","name":"Model","category":"model","type":"select","currentValue":"opencode/big-pickle","options":[{"value":"lmstudio/qwen/qwen3-coder-30b","name":"LMStudio/Qwen3 Coder 30B"}]}]}
{"sessionUpdate":"agent_message_chunk","messageId":"msg_1","content":{"type":"text","text":"Created"}}
{"sessionUpdate":"agent_thought_chunk","messageId":"msg_2","content":{"type":"text","text":"The user wants me"}}
{"sessionUpdate":"tool_call","toolCallId":"call_c95bdab20b584813b28ef777","title":"write","kind":"edit","status":"pending","locations":[],"rawInput":{}}
{"sessionUpdate":"tool_call_update","toolCallId":"call_c95bdab20b584813b28ef777","status":"in_progress","kind":"edit","title":"write","locations":[{"path":"/tmp/p4/p4-check.txt"}],"rawInput":{"content":"okra","filePath":"/tmp/p4/p4-check.txt"}}
{"sessionUpdate":"usage_update","used":11524,"size":200000,"cost":{"amount":0,"currency":"USD"}}
{"sessionUpdate":"available_commands_update","availableCommands":[]}
{"stopReason":"end_turn","usage":{"inputTokens":196,"outputTokens":15,"totalTokens":11552,"thoughtTokens":13,"cachedReadTokens":11328}}
Loading