Bladeren bron

docs: add OpenCode v2 gap report

Alvin Unreal 3 weken geleden
bovenliggende
commit
5266063501
2 gewijzigde bestanden met toevoegingen van 361 en 0 verwijderingen
  1. 3 0
      docs/opencode-v2-compatibility.md
  2. 358 0
      docs/opencode-v2-gap-report.md

+ 3 - 0
docs/opencode-v2-compatibility.md

@@ -5,6 +5,9 @@ and OpenCode v2 (`opencode2`) from a single published package. This document
 describes how each host loads the plugin, what is supported where, and how to
 register it.
 
+> **Capability details:** see the [OpenCode v2 capability-gap report](opencode-v2-gap-report.md)
+> for the verified matrix, source citations, and migration dispositions.
+
 ## How it works
 
 The package's default export is an object:

+ 358 - 0
docs/opencode-v2-gap-report.md

@@ -0,0 +1,358 @@
+# OpenCode beta v2 capability-gap report
+
+This report is the detailed companion to the [v2 compatibility guide](opencode-v2-compatibility.md).
+It describes the gap between this plugin's v1 behavior and a native OpenCode
+v2 Promise plugin. It does **not** claim that native v2 support has shipped.
+
+## Scope and authority
+
+- **Target:** OpenCode beta v2, commit
+  `d6deb62379c54dc60468b80c498bd6a5899797cf`.
+- **Current implementation:** the adapter in
+  [`src/v2/setup.ts`](../src/v2/setup.ts), which invokes the v1 factory and
+  translates selected hooks.
+- **Matrix authority:** the verified Oracle migration review, not the earlier
+  optimistic compatibility inventory. The source citations below point to the
+  pinned beta checkout and to the current adapter; they do not imply that the
+  adapter has native v2 parity.
+- **Boundary rule:** an HTTP endpoint in OpenCode's Protocol or Client package
+  is not automatically a Promise plugin API. This report cites the Promise
+  plugin context and domain types where plugin support is claimed.
+
+## Classifications
+
+- **Direct official mapping** — the beta Promise plugin exposes a domain or
+  hook that can own the behavior. Native code still needs implementation and
+  verification; the current adapter is not proof of parity.
+- **Supported only with behavior change** — v2 exposes useful primitives, but
+  not the v1 lifecycle, atomicity, persistence, or UI semantics. The behavior
+  must be redesigned and documented.
+- **Unavailable** — the supported Promise plugin surface has no equivalent;
+  do not preserve the behavior with a fake client or inferred protocol calls.
+
+## At-a-glance matrix
+
+| Capability | Classification | Disposition |
+| --- | --- | --- |
+| Session context and prompt transforms | Direct official mapping | Implement with `session.hook("context")`; remove v1 payload conversion. |
+| Tools and lifecycle | Direct mapping; v1-only hooks change | Port registration and compatible hooks; redesign cancellation/permission-dependent hooks. |
+| Command definitions | Direct official mapping | Add executable Promise commands. |
+| Global command interception | Unavailable | Retire the v1 interception contract. |
+| Current adapter `draft.update` | Unverified/incompatible | Do not treat it as Promise command parity; replace with `draft.add`. |
+| MCP registration | Direct official mapping | Register through `ctx.mcp.transform` and reload. |
+| Events and live Companion signals | Direct official mapping | Consume volatile `{ type, data }` events; redesign reconnect/reload reconstruction. |
+| Cache telemetry | Direct official mapping | Read `session.step.ended` `data.tokens.cache.read/write`. |
+| Atomic model failover | Unavailable | Retire the exact atomic contract. |
+| Non-atomic model retry | Supported only with behavior change | Redesign retry and transcript semantics explicitly. |
+| Explicit reusable session IDs | Direct official mapping | Use `session.create({ id })`; keep it separate from scheduler semantics. |
+| Background scheduler, child/todo/status reads | Unavailable | Retire or separately redesign the legacy job-board contract. |
+| External multiplexer panes | Unavailable | Retire external pane parity or design a separate TUI replacement. |
+| Tool cancellation and permissions | Unavailable | Use host-managed controls; retire v1 interception. |
+| Interview recovery | Supported only with behavior change | Persist and reconcile history explicitly. |
+| TUI controls | Direct official mapping | Implement a native `tui: true` surface. |
+| `/preset` semantics | Supported only with behavior change | Rebuild selection and session/configuration updates explicitly. |
+
+## Capability matrix
+
+### Session context and prompt transforms
+
+**Classification: Direct official mapping.**
+
+- **v1 behavior:** system and message transforms inject the orchestrator
+  prompt, phase reminders, skill filtering, display-name rewrites, image
+  routing, and background-job context. The adapter converts v2 messages to v1
+  `{ info, parts }` values before running those transforms.
+- **Exact v2 surface:** `session.hook("context")` receives `sessionID`,
+  `agent`, `model`, mutable `system`, `messages`, and `tools`. This is the
+  supported replacement for raw v1 message transforms.
+- **What changes:** native code must mutate the v2 context directly. It must
+  preserve prompt-cache prefix rules and explicitly decide which injections
+  remain valid when v1 message ordering and part shapes disappear.
+- **Disposition:** implement natively; remove the v1 conversion and verify
+  cache-safe output with a pinned host.
+
+Source: [Promise session domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/session.ts#L9-L16),
+[current adapter context bridge](../src/v2/setup.ts#L220-L300).
+
+### Tools and lifecycle hooks
+
+**Classification: Direct official mapping for registration and execution
+observation; supported only with behavior change for v1 hook semantics.**
+
+- **v1 behavior:** registers custom tools and runs before/after hooks for
+  apply-patch recovery, JSON recovery, task-session bookkeeping, loop guards,
+  and post-tool nudges.
+- **Exact v2 surface:** `tool.transform` adds a tool; `tool.hook` exposes
+  `execute.before` with mutable input and `execute.after` with completed/error
+  results. `shell.hook("create.before")` is the shell-specific lifecycle hook.
+- **What changes:** native tools use v2 tool definitions and result types.
+  Before/after hooks can validate or rewrite input and observe results, but
+  they are not a general cancellation, permission, or arbitrary lifecycle
+  interception mechanism.
+- **Disposition:** map registration and compatible hooks natively; redesign or
+  retire hooks that depend on v1-only output, cancellation, or permission
+  timing.
+
+Source: [Promise tool domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/tool.ts#L25-L63),
+[Promise shell domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/shell.ts#L3-L17).
+
+### Commands and global interception
+
+**Classification: Direct official mapping for command definitions; unavailable
+for the v1 global pre-execution interception contract.**
+
+- **v1 behavior:** supplies `/deepwork`, `/reflect`, `/loop`, and `/interview`
+  commands, and uses `command.execute.before` to rewrite or intercept command
+  execution globally.
+- **Exact v2 surface:** `command.transform` adds executable
+  `{ name, description, execute }` definitions and provides `reload()`. The
+  Promise command domain does not expose a global `command.execute.before`
+  hook.
+- **What changes:** native commands must own their execution callback. A
+  command definition is not evidence that every v1 pre-execution transform is
+  preserved.
+- **Disposition:** port command behavior into explicit executable definitions;
+  redesign or retire global interception. **The current adapter's
+  `draft.update` translation is unverified and incompatible with the native
+  Promise `CommandDraft`, so it must not be treated as command parity.**
+
+Source: [Promise command domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/command.ts#L13-L25),
+[current command adapter](../src/v2/setup.ts#L169-L218).
+
+### MCP registration
+
+**Classification: Direct official mapping.**
+
+- **v1 behavior:** creates built-in MCP definitions and merges them through the
+  v1 config hook.
+- **Exact v2 surface:** `mcp.transform` can list/get/set/update/remove server
+  configurations and `mcp.reload()` applies the result.
+- **What changes:** native setup must register built-in MCP configurations
+  through `ctx.mcp`; it must not rely on the v1 config mutation or describe MCP
+  support as config-only because the adapter currently omits this bridge.
+- **Disposition:** add native MCP registration and verify connection/status
+  behavior independently.
+
+Source: [Promise MCP domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/mcp.ts#L6-L17),
+[current v1 config bridge](../src/v2/setup.ts#L65-L98).
+
+### Events
+
+**Classification: Direct official mapping for observation; supported only with
+behavior change for v1 lifecycle semantics.**
+
+- **v1 behavior:** observes host events for session tracking, task lifecycle,
+  companion state, cache monitoring, pane cleanup, and model fallback.
+- **Exact v2 surface:** `ctx.event.subscribe()` returns a live, volatile
+  stream of events shaped as `{ type, data }` (with transport metadata on some
+  events). It is an observation stream, not a replay/history API, pane-control
+  API, task scheduler, or atomic execution transaction.
+- **What changes:** native consumers must read the v2 `data` field and map the
+  published event schema. **The current adapter forwards each event unchanged
+  to the v1 hook and interview bridge; its handlers still read `properties`,
+  so this forward path is unchanged and incompatible.** An event stream cannot
+  create, mirror, or control tmux/zellij panes.
+- **Disposition:** implement explicitly mapped live-event projections and a
+  separate recovery/replay design where needed. Do not treat the current
+  adapter's event support as parity.
+
+Source: [Promise event domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/event.ts#L1-L3),
+[Promise event subscription](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/client/src/promise/generated/client.ts#L1532-L1538),
+[v2 event shape](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/client/src/promise/generated/types.ts#L1183-L1200),
+[current unchanged forwarder](../src/v2/setup.ts#L375-L408),
+[current `properties` reader](../src/v2/interview-bridge.ts#L213-L240).
+
+### Cache telemetry
+
+**Classification: Direct official mapping.**
+
+- **v1 behavior:** the cache monitor observes host lifecycle/message signals and
+  reports cache diagnostics without rewriting the prompt.
+- **Exact v2 surface:** `session.step.ended` is a durable v2 event whose
+  `data.tokens` contains `cache.read` and `cache.write`. A native subscriber
+  can read those counters directly from the event.
+- **What changes:** replace the v1 lifecycle/message monitor with a projection
+  over `session.step.ended` and its `{ type, data }` payload. The current
+  adapter does not translate this payload shape, so its cache handling is not
+  native telemetry parity.
+- **Disposition:** implement the direct event projection and preserve the
+  host/provider-reported values without inferring additional cache state.
+
+Source: [session step event](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/schema/src/session-event.ts#L307-L322),
+[generated v2 event payload](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/client/src/promise/generated/types.ts#L1183-L1200),
+[current unchanged event forwarder](../src/v2/setup.ts#L375-L408).
+
+### Companion signals
+
+**Classification: Direct official mapping for live signals; supported only with
+behavior change for reconnect/reload reconstruction.**
+
+- **v1 behavior:** the companion manager receives session status and
+  permission/question waiting/resolution signals and presents companion-side
+  state.
+- **Exact v2 surface:** `ctx.event.subscribe()` carries live `session.status`
+  and permission events, including `permission.asked` and
+  `permission.replied`. These are the direct source for live Companion
+  signals. This does not infer a current question event from the separate v1
+  question contract.
+- **What changes:** reconnect and plugin reload cannot assume that a volatile
+  subscription replays prior signals. Reconstructing Companion state after a
+  reconnect/reload requires an explicit status/history reconciliation design.
+- **Disposition:** map live signals directly; redesign reconnect/reload state
+  reconstruction separately.
+
+Source: [session status event](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/schema/src/session-status-event.ts#L35-L43),
+[permission events](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/schema/src/permission.ts#L43-L52),
+[Promise event domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/event.ts#L1-L3).
+
+### Model failover and small-model selection
+
+**Classification: Unavailable for atomic failover; supported only with behavior
+change for non-atomic retry. Small-model selection remains an inventory
+decision.**
+
+- **v1 behavior:** `ForegroundFallbackManager` reacts to provider/rate-limit
+  failures, aborts, selects the next model, and re-prompts. The current code
+  also uses `runtime.smallModel()` for SmartFetch secondary-model selection.
+- **Exact v2 surface:** `session.switchModel`, `session.interrupt`, and session
+  hooks for `model.request`, `http.request`, and `http.response` exist. None
+  defines an atomic failure-detection, model-switch, retry, and transcript
+  transaction.
+- **What changes:** exact atomic failover is unavailable. A non-atomic retry
+  can be redesigned around explicit retry and transcript semantics, but
+  **`switchModel` must not be described as atomic failover**.
+- **Disposition:** retire the exact atomic contract and separately redesign
+  non-atomic retry. Treat small-model selection as an inventory decision:
+  determine the native SmartFetch equivalent before deciding its fate.
+
+Source: [Promise session domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/session.ts#L41-L63),
+[current model selection](../src/index.ts#L261-L287),
+[current fallback manager](../src/index.ts#L351-L360).
+
+### Background scheduler, child reads, status, and reusable IDs
+
+**Classification: Direct official mapping for explicit reusable session IDs;
+unavailable for the legacy scheduler and child/todo/status semantics.**
+
+- **v1 behavior:** the background job board and scheduler own reusable child
+  sessions, wake orchestration, task cancellation/revival, child/todo/status
+  reads, and task identity reconciliation.
+- **Exact v2 surface:** Promise `session` exposes `create`, and the official
+  `session.create` input accepts an explicit `id`. This is a direct mapping for
+  reusable session identity. It does not expose the v1 child/todo/status/
+  prompt-async read model or a background-job scheduler.
+- **What changes:** explicit session IDs must remain distinct from task-board
+  ownership and reconciliation. The legacy scheduler replacement would still
+  need to define wake, status certainty, cancellation, revival, and ID conflict
+  behavior.
+- **Disposition:** use explicit IDs where session identity is sufficient;
+  retire or separately redesign the legacy scheduler/board contract. Do not
+  infer scheduler capabilities from Protocol session endpoints.
+
+Source: [Promise session domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/session.ts#L48-L63),
+[explicit session ID input](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/protocol/src/groups/session.ts#L170-L184),
+[current scheduler/board](../src/hooks/task-session-manager/index.ts#L1-L49),
+[current supervisor](../src/utils/background-job-supervisor.ts#L23-L29).
+
+### Multiplexer and child panes
+
+**Classification: Unavailable for external multiplexer parity; supported only
+with behavior change through native TUI controls.**
+
+- **v1 behavior:** tmux, zellij, herdr, and cmux panes mirror child task
+  sessions and are cleaned up from lifecycle events.
+- **Exact v2 surface:** the TUI context provides data, tabs, slots, keymaps,
+  dialogs, and UI controls. It does not provide the external multiplexer
+  process/pane API.
+- **What changes:** native v2 can render a redesigned TUI experience, but an
+  event subscription cannot create or mirror external panes.
+- **Disposition:** retire external pane parity for native v2 or replace it with
+  a separately specified TUI design.
+
+Source: [TUI context UI surface](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/tui/context.ts#L414-L468),
+[current multiplexer session manager](../src/multiplexer/session-manager.ts#L1-L49).
+
+### Tool cancellation and permissions
+
+**Classification: Unavailable for exact v1 interception; supported only with
+behavior change through host-managed controls.**
+
+- **v1 behavior:** tool hooks participate in task cancellation and permission
+  prompting/recovery.
+- **Exact v2 surface:** Promise tool hooks cover `execute.before` and
+  `execute.after`; Session provides whole-session interrupt. The Promise plugin
+  context does not expose a v1-equivalent permission-prompt interception or
+  per-tool cancellation hook.
+- **What changes:** native tools must rely on official host permission policy
+  and session interruption semantics. Before/after hooks cannot be treated as
+  cancellation or permission ownership.
+- **Disposition:** retire exact v1 interception and document the host-managed
+  behavior.
+
+Source: [Promise tool hooks](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/tool.ts#L31-L63),
+[Promise session operations](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/session.ts#L48-L63),
+[current tool lifecycle hooks](../src/hooks/task-session-manager/tool-execute-hooks.ts#L1-L7).
+
+### Interview recovery
+
+**Classification: Supported only with behavior change.**
+
+- **v1 behavior:** the current adapter keeps a per-session transcript in an
+  in-memory `Map`, repopulates it from the v2 context hook, and updates it from
+  streamed text events. The interview service separately persists Q/A history
+  and final documents to markdown; the tests assert that history is appended
+  and preserved across writes.
+- **Exact v2 surface:** Session context hooks can inject or transform current
+  context; Promise storage provides JSON get/set/remove/scan; event subscription
+  observes public events. No API automatically restores a plugin-owned
+  interview transcript into a reloaded session.
+- **What changes:** native code must define durable state, versioning, reload
+  reconciliation, and prompt injection itself. In-memory projections are not
+  recovery.
+- **Disposition:** redesign with explicit storage and recovery tests, or retire
+  reload reconstruction.
+
+Source: [Promise storage domain](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/storage.ts#L4-L9),
+[current in-memory/context reconstruction](../src/v2/interview-bridge.ts#L56-L66),
+[current markdown persistence](../src/interview/document.ts#L400-L491),
+[history preservation tests](../src/interview/interview.test.ts#L283-L356).
+
+### TUI and preset controls
+
+**Classification: Direct official mapping for TUI controls; supported only with
+behavior change for preset semantics.**
+
+- **v1 behavior:** `/preset` has an interactive switcher, and v1 uses TUI
+  notifications/toasts for user feedback.
+- **Exact v2 surface:** the Promise plugin definition may set `tui: true`; the
+  TUI context exposes `ui.toast`, dialogs including `select`, keymap commands,
+  slots, tabs, data, attention, and durable storage. Promise command
+  definitions and `session.switchModel` are also available, but do not by
+  themselves recreate the v1 preset semantics.
+- **What changes:** native migration must implement a TUI plugin/control path
+  and decide how preset selection updates configuration and sessions. The
+  current Promise adapter does not bridge these controls.
+- **Disposition:** map TUI controls directly in a native TUI plugin; rebuild
+  `/preset` selection and its configuration/session effects explicitly. Do not
+  claim current adapter parity.
+
+Source: [Promise plugin definition](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/promise/plugin.ts#L19-L49),
+[TUI controls](https://github.com/anomalyco/opencode/blob/d6deb62379c54dc60468b80c498bd6a5899797cf/packages/plugin/src/tui/context.ts#L241-L468),
+[current v2 setup](../src/v2/setup.ts#L194-L218).
+
+## Migration disposition
+
+The native implementation should proceed in this order:
+
+1. Extract host-neutral agent, prompt, tool, and configuration logic without
+   carrying v1 hook payloads across the boundary.
+2. Implement direct mappings: session context, tools, executable commands,
+   MCPs, event observation, and the explicitly chosen TUI surface.
+3. Specify behavior changes for failover, telemetry, companion signals,
+   interview recovery, and session-based background work.
+4. Retire unavailable v1 contracts: global command interception, legacy task
+   scheduler/child reads, external multiplexer panes, and tool permission or
+   cancellation interception.
+5. Verify native registration, cleanup, context transformation, tool lifecycle,
+   MCP registration, event mapping, TUI controls, and both host cutover paths
+   before removing the adapter.