docs(changelog): v2.6.7-interrupt-guard + reconcile roadmap/review/openspec
CHANGELOG entry for v2.6.7. Plus the session's doc reconciliation: roadmap shipped record synced through v2.6.7 (v2.3 lifecycle marked shipped, relicense AGPL->MIT batch, fork-sweep lift items, claude-agent-sdk SessionStore, ACP package fix); boocode_code_review_v2 (two fork sweeps, relicense decision = 3 AGPL files, jinja gate green); openspec v2-3 reconciled to shipped (v2.5.4-v2.5.13); openspec v2-6 Phase 0/1 + P1.5 shipped, F.1 done, remaining-phase plan + lift sources. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
Detailed implementation plan for Paseo-style provider registration, readiness probing, and enable/disable toggles in BooCoder.
|
||||
|
||||
> **✅ Shipped 2026-05-29 across `v2.5.4`–`v2.5.13` (reconciled 2026-05-31).** All 6 phases live. As-built deltas: the diagnostic ships as JSON `{ diagnostic: string }` (§6) rather than a plaintext HTTP body (§8's framing); the provider-management UI landed as a **Settings → Providers tab** (the §7.1 "or section under existing settings" path), not a standalone `ProviderSettingsDrawer`; `AddProviderModal` is at `apps/web/src/components/coder/`. **Deferred** (the §7.1 "optional phase 2" + tasks O.1–O.3): WS `provider_snapshot_updated` frame, `available_agents.enabled` column, diagnostic row-click modal — tracked in `docs/DEFERRED-WORK.md`.
|
||||
|
||||
**Audience:** Sam + future agents implementing the batch.
|
||||
**Paseo reference:** `/opt/forks/paseo/packages/server/src/server/agent/` (registry, snapshot manager, generic ACP), `/opt/forks/paseo/packages/app/src/screens/settings/providers-section.tsx` (UI behavior).
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# v2.3 Provider lifecycle (Paseo-style registry)
|
||||
|
||||
**Status:** Planned
|
||||
**Status:** ✅ **Shipped** across `v2.5.4`–`v2.5.13` (2026-05-29; reconciled 2026-05-31) — all 6 phases live; only the 3 optional Tier-2 items deferred
|
||||
**Depends on:** v2.2 Paseo providers (snapshot, modes, commands, ACP dispatch)
|
||||
**Reference fork:** `/opt/forks/paseo`
|
||||
**Related deferred work:** [`docs/DEFERRED-WORK.md`](../../../docs/DEFERRED-WORK.md) §2 (cold-probe skip)
|
||||
|
||||
> **Shipped mapping (reconciled 2026-05-31):** Phase 1 → `v2.5.4`, Phase 2 → `v2.5.5`, Phase 3 → `v2.5.6`, Phase 4 → `v2.5.12`, Phase 5 → `v2.5.13`, Phase 6 docs → `v2.5.13`/`v2.5.14`. **Deferred (tasks O.1–O.3):** WS `provider_snapshot_updated` frame, `available_agents.enabled` column, diagnostic row-click modal — tracked in `docs/DEFERRED-WORK.md`. (Cursor was retired in `v2.5.3`, so the success-criterion mention below is historical.)
|
||||
|
||||
## Why
|
||||
|
||||
BooCode v2.2 copied Paseo’s **snapshot wire shape** (modes, thinking, commands) but not Paseo’s **provider lifecycle**:
|
||||
@@ -46,12 +48,12 @@ Paseo’s model (see `/opt/forks/paseo/public-docs/providers.md`) treats provide
|
||||
|
||||
## Success criteria
|
||||
|
||||
- Add `amp-acp` via catalog → appears in picker after refresh without coder redeploy
|
||||
- Disable goose in settings → gone from picker, still visible as “Disabled” in settings
|
||||
- opencode not on PATH → shows “Not installed” in settings, hidden from picker
|
||||
- Second snapshot open within warm window completes in <500ms (no ACP spawns)
|
||||
- `POST /api/providers/refresh` still runs full cold probe
|
||||
- Existing v2.2 dispatch (cursor, opencode, claude, qwen) unchanged for built-ins
|
||||
- ✅ Add `amp-acp` via catalog → appears in picker after refresh without coder redeploy *(catalog smoke-test entry; per `boocode_code_review_v2.md` §5m, Amp itself is paid-cloud, not a usable local provider)*
|
||||
- ✅ Disable goose in settings → gone from picker, still visible as “Disabled” in settings
|
||||
- ✅ opencode not on PATH → shows “Not installed” in settings, hidden from picker
|
||||
- ✅ Second snapshot open within warm window completes in <500ms (no ACP spawns)
|
||||
- ✅ `POST /api/providers/refresh` still runs full cold probe
|
||||
- ✅ Existing v2.2 dispatch unchanged for built-ins *(opencode, claude, qwen, goose — cursor + copilot retired `v2.5.3`)*
|
||||
|
||||
## Deliverables
|
||||
|
||||
|
||||
@@ -2,70 +2,68 @@
|
||||
|
||||
Implement in phase order from [`design.md`](./design.md). Do not commit unless Sam asks.
|
||||
|
||||
## Phase 1 — Config + registry
|
||||
> **✅ SHIPPED across `v2.5.4`–`v2.5.13` (reconciled 2026-05-31).** All 6 phases done; the 3 Optional items (O.1–O.3) deferred (tracked in `docs/DEFERRED-WORK.md`). Verified in tree: `provider-config.ts`, `provider-config-registry.ts`, `command-availability.ts`, `provider-diagnostic.ts`, `acp-provider-catalog.ts`, `components/coder/AddProviderModal.tsx`, Settings→Providers tab.
|
||||
|
||||
- [ ] 1.1 Add `CODER_PROVIDERS_PATH` to `apps/coder/src/config.ts` (default `/data/coder-providers.json`)
|
||||
- [ ] 1.2 Add `data/coder-providers.json` example + wire in `apps/coder/.env.host`
|
||||
- [ ] 1.3 Implement `provider-config.ts` (Zod schema + load/merge/save)
|
||||
- [ ] 1.4 Implement `provider-config-registry.ts` (`buildResolvedRegistry`, module singleton + reload)
|
||||
- [ ] 1.5 Unit tests: built-in override, custom ACP add, enabled false, invalid entry skipped
|
||||
- [ ] 1.6 Update `agent-probe.ts` to iterate resolved registry (include custom ids, respect enabled)
|
||||
## Phase 1 — Config + registry — ✅ `v2.5.4-provider-lifecycle-phase1`
|
||||
|
||||
## Phase 2 — Snapshot lifecycle
|
||||
- [x] 1.1 Add `CODER_PROVIDERS_PATH` to `apps/coder/src/config.ts` (default `/data/coder-providers.json`)
|
||||
- [x] 1.2 Add `data/coder-providers.json` example + wire in `apps/coder/.env.host`
|
||||
- [x] 1.3 Implement `provider-config.ts` (Zod schema + load/merge/save)
|
||||
- [x] 1.4 Implement `provider-config-registry.ts` (`buildResolvedRegistry`, module singleton + reload)
|
||||
- [x] 1.5 Unit tests: built-in override, custom ACP add, enabled false, invalid entry skipped
|
||||
- [x] 1.6 Update `agent-probe.ts` to iterate resolved registry (include custom ids, respect enabled)
|
||||
|
||||
- [ ] 2.1 Extend `ProviderSnapshotEntry` / status union in coder + web types (`loading`, `unavailable`, `enabled`)
|
||||
- [ ] 2.2 Add `command-availability.ts` (`isCommandAvailable`)
|
||||
- [ ] 2.3 Rewrite `buildProviderEntry`: never return null; handle disabled/uninstalled/loading
|
||||
- [ ] 2.4 Implement tier-2 skip using `available_agents.last_probed_at` + `PROVIDER_PROBE_TTL_MS`
|
||||
- [ ] 2.5 Return `loading` entries synchronously on cache miss; complete via inflight promise
|
||||
- [ ] 2.6 Extend `provider-snapshot.test.ts` for disabled, uninstalled, fresh DB skip, force refresh
|
||||
- [ ] 2.7 Verify warm cache: second snapshot call does not invoke `probeAcpProvider` (mock assert)
|
||||
## Phase 2 — Snapshot lifecycle — ✅ `v2.5.5-provider-lifecycle-phase2`
|
||||
|
||||
## Phase 3 — Generic dispatch
|
||||
- [x] 2.1 Extend `ProviderSnapshotEntry` / status union in coder + web types (`loading`, `unavailable`, `enabled`)
|
||||
- [x] 2.2 Add `command-availability.ts` (`isCommandAvailable`)
|
||||
- [x] 2.3 Rewrite `buildProviderEntry`: never return null; handle disabled/uninstalled/loading
|
||||
- [x] 2.4 Implement tier-2 skip using `available_agents.last_probed_at` + `PROVIDER_PROBE_TTL_MS`
|
||||
- [x] 2.5 Return `loading` entries synchronously on cache miss; complete via inflight promise *(client-side poll deferred to Phase 5; cache miss returns `loading` then settles)*
|
||||
- [x] 2.6 Extend `provider-snapshot.test.ts` for disabled, uninstalled, fresh DB skip, force refresh
|
||||
- [x] 2.7 Verify warm cache: second snapshot call does not invoke `probeAcpProvider` (mock assert)
|
||||
|
||||
- [ ] 3.1 Add `resolveLaunchSpec()` to `acp-spawn.ts`
|
||||
- [ ] 3.2 Wire `acp-dispatch.ts` to use launch spec + env merge
|
||||
- [ ] 3.3 Wire `dispatcher.ts` to load resolved def by agent name
|
||||
- [ ] 3.4 Unit test: custom command argv reaches spawn
|
||||
- [ ] 3.5 Smoke: task dispatch for one custom catalog provider (if installed on host)
|
||||
## Phase 3 — Generic dispatch — ✅ `v2.5.6-provider-lifecycle-phase3`
|
||||
|
||||
## Phase 4 — HTTP API
|
||||
- [x] 3.1 Add `resolveLaunchSpec()` to `acp-spawn.ts`
|
||||
- [x] 3.2 Wire `acp-dispatch.ts` to use launch spec + env merge
|
||||
- [x] 3.3 Wire `dispatcher.ts` to load resolved def by agent name
|
||||
- [x] 3.4 Unit test: custom command argv reaches spawn (built-in dispatch byte-identical)
|
||||
- [x] 3.5 Smoke: task dispatch for one custom catalog provider (if installed on host)
|
||||
|
||||
- [ ] 4.1 `GET /api/providers/config`
|
||||
- [ ] 4.2 `PATCH /api/providers/config` (merge + write file + reload registry + clear snapshot cache)
|
||||
- [ ] 4.3 `POST /api/providers/refresh` optional body `{ providers?: string[] }`
|
||||
- [ ] 4.4 `GET /api/providers/:id/diagnostic` (plaintext report)
|
||||
- [ ] 4.5 Extend `apps/web/src/api/client.ts` coder namespace
|
||||
- [ ] 4.6 Confirm BooChat proxy forwards new routes (or document direct :9502)
|
||||
## Phase 4 — HTTP API — ✅ `v2.5.12-provider-lifecycle-phase4`
|
||||
|
||||
## Phase 5 — Web UI
|
||||
- [x] 4.1 `GET /api/providers/config`
|
||||
- [x] 4.2 `PATCH /api/providers/config` (merge + write file + reload registry + clear snapshot cache)
|
||||
- [x] 4.3 `POST /api/providers/refresh` optional body `{ providers?: string[] }`
|
||||
- [x] 4.4 `GET /api/providers/:id/diagnostic` *(ships as JSON `{ diagnostic: string }`, not plaintext — see design §8 delta)*
|
||||
- [x] 4.5 Extend `apps/web/src/api/client.ts` coder namespace
|
||||
- [x] 4.6 Confirm BooChat proxy forwards new routes (blanket `/api/coder/*` forward)
|
||||
|
||||
- [ ] 5.1 Create `apps/web/src/data/acp-provider-catalog.ts` (5–10 curated entries)
|
||||
- [ ] 5.2 `AddProviderModal.tsx` — search, install → patch + refresh subset
|
||||
- [ ] 5.3 `ProviderSettingsDrawer.tsx` — list, status, toggle, refresh, link to add
|
||||
- [ ] 5.4 Entry point from CoderPane / AgentComposerBar (gear or settings link)
|
||||
- [ ] 5.5 Filter `AgentComposerBar` selectable providers (`enabled && ready`)
|
||||
- [ ] 5.6 Loading state while snapshot entries `loading` (poll or one-shot refetch)
|
||||
- [ ] 5.7 `npx tsc -p apps/web/tsconfig.app.json --noEmit`
|
||||
## Phase 5 — Web UI — ✅ `v2.5.13-provider-lifecycle-phase5`
|
||||
|
||||
## Phase 6 — Docs, deploy, closeout
|
||||
- [x] 5.1 Create `apps/web/src/data/acp-provider-catalog.ts` (5–10 curated entries)
|
||||
- [x] 5.2 `AddProviderModal.tsx` — search, install → patch + refresh subset *(at `components/coder/`)*
|
||||
- [x] 5.3 Provider management UI *(shipped as a **Settings → Providers tab** in `SettingsPane.tsx`, not a standalone `ProviderSettingsDrawer` — design §7.1 "or section under existing settings")*
|
||||
- [x] 5.4 Entry point from CoderPane / AgentComposerBar (gear or settings link)
|
||||
- [x] 5.5 Filter `AgentComposerBar` selectable providers (`enabled && ready|loading`)
|
||||
- [x] 5.6 Loading state while snapshot entries `loading`
|
||||
- [x] 5.7 `npx tsc -p apps/web/tsconfig.app.json --noEmit`
|
||||
|
||||
- [ ] 6.1 `BOOCODER.md` — config file, refresh contract, enable/disable
|
||||
- [ ] 6.2 Update `docs/DEFERRED-WORK.md` — mark tier-2 cold-probe item addressed
|
||||
- [ ] 6.3 `CHANGELOG.md` entry when tagged
|
||||
- [ ] 6.4 `pnpm -C apps/coder test && pnpm -C apps/coder build`
|
||||
- [ ] 6.5 `sudo systemctl restart boocoder`
|
||||
- [ ] 6.6 Smoke via Tailscale:
|
||||
- `curl http://100.114.205.53:9502/api/providers/snapshot`
|
||||
- PATCH disable goose → absent from composer, visible in settings
|
||||
- POST refresh → models repopulate
|
||||
- Add catalog entry → appears after refresh
|
||||
## Phase 6 — Docs, deploy, closeout — ✅ `v2.5.13` / docs `v2.5.14`
|
||||
|
||||
## Optional (same batch if time)
|
||||
- [x] 6.1 `BOOCODER.md` — config file, refresh contract, enable/disable
|
||||
- [x] 6.2 Update `docs/DEFERRED-WORK.md` — tier-2 cold-probe item marked addressed
|
||||
- [x] 6.3 `CHANGELOG.md` entries (per-phase tags, not a single tag)
|
||||
- [x] 6.4 `pnpm -C apps/coder test && pnpm -C apps/coder build`
|
||||
- [x] 6.5 `sudo systemctl restart boocoder`
|
||||
- [x] 6.6 Smoke via Tailscale (snapshot / disable goose / refresh / add-catalog)
|
||||
|
||||
- [ ] O.1 WS frame `provider_snapshot_updated` (skip polling)
|
||||
- [ ] O.2 `available_agents.enabled` column mirror
|
||||
- [ ] O.3 Diagnostic sheet UI (row click → modal)
|
||||
## Optional — ⬜ DEFERRED (tracked in `docs/DEFERRED-WORK.md`)
|
||||
|
||||
- [ ] O.1 WS frame `provider_snapshot_updated` (skip polling) — **deferred**; `AgentComposerBar:219` polls instead (comment notes the absence)
|
||||
- [ ] O.2 `available_agents.enabled` column mirror — **deferred**; `enabled` read from config memory only (no DB column)
|
||||
- [ ] O.3 Diagnostic sheet UI (row click → modal) — **deferred**; the plaintext/JSON diagnostic API + Settings surface shipped, the modal polish did not
|
||||
|
||||
## Explicitly out of scope
|
||||
|
||||
|
||||
Reference in New Issue
Block a user