Dashboard › opencode › Distillation
523e7583-f456-4544-92ce-3f933c8c1369["lore_tm_v1_GCwAHmIJ9H16-khT7_5g7eZPQjR76k8N_2HCVcIxO3g","lore_tm_v1_nwQSukDyiL0dOBGaTo8GSosdqENw4aEj_VAio-4VNJs","lore_tm_v1_mTzIHDdm7FZKyY4N2XsPxMPhshARX_W1-bF56c0rj1Y","lore_tm_v1_kDzkRvi-n94lOE33UWeKgYsey7Rjxn4Bdbb4w7Gjp2c","lore_tm_v1_vAK4LQ06h02YHuOky9y82dZb019F5TYsRurkKaNJHnM","lore_tm_v1_FZcWggJJ8PjFQljq99irGxhTpS3Yol5p9S04lW-rYK4"]
Date: Sep 17, 2026
packages/core/src/database/migration.gen.ts includes the new session-recovery schema changes, and packages/core/schema.json has ID 3bc49670-06d1-4eba-9a45-8c8128bdcf6f with sole prevIds entry f14a9b18-8207-487e-a3d3-227e629ba9ad; this directly follows the base schema whose ID is f14a9b18-8207-487e-a3d3-227e629ba9ad.python failed with /usr/bin/bash: line 1: python: command not found; subsequent schema-lineage verification succeeded through another command.packages/core/src/session/sql.ts was expanded from 176 to 263 lines, adding sql from drizzle-orm, check from drizzle-orm/sqlite-core, session wake-attempt constraints, and Drizzle definitions for the session_execution and session_recovery persistence structures.packages/core/src/session/execution/local.ts creates a process-unique ownerID with crypto.randomUUID(), stores active claims in Map<SessionSchema.ID, SessionExecutionClaim.Claim>, stores coalesced interruption completion in Map<SessionSchema.ID, Deferred.Deferred<void>>, and constructs a SessionRunCoordinator keyed by SessionSchema.ID.packages/core/src/session/execution/local.ts creates a random executionID, reads the latest assistant seq, and attempts an immediate transaction insert into SessionExecutionTable with phase "ready", assistant_seq defaulting to -1, and expiry now + SESSION_EXECUTION_LEASE_MS. .onConflictDoNothing() means a conflicting per-session claim causes the drain to return without running.packages/core/src/session/execution/local.ts selects the oldest recoverable SessionRecoveryTable row for that Session where wake_pending = true and recovery_error IS NULL, ordered by time_created then execution_id; its continuation_message_id is passed to input.run(claim, force, recoveryInputID).input.run(...) against repeated SessionExecutionClaim.renew(...) calls scheduled every SESSION_EXECUTION_LEASE_MS / 3. On exit, the implementation removes the matching in-memory active claim; successful execution clears the durable claim, while failure preserves claims in "cancelling"/"cancelled" and interrupted "safe" states and otherwise clears phases other than "unknown" or "continue".packages/core/src/session/execution/local.ts renews the claim first. It clears an already "cancelled" claim, dies unless the phase is "cancelling", clears when no assistant message is attached, and clears completed assistants after setting phase "cancelled" with assistant_message_id: null.SessionEvent.Step.Interrupted with sessionID, assistantMessageID, the current DateTime, and { type: "unknown", message: "Provider Step outcome unknown after interruption" }; the event commit changes the claim to "cancelled" and clears assistant_message_id, after which the claim is cleared. Missing EventV2.Service causes the defect "Event service unavailable during interrupted Session settlement".SessionExecutionLocal.interrupt(sessionID) joins an already-running interruption through its Deferred; without an active local claim it delegates to coordinator.interrupt(sessionID). With a claim it changes phase to "cancelling", races coordinator interruption/settlement against lease renewal every leaseDuration / 3, and treats SessionExecutionClaim.Lost as harmless only when no current SessionExecutionTable row remains for the Session.SessionExecutionLocal layer resolves a Session through SessionStore.Service, dies with Session not found: ${claim.sessionID} if absent, and runs runner.run({ ...claim, force, recoveryInputID }) with the location-specific layer returned by LocationServiceMap.Service.get(session.location). Its global node depends on Database.node, EventV2.node, SessionStore.node, and LocationServiceMap.node.packages/core/src/session/run-coordinator.ts defines each active entry with done, optional interruption, optional owner Fiber, optional exit, pendingWake, and stopping; a Map<Key, Entry<E>> serializes work per key, while FiberSet.makeRuntime permits different keys to execute concurrently.SessionRunCoordinator.run(key) joins an existing non-stopping execution by awaiting its done; if the entry is stopping, it waits and recursively retries. An idle explicit run creates an entry and calls drain(key, true), whereas wake(key) coalesces into pendingWake = true for an active entry or starts drain(key, false) when idle.pendingWake = true clears that flag and starts a successor drain with force = false on the same entry after Effect.yieldNow. Other settlement creates a fresh successor only when a wake remains pending; otherwise it deletes the active key and completes the original entryβs done deferred with the drain exit.SessionRunCoordinator.interrupt(key, cleanup) runs cleanup immediately if no owner exists, joins an existing interruption when present, marks the entry as stopping, clears prior pendingWake, interrupts the owner fiber, runs cleanup, and then either deletes the entry or starts a non-forced successor for work that arrived while stopping. It defects with Interrupted Session execution did not settle if the interrupted owner produced no stored exit, and propagates cleanup failure after internal settlement.