Summary
A Codex CLI session whose first interaction is /goal can still be omitted from the interactive codex resume list, even though the thread exists and can be resumed directly by ID.
This looks related to #20792, but the remaining failure is a writer-side gap: the existing fix lets resume/list metadata use a persisted ThreadGoalUpdated event as the preview, but the live app-server goal update path can notify the client without persisting that event to the rollout.
Steps to reproduce
- Use
codex-cli 0.139.0 or a current main build.
- Start
codex in a local project directory, for example /Users/alice/projects/codex.
- Make the first user interaction a
/goal command. Example objective: echo 1,2,3 until 10.
- Let the goal complete.
- Quit the session. The CLI prints a direct resume hint such as
codex resume <thread-id>.
- From the same project directory, run
codex resume with no explicit thread ID.
Expected behavior
The goal-first session appears in the interactive resume list for the same cwd.
Actual behavior
The session can be missing from the interactive resume list, even though the thread row exists and has the expected cwd/source/provider/archive metadata. Direct resume by thread ID can still be available.
Investigation notes
I reproduced this on codex-cli 0.139.0. The affected thread had:
source = cli
model_provider = openai
cwd = /Users/alice/projects/codex
archived = 0
preview = ""
first_user_message = ""
The resume/list query excludes rows with an empty preview, so this thread is filtered out.
The corresponding rollout contained the session metadata and hidden goal context, but no durable EventMsg::ThreadGoalUpdated. That means the metadata sync path has no goal event to use as a preview later.
I checked the official refs:
origin/main at dfd03ea01bbec2613013b477fb82abc67534a7d7
rust-v0.139.0 at 7cadca4c6e8c821fa7b75b50006b1806ccebdf1c
Both have the same app-server listener behavior in codex-rs/app-server/src/request_processors/thread_lifecycle.rs: ThreadListenerCommand::EmitThreadGoalUpdated sends thread/goal/updated, but does not persist EventMsg::ThreadGoalUpdated into the rollout.
The earlier fix commit f10ddc3f13 (Use goal preview metadata for goal-first threads) is present, but it appears to cover the reader/indexing side. It does not cover this path where the goal event is never written.
Suspected fix
Persist EventMsg::ThreadGoalUpdated to the live thread rollout before/with the ordered thread/goal/updated notification. Then, even if the SQLite preview update happens before the thread metadata row exists, later rollout metadata sync can recover the preview from the persisted goal objective.
Summary
A Codex CLI session whose first interaction is
/goalcan still be omitted from the interactivecodex resumelist, even though the thread exists and can be resumed directly by ID.This looks related to #20792, but the remaining failure is a writer-side gap: the existing fix lets resume/list metadata use a persisted
ThreadGoalUpdatedevent as the preview, but the live app-server goal update path can notify the client without persisting that event to the rollout.Steps to reproduce
codex-cli 0.139.0or a currentmainbuild.codexin a local project directory, for example/Users/alice/projects/codex./goalcommand. Example objective:echo 1,2,3 until 10.codex resume <thread-id>.codex resumewith no explicit thread ID.Expected behavior
The goal-first session appears in the interactive resume list for the same cwd.
Actual behavior
The session can be missing from the interactive resume list, even though the thread row exists and has the expected cwd/source/provider/archive metadata. Direct resume by thread ID can still be available.
Investigation notes
I reproduced this on
codex-cli 0.139.0. The affected thread had:source = climodel_provider = openaicwd = /Users/alice/projects/codexarchived = 0preview = ""first_user_message = ""The resume/list query excludes rows with an empty preview, so this thread is filtered out.
The corresponding rollout contained the session metadata and hidden goal context, but no durable
EventMsg::ThreadGoalUpdated. That means the metadata sync path has no goal event to use as a preview later.I checked the official refs:
origin/mainatdfd03ea01bbec2613013b477fb82abc67534a7d7rust-v0.139.0at7cadca4c6e8c821fa7b75b50006b1806ccebdf1cBoth have the same app-server listener behavior in
codex-rs/app-server/src/request_processors/thread_lifecycle.rs:ThreadListenerCommand::EmitThreadGoalUpdatedsendsthread/goal/updated, but does not persistEventMsg::ThreadGoalUpdatedinto the rollout.The earlier fix commit
f10ddc3f13(Use goal preview metadata for goal-first threads) is present, but it appears to cover the reader/indexing side. It does not cover this path where the goal event is never written.Suspected fix
Persist
EventMsg::ThreadGoalUpdatedto the live thread rollout before/with the orderedthread/goal/updatednotification. Then, even if the SQLite preview update happens before the thread metadata row exists, later rollout metadata sync can recover the preview from the persisted goal objective.