DashboardopencodeSession 03ipsxxs0vLT

Session 03ipsxxs0vLT

Full ID: 03ipsxxs0vLTYjLT7
Messages: 57
Distillations: 12
Time range: 2026-09-16 14:44:25 — 2026-09-16 14:59:10

Conversation (57 messages)

Perform the final independent CORRECTNESS/adversarial review of the immutable OpenCode V2 recovery candidate. Read-only only: do not modify files, refs, index, services, artifacts, or databases; do not build or run tests. Immutable base is ab9408c81cc9916177641ae8e9f08624fc27b5b9. Frozen patch is /tmp/opencode/session-recovery-final-v7.patch with expected SHA-256 9fdee0490a8756207a93adc96c708c0327e4a9b39c58301ce55aed70fe6fa00e. Exact built SEA is /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server with expected SHA-256 f02bc81487350640f989f37bb813043c88f80a8fb59a138bf08f4ff718b1b2ba. A clean applied inspection tree exists at /tmp/opencode/session-recovery-v7-check; note newly added files are untracked there because the patch is not committed, so inspect them too. First verify the exact hashes and that the patch applies to the exact base; if either differs, report the exact blocker and stop. Inspect all 33 changed files and trace behavior across Schema/Core/Server/SDK. Review especially: exact execution lease fencing; never taking a live lease; never renewing an expired owner; no second owner/re-entry; explicit decline keeps renewal alive through finalizers then atomically clears the exact claim; provider/tool fiber interruption and joining; stream failure after step-finish never commits Step.Ended; interrupted assistants never remain running; hosted/local tool reconciliation ordering; fresh synthetic queued continue only; no replay of uncertain calls; recovery validation and reservation; replay-safe wake intent; bounded 100-row scheduler with retry reservation under endless fresh work; saturating and DB-constrained counters; CAS no-op/failure paths; restart/layer reconstruction; migration schema lineage; deterministic tests and negative controls. ...

gateway · 2026-09-16 14:44:25
result
No files found
gateway · 2026-09-16 14:45:09
result
9fdee0490a8756207a93adc96c708c0327e4a9b39c58301ce55aed70fe6fa00e  /tmp/opencode/session-recovery-final-v7.patch
f02bc81487350640f989f37bb813043c88f80a8fb59a138bf08f4ff718b1b2ba  /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server
ab9408c81cc9916177641ae8e9f08624fc27b5b9
 M packages/core/schema.json
 M packages/core/src/database/migration.gen.ts
 M packages/core/src/database/schema.gen.ts
 M packages/core/src/session.ts
 M packages/core/src/session/compaction.ts
 M packages/core/src/session/context-epoch.ts
 M packages/core/src/session/execution/local.ts
 M packages/core/src/session/input.ts
 M packages/core/src/session/message-updater.ts
 M packages/core/src/session/projector.ts
 M packages/core/src/session/run-coordinator.ts
 M packages/core/src/session/runner/index.ts
 M packages/core/src/session/runner/llm.ts
 M packages/core/src/session/runner/publish-llm-event.ts
 M packages/core/src/session/sql.ts
 M packages/core/test/database-migration.test.ts
 M ...
gateway · 2026-09-16 14:45:16
result
Found 33 matches
/tmp/opencode/session-recovery-final-v7.patch:
  Line 1: diff --git a/packages/core/schema.json b/packages/core/schema.json

  Line 881: diff --git a/packages/core/src/database/migration.gen.ts b/packages/core/src/database/migration.gen.ts

  Line 892: diff --git a/packages/core/src/database/migration/20260914170650_session-recovery.ts b/packages/core/src/database/migration/20260914170650_session-recovery.ts

  Line 956: diff --git a/packages/core/src/database/schema.gen.ts b/packages/core/src/database/schema.gen.ts

  Line 1058: diff --git a/packages/core/src/session.ts b/packages/core/src/session.ts

  Line 1090: diff --git a/packages/core/src/session/compaction.ts b/packages/core/src/session/compaction.ts

  Line 1179: diff --git a/packages/core/src/session/context-epoch.ts b/packages/core/src/session/context-epoch.ts

  Line 1355: diff --git a/packages/core/src/session/execution/local.ts b/packages/core/src/session/execution/local.ts

  Line 1541: diff --git ...
gateway · 2026-09-16 14:46:27
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/execution/claim.ts</path>
<type>file</type>
<content>
1: export * as SessionExecutionClaim from "./claim"
2: 
3: import { and, eq, gt } from "drizzle-orm"
4: import { Clock, Effect } from "effect"
5: import type { Database } from "../../database/database"
6: import type { SessionSchema } from "../schema"
7: import { SESSION_EXECUTION_LEASE_MS, SessionExecutionTable } from "../sql"
8: 
9: type DatabaseService = Database.Interface["db"]
10: 
11: export type Claim = {
12:   readonly sessionID: SessionSchema.ID
13:   readonly executionID: string
14:   readonly ownerID: string
15: }
16: 
17: export type Values = Partial<Pick<typeof SessionExecutionTable.$inferInsert, "assistant_message_id" | "phase">>
18: 
19: export class Lost extends Error {
20:   constructor(readonly claim: Claim) {
21:     super(`Session execution claim lost: ${claim.executionID}`)
22:   }
23: }
24: 
25: const where = (claim: Claim, now: number) ...
gateway · 2026-09-16 14:46:31
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/execution/local.ts</path>
<type>file</type>
<content>
1: import { and, asc, eq, isNull } from "drizzle-orm"
2: import { Cause, Clock, Duration, Effect, Exit, Layer, Schedule } from "effect"
3: import { Database } from "../../database/database"
4: import { LocationServiceMap } from "../../location-service-map"
5: import { makeGlobalNode } from "../../effect/app-node"
6: import { SessionRunCoordinator } from "../run-coordinator"
7: import { SessionRunner } from "../runner"
8: import { SessionMessage } from "../message"
9: import { SessionSchema } from "../schema"
10: import { SessionStore } from "../store"
11: import { SessionExecution } from "../execution"
12: import { SessionExecutionClaim } from "./claim"
13: import { SESSION_EXECUTION_LEASE_MS, SessionExecutionTable, SessionRecoveryTable } from "../sql"
14: 
15: /** Current-process routing for implicit-local Locations. Future remote placement belongs here. ...
gateway · 2026-09-16 14:46:40
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/recovery.ts</path>
<type>file</type>
<content>
1: export * as SessionRecovery from "./recovery"
2: 
3: import { and, asc, desc, eq, exists, gt, isNull, lte, or, sql } from "drizzle-orm"
4: import { Clock, DateTime, Effect, Layer, Option, Schedule, Schema } from "effect"
5: import { Database } from "../database/database"
6: import { makeGlobalNode } from "../effect/app-node"
7: import { EventV2 } from "../event"
8: import { SessionEvent } from "./event"
9: import { SessionExecution } from "./execution"
10: import { SessionProjector } from "./projector"
11: import { SessionExecutionClaim } from "./execution/claim"
12: import { SessionInput } from "./input"
13: import { SessionSchema } from "./schema"
14: import {
15:   MAX_WAKE_ATTEMPTS,
16:   SESSION_EXECUTION_LEASE_MS,
17:   SessionExecutionTable,
18:   SessionInputTable,
19:   SessionRecoveryTable,
20:   SessionMessageTable,
21:   SessionTable,
22: } from ...
gateway · 2026-09-16 14:46:47
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/input.ts</path>
<type>file</type>
<content>
1: export * as SessionInput from "./input"
2: 
3: import { and, asc, desc, eq, isNull, lte } from "drizzle-orm"
4: import { DateTime, Effect, Option, Schema } from "effect"
5: import { Admitted, Delivery } from "@opencode-ai/schema/session-input"
6: import type { Database } from "../database/database"
7: import { EventV2 } from "../event"
8: import { SessionEvent } from "./event"
9: import { SessionMessage } from "./message"
10: import { Prompt } from "./prompt"
11: import { continuation, message } from "./recovery-id"
12: import { SessionSchema } from "./schema"
13: import { SessionInputTable, SessionMessageTable, SessionRecoveryTable } from "./sql"
14: 
15: type DatabaseService = Database.Interface["db"]
16: 
17: export { Admitted, Delivery }
18: 
19: const decodePrompt = Schema.decodeUnknownSync(Prompt)
20: const encodePrompt = Schema.encodeSync(Prompt)
21: const ...
gateway · 2026-09-16 14:46:53
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/run-coordinator.ts</path>
<type>file</type>
<content>
1: export * as SessionRunCoordinator from "./run-coordinator"
2: 
3: import { Deferred, Effect, Exit, Fiber, FiberSet, Scope } from "effect"
4: 
5: /** Serializes execution for each key while allowing different keys to run concurrently. */
6: export interface Coordinator<Key, E> {
7:   /** Snapshots keys with an execution owned by this coordinator. */
8:   readonly active: Effect.Effect<ReadonlySet<Key>>
9:   /** Starts execution while idle or joins the active execution. */
10:   readonly run: (key: Key) => Effect.Effect<void, E>
11:   /** Registers one coalesced follow-up after newly recorded work. */
12:   readonly wake: (key: Key) => Effect.Effect<void>
13:   /** Stops active execution, runs cleanup, then starts work that arrived while stopping. */
14:   readonly interrupt: (key: Key, cleanup?: Effect.Effect<void>) => Effect.Effect<void>
15: }
16: 
17: type ...
gateway · 2026-09-16 14:46:57
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/runner/index.ts</path>
<type>file</type>
<content>
1: export * as SessionRunner from "./index"
2: 
3: import type { LLMError } from "@opencode-ai/llm"
4: import { Context, Effect } from "effect"
5: import { SessionSchema } from "../schema"
6: import type { SessionMessage } from "../message"
7: import type { ContextSnapshotDecodeError, MessageDecodeError } from "../error"
8: import { SessionRunnerModel } from "./model"
9: import type { SystemContext } from "../../system-context/index"
10: import type { ToolOutputStore } from "../../tool-output-store"
11: 
12: export type RunError =
13:   | LLMError
14:   | SessionRunnerModel.Error
15:   | MessageDecodeError
16:   | ContextSnapshotDecodeError
17:   | SystemContext.InitializationBlocked
18:   | ToolOutputStore.Error
19: 
20: /** Runs one local continuation from already-recorded Session history. ...
gateway · 2026-09-16 14:47:07
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/runner/llm.ts</path>
<type>file</type>
<content>
1: import {
2:   LLM,
3:   LLMClient,
4:   LLMError,
5:   LLMEvent,
6:   Message,
7:   SystemPart,
8:   isContextOverflowFailure,
9:   type ProviderErrorEvent,
10: } from "@opencode-ai/llm"
11: import { Cause, DateTime, Effect, Exit, Fiber, Layer, Option, Semaphore, Stream } from "effect"
12: import { and, eq } from "drizzle-orm"
13: import { AgentV2 } from "../../agent"
14: import { Config } from "../../config"
15: import { Database } from "../../database/database"
16: import { EventV2 } from "../../event"
17: import { Location } from "../../location"
18: import { ModelV2 } from "../../model"
19: import { PermissionV2 } from "../../permission"
20: import { ProviderV2 } from "../../provider"
21: import { QuestionV2 } from "../../question"
22: import { SystemContext } from "../../system-context/index"
23: import { SystemContextRegistry } from ...
gateway · 2026-09-16 14:47:18
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/runner/publish-llm-event.ts</path>
<type>file</type>
<content>
1: import { ToolOutput, type LLMEvent, type ProviderMetadata, type ToolResultValue, type Usage } from "@opencode-ai/llm"
2: import { DateTime, Effect } from "effect"
3: import { EventV2 } from "../../event"
4: import { ModelV2 } from "../../model"
5: import { SessionEvent } from "../event"
6: import { SessionMessage } from "../message"
7: import { SessionSchema } from "../schema"
8: 
9: type Input = {
10:   readonly sessionID: SessionSchema.ID
11:   readonly agent: string
12:   readonly model: ModelV2.Ref
13:   readonly snapshot?: string
14:   readonly startCommit: (assistantMessageID: SessionMessage.ID) => Effect.Effect<void>
15:   readonly eventCommit: () => Effect.Effect<void>
16: }
17: 
18: const safe = (value: number | undefined) => Math.max(0, Number.isFinite(value) ? (value ?? ...
gateway · 2026-09-16 14:47:23
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/projector.ts</path>
<type>file</type>
<content>
1: export * as SessionProjector from "./projector"
2: 
3: import { and, desc, eq, gt, or, sql } from "drizzle-orm"
4: import { DateTime, Effect, Layer, Schema } from "effect"
5: import { Database } from "../database/database"
6: import { EventV2 } from "../event"
7: import { makeGlobalNode } from "../effect/app-node"
8: import { SessionEvent } from "./event"
9: import { SessionV1 } from "../v1/session"
10: import { WorkspaceTable } from "../control-plane/workspace.sql"
11: import { SessionMessage } from "./message"
12: import { SessionMessageUpdater } from "./message-updater"
13: import { SessionInput } from "./input"
14: import { Prompt } from "./prompt"
15: import { continuation } from "./recovery-id"
16: import { WorkspaceV2 } from "../workspace"
17: import {
18:   MessageTable,
19:   PartTable,
20:   SessionInputTable,
21:   SessionMessageTable,
22:   ...
gateway · 2026-09-16 14:47:30
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/message-updater.ts</path>
<type>file</type>
<content>
1: import { castDraft, produce, type WritableDraft } from "immer"
2: import { Effect } from "effect"
3: import { SessionEvent } from "./event"
4: import { SessionMessage } from "./message"
5: import { message } from "./recovery-id"
6: 
7: export type MemoryState = {
8:   messages: SessionMessage.Message[]
9: }
10: 
11: export interface Adapter {
12:   readonly getCurrentAssistant: () => Effect.Effect<SessionMessage.Assistant | undefined>
13:   readonly getAssistant: (messageID: SessionMessage.ID) => Effect.Effect<SessionMessage.Assistant | undefined>
14:   readonly getCurrentShell: (callID: string) => Effect.Effect<SessionMessage.Shell | undefined>
15:   readonly updateAssistant: (assistant: SessionMessage.Assistant) => Effect.Effect<void>
16:   readonly updateShell: (shell: SessionMessage.Shell) => Effect.Effect<void>
17:   readonly appendMessage: (message: ...
gateway · 2026-09-16 14:47:38
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/context-epoch.ts</path>
<type>file</type>
<content>
1: export * as SessionContextEpoch from "./context-epoch"
2: 
3: import { eq } from "drizzle-orm"
4: import { DateTime, Effect, Schema } from "effect"
5: import type { Database } from "../database/database"
6: import { EventV2 } from "../event"
7: import { SystemContext } from "../system-context/index"
8: import { ContextSnapshotDecodeError } from "./error"
9: import { SessionEvent } from "./event"
10: import { SessionHistory } from "./history"
11: import { SessionInput } from "./input"
12: import { SessionMessage } from "./message"
13: import { SessionSchema } from "./schema"
14: import { SessionContextEpochTable } from "./sql"
15: import { SessionExecutionClaim } from "./execution/claim"
16: 
17: type DatabaseService = Database.Interface["db"]
18: 
19: interface Prepared {
20:   readonly baseline: string
21:   readonly baselineSeq: number
22: }
23: 
24: export ...
gateway · 2026-09-16 14:47:46
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/compaction.ts</path>
<type>file</type>
<content>
1: export * as SessionCompaction from "./compaction"
2: 
3: import { LLM, LLMError, LLMEvent, Message, type LLMRequest, type Model } from "@opencode-ai/llm"
4: import { DateTime, Effect, Stream } from "effect"
5: import type { Config } from "../config"
6: import type { EventV2 } from "../event"
7: import { SessionEvent } from "./event"
8: import { SessionMessage } from "./message"
9: import { SessionSchema } from "./schema"
10: import { Token } from "../util/token"
11: 
12: const DEFAULT_BUFFER = 20_000
13: const DEFAULT_KEEP_TOKENS = 8_000
14: const TOOL_OUTPUT_MAX_CHARS = 2_000
15: const SUMMARY_OUTPUT_TOKENS = 4_096
16: const SUMMARY_TEMPLATE = `Output exactly the Markdown structure shown inside <template> and keep the section order unchanged. Do not include the <template> tags in your response. ...
gateway · 2026-09-16 14:48:03
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/sql.ts</path>
<type>file</type>
<content>
1: import { sql } from "drizzle-orm"
2: import { check, sqliteTable, text, integer, index, primaryKey, real, uniqueIndex } from "drizzle-orm/sqlite-core"
3: import * as DatabasePath from "../database/path"
4: import { ProjectTable } from "../project/sql"
5: import type { SessionMessage } from "./message"
6: import type { Prompt } from "./prompt"
7: import type { SessionInput } from "./input"
8: import type { Snapshot } from "../snapshot"
9: import { PermissionV1 } from "../v1/permission"
10: import { ProjectV2 } from "../project"
11: import type { SessionSchema } from "./schema"
12: import type { MessageID, PartID, SessionV1 } from "../v1/session"
13: import { WorkspaceV2 } from "../workspace"
14: import { Timestamps } from "../database/schema.sql"
15: import type { SystemContext } from "../system-context/index"
16: import { AgentV2 } from "../agent"
17: import type { ...
gateway · 2026-09-16 14:48:08
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/database/migration/20260914170650_session-recovery.ts</path>
<type>file</type>
<content>
1: import { Effect } from "effect"
2: import type { DatabaseMigration } from "../migration"
3: 
4: export default {
5:   id: "20260914170650_session-recovery",
6:   up(tx) {
7:     return Effect.gen(function* () {
8:       yield* tx.run(`ALTER TABLE \`session_input\` ADD \`wake_pending\` integer DEFAULT false NOT NULL;`)
9:       yield* tx.run(
10:         `ALTER TABLE \`session\` ADD \`wake_attempts\` integer DEFAULT 0 NOT NULL CHECK(\`wake_attempts\` >= 0 AND \`wake_attempts\` <= 9007199254740991);`,
11:       )
12:       yield* tx.run(`
13:         CREATE TABLE \`session_execution\` (
14:           \`id\` text NOT NULL,
15:           \`session_id\` text NOT NULL,
16:           \`owner_id\` text NOT NULL,
17:           \`assistant_message_id\` text,
18:           \`phase\` text NOT NULL,
19:           \`time_created\` integer NOT ...
gateway · 2026-09-16 14:48:19
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session.ts</path>
<type>file</type>
<content>
1: export * as SessionV2 from "./session"
2: export * from "./session/schema"
3: 
4: import { DateTime, Effect, Layer, Schema, Context, Stream } from "effect"
5: import { ListAnchor } from "@opencode-ai/schema/session"
6: import { and, asc, desc, eq, gt, like, lt, or, type SQL } from "drizzle-orm"
7: import { ProjectV2 } from "./project"
8: import { WorkspaceV2 } from "./workspace"
9: import { ModelV2 } from "./model"
10: import { Location } from "./location"
11: import { SessionMessage } from "./session/message"
12: import { Prompt } from "./session/prompt"
13: import { PromptInput } from "@opencode-ai/schema/prompt-input"
14: import { EventV2 } from "./event"
15: import { Database } from "./database/database"
16: import { SessionProjector } from "./session/projector"
17: import { SessionMessageTable, SessionTable } from "./session/sql"
18: import { SessionSchema } from ...
gateway · 2026-09-16 14:48:27
result
<path>/tmp/opencode/session-recovery-v7-check/packages/server/src/routes.ts</path>
<type>file</type>
<content>
1: import { Database } from "@opencode-ai/core/database/database"
2: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
3: import { httpClient } from "@opencode-ai/core/effect/app-node-platform"
4: import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
5: import { EventV2 } from "@opencode-ai/core/event"
6: import { Credential } from "@opencode-ai/core/credential"
7: import { PermissionSaved } from "@opencode-ai/core/permission/saved"
8: import { PtyTicket } from "@opencode-ai/core/pty/ticket"
9: import { SessionV2 } from "@opencode-ai/core/session"
10: import { SessionExecution } from "@opencode-ai/core/session/execution"
11: import { LocationServiceMap } from "@opencode-ai/core/location-service-map"
12: import { SessionExecutionLocal } from "@opencode-ai/core/session/execution/local"
13: import { SessionRecovery } from ...
gateway · 2026-09-16 14:48:31
result
<path>/tmp/opencode/session-recovery-v7-check/packages/opencode/src/server/routes/instance/httpapi/server.ts</path>
<type>file</type>
<content>
1: import { Config as EffectConfig, Context, Effect, Layer } from "effect"
2: import { HttpApiBuilder, OpenApi } from "effect/unstable/httpapi"
3: import { HttpClient, HttpMiddleware, HttpRouter, HttpServer, HttpServerResponse } from "effect/unstable/http"
4: import * as Socket from "effect/unstable/socket/Socket"
5: import { FSUtil } from "@opencode-ai/core/fs-util"
6: import * as Observability from "@opencode-ai/core/observability"
7: import { Account } from "@/account/account"
8: import { Agent } from "@/agent/agent"
9: import { Auth } from "@/auth"
10: import { BackgroundJob } from "@/background/job"
11: import { Command } from "@/command"
12: import { Config } from "@/config/config"
13: import { Workspace } from "@/control-plane/workspace"
14: import { Env } from "@/env"
15: import { EventV2Bridge } from "@/event-v2-bridge"
16: import { ...
gateway · 2026-09-16 14:48:36
result
<path>/tmp/opencode/session-recovery-v7-check/packages/opencode/src/server/routes/instance/httpapi/server.ts</path>
<type>file</type>
<content>
261:   Installation.node,
262:   ShareNext.node,
263:   SessionShare.node,
264:   InstanceStore.node,
265:   httpClient,
266:   EventV2.node,
267:   ProjectV2.node,
268:   ProjectCopy.node,
269:   PtyTicket.node,
270: ])
271: 
272: export function createRoutes(
273:   corsOptions?: CorsOptions,
274: ): Layer.Layer<never, EffectConfig.ConfigError, RouteRequirements> {
275:   const locationServiceMapV2 = buildLocationServiceMap()
276: 
277:   return Layer.mergeAll(
278:     rootApiRoutes,
279:     eventApiRoutes,
280:     ptyConnectApiRoutes,
281:     instanceRoutes,
282:     serverRoutes,
283:     docRoute,
284:     uiRoute,
285:   ).pipe(
286:     Layer.provide([
287:       errorLayer,
288:       compressionLayer,
289:       corsVaryFix,
290:       fenceLayer,
291:       cors(corsOptions),
292:       AppNodeBuilderV1.build(MoveSession.node, ...
gateway · 2026-09-16 14:48:41
result
<path>/tmp/opencode/session-recovery-v7-check/packages/schema/src/session-event.ts</path>
<type>file</type>
<content>
1: export * as SessionEvent from "./session-event"
2: 
3: import { Schema } from "effect"
4: import { optional } from "./schema"
5: import { Event } from "./event"
6: import { ProviderMetadata, ToolContent } from "./llm"
7: import { Delivery } from "./session-delivery"
8: import { Model } from "./model"
9: import { DateTimeUtcFromMillis, NonNegativeInt, RelativePath } from "./schema"
10: import { FileAttachment, Prompt } from "./prompt"
11: import { SessionID } from "./session-id"
12: import { Location } from "./location"
13: import { SessionMessage } from "./session-message"
14: import { Revert } from "./revert"
15: 
16: export { FileAttachment }
17: 
18: export const Source = Schema.Struct({
19:   start: NonNegativeInt,
20:   end: NonNegativeInt,
21:   text: Schema.String,
22: }).annotate({
23:   identifier: "session.next.event.source",
24: })
25: export interface ...
gateway · 2026-09-16 14:48:48
result
Found 100 matches (more matches available)
/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner.test.ts:
  Line 607:   it.effect("redrives only the synthetic recovery continuation", () =>

  Line 676:   it.effect("clears durable execution intent when ordinary input is promoted", () =>

  Line 703:   it.effect("redrives an ordinary prompt after its advisory wake is lost", () =>

  Line 740:   it.effect("never dispatches a provider after ownership changes", () =>

  Line 766:   it.effect("never publishes streamed output after ownership changes", () =>

  Line 793:   it.effect("never starts a local tool after ownership changes", () =>

  Line 833:   it.effect("never fails interrupted tools after ownership changes", () =>

  Line 890:   it.effect("advertises and executes a globally attached application tool", () =>

  Line 946:   it.effect("starts a real runner turn after default prompt recording", () =>

  Line 965:   it.effect("streams one request with registry ...
gateway · 2026-09-16 14:48:53
result
Found 100 matches (more matches available)
/tmp/opencode/session-recovery-v7-check/packages/core/test/event.test.ts:
  Line 87:   it.effect("publishes events with the current location", () =>

  Line 116:   it.effect("publishes definition version", () =>

  Line 126:   it.effect("selects the latest durable definition independent of declaration order", () =>

  Line 144:   it.effect("publishes to typed and wildcard subscriptions", () =>

  Line 157:   it.effect("runs projectors inline", () =>

  Line 175:   it.effect("commits local operational state inside a new durable event transaction", () =>

  Line 192:   it.effect("rolls back the durable event and projector when the local commit fails", () =>

  Line 216:   it.effect("rejects local commit hooks on live-only events", () =>

  Line 225:   it.effect("runs projectors before publishing to streams", () =>

  Line 248:   it.effect("runs listeners inline after projectors", () =>

  Line 271:   it.effect("isolates observer defects after ...
gateway · 2026-09-16 14:49:00
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-execution-local.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect } from "bun:test"
2: import { Deferred, Effect, Exit, Fiber, Scope } from "effect"
3: import { TestClock } from "effect/testing"
4: import { eq } from "drizzle-orm"
5: import { Database } from "@opencode-ai/core/database/database"
6: import { Project } from "@opencode-ai/core/project"
7: import { ProjectTable } from "@opencode-ai/core/project/sql"
8: import { AbsolutePath } from "@opencode-ai/core/schema"
9: import { SessionExecutionLocal } from "@opencode-ai/core/session/execution/local"
10: import { SessionSchema } from "@opencode-ai/core/session/schema"
11: import { SessionExecutionTable, SessionTable } from "@opencode-ai/core/session/sql"
12: import { testEffect } from "./lib/effect"
13: 
14: const sessionID = SessionSchema.ID.make("ses_execution_local")
15: const it = testEffect(Database.layerFromPath(":memory:"))
16: ...
gateway · 2026-09-16 14:49:20
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/session/recovery-id.ts</path>
<type>file</type>
<content>
1: import { SessionMessage } from "./message"
2: 
3: export const message = (executionID: string, assistantMessageID?: SessionMessage.ID) =>
4:   assistantMessageID ?? SessionMessage.ID.make(`msg_recovery_${executionID}`)
5: 
6: export const continuation = (executionID: string) => SessionMessage.ID.make(`msg_recovery_continue_${executionID}`)

(End of file - total 6 lines)
</content>
gateway · 2026-09-16 14:49:30
result
Found 24 matches
/tmp/opencode/session-recovery-v7-check/packages/core/test/session-projector.test.ts:
  Line 68:   it.effect("atomically reconciles one abandoned execution into one continuation", () =>

  Line 222:   it.effect("records a recovery continuation without forging an assistant identity", () =>

  Line 259:   it.effect("recovers each abandoned execution once across repeated startup scans", () =>

  Line 305:   it.effect("never recovers a live execution lease", () =>

  Line 343:   it.effect("never recovers an execution superseded by a newer assistant", () =>

  Line 390:   it.effect("redrives a durable recovery wake after admission", () =>

  Line 441:   it.effect("quarantines a malformed recovery row without blocking a valid wake", () =>

  Line 495:   it.effect("quarantines a full batch of poison recovery rows before redriving valid work", () =>

  Line 560:   it.effect("fairly redrives recovery and ordinary work beyond a full bounded batch", () =>

  Line 696:   ...
gateway · 2026-09-16 14:49:44
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-projector.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect } from "bun:test"
2: import { DateTime, Deferred, Effect, Exit, Fiber, Schema } from "effect"
3: import { TestClock } from "effect/testing"
4: import { asc, eq, sql } from "drizzle-orm"
5: import { Database } from "@opencode-ai/core/database/database"
6: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
7: import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
8: import { EventV2 } from "@opencode-ai/core/event"
9: import { EventTable } from "@opencode-ai/core/event/sql"
10: import { ModelV2 } from "@opencode-ai/core/model"
11: import { Project } from "@opencode-ai/core/project"
12: import { ProjectTable } from "@opencode-ai/core/project/sql"
13: import { ProviderV2 } from "@opencode-ai/core/provider"
14: import { AbsolutePath } from "@opencode-ai/core/schema"
15: import { SessionV2 } from ...
gateway · 2026-09-16 14:49:51
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-projector.test.ts</path>
<type>file</type>
<content>
851: 
852:       yield* SessionRecovery.recover().pipe(
853:         Effect.provideService(
854:           SessionExecution.Service,
855:           SessionExecution.Service.of({
856:             ...recoveryExecution,
857:             wake: (id) => Effect.sync(() => wakes.push(id)).pipe(Effect.asVoid),
858:           }),
859:         ),
860:       )
861: 
862:       expect(wakes).toEqual([])
863:       expect(yield* db.select().from(SessionRecoveryTable).get()).toMatchObject({
864:         wake_pending: false,
865:         wake_attempts: 0,
866:       })
867:       expect(
868:         yield* db.select().from(SessionInputTable).where(eq(SessionInputTable.session_id, ordinarySessionID)).get(),
869:       ).toMatchObject({ wake_pending: false })
870:       expect(
871:         yield* db
872:           .select({ wakeAttempts: SessionTable.wake_attempts })
873:      ...
gateway · 2026-09-16 14:49:59
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-projector.test.ts</path>
<type>file</type>
<content>
1651:     Effect.gen(function* () {
1652:       const { db } = yield* Database.Service
1653:       const events = yield* EventV2.Service
1654:       const contextKey = SystemContext.Key.make("test/advance-fence")
1655:       const context = (value: string) =>
1656:         SystemContext.make({
1657:           key: contextKey,
1658:           codec: Schema.toCodecJson(Schema.String),
1659:           load: Effect.succeed(value),
1660:           baseline: String,
1661:           update: (_previous, current) => current,
1662:         })
1663:       yield* db
1664:         .insert(ProjectTable)
1665:         .values({ id: Project.ID.global, worktree: AbsolutePath.make("/project"), sandboxes: [] })
1666:         .run()
1667:       yield* db
1668:         .insert(SessionTable)
1669:         .values({
1670:           id: sessionID,
1671:           project_id: ...
gateway · 2026-09-16 14:50:43
result
Found 16 matches
/tmp/opencode/session-recovery-v7-check/packages/core/test/session-prompt.test.ts:
  Line 140:   it.effect("exposes the execution registry", () =>

  Line 147:   it.effect("delegates execution continuation through SessionExecution", () =>

  Line 181:   it.effect("durably admits one user message before transcript promotion", () =>

  Line 254:   it.effect("resumes through a recorded message without appending another prompt", () =>

  Line 310:   it.effect("wakes execution when an exact prompt retry recovers a committed message", () =>

  Line 330:   it.effect("never wakes execution when retrying an already promoted prompt", () =>

  Line 374:   it.effect("durably records execution intent before advisory wake", () =>

  Line 408:   it.effect("replays historical prompt admission without execution intent as admit-only", () =>

  Line 440:   it.effect("turns an admit-only exact retry into durable execution intent", () =>

  Line 514:   it.effect("never arms durable wake ...
gateway · 2026-09-16 14:50:54
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-prompt.test.ts</path>
<type>file</type>
<content>
160:     Effect.gen(function* () {
161:       yield* setup
162:       const session = yield* SessionV2.Service
163:       interruptCalls.length = 0
164: 
165:       yield* session.interrupt(sessionID)
166:       expect(interruptCalls).toEqual([sessionID])
167:       expect(yield* session.messages({ sessionID })).toEqual([])
168:     }),
169:   )
170: 
171:   it.effect("delegates interruption without requiring a recorded Session", () =>
172:     Effect.gen(function* () {
173:       const session = yield* SessionV2.Service
174:       interruptCalls.length = 0
175: 
176:       yield* session.interrupt(SessionV2.ID.make("ses_missing"))
177:       expect(interruptCalls).toEqual([SessionV2.ID.make("ses_missing")])
178:     }),
179:   )
180: 
181:   it.effect("durably admits one user message before transcript promotion", () =>
182:     Effect.gen(function* () {
183:      ...
gateway · 2026-09-16 14:51:05
result
Found 54 matches
/tmp/opencode/session-recovery-v7-check/packages/core/schema.json:
  Line 66:       "name": "session_execution",

  Line 78:       "name": "session_recovery",

  Line 941:       "table": "session_execution"

  Line 951:       "table": "session_execution"

  Line 961:       "table": "session_execution"

  Line 971:       "table": "session_execution"

  Line 981:       "table": "session_execution"

  Line 991:       "table": "session_execution"

  Line 1001:       "table": "session_execution"

  Line 1011:       "table": "session_execution"

  Line 1079:       "name": "wake_pending",

  Line 1171:       "table": "session_recovery"

  Line 1181:       "table": "session_recovery"

  Line 1191:       "table": "session_recovery"

  Line 1201:       "table": "session_recovery"

  Line 1211:       "table": "session_recovery"

  Line 1219:       "name": "wake_pending",

  Line 1221:       "table": "session_recovery"

  Line 1229:       "name": "wake_attempts",

  Line 1231:    ...
gateway · 2026-09-16 14:51:11
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/schema.json</path>
<type>file</type>
<content>
50:       "name": "project",
51:       "entityType": "tables"
52:     },
53:     {
54:       "name": "message",
55:       "entityType": "tables"
56:     },
57:     {
58:       "name": "part",
59:       "entityType": "tables"
60:     },
61:     {
62:       "name": "session_context_epoch",
63:       "entityType": "tables"
64:     },
65:     {
66:       "name": "session_execution",
67:       "entityType": "tables"
68:     },
69:     {
70:       "name": "session_input",
71:       "entityType": "tables"
72:     },
73:     {
74:       "name": "session_message",
75:       "entityType": "tables"
76:     },
77:     {
78:       "name": "session_recovery",
79:       "entityType": "tables"
80:     },
81:     {
82:       "name": "session",
83:       "entityType": "tables"
84:     },
85:     {
86:       "name": "todo",
87:       "entityType": "tables"
88:     },
89:     {
90:       "name": ...
gateway · 2026-09-16 14:51:26
result
Found 14 matches
/tmp/opencode/session-recovery-v7-check/packages/core/src/database/schema.gen.ts:
  Line 158:         CREATE TABLE \`session_execution\` (

  Line 167:           CONSTRAINT \`session_execution_pk\` PRIMARY KEY(\`id\`),

  Line 168:           CONSTRAINT \`fk_session_execution_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE,

  Line 169:           CONSTRAINT "session_execution_phase_check" CHECK("phase" IN ('ready', 'safe', 'unknown', 'continue'))

  Line 198:         CREATE TABLE \`session_recovery\` (

  Line 208:           CONSTRAINT \`session_recovery_pk\` PRIMARY KEY(\`execution_id\`),

  Line 209:           CONSTRAINT \`fk_session_recovery_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE,

  Line 210:           CONSTRAINT \`fk_session_recovery_assistant_message_id_session_message_id_fk\` FOREIGN KEY (\`assistant_message_id\`) REFERENCES ...
gateway · 2026-09-16 14:51:39
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/database/schema.gen.ts</path>
<type>file</type>
<content>
130:           \`session_id\` text NOT NULL,
131:           \`time_created\` integer NOT NULL,
132:           \`time_updated\` integer NOT NULL,
133:           \`data\` text NOT NULL,
134:           CONSTRAINT \`fk_message_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE
135:         );
136:       `)
137:       yield* tx.run(`
138:         CREATE TABLE \`part\` (
139:           \`id\` text PRIMARY KEY,
140:           \`message_id\` text NOT NULL,
141:           \`session_id\` text NOT NULL,
142:           \`time_created\` integer NOT NULL,
143:           \`time_updated\` integer NOT NULL,
144:           \`data\` text NOT NULL,
145:           CONSTRAINT \`fk_part_message_id_message_id_fk\` FOREIGN KEY (\`message_id\`) REFERENCES \`message\`(\`id\`) ON DELETE CASCADE
146:         );
147:       `)
148:       ...
gateway · 2026-09-16 14:51:46
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/src/database/migration.gen.ts</path>
<type>file</type>
<content>
1: import type { DatabaseMigration } from "./migration"
2: 
3: export const migrations = (
4:   await Promise.all([
5:     import("./migration/20260127222353_familiar_lady_ursula"),
6:     import("./migration/20260211171708_add_project_commands"),
7:     import("./migration/20260213144116_wakeful_the_professor"),
8:     import("./migration/20260225215848_workspace"),
9:     import("./migration/20260227213759_add_session_workspace_id"),
10:     import("./migration/20260228203230_blue_harpoon"),
11:     import("./migration/20260303231226_add_workspace_fields"),
12:     import("./migration/20260309230000_move_org_to_state"),
13:     import("./migration/20260312043431_session_message_cursor"),
14:     import("./migration/20260323234822_events"),
15:     import("./migration/20260410174513_workspace-name"),
16:     ...
gateway · 2026-09-16 14:52:02
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/database-migration.test.ts</path>
<type>file</type>
<content>
100:         }),
101:       ),
102:     ).rejects.toThrow("does not match any known migration")
103:   })
104: 
105:   test("serializes concurrent embedded initialization for one database path", async () => {
106:     await using tmp = await tmpdir()
107:     const filename = path.join(tmp.path, "embedded.sqlite")
108:     const layers = [Database.layerFromPath(filename), Database.layerFromPath(filename)]
109: 
110:     await Effect.runPromise(
111:       Effect.all(
112:         layers.map((layer) => Effect.scoped(Layer.build(layer))),
113:         { concurrency: "unbounded" },
114:       ),
115:     )
116:   })
117:   if (process.platform === "linux") {
118:     test("declared schema has no ungenerated migrations", async () => {
119:       const result = await $`bun ${fileURLToPath(new URL("../script/migration.ts", import.meta.url))} --check`
120:         ...
gateway · 2026-09-16 14:52:16
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
580:       yield* db
581:         .select({ id: SessionExecutionTable.id, phase: SessionExecutionTable.phase })
582:         .from(SessionExecutionTable)
583:         .where(eq(SessionExecutionTable.session_id, sessionID))
584:         .get(),
585:     ).toEqual({ id: executionID, phase: "unknown" })
586:     expect(
587:       (yield* db.select({ type: EventTable.type }).from(EventTable).all()).some((event) =>
588:         event.type.startsWith(SessionEvent.Step.Interrupted.type),
589:       ),
590:     ).toBe(true)
591:     expect(yield* session.context(sessionID)).toMatchObject([
592:       { type: "user", text: prompt },
593:       {
594:         type: "assistant",
595:         finish: "error",
596:         error: { type: "unknown", message: "Provider Step outcome unknown after interruption" },
597:         content: [
598:           kind === "tool input"
599:  ...
gateway · 2026-09-16 14:52:28
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
1450: 
1451:       const context = yield* (yield* SessionStore.Service).context(sessionID)
1452:       expect(context.map((message) => message.type)).toEqual(["compaction", "assistant"])
1453:       expect(context[0]).toMatchObject({
1454:         type: "compaction",
1455:         summary: "## Objective\n- Preserve the task",
1456:       })
1457: 
1458:       requests.length = 0
1459:       executions.length = 0
1460:       responses = [
1461:         fragmentFixture("text", "text-summary-2", ["## Objective\n- Preserve the updated task"]).completeEvents,
1462:         fragmentFixture("text", "text-final-2", ["Continued again"]).completeEvents,
1463:       ]
1464:       yield* session.prompt({
1465:         sessionID,
1466:         prompt: Prompt.make({ text: "Newest exact request ".repeat(180) }),
1467:         resume: false,
1468:       })
1469:       yield* ...
gateway · 2026-09-16 14:52:45
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
3360:       const registry = yield* ToolRegistry.Service
3361:       yield* registry.register({
3362:         blocked: Tool.make({
3363:           description: "Fail because policy blocked execution",
3364:           input: Schema.Struct({}),
3365:           output: Schema.Struct({}),
3366:           execute: () =>
3367:             Effect.fail(new PermissionV2.BlockedError({ rules: [] })).pipe(
3368:               Effect.mapError(() => new Tool.Failure({ message: "Permission blocked" })),
3369:             ),
3370:         }),
3371:       })
3372:       yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Call blocked" }), resume: false })
3373: 
3374:       requests.length = 0
3375:       responses = [
3376:         [
3377:           LLMEvent.stepStart({ index: 0 }),
3378:           LLMEvent.toolCall({ id: "call-blocked", name: "blocked", input: {} ...
gateway · 2026-09-16 14:52:52
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner-recorded.test.ts</path>
<type>file</type>
<content>
1: import { HttpRecorder } from "@opencode-ai/http-recorder"
2: import { HttpRecorderInternal } from "@opencode-ai/http-recorder/internal"
3: import * as OpenAIChat from "@opencode-ai/llm/protocols/openai-chat"
4: import { Auth, LLMClient, RequestExecutor } from "@opencode-ai/llm/route"
5: import { Database } from "@opencode-ai/core/database/database"
6: import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
7: import { LayerNodePlatform } from "@opencode-ai/core/effect/app-node-platform"
8: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
9: import { EventV2 } from "@opencode-ai/core/event"
10: import { EventTable } from "@opencode-ai/core/event/sql"
11: import { PermissionV2 } from "@opencode-ai/core/permission"
12: import { AgentV2 } from "@opencode-ai/core/agent"
13: import { Config } from ...
gateway · 2026-09-16 14:53:06
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner-tool-events.test.ts</path>
<type>file</type>
<content>
1: import { expect, test } from "bun:test"
2: import { Effect, Schema, Stream } from "effect"
3: import { LLMEvent } from "@opencode-ai/llm"
4: import { EventV2 } from "@opencode-ai/core/event"
5: import { SessionEvent } from "@opencode-ai/core/session/event"
6: import { SessionMessage } from "@opencode-ai/core/session/message"
7: import { SessionV2 } from "@opencode-ai/core/session"
8: import { ModelV2 } from "@opencode-ai/core/model"
9: import { ProviderV2 } from "@opencode-ai/core/provider"
10: import { createLLMEventPublisher } from "@opencode-ai/core/session/runner/publish-llm-event"
11: 
12: const sessionID = SessionV2.ID.make("ses_tool_event_test")
13: const base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB"
14: 
15: const capture = () => {
16:   const published: Array<{ readonly type: string; readonly data: unknown }> = []
17:   const events = ...
gateway · 2026-09-16 14:53:13
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-run-coordinator.test.ts</path>
<type>file</type>
<content>
190:               ),
191:             ),
192:         })
193: 
194:         const resumed = yield* coordinator.run("session").pipe(Effect.forkChild)
195:         yield* Effect.yieldNow
196:         yield* coordinator.wake("session")
197:         yield* Deferred.succeed(firstGate, undefined)
198:         yield* Deferred.await(secondStarted)
199:         yield* coordinator.wake("session")
200:         yield* Deferred.succeed(secondGate, undefined)
201:         yield* Deferred.await(thirdStarted)
202:         yield* Fiber.join(resumed)
203: 
204:         expect(runs).toBe(3)
205:       }),
206:     ),
207:   )
208: 
209:   it.effect("does nothing when interrupted while idle", () =>
210:     Effect.scoped(
211:       Effect.gen(function* () {
212:         const coordinator = yield* SessionRunCoordinator.make({ drain: () => Effect.void })
213:         yield* ...
gateway · 2026-09-16 14:53:24
result
Found 16 matches
/tmp/opencode/session-recovery-v7-check/packages/sdk/js/src/v2/gen/types.gen.ts:
  Line 874:           requestExecution?: boolean

  Line 879:         type: "session.next.prompt.execution_requested"

  Line 983:         type: "session.next.step.recovered"

  Line 987:           executionID: string

  Line 3430:       requestExecution?: boolean

  Line 3439:     type: "session.next.prompt.execution_requested.1"

  Line 3606:     type: "session.next.step.recovered.1"

  Line 3613:       executionID: string

  Line 4362:     requestExecution?: boolean

  Line 4371:   type: "session.next.prompt.execution_requested"

  Line 4565:   type: "session.next.step.recovered"

  Line 4575:     executionID: string

  Line 6464:     requestExecution?: boolean

  Line 6470:   type: "session.next.prompt.execution_requested"

  Line 6583:   type: "session.next.step.recovered"

  Line 6587:     executionID: string
gateway · 2026-09-16 14:53:32
result
<path>/tmp/opencode/session-recovery-v7-check/packages/sdk/js/src/v2/gen/types.gen.ts</path>
<type>file</type>
<content>
840:           messageID: string
841:           model: ModelRef
842:         }
843:       }
844:     | {
845:         id: string
846:         type: "session.next.moved"
847:         properties: {
848:           timestamp: number
849:           sessionID: string
850:           location: LocationRef
851:           subdirectory?: string
852:         }
853:       }
854:     | {
855:         id: string
856:         type: "session.next.prompted"
857:         properties: {
858:           timestamp: number
859:           sessionID: string
860:           messageID: string
861:           prompt: Prompt
862:           delivery: "steer" | "queue"
863:         }
864:       }
865:     | {
866:         id: string
867:         type: "session.next.prompt.admitted"
868:         properties: {
869:           timestamp: number
870:           sessionID: string
871:           messageID: ...
gateway · 2026-09-16 14:53:39
result
Found 20 matches
/tmp/opencode/session-recovery-v7-check/packages/sdk/openapi.json:
  Line 17899:                       "requestExecution": {

  Line 17919:                     "enum": ["session.next.prompt.execution_requested"]

  Line 18289:                     "enum": ["session.next.step.recovered"]

  Line 18301:                       "executionID": {

  Line 18313:                     "required": ["timestamp", "sessionID", "executionID", "phase"],

  Line 25709:                   "requestExecution": {

  Line 25740:                 "enum": ["session.next.prompt.execution_requested.1"]

  Line 26299:                 "enum": ["session.next.step.recovered.1"]

  Line 26321:                   "executionID": {

  Line 26333:                 "required": ["timestamp", "sessionID", "executionID", "phase"],

  Line 28599:               "requestExecution": {

  Line 28622:             "enum": ["session.next.prompt.execution_requested"]

  Line 29190:             "enum": ...
gateway · 2026-09-16 14:53:55
result
<path>/tmp/opencode/session-recovery-v7-check/packages/sdk/openapi.json</path>
<type>file</type>
<content>
17870:                   "id": {
17871:                     "type": "string",
17872:                     "pattern": "^evt_"
17873:                   },
17874:                   "type": {
17875:                     "type": "string",
17876:                     "enum": ["session.next.prompt.admitted"]
17877:                   },
17878:                   "properties": {
17879:                     "type": "object",
17880:                     "properties": {
17881:                       "timestamp": {
17882:                         "type": "number"
17883:                       },
17884:                       "sessionID": {
17885:                         "type": "string",
17886:                         "pattern": "^ses"
17887:                       },
17888:                       "messageID": {
17889:                         "type": "string",
17890:                         "pattern": ...
gateway · 2026-09-16 14:54:08
result
<path>/tmp/opencode/session-recovery-v7-check/packages/sdk/openapi.json</path>
<type>file</type>
<content>
18275:                   }
18276:                 },
18277:                 "required": ["id", "type", "properties"],
18278:                 "additionalProperties": false
18279:               },
18280:               {
18281:                 "type": "object",
18282:                 "properties": {
18283:                   "id": {
18284:                     "type": "string",
18285:                     "pattern": "^evt_"
18286:                   },
18287:                   "type": {
18288:                     "type": "string",
18289:                     "enum": ["session.next.step.recovered"]
18290:                   },
18291:                   "properties": {
18292:                     "type": "object",
18293:                     "properties": {
18294:                       "timestamp": {
18295:                         "type": "number"
18296:                       },
18297:         ...
gateway · 2026-09-16 14:54:17
result
<path>/tmp/opencode/session-recovery-v7-check/packages/schema/test/event-manifest.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect, test } from "bun:test"
2: import { FileSystem, Integration, Permission, Project, Reference, Session, Workspace } from "../src"
3: import { EventManifest } from "../src/event-manifest"
4: import { IdeEvent } from "../src/ide-event"
5: import { SessionEvent } from "../src/session-event"
6: import { SessionTodo } from "../src/session-todo"
7: import { SessionV1 } from "../src/session-v1"
8: import { WorkspaceEvent } from "../src/workspace-event"
9: 
10: describe("public event manifest", () => {
11:   test("owns the complete public event surface", () => {
12:     expect(EventManifest.ServerDefinitions.length).toBe(61)
13:     expect(EventManifest.Definitions.length).toBe(91)
14:     expect(SessionV1.Event.Definitions).toEqual([
15:       SessionV1.Event.Created,
16:       SessionV1.Event.Updated,
17:       SessionV1.Event.Deleted,
18:   ...
gateway · 2026-09-16 14:54:23
result
531	48	packages/core/schema.json
1	0	packages/core/src/database/migration.gen.ts
58	0	packages/core/src/database/migration/20260914170650_session-recovery.ts
48	1	packages/core/src/database/schema.gen.ts
5	4	packages/core/src/session.ts
31	16	packages/core/src/session/compaction.ts
54	34	packages/core/src/session/context-epoch.ts
135	19	packages/core/src/session/execution/local.ts
342	31	packages/core/src/session/input.ts
69	0	packages/core/src/session/message-updater.ts
77	1	packages/core/src/session/projector.ts
413	0	packages/core/src/session/recovery.ts
30	5	packages/core/src/session/run-coordinator.ts
4	0	packages/core/src/session/runner/index.ts
265	104	packages/core/src/session/runner/llm.ts
79	29	packages/core/src/session/runner/publish-llm-event.ts
78	1	packages/core/src/session/sql.ts
66	1	packages/core/test/database-migration.test.ts
283	0	packages/core/test/session-execution-local.test.ts
1866	3	packages/core/test/session-projector.test.ts
247	25	packages/core/test/session-...
gateway · 2026-09-16 14:54:47
result
Found 6 matches
/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner.test.ts:
  Line 212:         : SystemContext.empty,

  Line 215: const referenceGuidance = Layer.mock(ReferenceGuidance.Service, { load: () => Effect.succeed(SystemContext.empty) })

  Line 2037:   it.effect("keeps a provider defect after Step finish unknown", () =>

  Line 4138:   it.effect("durably fails a hosted tool left unresolved at normal provider EOF", () =>

  Line 4142:       yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail hosted tool at EOF" }), resume: false })

  Line 4157:         { type: "user", text: "Fail hosted tool at EOF" },
gateway · 2026-09-16 14:54:58
result
<path>/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
3990:       expect(requests[2]?.toolChoice).toMatchObject({ type: "none" })
3991:       expect(executions).toEqual(["before", "after"])
3992:     }),
3993:   )
3994: 
3995:   it.effect("projects provider errors as terminal assistant step failures", () =>
3996:     Effect.gen(function* () {
3997:       yield* setup
3998:       const session = yield* SessionV2.Service
3999:       yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail durably" }), resume: false })
4000: 
4001:       requests.length = 0
4002:       responses = undefined
4003:       streamGate = undefined
4004:       streamStarted = undefined
4005:       response = [LLMEvent.stepStart({ index: 0 }), LLMEvent.providerError({ message: "Provider unavailable" })]
4006: 
4007:       yield* session.resume(sessionID)
4008: 
4009:       expect(requests).toHaveLength(1)
4010:       expect(yield* ...
gateway · 2026-09-16 14:55:12
result
...output truncated...

Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_0aab6fd12001qTTmY55co1jMYA

+                commit: () =>
+                  updateExecution({
+                    phase: "continue",
+                    assistant_message_id: null,
+                  }),
+              }),
+            ))
           )
             return yield* Effect.die(continueAfterOverflowCompaction(currentStep))
           if (overflowFailure) yield* publish(overflowFailure)
@@ -299,27 +397,43 @@ const layer = Layer.effect(
             yield* withPublication(publisher.failUnsettledTools("Provider did not return a tool result", true))
             yield* withPublication(publisher.failAssistant(llmFailure.reason.message))
           }
-          if (stream._tag === "Failure" && Cause.hasInterrupts(stream.cause)) yield* FiberSet.clear(toolFibers)
-          const settled = yield* restore(awaitToolFibers(toolFibers)).pipe(Effect.exit)
+          if (stream._tag === ...
gateway · 2026-09-16 14:57:10
result
Found 1 matches
/tmp/opencode/session-recovery-v7-check/packages/core/src/session/runner/publish-llm-event.ts:
  Line 466:     hasActiveAssistant: () => assistantActive,
gateway · 2026-09-16 14:59:10

Findings

MUST-FIX — EOF without step-finish strands a running assistant permanently

stepSettlement exists only after a step-finish event (packages/core/src/session/runner/publish-llm-event.ts:445-450). On clean EOF without that event, the runner:

  • reconciles hosted tools (packages/core/src/session/runner/llm.ts:434-435);
  • skips Step.Ended (packages/core/src/session/runner/llm.ts:437-469);
  • returns success (packages/core/src/session/runner/llm.ts:470-473);
  • unconditionally clears the successful execution claim (packages/core/src/session/execution/local.ts:75-80).

The existing test exercises this exact protocol boundary with a hosted tool call followed by EOF and no step-finish (packages/core/test/session-runner.test.ts:4138-4159), but it never asserts assistant completion or claim retention. The projected assistant retains no time.completedorfinish`, while the claim is gone, so recovery can never reconcile it.

Treat EOF without step-finish as an interrupted/unknown Step: either persist Step.Interrupted before marking the claim safe, or fail while preserving the unknown claim.

MUST-FIX — in-memory settlement flags can advance the claim without durable settlement

The publisher changes state before the corresponding durable event succeeds:

  • providerFailed is set before Step.Failed publishes (packages/core/src/session/runner/publish-llm-event.ts:453-455).
  • assistantFailed and assistantActive change before that publish (packages/core/src/session/runner/publish-llm-event.ts:221-238).
  • A tool becomes settled before Tool.Success or Tool.Failed publishes (packages/core/src/session/runner/publish-llm-event.ts:386-423).

Two concrete failures follow:

  1. If Step.Failed publication defects after Step.Started committed, the stream fails but hasProviderError() remains true. The runner then marks the execution safe (packages/core/src/session/runner/llm.ts:427-433), returns the stream failure ...
gpt-5.6-sol · 2026-09-16 14:59:10 · ~1.1K tokens

Distillations (12)

Gen 0 2026-09-16 18:47:28 · 521 tokens

Date: Sep 16, 2026 * 🔴 (14:57) User provided truncated session-recovery code/test diff output; the full output is saved at `/home/byk/.local/share/opencode/tool-output/tool_0aab6fd12001qTTmY55co1jMYA`. * 🔴 (14:57) Added test “never dispatches a provider after ownership changes,” asserting execution ownership fencing before provider dispatch. * 🔴 (14:57) Added test “never publishes streamed out…

Gen 0 2026-09-16 18:27:21 · 3020 tokens

Date: Sep 16, 2026 * 🔴 (14:53) `packages/core/test/session-runner-recorded.test.ts` configures cassette `session-runner/openai-chat-streams-text` under `fixtures/recordings`; `RECORD=true` selects `HttpRecorderInternal.cassetteLayer(..., { mode: "record" })`, otherwise `HttpRecorder.http(...)`. * 🔴 (14:53) The recorded runner test uses OpenAI Chat at `https://api.openai.com/v1`, bearer auth fro…

Gen 0 2026-09-16 18:21:48 · 224 tokens

Date: Sep 16, 2026 * 🔴 (14:52) The recovery execution test suite specifies “never commits continuation before unresolved hosted tools are reconciled” (line 1963). * 🔴 (14:52) The recovery execution test suite specifies “never commits a Step end after the provider stream fails” (line 2015); the failed resume is expected to return an `Exit` failure, and the queried Step-end events are expected to…

Gen 0 2026-09-16 18:05:53 · 1804 tokens

Date: Sep 16, 2026 * 🔴 (14:51) `/tmp/opencode/session-recovery-v7-check/packages/core/src/database/schema.gen.ts` defines `session_input.wake_pending` as `integer DEFAULT false NOT NULL` and `session.wake_attempts` as `integer DEFAULT 0 NOT NULL`; `session_wake_attempts_check` restricts `wake_attempts` to `0` through `9007199254740991`. * 🔴 (14:51) `/tmp/opencode/session-recovery-v7-check/packa…

Gen 0 2026-09-16 17:48:40 · 1101 tokens

Date: Sep 16, 2026 * 🔴 (14:50) `/tmp/opencode/session-recovery-v7-check/packages/core/test/session-prompt.test.ts` specifies “exposes the execution registry” (line 140) and “delegates execution continuation through SessionExecution” (line 147). * 🔴 (14:50) `/tmp/opencode/session-recovery-v7-check/packages/core/test/session-prompt.test.ts` specifies “durably admits one user message before transc…

Gen 0 2026-09-16 17:25:28 · 352 tokens

Date: Sep 16, 2026 * 🔴 (14:49) `/tmp/opencode/session-recovery-v7-check/packages/core/test/session-projector.test.ts` specifies that recovery “never recovers a pre-promotion claim when input commits at the recovery boundary” (line 1086). * 🔴 (14:49) `/tmp/opencode/session-recovery-v7-check/packages/core/test/session-projector.test.ts` specifies that recovery “never promotes a recovery supersede…

Gen 0 2026-09-16 16:54:24 · 326 tokens

Date: Sep 16, 2026 * 🔴 (14:49) `/tmp/opencode/session-recovery-v7-check/packages/core/test/session-projector.test.ts` specifies that recovery never recovers a live execution lease (line 305). * 🔴 (14:49) `/tmp/opencode/session-recovery-v7-check/packages/core/test/session-projector.test.ts` specifies that recovery never recovers an execution superseded by a newer assistant (line 343). * 🔴 (14:4…

Gen 0 2026-09-16 16:37:51 · 1770 tokens

Date: Sep 16, 2026 * 🔴 (14:48) `/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner.test.ts` asserts that the runner “never dispatches a provider after ownership changes” (line 740). * 🔴 (14:48) `/tmp/opencode/session-recovery-v7-check/packages/core/test/session-runner.test.ts` asserts that the runner “never publishes streamed output after ownership changes” (line 766). * …

Gen 0 2026-09-16 16:08:57 · 1190 tokens

Date: Sep 16, 2026 * 🔴 (14:48) `/tmp/opencode/session-recovery-v7-check/packages/core/src/session/sql.ts` defines `MAX_WAKE_ATTEMPTS = Number.MAX_SAFE_INTEGER`; both `SessionTable.wake_attempts` and `SessionRecoveryTable.wake_attempts` default to `0` and are constrained between `0` and `MAX_WAKE_ATTEMPTS`. * 🔴 (14:48) `SessionInputTable` in `/tmp/opencode/session-recovery-v7-check/packages/core…

Gen 0 2026-09-16 15:38:49 · 979 tokens

Date: Sep 16, 2026 * 🔴 (14:47) User directed: “never resume an older assistant projection”; a newer turn supersedes stale incomplete rows. This rule appears in both the database projection and in-memory projection logic. * 🔴 (14:47) In `/tmp/opencode/session-recovery-v7-check/packages/core/src/session/context-epoch.ts`, `SessionContextEpoch.initialize()` and `SessionContextEpoch.prepare()` requ…

Gen 0 2026-09-16 15:26:39 · 272 tokens

Date: Sep 16, 2026 * 🔴 (14:47) User directed that local ownership be replaced with durable multi-node ownership when clustered. * 🔴 (14:47) In `/tmp/opencode/session-recovery-v7-check/packages/core/src/session/runner/index.ts`, the session runner’s implementation checklist marks durable recording of each tool call before side effects begin as complete. * 🔴 (14:47) The session runner’s remainin…

Gen 0 2026-09-16 15:14:02 · 986 tokens

Date: Sep 16, 2026 * 🔴 (14:46) User asserted the session-execution lease invariant: “an expired claim never renews itself.” * 🔴 (14:46) User provided `/tmp/opencode/session-recovery-final-v7.patch`, containing 33 matched file diffs for session recovery, including schema/database migrations, session execution, compaction, context epochs, input projection, message updates, recovery, coordination,…