DashboardopencodeSession 1Ott14A3vCIk

Session 1Ott14A3vCIk

Full ID: 1Ott14A3vCIkpvzdr
Messages: 59
Distillations: 0
Time range: 2026-09-17 00:01:24 — 2026-09-17 00:14:36

Conversation (59 messages)

Read-only independent security review frozen v17. Base ab9408c81cc9916177641ae8e9f08624fc27b5b9. Patch /tmp/opencode/session-recovery-final-v17.patch SHA-256 0eb85245c71fb55fa2a8e169a1cd1de5579059d77aaca30b6ac254482e255a2e. SEA /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server SHA-256 308e9e562a3473b66bac430166db9d6cdd29f5f071d5695c1c35f28b99f26bf4. Verify immutable inputs/clean apply/34 paths and inspect all. No mutation/tests/builds/services, no recall. Focus prior blocker: cancellation after durable Step.Failed while local tool settlement active must terminally settle ownership without duplicate assistant event; runner uses hasAssistantFailed after tool reconciliation to call exact live cancelling->cancelled transition; cleanup removes claim after fibers/finalizers; regression asserts one Failed, no Interrupted, no claim/recovery. Also monotonic cancellation guard/renew isolation/publication defects. Reassess stale owners, recovery identity/replay/supersession, explicit resume, scheduling DoS, tools, schema/clients/auth/dependencies. Accepted final check-call/process-local/skew residuals. Evidence 229 recovery, full Core 1186/0, typecheck, migration upgrades/script, exact smoke. PASS/CONCERN/MUST-FIX file:line; end MERGE or DO-NOT-MERGE. Empty invalid.

gateway · 2026-09-17 00:01:24
result
0eb85245c71fb55fa2a8e169a1cd1de5579059d77aaca30b6ac254482e255a2e  /tmp/opencode/session-recovery-final-v17.patch
308e9e562a3473b66bac430166db9d6cdd29f5f071d5695c1c35f28b99f26bf4  /home/byk/Code/opencode/packages/opencode/dist/server/opencode-server
/tmp/opencode/session-recovery-final-v17.patch 414241 bytes 2026-09-16 23:58:55.914307051 +0000
/home/byk/Code/opencode/packages/opencode/dist/server/opencode-server 157879104 bytes 2026-09-16 23:57:25.659673826 +0000
gateway · 2026-09-17 00:02:21
result
dc661f30cb2055ad6248fdc59b14998d834497be
commit
 M .lore.md
 M AGENTS.md
 M packages/client/src/generated/types.ts
 M packages/core/schema.json
 M packages/core/src/database/migration.gen.ts
 M packages/core/src/database/migration/20260914170650_session-recovery.ts
 D packages/core/src/database/migration/20260914214636_session-execution.ts
 D packages/core/src/database/migration/20260914222526_session-execution-phase.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/recovery.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
 ...
gateway · 2026-09-17 00:02:30
result
bf77604a044ec48ee2e7848865ddee41e317d78e1e8f525c1f326109443742e4  -
72	0	packages/client/src/generated/types.ts
567	48	packages/core/schema.json
1	0	packages/core/src/database/migration.gen.ts
62	0	packages/core/src/database/migration/20260914170650_session-recovery.ts
52	1	packages/core/src/database/schema.gen.ts
6	4	packages/core/src/session.ts
31	16	packages/core/src/session/compaction.ts
54	34	packages/core/src/session/context-epoch.ts
165	19	packages/core/src/session/execution/local.ts
391	31	packages/core/src/session/input.ts
69	0	packages/core/src/session/message-updater.ts
88	1	packages/core/src/session/projector.ts
504	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
300	104	packages/core/src/session/runner/llm.ts
108	46	packages/core/src/session/runner/publish-llm-event.ts
88	1	packages/core/src/session/sql.ts
66	1	packages/core/test/database-migration.test.ts
352	0	packages/core/test/sessi...
gateway · 2026-09-17 00:02:48
result
Found 34 matches
/tmp/opencode/session-recovery-final-v17.patch:
  Line 1: diff --git a/packages/client/src/generated/types.ts b/packages/client/src/generated/types.ts

  Line 109: diff --git a/packages/core/schema.json b/packages/core/schema.json

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

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

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

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

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

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

  Line 1515: diff --git ...
gateway · 2026-09-17 00:02:58
result
ab9408c81cc9916177641ae8e9f08624fc27b5b9
1
M	.lore.md
M	packages/core/schema.json
M	packages/core/src/database/migration.gen.ts
A	packages/core/src/database/migration/20260914170650_session-recovery.ts
A	packages/core/src/database/migration/20260914214636_session-execution.ts
A	packages/core/src/database/migration/20260914222526_session-execution-phase.ts
M	packages/core/src/database/schema.gen.ts
M	packages/core/src/session/compaction.ts
M	packages/core/src/session/execution/local.ts
M	packages/core/src/session/message-updater.ts
M	packages/core/src/session/projector.ts
A	packages/core/src/session/recovery.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
A	packages/core/test/session-execution-local.test.ts
M	packages/core/test/session-projector.test.ts
M	packages/core/test/session-runner-tool-events.test.ts
M	packages/core/test/session-runner.test.ts
M	packages/opencode/src/server/routes/instance/ht...
gateway · 2026-09-17 00:03:06
result
Found 39 matches
/tmp/opencode/session-recovery-final-v17.patch:
  Line 2: index 3b3188c874..5130fa9496 100644

  Line 110: index d0eeeebd5c..81e5eca808 100644

  Line 1026: index e6ea4eaa14..77948f1529 100644

  Line 1037: new file mode 100644

  Line 1038: index 0000000000..20eb1a4373

  Line 1105: index ed60fde6c5..94881e7038 100644

  Line 1211: index 2dabfb2d6f..1fbd6285d0 100644

  Line 1251: index f714633295..92a934c44f 100644

  Line 1340: index 65b17a86a4..880d42bcf9 100644

  Line 1516: index d874c40832..0bb4f02b2c 100644

  Line 1732: index 14b613678d..61f6a9a465 100644

  Line 2327: index 46118a89fe..e2d7e6b38e 100644

  Line 2421: index 792067017d..2742cabc24 100644

  Line 2540: new file mode 100644

  Line 2541: index 0000000000..e289b821c7

  Line 3050: index 2f89aff9e3..ab4b833374 100644

  Line 3119: index 634075dd91..7b9ac3ae83 100644

  Line 3141: index 874086a06b..3853bb7d75 100644

  Line 3725: index 33652a618c..e2b9b9b8f4 100644

  Line 4071: index ...
gateway · 2026-09-17 00:03:35
result
fatal: path 'packages/core/src/database/migration/20260914170650_session-recovery.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9'
fatal: path 'packages/core/src/session/recovery.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9'
fatal: path 'packages/core/test/session-execution-local.test.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9'
fatal: path 'packages/core/src/session/execution/claim.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9'
fatal: path 'packages/core/src/session/recovery-id.ts' exists on disk, but not in 'ab9408c81cc9916177641ae8e9f08624fc27b5b9'
sections=34
clean_in_memory_apply=True
base_and_worktree_blob_matches=True
gateway · 2026-09-17 00:03:46
result
<path>/home/byk/Code/opencode/packages/core/src/session/execution/claim.ts</path>
<type>file</type>
<content>
1: export * as SessionExecutionClaim from "./claim"
2: 
3: import { and, eq, gt, notInArray } 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<
18:   Pick<typeof SessionExecutionTable.$inferInsert, "assistant_message_id" | "assistant_seq" | "phase">
19: >
20: 
21: export class Lost extends Error {
22:   constructor(readonly claim: Claim) {
23:     super(`Session execution claim lost: ${claim.executionID}`)
24:   }
25: }
26: 
27: const where = ...
gateway · 2026-09-17 00:03:51
result
<path>/home/byk/Code/opencode/packages/core/src/session/execution/local.ts</path>
<type>file</type>
<content>
1: import { and, asc, desc, 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 {
14:   SESSION_EXECUTION_LEASE_MS,
15:   SessionExecutionTable,
16:   SessionMessageTable,
17:   SessionRecoveryTable,
18: } from "../sql"
19: 
20: /** Current-process routing for implicit-local Locations. ...
gateway · 2026-09-17 00:03:55
result
<path>/home/byk/Code/opencode/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 "../../system-context/registry"
24: ...
gateway · 2026-09-17 00:03:59
result
<path>/home/byk/Code/opencode/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, seq: number) => 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-17 00:04:10
result
<path>/home/byk/Code/opencode/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 Entry<E> = {
18: ...
gateway · 2026-09-17 00:04:17
result
<path>/home/byk/Code/opencode/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 { continuation } from "./recovery-id"
14: import { SessionSchema } from "./schema"
15: import {
16:   MAX_WAKE_ATTEMPTS,
17:   SESSION_EXECUTION_LEASE_MS,
18:   SessionExecutionTable,
19:   SessionInputTable,
20:   SessionRecoveryTable,
21:   SessionMessageTable,
22:   ...
gateway · 2026-09-17 00:04:23
result
<path>/home/byk/Code/opencode/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, SessionTable } 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-17 00:04:27
result
<path>/home/byk/Code/opencode/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:   SessionRecoveryTable,
23:   ...
gateway · 2026-09-17 00:04:30
result
<path>/home/byk/Code/opencode/packages/core/src/session/projector.ts</path>
<type>file</type>
<content>
351:           .where(eq(SessionTable.id, event.data.sessionID))
352:           .run()
353:           .pipe(Effect.orDie)
354:         yield* run(db, event)
355:       }),
356:     )
357:     yield* events.project(SessionEvent.Prompted, (event) =>
358:       Effect.gen(function* () {
359:         if (event.durable === undefined) return yield* Effect.die("Durable Session event is missing aggregate sequence")
360:         yield* SessionInput.projectPrompted(db, {
361:           id: event.data.messageID,
362:           sessionID: event.data.sessionID,
363:           prompt: event.data.prompt,
364:           delivery: event.data.delivery,
365:           timeCreated: event.data.timestamp,
366:           promotedSeq: event.durable.seq,
367:         })
368:         yield* run(db, event)
369:       }),
370:     )
371:     yield* events.project(SessionEvent.PromptAdmitted, (event) =>
372:    ...
gateway · 2026-09-17 00:04:34
result
<path>/home/byk/Code/opencode/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-17 00:04:38
result
<path>/home/byk/Code/opencode/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 function ...
gateway · 2026-09-17 00:04:45
result
<path>/home/byk/Code/opencode/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-17 00:04:58
result
<path>/home/byk/Code/opencode/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 { Revert } from ...
gateway · 2026-09-17 00:05:12
result
<path>/home/byk/Code/opencode/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 CONSTRAINT \`session_wake_attempts_check\` 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:            ...
gateway · 2026-09-17 00:05:21
result
Found 21 matches
/home/byk/Code/opencode/packages/core/src/database/schema.gen.ts:
  Line 158:         CREATE TABLE \`session_execution\` (

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

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

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

  Line 181:           \`wake_pending\` integer DEFAULT false NOT NULL,

  Line 199:         CREATE TABLE \`session_recovery\` (

  Line 205:           \`wake_pending\` integer DEFAULT true NOT NULL,

  Line 206:           \`wake_attempts\` integer DEFAULT 0 NOT NULL,

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

  Line 210:           CONSTRAINT \`fk_session_recovery_session_id_session_id_fk\` FOREIGN KEY ...
gateway · 2026-09-17 00:05:31
result
<path>/home/byk/Code/opencode/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 Source extends ...
gateway · 2026-09-17 00:05:48
result
<path>/home/byk/Code/opencode/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 { Format } from ...
gateway · 2026-09-17 00:05:53
result
<path>/home/byk/Code/opencode/packages/opencode/src/server/routes/instance/httpapi/server.ts</path>
<type>file</type>
<content>
181:   Layer.provide([serverHttpApiAuthLayer, v2SchemaErrorLayer]),
182: )
183: 
184: // `OpenApi.fromApi` is non-trivial; defer until /doc is actually hit so
185: // processes that never serve it (CLI, scripts) don't pay at module load.
186: // `HttpServerResponse.jsonUnsafe` runs JSON.stringify eagerly, so caching
187: // the response also caches the serialized body — every /doc request reuses
188: // the same Uint8Array instead of re-stringifying the spec.
189: const docResponse = lazy(() => HttpServerResponse.jsonUnsafe(OpenApi.fromApi(PublicApi)))
190: 
191: const docRoute = HttpRouter.use((router) => router.add("GET", "/doc", () => Effect.succeed(docResponse()))).pipe(
192:   Layer.provide(authOnlyRouterLayer),
193: )
194: 
195: const uiRoute = HttpRouter.use((router) =>
196:   Effect.gen(function* () {
197:     const fs = yield* FSUtil.Service
198:     ...
gateway · 2026-09-17 00:06:01
result
<path>/home/byk/Code/opencode/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-17 00:06:12
result
<path>/home/byk/Code/opencode/packages/core/src/session.ts</path>
<type>file</type>
<content>
320:         const boundary = anchor
321:           ? order === "asc"
322:             ? gt(SessionMessageTable.seq, anchor.seq)
323:             : lt(SessionMessageTable.seq, anchor.seq)
324:           : undefined
325:         const where = boundary
326:           ? and(eq(SessionMessageTable.session_id, input.sessionID), boundary)
327:           : eq(SessionMessageTable.session_id, input.sessionID)
328:         const query = db
329:           .select()
330:           .from(SessionMessageTable)
331:           .where(where)
332:           .orderBy(order === "asc" ? asc(SessionMessageTable.seq) : desc(SessionMessageTable.seq))
333:         const rows = yield* (input.limit === undefined ? query.all() : query.limit(input.limit).all()).pipe(
334:           Effect.orDie,
335:         )
336:         return yield* Effect.forEach(direction === "previous" ? rows.toReversed() : rows, decode)
337:       ...
gateway · 2026-09-17 00:06:25
result
Found 84 matches
/home/byk/Code/opencode/packages/core/test/session-runner.test.ts:
  Line 752:   it.effect("never dispatches a provider after ownership changes", () =>

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

  Line 787:       yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "fence publication" }), resume: false })

  Line 793:         .set({ id: "publication-successor", owner_id: "successor", expires_at: 60_000 })

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

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

  Line 2055:   it.effect("keeps a running assistant recoverable when Step failure publication defects", () =>

  Line 2060:       yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail Step publication" }), resume: false })

  Line 2063:         CREATE TRIGGER fail_step_failure_publication

  Line 2067:           SELECT ...
gateway · 2026-09-17 00:06:32
result
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
700:         LLMEvent.stepStart({ index: 0 }),
701:         LLMEvent.stepFinish({ index: 0, reason: "stop" }),
702:         LLMEvent.finish({ reason: "stop" }),
703:       ]
704: 
705:       yield* session.resume(sessionID)
706: 
707:       expect(
708:         yield* db.select().from(SessionInputTable).where(eq(SessionInputTable.id, message.id)).get(),
709:       ).toMatchObject({
710:         wake_pending: false,
711:       })
712:     }),
713:   )
714: 
715:   it.effect("redrives an ordinary prompt after its advisory wake is lost", () =>
716:     Effect.gen(function* () {
717:       yield* setup
718:       const session = yield* SessionV2.Service
719:       const events = yield* EventV2.Service
720:       const { db } = yield* Database.Service
721:       const { admitted: message } = yield* SessionInput.admit(db, events, {
722:         id: ...
gateway · 2026-09-17 00:06:36
result
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
3860:       const run = yield* session.resume(sessionID).pipe(Effect.forkChild)
3861:       while (executions.length === 0) yield* Effect.yieldNow
3862:       const { db } = yield* Database.Service
3863:       expect(
3864:         yield* db.select().from(SessionExecutionTable).where(eq(SessionExecutionTable.session_id, sessionID)).get(),
3865:       ).toMatchObject({
3866:         phase: "unknown",
3867:       })
3868:       yield* session.interrupt(sessionID)
3869:       toolExecutionGate = undefined
3870: 
3871:       expect(yield* Fiber.await(run)).toMatchObject({ _tag: "Failure" })
3872:       yield* session.interrupt(sessionID)
3873:       expect(yield* session.context(sessionID)).toMatchObject([
3874:         { type: "user", text: "Interrupt blocked tool" },
3875:         {
3876:           type: "assistant",
3877:           finish: "error",
3878:           error: { type: ...
gateway · 2026-09-17 00:06:46
result
<path>/home/byk/Code/opencode/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, sql } 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 { SessionExecutionClaim } from "@opencode-ai/core/session/execution/claim"
11: import { SessionMessage } from "@opencode-ai/core/session/message"
12: import { SessionSchema } from "@opencode-ai/core/session/schema"
13: import { SessionExecutionTable, SessionTable } from "@opencode-ai/core/session/sql"
14: import { testEffect } from ...
gateway · 2026-09-17 00:07:07
result
Found 100 matches (more matches available)
/home/byk/Code/opencode/packages/core/test/session-runner.test.ts:
  Line 619:   it.effect("redrives only the synthetic recovery continuation", () =>

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

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

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

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

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

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

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

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

  Line 977:   it.effect("streams one request with registry definitions from ...
gateway · 2026-09-17 00:07:18
result
Found 52 matches
/home/byk/Code/opencode/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 258:   it.effect("recovers each abandoned execution once across repeated startup scans", () =>

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

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

  Line 390:     it.effect(`never recovers an assistant-less ${phase} execution superseded by a newer assistant`, () =>

  Line 435:     it.effect(`never commits assistant-less ${phase} recovery after concurrent assistant supersession`, () =>

  Line 504:   it.effect("recovers assistant-less continuation at its current assistant boundary", () =>

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

  Line ...
gateway · 2026-09-17 00:07:25
result
<path>/home/byk/Code/opencode/packages/core/test/session-projector.test.ts</path>
<type>file</type>
<content>
700:         wake: (id) => Effect.sync(() => wakes.push(id)).pipe(Effect.asVoid),
701:       })
702: 
703:       yield* SessionRecovery.recover().pipe(Effect.provideService(SessionExecution.Service, execution))
704:       expect(wakes).toEqual([])
705:       expect(
706:         yield* db
707:           .select()
708:           .from(SessionRecoveryTable)
709:           .where(eq(SessionRecoveryTable.recovery_error, "Invalid recovery continuation input"))
710:           .all(),
711:       ).toHaveLength(SessionRecovery.BATCH_SIZE)
712: 
713:       yield* SessionRecovery.recover().pipe(Effect.provideService(SessionExecution.Service, execution))
714:       expect(wakes).toEqual([sessions[poisonCount]])
715:       expect(
716:         yield* db
717:           .select()
718:           .from(SessionRecoveryTable)
719:           .where(eq(SessionRecoveryTable.recovery_error, ...
gateway · 2026-09-17 00:08:03
result
<path>/home/byk/Code/opencode/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. */
21: export interface Interface {
22:   /** Drains eligible durable work. ...
gateway · 2026-09-17 00:08:09
result
<path>/home/byk/Code/opencode/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-17 00:08:15
result
Found 50 matches
/home/byk/Code/opencode/packages/schema/test/event-manifest.test.ts:
  Line 52:     expect(EventManifest.Durable.get("session.next.prompt.execution_requested.1")).toBe(

  Line 53:       SessionEvent.PromptExecutionRequested,


/home/byk/Code/opencode/packages/client/src/generated/types.ts:
  Line 784:         readonly type: "session.next.prompt.execution_requested"

  Line 908:         readonly type: "session.next.step.recovered"

  Line 1278:       readonly type: "session.next.prompt.execution_requested"

  Line 1402:       readonly type: "session.next.step.recovered"


/home/byk/Code/opencode/packages/sdk/openapi.json:
  Line 15312:             "$ref": "#/components/schemas/EventSessionNextPromptExecution_requested"

  Line 15339:             "$ref": "#/components/schemas/EventSessionNextStepRecovered"

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

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

  ...
gateway · 2026-09-17 00:08:19
result
<path>/home/byk/Code/opencode/packages/sdk/js/src/v2/gen/types.gen.ts</path>
<type>file</type>
<content>
3425:       timestamp: number
3426:       sessionID: string
3427:       messageID: string
3428:       prompt: Prompt
3429:       delivery: "steer" | "queue"
3430:       requestExecution?: boolean
3431:     }
3432:   }
3433: }
3434: 
3435: export type SyncEventSessionNextPromptExecutionRequested = {
3436:   type: "sync"
3437:   id: string
3438:   syncEvent: {
3439:     type: "session.next.prompt.execution_requested.1"
3440:     id: string
3441:     seq: number
3442:     aggregateID: string
3443:     data: {
3444:       timestamp: number
3445:       sessionID: string
3446:       messageID: string
3447:     }
3448:   }
3449: }
3450: 
3451: export type SyncEventSessionNextContextUpdated = {
3452:   type: "sync"
3453:   id: string
3454:   syncEvent: {
3455:     type: "session.next.context.updated.1"
3456:     id: string
3457:     seq: number
3458:     aggregateID: string
3459:     data: ...
gateway · 2026-09-17 00:08:24
result
<path>/home/byk/Code/opencode/packages/sdk/openapi.json</path>
<type>file</type>
<content>
35170:               "timestamp": {
35171:                 "type": "number"
35172:               },
35173:               "sessionID": {
35174:                 "type": "string",
35175:                 "pattern": "^ses"
35176:               },
35177:               "assistantMessageID": {
35178:                 "type": "string",
35179:                 "pattern": "^msg_"
35180:               },
35181:               "error": {
35182:                 "$ref": "#/components/schemas/SessionErrorUnknown"
35183:               }
35184:             },
35185:             "required": ["timestamp", "sessionID", "assistantMessageID", "error"],
35186:             "additionalProperties": false
35187:           }
35188:         },
35189:         "required": ["id", "type", "properties"],
35190:         "additionalProperties": false
35191:       },
35192:       "EventSessionNextStepRecovered": {
35193:         ...
gateway · 2026-09-17 00:08:32
result
Found 4 matches
/home/byk/Code/opencode/packages/core/schema.json:
  Line 2306:       "name": "session_execution_recovery_scan_idx",

  Line 2510:       "name": "session_recovery_wake_pending_error_attempts_created_execution_idx",

  Line 2572:       "name": "session_execution_phase_check",

  Line 2578:       "name": "session_recovery_wake_attempts_check",
gateway · 2026-09-17 00:08:54
result
<path>/home/byk/Code/opencode/packages/core/schema.json</path>
<type>file</type>
<content>
2180:     {
2181:       "columns": [
2182:         {
2183:           "value": "project_id",
2184:           "isExpression": false
2185:         },
2186:         {
2187:           "value": "action",
2188:           "isExpression": false
2189:         },
2190:         {
2191:           "value": "resource",
2192:           "isExpression": false
2193:         }
2194:       ],
2195:       "isUnique": true,
2196:       "where": null,
2197:       "origin": "manual",
2198:       "name": "permission_project_action_resource_idx",
2199:       "entityType": "indexes",
2200:       "table": "permission"
2201:     },
2202:     {
2203:       "columns": [
2204:         {
2205:           "value": "session_id",
2206:           "isExpression": false
2207:         },
2208:         {
2209:           "value": "time_created",
2210:           "isExpression": false
2211:         },
2212:         {
2213:           ...
gateway · 2026-09-17 00:09:02
result
Found 3 matches
/home/byk/Code/opencode/packages/core/schema.json:
  Line 66:       "name": "session_execution",

  Line 70:       "name": "session_input",

  Line 78:       "name": "session_recovery",
gateway · 2026-09-17 00:09:08
result
<path>/home/byk/Code/opencode/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:     import("./migration/20260413175956_chief_energizer"),
17:     ...
gateway · 2026-09-17 00:09:22
result
<path>/home/byk/Code/opencode/packages/core/test/database-migration.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect, test } from "bun:test"
2: import { $ } from "bun"
3: import { fileURLToPath } from "url"
4: import path from "path"
5: import { SqliteClient } from "@effect/sql-sqlite-bun"
6: import { EffectDrizzleSqlite } from "@opencode-ai/effect-drizzle-sqlite"
7: import { Effect, Exit, Layer } from "effect"
8: import { eq, inArray, sql } from "drizzle-orm"
9: import { DatabaseMigration } from "@opencode-ai/core/database/migration"
10: import { migrations } from "@opencode-ai/core/database/migration.gen"
11: import workspaceNameMigration from "@opencode-ai/core/database/migration/20260410174513_workspace-name"
12: import sessionUsageMigration from "@opencode-ai/core/database/migration/20260510033149_session_usage"
13: import normalizeStoragePathsMigration from "@opencode-ai/core/database/migration/20260601010001_normalize_storage_paths"
14: import ...
gateway · 2026-09-17 00:09:28
result
<path>/home/byk/Code/opencode/packages/core/src/database/schema.gen.ts</path>
<type>file</type>
<content>
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:       yield* tx.run(`
149:         CREATE TABLE \`session_context_epoch\` (
150:           \`session_id\` text PRIMARY KEY,
151:           \`baseline\` text NOT NULL,
152:           \`snapshot\` text NOT NULL,
153:           \`baseline_seq\` integer NOT NULL,
154:           CONSTRAINT \`fk_session_context_epoch_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE
155:         );
156:       `)
157:       yield* tx.run(`
158:         ...
gateway · 2026-09-17 00:09:39
result
Found 29 matches
/home/byk/Code/opencode/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 159:   it.effect("delegates process-local interruption through SessionExecution", () =>

  Line 171:   it.effect("delegates interruption without requiring a recorded Session", () =>

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

  Line 203:   it.effect("resolves attachment MIME before admission", () =>

  Line 224:   it.effect("streams durable Session events after an aggregate sequence", () =>

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

  Line 275:   it.effect("records distinct messages when the ID is omitted", () =>

  Line 290:   it.effect("returns the original recorded message when the ID is retried", () =>

  Line 310:   ...
gateway · 2026-09-17 00:09:44
result
<path>/home/byk/Code/opencode/packages/core/test/session-prompt.test.ts</path>
<type>file</type>
<content>
130:       SessionExecution.Service.of({
131:         active: Effect.succeed(new Set()),
132:         resume: () => Effect.void,
133:         interrupt: () => Effect.void,
134:         wake: (id) => Effect.sync(() => wakeCalls.push(id)).pipe(Effect.asVoid),
135:       }),
136:     ),
137:   )
138: 
139: describe("SessionV2.prompt", () => {
140:   it.effect("exposes the execution registry", () =>
141:     Effect.gen(function* () {
142:       activeSessions.add(sessionID)
143:       expect(Array.from(yield* (yield* SessionV2.Service).active)).toEqual([sessionID])
144:     }).pipe(Effect.ensuring(Effect.sync(() => activeSessions.clear()))),
145:   )
146: 
147:   it.effect("delegates execution continuation through SessionExecution", () =>
148:     Effect.gen(function* () {
149:       yield* setup
150:       const session = yield* SessionV2.Service
151:       executionCalls.length = ...
gateway · 2026-09-17 00:09:51
result
<path>/home/byk/Code/opencode/packages/core/test/session-run-coordinator.test.ts</path>
<type>file</type>
<content>
1: import { describe, expect } from "bun:test"
2: import { Cause, Deferred, Effect, Exit, Fiber, Layer } from "effect"
3: import { SessionRunCoordinator } from "@opencode-ai/core/session/run-coordinator"
4: import { testEffect } from "./lib/effect"
5: 
6: const it = testEffect(Layer.empty)
7: 
8: describe("SessionRunCoordinator", () => {
9:   it.effect("joins concurrent resumes for one key", () =>
10:     Effect.scoped(
11:       Effect.gen(function* () {
12:         const gate = yield* Deferred.make<void>()
13:         let runs = 0
14:         const coordinator = yield* SessionRunCoordinator.make({
15:           drain: () => Effect.sync(() => runs++).pipe(Effect.andThen(Deferred.await(gate))),
16:         })
17: 
18:         const first = yield* coordinator.run("session").pipe(Effect.forkChild)
19:         yield* Effect.yieldNow
20:         const second = yield* ...
gateway · 2026-09-17 00:10:03
result
<path>/tmp/opencode/session-recovery-final-v17.patch</path>
<type>file</type>
<content>
7850:      Effect.scoped(
7851:        Effect.gen(function* () {
7852: diff --git a/packages/core/test/session-runner-recorded.test.ts b/packages/core/test/session-runner-recorded.test.ts
7853: index d45cc8c734..ec91d1b4a4 100644
7854: --- a/packages/core/test/session-runner-recorded.test.ts
7855: +++ b/packages/core/test/session-runner-recorded.test.ts
7856: @@ -19,7 +19,7 @@ import { Snapshot } from "@opencode-ai/core/snapshot"
7857:  import { Prompt } from "@opencode-ai/core/session/prompt"
7858:  import { SessionProjector } from "@opencode-ai/core/session/projector"
7859:  import { SessionExecution } from "@opencode-ai/core/session/execution"
7860: -import { SessionRunCoordinator } from "@opencode-ai/core/session/run-coordinator"
7861: +import { SessionExecutionLocal } from "@opencode-ai/core/session/execution/local"
7862:  import { SessionRunner } from "@opencode-ai/core/session/runner"
7863:  ...
gateway · 2026-09-17 00:10:15
result
<path>/tmp/opencode/session-recovery-final-v17.patch</path>
<type>file</type>
<content>
9390:      }),
9391:    )
9392:  
9393: diff --git a/packages/opencode/src/server/routes/instance/httpapi/server.ts b/packages/opencode/src/server/routes/instance/httpapi/server.ts
9394: index fb9d2db656..748e8aa43b 100644
9395: --- a/packages/opencode/src/server/routes/instance/httpapi/server.ts
9396: +++ b/packages/opencode/src/server/routes/instance/httpapi/server.ts
9397: @@ -66,6 +66,7 @@ import { SessionProjector } from "@opencode-ai/core/session/projector"
9398:  import { SessionV2 } from "@opencode-ai/core/session"
9399:  import { SessionExecution } from "@opencode-ai/core/session/execution"
9400:  import * as SessionExecutionLocal from "@opencode-ai/core/session/execution/local"
9401: +import { SessionRecovery } from "@opencode-ai/core/session/recovery"
9402:  import { lazy } from "@/util/lazy"
9403:  import { CorsConfig, isAllowedCorsOrigin, type CorsOptions } from ...
gateway · 2026-09-17 00:10:42
result
/home/byk/Code/opencode/packages/core/src/event.ts
gateway · 2026-09-17 00:10:47
result
<path>/home/byk/Code/opencode/packages/core/src/event.ts</path>
<type>file</type>
<content>
1: export * as EventV2 from "./event"
2: 
3: import { Cause, Context, Effect, Layer, Option, PubSub, Queue, Schema, Stream } from "effect"
4: import { Event } from "@opencode-ai/schema/event"
5: import type { Data, Definition, Payload } from "@opencode-ai/schema/event"
6: import { and, asc, eq, gt, inArray } from "drizzle-orm"
7: import { Database } from "./database/database"
8: import { EventSequenceTable, EventTable } from "./event/sql"
9: import { Location } from "./location"
10: import { makeGlobalNode } from "./effect/app-node"
11: import { isDeepStrictEqual } from "node:util"
12: import { Durable } from "@opencode-ai/schema/durable-event-manifest"
13: 
14: export const ID = Event.ID
15: export type ID = import("@opencode-ai/schema/event").ID
16: export type { Data, Definition, Payload } from "@opencode-ai/schema/event"
17: 
18: export type Subscriber<D extends Definition = Definition> = ...
gateway · 2026-09-17 00:11:01
result
Found 76 matches
/home/byk/Code/opencode/packages/core/test/session-runner.test.ts:
  Line 818:       const unsubscribe = yield* events.listen((event) =>

  Line 3245:       yield* events.listen((event) =>


/home/byk/Code/opencode/packages/core/test/permission.test.ts:
  Line 93:     const unsubscribe = yield* events.listen((event) =>

  Line 292:       const unsubscribe = yield* events.listen((event) =>


/home/byk/Code/opencode/packages/core/test/event.test.ts:
  Line 257:       const unsubscribe = yield* events.listen(() =>

  Line 275:       yield* events.listen(() => {

  Line 278:       yield* events.listen((event) =>

  Line 297:       yield* events.listen((event) =>

  Line 358:       yield* events.listen(() => Effect.interrupt)

  Line 377:       yield* events.listen(() => Effect.die(defect))

  Line 966:       yield* events.listen((event) => Effect.sync(() => received.push(event)))

  Line 994:       yield* events.listen((event) => Effect.sync(() => received.push(event)))

 ...
gateway · 2026-09-17 00:11:13
result
<path>/home/byk/Code/opencode/packages/opencode/src/event-v2-bridge.ts</path>
<type>file</type>
<content>
1: // Opencode publish boundary for core events. Attach routed instance location
2: // so direct EventV2 consumers can isolate directory/workspace streams.
3: import { LayerNode } from "@opencode-ai/core/effect/layer-node"
4: import { InstanceRef, WorkspaceRef } from "@/effect/instance-ref"
5: import { GlobalBus } from "@/bus/global"
6: import { EventV2 } from "@opencode-ai/core/event"
7: import { Location } from "@opencode-ai/core/location"
8: import { Project } from "@opencode-ai/core/project"
9: import { AbsolutePath } from "@opencode-ai/core/schema"
10: import { Context, Effect, Layer } from "effect"
11: 
12: export class Service extends Context.Service<Service, EventV2.Interface>()("@opencode/EventV2Bridge") {}
13: 
14: const layer = Layer.effect(
15:   Service,
16:   Effect.gen(function* () {
17:     const events = yield* EventV2.Service
18: 
19:     const publish: ...
gateway · 2026-09-17 00:11:30
result
<path>/home/byk/Code/opencode/packages/core/test/session-runner.test.ts</path>
<type>file</type>
<content>
2010:       const claim = yield* db.select().from(SessionExecutionTable).get()
2011:       const started = yield* db
2012:         .select({ seq: EventTable.seq })
2013:         .from(EventTable)
2014:         .where(eq(EventTable.type, "session.next.step.started.1"))
2015:         .get()
2016:       expect(claim).toMatchObject({ phase: "unknown", assistant_seq: started?.seq })
2017:       expect(
2018:         (yield* session.context(sessionID))
2019:           .filter((message) => message.type === "assistant")
2020:           .flatMap((message) => message.content)
2021:           .find((part) => part.type === "tool" && part.id === "call-hosted-pending"),
2022:       ).toMatchObject({ type: "tool", state: { status: "running" } })
2023:       expect(
2024:         yield* db
2025:           .select({ type: EventTable.type })
2026:           .from(EventTable)
2027:           ...
gateway · 2026-09-17 00:12:50
result
<path>/home/byk/Code/opencode/packages/client/src/generated/types.ts</path>
<type>file</type>
<content>
750:           readonly delivery: "steer" | "queue"
751:         }
752:       }
753:     | {
754:         readonly id: string
755:         readonly metadata?: { readonly [x: string]: JsonValue }
756:         readonly type: "session.next.prompt.admitted"
757:         readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number }
758:         readonly location?: { readonly directory: string; readonly workspaceID?: string }
759:         readonly data: {
760:           readonly timestamp: number
761:           readonly sessionID: string
762:           readonly messageID: string
763:           readonly prompt: {
764:             readonly text: string
765:             readonly files?: ReadonlyArray<{
766:               readonly uri: string
767:               readonly mime: string
768:               readonly name?: string
769:               readonly ...
gateway · 2026-09-17 00:13:29
result
Found 3 matches
/home/byk/Code/opencode/packages/core/src/session/runner/llm.ts:
  Line 203:       const renewCancellation = () => SessionExecutionClaim.settleCancellation(db, claim)

  Line 205:         SessionExecutionClaim.settleCancellation(db, claim, { phase: "cancelled", assistant_message_id: null })

  Line 436:               if (cancelling && publisher.hasAssistantFailed()) yield* settleCancellation()
gateway · 2026-09-17 00:14:36

Immutable input verification

  • PASS Base commit exists: ab9408c81cc9916177641ae8e9f08624fc27b5b9.
  • PASS Patch SHA-256 matches: 0eb85245c71fb55fa2a8e169a1cd1de5579059d77aaca30b6ac254482e255a2e.
  • PASS SEA SHA-256 matches: 308e9e562a3473b66bac430166db9d6cdd29f5f071d5695c1c35f28b99f26bf4.
  • PASS Patch contains exactly 34 paths.
  • PASS In-memory application verified every hunk against the base. Every old blob matched the base, every resulting blob matched the patch index, and all 34 inspected source files matched those resulting blobs.
  • The mutable worktree contains unrelated .lore.md, AGENTS.md, and perf.data* changes. I excluded them from the review.
  • I performed no mutation, tests, builds, or service operations.

Findings

MUST-FIX — durable Step.Failed can still be followed by duplicate Step.Interrupted

failAssistant records assistantFailed = true only after events.publish(Step.Failed) returns:

  • packages/core/src/session/runner/publish-llm-event.ts:222-240

Durable publication commits before notification completes. The transaction is uninterruptible, but notification occurs afterward and remains interruptible:

  • packages/core/src/event.ts:237-363
  • packages/core/src/event.ts:378-390
  • packages/core/src/event.ts:406-416

Cancellation settlement later trusts only the in-memory flag:

  • packages/core/src/session/runner/llm.ts:431-443

This leaves the following reproducible boundary:

  1. A local tool remains active.
  2. Step.Failed commits durably.
  3. The publishing fiber blocks or gets interrupted during post-commit notification.
  4. assistantFailed = true never executes.
  5. Tool reconciliation completes.
  6. hasAssistantFailed() returns false.
  7. Cancellation publishes Step.Interrupted for the assistant that already has durable Step.Failed.

The v17 regression checks the ordinary timing but does not control this boundary:

  • packages/core/test/session-runner.test.ts:3951-3995

A ...

gpt-5.6-sol · 2026-09-17 00:14:36 · ~1.4K tokens