nandi/oripublic Fork 0
b6cd929ab1425a4ef6073ea9c189917cca02cf3c
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

history.md · 190 lines · 38.0 KBmarkdown Blame HistoryRaw
✨ Workspace panel, selectors, previews, desktop app, sandbox template, resizable file tree, light/dark theme 76d62ac k33g yesterday1# History
2
3## 2026-09-17 — Ticket 0004: ACP web client (initial implementation)
4
5- **Goal**: implement `.tickets/issues/0004-specifications.yaml` — a webapp (Go backend + SPA) acting as an ACP client for a code agent (Claude Code first), UI following the principles of Zed's agent panel, designed to evolve. Driven with the `methodical-dev` skill, all checkpoints user-approved.
6- **Changes**: whole codebase created — `cmd/ori`, `cmd/ori-mock-agent`, `internal/{config,httpserver,agent,bridge,mockagent}`, `ui/` (Vite + React 19 + TS SPA with reducer/store/ws-client and panel components), `Makefile`, `biome.json`, `.qlty/qlty.toml`, bilingual `docs/` (en+fr, Diátaxis, 7 pages each), `docs/diagrams/packages.drawio`, root `README.md`.
7- **Decisions**: `coder/acp-go-sdk` for ACP (no official Go lib exists; the claude CLI has no native ACP mode — the user initially chose "native CLI", reversed after verification, and approved the `claude-code-acp` adapter); ACP payloads relayed verbatim to the browser; server as single source of truth with history replay + `user_message` echo; one shared session in v1. Mid-session the user corrected the Go module path from `github.com/bots-garden/ori` to `rickub.com/bots-garden/ori` (repo not on GitHub) — renamed everywhere, tests green.
8- **Tests**: 7 config + 6 httpserver + 10 agent (in-memory mock ACP agent) + 15 bridge (incl. 4 real-WebSocket integration) + 2 mockagent + 1 full e2e (compiled mock binary, real subprocess, real WS, permission round-trip, late-joiner replay) — all green incl. `-race`; 28 frontend tests (reducer, ws client with fake WebSocket, components) — green. One command: `make test`.
9- **Quality**: gate **PASS** (0 errors / 0 warnings / 0 smells, total complexity 145; started at 13/4/5/158). Config adjustments user-approved (see summary). Two environment fights: the 488MB `~/.qlty` volume (cache symlinked to main disk) and a partial JDK extraction.
10- **Docs**: `docs/en/` + `docs/fr/` complete four-quadrant sets; package diagram in draw.io; root README quick start.
11
12## 2026-09-17 — Live thinking block + working spinner (same session, follow-up)
13
14- **Goal**: after testing against real Claude Code, the user asked for (1) the agent's thinking content visible live while it streams, (2) a spinner with rotating phrases while the agent works, Claude-style.
15- **Changes**: new `ui/src/components/WorkingIndicator.tsx` (spinner + `workingPhrases` rotating every 2.5s), `ChatThread` refactored with a `ThoughtEntry` component (live open block `💭 Thinking…` while streaming, collapsible `💭 Thought for a moment` once the turn ends), CSS spinner/thought-live, tutorials updated in both languages.
16- **Decisions**: live-vs-collapsed decided by the existing `closed` flag on thought items (no reducer change needed); phrases exported for deterministic tests.
17- **Tests**: +3 WorkingIndicator (fake timers: first phrase, rotation, wrap-around) and +2 App (thought open→collapsed across turn end; spinner present during a turn, gone after) — 33 frontend tests green, Go suite untouched.
18- **Quality**: gate PASS again (a first re-run flagged `ThreadEntry` at 6 returns; fixed by extracting `ThoughtEntry`).
19- **Also verified this session**: real Claude Code works end to end via `env -u CLAUDECODE ./bin/ori` (nested-session guard); adapter package renamed upstream to `@agentclientprotocol/claude-agent-acp` (default not changed yet).
20
21## 2026-09-17 — Workspace panel: preview, editor, terminal, monospace command output (same session, follow-up 2)
22
23- **Goal**: user-requested evolutions — a preview panel (syntax-highlighted code + rendered Markdown/AsciiDoc), a terminal panel, a file editor panel (Monaco), and monospace rendering for system-command output in the chat.
24- **Changes**: backend `internal/files` (list/read/write file API, unrestricted access per user's explicit choice) and `internal/terminal` (PTY shell per WebSocket, creack/pty); frontend workspace layout (chat left + collapsible right panel: file tree with lazy directories, Preview/Editor/Terminal tabs kept mounted when inactive), `MonacoViewer` shared by read-only preview and editor (bundled workers, lazy chunk), AsciiDoc rendering via lazy `@asciidoctor/core`, xterm.js terminal, `tool-output` monospace block for `execute` tool calls. New deps: creack/pty, monaco-editor + @monaco-editor/react, @asciidoctor/core, @xterm/xterm + addon-fit.
25- **Decisions**: layout chat+workspace (user), interactive user terminal only in v1 (ACP terminals later, user), free filesystem/terminal access (user — sandbox assumed isolated), Monaco over CodeMirror (user); panes hidden not unmounted so the shell survives tab switches; monaco 0.56 import specifiers go through its exports map (no `esm/vs/` prefix).
26- **Tests**: +9 files API, +5 terminal PTY integration (real shell over real WS: command output, cwd, resize via stty, malformed frames, exit closes socket) → 46 Go tests incl. e2e; front +5 workspace store, +4 FileTree, +8 lang detection, +6 PreviewPane, +6 EditorPane, +4 TerminalPane (xterm/WS mocked), +2 ToolCallCard mono/markdown → 66 front tests. All green, `-race` clean.
27- **Quality**: gate PASS (0/0/0, total complexity 281). Iterations: biome 1.9 rejects the `noStaticElementInteractions` suppression (rule doesn't exist there — removed), the dangerouslySetInnerHTML suppression must sit between JSX attributes, EditorPane/ToolContent refactored (extracted EditorHeader/editorPlaceholder/TextToolContent) to clear return/complexity smells.
28- **Docs**: new how-to `use-the-workspace` + reference `workspace-api` in both languages; architecture pages and indexes updated; drawio diagram extended (files, terminal, pty, SPA runtime edges); root README.
29
30## 2026-09-17 — Source code analysis document (new session)
31
32- **Goal**: analyse the source code and produce a summary as an AsciiDoc document.
33- **Changes**: new `docs/source-code-analysis.adoc` — overview, backend package table, frontend module/component inventory, HTTP/WS endpoints, bridge protocol summary, test counts (55 Go tests + 1 e2e, ~215 vitest cases), Makefile targets, design decisions, known limitations. No code changed.
34- **Method**: read `.memory/` first, then an Explore agent verified the memory picture against the sources (LOC: ~3,064 Go / ~3,252 TS-TSX).
35- **Tests / quality**: not run — documentation-only session, no code touched.
36
37## 2026-09-17 — Workspace polish: AsciiDoc fix, VS Code-style tree with Material icons, dark terminal (same session, follow-up 3)
38
39- **Goal**: user feedback after trying the workspace — AsciiDoc preview broken in production ("m is not a function"), file tree should look like VS Code's with Material icons, terminal should always be dark.
40- **Changes**: AsciiDocView now uses @asciidoctor/core v4's real API — `convert` is a **named export and asynchronous** (the v3 `asciidoctor()` factory no longer exists; my CJS-default cast called `undefined()`); added a **non-mocked** AsciiDocView test rendering with the real converter — the mocked-only tests were exactly why the breakage reached production. FileTree restyled VS Code-like: `vscode-material-icons` (910 SVGs copied to `ui/public/material-icons/` by `ui/scripts/copy-icons.mjs`, npm pre-hooks on dev/build, gitignored), chevrons, indent guides, open-folder icons, active-file highlight. Terminal always dark (`#1e1e1e`) whatever the app theme.
41- **Tests**: +2 real AsciiDoc render, +2 FileTree (icons present, active highlight) → 70 front tests, all green; Go untouched (46).
42- **Quality**: gate PASS.
43
44## 2026-09-17 — Inline monospace for backticked commands (same session, follow-up 4)
45
46- **Goal**: user feedback — tool titles like ``Run `ls .memory/` `` showed literal backticks in a proportional font.
47- **Changes**: new `InlineText` component (backtick spans → `<code class="inline-code">`, no markdown pipeline), applied to tool call titles, permission titles and plan entries; `.inline-code` CSS.
48- **Tests**: +4 InlineText (spans, multiples, plain, unpaired backtick) and +1 ToolCallCard title assertion → 75 front tests green.
49
50## 2026-09-17 — sbx template + kit for ori (same session, follow-up 5)
51
52- **Goal**: package ori as a Docker Sandboxes template (image `k33g/ori`, the user builds it under their handle) and add a kit to launch it easily from sbx.
53- **Changes**: `template/Dockerfile` (multi-stage: node builds the SPA, go builds the binaries, final layer = `docker/sandbox-templates:claude-code` + globally installed `@zed-industries/claude-code-acp` + `/usr/local/bin/{ori,ori-mock-agent}`, EXPOSE 8888, standalone CMD), `.dockerignore` (excludes the 635MB `sandboxes/` checkout, node_modules, .git…), `kits/ori/spec.yaml` (schemaVersion 2 mixin: idempotent `setup.startup` launching ori as the agent user on :8888, agentInstructions), `kits/ori/README.md`, `make template`, how-to `run-in-a-sandbox` in docs en+fr.
54- **Decisions**: no `sbx template build` exists — a template IS a container image passed via `sbx create claude --template k33g/ori`, and `--kit` accepts a mixin directory (verified in `sandboxes/docs/yml/sbx_create_claude.yaml`); the ori kit adds no network permissions (Anthropic hosts come from the claude agent kit, the adapter is baked into the image); kit startup guarded by `pgrep -x ori` because startup commands re-run on every container start.
55- **Tests/validation**: image built locally (2.81GB) and smoke-tested standalone with the mock agent (healthz + session OK); the kit's exact startup command exec'd in a sleeping container of the image → adapter session created, healthz OK; idempotency check OK; kit YAML parse-validated.
56
57## 2026-09-17 — Kit refinements from the sbx source deep-dive (same session, follow-up 5b)
58
59- A thorough exploration of the sbx source confirmed the template/kit design and yielded three refinements applied to `kits/ori/spec.yaml`: `requires: {agent: claude}` (mixin-only field, enforces composition with the claude agent kit), a `ports:` block (container 8888 — kits auto-publish an ephemeral localhost port at create; Dockerfile EXPOSE is read by nothing), and dropping `user: "agent"` from the startup step (StartupCommand.user defaults to "1000", the agent uid; "agent" is non-standard).
60- Also learned and documented: sandboxd has its own image store — a never-pushed local image reaches it via `docker save` + `sbx template load`; kit references resolve fresh each create (no local kit registry); `sbx kit validate/pack/push` exist for distribution; an alternative shape (kind:sandbox + `extends: claude` + `sandbox.image: k33g/ori`) would allow `sbx create ./kits/ori .` in one argument — not adopted, the mixin matches the dev-toolkit pattern already in use.
61
62## 2026-09-17 — build.sh, Hub publication at 0.0.0, parameterized kit port, quickstart (same session, follow-up 5c)
63
64- **Goal**: user wants to push `k33g/ori` to Docker Hub — a `template/build.sh` they run themselves, image tagged `0.0.0`; the kit's listen port made configurable; a `quickstart.md` with the sandbox-creation commands.
65- **Changes**: `template/build.sh` (multi-arch buildx --push, tags 0.0.0 + latest, VERSION as $1, PLATFORMS overridable); `kits/ori/spec.yaml` gained `args.port` (default "8888", pattern-validated) substituted into `ports.container` (unquoted `${{ kit.args.port }}` — the source's expand.go explicitly re-infers it as an integer), the startup `--addr`, and the agentInstructions; `quickstart.md` at the repo root; kit README and both run-in-a-sandbox pages now reference `k33g/ori:0.0.0` and `--kit-arg ori.port=`.
66- **Validation**: spec YAML parses with the arg refs; build.sh is the push path, `make template` stays the local-only path. The actual Hub push is the user's action (their Docker login).
67
68## 2026-09-17 — Multi-arch build fix: no qemu in the template build (same session, follow-up 5d)
69
70- **Problem**: the user's `./template/build.sh` failed on the linux/amd64 half — on an arm64 host that stage runs under qemu, where Vite bundling Monaco exhausts Node's 2GB heap ("FATAL ERROR: Ineffective mark-compacts near heap limit", "qemu: uncaught target signal 6").
71- **Fix**: every build stage now runs on `--platform=$BUILDPLATFORM`: the SPA build is platform-independent (built once, natively), Go cross-compiles with `GOOS=$TARGETOS GOARCH=$TARGETARCH`, and the ACP adapter is npm-installed in a native stage then COPY'd into the template's npm prefix (`/usr/local/share/npm-global`, agent-owned, on PATH). The final stage contains no RUN at all, so a multi-arch build never invokes qemu.
72- **Validation**: native rebuild green; smoke tests pass (healthz with mock agent; `claude-code-acp` resolves from the copied prefix and initializes a real ACP session).
73
74## 2026-09-17 — Kit startup fix: su resets PATH (same session, follow-up 5e)
75
76- **Problem**: the user's real `sbx create … --kit ./kits/ori -p 5555:8888` came up with nothing listening. Root cause read from the sbx source (`sandboxlib/kit/durable_startup.go`): startup commands are rendered as `exec su -s /bin/sh -c '<script>' agent`, and util-linux `su` always resets PATH to the login.defs default — which lacks `/usr/local/share/npm-global/bin`, so ori died instantly with "claude-code-acp: executable file not found". Reproduced in the image (`su -c 'command -v claude-code-acp' agent` → missing); my earlier validation had used `docker exec`, which preserves image ENV — that's why it passed.
77- **Fix**: the kit's startup script now exports `PATH="/usr/local/share/npm-global/bin:/home/agent/.local/bin:$PATH"` first (comment marks it load-bearing). Re-validated through the exact `su` path: healthz OK, ACP session created.
78- **No image rebuild needed** — kit-side only; the user must `sbx rm` and recreate the sandbox for the new kit to apply. Debug window for kit startup: `/var/log/sbx-kit-startup.log` (dispatcher log) + `/home/agent/.ori.log`.
79
80## 2026-09-17 — Session end inside the sandbox: WS-offline investigation in flight (follow-up 5f)
81
82- After the su-PATH fix, the user's sandbox serves the SPA on localhost:5555 but the UI shows "offline" (the WebSocket to /ws does not stay up). Established before stopping: ori's WS handshake is correct against browser-like Origin headers (101 for localhost:* origins, 403 for foreign — tested with curl against the image); sbx port publishing goes through gvisor's port mapper (raw L4, so the upgrade should pass). Three discriminating diagnostics were handed to the user (server log; WS handshake from inside the sandbox; WS handshake through the forward) — answers not yet received. The session ends here: the user is relaunching the assistant outside sbx.
83- Everything since commit 2434cc7 is still uncommitted (user's call, repeatedly deferred).
84
85## 2026-09-17 — Why the ori sandbox stops on its own: sbx auto-stop investigation (follow-up 6, read-only)
86
87- **Asked**: the sandbox created with `sbx create claude . --template k33g/ori:0.0.0 --kit ./kits/ori --name ori -p 8888:8888` serves the webapp then goes `stopped` by itself; find the auto-stop mode in the sbx source and a way to disable it.
88- **Found** (in `sandboxes/`, the vendored sbx checkout, v0.43.0 daemon on this Mac): sandboxd counts "sentinel" long-poll sessions per sandbox (`GET /sandbox/{name}/session`, `holdSession` in `sandboxd/pkg/server/backend_dockernext.go`); when the count hits zero it stops the container after a hard-coded 30 s grace (`WithAutoStopDelay(30*time.Second)` in `setupDockerNextBackend`). `sbx create` holds a sentinel only for its own lifetime (`executeCreateAndReleaseSession` in `cli-plugin/commands/create.go`), so the stop fires 30 s after the command returns — confirmed by the daemon log (`session disconnected, deferring auto-stop``auto-stopped runtime` 30 s later for `ori` and `ori2`). Port publishing and browser traffic hold no session.
89- **Escape hatch**: the create-time spec field `detached: true` (openapi `SandboxCreateRequest.detached`) makes `holdSession` never auto-stop. Only `sbx run -d/--detached` sets it (`create_daemon.go: Detached: opts.detached`); `sbx create` has no such flag; there is no update API, no `sbx settings` key and no env var for the delay.
90- **Recommendation given**: `sbx rm ori` then `sbx run -d claude . --template k33g/ori:0.0.0 --kit ./kits/ori --name ori -p 8888:8888`.
91- **Docs switched (same session, at the user's request while they tested)**: `quickstart.md`, `kits/ori/README.md`, `docs/en|fr/how-to/run-in-a-sandbox.md` now use `sbx run -d`, explain the 30 s auto-stop and why detached is the fix, and add a restart line (`sbx run -d --name <name>`) plus a daemon-log diagnostic hint. No `sbx create` invocation remains in project docs. No code change.
92- **Also observed**: the WS-"offline" symptom from follow-up 5f is very plausibly this same stop (the page was already loaded when the container died), still to be confirmed by the user.
93
94## 2026-09-17 — Three parallel agents: ori-desktop (Wails), @/skill selectors + draw.io/image previews, ACP command inventory
95
96- **Asked**: (bob) create `ori-desktop/`, a Wails app connecting to the ori webapp; (riker) add an `@` file selector, a skill selector, draw.io and image previews; (milo, read-only) list the ACP commands exposed. Then the user built ori-desktop on their Mac: Check OK, Connect "did nothing".
97- **bob**: new module `ori-desktop/` (Wails v2.16.0, plain template, iframe embed of the ori SPA, settings JSON, bound methods, `internal/settings` + `internal/health` with 12 tests, EN+FR READMEs, `make desktop`/`desktop-test`, .gitignore, ticket 0005 filled). Verified: tests, vet, gofmt, Windows cross-build, root `make build`/`make test` unaffected. Not verifiable in the sandbox: running the window (no gcc/webkit2gtk).
98- **riker**: `GET /api/files/search`, `GET /api/raw`, new `internal/skills` + `GET /api/skills`; `prompt.attachments` → ACP `resource_link` blocks (`Prompter.Prompt(blocks)` replaces `PromptText`, `Bridge.SetWorkspaceRoot`); reducer stores `available_commands_update` commands; `mentions.ts`, `useCompletion.ts`, `CompletionPopup`, rewritten `PromptInput`, `ImageView`, `DrawioView` (embed.diagrams.net + Source fallback), `lang.ts` kinds `image`/`drawio`; mock agent emits commands and echoes attachments; Vite dev proxy gained `/api`; `biome format --write` reformatted 11 files. Docs EN+FR: workspace-api, websocket-protocol, use-the-workspace, new how-to `mention-files-and-skills`, architecture sections, READMEs. Tickets 0008/0009/0011/0012 filled.
99- **milo**: ori calls `initialize`, `session/new`, `session/prompt`, `session/cancel`; serves `session/update`, `session/request_permission`, `fs/read_text_file`, `fs/write_text_file`; refuses `terminal/*`; unused stable methods: `authenticate`, `logout`, `session/load|resume|list|close|set_mode|set_config_option`. "Agent commands" are not ACP methods: `available_commands_update``/name` text in the prompt. Relayed to riker, who implemented it (ticket 0008).
100- **Bug fixed after the user's test**: `ori-desktop/frontend/src/main.css``#connect-screen {display:grid}` outranked `.screen[hidden]`, so Connect (and the startup auto-connect) rendered the viewer below the fold; now class `.connect` + `.screen[hidden] {display:none !important}`. Rebuild needed (`wails build`); iframe content in WKWebView still unconfirmed.
101- **Tests**: `make test` → 9 Go packages ok, vitest 16 files / 102 tests (was 66); `go test -race ./...` ok (riker installed gcc + libc6-dev via apt in the sandbox for it).
102- **Quality gate**: NOT run — qlty absent from this sandbox (`~/.qlty` missing). gofmt / go vet / biome check clean.
103- Nothing committed (still everything since 2434cc7).
104
105## 2026-09-17 — Launch ori for manual testing of the new features (evening session)
106
107- **Asked**: "lance ori que je puisse tester les nouveautés". No code change: `make build` (SPA + binaries), then `env -u CLAUDECODE nohup ./bin/ori --addr 0.0.0.0:8888 > /tmp/ori.log 2>&1 &` inside the `claude-ori` sandbox. Adapter `@zed-industries/claude-code-acp@0.16.2` resolved via npx (npm now flags it deprecated → renamed `@agentclientprotocol/claude-agent-acp`; still works). ACP session ready, `/healthz` ok, `/api/skills` lists the skills. Port 8888 must be published on the host with `sbx ports claude-ori --publish 8888:8888/tcp` (not doable from inside the sandbox).
108- Trap hit: a `curl` WebSocket handshake against `/ws` never returns on success (101 keeps the socket open) — use `-m` or check the log instead.
109- **Follow-up (same session)**: first real prompt failed with `-32603 There's an issue with the selected model (fable[1m])`. Root cause: `@zed-industries/claude-code-acp@0.16.2` bundles `@anthropic-ai/claude-agent-sdk@0.2.44`, whose embedded Claude Code CLI is **2.1.44** (zero mentions of Fable), while `~/.claude/settings.json` sets `"model": "fable[1m]"` and the adapter forwards it verbatim. The system CLI (2.1.275) accepts `fable[1m]` fine. Fix without touching the user's settings: the adapter honours `CLAUDE_CODE_EXECUTABLE``pathToClaudeCodeExecutable`; ori relaunched with `CLAUDE_CODE_EXECUTABLE=/home/agent/.local/share/claude/versions/2.1.275`; a WS prompt round-trip returned `pong` (`turn_ended end_turn`). No code change.
110
111## 2026-09-17 — Resizable file explorer column (ticket 0015), via methodical-dev
112
113- **Goal**: make the workspace file tree column resizable with the mouse; user chose localStorage persistence and the file-tree divider only (not the chat/workspace split).
114- **Changes**: `ui/src/workspace.ts` (`fileTreeWidth`, `setFileTreeWidth`, `resetFileTreeWidth`, `clampFileTreeWidth`, constants, guarded localStorage), new `ui/src/components/ResizeHandle.tsx` (+ test), `Workspace.tsx` (handle between tree and tabs, `--filetree-width` on the aside; new `Workspace.test.tsx`), `app.css` (`.filetree` width from the variable, `.resize-handle` styles). Ticket 0015 closed.
115- **Decisions**: width in px (drag produces px; comparable with bounds); FileTree untouched — width reaches CSS via a custom property; handle owns no width, the store clamps. jsdom 26 has no PointerEvent → test-local MouseEvent polyfill.
116- **Quality gate** (first run of qlty on the tree since the parallel-agents session): 12 errors / 1 warning / 2 smells, all pre-existing — fixed without weakening anything: `ori-desktop/frontend/src/main.js` became an ES module (`type="module"`, IIFE and `"use strict"` dropped, optional chains, template literals, `reloadFrame()` instead of `src = src`), `internal/files/raw.go` explicit `_ = file.Close()` with rationale, `internal/files/search.go` walk callback → `searchWalker.visit/visitDir/collect`, `PreviewPane.tsx` loading effect → `usePreviewFile` hook; `qlty fmt` on main.css / main.js / wails.json. Run #15 PASS (0/0/0, complex 507).
117- **Tests**: 118 vitest (18 files), 9 Go packages, ori-desktop 2 packages — green. `make test`.
118- **Docs**: how-to `use-the-workspace` (step 5 + keyboard/persistence variant) and architecture explanation, EN + FR; root README; ori-desktop READMEs (ES module).
119- **Not verifiable here**: the ori-desktop frontend change (ES module) needs a `wails build` + launch on the user's Mac.
120
121## 2026-09-17 — Light / dark theme selector, light by default (ticket 0013)
122
123- **Goal**: user request received mid-session; choices made via AskUserQuestion: two themes only (no "system" option), single review at the end.
124- **Changes**: new `ui/src/theme.ts` (+ `theme.test.ts`), `app.css` (dark palette on `:root[data-theme="dark"]`, `color-scheme` per theme, `.topbar-theme`), `App.tsx` (☾/☀ button, aria-label "Switch to dark/light theme"), `MonacoViewer.tsx` (store instead of `matchMedia`), `main.tsx` (side-effect import so the theme is stamped before the first render), `App.test.tsx` (+1). Ticket 0013 closed.
125- **Decisions**: dropping `prefers-color-scheme` is a behaviour change (dark-OS users now get light until they toggle) — accepted by the user ("light par défaut"); documented in the architecture explanation. Terminal keeps its dark background (pre-existing decision).
126- **Tests**: 124 vitest / 19 files green; Go untouched. **Quality**: run #16 PASS (0/0/0, complex 514).
127- **Docs**: new how-to `switch-the-theme.md` EN + FR, both indexes, architecture explanation paragraph EN + FR, root README.
128- ori rebuilt and restarted on :8888 for the user's review.
📝 Update project memory after the merge into main 3017563 k33g yesterday129
130## 2026-09-17 — Commit and merge into main
131
132- User asked to merge `feat/acp-webapp` into `main`. Everything since 2434cc7 committed as `76d62ac` (203 files, +21 595 lines), excluding `hello.md` (test artefact) and `.claude/settings.local.json` (local permissions). `main` fast-forwarded (merge base was 4edda86, no divergence). Not pushed to `origin` (git.rickub.com) — not asked. This memory update itself is a follow-up commit on main.
🛟 Updated. ca7e020 k33g yesterday133
134## 2026-09-18 — Diagnose `git push --set-upstream origin main` hanging
135
136- **Asked**: why the first push to `origin` never finishes. Diagnostic only; no code or config changed.
137- **Finding**: `origin` is `https://git.rickub.com/bots-garden/ori.git`; the server answers 401 on `git-receive-pack`, the macOS keychain has no entry for that host, and the session (launched from VSCodium's terminal) exports `GIT_ASKPASS` → VSCodium's `askpass.sh`. Git therefore hands the password prompt to VSCodium's input box, which is easy to miss, so the push waits forever. Confirmed with `ps`: `git-remote-https``askpass.sh "Password for 'https://git.rickub.com'"` blocked.
138- **Also verified**: network fine (DNS, 443, 22 all open); anonymous read over HTTPS works; SSH key `~/.ssh/id_ed25519` is accepted by `git@git.rickub.com` (server replies "serves git only"); `git ls-remote` over SSH succeeds and shows the remote repo is **empty** (no branches yet). Local `main` = 34e69b5.
139- **Recommendation left to the user**: switch `origin` to `git@git.rickub.com:bots-garden/ori.git` (no password, key already trusted), or run the push in a plain terminal with `GIT_ASKPASS` unset so osxkeychain stores the credentials. Not applied — awaiting the user's choice.
🛟 Updated. f5c963a k33g yesterday140
141## 2026-09-18 — AppleScript launcher for the ori sandbox + desktop app
142
143- **Asked**: an AppleScript that runs `sbx run -d claude . --template k33g/ori:0.0.1 --kit ./kits/ori --name ori -p 5555:8888` then launches `ori-desktop/build/bin/ori-desktop.app`.
144- **Changes**: new `scripts/launch-ori.applescript`; one row in `quickstart.md` (everyday commands); pointer in `summary.md`.
145- **Decisions**: (1) if `sbx ls -q` already lists `ori`, restart it with `sbx run -d --name ori` instead of re-running the create command (which would collide on the name); errors on that path only notify, the health check decides. (2) Poll `/healthz` on :5555 (2 s × 45) before opening the app, because the kit starts the server asynchronously and the desktop app auto-connects to the saved URL (`~/Library/Application Support/ori-desktop/settings.json` already holds `http://localhost:5555`). (3) `PATH` exported explicitly (Finder launches lack `/opt/homebrew/bin`). (4) Repo root derived from `path to me` so the compiled `.app` works from `scripts/` too. Rejected: `sbx rm` + recreate on every launch (destroys the sandbox's Claude session/state).
146- **Tests**: `osacompile` OK; handlers exercised via `load script`: `sandboxExists` → false with no sandbox, `waitForServer` → false on a closed port, true against a throw-away Python `/healthz` on :5555. Not run end to end (would create a real sandbox and start Claude in it). Quality gate not re-run (no Go/TS touched).
147
148## 2026-09-18 — Ticket 0005 back to the IssueSpec task schema; launcher compiled as an app
149
150- **Asked**: "le ticket 0005 n'est plus au bon format"; then how to make the AppleScript launcher double-clickable.
151- **Cause**: the 0005 checklist had been hand-written as `- text: … / done: true|false`, which is not IssueSpec's task shape (`id`, `title`, `state`, `priority`, `author`, `createdAt`, optional `updatedAt`/`closedAt`). IssueSpec's parser rejects the file: "tasks[0].id must be a positive integer".
152- **Changes**: `.tickets/issues/0005-….yaml` — 8 tasks rewritten (7 `closed` with `updatedAt`/`closedAt` = 2026-09-17T22:23:39Z, 1 `open`; all `priority: none`, author k33g); issue `updatedAt` bumped. `scripts/Launch Ori.app` built with `osacompile`, ignored via `.gitignore` (`scripts/*.app/`). `summary.md` gains a `.tickets` paragraph.
153- **Verification**: bundled IssueSpec's `parseIssueDocument` (from the local clone `~/CodeBerg/issuespec`, esbuild `--format=cjs`) and ran it over all 15 tickets: all OK; the committed 0005 fails as expected.
154- **Follow-up**: `scripts/README.md` + `scripts/README.fr.md` written (what the launcher does, run vs. double-click, design choices, handler test recipe); quickstart row now points to it.
✨ Switch the ACP adapter to @agentclientprotocol/claude-agent-acp (template 0.0.2) 5d476ff k33g yesterday155
156## 2026-09-18 — `sbx kit package` does not exist
157
158- User hit `ERROR: sbx: unknown command: sbx kit package` (sbx v0.43.0). The verbs are `sbx kit pack DIRECTORY [-o file.zip]` (local ZIP) and `sbx kit push DIRECTORY registry/repo:tag` (package + push to OCI, adds SLSA provenance, `--sign` optional). Both take the kit **directory**, not `spec.yaml`. `sbx kit validate kits/ori` → VALID. Not pushed: publishing to Docker Hub left to the user.
159
160## 2026-09-18 — `sbx kit push` rejected the kit: arg placeholder in an integer field
161
162- **Asked**: `sbx kit push kits/ori docker.io/k33g/ori-kit:latest` failed with `invalid spec.yaml: line 38: cannot unmarshal !!str `${{ kit...` into int`.
163- **Cause (verified in `sandboxes/` source, v0.44.0-rc1+26, and by trial)**: `Pack`/`Push` call `LoadFromDirectory` → strict typed decode of the raw spec (`ports[].container` is `int`), with **no** `${{ kit.args.* }}` expansion; `validate`/`inspect`/`run` expand first (`expand.go`, `argScan`), hence VALID vs INVALID for the same directory. v3 kits (`schemaVersion: "3"`, `com.docker.runtime/port@1` capabilities) keep placeholders at push and expand at pull, but the installed sbx v0.43.0 has no v3 support (0 hits for the capability type in the binary).
164- **Changes**: `kits/ori/spec.yaml` `ports[0].container` → literal `8888` with a comment explaining why; `${{ kit.args.port }}` kept in the startup command and agentInstructions (string fields decode fine). Kit README, docs EN/FR how-to `run-in-a-sandbox`: with a custom port, publish it with `-p` since the declared port stays 8888. Rejected: dropping the `port` arg (loses a documented feature); moving to v3 (needs sbx ≥ 0.44 on every consumer).
165- **Verification**: `sbx kit validate kits/ori` (default and `--kit-arg ori.port=9000`) VALID; `sbx kit pack kits/ori` OK; `inspect --kit-arg ori.port=9000` shows `--addr ":9000"` substituted with `"container": 8888`. **Push not run** — the user publishes.
166- **Follow-up**: kit published by the user; `sbx kit inspect docker.io/k33g/ori-kit:latest` resolves (mixin, schema v2, 1 port, 1 startup command). Sandboxes running at that time: `ori` (5555→8888) and `hello-ori` (3000→8888), both on this repo.
167
168## 2026-09-18 — "Claude Code 2.1.44 does not support this model; 2.1.251 or newer required"
169
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.
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.
📝 Update project memory after the adapter switch (summary, history, handoff) 4166f8f k33g yesterday173
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.
🛟 Updated. b6cd929 k33g yesterday181
182## 2026-09-18 — Linux build of ori-desktop (webkit2gtk-4.1) + MIT LICENSE
183
184- **Asked**: `cd ori-desktop && wails build`; then, mid-session, "ajoute un fichier de licence MIT".
185- **Build**: installed the Wails CLI (`go install …/cmd/wails@v2.16.0`) and the GUI toolchain (`sudo apt-get install libgtk-3-dev libwebkit2gtk-4.1-dev`) in the sandbox — they were absent, which is why the window had never been launched here. Plain `wails build` fails: Wails' cgo pkg-config asks for `webkit2gtk-4.0`, Ubuntu 26.04 only ships 4.1. `wails build -tags webkit2_41``build/bin/ori-desktop`, ELF aarch64, 9.4 MB, 4.8 s. `wails doctor` still says `libwebkit: Not Found` (it only probes 4.0) — a false negative. No source change was needed.
186- **Not done**: no macOS build — Wails cannot cross-compile to macOS from Linux, and the `.app` the user actually launches (`build/bin/ori-desktop.app`, and the AppleScript launcher) must still be built on the Mac. The Linux binary was added next to the existing `.app` and `.exe`, overwriting neither. The window itself was not run (no display in the sandbox).
187- **Changes**: `LICENSE` (MIT, `Copyright (c) 2026 k33g`) at the repository root — the only file added to the tree; `build/bin/` and `frontend/wailsjs/` are gitignored. `.memory/summary.md`: the `-tags webkit2_41` requirement and the three build outputs on the `ori-desktop/` bullet, the apt/CLI install recipe under "Environment facts", the licence line.
188- **Decisions**: holder `k33g` (the name used by every ticket author block and the git identity), not a guessed legal name. Root-only LICENSE, no copy under `ori-desktop/` despite it being a separate Go module. `make desktop` left untouched even though it fails on Linux for want of the tag — a Makefile change was outside what was asked; flagged to the user instead.
189- **Verification**: `go test ./internal/...` in `ori-desktop` green (health, settings). Quality gate not re-run: no Go/TS source was modified.
190- **Follow-up (same session)**: `ori-desktop/how-to-build.md` written on request — prerequisites, the from-where/to-what cross-build matrix (macOS only from macOS; Windows from anywhere; Linux from Linux), one section per platform, the `wails build` flags that matter, `wails dev`, the tests, and a troubleshooting list (webkit 4.0 vs 4.1, the `wails doctor` false negative, `make desktop` on Linux, the lost execute bit under cloud sync, Gatekeeper/`xattr -cr`, empty window = no server). English only, house Diátaxis how-to style; `how-to-build.fr.md` NOT written and `README.md` NOT linked to it — the user's own edits to `ori-desktop/README*.md` are uncommitted in the tree and were left alone. All four relative links in the doc were checked to resolve.