/goal-first sessions can still be omitted from codex resume when preview metadata stays empty
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.0or a currentmainbuild. - Start
codexin a local project directory, for example/Users/alice/projects/codex. - Make the first user interaction a
/goalcommand. 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 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.0at7cadca4c6e8c821fa7b75b50006b1806ccebdf1c
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.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗