Dashboard › opencode › Distillation
b9b73fb5-0b62-4140-a3ee-e4d6e4257fef["lore_tm_v1_qbIAE1Xpyia9eHS_HUCBu796XuVCUdQTYm5fCNuTl2s","lore_tm_v1_c2gWcoSJLOSDqc9ErungzLKZFuz55ZgigkfWZBQZMNQ","lore_tm_v1_SEtvAUx6B615eczmxkKpvKgu5_X-lUjOajTewctRPvk","lore_tm_v1_nDCtxtAY0-sf-KJMbBWrM9UzS0DiGzQQA68ZtFTY50s","lore_tm_v1_N7WFh3CRTWBKymb155Zj7od2XXehj6nUcjgNytaBePA","lore_tm_v1_TU7RuIXDYdrckX21fz7LQ29JDaj3ulbDoZSAilhEmlk","lore_tm_v1__B68XByxYH5M9zl4-hLu70k9VmN0C_jVa76N_v5tEfM","lore_tm_v1_oNjG3lKZxppG9RUMdH1n6-EonUskHEsCQtSGrk0wRNU","lore_tm_v1_dPwF8jwMUqP5iZsoTJwTBWhwCmJU-DT2naf3I4cUpAo"]
Date: Sep 17, 2026
packages/core/src/session/sql.ts defines MAX_WAKE_ATTEMPTS = Number.MAX_SAFE_INTEGER; SessionTable.wake_attempts defaults to 0 and is constrained by session_wake_attempts_check to 0..MAX_WAKE_ATTEMPTS.SessionInputTable in packages/core/src/session/sql.ts includes wake_pending as a non-null boolean defaulting to false; index session_input_wake_pending_promoted_session_idx covers (wake_pending, promoted_seq, session_id).SessionRecoveryTable in packages/core/src/session/sql.ts stores session_id, execution_id, nullable assistant_message_id, unique continuation_message_id, phase "ready" | "unknown" | "continue", wake_pending defaulting to true, wake_attempts defaulting to 0, nullable recovery_error, and time_created. Primary key session_recovery_pk is on execution_id; session_recovery_wake_attempts_check constrains attempts to 0..MAX_WAKE_ATTEMPTS.session_recovery_wake_pending_error_attempts_created_execution_idx on (wake_pending, recovery_error, wake_attempts, time_created, execution_id); continuation_message_id has unique index session_recovery_continuation_message_idx.SessionExecutionTable in packages/core/src/session/sql.ts stores id, unique session_id, owner_id, nullable assistant_message_id, assistant_seq defaulting to -1, time_created, expires_at, nullable recovery_error, and phase "ready" | "safe" | "unknown" | "continue" | "cancelling" | "cancelled". It uses primary key session_execution_pk, unique index session_execution_session_idx, owner index session_execution_owner_idx, recovery index session_execution_recovery_scan_idx on (recovery_error, expires_at, time_created, id), and check session_execution_phase_check.packages/core/src/session/sql.ts sets SESSION_EXECUTION_LEASE_MS = 30_000.packages/core/src/database/migration/20260914170650_session-recovery.ts, ID 20260914170650_session-recovery, adds session_input.wake_pending, adds session.wake_attempts, creates session_execution and session_recovery with their foreign keys/checks/indexes, and uses the exact numeric upper bound 9007199254740991 for wake attempts.packages/core/src/database/migration.gen.ts registers ./migration/20260914170650_session-recovery as the final entry in the generated migration list.packages/core/schema.json is SQLite schema version "7" with ID "3bc49670-06d1-4eba-9a45-8c8128bdcf6f" and previous ID "f14a9b18-8207-487e-a3d3-227e629ba9ad".packages/core/src/session/compaction.ts uses defaults DEFAULT_BUFFER = 20_000, DEFAULT_KEEP_TOKENS = 8_000, TOOL_OUTPUT_MAX_CHARS = 2_000, and SUMMARY_OUTPUT_TOKENS = 4_096; configuration documents can override compaction.auto, compaction.buffer, and compaction.keep.tokens.## Objective, ## Important Details, ## Work State with ### Completed, ### Active, and ### Blocked, then ## Next Move with two numbered actions, and ## Relevant Files. Rules require terse bullets, every section even if empty, exact paths/symbols/commands/errors/URLs/identifiers, and no mention of compaction or the summary process.serializeToolContent() in packages/core/src/session/compaction.ts joins text content directly and renders non-text items as [Attached ${item.mime}: ${item.name}] when named or [Attached ${item.mime}] otherwise; truncate() limits serialized tool and shell output to 2_000 characters and appends \n[truncated].[User], [Assistant], [Assistant reasoning], [Assistant tool call], [Tool result], [Tool error], [System update], [Synthetic context], and [Shell]; user files are rendered as [Attached ${file.mime}: ${file.name ?? file.uri}].select() in packages/core/src/session/compaction.ts excludes messages of type "compaction", walks backward to retain recent serialized conversation within the configured token budget, and returns separate head and recent strings.buildPrompt() either requests a new anchored summary or combines <prior-summary> with newer <conversation> content; update instructions say newer conversation wins conflicts, unfinished objectives/directives/decisions/workstreams must carry forward, completed work moves to Completed, resolved blockers are updated, and Objective/Next Move reflect current state.compactIfNeeded() skips compaction when automatic mode is disabled, model context is absent/nonpositive, or estimated { system, messages, tools } usage is within context - Math.max(output, config.buffer); otherwise it delegates to compactAfterOverflow().compactAfterOverflow() caps summary generation at 4_096 tokens, rejects prompts larger than context - summaryOutput, publishes SessionEvent.Compaction.Started before streaming and SessionEvent.Compaction.Ended after a valid summary, invokes optional beforeStream, eventCommit, and commit hooks, supplies no tools to the summary LLM, and returns false on LLM.Error, provider-error events, empty output, or invalid capacity.packages/core/src/session/context-epoch.ts requires a SessionExecutionClaim.Claim for initialize() and prepare(); both write paths use SessionExecutionClaim.transaction(...) to guard context-epoch insertion, replacement, and snapshot advancement.SessionContextEpoch.prepare() concurrently resolves the live system context, stored SessionContextEpochTable row, and SessionHistory.latestCompaction(...) with concurrency: "unbounded". With no stored row it initializes and inserts a generation; otherwise it decodes SystemContext.Snapshot, mapping failure to ContextSnapshotDecodeError.SystemContext.replace(...) when a newer compaction sequence exceeds stored.baseline_seq; otherwise it uses SystemContext.reconcile(...). "Unchanged" and "ReplacementBlocked" preserve the stored baseline; "ReplacementReady" replaces baseline/snapshot using the compaction sequence or EventV2.latestSequence(...); an incremental update publishes SessionEvent.ContextUpdated and advances the snapshot in its commit callback.SessionContextEpoch.initialize() returns without changes when an epoch already exists; insertion records baseline, snapshot, and the current EventV2.latestSequence(...) as baseline_seq. reset() deletes the sessionβs row, while failed replace() or advance() operations die with "Context Epoch not found".packages/core/src/session/runner/index.ts defines SessionRunner.RunError as LLMError | SessionRunnerModel.Error | MessageDecodeError | ContextSnapshotDecodeError | SystemContext.InitializationBlocked | ToolOutputStore.Error.SessionRunner.Interface.run() accepts { sessionID, force, executionID, ownerID, recoveryInputID? } and returns Effect.Effect<void, RunError>; its contract is to run one local continuation from already-recorded session history, drain eligible durable work, and perform one provider attempt for explicit runs even when no work is eligible. The service identifier is "@opencode/v2/SessionRunner".