Dashboard › opencode › Distillation
c7a4bedc-b5d7-4a73-ad91-35e8cf6c05d2["lore_tm_v1_KdEft2wV3IVwTAvfS5USQE-yUdLEGo9j4-CYCijxMrQ","lore_tm_v1_-fIEPt6UikevuaLkLHS8o9DBHre10WnJyn-JsLOBD4w"]
Date: Sep 14, 2026
/home/byk/Code/opencode/packages/schema/src/v1/permission.ts defines ID as a branded string beginning with "per" and adds ID.ascending(id?), which uses the supplied ID or generates "per_" + ascending()./home/byk/Code/opencode/packages/schema/src/v1/permission.ts defines Action as "allow" | "deny" | "ask"; Rule as { permission: string, pattern: string, action: Action }; and Ruleset as Schema.Array(Rule).Request is { id: ID, sessionID: SessionID, permission: string, patterns: string[], metadata: Record<string, unknown>, always: string[], tool?: { messageID: string, callID: string } }; AskInput contains the same fields but makes id optional and adds ruleset: Ruleset."once" | "always" | "reject"; ReplyBody is { reply: Reply, message?: string }; ReplyInput is { requestID: ID, ...ReplyBody.fields }; and Approval is { projectID: Project.ID, patterns: string[] }./home/byk/Code/opencode/packages/schema/src/v1/permission.ts:61-66 defines permission.asked with Request.fields and permission.replied with { sessionID: SessionID, requestID: ID, reply: Reply }, exporting both through Event and inventory(Asked, Replied)./home/byk/Code/opencode/packages/opencode/src/node.ts:1-4, with build entry /home/byk/Code/opencode/packages/opencode/script/build-node.ts:15-21.Server.listen() constructs the Node listener and route/service graph (server/server.ts:73-138); 2. an instance-routed request lazily loads its directory and runs InstanceBootstrap.run (instance-context.ts:23-34, project/instance-store.ts:45-63); 3. bootstrap loads config, initializes plugins first, then initializes LSP, sharing, formatting, VCS, snapshots, and project services concurrently without inspecting or resuming sessions (project/bootstrap.ts:32-46).POST /session/:sessionID/message invokes SessionPrompt.prompt, while prompt_async forks the same operation into listener scope and returns immediately (groups/session.ts:78-105, handlers/session.ts:295-329); 5. SessionPrompt.prompt resolves files/resources, runs plugin hooks, persists the user message and each part separately, touches the session, optionally replaces permissions from deprecated tools, returns for noReply, and otherwise enters loop (session/prompt.ts:635-670, 995-1071).SessionRunState.ensureRunning acquires a per-directory in-memory Runner, and concurrent same-process calls join its Deferred rather than starting another run (session/run-state.ts:35-69, effect/runner.ts:115-138); 7. each loop iteration reloads projected history, determines latest user/assistant/task state, persists a new incomplete assistant message, resolves tools/system context, and calls SessionProcessor.process (session/prompt.ts:1081-1286); 8. SessionProcessor.process consumes llm.stream, persists stream events, retries retryable failures, runs cleanup, and completes the assistant message (session/processor.ts:641-697).1 (packages/schema/src/v1/session.ts:502-507, 571-630) and that each event plus its SQL projection commits in one database transaction (packages/core/src/event.ts:236-353).time.completed; and tool parts in pending or running state. Schema references: packages/core/src/session/sql.ts:22-98, packages/core/src/event/sql.ts:4-24, and packages/core/src/session/projector.ts:260-327.prompt_async returns after forking rather than waiting for a durable admission barrier.message.part.delta text and reasoning deltas are non-durable; only start/end or cleanup updates persist accumulated text, so a hard crash can leave an empty or stale partial text/reasoning part (packages/schema/src/v1/session.ts:632-641, session/processor.ts:500-545).Deferreds whose events are non-durable (permission/index.ts:18-26, 46-65, schema/src/v1/permission.ts:61-65); background jobs are also instance-local memory (background/job.ts:17-31).SessionRunState, a per-directory Map<SessionID, Runner> whose states are Idle, Running, Shell, and ShellThenRun (session/run-state.ts:35-49, effect/runner.ts:33-38); and SessionStatus, a per-directory public-status map holding busy or retry, where idle removes the entry and absence means idle (session/status.ts:26-48).idle, busy, and retry, with no durable status-event declaration (packages/schema/src/session-status-event.ts:9-49), while assertNotBusy checks the runner map rather than the public status map (session/run-state.ts:71-75).core/src/database/database.ts:22-36, server/routes/instance/httpapi/server.ts:212-269, core/src/session/projector.ts:210-233), but projector registration only adds callbacks for future events and does not replay or scan history (core/src/event.ts:615-620).server/server.ts:1, server/init-projectors.ts:1-3, and server/projectors.ts:1. No startup code lists incomplete V1 assistant messages, reconciles pending/running tools, reconstructs statuses or runners, invokes SessionPrompt.loop, re-establishes pending permissions, or claims durable execution ownership.session/run-state.ts:39-47, session/processor.ts:553-610); listener.stop() closes listener scope and can trigger cleanup (server/server.ts:172-191), but a crash or forced process exit cannot.SessionProcessor retries the complete llm.stream consumption for retryable network failures, timeouts, rate limits, and 5xx responses (session/processor.ts:649-690, session/retry.ts:31-40, 183-205). A provider may already have received the request—or a tool may already have executed—before the stream failure is observed, yet the retry has no durable provider-attempt ID or idempotency key.session/llm.ts:271-280); wrappers execute real operations without a durable invocation ledger (session/tools.ts:92-132); and normal completion relies on a later tool-result stream event to persist the result (session/processor.ts:383-413).pending or running; 5. manual continuation or user retry may repeat the logical operation. Model conversion labels stale calls interrupted only in reconstructed model input and neither proves whether the effect occurred nor durably reconciles the part (session/message-v2.ts:349-360).loop as high risk: it reads incomplete history but creates a new assistant message and sends another provider request rather than resuming the original stream/attempt (session/prompt.ts:1081-1098, 1186-1219), allowing the model to repeat an interrupted tool call under a new call ID.running even though the command already changed external state (session/prompt.ts:470-518, 528-583).pending/running tool parts; 2. persist them as aborted/interrupted while preserving captured output and timestamps; 3. emit idle status; 4. never automatically call SessionPrompt.loop for those records. This repairs the transcript but does not continue the prompt.admitted, started, and terminal; 2. make prompt_async return only after admission commits; 3. add a database-backed session execution lease with fencing to block concurrent Node processes; 4. restart only admitted records having no provider attempt; 5. treat every started but non-terminal provider attempt as uncertain and never automatically replay it unless the provider supports an idempotency key or resumable request; 6. add a durable tool-invocation ledger keyed by execution attempt and tool-call ID, commit intent before execution and result before returning, never rerun uncertain state-changing calls, and retry only tools explicitly classified as idempotent.session_input table demonstrates the proposed admission-record shape but belongs to the current session runtime rather than V1 (packages/core/src/session/sql.ts:140-165).repo-setup skill was unavailable, so the assistant directly read the repository’s AGENTS.md, CONTRIBUTING.md, package manifest, server entry points, and relevant source.