Skip to content

[spike] Codex session continuity — verify resume-by-id is viable before building it #730

Description

@serge-ivo

Reframed from an implementation issue to a spike (2026-08-22) after an adversarial review found engine-side Codex resume is unreliable upstream and in tension with this repo's own decisions. Do NOT build the resume path until this spike passes.

Depends on #729 (the --json thread.started id is the only source of a session id).

Why this is a spike, not a build

Three independent problems, none of which #730's original "just persist the id and call resume" plan addressed:

  1. Engine-side resume may silently no-op. codex exec resume <id> with an id captured from a --json exec run is reported upstream to silently start a fresh thread with no prior context (openai/codex#15538), and exec sessions may be treated as ephemeral so the id is not reliably resumable (openai/codex#3817). A resume that exits 0 but starts cold is worse than starting clean — it's confidently wrong.

  2. The codebase already measured and rejected Codex resume. workers/api/src/lib/coding-engines.ts (DEFAULT_ENGINES comment) and docs/coding-engines.md § "Why no shipped preset resumes" document a measured failure: codex exec resume --last followed an unrelated codex exec that ran in the same directory. Session-id pinning is the proposed answer to that specific failure — the spike must prove it actually avoids it, not assume it.

  3. The argv contract has no slot for a resume subcommand. runOneShot (headless.ts) is "preset command as prefix + turn text appended as the final positional." codex exec resume <id> "<turn>" inserts a subcommand and a positional between the prefix and the turn text. cmdArgs is computed once at construction and is immutable per session, so this cannot be done by editing the preset — it needs a dedicated resume argv path. The docs also note codex exec resume accepts --dangerously-bypass-approvals-and-sandbox but not --sandbox <mode>, so the write-flag would have to change too.

Strategic tension with #693 (must be resolved, not ignored)

#693 ("The platform owns the conversation — the engine's own memory is an optimisation") explicitly names Codex's lack of continuity and proposes the platform seed each turn from coding_timeline, demoting the engine's own session store. #730 does the opposite — it persists a Codex-owned session id in the runner's state file and leans on the engine's resume, re-creating for Codex exactly the machine-bound, opaque continuity #693 wants to move away from.

Decision recorded: pursue engine-side resume only as a pragmatic stopgap because #693 is deferred (P3: later), and revisit onto the platform-owned store when #693's seed-from-timeline slice lands. If the spike below fails, prefer #693's approach outright rather than shipping an unreliable resume.

Spike deliverables (this issue)

  1. On a machine with a known codex-cli version (record it), run two consecutive codex exec --json turns where the second resumes the first by captured thread_id. Prove context carries — not that the command exits 0. Capture the raw JSONL of both turns as a fixture.
  2. Confirm whether codex exec resume <id> --json "<turn>" accepts the flags/positions we need (write flag, --json, turn text) without conflict.
  3. Repeat test (1) after an unrelated codex exec runs in the same CWD — reproduce or rule out the --last-class hijack for the explicit-id form.

Exit criteria

Refs: #729, #693, #556; upstream openai/codex#15538, #3817.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3: laterDesign, strategy, or deferred pending a decision or demandcoderThe Coder wedge agent (#68) — Engine, Pilot, Co-pilot, Loop, OverseerenhancementNew feature or requestrunnerpackages/browser-runner + packages/cli — ships only via an npm publish

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions