diff --git a/docs/opencode-fork-decision.md b/docs/opencode-fork-decision.md index d1669fef..14f4ab4b 100644 --- a/docs/opencode-fork-decision.md +++ b/docs/opencode-fork-decision.md @@ -5,7 +5,8 @@ > The conclusion is reversed below. The mistake is written up rather than deleted, because the shape of > it is the useful part. -**Decision: the fork is worth taking. Not started, and gated on one open question.** +**Decision: the fork is worth taking, and it is no longer blocked.** Not started; the blocker turned out +to be a missing credential and is fixed — see RESOLVED below. --- @@ -41,7 +42,47 @@ Steer and queue are exactly the two features we hand-built for Claude and that A changer. Having them as primitives, plus a resumable per-session cursor that mirrors officer's durable replay, is a strong argument for migrating. -## The blocker, now characterised: only free models run +## RESOLVED — it was a missing credential, not a bug + +Andre said he had a paid Zen key working in his terminal and suggested it simply was not set up here. He +was right, and this is the second wrong conclusion I reached on this page. + +**The new pipeline has its own credential store, separate from `auth.json`.** `opencode run`, the CLI and +the legacy `/session` surface all read `~/.local/share/opencode/auth.json`, which holds the Zen key — so +they reach paid models. The `/api/*` surface reads integrations instead (`/api/integration`, +`/api/credential`), and ours had **none connected**. With no credential it silently fell back to what +needs none, which is exactly the free tier. + +The fix was one call, and it persists across a serve restart (verified — a paid model still ran after +`pm2 restart officer-opencode`): + +``` +POST /api/integration/opencode/connect/key { "key": "", "label": "…" } → 204 +``` + +Afterwards `claude-sonnet-4-6` and `claude-haiku-4-5` both run on the new pipeline. **The fork is +unblocked**, and everything the table above promises — steer, queue, interrupt, resumable per-session +SSE — is available with real models. + +Two consequences worth carrying: + +- **alpha needs the same one-time connect** before it can use the new pipeline. +- The sidecar should do this itself at boot rather than relying on someone having run it by hand, since + a missing credential degrades to "only free models work" with no error anywhere. + +### What the evidence looked like while I was getting it wrong + +Recorded because the shape repeats: the failure was **silent and total** for paid models, and the cost +table drew a perfect line — every cost-0 model ran, every cost>0 model did not. I read that as a billing +boundary inside a broken pipeline. It was a billing boundary caused by an absent credential, which is a +far more ordinary explanation and one Andre reached from knowing his own setup rather than from the API. + +The tell I had and did not use: the configured default is `opencode/big-pickle`, and a session created +with no model ran on `ling-3.0-tiny-free` **instead of the default**. A pipeline ignoring its configured +default is a pipeline that cannot use it — that is a credential symptom, and it was sitting in the +`/config/providers` output the whole time. + +## The original diagnosis, kept for the record: only free models run It is not sonnet, and it is not `variant`. Swept four models through `POST /api/session/{id}/model` followed by a prompt: diff --git a/docs/opencode-parity.md b/docs/opencode-parity.md index a4e28387..669f9370 100644 --- a/docs/opencode-parity.md +++ b/docs/opencode-parity.md @@ -91,7 +91,7 @@ is gone. What remains is bucket 1 — capabilities Claude has and OpenCode does visible ones (token streaming, mid-turn injection, background tasks, interrupt-without-teardown) are downstream of `stdin: 'ignore'` and therefore of the Phase 2 fork. -**The fork is REOPENED and worth taking.** The serve publishes a newer `/api/session/*` surface offering +**The fork is REOPENED, unblocked, and worth taking.** The serve publishes a newer `/api/session/*` surface offering those capabilities natively, and on 1.18.16 **`delivery: "steer"` and `delivery: "queue"` are both verified working** — mid-turn injection and queueing, as primitives, plus `/interrupt` and a resumable per-session event stream. One blocker remains: `claude-sonnet-4-6` silently does not run on that surface