forked from bots-garden/ori
📝 Update project memory after the adapter switch (summary, history, handoff)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
4166f8f parent: 5d476ff added
.memory/handoffs/2026-09-18-claude-agent-acp-adapter.md +27 -0 | new file mode 100644 | ||
| @@ -0,0 +1,27 @@ | ||
| 1 | +# Handoff — 2026-09-18 — ACP adapter switched to @agentclientprotocol/claude-agent-acp | |
| 2 | + | |
| 3 | +## State | |
| 4 | + | |
| 5 | +Done and merged into `main` (`5d476ff` + this memory commit): backend default, template Dockerfile, kit, docs EN+FR, launcher, quality gate PASS (run #18). Published: `k33g/ori:0.0.2` (Docker Hub, multi-arch, pushed by the user) and `docker.io/k33g/ori-kit:latest` (pushed by this session, `claude-agent-acp`). The user confirmed a real prompt works in sandbox `hello-world` (template 0.0.2 + published kit, port 5555 dual-stack). | |
| 6 | + | |
| 7 | +## In flight | |
| 8 | + | |
| 9 | +- Sandbox `hello-world` was created with the **old** kit: its baked startup script still says `claude-code-acp`; ori was started by hand. On restart it dies again → `sbx rm hello-world`, recreate with the published kit and `-p 5555:8888/tcp`. Sandbox `ori-acp` (local image `k33g/ori:0.0.2-local`, port 7777) and that template can be removed. | |
| 10 | +- amd64 `adapter` stage: verified in a `node:24-bookworm` container, not inspected inside the pushed amd64 image (the background `buildx --target adapter --platform linux/amd64` was still running when the session moved on). | |
| 11 | +- `scripts/Launch Ori.app` rebuilt from the updated script; still never run end to end. | |
| 12 | + | |
| 13 | +## Next steps | |
| 14 | + | |
| 15 | +1. `sbx template rm k33g/ori:0.0.2-local`, `sbx rm ori-acp` (housekeeping). | |
| 16 | +2. Ticket for an automated real-prompt smoke test (see `summary.md` "Not yet established"). | |
| 17 | +3. `docs/.assets/ori-architecture.drawio.svg` / `.json` (talk assets) still say `claude-code-acp` — cosmetic, not updated. | |
| 18 | + | |
| 19 | +## Watch out for | |
| 20 | + | |
| 21 | +- `npm install --cpu=amd64` installs no native SDK and fails silently; use `x64`. The Dockerfile asserts the package directory exists. | |
| 22 | +- Image and kit must be published together: the kit's `--agent-cmd` must name the binary the image ships. | |
| 23 | +- `-p H:8888` = IPv4 only; use `/tcp`. Chrome blocks 6665–6669. | |
| 24 | +- qlty on this Mac: delete dangling `.qlty/{logs,out,plugin_cachedir,results}` symlinks created inside a sandbox; golangci-lint must be a build with Go ≥ 1.26 (pinned 2.13.2). qlty leaves a stray `.shellcheckrc` copy at the repo root; safe to delete (identical to `.qlty/configs/.shellcheckrc`). | |
| 25 | +- `scripts/launch-ori.applescript` came back UTF-16 after a Script Editor save; keep it UTF-8 (`iconv -f UTF-16 -t UTF-8`). | |
| 26 | +- Node 25: run vitest through `npm run test` (the script carries the webstorage flag); a bare `npx vitest run` fails 15 tests. | |
| 27 | +- A Python edit script that asserts on text must run under `&&` before any `git commit`: this session's first memory write failed on an anchor and the commit went ahead without it. | |
| new file mode 100644 | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | +# Handoff — 2026-09-18 — ACP adapter switched to @agentclientprotocol/claude-agent-acp | ||
| 2 | + | ||
| 3 | +## State | ||
| 4 | + | ||
| 5 | +Done and merged into `main` (`5d476ff` + this memory commit): backend default, template Dockerfile, kit, docs EN+FR, launcher, quality gate PASS (run #18). Published: `k33g/ori:0.0.2` (Docker Hub, multi-arch, pushed by the user) and `docker.io/k33g/ori-kit:latest` (pushed by this session, `claude-agent-acp`). The user confirmed a real prompt works in sandbox `hello-world` (template 0.0.2 + published kit, port 5555 dual-stack). | ||
| 6 | + | ||
| 7 | +## In flight | ||
| 8 | + | ||
| 9 | +- Sandbox `hello-world` was created with the **old** kit: its baked startup script still says `claude-code-acp`; ori was started by hand. On restart it dies again → `sbx rm hello-world`, recreate with the published kit and `-p 5555:8888/tcp`. Sandbox `ori-acp` (local image `k33g/ori:0.0.2-local`, port 7777) and that template can be removed. | ||
| 10 | +- amd64 `adapter` stage: verified in a `node:24-bookworm` container, not inspected inside the pushed amd64 image (the background `buildx --target adapter --platform linux/amd64` was still running when the session moved on). | ||
| 11 | +- `scripts/Launch Ori.app` rebuilt from the updated script; still never run end to end. | ||
| 12 | + | ||
| 13 | +## Next steps | ||
| 14 | + | ||
| 15 | +1. `sbx template rm k33g/ori:0.0.2-local`, `sbx rm ori-acp` (housekeeping). | ||
| 16 | +2. Ticket for an automated real-prompt smoke test (see `summary.md` "Not yet established"). | ||
| 17 | +3. `docs/.assets/ori-architecture.drawio.svg` / `.json` (talk assets) still say `claude-code-acp` — cosmetic, not updated. | ||
| 18 | + | ||
| 19 | +## Watch out for | ||
| 20 | + | ||
| 21 | +- `npm install --cpu=amd64` installs no native SDK and fails silently; use `x64`. The Dockerfile asserts the package directory exists. | ||
| 22 | +- Image and kit must be published together: the kit's `--agent-cmd` must name the binary the image ships. | ||
| 23 | +- `-p H:8888` = IPv4 only; use `/tcp`. Chrome blocks 6665–6669. | ||
| 24 | +- qlty on this Mac: delete dangling `.qlty/{logs,out,plugin_cachedir,results}` symlinks created inside a sandbox; golangci-lint must be a build with Go ≥ 1.26 (pinned 2.13.2). qlty leaves a stray `.shellcheckrc` copy at the repo root; safe to delete (identical to `.qlty/configs/.shellcheckrc`). | ||
| 25 | +- `scripts/launch-ori.applescript` came back UTF-16 after a Script Editor save; keep it UTF-8 (`iconv -f UTF-16 -t UTF-8`). | ||
| 26 | +- Node 25: run vitest through `npm run test` (the script carries the webstorage flag); a bare `npx vitest run` fails 15 tests. | ||
| 27 | +- A Python edit script that asserts on text must run under `&&` before any `git commit`: this session's first memory write failed on an anchor and the commit went ahead without it. | ||
modified
.memory/history.md +8 -0 | @@ -170,3 +170,11 @@ | ||
| 170 | 170 | - **Asked**: reminder of what to do to avoid this prompt failure in the sandbox (kit `docker.io/k33g/ori-kit:latest`, template `k33g/ori:0.0.1`). |
| 171 | 171 | - **Diagnosis (read-only, verified)**: ori in sandbox `ori` runs with no `CLAUDE_CODE_EXECUTABLE`, so the Zed adapter 0.16.2 uses its bundled CLI 2.1.44 (SDK 0.2.44). The model comes from the host `~/.claude/settings.json` (`claude-fable-5-1[1m]`), which the API only serves to CLI ≥ 2.1.251. Yesterday's workaround (point the adapter at the template's system CLI) **no longer suffices**: the base image `docker/sandbox-templates:claude-code` (built 2026-08-26) ships CLI 2.1.246. Sandbox egress reaches the Claude Code release bucket (latest = 2.1.276) and npm, so `claude update` inside is feasible. `@agentclientprotocol/claude-agent-acp@0.79.0` (bin `claude-agent-acp`) depends on `@anthropic-ai/claude-agent-sdk@0.3.274`, whose `manifest.json` says CLI **2.1.274**, delivered through per-platform optional deps (`…-sdk-linux-arm64`, `…-linux-x64`, …) — no `cli.js` any more. |
| 172 | 172 | - **Nothing changed**: options given to the user (immediate: `claude update` in the sandbox + restart ori with `CLAUDE_CODE_EXECUTABLE`; permanent: switch the template to the new adapter, or bake a recent CLI + the env var into template/kit). Their call. |
| 173 | + | |
| 174 | +## 2026-09-18 — Switch the ACP adapter to @agentclientprotocol/claude-agent-acp (template 0.0.2), Node 25 test fix, MIME pin | |
| 175 | + | |
| 176 | +- **Goal**: option 1 of the "Claude Code 2.1.44 too old" diagnosis, approved by the user: stop depending on the Zed adapter's embedded CLI; rebuild template 0.0.2; republish the kit. Worked on `feature/copy-paste-functionality` (user's choice), commit `5d476ff`, fast-forwarded into `main`; this memory update is a follow-up commit on `main`. | |
| 177 | +- **Changes**: `internal/config/config.go` `DefaultAgentCommand` → `npx -y @agentclientprotocol/claude-agent-acp` (+ `TestDefaultAgentCommandIsClaudeAgentACP`); doc comments in `internal/agent/agent.go`, `cmd/ori/main.go`. `template/Dockerfile`: `adapter` stage installs the new adapter with `npm install --os=linux --cpu=$npm_cpu`, Docker's `amd64` mapped to npm's `x64` (with `--cpu=amd64` npm silently installs **no** native SDK), and asserts `claude-agent-sdk-linux-<cpu>` exists; CMD `--agent-cmd claude-agent-acp`. `kits/ori/spec.yaml`: startup + agentInstructions → `claude-agent-acp`, template 0.0.2. `internal/files/raw.go`: `textTypes` pins `.md`/`.markdown` → `text/markdown; charset=utf-8` (Go's mime table comes from the host; macOS leaves `text/markdown` commented out, so `TestRawAcceptsAbsolutePathsLikeTheOtherEndpoints` failed on the Mac) + 2 table cases. `ui/package.json` test script gains `NODE_OPTIONS=--no-experimental-webstorage`. `ui/src/components/Markdown.tsx`: `React.ReactElement<{ children?: unknown }>` cast — the copy-paste commit did not compile (TS2339 ×3) and blocked `docker build`. `ui/src/components/ToolCallCard.tsx`: copy text extracted into pure `contentText` / `toolContentText` (+5 tests), clearing two function-complexity smells. `.qlty/qlty.toml`: golangci-lint pinned 2.13.2. Docs EN+FR (architecture explanation, how-to run-with-claude-code / run-in-a-sandbox / run-the-tests, reference cli), `docs/diagrams/packages.drawio`, `docs/source-code-analysis.adoc`, kit README, root README, quickstart, `scripts/launch-ori.applescript` (0.0.2, `/tcp`, converted back from UTF-16) + its READMEs. | |
| 178 | +- **Decisions**: (1) new adapter over "bake `claude update` + `CLAUDE_CODE_EXECUTABLE`": the SDK ships a current CLI per platform, no version chasing. (2) `adapter` stage stays `--platform=$BUILDPLATFORM` (native npm) and targets the CPU explicitly, instead of npm under qemu. (3) Backend default changed too (user: "backend + template") so `make run` gets the same fix. (4) Pre-existing failures fixed along the way with the user's explicit OK: MIME test, Node 25, Markdown.tsx types, ToolCallCard complexity. (5) Left untracked as the user's artefacts/memos: `kits/.backup/`, `demo/` (the three prompt-generated stories the user moved there — their root copies are deleted in `5d476ff`), `kits/ori/publish.kit.md`, `template/publish.template.md`. | |
| 179 | +- **Verification**: `go vet ./... && go test ./...` green; ui `tsc -b` + 134 vitest green; `docker build --check` clean; arm64 image built locally — `claude-agent-acp` resolves for root and via `su … agent`, native SDK `linux-arm64` with the 230 MB CLI, manifest 2.1.274, ACP `initialize` answered by adapter 0.79.0, Zed adapter gone; amd64 install verified in a `node:24` container (`-linux-x64` present). Test sandbox `ori-acp` (image via `sbx template load`) served ori with CLI 2.1.274; the user pushed `k33g/ori:0.0.2` (multi-arch) and confirmed a real prompt in sandbox `hello-world` after the kit re-push. **Quality**: run #18 PASS (0/0/0, complex 532) after repairing qlty on the Mac (dangling `.qlty/*` symlinks from the sandbox; golangci-lint too old for Go 1.26). | |
| 180 | +- **Docs**: as listed, EN + FR in sync. `diataxis-doc` skill not invoked: edits to existing pages, done directly. | |
| @@ -170,3 +170,11 @@ | |||
| 170 | - **Asked**: reminder of what to do to avoid this prompt failure in the sandbox (kit `docker.io/k33g/ori-kit:latest`, template `k33g/ori:0.0.1`). | 170 | - **Asked**: reminder of what to do to avoid this prompt failure in the sandbox (kit `docker.io/k33g/ori-kit:latest`, template `k33g/ori:0.0.1`). |
| 171 | - **Diagnosis (read-only, verified)**: ori in sandbox `ori` runs with no `CLAUDE_CODE_EXECUTABLE`, so the Zed adapter 0.16.2 uses its bundled CLI 2.1.44 (SDK 0.2.44). The model comes from the host `~/.claude/settings.json` (`claude-fable-5-1[1m]`), which the API only serves to CLI ≥ 2.1.251. Yesterday's workaround (point the adapter at the template's system CLI) **no longer suffices**: the base image `docker/sandbox-templates:claude-code` (built 2026-08-26) ships CLI 2.1.246. Sandbox egress reaches the Claude Code release bucket (latest = 2.1.276) and npm, so `claude update` inside is feasible. `@agentclientprotocol/claude-agent-acp@0.79.0` (bin `claude-agent-acp`) depends on `@anthropic-ai/claude-agent-sdk@0.3.274`, whose `manifest.json` says CLI **2.1.274**, delivered through per-platform optional deps (`…-sdk-linux-arm64`, `…-linux-x64`, …) — no `cli.js` any more. | 171 | - **Diagnosis (read-only, verified)**: ori in sandbox `ori` runs with no `CLAUDE_CODE_EXECUTABLE`, so the Zed adapter 0.16.2 uses its bundled CLI 2.1.44 (SDK 0.2.44). The model comes from the host `~/.claude/settings.json` (`claude-fable-5-1[1m]`), which the API only serves to CLI ≥ 2.1.251. Yesterday's workaround (point the adapter at the template's system CLI) **no longer suffices**: the base image `docker/sandbox-templates:claude-code` (built 2026-08-26) ships CLI 2.1.246. Sandbox egress reaches the Claude Code release bucket (latest = 2.1.276) and npm, so `claude update` inside is feasible. `@agentclientprotocol/claude-agent-acp@0.79.0` (bin `claude-agent-acp`) depends on `@anthropic-ai/claude-agent-sdk@0.3.274`, whose `manifest.json` says CLI **2.1.274**, delivered through per-platform optional deps (`…-sdk-linux-arm64`, `…-linux-x64`, …) — no `cli.js` any more. |
| 172 | - **Nothing changed**: options given to the user (immediate: `claude update` in the sandbox + restart ori with `CLAUDE_CODE_EXECUTABLE`; permanent: switch the template to the new adapter, or bake a recent CLI + the env var into template/kit). Their call. | 172 | - **Nothing changed**: options given to the user (immediate: `claude update` in the sandbox + restart ori with `CLAUDE_CODE_EXECUTABLE`; permanent: switch the template to the new adapter, or bake a recent CLI + the env var into template/kit). Their call. |
| 173 | + | ||
| 174 | +## 2026-09-18 — Switch the ACP adapter to @agentclientprotocol/claude-agent-acp (template 0.0.2), Node 25 test fix, MIME pin | ||
| 175 | + | ||
| 176 | +- **Goal**: option 1 of the "Claude Code 2.1.44 too old" diagnosis, approved by the user: stop depending on the Zed adapter's embedded CLI; rebuild template 0.0.2; republish the kit. Worked on `feature/copy-paste-functionality` (user's choice), commit `5d476ff`, fast-forwarded into `main`; this memory update is a follow-up commit on `main`. | ||
| 177 | +- **Changes**: `internal/config/config.go` `DefaultAgentCommand` → `npx -y @agentclientprotocol/claude-agent-acp` (+ `TestDefaultAgentCommandIsClaudeAgentACP`); doc comments in `internal/agent/agent.go`, `cmd/ori/main.go`. `template/Dockerfile`: `adapter` stage installs the new adapter with `npm install --os=linux --cpu=$npm_cpu`, Docker's `amd64` mapped to npm's `x64` (with `--cpu=amd64` npm silently installs **no** native SDK), and asserts `claude-agent-sdk-linux-<cpu>` exists; CMD `--agent-cmd claude-agent-acp`. `kits/ori/spec.yaml`: startup + agentInstructions → `claude-agent-acp`, template 0.0.2. `internal/files/raw.go`: `textTypes` pins `.md`/`.markdown` → `text/markdown; charset=utf-8` (Go's mime table comes from the host; macOS leaves `text/markdown` commented out, so `TestRawAcceptsAbsolutePathsLikeTheOtherEndpoints` failed on the Mac) + 2 table cases. `ui/package.json` test script gains `NODE_OPTIONS=--no-experimental-webstorage`. `ui/src/components/Markdown.tsx`: `React.ReactElement<{ children?: unknown }>` cast — the copy-paste commit did not compile (TS2339 ×3) and blocked `docker build`. `ui/src/components/ToolCallCard.tsx`: copy text extracted into pure `contentText` / `toolContentText` (+5 tests), clearing two function-complexity smells. `.qlty/qlty.toml`: golangci-lint pinned 2.13.2. Docs EN+FR (architecture explanation, how-to run-with-claude-code / run-in-a-sandbox / run-the-tests, reference cli), `docs/diagrams/packages.drawio`, `docs/source-code-analysis.adoc`, kit README, root README, quickstart, `scripts/launch-ori.applescript` (0.0.2, `/tcp`, converted back from UTF-16) + its READMEs. | ||
| 178 | +- **Decisions**: (1) new adapter over "bake `claude update` + `CLAUDE_CODE_EXECUTABLE`": the SDK ships a current CLI per platform, no version chasing. (2) `adapter` stage stays `--platform=$BUILDPLATFORM` (native npm) and targets the CPU explicitly, instead of npm under qemu. (3) Backend default changed too (user: "backend + template") so `make run` gets the same fix. (4) Pre-existing failures fixed along the way with the user's explicit OK: MIME test, Node 25, Markdown.tsx types, ToolCallCard complexity. (5) Left untracked as the user's artefacts/memos: `kits/.backup/`, `demo/` (the three prompt-generated stories the user moved there — their root copies are deleted in `5d476ff`), `kits/ori/publish.kit.md`, `template/publish.template.md`. | ||
| 179 | +- **Verification**: `go vet ./... && go test ./...` green; ui `tsc -b` + 134 vitest green; `docker build --check` clean; arm64 image built locally — `claude-agent-acp` resolves for root and via `su … agent`, native SDK `linux-arm64` with the 230 MB CLI, manifest 2.1.274, ACP `initialize` answered by adapter 0.79.0, Zed adapter gone; amd64 install verified in a `node:24` container (`-linux-x64` present). Test sandbox `ori-acp` (image via `sbx template load`) served ori with CLI 2.1.274; the user pushed `k33g/ori:0.0.2` (multi-arch) and confirmed a real prompt in sandbox `hello-world` after the kit re-push. **Quality**: run #18 PASS (0/0/0, complex 532) after repairing qlty on the Mac (dangling `.qlty/*` symlinks from the sandbox; golangci-lint too old for Go 1.26). | ||
| 180 | +- **Docs**: as listed, EN + FR in sync. `diataxis-doc` skill not invoked: edits to existing pages, done directly. | ||
modified
.memory/summary.md +10 -9 | @@ -2,7 +2,7 @@ | ||
| 2 | 2 | |
| 3 | 3 | ## What it is |
| 4 | 4 | |
| 5 | -Ori is a web client for ACP (Agent Client Protocol, https://agentclientprotocol.com) code agents: a Go backend serves an embedded React SPA and connects over ACP (JSON-RPC on stdio) to an agent subprocess — Claude Code via the `@zed-industries/claude-code-acp` adapter by default. The browser gets a Zed-style agent panel: streamed markdown answers, collapsible thoughts, tool call cards (with statuses, locations and diffs), the agent's plan, and permission prompts answered from the UI. Implements ticket `.tickets/issues/0004-specifications.yaml`. | |
| 5 | +Ori is a web client for ACP (Agent Client Protocol, https://agentclientprotocol.com) code agents: a Go backend serves an embedded React SPA and connects over ACP (JSON-RPC on stdio) to an agent subprocess — Claude Code via the `@agentclientprotocol/claude-agent-acp` adapter by default (since 2026-09-18). The browser gets a Zed-style agent panel: streamed markdown answers, collapsible thoughts, tool call cards (with statuses, locations and diffs), the agent's plan, and permission prompts answered from the UI. Implements ticket `.tickets/issues/0004-specifications.yaml`. | |
| 6 | 6 | |
| 7 | 7 | ## Architecture |
| 8 | 8 | |
| @@ -25,7 +25,7 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess | ||
| 25 | 25 | |
| 26 | 26 | ## Key decisions in force |
| 27 | 27 | |
| 28 | -- Claude Code is reached through the official Zed adapter (`npx -y @zed-industries/claude-code-acp`) — the `claude` CLI (v2.1.274) has no native ACP mode; verified. | |
| 28 | +- Claude Code is reached through `@agentclientprotocol/claude-agent-acp` (default `npx -y @agentclientprotocol/claude-agent-acp`, since 2026-09-18; `internal/config.DefaultAgentCommand`, pinned by `TestDefaultAgentCommandIsClaudeAgentACP`). It bundles its own Claude Code CLI via `@anthropic-ai/claude-agent-sdk` 0.3.274 → CLI 2.1.274 delivered as per-platform optional deps (`…-sdk-linux-arm64`, `-linux-x64`, …; no `cli.js` any more). Replaced Zed's `@zed-industries/claude-code-acp` 0.16.2, whose embedded CLI 2.1.44 the API rejects for current models ("version 2.1.251 or newer is required"). The `claude` CLI itself has no native ACP mode; verified. | |
| 29 | 29 | - draw.io diagrams render online via `embed.diagrams.net` (no bundlable offline renderer exists: `viewer.min.js` is not on npm, `mxgraph` is archived and lacks draw.io's shapes, `drawio2svg` is GPL); future offline path = vendoring `viewer-static.min.js` (~3 MB, Apache-2.0). Documented in the architecture explanations. |
| 30 | 30 | - ACP payloads cross the WebSocket verbatim (raw `SessionUpdate` / `RequestPermissionRequest`), keeping the front forward-compatible. |
| 31 | 31 | - One agent session shared by all browsers in v1; multi-session is a planned evolution seam (`bridge.Prompter` interface, per-connection subscriptions). |
| @@ -36,22 +36,23 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess | ||
| 36 | 36 | |
| 37 | 37 | - `make deps` — npm install in `ui/`. |
| 38 | 38 | - `make build` — SPA build then Go binaries (`bin/ori`, `bin/ori-mock-agent`). Order matters: the Go build embeds `ui/dist`. |
| 39 | -- `make test` — `go test ./...` + `vitest run`. Also useful: `go test -race ./...`, `go test -short ./...` (skips e2e). | |
| 39 | +- `make test` — `go test ./...` + `vitest run` (the ui `test` script sets `NODE_OPTIONS=--no-experimental-webstorage`: Node 25's built-in `localStorage` lacks `clear()` and shadows jsdom's — 15 store tests fail without it; verified 2026-09-18 on Node 25.9). Also useful: `go test -race ./...`, `go test -short ./...` (skips e2e). | |
| 40 | 40 | - `make run` — with Claude Code adapter; `make run-mock` — with the demo agent (no Claude/network needed). |
| 41 | -- `make template` — builds the `k33g/ori` sandbox template image (`template/Dockerfile`, FROM `docker/sandbox-templates:claude-code`); launch with `sbx run -d claude <project> --template k33g/ori:0.0.0 --kit <ori repo>/kits/ori --name ori -p 8888:8888` (detached — see the auto-stop trap below) (see `kits/ori/README.md` and docs how-to `run-in-a-sandbox`). | |
| 42 | -- `scripts/launch-ori.applescript` (2026-09-18) — macOS launcher: `sbx ls -q` → restart by name or create (`k33g/ori:0.0.1`, `./kits/ori`, `-p 5555:8888`), poll `http://localhost:5555/healthz` up to 90 s, then `open ori-desktop/build/bin/ori-desktop.app`. Run with `osascript`, or `osacompile` into `scripts/Launch Ori.app`; repo root derived from the script's own location. Compile-checked and handlers unit-tested; full end-to-end run not yet done. | |
| 41 | +- `make template` — builds the `k33g/ori` sandbox template image (`template/Dockerfile`, FROM `docker/sandbox-templates:claude-code`); launch with `sbx run -d claude <project> --template k33g/ori:0.0.2 --kit docker.io/k33g/ori-kit:latest --name ori -p 8888:8888/tcp` (detached — see the auto-stop trap below) (see `kits/ori/README.md` and docs how-to `run-in-a-sandbox`). | |
| 42 | +- `scripts/launch-ori.applescript` (2026-09-18) — macOS launcher: `sbx ls -q` → restart by name or create (`k33g/ori:0.0.2`, `./kits/ori`, `-p 5555:8888/tcp`), poll `http://localhost:5555/healthz` up to 90 s, then `open ori-desktop/build/bin/ori-desktop.app`. Run with `osascript`, or `osacompile` into `scripts/Launch Ori.app`; repo root derived from the script's own location. Compile-checked and handlers unit-tested; full end-to-end run not yet done. | |
| 43 | 43 | - Kit publishing (sbx v0.43.0, verified 2026-09-18): `sbx kit validate kits/ori`, `sbx kit pack kits/ori -o ori-kit.zip`, `sbx kit push kits/ori docker.io/k33g/ori-kit:<tag>` — directory argument, not `spec.yaml`; there is no `sbx kit package`. Auth: `sbx login` session, then `sbx secret set --registry`, then the Docker credential store. |
| 44 | 44 | - **Kit packaging trap (verified 2026-09-18)**: `pack`/`push` decode `spec.yaml` raw (no `${{ kit.args }}` expansion) — an arg placeholder in an integer field (`ports[].container`) breaks them even though `validate`/`run` accept it. `ports[0].container` is therefore a literal 8888; the `port` arg only drives the startup command and agentInstructions. |
| 45 | -- Published kit: `docker.io/k33g/ori-kit:latest` (pushed 2026-09-18, verified with `sbx kit inspect`); usable as `--kit docker.io/k33g/ori-kit:latest` instead of `--kit ./kits/ori`. | |
| 45 | +- Published artefacts (2026-09-18): template `k33g/ori:0.0.2` on Docker Hub (multi-arch amd64+arm64, pushed by the user with `./template/build.sh`, ships only `claude-agent-acp`); kit `docker.io/k33g/ori-kit:latest` re-pushed with `--agent-cmd claude-agent-acp` + template 0.0.2. **They must move together**: the first `hello-world` sandbox paired image 0.0.2 with the morning's kit (`claude-code-acp`) and ori died with "executable file not found". | |
| 46 | +- **Port publishing traps**: `-p H:8888` without protocol binds `tcp4` only — browsers resolving `localhost` to `::1` fail; always `-p H:8888/tcp` (dual-stack). Chrome refuses ports 6665–6669 (`ERR_UNSAFE_PORT`) whatever the server does. `sbx ports NAME` lists; `sbx ports ls` looks for a sandbox called `ls`. | |
| 46 | 47 | - **sbx auto-stop trap (verified in the sbx source + daemon log, 2026-09-17)**: sandboxd stops a sandbox 30 s (hard-coded `WithAutoStopDelay(30*time.Second)`, `sandboxd/pkg/server/backend_dockernext.go`) after its last CLI "sentinel" session closes; `sbx create`/`sbx exec`/`sbx run` all hold one for their own duration, browser traffic on a published port counts for nothing. Only a sandbox created with the spec field `detached: true` (CLI: `sbx run -d …`, absent from `sbx create`) is exempt; the field is create-time only (no PATCH), so an existing sandbox must be `sbx rm`'d and recreated with `sbx run -d`. No settings/env knob for the delay. |
| 47 | -- Quality: `python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace .` (gate PASS, run #16, 2026-09-17 late evening: 0 errors, 0 warnings, 0 smells, complex 514 — covers the selectors/previews/desktop work, the resizable file tree and the light/dark theme). | |
| 48 | +- Quality: `python3 .claude/skills/quality/scripts/quality_report.py --workspace .` (the script lives in the repo, not `~/.claude`). Gate PASS, run #18, 2026-09-18: 0 errors, 0 warnings, 0 smells, complex 532 (covers the adapter switch, the MIME pin, the copy-paste feature). **Mac trap**: `.qlty/{logs,out,plugin_cachedir,results}` are symlinks qlty creates into its cache; ones created inside the sandbox point at `/home/agent/…` and dangle on the Mac, making every plugin invocation "FATAL" with no detail — delete the dangling links, qlty recreates them. `.qlty/qlty.toml` pins golangci-lint 2.13.2 (built with Go 1.27): qlty's default 1.61.0 and its latest-known 2.6.2 refuse this repo's `go 1.26.5`. | |
| 48 | 49 | - `docs/source-code-analysis.adoc` — AsciiDoc snapshot analysis of the codebase (2026-09-17), outside the bilingual Diátaxis set. |
| 49 | 50 | |
| 50 | 51 | ## Environment facts (sandbox) |
| 51 | 52 | |
| 52 | 53 | - `~/.qlty` is a dedicated 488MB volume, too small for qlty's tool cache; the cache was moved to `~/.qlty-cache` on the main disk with a symlink `~/.qlty/cache -> /home/agent/.qlty-cache`. If qlty reports "No space left on device", check this symlink survived. (It did NOT survive a sandbox recreation on 2026-09-17: the volume came back empty and the first run failed exactly that way; recreating the symlink fixed it.) |
| 53 | 54 | - `~/.npm` is the same kind of 488MB dedicated volume and filled up when installing Monaco; the npm cache now lives at `~/.npm-big` via `NPM_CONFIG_CACHE` exported in `/etc/sandbox-persistent.sh`. |
| 54 | -- Running ori inside this Claude-Code-driven sandbox requires `env -u CLAUDECODE ./bin/ori` (Claude refuses nested sessions). Also set `CLAUDE_CODE_EXECUTABLE=<current claude binary>`: the Zed adapter 0.16.2 bundles Claude Code 2.1.44, which rejects the `claude-fable-5-1[1m]` model from the host `~/.claude/settings.json`. **Since 2026-09-18 the API requires CLI ≥ 2.1.251 for that model, and the template's own CLI is 2.1.246 (base image built 2026-08-26)** — so the env var alone is not enough; run `claude update` in the sandbox first, or switch the template to `@agentclientprotocol/claude-agent-acp` (SDK 0.3.274 → CLI 2.1.274). Handoff `2026-09-18-claude-version-too-old.md`. | |
| 55 | +- Running ori inside this Claude-Code-driven sandbox requires `env -u CLAUDECODE ./bin/ori` (Claude refuses nested sessions). With the current template/kit (`claude-agent-acp`, bundled CLI 2.1.274) no `CLAUDE_CODE_EXECUTABLE` is needed. It remains the lever if something spawns the old Zed adapter (points it at another `claude` binary) — but the template's own CLI is 2.1.246 (base image 2026-08-26), below the 2.1.251 floor the API enforces for `claude-fable-5-1[1m]` (host `~/.claude/settings.json`), so `claude update` inside the sandbox would come first. Handoffs `2026-09-18-claude-version-too-old.md`, `2026-09-18-claude-agent-acp-adapter.md`. | |
| 55 | 56 | - npm blocks install scripts by default here; esbuild's postinstall was approved via `npm approve-scripts` (recorded in `ui/package.json` `allowScripts`). |
| 56 | 57 | |
| 57 | 58 | ## Known limitations |
| @@ -68,7 +69,7 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess | ||
| 68 | 69 | |
| 69 | 70 | - ori-desktop: the window was launched by the user on their Mac (build OK, Check OK); after the CSS specificity fix (`#connect-screen` outranked `.screen[hidden]`, so the connect screen never hid and the viewer rendered below the fold) it has not yet been confirmed that the iframe actually shows ori inside WKWebView (`wails://` origin loading `http://localhost`; `NSAllowsLocalNetworking` set in `build/darwin/Info.plist`). |
| 70 | 71 | |
| 71 | -- Behaviour against a real Claude Code session (auth flow, real tool calls) has not been exercised in this sandbox — only against the mock agent and unit doubles. | |
| 72 | +- Real Claude Code sessions: exercised by the user on 2026-09-18 (sandbox `hello-world`, template 0.0.2 + published kit, real prompt answered). Still missing: an automated end-to-end test that drives a real prompt. | |
| 72 | 73 | |
| 73 | 74 | ## Tickets (`.tickets/`) |
| 74 | 75 | |
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | ## What it is | 3 | ## What it is |
| 4 | 4 | ||
| 5 | -Ori is a web client for ACP (Agent Client Protocol, https://agentclientprotocol.com) code agents: a Go backend serves an embedded React SPA and connects over ACP (JSON-RPC on stdio) to an agent subprocess — Claude Code via the `@zed-industries/claude-code-acp` adapter by default. The browser gets a Zed-style agent panel: streamed markdown answers, collapsible thoughts, tool call cards (with statuses, locations and diffs), the agent's plan, and permission prompts answered from the UI. Implements ticket `.tickets/issues/0004-specifications.yaml`. | 5 | +Ori is a web client for ACP (Agent Client Protocol, https://agentclientprotocol.com) code agents: a Go backend serves an embedded React SPA and connects over ACP (JSON-RPC on stdio) to an agent subprocess — Claude Code via the `@agentclientprotocol/claude-agent-acp` adapter by default (since 2026-09-18). The browser gets a Zed-style agent panel: streamed markdown answers, collapsible thoughts, tool call cards (with statuses, locations and diffs), the agent's plan, and permission prompts answered from the UI. Implements ticket `.tickets/issues/0004-specifications.yaml`. |
| 6 | 6 | ||
| 7 | ## Architecture | 7 | ## Architecture |
| 8 | 8 | ||
| @@ -25,7 +25,7 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess | |||
| 25 | 25 | ||
| 26 | ## Key decisions in force | 26 | ## Key decisions in force |
| 27 | 27 | ||
| 28 | -- Claude Code is reached through the official Zed adapter (`npx -y @zed-industries/claude-code-acp`) — the `claude` CLI (v2.1.274) has no native ACP mode; verified. | 28 | +- Claude Code is reached through `@agentclientprotocol/claude-agent-acp` (default `npx -y @agentclientprotocol/claude-agent-acp`, since 2026-09-18; `internal/config.DefaultAgentCommand`, pinned by `TestDefaultAgentCommandIsClaudeAgentACP`). It bundles its own Claude Code CLI via `@anthropic-ai/claude-agent-sdk` 0.3.274 → CLI 2.1.274 delivered as per-platform optional deps (`…-sdk-linux-arm64`, `-linux-x64`, …; no `cli.js` any more). Replaced Zed's `@zed-industries/claude-code-acp` 0.16.2, whose embedded CLI 2.1.44 the API rejects for current models ("version 2.1.251 or newer is required"). The `claude` CLI itself has no native ACP mode; verified. |
| 29 | - draw.io diagrams render online via `embed.diagrams.net` (no bundlable offline renderer exists: `viewer.min.js` is not on npm, `mxgraph` is archived and lacks draw.io's shapes, `drawio2svg` is GPL); future offline path = vendoring `viewer-static.min.js` (~3 MB, Apache-2.0). Documented in the architecture explanations. | 29 | - draw.io diagrams render online via `embed.diagrams.net` (no bundlable offline renderer exists: `viewer.min.js` is not on npm, `mxgraph` is archived and lacks draw.io's shapes, `drawio2svg` is GPL); future offline path = vendoring `viewer-static.min.js` (~3 MB, Apache-2.0). Documented in the architecture explanations. |
| 30 | - ACP payloads cross the WebSocket verbatim (raw `SessionUpdate` / `RequestPermissionRequest`), keeping the front forward-compatible. | 30 | - ACP payloads cross the WebSocket verbatim (raw `SessionUpdate` / `RequestPermissionRequest`), keeping the front forward-compatible. |
| 31 | - One agent session shared by all browsers in v1; multi-session is a planned evolution seam (`bridge.Prompter` interface, per-connection subscriptions). | 31 | - One agent session shared by all browsers in v1; multi-session is a planned evolution seam (`bridge.Prompter` interface, per-connection subscriptions). |
| @@ -36,22 +36,23 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess | |||
| 36 | 36 | ||
| 37 | - `make deps` — npm install in `ui/`. | 37 | - `make deps` — npm install in `ui/`. |
| 38 | - `make build` — SPA build then Go binaries (`bin/ori`, `bin/ori-mock-agent`). Order matters: the Go build embeds `ui/dist`. | 38 | - `make build` — SPA build then Go binaries (`bin/ori`, `bin/ori-mock-agent`). Order matters: the Go build embeds `ui/dist`. |
| 39 | -- `make test` — `go test ./...` + `vitest run`. Also useful: `go test -race ./...`, `go test -short ./...` (skips e2e). | 39 | +- `make test` — `go test ./...` + `vitest run` (the ui `test` script sets `NODE_OPTIONS=--no-experimental-webstorage`: Node 25's built-in `localStorage` lacks `clear()` and shadows jsdom's — 15 store tests fail without it; verified 2026-09-18 on Node 25.9). Also useful: `go test -race ./...`, `go test -short ./...` (skips e2e). |
| 40 | - `make run` — with Claude Code adapter; `make run-mock` — with the demo agent (no Claude/network needed). | 40 | - `make run` — with Claude Code adapter; `make run-mock` — with the demo agent (no Claude/network needed). |
| 41 | -- `make template` — builds the `k33g/ori` sandbox template image (`template/Dockerfile`, FROM `docker/sandbox-templates:claude-code`); launch with `sbx run -d claude <project> --template k33g/ori:0.0.0 --kit <ori repo>/kits/ori --name ori -p 8888:8888` (detached — see the auto-stop trap below) (see `kits/ori/README.md` and docs how-to `run-in-a-sandbox`). | 41 | +- `make template` — builds the `k33g/ori` sandbox template image (`template/Dockerfile`, FROM `docker/sandbox-templates:claude-code`); launch with `sbx run -d claude <project> --template k33g/ori:0.0.2 --kit docker.io/k33g/ori-kit:latest --name ori -p 8888:8888/tcp` (detached — see the auto-stop trap below) (see `kits/ori/README.md` and docs how-to `run-in-a-sandbox`). |
| 42 | -- `scripts/launch-ori.applescript` (2026-09-18) — macOS launcher: `sbx ls -q` → restart by name or create (`k33g/ori:0.0.1`, `./kits/ori`, `-p 5555:8888`), poll `http://localhost:5555/healthz` up to 90 s, then `open ori-desktop/build/bin/ori-desktop.app`. Run with `osascript`, or `osacompile` into `scripts/Launch Ori.app`; repo root derived from the script's own location. Compile-checked and handlers unit-tested; full end-to-end run not yet done. | 42 | +- `scripts/launch-ori.applescript` (2026-09-18) — macOS launcher: `sbx ls -q` → restart by name or create (`k33g/ori:0.0.2`, `./kits/ori`, `-p 5555:8888/tcp`), poll `http://localhost:5555/healthz` up to 90 s, then `open ori-desktop/build/bin/ori-desktop.app`. Run with `osascript`, or `osacompile` into `scripts/Launch Ori.app`; repo root derived from the script's own location. Compile-checked and handlers unit-tested; full end-to-end run not yet done. |
| 43 | - Kit publishing (sbx v0.43.0, verified 2026-09-18): `sbx kit validate kits/ori`, `sbx kit pack kits/ori -o ori-kit.zip`, `sbx kit push kits/ori docker.io/k33g/ori-kit:<tag>` — directory argument, not `spec.yaml`; there is no `sbx kit package`. Auth: `sbx login` session, then `sbx secret set --registry`, then the Docker credential store. | 43 | - Kit publishing (sbx v0.43.0, verified 2026-09-18): `sbx kit validate kits/ori`, `sbx kit pack kits/ori -o ori-kit.zip`, `sbx kit push kits/ori docker.io/k33g/ori-kit:<tag>` — directory argument, not `spec.yaml`; there is no `sbx kit package`. Auth: `sbx login` session, then `sbx secret set --registry`, then the Docker credential store. |
| 44 | - **Kit packaging trap (verified 2026-09-18)**: `pack`/`push` decode `spec.yaml` raw (no `${{ kit.args }}` expansion) — an arg placeholder in an integer field (`ports[].container`) breaks them even though `validate`/`run` accept it. `ports[0].container` is therefore a literal 8888; the `port` arg only drives the startup command and agentInstructions. | 44 | - **Kit packaging trap (verified 2026-09-18)**: `pack`/`push` decode `spec.yaml` raw (no `${{ kit.args }}` expansion) — an arg placeholder in an integer field (`ports[].container`) breaks them even though `validate`/`run` accept it. `ports[0].container` is therefore a literal 8888; the `port` arg only drives the startup command and agentInstructions. |
| 45 | -- Published kit: `docker.io/k33g/ori-kit:latest` (pushed 2026-09-18, verified with `sbx kit inspect`); usable as `--kit docker.io/k33g/ori-kit:latest` instead of `--kit ./kits/ori`. | 45 | +- Published artefacts (2026-09-18): template `k33g/ori:0.0.2` on Docker Hub (multi-arch amd64+arm64, pushed by the user with `./template/build.sh`, ships only `claude-agent-acp`); kit `docker.io/k33g/ori-kit:latest` re-pushed with `--agent-cmd claude-agent-acp` + template 0.0.2. **They must move together**: the first `hello-world` sandbox paired image 0.0.2 with the morning's kit (`claude-code-acp`) and ori died with "executable file not found". |
| 46 | +- **Port publishing traps**: `-p H:8888` without protocol binds `tcp4` only — browsers resolving `localhost` to `::1` fail; always `-p H:8888/tcp` (dual-stack). Chrome refuses ports 6665–6669 (`ERR_UNSAFE_PORT`) whatever the server does. `sbx ports NAME` lists; `sbx ports ls` looks for a sandbox called `ls`. | ||
| 46 | - **sbx auto-stop trap (verified in the sbx source + daemon log, 2026-09-17)**: sandboxd stops a sandbox 30 s (hard-coded `WithAutoStopDelay(30*time.Second)`, `sandboxd/pkg/server/backend_dockernext.go`) after its last CLI "sentinel" session closes; `sbx create`/`sbx exec`/`sbx run` all hold one for their own duration, browser traffic on a published port counts for nothing. Only a sandbox created with the spec field `detached: true` (CLI: `sbx run -d …`, absent from `sbx create`) is exempt; the field is create-time only (no PATCH), so an existing sandbox must be `sbx rm`'d and recreated with `sbx run -d`. No settings/env knob for the delay. | 47 | - **sbx auto-stop trap (verified in the sbx source + daemon log, 2026-09-17)**: sandboxd stops a sandbox 30 s (hard-coded `WithAutoStopDelay(30*time.Second)`, `sandboxd/pkg/server/backend_dockernext.go`) after its last CLI "sentinel" session closes; `sbx create`/`sbx exec`/`sbx run` all hold one for their own duration, browser traffic on a published port counts for nothing. Only a sandbox created with the spec field `detached: true` (CLI: `sbx run -d …`, absent from `sbx create`) is exempt; the field is create-time only (no PATCH), so an existing sandbox must be `sbx rm`'d and recreated with `sbx run -d`. No settings/env knob for the delay. |
| 47 | -- Quality: `python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace .` (gate PASS, run #16, 2026-09-17 late evening: 0 errors, 0 warnings, 0 smells, complex 514 — covers the selectors/previews/desktop work, the resizable file tree and the light/dark theme). | 48 | +- Quality: `python3 .claude/skills/quality/scripts/quality_report.py --workspace .` (the script lives in the repo, not `~/.claude`). Gate PASS, run #18, 2026-09-18: 0 errors, 0 warnings, 0 smells, complex 532 (covers the adapter switch, the MIME pin, the copy-paste feature). **Mac trap**: `.qlty/{logs,out,plugin_cachedir,results}` are symlinks qlty creates into its cache; ones created inside the sandbox point at `/home/agent/…` and dangle on the Mac, making every plugin invocation "FATAL" with no detail — delete the dangling links, qlty recreates them. `.qlty/qlty.toml` pins golangci-lint 2.13.2 (built with Go 1.27): qlty's default 1.61.0 and its latest-known 2.6.2 refuse this repo's `go 1.26.5`. |
| 48 | - `docs/source-code-analysis.adoc` — AsciiDoc snapshot analysis of the codebase (2026-09-17), outside the bilingual Diátaxis set. | 49 | - `docs/source-code-analysis.adoc` — AsciiDoc snapshot analysis of the codebase (2026-09-17), outside the bilingual Diátaxis set. |
| 49 | 50 | ||
| 50 | ## Environment facts (sandbox) | 51 | ## Environment facts (sandbox) |
| 51 | 52 | ||
| 52 | - `~/.qlty` is a dedicated 488MB volume, too small for qlty's tool cache; the cache was moved to `~/.qlty-cache` on the main disk with a symlink `~/.qlty/cache -> /home/agent/.qlty-cache`. If qlty reports "No space left on device", check this symlink survived. (It did NOT survive a sandbox recreation on 2026-09-17: the volume came back empty and the first run failed exactly that way; recreating the symlink fixed it.) | 53 | - `~/.qlty` is a dedicated 488MB volume, too small for qlty's tool cache; the cache was moved to `~/.qlty-cache` on the main disk with a symlink `~/.qlty/cache -> /home/agent/.qlty-cache`. If qlty reports "No space left on device", check this symlink survived. (It did NOT survive a sandbox recreation on 2026-09-17: the volume came back empty and the first run failed exactly that way; recreating the symlink fixed it.) |
| 53 | - `~/.npm` is the same kind of 488MB dedicated volume and filled up when installing Monaco; the npm cache now lives at `~/.npm-big` via `NPM_CONFIG_CACHE` exported in `/etc/sandbox-persistent.sh`. | 54 | - `~/.npm` is the same kind of 488MB dedicated volume and filled up when installing Monaco; the npm cache now lives at `~/.npm-big` via `NPM_CONFIG_CACHE` exported in `/etc/sandbox-persistent.sh`. |
| 54 | -- Running ori inside this Claude-Code-driven sandbox requires `env -u CLAUDECODE ./bin/ori` (Claude refuses nested sessions). Also set `CLAUDE_CODE_EXECUTABLE=<current claude binary>`: the Zed adapter 0.16.2 bundles Claude Code 2.1.44, which rejects the `claude-fable-5-1[1m]` model from the host `~/.claude/settings.json`. **Since 2026-09-18 the API requires CLI ≥ 2.1.251 for that model, and the template's own CLI is 2.1.246 (base image built 2026-08-26)** — so the env var alone is not enough; run `claude update` in the sandbox first, or switch the template to `@agentclientprotocol/claude-agent-acp` (SDK 0.3.274 → CLI 2.1.274). Handoff `2026-09-18-claude-version-too-old.md`. | 55 | +- Running ori inside this Claude-Code-driven sandbox requires `env -u CLAUDECODE ./bin/ori` (Claude refuses nested sessions). With the current template/kit (`claude-agent-acp`, bundled CLI 2.1.274) no `CLAUDE_CODE_EXECUTABLE` is needed. It remains the lever if something spawns the old Zed adapter (points it at another `claude` binary) — but the template's own CLI is 2.1.246 (base image 2026-08-26), below the 2.1.251 floor the API enforces for `claude-fable-5-1[1m]` (host `~/.claude/settings.json`), so `claude update` inside the sandbox would come first. Handoffs `2026-09-18-claude-version-too-old.md`, `2026-09-18-claude-agent-acp-adapter.md`. |
| 55 | - npm blocks install scripts by default here; esbuild's postinstall was approved via `npm approve-scripts` (recorded in `ui/package.json` `allowScripts`). | 56 | - npm blocks install scripts by default here; esbuild's postinstall was approved via `npm approve-scripts` (recorded in `ui/package.json` `allowScripts`). |
| 56 | 57 | ||
| 57 | ## Known limitations | 58 | ## Known limitations |
| @@ -68,7 +69,7 @@ browser ⇆ WebSocket /ws ⇆ Go backend ⇆ stdio (ACP) ⇆ agent subprocess | |||
| 68 | 69 | ||
| 69 | - ori-desktop: the window was launched by the user on their Mac (build OK, Check OK); after the CSS specificity fix (`#connect-screen` outranked `.screen[hidden]`, so the connect screen never hid and the viewer rendered below the fold) it has not yet been confirmed that the iframe actually shows ori inside WKWebView (`wails://` origin loading `http://localhost`; `NSAllowsLocalNetworking` set in `build/darwin/Info.plist`). | 70 | - ori-desktop: the window was launched by the user on their Mac (build OK, Check OK); after the CSS specificity fix (`#connect-screen` outranked `.screen[hidden]`, so the connect screen never hid and the viewer rendered below the fold) it has not yet been confirmed that the iframe actually shows ori inside WKWebView (`wails://` origin loading `http://localhost`; `NSAllowsLocalNetworking` set in `build/darwin/Info.plist`). |
| 70 | 71 | ||
| 71 | -- Behaviour against a real Claude Code session (auth flow, real tool calls) has not been exercised in this sandbox — only against the mock agent and unit doubles. | 72 | +- Real Claude Code sessions: exercised by the user on 2026-09-18 (sandbox `hello-world`, template 0.0.2 + published kit, real prompt answered). Still missing: an automated end-to-end test that drives a real prompt. |
| 72 | 73 | ||
| 73 | ## Tickets (`.tickets/`) | 74 | ## Tickets (`.tickets/`) |
| 74 | 75 | ||