Skip to content

fix(codex): retry caller main after pool rejection (carry of #3135) - #3180

Merged
lidge-jun merged 3 commits into
devfrom
codex/3135-caller-main-carry
Sep 1, 2026
Merged

fix(codex): retry caller main after pool rejection (carry of #3135)#3180
lidge-jun merged 3 commits into
devfrom
codex/3135-caller-main-carry

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

Maintainer rebase carry of #3135 by @luvs01 — all three commits cherry-picked onto current dev with author credit preserved.

  • Distinguishes an account-gated model with no confirmed grant from one whose granted accounts are temporarily unavailable.
  • When a stored Pool account loses a gated-model grant or returns a pre-stream quota rejection, the request's already-validated caller-owned main credential may serve as the single bounded alternate.
  • Never loops back to main when main itself is the excluded credential. Exact-account selection and the stored-account 401 refresh/replay budget are unchanged.
  • Records caller-owned main retries as passthrough credentials in affinity diagnostics rather than claiming a stored credential was substituted.

This is not superseded by #3166. That question was checked explicitly. #3166 (75090d4e) fixed initial selection — keeping a healthy request-owned __main__ pin so Pool discovery does not persist an exhausted stored account before the first send. This is the post-rejection retry, and the gap was still present in the landed tree: src/codex/auth-context.ts refused the fallback on any excludeAccountId, and src/server/responses/compact.ts still dropped on !authCtx.accountId. #3166's own description called the two complementary.

Security review

Credential-selection change, so MAINTAINERS.md requires explicit review. Performed on this exact head by reading the diff:

  • The fallback narrows from "no exclusion at all" to "the exclusion is not main itself" — options.excludeAccountId !== MAIN_CODEX_ACCOUNT_ID. The exactly-once boundary is preserved by that condition, not by the absence of exclusions.
  • The caller credential is still checked against its own authenticated model roster before use, is used for one alternate send, and never enters Pool affinity, health, or promotion state.
  • The new mainModelGrantUnobserved flag only changes which of two error messages is returned; it does not widen who may serve a request.
  • No credential is persisted, logged, or copied into stored-account state.

Conflict resolution

One conflict in src/server/responses/core.ts and one in tests/codex-auth-context.test.ts, both against work that landed this week.

The core.ts conflict is the interesting one: #3176 added a 5xx quota-outcome recorder inside the no-alternate branch, and this PR widens the condition guarding that same branch to admit main. Both are kept — the guard now excludes pool, main-pool, and main, and the recorder stays inside it. Taking either side alone would have silently dropped a fix.

The test conflict was purely additive: #3166 added request-owned-pin cases, this PR added caller-main fallback cases. Both are retained.

Verification

Exact head e280397a3:

  • bun test ./tests/codex-auth-context.test.ts70 pass, 0 fail, 278 expect() calls. That count includes both authors' cases, which is the proof the merge kept both.

Full-suite and typecheck coverage is left to CI on this exact head.

Checklist

  • Targets dev
  • Author credit preserved across all three commits
  • Security review recorded above, on this head, before merge
  • Conflict resolution documented rather than silently taking one side
  • No credential persisted, logged, or promoted into stored-account state

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 1, 2026 17:15
@lidge-jun
lidge-jun merged commit 634d9e5 into dev Sep 1, 2026
6 checks passed
@lidge-jun
lidge-jun deleted the codex/3135-caller-main-carry branch September 1, 2026 17:16
@github-actions github-actions Bot added the bug Something isn't working label Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@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: e280397a3b

ℹ️ 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".

Comment thread src/codex/auth-context.ts
if (
requestScopedMainCredential
&& fixedAccountId === undefined
&& options.excludeAccountId !== MAIN_CODEX_ACCOUNT_ID

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 Refuse caller fallback when it is the rejected account

When the inbound chatgpt-account-id identifies the same ChatGPT account as the rejected Pool credential, this condition still treats the caller bearer as an alternate because it compares only the Pool's local id (for example, pool-a) with __main__. A 429/402 therefore triggers a second request against the same exhausted upstream account in both Responses and compact flows, defeating the alternate-account retry bound. Pass the rejected credential identity/account id into this decision and suppress the caller fallback when it matches.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

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-01T17:19:48.283901Z e280397 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.

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