Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .opencode/skills/codenomad-architecture-guide/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ description: |

- Runtime requirements live in `opencode/runtime-support.ts`; each blocking requirement needs demonstrated API/behavior evidence. Distinguish technically incompatible, recommended/tested and unverified versions. Setup uses bundled Node/npm and a versioned user prefix; shared-daemon restart is explicit and uses the existing native-parent launch bridge. Retire obsolete wire translations while retaining current identity/authority checks. See `dev-docs/OPENCODE_V2_POST_BETA.md` for precise retirement boundaries and validation evidence.

- Server and UI pin the official `@opencode/client@2.0.11` together; the pruning plugin pins `@opencode/plugin@2.0.11`. Review official V2 docs, installed declarations, generated wire paths and native integration tests when upgrading. Qualify against the latest published stable runtime, but never infer the minimum from that version or from the dependency pin. Record technical minimum requirements and tested scenarios in PR/CI logs and update `dev-docs/OPENCODE_V2_COMPATIBILITY.md` in place rather than adding per-version reports. The runtime CLI is managed independently.
- Server and UI pin the official `@opencode/client@2.0.15` together; the pruning plugin pins `@opencode/plugin@2.0.15`. Review official V2 docs, installed declarations, generated wire paths and native integration tests when upgrading. Qualify against the latest published stable runtime, but never infer the minimum from that version or from the dependency pin. Record technical minimum requirements and tested scenarios in PR/CI logs and update `dev-docs/OPENCODE_V2_COMPATIBILITY.md` in place rather than adding per-version reports. The runtime CLI is managed independently.
- Do not use `@opencode-ai/sdk`, `@opencode-ai/sdk/v2/client`, or `createOpencodeClient()`; follow installed `@opencode/client` declarations.
- There is no legacy `packages/opencode-plugin/`. Do not restore the V1 compatibility runtime or add general plugin extension points. The narrow integrations are the bundled `codenomad.automation` plugin and bundled session-pruning RPC; see `dev-docs/DEVELOPER_MODE.md`, `dev-docs/BROWSER_AUTOMATION.md` and `dev-docs/SESSION_PRUNING_RPC.md`. All automation tools follow backend presence without a Developer Mode gate, sharing the authenticated native transport and execution-time session/window fences.
- The server uses the selected host or WSL CLI's official `service status`, `service start`, and `service get password` lifecycle to connect to one externally owned global OpenCode daemon. It owns no private port/database/registration/PID and never stops the daemon on backend shutdown. WSL requires Windows localhost forwarding and uses no cross-namespace PID operations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Client-state V3 is a per-window envelope over the V2 content-addressed partition

| Owner | Responsibilities | Main paths |
|---|---|---|
| OpenCode V2 | Sessions, messages, permissions, Forms, files, session Shell/instructions, background Shells, interactive PTYs | pinned stable `@opencode/client@2.0.11` contract across server and UI |
| OpenCode V2 | Sessions, messages, permissions, Forms, files, session Shell/instructions, background Shells, interactive PTYs | pinned stable `@opencode/client@2.0.15` contract across server and UI |
| CodeNomad server | Shared service lifecycle, locations, proxy authorization, Git mutations, Yolo, auth, storage, speech, SSE multiplexing, Developer Mode bridge | `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/` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

## Package

CodeNomad server and UI pin `@opencode/client@2.0.11`. The runtime CLI is managed independently; startup validates authenticated loopback `/api/status`, then `/api/health`, then `/api/info`, advancing only on HTTP 404 with the same endpoint, credentials and deadline. Each response has its own validated schema and a 64 KiB bound. The shared transport maps canonical `server.info()` to the discovered route. Older services do not expose `paths.tmp`; consumers may use only the metadata actually provided. Discovery does not prove compatibility for other APIs. Review official V2 docs, installed declarations, generated routes and native regression tests together when upgrading.
CodeNomad server and UI pin `@opencode/client@2.0.15`. The runtime CLI is managed independently; startup validates authenticated loopback `/api/status`, then `/api/health`, then `/api/info`, advancing only on HTTP 404 with the same endpoint, credentials and deadline. Each response has its own validated schema and a 64 KiB bound. The shared transport maps canonical `server.info()` to the discovered route. Older services do not expose `paths.tmp`; consumers may use only the metadata actually provided. Discovery does not prove compatibility for other APIs. Review official V2 docs, installed declarations, generated routes and native regression tests together when upgrading.

Runtime requirements live in `packages/server/src/opencode/runtime-support.ts`: minimum 2.0.7 for native step-start timestamps, independently of recommended/tested 2.0.11. The shared connection binds authenticated runtime identity, the canonical client and forwarding transport. Admission precedes functional requests/plugin provisioning; unlisted versions, including custom/prerelease/future labels, require authenticated bounded API recognition. Legacy request/response/event and live location translations are retired. Never add operation-specific retry fallbacks in UI stores or Yolo. See `dev-docs/OPENCODE_V2_POST_BETA.md` for precise boundaries, setup and migration evidence.
Runtime requirements live in `packages/server/src/opencode/runtime-support.ts`: minimum 2.0.7 for native step-start timestamps, independently of recommended/tested 2.0.15. The shared connection binds authenticated runtime identity, the canonical client and forwarding transport. Admission precedes functional requests/plugin provisioning; unlisted versions, including custom/prerelease/future labels, require authenticated bounded API recognition. Legacy request/response/event and live location translations are retired. Never add operation-specific retry fallbacks in UI stores or Yolo. See `dev-docs/OPENCODE_V2_POST_BETA.md` for precise boundaries, setup and migration evidence.

The Promise client preserves the full `baseUrl` path prefix. Forward its generated URL unchanged through `createInstanceFetch`; remove the proxy prefix only when classifying reads for scheduling. Declared API errors are `Error` instances retaining their native `_tag`/data fields; undeclared statuses remain `ClientError("UnexpectedStatus")`.

- Promise client: `import { OpenCode } from "@opencode/client"`
- Service authentication headers: `import { Service } from "@opencode/client/service"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

## Contract

- Server and UI pin `@opencode/client@2.0.11`. Manage the runtime CLI independently: startup checks authenticated loopback `/api/status`, then `/api/health`, then `/api/info`, advancing only on HTTP 404. All probes share the endpoint, credentials, 64 KiB response bound and absolute deadline; authentication, transport and malformed response failures do not trigger fallback. The shared transport maps canonical `server.info()` to the discovered route. Older services do not provide `paths.tmp`; never infer that path from the backend host. Discovery alone does not prove client/API compatibility. Review documentation, installed declarations and proxy/API parity whenever the client contract changes.
- Server and UI pin `@opencode/client@2.0.15`. Manage the runtime CLI independently: startup checks authenticated loopback `/api/status`, then `/api/health`, then `/api/info`, advancing only on HTTP 404. All probes share the endpoint, credentials, 64 KiB response bound and absolute deadline; authentication, transport and malformed response failures do not trigger fallback. The shared transport maps canonical `server.info()` to the discovered route. Older services do not provide `paths.tmp`; never infer that path from the backend host. Discovery alone does not prove client/API compatibility. Review documentation, installed declarations and proxy/API parity whenever the client contract changes.
- The package root is the generated zero-Effect Promise client. Use installed declarations, not current public `@opencode-ai/sdk` examples.
- Native routes are `/api/*`; CodeNomad exposes them only through the authorized `/workspaces/:id/instance` proxy.
- That proxy is an explicit method/path allowlist. Future upstream APIs are not exposed automatically.
- Proxy authorization and forwarding share one acquired connection. A stale generation must be rejected at actual HTTP dispatch, including after asynchronous body preparation; late streams cannot invalidate a replacement connection.
- The technical minimum is 2.0.7: native `session.step.started.data.started` is consumed directly after removing its older fallback. Recommendation/qualification 2.0.11 is independent. Unknown version labels, prereleases and future majors require bounded authenticated API recognition, including session environment support; they are not rejected solely by label. Legacy HTTP inbox and event conversions are retired. Native `session.inbox.enqueued` still has a distinct shape: its timestamp belongs to event metadata, not an HTTP inbox record.
- The technical minimum is 2.0.7: native `session.step.started.data.started` is consumed directly after removing its older fallback. Recommendation/qualification 2.0.15 is independent. Unknown version labels, prereleases and future majors require bounded authenticated API recognition, including session environment support; they are not rejected solely by label. Legacy HTTP inbox and event conversions are retired. Native `session.inbox.enqueued` still has a distinct shape: its timestamp belongs to event metadata, not an HTTP inbox record.
- Never retry a write using another contract after a 400/404/transport failure. Keep the setup/recovery path distinct from functional transport and never replay prompts.

## Location Is Authority
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ OpenCode owns standard state/database. Allowed configured environment variables

Workspace creation calls `client.location.get({ location: { directory } })` and records the returned directory. Its `project` field supplies project metadata. Public locations have no workspace selector. Explicit Stop Workspace calls `client.debug.location.evict` before removing the logical workspace. Ordinary tab/window close only detaches local UI and never evicts.

The technical minimum is 2.0.7 for the native step-start timestamp, with 2.0.11 independently recommended/tested; old request/response/event and live location translations are retired. Preserve historical `workspaceID` validation internally: obsolete public selectors must be rejected rather than erased from imports, cursors, pending Forms or move rollback. Native 2.0.3→2.0.7/2.0.11 migration collapses workspace selectors to local directory scope while preserving session IDs. See `dev-docs/OPENCODE_V2_POST_BETA.md`.
The technical minimum is 2.0.7 for the native step-start timestamp, with 2.0.15 independently recommended/tested; old request/response/event and live location translations are retired. Preserve historical `workspaceID` validation internally: obsolete public selectors must be rejected rather than erased from imports, cursors, pending Forms or move rollback. Native 2.0.3→2.0.7/2.0.15 migration collapses workspace selectors to local directory scope while preserving session IDs. See `dev-docs/OPENCODE_V2_COMPATIBILITY.md` for current qualification and `dev-docs/OPENCODE_V2_POST_BETA.md` for the transition record.

The instance proxy is method/path allowlisted, rejects unowned paths, `directory`, `location.directory`, and `location[directory]` values, and verifies session location before forwarding. Keep this check at the server trust boundary; new upstream routes require explicit review.

Expand Down
77 changes: 76 additions & 1 deletion dev-docs/OPENCODE_V2_COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ runtimes. Keep detailed results in the change's PR and CI logs, not in per-versi
reports. Update this reference in place.

PR #696's corrected technical minimum is **2.0.7**, when native step-start events
gain the `data.started` field consumed by the current Solid reducer. **2.0.11**
gain the `data.started` field consumed by the current Solid reducer. **2.0.15**
is the recommended release-tested target, not the minimum. Unlisted versions,
including prereleases/custom labels/future majors, undergo authenticated contract
recognition rather than being refused solely for their label. Missing canonical
Expand All @@ -41,6 +41,81 @@ main turn. It passes on 2.0.7 (technical minimum), 2.0.11 and 2.0.12, and runs i
the minimum/latest-stable CI matrix. These targeted results do not change the
global minimum, dependency pins or recommended release-tested version.

### 2.0.14 qualification baseline (2026-09-23)

The qualification baseline includes merged #751 (`0a31a8b3`). Server/UI client
and bundled-plugin dependencies were aligned at **2.0.14**, together with the
then-recommended/tested version. The technical minimum remains **2.0.7**. Newer
runtime labels continue through authenticated contract recognition; this update
does not widen the proxy allowlist or retry mutations under another contract.

The 2.0.11-to-2.0.14 client contract adds `ConnectionCredentialInfo.method`
(`key` or `oauth`). Historical migration assertions retain full comparison of
the old connection fields and separately validate that the synthetic key
credential remains a key when the runtime exposes that metadata. They do not
discard unknown fields or relax session/history preservation checks.

With the 2.0.14 dependencies, isolated Windows fixtures pass native migrations
from 2.0.3 and beta-19271 to both 2.0.7 and 2.0.14, preserving complete history,
forks, pending inbox state and provider configuration. The same native suite
passes against both 2.0.7 and 2.0.14: discovery/automation, plugin provisioning/heartbeats, proxy and
ownership checks, worktrees, Forms/permissions, 241-message history queries,
1,501-message outline/window parity, pruning/concurrency/restart, per-send
environment, inclusive forks and idle/busy side questions. All storage and
daemons are synthetic and isolated. Detailed logs and remaining platform
qualification belong in the qualification PR/CI, not a separate version report.

The previous #751 compatibility failures on Linux, Windows and macOS all stop
at the same additive credential-metadata assertion. Local Windows migration
coverage completed; the subsequent 2.0.15 qualification also confirms the
corrected migrations on Linux, Windows and macOS in CI.
The separate system-message browser fixture still has two search timeouts:
it mocks HTTP APIs with `{}` and does not provide the current bounded history
query contract. Those tests use synthetic browser data, not a 2.0.14 daemon;
they are not native-runtime qualification evidence.

### Current stable target: 2.0.15

Server/UI client, bundled plugin and recommendation advance together to **2.0.15**;
the technical minimum stays **2.0.7**. The upstream client now preserves a
`baseUrl` path prefix ([#50428](https://github.com/anomalyco/opencode/pull/50428)).
CodeNomad removes its former prefix-repair workaround: the generated URL passes
through unchanged, while scheduling classifies the API path relative to the
proxy prefix. A regression using the real generated client reproduced duplicate
proxy prefixes before this correction and verifies exact DELETE/PUT instruction
paths afterward, including deployments with an additional base path.

Declared native API errors are now `Error` instances retaining `_tag`/data
([#50788](https://github.com/anomalyco/opencode/pull/50788)); existing error
classification remains applicable. Undeclared HTTP 500 responses still surface
as `UnexpectedStatus`. Additive contracts include project `time.active`, session
metadata updates and their event; these do not add new proxy routes or minimum
runtime requirements. Runtime changes also cover media/provider handling,
Code Mode expression support and Windows CLI update/uninstall coordination.

These changes do **not** establish a fix for #750's remaining CodeNomad
pre-forward exception. Updating only the CLI cannot replace the client bundled
with CodeNomad. Keep #750 open until a reproducing desktop send verifies its
specific failure; synthetic qualification is not that reproduction.

With the 2.0.15 pins, Windows qualification passes the native suites on both
2.0.7 and 2.0.15 (automation/discovery, proxy/ownership/worktrees, history/pruning,
environment, forks and idle/busy side questions), plus all four historical
migrations from 2.0.3/beta-19271 to minimum/current. The environment fixture's
duplicate prefix workaround was removed too; its initial 403 was reproduced on
both runtimes and the corrected real-manager/native-shell cases pass on both.
CI run `35848468936` confirms historical migrations on Linux, Windows and macOS,
plus native pruning/UI on Linux and macOS. Both Windows runtime suites complete
their 2.0.7/2.0.15 native cases, then fail because the merge-ref workflow invokes
the newer blank-session fixture absent from the checked-out PR head. Integrating
`dev` brings that fixture into the branch; its native checks pass locally on both
runtimes with the 2.0.15 client. The separate Windows pruning/UI CI process exits
without an exception diagnostic. A local Node 24.20.0 run also exits abruptly,
but the subsequent instrumented run passes the complete native/UI suite. Keep
startup phase diagnostics for a recurrence; this passing rerun does not establish
the cause or a fix for the intermittent exit. Detailed results and remaining CI
gates belong in #752 rather than being inferred from other passing platforms.

The audit and implementation record below is historical context, not a runtime
qualification matrix to maintain.

Expand Down
Loading
Loading