# Codex Runtime Consolidation

> Canonical path: `specs/daemon/codex-runtime-consolidation.md`
> Related specs: [daemon.md](daemon.md), [../message/delivery-runtime.md](../message/delivery-runtime.md), [../message/rewind.md](../message/rewind.md), [../../docs/codex-app-server-native-protocol.md](../../docs/codex-app-server-native-protocol.md)
> Status: design-approved
> Date: 2026-04-25
> Outcome: implemented. Post-consolidation, `codex` is the only public Codex runtime ID and uses the app-server JSON-RPC implementation. The old daemon compatibility gate for distinguishing one-shot Codex CLI from app-server-as-`codex` has been removed; references below to two Codex IDs describe the pre-consolidation design-time state and durable data migration requirements.

## 1. Problem

At design time, AgentTeam exposed two Codex runtime implementations:

| Runtime ID | Design-time meaning |
|------------|-----------------|
| `codex` | one-shot Codex CLI driver |
| `codex-app-server` | long-lived Codex app-server JSON-RPC driver |

This split is no longer the intended product model. Codex is one product from the user's point of
view, and the app-server implementation is the correct AgentTeam runtime because it supports native
thread / turn protocol control, thread rollback, idle-time compaction, and structured streaming.

The design-time split was visible across product docs and code:

- Product/runtime docs list both Codex implementations: `SPECS.md`, `docs/tech_design.md`.
- Daemon runtime IDs are defined in `desktop/internal/agent/runtime.go`.
- Runtime detection reports both `codex` and `codex-app-server` in `desktop/internal/channel/agentteam/channel.go`.
- Server-side runtime validation accepts both IDs in `internal/store/runtime_public.go`.
- Rewind capabilities treat `codex-app-server` as supported and `codex` as unsupported in `internal/core/rewindcaps/rewindcaps.go`.
- Web runtime pickers expose both IDs in `web/src/agentteam/workspace/agentOptions.ts` and desktop dashboard helpers.

Leaving both IDs in place creates product confusion and makes runtime capability checks depend on
which Codex name a caller chose instead of the effective implementation.

## 2. Goals

- Make `codex` the single public Codex runtime ID.
- Make `codex` use the current `codex-app-server` implementation and semantics.
- Remove the old one-shot Codex CLI runtime from supported runtime choices.
- Migrate existing durable rows so both old Codex IDs converge to `codex`.
- Keep rewind recovery behavior stable for the app-server implementation.

## 3. Non-goals

- Do not preserve the old one-shot Codex CLI as a hidden or legacy runtime.
- Do not keep `codex-app-server` as a user-visible or API-visible runtime alias after migration.
- Do not change the app-server JSON-RPC protocol itself.
- Do not rename the existing recovery strategy string `codex_app_server_turns`; it describes the recovery mechanism and is already stored in recovery points.
- Do not keep an app-server-as-`codex` capability bit as a long-lived protocol requirement.

## 4. Proposed Behavior

### 4.1 Runtime identity

`codex` becomes the canonical and only supported Codex runtime ID. In product surfaces, API payloads,
daemon ready payloads, machine runtime capabilities, Role defaults, and Agent records, `codex`
means:

- long-lived `codex app-server --listen stdio://` process
- native `turn/start` delivery for idle / new-turn message bodies
- active-turn pending queue plus stdin notification for inbound message bodies
- native `thread/rollback` restore
- idle compaction through `thread/compact/start`
- JSON-RPC notification streaming

The old one-shot `codex exec --json` driver is removed from the supported runtime set.

### 4.2 Ready payload behavior

The daemon no longer advertises a Codex migration capability. A ready payload that reports `codex`
means the canonical Codex app-server runtime. The server filters ready runtime capabilities by the
current supported runtime catalog:

1. Accept `codex` as the canonical Codex runtime without requiring an additional capability bit.
2. Ignore unsupported runtime IDs such as the historical `codex-app-server` public alias.
3. Apply the same filtering to `runtimeDefaults`; defaults for ignored runtime IDs must not be
   copied onto `codex`.
4. Deduplicate repeated runtime IDs after trimming whitespace.

This keeps the daemon protocol aligned with the post-consolidation runtime model instead of
retaining a permanent compatibility branch for the one-shot Codex CLI era.

### 4.3 Runtime detection

New daemon detection must only report `codex` when the app-server entrypoint is available:

```text
codex app-server --help
```

Finding a `codex` binary alone is not enough. The machine runtime capability represents AgentTeam's
runtime implementation contract, not just a binary name.

### 4.4 Driver mapping

The daemon driver factory should map `agent.TypeCodex` to the current app-server driver. The old
Codex CLI driver and tests should be removed or rewritten around the new canonical behavior.

Implementation may either rename `CodexAppServerDriver` to `CodexDriver` or keep the implementation
name as an internal detail. Public runtime strings must not expose `codex-app-server`.

### 4.5 Data migration

The migration must update every durable public runtime field:

- `agents.runtime`
- `workspace agent installations.runtime`
- `machine_runtime_capabilities.runtime`

Rules:

1. Rows with `runtime='codex-app-server'` become `runtime='codex'`.
2. Existing rows with `runtime='codex'` remain `runtime='codex'`, but their old CLI runtime state is incompatible with app-server resume.
3. Existing `agents.runtime='codex'` rows must start fresh under app-server semantics when handled by daemons that advertise `agent:local-session-resume`. Runtime start/resume for those daemons must ignore legacy persisted `agents.session_id`, `agents.current_instance_id`, status/activity mirrors, and `agent_instances`; daemon-local runtime state decides whether resume is possible. During the daemon upgrade window, daemons that do not advertise `agent:local-session-resume` may still receive the sparse `agents.session_id` compatibility mirror described in `specs/daemon/daemon.md`. A one-time migration may clear legacy mirror fields for hygiene, but normal daemon telemetry must not repopulate them except for that explicit legacy session mirror.
4. Existing `agents.runtime='codex-app-server'` rows must preserve app-server-compatible session/thread state while renaming the runtime to `codex`.
5. Existing Codex-family rows in `machine_runtime_capabilities` may be removed during migration. New daemon ready payloads expose canonical `codex` runtime capability on the authenticated WebSocket connection; persisted capability rows, if kept as last-known diagnostic metadata, must only change when the reported value changes and must not be replaced on every `ready`.

The migration must handle uniqueness on `(machine_id, runtime)` when both old rows exist for the
same machine.

### 4.6 Rewind capability

After consolidation, `rewindcaps.ForRuntime("codex")` must return the current app-server capability:

- supported: true
- strategy: `codex_app_server_turns`
- detached restore: true
- live restore: true

The recovery strategy string and recovery ref schema remain unchanged. They describe the recovery
mechanism, not the public runtime ID.

### 4.7 Documentation and UI

User-visible surfaces should display one Codex option:

| Runtime ID | Label |
|------------|-------|
| `codex` | Codex |

Docs must stop describing `codex` as a CLI runtime and stop listing `codex-app-server` as a separate
supported runtime. Internal architecture docs may mention "app-server implementation" when
explaining the mechanism.

## 5. Implementation Boundaries

The change spans these boundaries:

- Daemon runtime model: `desktop/internal/agent/runtime.go`
- Daemon driver factory and app-server driver: `desktop/internal/agent/driver.go`, `desktop/internal/agent/driver_codex.go`
- Daemon ready and runtime detection: `desktop/internal/channel/agentteam/channel.go`
- Server ready handling and start guard: `internal/api/daemon/protocol.go`
- Server runtime validation and public agent APIs: `internal/store/runtime_public.go`
- Rewind capability registry: `internal/core/rewindcaps/rewindcaps.go`
- TiDB schema migration and bootstrap schema: `internal/tidb/migrations/`, `internal/tidb/bootstrap.sql`
- Web runtime choices and i18n labels: `web/src/agentteam/workspace/agentOptions.ts`, locale files, desktop dashboard helpers
- Product and runtime docs: `SPECS.md`, `docs/tech_design.md`, `specs/message/rewind.md`, daemon docs

## 6. Error Handling

Unsupported runtime IDs in ready payloads are filtered rather than persisted. Start-time failures
should reflect current runtime state, such as the target machine being offline or the agent already
running, rather than historical Codex CLI compatibility checks.

## 7. Validation Strategy

Required regression coverage:

- Runtime validation accepts `codex` and rejects `codex-app-server`.
- New daemon detection reports `codex` only when `codex app-server --help` succeeds.
- Daemon ready payloads expose `codex` on the authenticated connection without requiring a Codex migration capability; any persisted last-known runtime metadata is updated only on value change.
- Ready payloads ignore unsupported `codex-app-server` entries and do not copy their defaults onto `codex`.
- Manual `agent:start` and auto-wake for `codex` do not depend on a Codex migration capability.
- Existing `codex` agent rows are migrated to fresh app-server state.
- Existing `codex-app-server` agent rows are renamed to `codex`.
- Rewind planning treats `codex` as app-server-capable.
- Web runtime pickers show one Codex option.

Documentation-only changes do not require runtime regressions, but the implementation must run the
relevant Go and web tests before completion.
