diff --git a/.gitignore b/.gitignore index 088f80a..5fe5fec 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,13 @@ docs/product-pilot-judge-results-*.md docs/product-pilot-*.md docs/vscode-plugin.md +# ── internal ADRs / embed hook (living developer docs — not public tip) ── +docs/ADR-*.md +docs/CE-EMBED-HOOK.md + +# ── local skill-shell umbrella workspace (never ship) ── +skill-shell-rationalization/ + # ── machine-level admin policy drop-in (never commit a live copy) ── /admin.json /admin.baked.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dbe696..0342451 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,62 @@ Human-curated release notes. Earlier 0.9.x notes also live on the [GitHub releases](https://github.com/benjsmith/switchbay/releases) page. +## 2026-09-29 — v0.13.0 + +**Migration:** none. **Breaking:** none for wiki/vault format. After pull, +run `make refresh BUILD=1` and hard-reload the PWA. No new VSIX. + +Switchbay **0.13.0** same-origin reverse-proxies curiosity-engine and +okstratr (no iframes), mounts skill UIs in the same document, dual-mounts +CE sidebar + Graph canvas, auto-starts core skills, and is a thin client +over okstratr’s harness registry. Built-in Graph, Agents, and filebrowser +remain; proxied embeds are opt-in in Settings. + +Skill versions: + +| Skill | Version | Notes | +|---|---|---| +| curiosity-engine | **1.9.0** | Dual-mount Pages + atlas; IndexedDB cache | +| okstratr | **0.2.0** | Hosted proxy; registry SSOT; observer desk UX | +| curiosity-merge | **0.8.4** | Installer / UI-boundary contract | + +See [release notes](docs/releases/v0.13.0.md) and [architecture](docs/architecture.md). + +### Added + +- **Same-origin embed reverse-proxy** — `/embed/ce/*` → `:8766`, + `/embed/okstratr/*` → `:8767`; loopback-only upstreams; inject + `X-CE-Host` / `X-Okstratr-Host: switchbay`. Feature flag + `proxied_skill_embeds` (Settings) switches Graph → CE / Agents → okstratr; + daemon proxy is always on. Built-ins **not** deleted. +- **Same-document skill mount** — fetch proxied HTML when core-skills + healthy; rewrite assets; execute scripts in-panel; wait chrome via + `GET /api/core-skills/status` (`starting` / `unhealthy` / `building_wiki` / + `live`). Soft-reload on `sy:files-changed`. +- **Dual-mount CE Graph** — shell-left `CeSidebarSlot` (Pages|Files persists + across Graph/Agents/Editor) + Graph-pane `CeAtlasEmbed` canvas; shared + `ceEmbedSession`; prefers `window.CEEmbed.create` when present; keeps + atlas warm across tab switches; loads `atlas-cache.js` for cold Graph cache. +- **Core-skills auto-start** — always start CE + okstratr with the shell; + rail `host_notify`; `OKSTRATR_HOSTED=switchbay` on supervised serve. +- **Settings → okstratr harness registry** — thin client (`/api/okstratr/harness*`); + no second Switchbay allowlist. +- **Pack / ingest queues** — process CE `.workbench/pack-runs/` via rail LLM; + process ingest-runs via `local_ingest` / prefer CE drop-ingest endpoint. +- **Sandbox roots** — allow `/workspace` (+ env roots) in home-gate. + +### Fixed / polish + +- Keep CE atlas warm across Graph tab switches; dual-mount sidebar bugs after + Graph mount; gzip large JSON + guard soft-remount during CE load; retarget + viewer on workspace switch; serve `data.json` fast / enrich off hot path; + vault missing-extract UX from `vault.db`. + +### Unchanged + +- v0.12.19 Curate / desks / Web / Comms / watch-folder / Zen behavior remains + the product baseline. Graph and Agents chrome stay; proxied mode is opt-in. + ## 2026-09-20 — v0.12.19 No wiki/vault format migration. Review Web, Comms, and watch-folder behavior changes below. After updating, run `make refresh BUILD=1` and hard-reload the PWA. No new VSIX. diff --git a/README.md b/README.md index 2b5ab46..b59367a 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,10 @@ curate captured material into linked wiki pages, run Auto orchestration It runs **entirely on your machine**, against whatever models you choose, and nothing leaves unless you send it. -- **Local & private** — two processes and your files. No cloud, no - accounts; your data and API keys stay on your machine. +- **Local & private** — a Switchbay daemon on your machine (auto-starts + curiosity-engine + okstratr) and your files. No cloud, no accounts; your + data and API keys stay on your machine. See + [`docs/architecture.md`](docs/architecture.md). - **Bring your own models** — hosted APIs (Anthropic, xAI Grok, OpenAI, Gemini, Meta Muse Spark), subscription coding CLIs (Claude Code, Grok Build, Muse Code, Codex, Copilot), or fully-local models (llama.cpp / @@ -39,7 +41,8 @@ and nothing leaves unless you send it. New here? Read **[`docs/concepts-and-data-flow.md`](docs/concepts-and-data-flow.md)** — how Switch Bay is put together in one read: the core vocabulary (**Workspace → Thread → Run → Turn**), the runtime shape, and the data -flows behind the things you do most. Provider coverage (what's +flows behind the things you do most. Hosting / embed architecture: +**[`docs/architecture.md`](docs/architecture.md)**. Provider coverage (what's first-class vs preview, including Muse Code) is **[`docs/providers.md`](docs/providers.md)**. The default **open** profile is today's consumer product. An optional **enterprise** profile @@ -99,7 +102,9 @@ make sync # uv sync (base Python deps; add `make sync-semantic` for em make sync-frontend # pnpm install in frontend/ ``` -Two processes. In one terminal: +Dev needs the daemon and Vite. The daemon **auto-starts** curiosity-engine +(`:8766`) + okstratr (`:8767`); Vite is only for hot frontend reload. In +one terminal: ```sh WORKSPACE=/path/to/workspace make dev-daemon @@ -112,7 +117,8 @@ make dev-frontend ``` Then open the URL vite prints (default `http://localhost:5173`). Vite -proxies `/api` and `/ws` to the daemon on `:8765`. +proxies `/api`, `/ws`, and `/embed` to the daemon on `:8765`. Architecture: +[`docs/architecture.md`](docs/architecture.md). ## Test @@ -182,6 +188,7 @@ don’t need to quit and reopen the PWA after each restart. ## More +- **[`docs/architecture.md`](docs/architecture.md)** — how Switchbay hosts CE and okstratr (embed proxy, core-skills, pack/ingest queues). - **[`docs/concepts-and-data-flow.md`](docs/concepts-and-data-flow.md)** — the map: concepts + data flows. - **[`docs/known-issues.md`](docs/known-issues.md)** — rough edges + deliberate deferrals in this release. - **[`docs/THIRD-PARTY-NOTICES.md`](docs/THIRD-PARTY-NOTICES.md)** — third-party attributions. diff --git a/docs/ADR-004-same-origin-embed-proxy.md b/docs/ADR-004-same-origin-embed-proxy.md deleted file mode 100644 index 84e5e29..0000000 --- a/docs/ADR-004-same-origin-embed-proxy.md +++ /dev/null @@ -1,60 +0,0 @@ -# ADR-004: Same-origin embed reverse-proxy (no iframes) - -- **Status:** Accepted (Phase 4a); Embed v2 mount → [ADR-004b](./ADR-004b-embed-v2-same-document-mount.md) -- **Date:** 2026-09-18 -- **Deciders:** Ben / skill-shell rationalization charter - -## Context - -Switchbay hosts Graph (curiosity-engine atlas/wiki) and Agents (okstratr -observer/desk) surfaces. Cross-origin iframes pointed at -`127.0.0.1:8766` / `:8767` break hosted-mode control (okstratr HTML -settings must hide when `host=switchbay`) and create an opaque nested -browsing context. - -Charter locked decision #1: shells **same-origin reverse-proxy** skill -daemons; in-app panels load first-party proxied routes — **not nested -frames**. - -## Decision - -1. **Daemon reverse-proxy** (always on; independent of the UI flag): - - `/embed/ce/*` → `http://127.0.0.1:8766/*` (override: - `SWITCHBAY_CE_UPSTREAM`, must remain loopback) - - `/embed/okstratr/*` → `http://127.0.0.1:8767/*` (override: - `SWITCHBAY_OKSTRATR_UPSTREAM`, must remain loopback) - - Upstream allowlist is **loopback-only** (`127.0.0.1` / `::1` / - `localhost`). Non-loopback upstreams are rejected (502). - - Inject hosted-shell headers on every proxied request: - - `X-CE-Host: switchbay` - - `X-Okstratr-Host: switchbay` - -2. **No iframes** for Graph/Agents skill surfaces. Feature flag - `proxied_skill_embeds` (default **false**) switches Graph → CE panel - and Agents → okstratr panel that navigate `/embed/*` via same-origin - `fetch` + same-document rendering. Phase 4a was script-stripped HTML / JSON; Embed v2 (ADR-004b) executes skill scripts in-panel. - Built-in GraphTab / AgentDashboardTab / filebrowser remain the - default and are **not deleted**. - -3. **Settings → okstratr registry (done — ADR-005).** Switchbay settings - is a thin client over okstratr's harness/model registry - (`harnesses.toml` via `/api/okstratr/harness…` / embed proxy). No - second Switchbay allowlist. See - [ADR-005](./ADR-005-okstratr-harness-registry-client.md). - -## Consequences - -- Dev Vite must proxy `/embed` to the daemon (`vite.config.ts`). -- CE and okstratr should honor public-base + `X-*-Host` (okstratr - Phase 1a `public_base.py`; CE equivalent TBD). -- Full atlas/observer chrome parity is gated by the parity checklist - before any Switchbay duplicate deletion (Phase 4b+). -- WebSocket upgrade through the embed proxy is deferred; HTTP(S) first. - -## Alternatives considered - -| Option | Why not | -|--------|---------| -| Cross-origin iframe to :8766/:8767 | Opaque origin; hosted settings leak; charter forbid | -| Same-origin iframe to `/embed/*` | Still a nested frame; charter: no iframes | -| Delete built-in Graph/Agents now | Violates parity checklist / dual-stack gate | diff --git a/docs/ADR-004b-embed-v2-same-document-mount.md b/docs/ADR-004b-embed-v2-same-document-mount.md deleted file mode 100644 index ec018ef..0000000 --- a/docs/ADR-004b-embed-v2-same-document-mount.md +++ /dev/null @@ -1,78 +0,0 @@ -# ADR-004b: Embed v2 — same-document interactive mount - -- **Status:** Accepted (Embed v2) -- **Date:** 2026-09-19 -- **Parent:** [ADR-004](./ADR-004-same-origin-embed-proxy.md) -- **Contract:** umbrella `CONTRACT-EMBED-V2.md` - -## Context - -Phase 4a (`ProxiedSkillPanel`) fetched `/embed/*` HTML and injected a -**script-stripped** body. That proved the reverse-proxy path but left Graph -and Agents inert (no pan/zoom, no desk controls). Charter + ADR-004 forbid -`