From 2773ab600d9a4862d72cab99cbd25d552ca391ea Mon Sep 17 00:00:00 2001 From: Kevin Nguyen Date: Wed, 29 Jul 2026 22:49:15 +0700 Subject: [PATCH] =?UTF-8?q?CB-402:=20live=20dogfood=20complete=20=E2=80=94?= =?UTF-8?q?=20Stage=20B=20verified=20against=20opencode=201.18.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the one known-unverified item before cross-host. CB-402 merged in ded226a with increment 5 (the §5 live checklist) deferred; it has now run. Provider question (§7 Q1) resolved with no credentials needed: opencode's own gateway serves free-tier models. `opencode auth list` reports 0 credentials, yet `opencode run -m opencode/north-mini-code-free` answers. Distinct from the primary's subscription by construction, and needs no guard entry — opencode carries no ANTHROPIC_BASE_URL, so SubscriptionGuard never applies to it. The schema-drift risk was the real one and it did not bite. The adapter was designed against opencode 1.1.31; installed is 1.18.5. The generated config still validates unchanged (type:"remote" + instructions:[path]), and `OPENCODE_CONFIG=… opencode mcp list` reports the bridge connected. Pinned as a verified fact for 1.18.5. Full lifecycle through REST: spawn (201, kind-routed to OpenCodeLauncher) -> CB-306 gate passed ~0.6s -> ready -> send -> {"replySource":"reply"} (a STRUCTURED bridge_reply, not the CB-115 completion fallback) -> delete (204, tolerant teardown). Unplanned cross-validation with CB-501: the audit trail recorded the reply as role=WORKER actor=worker:term_657c… — connection-based identity classified an opencode process as a worker with no opencode-specific handling. The identity model is peer-kind-agnostic, which is what CB-308 needs when the roster stretches across hosts. Stage 5 verified live on the same run: /workers (CB-304) answers where the 13-day-old daemon 404'd, /metrics counted the delegation (sends_total{outcome=replied} 1, replies_total{path=rendezvous} 1, inbox_depth 0), and the audit log captured SPAWN/SEND/REPLY with correct roles. Adds the opencode-free dogfood profile to the local bridged.yaml (gitignored; recorded here for reproducibility) and docs/CB-402 §8 as-built. --- docs/CB-402-OpenCode-Adapter.md | 64 ++++++++++++++++++++++++++------- wiki | 2 +- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/docs/CB-402-OpenCode-Adapter.md b/docs/CB-402-OpenCode-Adapter.md index 0c1a0fd..45cba8b 100644 --- a/docs/CB-402-OpenCode-Adapter.md +++ b/docs/CB-402-OpenCode-Adapter.md @@ -1,11 +1,8 @@ # CB-402 — Second peer adapter: opencode (Stage B of the Peer Launcher SPI) -**Status:** ✅ **implemented and merged** (`ded226a`) — increments 1–4 of §4 all landed -(`HerdrPeerLauncher` base, `kind:` discriminator, `OpenCodeLauncher`, `CompositePeerLauncher`). -⚠️ **Increment 5 — the live dogfood (§5) — has NOT run.** It was deferred at merge time pending a -daemon restart and a resolved provider, and §7 Q1 (which provider this host has credentials for) is -still open; `opencode` is not installed on the dev host. Gitea issue #7 stays open until the §5 -checklist is executed. This is the single known-unverified item going into the cross-host stage. +**Status:** ✅ **complete — implemented, merged (`ded226a`), and live-dogfooded 2026-07-29.** +All five increments of §4 are done, including increment 5 (the §5 live checklist). See +[§8 As-built](#8-as-built--live-dogfood-2026-07-29) for the run. Gitea issue #7 closed. **Depends on:** CB-401 Stage A (`PeerLauncher` SPI, merged `3aa69a9`) **Stage:** 4 (Pluggable peers) · Stage B **Owner action:** design-note → file issue → delegate → primary-verify (per CB-401/306/307) @@ -258,10 +255,51 @@ until it is "major" (Stage-B whole), per the CB-401 bar. ## 7. Open questions for the lead -1. **Provider for the opencode dogfood profile** — which provider/model does this host have - credentials for that is distinct from the primary's subscription? -2. **Charter carrier** — generated `OPENCODE_CONFIG` `instructions` (recommended) vs an - `AGENTS.md` in the worktree? -3. **Merge cadence** — hold the whole Stage B on a feature branch to merge as one "major" - unit (per CB-401), or land the behaviour-preserving base-extraction (increment 1) to `main` - first to shrink the branch? +1. ✅ **Provider — resolved 2026-07-29.** None was needed. opencode's own gateway serves + **free-tier models with zero credentials** (`opencode auth list` → *0 credentials*, yet + `opencode run -m opencode/north-mini-code-free` answers). The dogfood profile uses + `opencode/north-mini-code-free`. It is distinct from the primary's Anthropic subscription by + construction, and needs no `guard` entry — opencode carries no `ANTHROPIC_BASE_URL`, so the + `SubscriptionGuard` does not apply to it at all. +2. ✅ **Charter carrier — confirmed as designed:** generated `OPENCODE_CONFIG` `instructions`. + Verified working against the installed version. +3. ✅ **Merge cadence — resolved as it happened:** Stage B landed as one unit (`ded226a`). + +--- + +## 8. As-built — live dogfood (2026-07-29) + +Run against `bridged` on `127.0.0.1:8766` at main `19cdf8d`, with opencode **1.18.5** installed +via Homebrew. Every §5 risk is now a verified fact rather than an assumption. + +**The version-drift risk was the real one, and it did not bite.** This adapter was designed against +opencode **1.1.31**; the installed version is **1.18.5**. The generated config schema still +validates unchanged — `mcp..type: "remote"`, `url`, `enabled`, and `instructions: [path]` are +all accepted, and `OPENCODE_CONFIG=… opencode mcp list` reports `✓ bridge connected`. Pinned here +as a dogfood-verified fact for 1.18.5. + +| §5 risk | Result | +|---|---| +| opencode TUI ⇄ herdr injection; CB-306 gate | ✅ `peer pane=wD:p3 reached injectable state` ~0.6s after `agent.start` | +| Bridge MCP visible + `bridge_reply` callable | ✅ MCP `initialize` from `Implementation[name=opencode, version=1.18.5]`; worker replied through the tool | +| Config schema drift (1.1.31 → 1.18.5) | ✅ unchanged, see above | +| Provider credentials | ✅ free tier, zero credentials | + +Full lifecycle exercised through the REST surface: + +1. `POST /workers?profile=opencode-free` → `201`, routed by `kind:` through `CompositePeerLauncher` + to `OpenCodeLauncher` (`spawning opencode profile=opencode-free`), pane `wD:p3`. +2. Readiness: `{"ready":true,"status":"idle"}`, roster state `ready`. +3. `POST /sessions/{id}/message` → **`{"replySource":"reply","reply":"391"}`** — a *structured* + `bridge_reply`, not the CB-115 completion-fallback transcript scrape. The clean path. +4. `DELETE /workers/wD:p3` → `204`, roster empty, tolerant teardown (`tab_not_found` ignored — + opencode had already closed its own tab). + +**Unplanned cross-validation with CB-501.** The audit trail recorded the worker's reply as +`role: WORKER, actor: worker:term_657c1dad2b9731e, action: REPLY, outcome: allowed`. Connection-based +identity (loopback peer PID → herdr pane) classified an **opencode** process as a worker with no +opencode-specific handling — confirming the identity model is peer-kind-agnostic, which is exactly +what CB-308 needs when it stretches the roster across hosts. + +CB-502 counters for the same run: `bridged_sends_total{outcome="replied"} 1`, +`bridged_replies_total{path="rendezvous"} 1`, `bridged_inbox_depth{...} 0`. diff --git a/wiki b/wiki index ef3e68a..f4af2a1 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit ef3e68a4004af226da49c5c4b350a3d0a59d92d1 +Subproject commit f4af2a1c22ef226b994b61bd02cc41feb219762f