Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
59cdcf6
perf(ui): bound expensive transcript rendering
pascalandr Aug 12, 2026
635228a
perf(ui): cap inactive transcript memory
pascalandr Aug 12, 2026
20dfdc2
perf(ui): cancel obsolete transcript work
pascalandr Aug 12, 2026
bb39dab
perf(ui): harden bounded transcript memory
pascalandr Aug 13, 2026
1ca5471
merge(DEV-v2): refresh bounded transcript memory
pascalandr Aug 18, 2026
68955d3
Merge branch 'DEV-v2' into refresh/pr648-20260818
pascalandr Aug 18, 2026
4e40628
Merge remote-tracking branch 'upstream/DEV-v2' into refresh/pr648-202…
pascalandr Aug 18, 2026
b8fd968
Merge remote-tracking branch 'upstream/DEV-v2' into refresh/pr648-202…
pascalandr Aug 19, 2026
1b6de75
Merge remote-tracking branch 'upstream/DEV-v2' into refresh/pr648-202…
pascalandr Aug 19, 2026
1e5f80c
Merge remote-tracking branch 'upstream/DEV-v2' into refresh/pr648-202…
pascalandr Aug 19, 2026
4700b23
Merge branch 'DEV-v2' into refresh/pr648-20260818
pascalandr Aug 19, 2026
a6b355a
fix(ui): close transcript memory gate findings
pascalandr Aug 19, 2026
5301ce5
fix(ui): close truncated diff approval bypasses
pascalandr Aug 19, 2026
360a224
fix(memory): isolate live reducers and cache replacement
pascalandr Aug 19, 2026
760a7c5
Merge branch 'DEV-v2' into refresh/pr648-20260818
pascalandr Aug 19, 2026
87bd430
Merge branch 'DEV-v2' into refresh/pr648-20260818
pascalandr Aug 19, 2026
bd57dc1
Merge branch 'DEV-v2' into refresh/pr648-20260818
pascalandr Aug 19, 2026
5484f9c
fix(v2): use native shells for background processes
pascalandr Aug 19, 2026
4a8dcd7
Merge branch 'DEV-v2' into refresh/pr648-20260818
pascalandr Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,21 +103,25 @@ jobs:

- name: Test changed runnable UI behavior
run: >-
node --import tsx --test
node --import tsx --test --test-force-exit
packages/ui/src/components/message-timeline-v2.test.ts
packages/ui/src/components/provider-auth/provider-options.test.ts
packages/ui/src/components/session/session-bottom-pin-intent.test.ts
packages/ui/src/components/session-list-visibility.test.ts
packages/ui/src/components/tool-call/render-memory.test.ts
packages/ui/src/components/unified-picker-path.test.ts
packages/ui/src/components/virtual-follow-behavior.test.ts
packages/ui/src/lib/filesystem-events.test.ts
packages/ui/src/lib/global-cache.test.ts
packages/ui/src/lib/hooks/use-app-session-capture.test.ts
packages/ui/src/lib/hooks/use-instance-metadata.test.ts
packages/ui/src/lib/hooks/use-foreground-refresh.test.ts
packages/ui/src/lib/launch-errors.test.ts
packages/ui/src/lib/message-selection-position.test.ts
packages/ui/src/lib/model-visibility.test.ts
packages/ui/src/lib/retained-size.test.ts
packages/ui/src/lib/runtime-env.test.ts
packages/ui/src/lib/session-transcript-lru.test.ts
packages/ui/src/lib/trailing-resync.test.ts
packages/ui/src/stores/abort-created-workspace-cleanup.test.ts
packages/ui/src/stores/app-session-reconciliation.test.ts
Expand All @@ -129,9 +133,10 @@ jobs:
packages/ui/src/stores/client-state.test.ts
packages/ui/src/stores/message-v2/instance-store.test.ts
packages/ui/src/stores/message-v2/message-hydration-authority.test.ts
packages/ui/src/stores/message-v2/message-window.test.ts
packages/ui/src/stores/message-v2/message-status.test.ts
packages/ui/src/stores/message-v2/normalizers.test.ts
packages/ui/src/stores/pty-store.test.ts
packages/ui/src/stores/shell-store.test.ts
packages/ui/src/stores/session-generation-recovery.test.ts
packages/ui/src/stores/session-pagination.test.ts
packages/ui/src/stores/session-pending-state.test.ts
Expand All @@ -144,12 +149,13 @@ jobs:
node --conditions=browser --import tsx --test --test-force-exit
packages/ui/src/components/form-request-tool-target.test.ts
packages/ui/src/components/form-request.test.ts
packages/ui/src/components/tool-call/renderer-copy.test.ts
packages/ui/src/lib/hooks/use-active-session-message-load.test.ts
packages/ui/src/stores/forms.test.ts
packages/ui/src/stores/instances-restore-ownership.test.ts
packages/ui/src/stores/opencode-data.test.ts
packages/ui/src/stores/permission-lifecycle.test.ts
packages/ui/src/stores/pty-store-reactivity.test.ts
packages/ui/src/stores/shell-store-reactivity.test.ts
packages/ui/src/stores/session-actions.test.ts
packages/ui/src/stores/session-native-events.test.ts
packages/ui/src/stores/session-request-authority.test.ts
Expand Down
4 changes: 2 additions & 2 deletions .opencode/skills/codenomad-architecture-guide/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ description: |
- There is no `packages/opencode-plugin/`. Do not restore plugin tools, plugin routes, or plugin packaging.
- The server owns one shared OpenCode service through `OpenCodeSharedService` and its lease-locked discovery, launcher, process-proof, and authenticated-stop lifecycle. Proven host shutdown delegates to native `Service.stop`; WSL uses native authenticated health stop to avoid the client's cross-namespace PID fallback. Workspaces are native OpenCode `Location`/directory scopes, not separate OpenCode processes.
- The UI uses generated Promise clients from `OpenCode.make()` through the CodeNomad proxy.
- OpenCode owns session APIs, native Shell (`client.session.shell`), session instructions (`client.session.instructions.entry`), and location-scoped native PTYs. Shell remains separate. The Status panel lists PTYs, refreshes on PTY events/reconnect, displays native metadata, and supports title updates and ownership-checked removal. Current installed declarations have no PTY output/read/stream or separate stop API, so output and distinct stop are unavailable; removal is the native stop action for a running PTY.
- OpenCode owns session APIs, session Shell (`client.session.shell`), session instructions (`client.session.instructions.entry`), location-scoped background Shells, and interactive PTYs. The Status panel lists `client.shell.*` records, refreshes on Shell events/reconnect, displays native metadata, and supports ownership-checked removal. Interactive `client.pty.*` terminals remain separate.
- CodeNomad owns workspace lifecycle, directory authorization, Git status/diff/stage/unstage/commit, Yolo persistence/auto-replies, and `/api/events`.
- V2 service startup forces `OPENCODE_DB` to `~/.local/share/opencode2/opencode.db`; never share the V1 database with V2.

Expand Down Expand Up @@ -61,7 +61,7 @@ description: |
| Public `@opencode-ai/sdk` examples | Installed experimental `@opencode-ai/client` declarations |
| One `opencode serve` per workspace | One CodeNomad-managed shared service |
| Per-worktree clients/processes | Root proxy client plus native location/directory inputs |
| Reintroducing `packages/opencode-plugin` or server plugin/background-process paths | Separate native Shell/instructions and native PTY management |
| Reintroducing `packages/opencode-plugin` or server plugin/background-process paths | Native session Shell/instructions, background `shell.*`, and separate interactive `pty.*` management |
| OpenCode APIs for stage/commit/Yolo policy | CodeNomad routes and managers |
| Hardcoded UI strings | `t()` / `tGlobal()` and every locale |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ The server uses `packages/server/src/workspaces/opencode-service.ts` for a lease

| Owner | Responsibilities | Main paths |
|---|---|---|
| OpenCode V2 | Sessions, messages, permissions/questions, files, native Shell/instructions, location-scoped PTYs | latest reviewed experimental `@opencode-ai/client` `next` protocol |
| OpenCode V2 | Sessions, messages, permissions/questions, files, session Shell/instructions, background Shells, interactive PTYs | latest reviewed experimental `@opencode-ai/client` `next` protocol |
| CodeNomad server | Shared service lifecycle, locations, proxy authorization, Git mutations, Yolo, auth, storage, speech, SSE multiplexing | `packages/server/src/` |
| CodeNomad UI | Generated Promise clients, state reconciliation, interaction and rendering | `packages/ui/src/` |
| Desktop hosts | Start CodeNomad and provide native OS integration | `packages/electron-app/`, `packages/tauri-app/` |

Native Shell remains separate from PTY management. The Status panel lists location-scoped PTYs, refreshes on PTY events/reconnect, displays native metadata, and supports title updates and ownership-checked removal. Current installed declarations have no PTY output/read/stream or separate stop endpoint; output display and a distinct stop action are unavailable, and removal is the native stop action for a running PTY. `packages/opencode-plugin/` and the server plugin/background-process integration remain deleted and must not be restored or used as extension points.
Session Shell remains separate from background Shell and PTY management. The Status panel lists location-scoped `shell.*` records, refreshes on Shell events/reconnect, displays native metadata, and supports ownership-checked removal. Output preserves native cursor pagination; interactive `pty.*` terminals remain separate. `packages/opencode-plugin/` and the server plugin/background-process integration remain deleted and must not be restored or used as extension points.

## HTTP And Events

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
1. UI obtains `getRootClient(instanceId)`.
2. Conversation mode updates `client.session.instructions.entry` for the voice instruction.
3. A normal prompt calls `client.session.prompt`; `!` shell mode calls native `client.session.shell`. Native Shell remains separate from PTY management.
4. The Status panel lists native PTYs for the active location, displays their native metadata, and refreshes on PTY events and reconnect.
5. Title updates and removal use native PTY APIs; the proxy verifies native `cwd` ownership before ID-scoped operations. Removing a running PTY is its native stop action.
6. Current installed declarations have no PTY output/read/stream API or separate stop endpoint, so output display and a distinct stop action are unavailable.
4. The Status panel lists native background Shells for the active location, displays their native metadata, and refreshes on Shell events and reconnect.
5. Removal uses native Shell APIs; the proxy verifies native `cwd` ownership before every ID-scoped operation and preserves output cursors.
6. Interactive PTYs use separate `pty.*` APIs and are not background-process records.
7. The proxy checks directory/session ownership and forwards to the shared service's `/api/*` route.
8. One upstream event subscription feeds `InstanceEventBridge`, then CodeNomad `/api/events`, then UI stores.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@

| Concern | Owner |
|---|---|
| Session/message/Shell/instructions | OpenCode native API; Shell remains separate from PTY management |
| PTY list/metadata/title/remove | Location-scoped OpenCode native API through CodeNomad ownership checks; Status UI refreshes on PTY events/reconnect |
| PTY output/distinct stop | Unavailable in current installed declarations; removal is the native stop action for a running PTY |
| Session/message/Shell/instructions | OpenCode native API; session Shell remains separate from background Shell and PTY management |
| Background Shell list/metadata/output/remove | Location-scoped OpenCode native API through CodeNomad ownership checks; Status UI refreshes on Shell events/reconnect |
| Interactive PTYs | Separate native `pty.*` API |
| Service discovery/start/stop | CodeNomad hardened adapter using selected OpenCode primitives |
| Workspace and directory authorization | CodeNomad |
| Git status/diff and mutations | CodeNomad |
| Yolo policy/persistence/auto-reply | CodeNomad |
| Browser event multiplexing | CodeNomad `/api/events` |

Current installed declarations have no PTY output/read/stream API or separate stop endpoint, so the UI cannot display PTY output or offer a distinct stop action. Do not restore `@opencode-ai/sdk`, per-workspace processes, `packages/opencode-plugin`, server plugin/background-process tools, or deleted plugin/runtime file paths.
Background Shell output uses native cursor pagination; interactive PTYs remain separate. Do not restore `@opencode-ai/sdk`, per-workspace processes, `packages/opencode-plugin`, server plugin/background-process tools, or deleted plugin/runtime file paths.
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ const client = OpenCode.make({ baseUrl, fetch: createInstanceFetch(baseUrl) })

Use `getRootClient(instanceId)` from `packages/ui/src/stores/opencode-client.ts`. Native location/directory inputs replace the old per-worktree-client pattern. Destroy cached clients when an instance is removed.

## Native Shell, Instructions, And PTYs
## Session Shell, Background Shells, And PTYs

- Shell mode calls `client.session.shell({ sessionID, command })`.
- Conversation mode adds/removes `client.session.instructions.entry` before `client.session.prompt`.
- Shell remains separate from native PTY management.
- PTYs are location-scoped and listed with `client.pty.list`; the Status panel refreshes on PTY lifecycle events and reconnect, displays native metadata, and supports title updates.
- PTY ID operations are ownership-checked against the native `cwd`. Removal is the native stop action for a running PTY.
- Current installed declarations have no PTY output/read/stream API or separate stop endpoint, so output display and a distinct stop action are unavailable.
- Session Shell remains separate from background Shell and native PTY management.
- Background Shells are location-scoped and listed with `client.shell.list`; the Status panel refreshes on Shell lifecycle events and reconnect and displays native metadata.
- Shell ID operations are ownership-checked against the native `cwd`; output preserves the native cursor and removal uses `client.shell.remove`.
- Interactive terminals use separate `client.pty.*` APIs.
- Keep `packages/opencode-plugin` and server plugin/background-process paths deleted.

## Event Flow
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ Then open a pull request on GitHub targeting the `dev` branch.
- V2 always uses `~/.local/share/opencode2/opencode.db`. Never reuse the V1 database for V2.
- OpenCode session calls use `/workspaces/:id/instance/api/*`; CodeNomad control routes and multiplexed events use `/api/*` and `/api/events`.
- The proxy is method/path allowlisted, so new upstream functionality is not exposed automatically.
- Native Shell (`client.session.shell`) and prompt instructions (`client.session.instructions.entry`) remain separate from native V2 PTY management.
- Native PTYs are location-scoped and listed in the Status panel. The UI refreshes them on PTY events and reconnect, displays native metadata, and supports title updates and ownership-checked removal. Current installed declarations have no PTY output/read/stream API or separate stop endpoint, so removal is the native stop action for a running PTY. `packages/opencode-plugin` and the server plugin/background-process paths remain deleted and must not be restored.
- Shell mode (`client.session.shell`) and prompt instructions (`client.session.instructions.entry`) remain separate from background shells and interactive PTYs.
- Location-scoped background shells use `client.shell.*` and are listed in the Status panel. The UI refreshes them on Shell events and reconnect, displays native metadata, and supports ownership-checked removal. `client.pty.*` remains reserved for interactive terminals. `packages/opencode-plugin` and the server plugin/background-process paths remain deleted and must not be restored.
- Native events are volatile. Reconnect handlers must refetch authoritative state instead of assuming missed events will replay.
- Git mutations and Yolo policy remain CodeNomad-owned server boundaries.

Expand Down
10 changes: 5 additions & 5 deletions MIGRATION_V2.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The migration removes the V1 compatibility layer rather than maintaining both in

- Remove the custom `packages/opencode-plugin` package.
- Remove V1 plugin communication channels and per-workspace runtime management.
- Replace interactive shell-mode requests with native V2 Shell and expose native V2 PTYs in the Status panel.
- Replace shell-mode requests with native `session.shell` and expose native background `shell.*` processes in the Status panel; keep interactive `pty.*` terminals separate.
- Replace per-workspace OpenCode binary selection with one global `opencode2` binary.
- Migrate the persisted V1 default command `opencode` to `opencode2` during workspace launch.
- Remove message and part deletion controls because V2 currently has no equivalent API.
Expand All @@ -39,7 +39,7 @@ The migration removes the V1 compatibility layer rather than maintaining both in

## Security and Service Lifecycle

- Restrict proxied Shell and PTY working directories to workspace-owned roots and Git worktrees; PTY controls also verify the native PTY `cwd` before forwarding ID-scoped requests.
- Restrict proxied Shell and PTY working directories to workspace-owned roots and Git worktrees; ID-scoped controls verify the native `cwd` before forwarding requests.
- Remove CodeNomad authentication cookies before forwarding requests to OpenCode.
- Prevent OpenCode `Set-Cookie` headers from being relayed to the browser.
- Avoid logging unredacted secret-bearing proxy request bodies.
Expand All @@ -61,7 +61,7 @@ The migration removes the V1 compatibility layer rather than maintaining both in
- The proxy validates the decoded scope of native session cursors before forwarding them and supports native global Form reply/cancel routes without treating `global` as a session ID.
- Before deleting a worktree, the server inventories the complete native project, evacuates affected session families with verification and rollback, and fails closed for direct API callers. One canonical folder maps to one logical workspace instead of creating non-isolated duplicates.
- The current working tree retains the isolated V2 database, deferred location eviction, and proxy path/location ownership validation.
- Current installed client declarations provide native PTY list/get/create/title-or-size update/remove and lifecycle events, but no output/read/stream API and no separate stop API. Removing a running PTY is therefore the only native stop action, and PTY output is not displayed.
- Current installed client declarations provide background Shell list/get/create/output/timeout/remove and lifecycle events. Shell output pagination keeps the native cursor authoritative. Interactive PTY APIs remain separate and are not used by the background-process panel.
- Local validation passes server/UI/Electron typechecks, the CI UI partitions, Electron native tests, server tests (with three platform skips), standalone server lockfile dry-run installation, UI/server/Electron builds, Tauri `cargo check --locked`, and `git diff --check`.

## Remaining Work
Expand Down Expand Up @@ -146,9 +146,9 @@ The smoke is complete only after all of these actions succeed in the visible V2
3. Open an existing session from the session list; direct API session creation is not a substitute.
4. Send a prompt from the composer and receive its visible assistant response.
5. Reload the V2 window and confirm the workspace and session list recover. While V1 owns cross-host restore, reopen the existing V2 session from the list and confirm its messages and pending state recover correctly.
6. Exercise one PTY create/list/remove cycle through the workspace proxy, then close only the V2 process after collecting its logs. PTY creation is not currently exposed in the visible UI.
6. Exercise one background Shell create/list/output/remove cycle through the workspace proxy, then close only the V2 process after collecting its logs. Shell creation is not currently exposed in the visible UI.

Do not count direct HTTP/CDP calls as validation for workspace, session, prompt, response, or reload behavior. CDP may inspect the V2 DOM and operate visible controls, but it must follow the same controls and state transitions as a user. The PTY protocol check is the sole exception until the UI exposes creation.
Do not count direct HTTP/CDP calls as validation for workspace, session, prompt, response, or reload behavior. CDP may inspect the V2 DOM and operate visible controls, but it must follow the same controls and state transitions as a user. The background Shell protocol check is the sole exception until the UI exposes creation.

## Review Notes

Expand Down
5 changes: 3 additions & 2 deletions dev-docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ dev-docs/ Development documentation
- Database: V2 always uses `~/.local/share/opencode2/opencode.db`, separate from V1
- Events: volatile native stream with authoritative reconnect reconciliation
- Proxy: explicit method/path allowlist; upstream additions are not automatic
- Shell and instructions: native session APIs, separate from PTY management
- PTYs: location-scoped native entries in Status, refreshed on PTY events/reconnect with metadata, title updates, and ownership-checked removal; current installed declarations have no output/read/stream or separate stop API, so output and distinct stop are unavailable and removal stops a running PTY
- Shell mode and instructions: native session APIs, separate from background Shell and PTY management
- Background Shells: location-scoped native `shell.*` entries in Status, refreshed on Shell events/reconnect with metadata and ownership-checked removal; output uses native cursor pagination
- PTYs: separate native interactive terminals, not background-process records
- Legacy plugin/background processes: `packages/opencode-plugin` and server plugin/background-process paths remain deleted
- Git mutations and Yolo: CodeNomad-owned
Loading
Loading