From 2fc0e3d1aa63f892fce8dc3e31423f4110383e4c Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Tue, 14 Jul 2026 21:54:40 -0700 Subject: [PATCH] fix(codex): guard the continuation nudge against role-alternation violations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the salvaged #63690: when the interim assistant message is too empty to append (no content and no reasoning of any kind), the last message in history is still the prior user/tool turn — appending the user-role nudge there would create a user→user or tool→user sequence that strict providers reject. Only append the nudge when the last message is an assistant turn. Also add IpastorSan to AUTHOR_MAP. --- agent/conversation_loop.py | 13 ++++++++++++- scripts/release.py | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/agent/conversation_loop.py b/agent/conversation_loop.py index 90173395ded9..6fe9dc68b320 100644 --- a/agent/conversation_loop.py +++ b/agent/conversation_loop.py @@ -4506,7 +4506,18 @@ def run_conversation( and _last_msg.get("role") == "user" and _last_msg.get("content") == _CODEX_INCOMPLETE_NUDGE ) - if not _already_nudged: + # Alternation guard: the nudge is a user-role message, + # so it may only follow an assistant message. When the + # interim was too empty to append (no content AND no + # reasoning), the last message is still the prior + # user/tool turn — appending the nudge there would + # create a user→user / tool→user sequence that strict + # providers reject. + _last_is_assistant = ( + isinstance(_last_msg, dict) + and _last_msg.get("role") == "assistant" + ) + if not _already_nudged and _last_is_assistant: messages.append({ "role": "user", "content": _CODEX_INCOMPLETE_NUDGE, diff --git a/scripts/release.py b/scripts/release.py index f246ddd2c86a..4af52a6d13ed 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -104,6 +104,7 @@ AUTHOR_MAP = { "root@vmi3351581.contaboserver.net": "ostravajih", # PR #58374 salvage (poolside: coerce integer finish_reason and tool_call id to strings) "hello@sahil-shubham.in": "sahil-shubham", # PR #58448 salvage (whatsapp_cloud: honor documented WHATSAPP_CLOUD_ALLOWED_USERS / ALLOW_ALL_USERS in the DM intake gate) "ahmet.tunc@gmail.com": "Ahmett101", # PR #58445 salvage (profiles: allowlist default-export roots + preserve symlinks) + "ignaciopastorsan@gmail.com": "IpastorSan", # PR #63690 salvage (codex: rescue reasoning-only turns that die after 3 continuation attempts) "Ahmett101@users.noreply.github.com": "Ahmett101", # PR #59455 salvage (background-review: guard summarize against list-shaped tool responses; #59437) "wyuebei@gmail.com": "wyuebei-cloud", # PR #56640 salvage (hermes journey: replace GNU-only %-d strftime with dt.day for Windows) "yingwaizhiying@gmail.com": "msh01", # PR #58250 salvage (telegram: wall-clock init timeout via daemon-thread deadline + abandon the shielded initialize task on timeout so the retry ladder advances instead of hanging on attempt 1/8 under s6 supervision; #58236). Also covers PR #58276 salvage (compression: preserve a real user turn after compaction; #55677).