This branch replaces CodeNomad's OpenCode V1 SDK, custom plugin, and per-workspace runtime architecture with the native OpenCode V2 client and one shared OpenCode service. It intentionally provides no V1 runtime fallback.
The work grew beyond an SDK swap. It also introduces location-based ownership, native Forms and Shell resources, project-wide session pagination, reconnect reconciliation, bounded virtualized timelines, multi-window desktop state, and a content-addressed restore format.
Server and UI pin the official @opencode/client@2.0.11; the bundled pruning plugin pins @opencode/plugin@2.0.11. Upgrade the client, plugin and lock together using official V2 documentation, installed declarations and generated wire paths. The runtime CLI is independently managed: production startup validates authenticated /api/status, then /api/health, then /api/info, advancing only on HTTP 404. All probes share the endpoint, credentials, response-size bound and absolute deadline. Canonical server.info() follows the discovered route. There is no exact version gate. Discovery compatibility alone does not establish compatibility for the remaining client APIs. The older beta reviews below are historical.
The incremental comparison with official OpenCode Desktop V2, including closed findings and remaining gaps, is recorded in DESKTOP_V2_COMPARISON.md.
The current cross-version issue register and historical API-change audit are maintained in dev-docs/OPENCODE_V2_COMPATIBILITY.md. The technical minimum is 2.0.7, which supplies the native session.step.started.data.started timestamp required by the current reducer after removing the fallback. 2.0.11 is recommended and release-tested. Unlisted/custom/prerelease/future versions require authenticated API recognition; an unfamiliar label alone is not incompatibility. Earlier wire adapters are retired; their regression results below are historical evidence rather than live support.
Setup and Preferences reuse a card with distinct missing/incompatible/optional-update actions and separate minimum/recommended version information. Default host installation uses CodeNomad's bundled Node/npm, including when system Node is absent, into ~/.local/share/codenomad/opencode. Node's archive already included npm; packaging now retains it. Custom/WSL binaries retain explicit execution-host instructions. Updating files does not update an already-running daemon: restart is separate and explicit, and remains optional for a usable daemon. Pending folder opening can resume; prompts are never replayed.
The isolated 2.0.3→2.0.11 migration fixture preserves session IDs, complete paginated message content, forks, compaction checkpoints, moved sessions and a pending inbox record. OpenCode itself collapses old workspace selectors to local directory scope. Historical ownership checks remain; CodeNomad does not rewrite the database. See the transition register for validation commands and outstanding packaged/platform release gates.
Qualification targets the latest published stable runtime. Maintain the shared compatibility reference in place; keep detailed acceptance results in PRs and CI logs. Record the technical dependency establishing the minimum in release notes. Do not raise it merely because a newer stable version is published or tested.
The former @opencode-ai/client beta contract cannot load normal sessions from a fresh 2.0.4 daemon. Fixing discovery alone is insufficient. This migration updates the server, UI, pruning plugin and guarded proxy together:
- Public locations are
{ directory }; project metadata comes fromlocation.get().project. Internal/eventLocationRef.workspaceIDis not a public request selector. Obsolete selectors are rejected by the proxy. - Forms lists remain location-scoped through
form.list. Settlement usessession.form.reply/cancel, with the native encoded directory header forsessionID: "global". Cancellation is DELETE on the form resource. - Permission replies send
decision; commands sendname; interrupt sendsresume; fork sends optionalbefore. Rename usessession.update, message lookup usessession.message.get, and inbox delivery usessession.inbox.update. - Wait, instructions and import routes use
/api/experimental/session/.... Active-session responses retain the generated{ data }envelope. Session and message traversal follows only nativecursor.next. - Catalogs use authoritative native reads and current
plugin.updated,provider.updatedandmodel.updatedevents. The removed activation-wait endpoint and obsolete Question routes are not exposed. - Native pruning CI installs CLI 2.0.4. Platform packages contain
bin/opencode(.exe); upstream still provides both public CLI aliases,opencodeandopencode2.
Validation uses synthetic data in isolated daemons/databases, including the actual UI fetch adapter and guarded proxy, native pagination, Forms, pruning concurrency/payload/fork/restart checks and rendered pruning controls. No test targets the shared daemon or user storage.
This branch replaces the removed session.messageUpdate callers with the narrow
CodeNomad plugin RPC described in SESSION_PRUNING_RPC.md.
The historical capability tables below describe the earlier beta integration, not
current deletion availability. Once the native plugin is loaded, a pruning request
requires compatible native storage, the execution-claim fence and a matching
daemon DB. Official Windows runtime tests use synthetic data only. WSL, interactive
TUI and desktop release checks remain documented separately. CodeNomad ships the
plugin and provisions its native entry at startup. RPC registrations follow the
presence of CodeNomad backends, with automatic expiry after a crash; OpenCode's
shared daemon is never stopped by this lifecycle.
- Use native locations and
SessionInfo.locationas the authority for workspace, session, file, event, Shell, PTY, and Git worktree ownership. - Use native APIs for projects, sessions, messages, prompts, commands, models, agents, providers, MCP, permissions, Forms, files, VCS, instructions, Shells, and PTYs.
- Use native session lifecycle and output events, including
session.created,session.renamed,session.moved,session.status,session.idle,session.execution.*,session.compaction.*,session.step.streamed,session.text.*,session.reasoning.*, andsession.tool.*. The current durable event union still includessession.message.content.updated; retain its authoritative reread path even though the old public mutation API was removed. Pruning uses its reviewed RPC invalidation and authoritative native rereads. - Use
@opencode/client/solidcreateDatafor live message, tool, permission, and Form projection while preserving REST-loaded history and optimistic local sends. - Replace the legacy Question request lifecycle with native Forms. Question tool output rendering remains independent of pending interruption state.
- Replace shell-mode prompts with native
session.shell. - Replace CodeNomad background processes with native
shell.*resources. The Status UI lists, displays bounded output for, and removes Shells; create/output routes remain available through the ownership-checked proxy. Interactivepty.*terminals remain separate. - Store voice-mode instructions with
session.instructions.entryand synchronize them before prompts, commands, and session Shell calls. - Inherit native durable JSON
SessionMetadatadirectly fromSessionInfo. Do not widen it to arbitraryunknownvalues or maintain a parallel CodeNomad-only metadata contract. - Read location-scoped native catalogs and refresh on
plugin.updatedand resource-specific updates. Stable 2.0.4 has no activation-wait endpoint. - Keep the narrow project-local
codenomad.automationexception on the V2setupandtool.transformcontract; it remains active underbeta-19059.
The beta-18414 to beta-18866 review found these additive client surfaces:
| Native addition | CodeNomad decision | Reason |
|---|---|---|
plugin.check |
Deferred candidate for a future plugin inventory UI. | It is read-like and location-scoped, but CodeNomad currently has no plugin-management workflow. |
plugin.update |
Keep blocked. | It installs or replaces executable plugin code and requires an explicit trusted update flow, confirmation, and mutation fencing. |
rpc.call and typed plugin RPC/events |
Keep the generic route blocked; permit only reviewed RPC definitions through a constrained broker if a concrete integration needs them. | A blanket RPC proxy would bypass the method-specific allowlist. The existing Developer Mode bridge has different process and authentication boundaries and is not automatically replaced by plugin RPC. |
experimental.persistentPty.read |
Keep blocked. | CodeNomad uses native Shell resources for background output and has no owned persistent-session-terminal lifecycle. |
vcs.base and diff base selection |
Deferred read-only candidate. | The current Git Changes UI displays working-tree and index changes and does not yet offer base-branch comparison. |
Service.stop({ pty }) handoff/clear behavior |
Do not adopt. | CodeNomad does not own or stop the shared OpenCode service. |
The 21 official beta releases from beta-18230 through beta-18999 have empty GitHub release bodies. The 2026-09-04 review therefore matched official publish workflows to source commits, read the intervening repository history, compared npm tarballs and generated Promise declarations, and checked the official V2 docs instead of relying on nonexistent prose release notes.
The final published range from beta-18866 (519cd8c7712fc2ca6d2ca1d356d7f52cbd6d5808) to beta-18999 (887f319769c55718e3e64f64b32c9aafb13c5d66) contains 114 commits. Its complete generated-contract delta is:
| Published change | CodeNomad decision |
|---|---|
Add POST /api/plugin/await-activation and its input/output types. |
Allowlist only this non-mutating plugin route. Coalesce waits by client and Location before catalog and plugin-status reads, with authoritative reads as the fallback for a lagging runtime. |
Remove PluginAdded and plugin.added. |
Delete the obsolete invalidation branch. Refresh agents, providers, commands, and metadata from the settled plugin.updated event. |
Rename ConfigEntry.autoupdate to update: "disable" | "notify" | "auto". |
No migration is required because CodeNomad has no OpenCode autoupdate caller or projection. Runtime CLI updates remain independently managed. |
The same audit reconfirmed the cumulative published additions already in use: native session.messageUpdate, durable session metadata, time.streamed, session.step.streamed, session.message.content.updated, current plugin state records, and the generated Solid event reducer. Provider/model canonical resolution and materialized skill text remain upstream runtime concerns; CodeNomad sends native IDs and prompt attachments without duplicating that lowering. Plugin package checks/updates, generic RPC, persistent PTYs, VCS review-base reads, and session transfer UI remain explicit product/security decisions rather than accidental omissions.
The successful 2026-09-04 publish from c9d240704d6eefc88b63a1eca2cb933b3eb70ed3 produced beta-19059, the 22nd official beta in the reviewed range. Its release body is also empty. The audit therefore reviewed all 52 commits after beta-18999, compared both npm tarballs, refreshed the installed declarations and lock, and compared the official V2 OpenAPI and documentation.
No route or schema was added or removed: the OpenAPI remains at 119 paths, 140 operations, and 229 schemas, while the generated Promise client remains at 136 methods. The complete published client delta that affects CodeNomad is:
| Published change | CodeNomad decision |
|---|---|
Completed compaction messages and session.compaction.ended now carry optional model and providerState. |
Preserve both fields in normalized compaction parts; the upgraded Solid reducer also retains them for live events. |
createData fences event-driven refreshes while disconnected or disposed and adds an onError callback. |
Keep the existing connection signal and route refresh failures through the CodeNomad logger. The lifecycle fencing is inherited from the upgraded client. |
Command config adds subagent; subtask remains as a deprecated alias. |
CommandInfo exposes neither flag, so the runtime remains authoritative. Command submission stays serialized but no longer marks the parent optimistically busy; native events now distinguish current-session execution from a background child. |
ConfigEntry.update narrows from `"disable" |
"notify" |
The renewed OpenAPI review also made explicit that fs.list accepts absolute paths and .. traversal relative to a Location. The CodeNomad proxy now resolves that target, rejects duplicate selectors and paths outside owned worktrees, and translates an accepted path for WSL before forwarding it.
Runtime changes in the same release—settling abandoned compactions before resume, retrying failed Location initialization, disabling plugins after transform failures, backgrounding command subagents, restoring Windows terminal interruption, detecting new ecosystem config roots, and live provider/model fixes—are acquired automatically when the independently managed opencode2 runtime is updated. CodeNomad does not duplicate those internals or impose an exact version gate. At the time of this audit upstream/beta equals the published beta-19059 source, so there is no later unpublished contract delta.
- OpenCode V2 explicitly confirms that the intended architecture is one shared process for all workspaces and clients; workload slowdowns must be profiled and fixed within that topology rather than worked around with private servers.
- Replace one OpenCode runtime per workspace with one externally owned global service in the selected host or WSL environment.
- Discover or start it through the selected CLI's official
service status,service start, andservice get passwordcommands. - Validate the bounded
/api/statusresponse over the authenticated loopback endpoint, use earlier V2/api/healthonly after a status 404, and pin one service identity while connected. - Use OpenCode's standard service registration, state, and database. CodeNomad owns no private daemon port, database, registration, or PID.
- Pass configured startup environment variables and
NODE_EXTRA_CA_CERTSonly when starting a missing service. Strip legacyOPENCODE_DBandXDG_STATE_HOMEoverrides rather than taking ownership of OpenCode storage. - Never stop the global daemon during CodeNomad shutdown. Backend shutdown clears only CodeNomad's cached connection and logical workspace state.
- Run the Linux CLI inside the selected WSL distribution and require Windows localhost forwarding. No cross-namespace PID fallback or process signaling remains.
- OpenCode PR #46085, included since
beta-18721, bounds post-exit pipe draining so detached Windows GUI descendants no longer leave the parent session permanently running. Late output may be discarded;session.backgroundremains a user action rather than a required workaround.
- A CodeNomad workspace is now a logical UUID-backed instance over a native OpenCode location, not an OpenCode process.
- A normal folder launch always creates a new logical instance and tab, even when the same or canonically equivalent directory is already open.
- The explicit Open action selects an existing instance instead of creating another one.
- Duplicate-folder instances share the same daemon and native location but keep independent logical IDs, tabs, selection, drafts, and view state.
- The workspace catalog is shared by the backend. Tab membership, order, active selection, SideCars, drafts, attachments, and view state are local to each native window.
- Closing a tab or window detaches only local UI state. Stop Workspace deletes the selected logical instance and evicts the native location only after its final logical owner is removed.
- Restore matches duplicate-folder tabs by normalized-path occurrence rather than collapsing them into one instance.
- Owned Git worktrees are resolved server-side and participate in the same location, request, and event-routing rules as the root directory.
- Query a complete project-scoped session inventory across root and worktree subpaths without one request per parent; native
globalprojects remain scoped to the selected workspace directory. - Follow native
cursor.nextvalues for session and message pagination. The proxy decodes session cursors only to validate embedded directory/project scope, strips competing selectors, and forwards the original cursor unchanged. - Hydrate only missing ancestor chains with
session.getand fetch active status for later session pages. - Load message history lazily into a replace-in-place 200-message resident window. Older, newer, oldest, and latest navigation swaps authoritative pages without accumulating the transcript, while delayed REST responses cannot overwrite newer event state.
- Route location-scoped events to every owning logical workspace and resolve locationless session, permission, Form, Shell, and PTY events through native ownership.
- Use one upstream event subscription and browser
EventSourcefor web, Electron, and Tauri. - Treat events as volatile projections, not durable history. Browser
EventSourcerecovery refreshes the workspace catalog and per-instance authoritative state, reloads the active transcript, and invalidates other loaded transcripts for lazy refresh. Upstream instance-stream recovery performs only the per-instance reconciliation. - Preserve Solid projection controllers across browser transport reconnects and merge live records into REST history rather than clearing usable state. A native
server.connectedgeneration change disposes and recreates those controllers before reconciliation.
- Virtualize session lists and message timelines with
virtua0.51.0to bound mounted DOM for large histories. - Preserve user-controlled scroll position, bottom-follow intent, oversized streaming hold points, and anchor-based restore across live updates, pagination, tab changes, and desktop restarts.
- Shift ordered slides of the capped 200-message window in place. Reordered, paginated, and otherwise non-aligned key changes advance a measurement epoch and remount the virtualizer so stale measurements cannot be reused.
- Finalize the temporary
200 -> 201 -> 200shift in a generation-guarded microtask before paint, and compensate followed content growth from aResizeObserverattached to the mounted Virtua content root. Only explicit user scroll intent disables following. - Keep native cursors authoritative; do not infer completion from page length.
- Bound instance logs and validate restore-state counts, IDs, paths, snapshots, string budgets, partition sizes, and graph sizes.
- Reconcile only affected resources after native events or reconnects instead of periodically reloading full message history.
- Keep optimistic prompts visible before native admission and replace temporary parts with authoritative native parts without duplicating output.
- Keep every pending inbox prompt after delivered transcript messages in native inbox admission order. A local send pins the new prompt to the bottom, while pagination and remote updates preserve a user's escaped follow state.
- Project every native streaming delta through the shared reactive message path, while limiting timeline reconstruction for text, reasoning, and compaction by the same streamed-content buckets.
- Merge pending permissions and Forms into one ordered interruption UI while preserving their separate native reply/cancel APIs.
- Reconcile pending requests from the root, active catalog, known session, worktree, and queued Form locations after reconnect and during bounded liveness checks while sessions or prompts are active.
- Treat successful permission and Form replies or cancellations as local authority so stale events and partial scans cannot resurrect settled interruptions; failed mutations trigger authoritative reconciliation.
- Carry location for global Forms through the proxy without inventing a synthetic session.
- Support native provider API-key, OAuth, command, and interactive Form authentication, including dynamic required fields and custom choices.
- Expose read-only quota usage for the supported provider registry, including xAI, Claude, Command Code, CrofAI, DeepSeek, and NeuralWatt, without returning, refreshing, or mutating provider credentials.
- Keep Yolo policy server-owned: persist enabled session families, inherit policy across descendants, deduplicate duplicate-instance delivery by permission ID, retry within a fixed bound, and synchronize state to every window.
Before deleting a Git worktree, CodeNomad now:
- Resolves and fences the canonical physical worktree identity across nested paths, aliases, junctions, symlinks, and WSL paths.
- Rejects new OpenCode, file, and Git mutations and drains already admitted mutations, failing closed if the bounded drain cannot complete.
- Resolves the native project and inventories every session with native cursors.
- Selects sessions whose native location belongs to the worktree.
- Refuses deletion while affected sessions are active.
- Moves affected sessions to the root location.
- Re-inventories until the moves are authoritative.
- Removes the Git worktree inside the same rollback boundary.
- Restores moved sessions if verification or deletion fails.
Git status is hybrid: native vcs.status is augmented with CodeNomad server detail data. Selected-file diff, stage, unstage, and commit remain server operations. Although beta-18866 exposes native worktree creation and removal, CodeNomad retains its server workflow for ownership fencing, session evacuation, verification, and rollback semantics.
- Expose only reviewed method/path pairs; new upstream APIs are unavailable until explicitly allowlisted.
- Verify workspace ownership for native locations, sessions, projects, cursors, Shell/PTY CWDs, imported session locations, and prompt file URIs before forwarding.
- Reject encoded path traversal, foreign locations/projects, forged cursors, and mismatched workspace selectors. Preserve validated native location workspace identities, including global Form headers, across the proxy.
- Translate host/WSL paths only after ownership validation.
- Strip CodeNomad cookies, browser authorization, forwarding headers, and incoming
x-opencode-*headers; inject shared-service authentication server-side. - Block upstream cookies and authentication challenges and avoid logging unredacted secret-bearing request bodies.
- Treat each unguessable preview token as a route-scoped capability. Loopback HTTP native previews use
<token>.preview.localhostso applications retain normal root paths; HTTPS, LAN, and web clients use the equivalent capability path. SideCar/browser previews remain opaque-origin sandboxes withoutallow-same-origin, and element comments cross a source-checked message bridge.
- Run one native singleton and one CodeNomad backend per channel/config profile. Stable, development, and non-default config identities use isolated singleton, browser-storage, backend, and client-state scopes.
- Open another local window on a second launch by default; an Advanced preference restores most-recent-window focus, while
--new-windowalways opens another window. - Give each Electron or Tauri window a UUID and independent tab/restore record while sharing the backend and global OpenCode data.
- Persist one record per window in a V3 envelope over a V2 content-addressed partition graph.
- Split workspace/session documents and chunk attachments so unrelated state does not rewrite one monolithic snapshot.
- Validate hashes, canonical JSON, allowed fields, graph references, and size/count limits. A corrupt leaf can be discarded while valid sibling state survives.
- Prepare immutable partitions before atomically publishing the root; serialize and fence writes against ownership loss, renderer-token mismatch, shutdown, and migration races.
- Coordinate Electron/Tauri ownership with participant markers, process-start identity, stale-owner recovery, and verified release.
- Copy legacy Electron/Tauri client state non-destructively on first migration and refuse to overwrite unsupported future formats.
- Store the stable/default cross-host state under
~/.codenomad/client-state/v2; development and non-default profiles use derived profile-specific locations. - Restore every persisted UUID window, exact active tab/session selection, drafts, attachments, expansion, scroll/follow state, idle markers, interrupted generations, bounds, and zoom.
- Fence late workspace creation and cleanup so cancelled restore requests cannot leak or delete the wrong logical instance.
- Build Electron and Tauri server resources reproducibly from the integrity-pinned root workspace lock for the requested OS/CPU target; no independent server lockfile or prebuild dependency repair remains.
For interactive validation of the native V2 application, use the existing release binary rather than tauri dev, which compiles and runs a different debug environment. Enable Developer Mode from the session tab bar and restart CodeNomad when prompted. The native host then selects its derived persistent developer profile, enables Rust backtraces and Node source maps, and opens CDP on a dynamically assigned loopback port.
& "$PWD\packages\tauri-app\target\release\codenomad-tauri.exe"The Developer Mode bridge discovers and verifies the actual dynamic cdpUrl; do not set or assume port 9223. Stop the running instance before rebuilding this release path, then relaunch it from the independent OpenCode TUI or through the pinned codenomad.act({ action: "restart" }) workflow.
The migration deletes rather than maintains these superseded systems:
- The complete
packages/opencode-pluginpackage, its packaging script, desktop resources, setup hooks, environment plumbing, and plugin README. - Plugin POST/SSE channels, handlers, voice synchronization routes, and the custom plugin-to-CodeNomad event bridge.
- Per-workspace OpenCode runtime processes, loopback servers, clients, authentication, binary selection, launch cleanup, process identity, process-tree signaling, and runtime tests.
- The
.codenomad/worktreeMap.jsonmapping layer and UI-side OpenCode workspace/worktree-client matching. - The custom background-process manager, persistence, HTTP routes, and UI store; native Shell listing, bounded output display, and removal replace them.
- Legacy Question queues, request event handling, state, components, and tests, replaced by native Forms.
- The V1 message/delta buffer and periodic full-history event reload strategy, replaced by native events plus authoritative reconciliation.
- The duplicate Rust-native Tauri SSE transport, including batching, coalescing, cookie forwarding, pong handling, reconnect code, commands, managed state, and tests.
- The desktop native-event adapter made unnecessary by the shared browser
EventSourcepath. - Arbitrary whole-message deletion and local-only transcript mutation companions for operations not offered by the V2 beta protocol. Technical tool/reasoning cleanup now uses native
session.messageUpdate. - The server and UI dependency on
@opencode-ai/sdkand the runtime V1 compatibility path.
During stabilization, CodeNomad implements the public native V2 contract and removes V1 behavior that cannot be reproduced authoritatively. It does not depend on compatibility routes, private APIs, local-only transcript mutations, or a bundled OpenCode fork to simulate parity; inert legacy Question allowlist entries remain pending cleanup. Missing protocol capabilities are documented rather than proposed upstream until the V2 migration is complete and stable. The current V2 TUI is the minimum user-facing behavior reference where its workflow can be reproduced through the public contract; CodeNomad may add conveniences and product-specific capabilities beyond that baseline.
| Capability | Native V2 availability | CodeNomad decision | Revisit or complete when |
|---|---|---|---|
| Assistant content mutation | session.messageUpdate authoritatively replaces the text, reasoning, and tool content of a completed assistant message. There is still no generic deletion of a complete delivered message or mutation of user messages. |
Restores individual tool/reasoning deletion through the native update route. Arbitrary whole-message deletion remains absent rather than locally simulated. | Add broader deletion only if V2 exposes an authoritative operation for the required message type. |
| Bulk tool and reasoning cleanup | No native bulk operation, but session.messageUpdate can safely compose cleanup one assistant message at a time. |
Restores selected-group and full-session technical-part cleanup through authoritative per-message updates. | A native bulk operation is only needed if per-message updates become a measured performance problem. |
| Delete-to-boundary / undo | session.revert.stage and session.revert.clear use V2 staged-revert semantics instead of arbitrary deletion. |
Command-palette Undo uses revert.stage; Redo clears the staged revert through revert.clear. |
Revisit only if V2 adds broader authoritative transcript deletion. |
| Compaction | Native checkpoint compaction summarizes the older head and retains a server-selected recent tail controlled by compaction.keep.tokens. |
Uses session.compact; there is no message-level selective compaction. CodeNomad displays the partial summary through the same reactive streaming path as text and reasoning, then replaces it with the terminal summary. |
Add scoped controls only if V2 defines scoped compaction semantics. |
| Transcript pagination authority | Message pages expose only opaque previous/next cursors. They provide no transcript revision, total, absolute range, position, or random seek target. | Uses bounded cursor traversal and a 200-message resident window, with defensive reconciliation after destructive events. It cannot prove that pages loaded across compaction or revert belong to one snapshot. | V2 adds snapshot revision authority (#43766) and navigable position metadata (#44660). |
| Full-session search | session.list(search) filters session titles only. There is no server transcript-search endpoint returning message identity, excerpt, navigable position, and transcript revision. |
Retained through exhaustive message-cursor traversal while keeping only the 200-message resident window and collected matches. Large searches still fetch every page. | V2 exposes transcript search (#45801) with a target that composes with transcript revision and seek metadata. |
| Queued prompt management | Native inbox list, cancel, steer, and queue operations cover authoritative follow-up delivery. The TUI's edit action removes a locally queued prompt before restoring it to the composer; it is not an atomic inbox update. | Implements a persisted primary steer/queue preference, inverse alternate shortcut, delivery switching, cancellation, cancel-first composer restoration with the structured payload retained, and native-order timeline projection. Earlier automatic replacement and reorder experiments were removed because they could change identity and position, duplicate prompts, or race with a concurrent drain. |
Revisit atomic editing or reordering only if a concrete product need is established. |
| Background execution | Native session.background moves blocking tools out of the foreground; Shell resources separately support listing, bounded output, and removal. |
Exposes session.background through the proxy and UI with Ctrl/Cmd+B, and replaces the custom process manager with native Shells. Unsupported controls such as rename remain removed. |
Add controls only when the native session or Shell APIs support them. |
| Service lifecycle | V2 uses one shared externally owned service rather than one runtime per workspace. | CodeNomad discovers or starts the service. Stop Workspace evicts the native location after its final logical owner is removed; application shutdown never stops the daemon. | No parity work planned unless V2 changes service ownership semantics. |
This table is release-facing and must remain synchronized with the open migration pull request description whenever a capability is removed, restored, or becomes available in the current V2 client.
At the 2026-08-28 migration gate (878550ca), UI and server typechecks, 86 focused UI tests, 64 focused server tests, the production UI/server build, Tauri cargo check, all 121 Rust tests, and git diff --check passed.
At the 2026-09-03 timeline stabilization head (dea20996):
- UI TypeScript typecheck passed.
- All 68 focused timeline, pagination, request-authority, and restore tests passed.
- The Tauri release build passed against the
beta-18999lock;beta-19059validation is recorded with the final branch checks. - Native Developer Mode validation observed in-place capped-window shifts with no remount or empty frame, same-cycle growth compensation, preserved manual escape, and inactive-tab anchor restoration within 0.3125 px.
At the 2026-09-04 beta-19059 branch gate:
- The installed UI/server Promise client, protocol, schema, npm metadata, 119 paths, 140 operations, 229 schemas, and 136 Promise methods all resolve to
0.0.0-beta-19059. The 22 beta publications frombeta-18230throughbeta-19059, the 52 commits afterbeta-18999, generated declarations, OpenAPI snapshot, official repository head, and V2 documentation were reviewed; no later unpublished contract delta existed. - UI, Electron, and server TypeScript typechecks passed. The pure UI suite passed 323 tests, the browser-runtime UI suite passed 148, and the server suite passed 373 with the two expected Windows skips.
- Desktop resource integrity passed 3 tests, the complete Electron native suite passed, and Tauri passed all 139 Rust tests serially. The 14 cross-host election tests also passed eight consecutive Windows runs after replacing the slow WMI process-identity probe with
Get-Process.StartTimeon both hosts. - The production UI build and Tauri release/NSIS build passed. The rebuilt release was relaunched without stopping the shared OpenCode daemon.
- Native Developer Mode validation covered the
systempalette merge reset, the 14-color custom palette, notification anchoring/outside-click/Escapefocus restoration, active-composer agent/model/thinking shortcuts, and the responsive/touch layout at320x800; document width remained 320 px, all five native menus remained available, and both drawers remained reachable. - The independent compatibility runtime still reports
beta-18999. It exercised the intentional authoritative-read fallback without an exact startup gate; updating that globally managed CLI tobeta-19059remains independent of this client/build gate.
- Review official V2 documentation, installed declarations, generated routes, proxy/API parity and
/api/pluginfailures whenever the pinned stable client changes. CodeNomad uses the network client. - V1-style global plugins are outside the CodeNomad client migration. Under the reviewed V2 contract through
beta-19059, the installed After Effects, Blender, Microsoft 365, Resolve, Unreal, Ponytail, and Gemini Auth integrations require independent migrations to a V2 definition with anidandsetuporeffect. - Upgrade references: OpenCode releases, OpenCode V2 documentation, and the resolved
node_modules/@opencode/client/dist/promise/declarations and generated implementation.