Overview

Codex App Server Architecture

Date: 2026-08-29

This document describes the Codex runtime adapter. The provider-neutral runtime registry and cross-runtime invariants live in docs/architecture/AGENT_RUNTIME_ARCHITECTURE.md.

Goal#

The Codex integration runs AI coding work through a long-lived Codex App Server while Task Monki remains authoritative for local evidence and workflow state.

Task Monki owns:

  • task records and workflow phases;
  • isolated task worktrees and branches;
  • Git snapshots, dirty fingerprints, and diff artifacts;
  • GitHub branch, PR, check, review, and merge evidence;
  • local acceptance and Done transitions.

Codex owns:

  • App Server lifecycle;
  • provider threads and turns;
  • provider items, approvals, plans, settings, usage, and subagent events;
  • model catalog and supported reasoning efforts.

Process topology#

Task Monki uses one Codex App Server process per running app process.

flowchart LR
  UI["Renderer"] --> IPC["Typed IPC / API client"]
  IPC --> Service["TaskManagerService"]
  Service --> Orchestrator["AgentOrchestrator"]
  Orchestrator --> Adapter["AgentRuntimeAdapter"]
  Adapter --> Codex["CodexAppServerAdapter"]
  Codex --> RPC["CodexRpcClient"]
  RPC --> Server["resolved codex app-server stdio transport"]
  RPC --> Journal["Protocol journal"]
  Orchestrator --> RuntimeStore["SqliteAgentRuntimeStore"]
  Codex --> RuntimeStore
  Journal --> RuntimeStore
  Service --> TaskStore["SqliteTaskStore domain state"]
  Service --> Git["GitSnapshotService"]
  Service --> GitHub["GitHubService"]

Reasons:

  • App Server already supports many provider threads.
  • Authentication and model catalog are process-wide.
  • Per-turn working directory, sandbox, approval, network, model, and reasoning settings keep task execution scoped.
  • One process makes request correlation and recovery easier.

The integration follows the public Codex App Server contract: initialize once per connection, use version-matched generated schemas, stream thread/turn/item notifications, and gate experimental methods through negotiated capability. The stdio transport remains the production default; unsupported experimental WebSocket transport is not used.

Important records#

SqliteAgentRuntimeStore owns provider sessions, runs, items, interactions, observations, artifacts, and journal metadata. SqliteTaskStore owns Task and workflow domain records.

  • Task
    • User intent, workflow phase, current implementation-side run, worktree, projections, and evidence pointers. Composer-created tasks may also retain an opaque creation token and normalized-request fingerprint so a lost create response resolves to the same durable task rather than consuming its draft twice.
  • Repository
    • Stable domain identity plus the mutable local checkout path, availability, and observed Git metadata. Tasks and worktrees reference the repository ID.
  • Board
    • A named saved filter containing repository IDs, workflow phases, and a presentation color. It does not contain task membership or workflow truth.
  • RunRecord
    • One implementation, follow-up, retry, review, or provider-origin child run. Fork alternatives are represented as a new Task with its own implementation run, not as a run inside the source task.
  • AgentSessionRecord
    • Provider thread/session metadata. Primary sessions are used for implementation-side work. Review sessions use role: "REVIEW".
  • AgentServerInstance
    • Codex App Server process state, runtime version, schema hash, and status.
  • AgentProtocolJournal
    • Bounded append-only NDJSON segments for structurally redacted protocol debugging. Segment zero keeps the unnumbered server journal path; rotated references carry an explicit segment. Complete old segments are pruned at the per-server retention bound. Across every runtime, only the eight newest unreferenced terminal server records are retained; referenced and nonterminal servers are protected. The store removes a collected server record durably before its serialized journal cleanup, and startup reconciles safe orphan segments. Debug history is therefore neither a lossless provider transcript nor a permanent audit log.
  • StatusProjection
    • Compact UI-facing state derived from Task Monki domain events.
  • TaskAttachmentRecord
    • Path-free durable metadata for one app-managed task input. Immutable task-owned files live outside Git worktrees and are reverified before provider delivery.
  • RunRecord.attachmentSubmissions
    • Path-free evidence recorded only after turn/start succeeds. It identifies the verified selection, transport, and provider-turn correlation. It does not assert that the model read or used the files.

Codex adapter responsibilities#

The adapter must:

  • resolve, launch, and initialize a compatible App Server runtime;
  • probe Codex App Server support by capability rather than rejecting runtimes solely because their version is newer than the generated protocol baseline;
  • start the embedded App Server from Task Monki's core app settings. The default is local-only: apps disabled, web search disabled, and discovered MCP servers disabled through per-server runtime config overrides so local coding turns do not inherit unrelated user/plugin tool processes;
  • allow explicit settings opt-in for cached or live Codex web search, all configured Codex MCP servers, and Codex apps/connectors when a task needs those external tools in packaged Electron. Browser development forces all three modes off, rejects enable attempts, and aborts before App Server launch unless every enabled MCP entry can be discovered and explicitly disabled;
  • validate settings reported by thread start/resume/fork responses before persistence or a subsequent turn/review operation. In browser development, an unsafe response or live settings notification latches the adapter closed and stops the process before any storage wait;
  • avoid copying MCP environment values into stored App Server argv records when building those runtime config overrides;
  • opt out of high-volume provider delta notifications that Task Monki does not use as verified evidence;
  • discover account, models, supported reasoning efforts, and settings;
  • create, attach, and read provider sessions;
  • map native thread fork only through the optional session-fork operation;
  • start implementation, follow-up, retry, and shared read-only turns;
  • correlate provider thread IDs, turn IDs, item IDs, and request IDs;
  • materialize useful provider events into Task Monki records;
  • keep structurally redacted protocol traffic in the journal;
  • recover or locally reconcile when provider delivery is ambiguous;
  • resolve attachment records only from Task Monki storage, reverify their immutable task-owned files, use native localImage inputs when appropriate, and persist path-free submission evidence on the run without claiming model consumption.

The adapter must not:

  • decide Task Monki workflow phase by trusting provider text;
  • treat provider debug state as local evidence;
  • let detached review runs replace the implementation run;
  • expose experimental protocol features without explicit capability gates;
  • accept renderer-supplied or canonical managed-attachment paths, or claim generic App Server file or PDF support that the live protocol does not provide.

The complete attachment storage, delivery, cleanup, and security contract is in docs/architecture/ATTACHMENT_LIFECYCLE.md.

Attachment protocol boundary#

The generated Codex protocol currently exposes text, image, localImage, skill, and mention user inputs. It does not expose a generic file or PDF turn input. Task Monki therefore sends supported images through localImage after reverifying the immutable task-owned file. It provides supported text-like files through an untrusted-data prompt manifest. A qualified runtime uses the exact read-only managed path. Runtime discovery verifies the required permission-profile contract. Task-owned files remain outside Git worktrees and are reused across runs and reviews. PDFs, Office files, video, audio, archives, databases, and arbitrary binaries remain unsupported because they require a separately secured extraction or tool boundary.

For scoped execution, the adapter supplies a complete, collision-resistant permission profile through the existing thread-local config layer. It grants :minimal, the exact worktree, and exact verified task attachment files. For every restricted implementation or review session, the adapter also resolves and canonicalizes the worktree's Git directory and common Git directory, proves that the worktree is registered to the selected repository and uses that repository's common Git directory, and grants only that exact common directory read-only. The cwd and sole runtime workspace root remain the task worktree. Missing, symlinked, or unrelated Git metadata fails before provider input. Unrelated prunable worktree registrations are ignored; the active worktree must still resolve and match exactly. Restricted subprocesses use the already resolved concrete Git executable in a non-login shell, ignore system and user Git configuration, disable optional Git locks, and resolve Git's excludes file to the null device. Review sessions additionally isolate home and XDG configuration inside the worktree; implementation sessions retain their ordinary home environment so unrelated developer tools keep working. This avoids macOS xcrun cache failures and out-of-sandbox Git metadata access without adding writable roots. Full access instead selects Codex's documented :danger-full-access built-in; Task Monki does not label a worktree-scoped custom profile as unrestricted. Multi-agent V1/V2 and memories are disabled in both configurations. Runtime discovery proves the custom-profile surface with a disposable ephemeral thread before selecting a Codex binary.

Review, prompt refinement, Preview recipe generation, and Discourse use Task Monki's read-only policy. A Full access implementation selection does not make a review unrestricted. The review uses the isolated read-only profile plus the validated Git common directory.

Thread create, resume, fork, each ordinary turn, and recovery require the returned profile. They also require the sole runtime workspace root before provider input. Live settings drift terminates the provider and fails active runs. Attachment reads need no separate permission escalation or path expansion flow. Before each read-only thread starts or resumes, the adapter finds each enabled MCP server and disables it in that thread. If discovery fails, the turn does not start.

Codex review, prompt refinement, Preview recipe generation, and Discourse use ordinary turn/start requests. The adapter does not expose separate review or refinement workflow methods. For review, prompt refinement, and Discourse, AgentOrchestrator records repository state before delivery. It compares that state after terminal output and fails a changed or unreadable turn. Task Monki leaves detected repository changes in place as evidence. Preview recipe generation receives only an app-owned disposable evidence directory. It does not receive a repository root. PreviewRecipeGenerationService hashes the exact evidence file before and after the turn and rejects changed evidence.

An empty local Codex session can bind its first exact attachment scope before the first provider prompt. The store permits this only before materialization and before any provider turn ID exists.

Codex keeps that permission-profile identity after provider admission. It cannot replace it with a different exact attachment scope. When a Design turn selects a different reference set, Task Monki uses the existing native thread-fork operation. The fork keeps the conversation history but starts with a new, attested profile for only that turn's selected files. Task Monki creates a new local primary session for the forked thread. The old local session keeps its immutable provider thread identity. Both sessions stay in the same Task conversation lineage. If the reference scope is unchanged, it resumes the current thread as usual.

Full access remains available with or without attachments. It requires the runtime to attest the exact :danger-full-access profile and sole Task Monki worktree root. Full access does not claim to confine managed files. The user's network choice also remains unchanged. In packaged Electron, attachments do not override the user's Codex web search, MCP server, or app settings. Enabling an integration is an explicit decision to trust it with task content, including attachment content the agent supplies to it. Exact file permissions and path checks do not confine a same-user integration process or prevent an enabled external tool from transmitting content. Browser development retains its independent fail-closed rule that forces all three integration modes off.

Codex serializes a submitted localImage into an image data URL in its model-facing conversation history. Task Monki protocol journals replace attachment input and managed paths before durable storage. Codex history and provider telemetry can still retain delivered content, so Task Monki makes no complete-erasure claim. Normal task snapshots, interaction requests, approval decisions, and submission evidence remain path-free. External provider permission paths are redacted and declined. The Debug view shows the path-free submission record, not proof of model consumption.

Private managed storage, atomic synchronized writes, startup reconciliation, the HTTP/Vite token boundary, Electron sender guards, and transport resource limits are Task Monki responsibilities, not provider capabilities. They are defined in the attachment lifecycle document rather than inferred from Codex events.

Turn modes#

  • IMPLEMENTATION
    • First coding run for a task.
  • FOLLOW_UP
    • A new turn in the current task and worktree. This includes ordinary post-success follow-up, requested review changes, and explicit continuation of unfinished work. User-facing activity derives the correct action from the source run outcome rather than presenting every turn as a follow-up.
  • RETRY
    • Another attempt at the authoritative original implementation goal after an unsuccessful outcome. It reuses current state when safe, inspects Git and external outcomes, and does not imply a clean worktree reset.
  • REVIEW
    • Detached read-only quality gate. It inspects the current diff and stores projection.agentReview.
  • Provider-origin child runs
    • Observed child/subagent activity. These do not replace the task workflow.

Fork alternatives are intentionally not a RunRecord.mode. They are created by Task Monki as a new task with a separate worktree, branch, iteration, fresh provider session, and implementation run. The source task stores the alternative task id, and the alternative stores its source task/run ids for traceability. After creation, workflow and delivery actions on either task are independent. If worktree or run startup fails after the alternative task is stored, Task Monki leaves the alternative visible and blocked rather than silently hiding the partial candidate.

Read docs/workflows/AGENT_REVIEW_WORKFLOW_LIFECYCLE.md before changing review mode or follow-up behavior.

Local preview control plane#

Preview execution is a separate Task Monki-owned domain. It is not an agent run mode, workflow transition, or provider-evidence stream. When a recipe is missing, Task Monki can use one transient shared read-only agent turn to propose YAML. The provider output does not become Preview evidence and does not change Preview authority. The Preview manager, graph, native launcher, managed OCI and Compose runtimes, encrypted vault, loopback gateway, store records, stop-only reconciliation, and renderer projection have their own authority and shutdown boundaries.

The canonical current description is Preview Architecture. Repository authors and users should read the Preview Guide. Those documents define native and Compose behavior, capability approval, source generations, private inputs, attached dependencies, exact ownership, destructive cleanup, shutdown, and recovery without duplicating the App Server lifecycle here.

Graceful app quit fences new service actions and starts the Preview and Codex runtime owners' single-flight shutdown paths together. App Server shutdown cancels pending startup/restart work, drains RPC handling, removes process listeners, and terminates its portable child process tree. Preview shutdown independently cancels and joins generation work, watches, sockets, and cleanup. Preview events never update Task.workflowPhase or the agent projection.

The Codex process is also launched behind the application-wide IPC owner boundary. If the Electron process is killed before graceful shutdown runs, the owner stops the exact Codex process group. On the next start, the adapter still reconciles durable session, turn, interaction, and run evidence; it does not infer a provider result from process disappearance or resend ambiguous input.

Renderer and development-host trust#

The Electron renderer runs with context isolation and sandboxing, without Node integration. A local CSP permits only packaged renderer assets and the exact development WebSocket origin when applicable. Typed IPC rejects messages that do not originate from the expected main frame, and the main process blocks renderer navigation, popup creation, permission requests, and unexpected external targets.

The browser development host is a distinct loopback boundary. Its API requires a short-lived private token transferred to Vite through a one-use local lease, plus the exact Host, renderer Origin, and Fetch Metadata. It bounds JSON bodies and event streams and closes both during process shutdown. Browser-hosted agent runs are non-escalatable: network access and external Codex tools are forced off, and unsafe persisted settings are refused. Deterministic seed hosts keep the provider inert so synthetic provider records cannot start a live Codex process.

Renderer reads and invalidations#

The Electron IPC and browser HTTP transports expose the same client read boundaries:

  • a compact board snapshot containing task-card and actionable Inbox data;
  • a selected-task detail snapshot containing that task's ownership graph plus the compact cross-task Preview route catalog needed by the detail view.

Both reads are derived directly from the store's immutable published state. The full durable snapshot remains an internal service, test, and diagnostic boundary; it is not a renderer API. Board and detail requests have independent generations so an older completion cannot replace newer UI state. Opening or deleting a task always reconciles fresh task detail before the UI acts on worktree or Git evidence.

Task detail bounds run final messages and nested provider item/event payload strings to 128 KiB per field for display. Excerpt metadata identifies the original and displayed byte counts and whether a bounded retained artifact is available. Arbitrary provider fields do not claim a complete artifact. Durable records remain unchanged, and behavior-producing actions use structured findings or an explicitly loaded retained artifact rather than excerpt text.

App-update events are compact invalidations shared by Electron and browser transports. Output and routine activity are volume signals; authoritative state transitions, including ambiguous or recovery-required mutations, use run.state.updated and promptly invalidate the board plus matching open detail. App-scoped fallback invalidations refresh both the board and any open detail. An open detail also refreshes when another task changes Preview route availability because the detail owns the compact cross-task route catalog. The browser uses polling only while its EventSource connection is unavailable; native EventSource reconnect remains active, and a reopened stream stops the poller. Only direct-render events such as Preview recipe progress and Discourse deltas retain their bounded payloads in the client event projection.

Settings#

Task and review execution settings stored on task/run records include:

  • model;
  • reasoning effort;
  • sandbox;
  • approval policy;
  • approval reviewer;
  • network access.

Settings are validated against the live model catalog before a turn starts. An explicit model must match that catalog exactly, including after one forced refresh; only an omitted or default selection may use the provider default. Renderer settings update the exact runtime and model for implementation, prompt refinement, Preview recipe generation, and review. They do not replace a missing explicit Preview model with another model.

App-level user preferences are separate from SqliteTaskStore. The Electron and development hosts receive the same SQLite-backed AppSettingsStore from ApplicationPersistence. These settings include:

  • theme, sidebar, and mascot preferences;
  • first-launch setup completion;
  • default implementation, prompt-refinement, Preview-generation, and review models;
  • selected repository ID for the new-task default;
  • automatic installation of a downloaded desktop update on normal quit;
  • Codex external tool modes for web search, MCP servers, and apps;
  • external executable path preferences for Git, Codex CLI, and GitHub CLI; other registered runtimes use PATH or their documented environment override;
  • the persisted high loopback port used by the local preview gateway.

Empty executable paths mean Auto-detect. The main process resolves and probes executables live; resolved paths and detected versions are not persisted. Git and at least one ready agent runtime are required, while GitHub CLI is optional. The executable environment variables TASK_MANAGER_GIT_PATH, TASK_MONKI_CODEX_BIN, and TASK_MANAGER_GH_PATH act as debug overrides ahead of saved settings.

Repository records and boards belong to SqliteTaskStore, not app settings. All structured stores share one versioned application database. Startup applies forward SQLite migrations, then validates stored records before current-state reconciliation such as resolving an interrupted provider turn. See docs/architecture/PERSISTENCE_ARCHITECTURE.md for the storage boundary.

Codex Auto-detect status may display the resolved codex path, but that auto-discovered path is not passed as an explicit App Server runtime. In Auto mode, App Server startup leaves the executable unset so capability-based runtime resolution can scan all candidates and choose a compatible runtime. Saved custom paths, constructor overrides, and TASK_MONKI_CODEX_BIN are intentional and are passed explicitly.

After App Server startup resolves a compatible runtime, all Codex turns use that active server. They must not fall back to an unrelated codex earlier on PATH.

Runtime resolution#

Task Monki resolves a Codex executable before launching the long-lived App Server. Resolution checks explicit configuration first, then the TASK_MONKI_CODEX_BIN environment override, then every codex found on PATH, then known bundled runtimes such as Codex Desktop and the OpenAI Codex VS Code extension.

Automatic discovery does not fail on the first stale binary. Each candidate is probed with --version, codex app-server --help, an isolated temporary CODEX_HOME, initialize, and the JSON-RPC methods Task Monki needs. The newest compatible automatically discovered runtime is selected. An explicit configured runtime is treated as intentional and must itself be compatible. CODEX_HOME belongs to the versioned Codex child-environment contract; it is not part of Task Monki's portable process base and is never forwarded to OpenCode or ACP children. The selected runtime, all candidate versions, rejected candidates, missing capabilities, and probe failures are persisted on the App Server instance and shown only in provider diagnostics/debug surfaces.

The default transport is the documented local stdio App Server transport. Task Monki prefers codex app-server --stdio, uses --listen stdio:// when that is the supported stdio form, and can fall back to codex app-server only when the runtime documents default stdio but not a stdio flag.

Codex protocol detail:

  • Task Monki initializes both the compatibility probe and the selected App Server with experimentalApi: true. The generated protocol binding marks item/tool/requestUserInput as experimental, so this explicit negotiation is required for typed mid-turn questions. Task Monki's runtime capability catalog continues to report user-input requests as experimental; enabling the protocol family does not make unknown experimental requests supported.
  • Runtime compatibility also requires collaborationMode/list. Implementation, follow-up, and retry turns select Codex's interactive plan collaboration preset because that is the native surface that exposes request_user_input, while explicit developer instructions keep the turn in implementation mode with normal file and command work. Shared read-only turns use the ordinary turn protocol without interactive implementation controls.
  • turn/start has a first-class effort field.
  • thread/start, thread/resume, and thread/fork do not; they must pass model_reasoning_effort through the request config object.
  • thread/start allocates an empty thread on the current App Server but does not create a resumable rollout. The first turn/start therefore uses the newly attested thread directly; calling thread/resume first fails with no rollout found for thread id on the real runtime. The initial permission profile includes the exact storage-verified attachment paths needed by that first turn.
  • An empty thread is reusable only while the adapter retains its permission attestation for the current App Server generation. After a process restart or a pre-turn profile change, Task Monki replaces the empty thread with a new attested thread/start. This is safe because no prompt was submitted. Once Task Monki is ready to submit the first turn/start, it first persists the run as starting, then durably fences the session as potentially materialized. It drains queued provider notifications and rechecks the live App Server generation and exact permission attestation immediately before submission. Therefore a pending permission drift blocks provider input, while a lost acknowledgement or post-acknowledgement storage failure can only take the resume-and-reconcile path; it can never replace the thread and replay the prompt. A definitive JSON-RPC rejection may clear the fence only after queued evidence is drained, the local run still has no provider turn identity, and no provider notification has failed to materialize since the empty-thread attestation and submission boundary. Timeout, transport ambiguity, or failed evidence materialization retain it. Provider reads never downgrade a durable materialization fence merely because a transient response has no turns. The normal resume-and-attest path is required for every later turn.
  • Shared read-only sessions carry their selected reasoning effort in the same thread and turn settings as other ordinary Codex turns.

Mid-turn user input#

Codex user input is a typed server-request lifecycle, not an assistant-text convention. Task Monki accepts only item/tool/requestUserInput, correlates its thread, turn, item, and JSON-RPC request ID to the exact active run, and durably publishes one USER_INPUT interaction. The request may contain provider choices, an allowed custom answer, or free text. Secret-marked questions remain blocked because Task Monki has no secret-safe response channel.

An answer is returned once as the response to that same server request. The outbound response is journaled before the stdio write; a definitive pre-write failure restores the interaction to pending, while an uncertain write makes the run recovery-required and is never retried automatically. The interaction remains RESPONDING until App Server emits serverRequest/resolved. That notification also clears a request canceled by turn start, completion, or interruption before an answer. After the request is resolved, the exact run/session leave AWAITING_USER_INPUT only when no sibling interaction for the same server ownership remains. Turn completion and interruption retain their normal terminal authority.

Ordinary assistant prose is never parsed into an actionable question.

Recovery rules#

Provider delivery can be ambiguous. The app must handle:

  • a provider mutation that is acknowledged before Task Monki can durably save the provider session, turn identity, or attachment submission evidence;
  • stale provider turn IDs;
  • no active turn to interrupt;
  • App Server exit during interrupt or review;
  • late protocol errors after a server already reached a terminal state;
  • missing terminal events after interruption.

Recovery must prefer a truthful local state over an endlessly running UI. An acknowledged mutation followed by local persistence failure is not safe to replay as a new mutation: keep the run in recovery-required state for reconciliation. If first-turn acknowledgement persistence fails, the durable pre-submit materialization fence prevents empty-thread replacement and Task Monki stops the owning App Server process before returning the ambiguity. The process and client are fenced before Task Monki attempts to persist the final lost-process diagnostic; even diagnostic persistence failure cannot leave a reusable client alive. A process that cannot be confirmed stopped latches the supervisor lifecycle closed. Attachments remain immutable task-owned inputs and are reused after reconciliation; there is no disposable run-specific attachment copy. If the provider cannot confirm a terminal event, record the ambiguity and reconcile locally when the evidence proves the run is no longer active.

Inbound notifications follow the same no-resend rule. After the RPC client has journaled a notification, the adapter serializes its normalized storage writes on one inbound queue. A failed notification write increments the empty-thread materialization generation before recovery, so a concurrent first turn cannot cross that failed-evidence boundary. For a notification that identifies a Task Monki thread or submitted turn, the adapter then performs one targeted thread/resume snapshot reconciliation on that run; it never replays turn/start. A terminal snapshot retries the idempotent final-artifact and terminal-event materialization, while a live or uncertain snapshot leaves an explicit recovery-required run. Notifications emitted for that same thread or turn while its snapshot recovery is in flight remain serialized, but they do not start a nested recovery loop; the resume response is the authoritative recovery snapshot. Concurrent notifications for other runs retain their own recovery path.

If that targeted path cannot durably leave the run terminal or recovery-required, the adapter latches readiness failed, clears its live attestations and deadlines, and stops the owning App Server through a one-way supervisor fence. The fenced generation is not automatically restarted. Only after the process boundary is closed does Task Monki best-effort record runtime loss for every run and pending interaction owned by that server. Failures in that loss sweep are diagnostic-only and do not recursively invoke notification recovery; a new application/runtime supervisor must reconcile the durable records later. Thus a dropped terminal write cannot leave a reusable provider generation silently running behind a local RUNNING record.

Intentional shutdown uses the same serialized runtime-loss settlement before it returns. On application startup, active runs and actionable interactions are reconciled even when their owning server record already reached EXITED, FAILED, or LOST; a terminal process record never makes active ownership safe by itself.

An active Codex goal may start a continuation turn when thread/resume reattaches an interrupted rollout. During startup reconciliation, Task Monki therefore gives the exact recovery run temporary ownership of that session, adopts a unique provider-reported live continuation, and records the run as recovered and running. It does not close the old turn and offer a retry while that continuation exists. The correlation is process-local and remains scoped to the unresolved recovery until a continuation arrives or provider goal evidence becomes terminal; persisted provider turn identity remains the durable owner after adoption.

Verification#

Use these before merging App Server or workflow changes:

npm run typecheck
npm test
npm run build
npm run check:codex-protocol
git diff --check

Was this page helpful?