Skip to content

fix(openai-chat): fold the developer role unless a destination records that it accepts it - #5334

Merged
lidge-jun merged 1 commit into
devfrom
codex/260920-developer-role-safe-default
Sep 20, 2026
Merged

lidge-jun merged 1 commit into
devfrom
codex/260920-developer-role-safe-default

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

Verification

  • tests/adapters/openai/openai-chat-developer-position.test.ts now holds the gap that let this ship: an undeclared destination must fold, and the role must still never be read from the hostname. Placement is asserted across all three declaration states so the role decision can never move a message.
  • The two ordering suites declare their destinations rather than asserting the default, because they are about where a reminder sits rather than which role carries it.
  • The reference table and the Claude Code guide state the new default in every locale that documents the key.
  • Local suites, typecheck and builds were not run in this lane; exact-head hosted CI on this pull request is the execution evidence.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

…s that it accepts it

#5213 removed a hostname test that decided the wire role, which was right: a
gateway proxying OpenAI accepts `developer` and the hostname cannot say so. The
replacement default was wrong in the other direction. Forwarding to every
destination assumed each one accepts a role until an operator marks it, so a
gateway that rejects it answered `400 role 'developer' is not allowed` and the
turn never started.

Nothing in this repository could see that. Every test asserted the new default
and passed; what broke was outside the tree. The key is now tri-state and the
unset state is the safe one: absent folds to `system`, `true` records an
upstream that rejects the role, `false` records one that accepts it and the
role is forwarded. Placement is untouched in all three cases, which is the
contract #5213 established and this change preserves.

The regression fixes the gap directly: an undeclared destination must fold, and
the role must still never be read from the hostname. The ordering suites declare
their destinations rather than asserting the default, because they are about
where a reminder sits, not which role carries it.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 20, 2026 12:19
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 20, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-20T12:22:36.080945Z 6c1f859 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@lidge-jun
lidge-jun merged commit d6d8744 into dev Sep 20, 2026
6 of 7 checks passed
@lidge-jun
lidge-jun deleted the codex/260920-developer-role-safe-default branch September 20, 2026 12:19
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 0f07f7b2-eab2-457b-b8a0-d844ddfe781a

📥 Commits

Reviewing files that changed from the base of the PR and between eb9a103 and 6c1f859.

📒 Files selected for processing (13)
  • docs-site/src/content/docs/fr/reference/configuration/providers.md
  • docs-site/src/content/docs/guides/claude-code.md
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/tr/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-tw/reference/configuration/providers.md
  • src/adapters/openai-chat/messages.ts
  • tests/adapters/openai/openai-chat-developer-position.test.ts
  • tests/adapters/openai/openai-chat-system-order.test.ts
  • tests/routing/cl01-openai-chat-review-regressions.test.ts
 ____________________________________________________________________________________________________________________________________________________
< There are no final decisions. No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change. >
 ----------------------------------------------------------------------------------------------------------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the bug Something isn't working label Sep 20, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c1f859c5c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// what this destination accepts, so the role folds to `system`; `true` means it is known to
// reject the role; `false` means it is known to accept it and the role is forwarded. Either
// way the message keeps the slot it arrived in — only the role changes, never the position.
const developerWireRole = provider.foldDeveloperRoleToSystem === false ? "developer" : "system";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Update the dangling-tool-call regression fixture

When foldDeveloperRoleToSystem is unset, this now emits system, but the shared provider in tests/adapters/openai/openai-chat-dangling-toolcalls.test.ts leaves it unset while lines 109, 170, and 187 still require developer. The focused adapter run therefore fails all three cases. Add foldDeveloperRoleToSystem: false to that placement-focused fixture, or change those assertions if folding is part of their contract, so the required test gate remains green.

AGENTS.md reference: src/AGENTS.md:L24-L26

Useful? React with 👍 / 👎.

// what this destination accepts, so the role folds to `system`; `true` means it is known to
// reject the role; `false` means it is known to accept it and the role is forwarded. Either
// way the message keeps the slot it arrived in — only the role changes, never the position.
const developerWireRole = provider.foldDeveloperRoleToSystem === false ? "developer" : "system";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Synchronize the authoritative developer-role contract

This reverses the unset configuration's meaning, but structure/providers/chat-compat.md lines 27-32 still states that every destination forwards developer unless the flag is set, and the public-field documentation in src/types/provider.ts lines 849-858 makes the same opposite promise. Because the source-to-doc map assigns src/adapters/ to that structure document, update both descriptions with the new tri-state semantics to prevent future adapter or configuration work from relying on the obsolete contract.

AGENTS.md reference: src/AGENTS.md:L10-L11

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

lidge-jun added a commit that referenced this pull request Sep 20, 2026
…veloper role (#5341)

#5334 folds the wire role unless a destination records acceptance. This vector is the one place that asserts the forwarded role, and it lives outside tests/, so the change missed it and dev went red with roles:value_mismatch.

Co-authored-by: codex <codex@users.noreply.github.com>
devin-ai-integration Bot added a commit to luvs01/opencodex that referenced this pull request Sep 20, 2026
…ling tool_calls suite

lidge-jun#5334 made foldDeveloperRoleToSystem tri-state: absent folds the developer
role to system on the wire, false records a destination known to accept it.
The other ordering suites were updated to declare their destination; this
one was missed, so its barrier-placement assertions read role "system"
where they expect "developer". These cases are about where the barrier
lands relative to repaired tool calls, not which role carries it, so declare
foldDeveloperRoleToSystem: false on the shared provider fixture.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration Bot added a commit to luvs01/opencodex that referenced this pull request Sep 20, 2026
…rdering suites

d6d8744 (lidge-jun#5334) made developer->system folding the default for destinations
that do not record foldDeveloperRoleToSystem and updated the ordering suites it
touched, but three suites that assert the developer role on the wire still ran
with an undeclared destination, so the PR merge ref fails them.

Declare foldDeveloperRoleToSystem: false in openai-chat-dangling-toolcalls,
chat-completions-endpoint's caller-fields case, and chat-inline-document-bytes,
matching the convention the fix commit established.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration Bot added a commit to luvs01/opencodex that referenced this pull request Sep 20, 2026
…forwarded role (lidge-jun#5334 follow-up)

lidge-jun#5334 made the developer wire role tri-state: an undeclared destination folds
it to system. Two suites asserting role:"developer" on the Chat wire were
missed because they are about tool-result repair ordering and document parts,
not role selection — declare the destination, per the convention the change
established.

Verified: both files fail on dev@600075d2 with system-for-developer wire roles
and pass with the declaration.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration Bot added a commit to luvs01/opencodex that referenced this pull request Sep 20, 2026
…-document suite

lidge-jun#5334 made foldDeveloperRoleToSystem tri-state: absent folds the developer
role to system on the wire, false records a destination known to accept it.
The inline-document bytes suite was missed, so its 'keeps its role' assertion
read role "system" where it expects "developer". These cases are about the
document reaching the wire intact, not which role carries it, so declare
foldDeveloperRoleToSystem: false on the shared provider fixture.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration Bot added a commit to luvs01/opencodex that referenced this pull request Sep 20, 2026
…ment suite

lidge-jun#5334 made foldDeveloperRoleToSystem tri-state: unset now folds developer to
system, and only an explicit false records a destination that accepts the role.
This suite's chatProvider fixture declared nothing, so its developer-turn
assertion folded and failed on the PR merge. Record acceptance, matching the
conformance-fixture fix in lidge-jun#5341.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration Bot added a commit to luvs01/opencodex that referenced this pull request Sep 20, 2026
lidge-jun#5334 folds developer to system for destinations that have not recorded
whether they accept the role. Two suites still asserted the forwarded role
on an unrecorded fixture: a document-carrying developer turn and the
dangling tool_calls barrier placement. Declare foldDeveloperRoleToSystem:
false on their destinations, matching the ordering suites, and pin the
unrecorded fold on the document path.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration Bot added a commit to luvs01/opencodex that referenced this pull request Sep 20, 2026
…ling tool_calls suite

lidge-jun#5334 flipped foldDeveloperRoleToSystem to fold on undeclared and updated the
other ordering suites to declare their destinations, but missed this file: its
provider carried no key, so the deferred developer barriers folded to system and
T1/T5/T6 failed on the merge into dev. Declare the destination accepts the role
(foldDeveloperRoleToSystem: false); the assertions are about barrier placement,
not the fold default.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration Bot added a commit to luvs01/opencodex that referenced this pull request Sep 20, 2026
…toolcalls suite

lidge-jun#5334 made foldDeveloperRoleToSystem tri-state: unset now folds developer to
system, and only an explicit false records a destination that accepts the role.
This suite's provider fixture declared nothing, so its deferred-barrier
assertions folded and T1/T5/T6 failed on the PR merge. Record acceptance,
matching the inline-document and conformance-fixture updates.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants