Dashboard › opencode › Distillation
d9760d01-61d2-4de8-b808-93a19a2591a1["lore_tm_v1_WmiA7F36Zd9TfIa4UUY9DEHBb4PrdZRTPIae2iaRRnM","lore_tm_v1_1wFmFnPuHGoa28LV1KpIt-sM6i9PPMmq_RyLFLvDAEo","lore_tm_v1_nmyXk9JEYMHWhSYkigU2rF6x84P7yWLQmz2ahkZVT0w","lore_tm_v1_d6ZShMdaYJ_VysGgrVHbn7T_7f-NX2panHDANU_05a0","lore_tm_v1_f5yr2dgt7VOdVFYsuVxrEzua7TJbxZqA7iyP1pdiN-g","lore_tm_v1_1owTuYAktsxIEblSWONsE_EAcRz-9bGEtsOPPtkzA3A","lore_tm_v1_dB1NtdEI5o8BYkcTOLFbUiN_jNyGSuqOn_RPthM8QEk","lore_tm_v1_q6ky_AA4dc5B-WPVRd0ps3rvWV6_FAs878b6Z7IJ8U0","lore_tm_v1_S5PnmCpmJ4JgOPBwH1adi4nXTpyH7KfC5jDc8osHQRo"]
Date: Sep 17, 2026
/tmp/opencode/session-recovery-v21-review/packages/core/src/session/context-epoch.ts defines claim-fenced context-epoch initialization and preparation. initialize() delegates to initializeOnce(); prepare() delegates to prepareOnce(); both receive a SessionExecutionClaim.Claim.SessionContextEpoch.prepareOnce() concurrently loads the current SystemContext.SystemContext, stored SessionContextEpochTable row, and SessionHistory.latestCompaction(db, sessionID) with { concurrency: "unbounded" }. With no stored epoch, it calls SystemContext.initialize(value), inserts the generation, and returns { baseline, baselineSeq }.prepareOnce() decodes stored.snapshot through Schema.decodeUnknownEffect(SystemContext.Snapshot) and maps failure to ContextSnapshotDecodeError({ sessionID, details: String(error) }). A completed compaction newer than stored.baseline_seq supplies replacementSeq; this selects SystemContext.replace(value, snapshot) rather than SystemContext.reconcile(value, snapshot).prepareOnce() handles context results as follows: Unchanged and ReplacementBlocked retain stored.baseline and stored.baseline_seq; ReplacementReady writes a replacement baseline using replacementSeq or EventV2.latestSequence(db, sessionID); an incremental update publishes SessionEvent.ContextUpdated with a new SessionMessage.ID, current timestamp, and result.text, and its commit callback calls advance(db, sessionID, result.snapshot, claim).pipe(Effect.orDie)./tmp/opencode/session-recovery-v21-review/packages/core/src/session/context-epoch.ts are fenced by SessionExecutionClaim.transaction(): insert() stores session_id, baseline, snapshot, and baseline_seq; replace() updates all baseline fields; advance() updates only snapshot. replace() and advance() die with "Context Epoch not found" if their update returns no row. reset() directly deletes the sessionβs epoch row./tmp/opencode/session-recovery-v21-review/packages/core/src/session/event.ts re-exports both named exports and the SessionEvent namespace from @opencode-ai/schema/session-event./tmp/opencode/session-recovery-v21-review/packages/schema/src/session-event.ts defines Compaction.Ended as durable event type "session.next.compaction.ended" with messageID, reason, text, and recent. Compaction.Delta is present in Definitions but omitted from DurableDefinitions; Compaction.Started and Compaction.Ended are in both inventories.packages/opencode/src/server/routes/instance/httpapi/server.ts from AppNodeBuilderV1.build(SessionV2.node, ...) to AppNodeBuilderV1.build(LayerNode.group([SessionV2.node, SessionRecovery.node]), ...), while retaining dependencies [LocationServiceMap.node, locationServiceMapV2] and [SessionExecution.node, SessionExecutionLocal.node]; this adds session recovery to the instance HTTP API application graph.SessionExecutionLocal tests use sessionID = SessionSchema.ID.make("ses_execution_local") and cover the ownership invariants "never starts a second owner while the lease is live", "never overwrites an expired lease", "never re-enters its own uncertain live lease", "never revives an expired claim on heartbeat", and "never lets runner settlement overwrite cancellation".packages/core/test/session-run-coordinator.test.ts adds "finalizes interruption when cleanup dies": the first run is interrupted with cleanup that waits on cleanupGate and then dies with new Error("cleanup defect"); a wake registered during cleanup must still start the second run, the interruption exit must contain a defect, coordinator.active must end empty, and runs must equal 2.packages/core/test/session-run-coordinator.test.ts adds "joins concurrent interruption behind one cleanup barrier": two concurrent interrupt("session", ...) calls must share the first cleanup barrier, keep both interrupt callers pending until cleanupGate opens, execute cleanup exactly once (cleanups === 1), and then run exactly one queued follow-up (runs === 2).SessionRunCoordinator interruption tests shown verify: interrupting while idle is a no-op; interrupting active execution clears its pending wake and leaves active empty; a wake registered during cleanup runs afterward; a forced run() registered during cleanup resumes with force sequence [false, true]; a wake racing with failure starts one follow-up; interrupting a joined waiter does not cancel the underlying execution; and different keys execute concurrently.packages/core/test/session-run-coordinator.test.ts includes "trampolines synchronous self-waking execution" with limit = 20_000, exercising stack-safe repeated synchronous wake behavior./tmp/opencode/session-recovery-v21-review/packages/core/test/session-runner.test.ts show recovery and ownership-fencing coverage. Recovery tests include "redrives only the synthetic recovery continuation", "redrives an ordinary prompt after its advisory wake is lost", "recovers the continuation committed with Compaction.Ended", and durable wake_pending state checks in SessionRecoveryTable and SessionInputTable.packages/core/test/session-runner.test.ts ownership tests include "never dispatches a provider after ownership changes", "never publishes streamed output after ownership changes", "never starts a local tool after ownership changes", and "never fails interrupted tools after ownership changes". The fenced local-tool fixture uses call ID "call-fenced", tool "echo", input { text: "must not run" }, and successor claim values including id: "tool-successor", owner_id: "successor", and expires_at: 60_000.packages/core/test/session-runner.test.ts coverage found includes global application-tool advertisement/execution for "application_context" with query "hello" and structured result { answer: "HELLO" }; graceful failure for an undecodable stored snapshot { invalid: { value: "bad" } }; direct baseline rebuilding after completed compaction; automatic compaction into a completed summary plus retained recent turn; and keeping automatic compaction ownership phase "unknown" until Compaction.Ended commits.packages/core/test/session-runner.test.ts uses summary "## Objective\n- Preserve recovery", deliberately dies with "crash after Compaction.Ended" when execution phase is "continue", expects SessionExecutionTable.phase to remain "continue", then switches to recoveryModel and continues with streamed text "Continued".