Skip to content

core: stabilize synthesized call output IDs#30327

Merged
bolinfest merged 1 commit into
mainfrom
pr30327
Jun 27, 2026
Merged

core: stabilize synthesized call output IDs#30327
bolinfest merged 1 commit into
mainfrom
pr30327

Conversation

@bolinfest

@bolinfest bolinfest commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Why

Response item IDs represent stable conversation identity. ContextManager::for_prompt repairs an unmatched call by synthesizing an "aborted" output in the disposable prompt projection, but that output previously had no ID. Assigning a fresh ID on every prompt build would make retries and resumes change otherwise identical model context and reduce prompt-cache reuse.

The concrete bug is that these normalization-created outputs bypass the regular item-ID allocation path. Even with item IDs enabled, a prompt could therefore contain an identified call paired with a synthetic output whose id was missing. This change closes that gap by deriving the output ID from the source call's item ID. For legacy calls that have no item ID, the output remains ID-less because there is no stable source identity to derive from.

The originating call already has a stable item ID under the item-ID model introduced in #28814. A prompt-only output can therefore derive stable identity from that call without mutating canonical history or persisted rollouts. This addresses the failure exposed by #30311 while keeping normalization read-only outside its detached prompt snapshot.

UUIDv5 is intentional here because it is the standard namespaced, deterministic UUID construction. Using the output kind and source call ID as the name produces the same UUID on every projection while keeping output kinds in separate name domains. UUIDv7 would introduce randomness and time, so keeping it stable would require persisting the synthetic repair. UUIDv5 uses SHA-1 internally, but this is only an identity mapping—not an authenticity or security boundary.

What changed

  • Derive a deterministic UUIDv5 ID for each synthesized call output from the source call item ID.
  • Use the Responses API prefix appropriate for function, custom-tool, tool-search, and local-shell outputs.
  • Preserve the existing insertion position immediately after the unmatched call.
  • Keep synthesized outputs prompt-only; no rollout, task-lifecycle, compaction, or raw-response behavior changes.

Testing

  • just test -p codex-core for_prompt_assigns_stable_id_to_synthetic_output_without_reordering_history
  • just test -p codex-core synthetic_call_output_id_is_stable_across_resumes
  • just test -p codex-core normalize_adds_missing_output
  • just test -p codex-core response_item_ids

@bolinfest bolinfest requested a review from a team as a code owner June 27, 2026 02:29
@bolinfest bolinfest changed the title core: persist repaired call outputs core: persist unmatched call output repairs Jun 27, 2026
@bolinfest bolinfest changed the title core: persist unmatched call output repairs core: stabilize synthesized call output IDs Jun 27, 2026

@rka-oai rka-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed - LGTM. Pretty funny how many places we've had to handle for item_id

@bolinfest bolinfest merged commit d2885dc into main Jun 27, 2026
50 of 69 checks passed
@bolinfest bolinfest deleted the pr30327 branch June 27, 2026 17:47
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants