Dashboard › opencode › Distillation
0704d985-6e17-4bf1-94c1-aacb24da7d58["lore_tm_v1_JqXVn4wLXkDWqfb-06fearHTmvmkqUbh_ZvERXHdHaE","lore_tm_v1_TmBR7jgJrFAK7PdLKg3iylWTG6JIhD4Ay49sL9ph4H8","lore_tm_v1_-N4x23pyJmRpfAeEhyXTQKV7Uccpm3-HLV_Wmw3mMgU","lore_tm_v1_ZSlT20apWb7Y-8p448g3Wni6jnRc93QSn2cUX1-qReU","lore_tm_v1__1m6d7ACY4rKbd-XcI9H10J0GbvRNHTwQcW2_hZq4-M","lore_tm_v1_5x0x0Oq_upVMFpA_3T0-KTAw_xhTOibIJ329JpGrcHU","lore_tm_v1_sjKdOIn2bAdIMXiXZmZI7LWipczM1m3um4FtmGRA1TM","lore_tm_v1_X7JImTjhXPflyRyYxPPq2eB3bKA9yx6LS5vhEDtL0VM"]
Date: Sep 17, 2026
/tmp/opencode/session-recovery-final-v19.patch is 11,174 lines and contains exactly 34 diff --git sections.packages/client/src/generated/types.ts +72/-0; packages/core/schema.json +567/-48; packages/core/src/database/migration.gen.ts +1/-0; packages/core/src/database/migration/20260914170650_session-recovery.ts +62/-0; packages/core/src/database/schema.gen.ts +52/-1; packages/core/src/session.ts +6/-4; packages/core/src/session/compaction.ts +31/-16; packages/core/src/session/context-epoch.ts +54/-34; packages/core/src/session/execution/local.ts +200/-19; packages/core/src/session/input.ts +391/-31; packages/core/src/session/message-updater.ts +69/-0; packages/core/src/session/projector.ts +88/-1; packages/core/src/session/recovery.ts +504/-0; packages/core/src/session/run-coordinator.ts +30/-5; packages/core/src/session/runner/index.ts +4/-0; packages/core/src/session/runner/llm.ts +358/-104; packages/core/src/session/runner/publish-llm-event.ts +111/-48; packages/core/src/session/sql.ts +88/-1; packages/core/test/database-migration.test.ts +66/-1; packages/core/test/session-execution-local.test.ts +352/-0; packages/core/test/session-projector.test.ts +2771/-3; packages/core/test/session-prompt.test.ts +247/-25; packages/core/test/session-run-coordinator.test.ts +45/-0; packages/core/test/session-runner-recorded.test.ts +5/-10; packages/core/test/session-runner-tool-events.test.ts +46/-7; packages/core/test/session-runner.test.ts +1184/-58; packages/opencode/src/server/routes/instance/httpapi/server.ts +2/-1; packages/schema/src/session-event.ts +43/-1; packages/schema/test/event-manifest.test.ts +8/-5; packages/sdk/js/src/v2/gen/types.gen.ts +190/-0; packages/sdk/openapi.json +657/-44; packages/server/src/routes.ts +2/-0; packages/core/src/session/execution/claim.ts +112/-0; packages/core/src/session/recovery-id.ts +6/-0.packages/core/src/database/schema.gen.ts, packages/core/src/session.ts, packages/core/src/session/execution/local.ts, packages/core/src/session/input.ts, packages/core/src/session/run-coordinator.ts, runner files, tests, generated SDK files, and server routes; a separate complete probe printed checks for all 34 paths in forward and reverse order without an error in that output../packages/sdk/js/script/build.ts for the legacy JavaScript SDK; after public Protocol or Server HttpApi changes, run bun run generate from packages/client; do not directly edit src/generated or src/generated-effect.sdk-next composes Client, Core, and Server.dev; local main may not exist, so diffs should use dev or origin/dev.feat/ or fix/; examples are session-recovery, fix-scroll-state, and regenerate-sdk.type(scope): summary form, with valid types feat, fix, docs, chore, refactor, and test; scopes are optional and may include core, opencode, tui, app, desktop, sdk, or plugin.try/catch and any; prefer Bun APIs such as Bun.file(); rely on inference; prefer flatMap, filter, and map over loops; bind Effect services to named variables before method calls; inline one-use values; avoid unnecessary destructuring; prefer const, ternaries, and early returns over reassignment and else.Effect, untrusted JSON should use helpers such as Schema.UnknownFromJsonString and Schema.decodeUnknownOption, and comments should explain only non-obvious constraints or surprising behavior.snake_case directly so column names do not need explicit string remapping.import { foo as bar } or resolve as pathResolve.import * as Foo and import type * as Foo; import a module’s own exported namespace by name instead, such as import { Project } from "@opencode-ai/core/project", then use Project.ID.await import("./module").then(...) or (await import("./module")).value().do-not-run-tests-from-root guard; tests should minimize mocks, avoid globalThis.* unless unavoidable, exercise actual implementations, and not duplicate implementation logic.bun typecheck from package directories such as packages/opencode; never run tsc directly.SessionV2.prompt(...) to durably admit one session_input before advisory SessionExecution.wake(sessionID), except resume: false is admit-only; the serialized runner promotes admitted inputs at safe boundaries.SessionExecution to remain process-global and Session-ID based; its local implementation owns the process-local coordinator and discovers placement via SessionStore plus LocationServiceMap.get(session.location) only when draining; no layer takes a Session ID; V2 interruption targets the active process-local ownership chain, while idle or missing interruption is a no-op.SessionRunner, model resolution, tool registry, permissions, and filesystem to remain Location-scoped; omitted Location.workspaceID means implicit-local placement, while explicit workspace identity is reserved for future semantics.llm.stream(request) per provider turn and projected-history reload before durable continuation; orchestration must not bridge through legacy SessionPrompt.loop(...) or an in-memory tool loop.SessionRunCoordinator joins explicit same-Session resumes, coalesces prompt wakes, and permits different Sessions concurrently; advisory wakes drain only eligible durable inbox rows; post-crash provider retry requires a separate explicit design; a drain has no durable identity or transcript boundary.steer is default and promotes at the next safe provider-turn boundary while continuation is needed; queue remains pending until the Session would otherwise idle, then exactly one queued input is promoted before continuation is reevaluated; any new user input resets the selected agent’s provider-turn allowance, with a steer batch resetting it once.src/system-context; Context Source producers stay with their observed domains; Session History selection and Context Epoch persistence remain Session-owned.@opencode-ai/schema <- @opencode-ai/protocol <- @opencode-ai/server; Schema contains serializable contracts, not services, runtime registries, side effects, or host-local implementations.V1; permanent replacement architecture must not retain V2 names. New/current code must not depend on the eventual src/v1/ subtree, and @opencode-ai/protocol plus @opencode-ai/sdk-next are the current /api/... surfaces.current, shared transitional, or V1-only; V1 emission alone does not justify Protocol/SDK Next exposure. Events such as message.updated and message.part.* must stay out of the current surface absent a documented current-client need, and each event must have one canonical definition.PluginID, PluginEvent, PtyInfo, PtyEvent, and SessionTodoInfo; use canonical members such as Plugin.ID; Core facades must re-export the exact Schema value; use flat exports plus namespace projections such as export * as SessionMessage from "./session-message".PascalCase, builders/combinators use camelCase, the static combinator is statics(...); optional object properties use the package optional(...) helper; decode-only convenience defaults use Schema.withDecodingDefault(...); public Schema.Struct records use same-name interfaces; public contracts are readonly and must not use Schema.mutable(...).Schema.Any; use Schema.Json for JSON-serializable values and Schema.Unknown for opaque values requiring narrowing; Schema.Any is allowed only at an explicitly unsafe, documented compatibility boundary.create(); directional constructors remain only for public ordering semantics or compatibility; generated ID schemas must validate the exact emitted prefix including _; legacy loose validators must not be tightened without explicit compatibility and migration decisions; public identifiers and brands must be stable and unique.undefined properties, absence of accidental current-contract Schema.Any, stable unique public identifiers, exact facade/Schema identity, and exclusion of V1-only events from current Protocol manifests.export namespace Foo; modules use flat top-level exports plus a self-reexport such as export * as Foo from "./foo", or export * as Foo from "." in a single-namespace index.ts. Multi-sibling directories such as src/session/ and src/config/ must not add barrel index.ts files.Effect.gen(function* () { ... }); use Effect.fn("Domain.method") for traced effects and Effect.fnUntraced for internal helpers; use Effect.callback for callback APIs; use Effect.void; prefer DateTime.nowAsDate; use Schema.Class, Schema.brand, Schema.TaggedErrorClass, and Schema.Defect; directly yield* new MyError(...) for early typed failure branches.makeRuntime from src/effect/run-service.ts for services and InstanceState from src/effect/instance-state.ts for per-directory/project state. Work belongs directly in InstanceState.make; cleanup uses Effect.addFinalizer or Effect.acquireRelease; background consumers use Effect.forkScoped; non-blocking initialization forks InstanceState.get(state) at the call site rather than inside the closure.Effect.fork or Effect.forkDaemon; use Effect.forkIn(scope).FileSystem.FileSystem over raw fs/promises, ChildProcessSpawner.ChildProcessSpawner with ChildProcess.make(...), HttpClient.HttpClient over raw fetch, and Path.Path, Config, Clock, and DateTime within Effect code; scheduled/background work should use Effect.repeat or Effect.schedule with Effect.forkScoped.Effect.cached for sharing in-flight computations instead of manually storing Fiber | undefined or Promise | undefined, and EffectBridge for native/external callbacks that must re-enter Effect services with instance/workspace context.HttpApiBuilder.group(...); SSE returns HttpServerResponse.stream(...) and declares HttpApiSchema.asText({ contentType: "text/event-stream" }); declared raw/WebSocket endpoints use handleRaw(...); raw HttpRouter.use(...) is reserved for routes outside the declared API such as UI fallback.Effect.provideService(...) middleware is only for request-derived context such as WorkspaceRouteContext, InstanceRef, or WorkspaceRef; stable services should be yielded once while constructing the handler layer.Schema.ErrorClass contracts for public JSON errors; built-in HttpApiError.* is allowed only when its empty/tagged body is intended. SDK-visible message-bearing errors need exact declared API schemas, domain/storage layers must remain free of HttpApi types, and expected domain errors are translated at the handler boundary.