Record V2 database, durable-event, projected-message, HTTP, and generated SDK schema changes here. Each entry states why the contract changed and whether consumers or stored data need compatibility handling. Commit messages for schema-affecting changes should include the same summary.
This document covers meaningful contract changes introduced on the `feat/opencode-embedded-api` branch since its divergence from `origin/dev`. Mechanical file moves and internal refactors are omitted unless they changed stored data, replay behavior, public HTTP or SDK shapes, or model-facing tool contracts.
-`session_input`, `session_message`, `event`, `event_sequence`, and disposable workspace beta storage.
- New synchronized `session.next.prompt.admitted.1` and `session.next.prompt.promoted.1` events.
- Experimental `SessionV2.prompt(...)`, HTTP, and generated SDK admission receipt.
Change:
- Replace inbox-local admission sequence with event-sourced prompt admission and promotion sequences.
- Give projected Session messages stable `msg_*` resource IDs distinct from `evt_*` creator event IDs.
- Give every event that creates a projected transcript resource an explicit `msg_*` resource ID. Assistant steps propagate one `assistantMessageID` through assistant-owned events.
- The reset preserves canonical V1 `session`, `message`, and `part` rows.
- Existing synchronized workspaces are disposable beta state and are removed by the reset.
- Before starting the new build, discard adapter-managed external workspace resources created by unreleased builds. The SQL migration cannot remove external resources through runtime adapters, and rediscovering retained resources after startup can replay incompatible beta history.
- Exact prompt retries reconcile one stable `msg_*` identity when Session, prompt, and delivery mode match.
### Replayable Session Event Refinement And Cursor Stream
Affected schema:
- Existing synchronized `session.next.*` event family in `packages/core/src/session/event.ts`.
- Existing projected V2 Session-message union in `packages/core/src/session/message.ts`.
- New explicit durable-event union and internal replay cursor returned by `sessions.events({ sessionID, after? })`.
Change:
- Keep the existing Session lifecycle event family and projected-message union rather than introducing them in this branch.
- Stop synchronizing text deltas, reasoning deltas, and tool-input deltas; keep them explicitly ephemeral.
- Add an explicit durable-event union for replay-safe consumers.
- Add replay-and-tail aggregate cursors backed by durable Session-event sequence.
- Encode synchronized event payloads before writing JSON storage and decode them while replaying so schema transforms remain explicit at the durable boundary.
Reason:
- Embedded Session execution needs a reconnect-safe replay stream over the existing durable log and derived chronological read model.
- Fragment streams are useful to connected renderers but must not advance durable cursors or inflate synchronized storage.
Compatibility:
- The `session.next.*` lifecycle event family predates this branch; this branch refines its experimental V2 durability and replay contracts.
- Durable replay cursors are per-aggregate event sequences; ephemeral deltas are intentionally absent after reconnect.
### Durable Step Settlement Ownership
Affected schema:
-`session.next.step.ended` and `session.next.step.failed` synchronized event version `2`.
- Database migration creates the inbox table and replaces its first pending index with a delivery-aware index.
- Exact prompt retries are idempotent; reusing a message ID for different input fails.
### Durable Session Projection Order
Affected schema:
-`session_message.seq` from `20260603040000_session_message_projection_order.ts`.
- Session-message and event indexes from `20260603001617_session_message_projection_indexes.ts`, `20260603040000_session_message_projection_order.ts`, and `20260603160727_jittery_ezekiel_stane.ts`.
- Persist canonical structured output and content for running, completed, and failed tools.
- Represent tool files explicitly as inline data, remote URL, or managed file URI sources rather than one ambiguous URI string.
Reason:
- Embedded tool execution needs one typed boundary between provider calls, local side effects, durable settlement, and replay.
Compatibility:
- These are additive experimental V2 runtime contracts.
- Tool results are durably settled before provider continuation.
- Legacy text, JSON, and inline-media results remain convertible; unresolved URL and file sources must be materialized or explicitly rejected before provider lowering.
-`PermissionV2.Request`, `AssertInput`, `ReplyInput`, source metadata, tagged errors, and lifecycle events.
- V2 permission list, reply, and saved-rule HTTP routes and generated SDK schemas.
Change:
- Add Location-scoped pending permission requests with `once`, `always`, and `reject` replies.
- Attach optional originating tool message and call IDs.
- Preserve authored ordered rules and saved approvals as separate inputs to evaluation.
- Establish action and resource conventions for `read`, `glob`, `grep`, `edit`, `external_directory`, `bash`, `todowrite`, and `webfetch` approvals.
Reason:
- Embedded tool calls need a Core-owned authorization boundary that can suspend and resume through HTTP.
Compatibility:
- These are additive experimental V2 contracts.
- Policy authors should account for canonical resource forms; originating tool source metadata remains optional until every registry call carries its durable assistant owner.
- Expose embedded Session creation and read-side behavior over the experimental HTTP API.
- Accept optional prompt admission `id`, `delivery`, and `resume` fields so callers can request idempotency, steering or queue semantics, and durable admission without immediate execution.
- Keep message cursors opaque and preserve configured Location routing through both legacy flat and nested `location[...]` query parameters in the V2 SDK client.
Reason:
- Remote and embedded consumers need one generated contract while Location middleware remains compatible with current server routing.
Compatibility:
- These are experimental V2 routes.
- Prompt admission now returns the admitted user-shaped message and may return a conflict error when one message ID is reused for different input.
- SDK Location GET rewriting preserves existing flat query behavior and adds nested compatibility parameters.
## 2026-06-03: Durable Session Message Pagination
Affected schema:
- Internal `SessionV2.messages()` cursor input.
- Opaque cursor payload returned by `GET /api/session/:sessionID/message`.
Change:
- Remove wall-clock `time` from the message cursor payload.
- Resolve the opaque cursor's projected message `id` to its stored `session_message.seq`.
- Apply page boundaries and ordering with durable per-session `seq` rather than `time_created` plus `id`.
Reason:
- Projected V2 message chronology is defined by synchronized Session-event order.
- Wall-clock timestamps may collide or move backwards, so they are not safe pagination boundaries.
- The list endpoint must agree with replay and context loading, which already order by durable sequence.
Compatibility:
- No database migration is required. `session_message.seq` and its session-scoped index already exist.
- The HTTP cursor remains opaque and existing cursors remain usable because they already carry the projected message `id`; older extra `time` data is ignored while decoding.
- No OpenAPI or generated SDK schema changes are required for this pagination correction.
## 2026-06-03: Public Provider And Model Catalog DTOs
Affected schema:
- Responses from `GET /api/provider`, `GET /api/provider/:providerID`, and `GET /api/model`.
- Generated `ProviderV2PublicInfo` and `ModelV2PublicInfo` SDK schemas.
Change:
- Replace internal catalog response schemas with explicit public DTOs.
- Remove provider request headers and bodies, API settings, custom enablement data, model request overrides, and variant request overrides from public responses.
Reason:
- Internal catalog records may contain credentials or provider-specific request material and must not cross the public HTTP serialization boundary.
Compatibility:
- Public V2 catalog responses intentionally expose fewer fields.
- Internal provider and model schemas remain available to the runtime.
## 2026-06-03: Durable Reasoning And Hosted Tool Replay Metadata
Affected schema:
- Durable `session.next.reasoning.started` and `session.next.reasoning.ended` events.
- Durable `session.next.tool.success` and `session.next.tool.failed` events.
- Projected assistant reasoning and settled tool message state.
Change:
- Add optional reasoning `providerMetadata`.
- Add optional durable tool `result` and project it into settled tool message state.
- Preserve projected tool-call metadata separately from optional settlement-result metadata.
- Replay provider-native reasoning and tool metadata only when the historical assistant model matches the selected continuation model.
Reason:
- Provider continuation requires signed or encrypted reasoning metadata on later turns.
- Provider-executed hosted tool results must survive projection so replay can keep hosted calls and results inline in assistant content.
- Recovery settlement must not erase provider-native call metadata needed to reconstruct a valid continuation request.
Compatibility:
- Added durable-event fields are optional so previously recorded experimental events remain decodable.
- Projected settled tool state gains model-facing result data when available.
- Projected assistant tools gain optional result-side provider metadata; the existing metadata slot remains the backward-compatible call-side slot.
- OpenAI Responses lowers reconstructed provider-executed hosted results to stored item references instead of rejecting assistant history.
- Bedrock Converse signatures, Gemini `thoughtSignature`, and OpenAI-compatible Chat `reasoning_content` now round-trip through canonical continuation parts.
## 2026-06-03: Projected Assistant Ownership And Full-Value Parts
Affected schema:
- Projected assistant text parts.
- Durable text and tool lifecycle boundaries.
- Projected assistant tool ownership.
Change:
- Preserve stable IDs on projected assistant text parts.
- No database, durable-event, HTTP, or generated SDK schema changes.
- Internal runner recovery and permission evaluation behavior only.
Change:
- Evaluate permissions through the default `build` agent when a Session omits an explicit agent, matching provider-turn execution.
- Before assembling a provider request, durably fail local tools still projected as `running` from a previous process with the existing `session.next.tool.failed` shape and `Tool execution interrupted` message.
Reason:
- Agent-less embedded Sessions previously executed as `build` while evaluating an empty permission ruleset, so the first local tool could wait forever for an approval surface the local Discord proof did not expose.
- A process lost while a local tool was running previously left a dangling tool call that made later provider continuation invalid. Recovery must settle the durable projection without replaying an abandoned side effect.
Compatibility:
- No migration, synchronized event version, OpenAPI, or SDK regeneration is required.
- Existing experimental Session databases recover dangling local-tool projections on the next provider attempt.
## 2026-06-03: V2 Skill Tool
Affected schema:
- New Core-owned `skill` model-facing tool parameters and success payload.
- Existing upstream `SkillV2` service remains the single Location-scoped skill registry.
Change:
- Accept `{ name: string }` for one skill selected from the upstream-discovered Location skill list.
- Assert `skill` permission for the selected name.
- Return V1-shaped `<skill_content name="...">` model output with the skill base directory and a bounded sampled supporting-file list.
Compatibility:
- This is an additive model-facing V2 tool contract.
- No database migration, durable-event version, public HTTP, OpenAPI, or generated SDK change is required.
- Existing durable tool-failure and replay-owner schemas are reused without version changes.
Change:
- Fence replay envelopes whose aggregate ID differs from the decoded synchronized payload and persist owner claims when replay first adopts an existing unowned aggregate.
- Settle abandoned local and provider-executed tools durably before continuation; hosted failures preserve inline provider-executed replay.
- Give `apply_patch` add hunks create-only semantics, make sequential commits uninterruptible after preflight, and reject malformed patch grammar eagerly.
- Wait for initial plugin boot before materializing the `skill` built-in, discover conventional config-root skill directories, and resolve current skills again during execution.
- Sanitize provider and model public API URLs by stripping credentials, queries, and fragments.
- Keep V1-like `webfetch` network semantics: approve the requested HTTP(S) URL, allow ordinary hostnames, and delegate redirects to the HTTP transport.
- Keep V2 request bodies required in generated OpenAPI and SDK types.
Compatibility:
- No database migration is required.
- Pre-launch `session.next.*` databases remain disposable experimental state rather than compatibility targets; reset experimental V2 data when upgrading across incompatible event-schema iterations.
- V1 returns fetched images as attachments. The first Core V2 typed settlement remains text-only, so V2 continues to reject fetched images and other non-text files until attachment settlement is designed explicitly.
## 2026-06-03: Defer V2 Bash Background Execution
Affected schema:
- Core V2 model-facing `bash` tool parameters and success payload.
Change:
- Remove the optional `background` bash parameter and process-local background settlement shape from the shipped tool.
- Retain the internal `BackgroundJob` prototype for a later integration slice.
Reason:
- The model has no registered observation or cancellation tool for background bash jobs, and process-local status is not a sufficient remote contract.
Compatibility:
- Foreground V2 bash execution is unchanged.
- Reintroduce background bash only with durable status observation, completion delivery, and explicit cancellation semantics.
- Add `session_context_epoch` for one active immutable baseline string, structured JSON snapshot, and baseline sequence per Session.
Change:
- Lazily initialize one durable Context Epoch snapshot at the first safe provider-turn boundary.
- Lower its exact baseline string through `LLMRequest.system` for every provider turn in the epoch.
- Reuse the stored baseline verbatim after restart or producer changes instead of resampling privileged initial context.
- Compare later observations against an overwriteable codec-encoded structured snapshot rather than rendered-text hashes.
- Expose admitted chronological context as first-class `system` Session messages while keeping the active baseline in bounded context state.
Compatibility:
- The unpublished Context Epoch schema is consolidated into one database migration; baseline and structured snapshots are operational state rather than synchronized event history.
- Add synchronized `session.next.context.updated.1` Session events containing a durable System-message ID and only exact combined model-visible text.
- Add `session_context_epoch.revision` for transactional structured-snapshot advancement.
- Add the first-class `system` Session message projection for chronological context updates.
Change:
- Reconcile Location-scoped Context Sources at each safe provider-turn boundary using one coherent observation.
- Keep the stored baseline immutable while admitting changed source renderings as chronological `Message.system(...)` history.
- Advance the overwriteable structured snapshot atomically with the rendered System-message event.
- Emit the previously stored model-meaningful removal rendering when a source is removed.
- Reject chronological system updates that would split a local tool call from its result across provider protocols; use wrapped user fallback when Anthropic native system-update placement is unsupported.
Compatibility:
- The synchronized event log retains only text actually shown to the model, not internal structured snapshots.
## 2026-06-05: Register Ambient System Context Producers
Affected schema:
- No database schema changes.
Change:
- Replace the Session-specific context loader with a Location-scoped registry of stable-keyed scoped context producers.
- Register environment/date and ambient instruction producers independently, then evaluate producers concurrently in stable contribution-key order.
- Directly discover and read global plus upward project `AGENTS.md` files at each safe provider-turn boundary.
- Preserve admitted instructions across transient scan/read failures and block first-epoch initialization while any context source is unavailable.
- Retry Context Epoch preparation until stable after optimistic revision mismatches.
- Clear the active Context Epoch when a Session moves so the destination initializes a complete baseline before promoting more input.
- Fence Context Epoch initialization against the authoritative Session Location so a concurrent old-Location runner cannot recreate stale privileged context after a move.
- Canonicalize ambient instruction traversal boundaries, honor `OPENCODE_DISABLE_PROJECT_CONFIG`, and make non-empty aggregate updates explicitly supersede previously loaded instructions.
- Add `session_context_epoch.agent` so each durable baseline records its owning effective agent.
- No synchronized event, public HTTP API, or generated SDK schema changes.
Change:
- Compose selected-agent, permission-filtered available-skill guidance with Location-wide System Context before Context Epoch admission.
- Keep skill bodies behind the existing permission-checked `skill` tool and remove the unfiltered skill list from its Location-wide definition.
- Stop missing-skill errors from enumerating the unfiltered Location-wide skill catalog.
- Bind local tool authorization and pending permission requests to the provider turn's effective agent.
- Keep absolute skill locations out of available-skill guidance; expose body and location only through the permission-checked `skill` tool.
- Request Context Epoch replacement after an agent switch, dynamically re-observe the effective agent during retries, and fence first-epoch creation against the authoritative effective agent.
- Fence existing-epoch replacement against the authoritative effective agent and block cross-agent provider turns while replacement context is unavailable.
- Group the System Context algebra, registry, and built-ins under `system-context/`; keep source producers and Context Epoch persistence with their owning Skill, instruction, and Session modules; rename projected conversation selection to Session History.
- Add the canonical V1-to-V2 runtime-context parity checklist to `specs/v2/session.md`.
Compatibility:
- Existing Context Epoch rows backfill the default `build` agent and reconcile to another selected agent at the next safe provider-turn boundary.