Native goal continuation emits UUIDv4 turn IDs despite the app-server UUIDv7 contract
What issue are you seeing?
With native goals enabled, an idle thread with an active goal can start an automatic continuation whose public app-server turn ID is UUIDv4.
The app-server Turn contract explicitly says: Codex-generated turn IDs are UUIDv7. However, the automatic goal path calls try_start_turn_if_idle, which currently creates its TurnContext with Uuid::new_v4(). The resulting UUIDv4 is exposed by turn/started, item/*, turn/completed, persisted turn metadata, and active-turn control RPCs.
This is observable without sending another turn/start: the goal-created turn itself already violates the public ID contract. Clients can rely on the documented UUIDv7 property for timestamp ordering and correlation, so the difference is not only cosmetic.
Environment:
- Codex CLI:
0.146.0 - Platform:
Darwin 25.5.0 arm64 - Also present on public
mainated2f985a26eee9a59cde0fdefd20f69b45bc25f5
What steps can reproduce the bug?
- Start app-server with native goals and the experimental API enabled.
- Initialize a materialized thread.
- Set an active goal with
thread/goal/set, for example:
``json``
{
"method": "thread/goal/set",
"id": 3,
"params": {
"threadId": "<thread-id>",
"objective": "Inspect the workspace and report the result.",
"status": "active"
}
}
- Leave the thread idle so the goal runtime starts its automatic continuation.
- Read the next
turn/startednotification. - Inspect
params.turn.id. Its UUID version nibble is4, not7.
The current source path is:
codex-rs/ext/goal/src/runtime.rs: active goal continuation callsthread.try_start_turn_if_idle(...).codex-rs/core/src/session/inject.rs:try_start_turn_if_idlecallsnew_default_turn_with_sub_id(uuid::Uuid::new_v4().to_string()).codex-rs/core/src/tasks/regular.rs:turn/startedexposes thatTurnContext.sub_idas the lifecycle turn ID.
What is the expected behavior?
Every Codex-generated turn ID exposed through app-server should be UUIDv7, including turns started automatically by native goal continuation.
The turn/started, item/*, turn/completed, persisted metadata, and active-turn control APIs should continue using one stable ID, but that ID should satisfy the documented UUIDv7 contract.
Additional information
Related: #36866 reports a separate correlation defect when a later turn/start returns a provisional UUIDv7 submission ID while input is steered into an already-active goal turn. This report is narrower and independently reproducible: the native goal continuation produces a UUIDv4 public turn ID even when no later turn/start is sent.