Skip to content

fix(routing): keep unbound account quota unknown (#1195) - #1288

Merged
lidge-jun merged 2 commits into
devfrom
codex/260808-1195-unbound-quota-unknown
Aug 8, 2026
Merged

fix(routing): keep unbound account quota unknown (#1195)#1288
lidge-jun merged 2 commits into
devfrom
codex/260808-1195-unbound-quota-unknown

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

Republishes @luvs01's #1195 on current dev. Their branch was 300 commits behind, so this is a maintainer rebase; the fix commit carries a Co-authored-by trailer and the routing change is theirs.

Policy profiles choose a provider and model before the request path resolves Pool/Direct identity, thread affinity, Anthropic session affinity, or round-robin/fill-first selection. Attaching the process-global active account during policy evaluation could therefore score or exclude a candidate using account A's quota and then execute the request on account B.

An unbound candidate now stays quota-unknown in both the live route trace and the management dry-run. Unknown quota already has an explicit profile policy, so leaving it unknown is more accurate than inventing an account reference, and it keeps account selection, cooldowns, and session affinity authoritative. Explicit codexAccountId and account-ref evidence is unchanged and still resolves to known quota.

This PR contains one maintainer-authored commit that was not in #1195. test(routing): prove the management dry-run leaves unbound candidates unknown adds two regressions to tests/routing-profile.test.ts. The contributor's patch deletes the same block from the live router and the management dry-run path, but only the live path had a regression; the existing dry-run test covers a candidate with an explicitly supplied codexAccountId, which stays known and is unaffected by the fix. Without those two tests the live/dry-run parity claim was unproven, so it is called out here rather than folded silently into the contributor's commit.

Supersedes #1195, which can be closed once this lands.

Verification

Rebased onto f5147cbc8 and re-verified after that rebase:

  • bun run test9992 pass / 7 skip / 0 fail across 625 files
  • bun test tests/routing-profile.test.ts tests/quota-scoring.test.ts — 31 pass / 0 fail
  • bun run typecheck — clean
  • Ablation, at identical scope: restoring both deleted blocks from dev (git checkout origin/dev -- src/router.ts src/server/management/routing-profile-routes.ts) gives 27 pass / 4 fail over the same 31 tests. The four failures are the two contributor runtime tests and the two maintainer dry-run tests, which is the intended coverage split. Restoring the patch returns 31 pass / 0 fail.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed. (English routing reference documents that unbound account quota stays unknown until account selection runs.)
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults. (The change removes account identifiers from route evidence; it adds none, and no account id is logged.)

Summary by CodeRabbit

  • Bug Fixes

    • Routing policy quota evidence now appears only when a candidate is explicitly associated with an account and cached quota is available.
    • Unassigned candidates no longer inherit active account identities or quota data.
    • Dry-run results now accurately show unknown quota status when account details are unavailable.
    • Explicit quota information continues to be reflected in policy results.
  • Documentation

    • Updated routing configuration guidance to describe account-bound quota evaluation and its scoring-only behavior.

lidge-jun and others added 2 commits August 8, 2026 21:48
Policy profiles choose a provider and model before the request path resolves
Pool/Direct identity, thread affinity, Anthropic session affinity, or
round-robin/fill-first selection. Attaching the process-global active account
during policy evaluation could therefore score or exclude a candidate using
account A's quota and then execute the request on account B.

An unbound candidate now stays quota-unknown in both the live route trace and
the management dry-run, which is more accurate than inventing an account
reference and keeps account selection, cooldowns, and session affinity
authoritative. Unknown quota already has an explicit profile policy.
Explicit `codexAccountId` and account-ref evidence remains unchanged.

Republished from #1195 by luvs01, whose branch was 300 commits behind dev.
Rebased onto f5147cb with no conflicts; authorship preserved below.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
… unknown

Maintainer-added coverage for the #1195 republish. The contributor's patch
deletes the same block from the live router and the management dry-run path,
but only the live path had a regression. The existing dry-run test covers a
candidate with an explicitly supplied codexAccountId, which stays known and
is unaffected by the fix, so the dry-run half of the parity claim was
unproven.

These two tests exercise an unbound Codex candidate with an active pool
account, and an unbound Anthropic candidate with an active account, and
assert both stay quota-unknown with no accountRef. Restoring either deleted
block fails them.
@github-actions github-actions Bot added the bug Something isn't working label Aug 8, 2026
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Routing policy quota evidence now requires an explicitly identified candidate account. Active Codex and Anthropic accounts no longer populate unbound candidates. Execution-path and dry-run tests verify absent account references and unknown quota status.

Changes

Quota evidence handling

Layer / File(s) Summary
Candidate evidence assembly
src/router.ts, src/server/management/routing-profile-routes.ts, docs-site/src/content/docs/reference/configuration/routing.md
Candidate evidence no longer inherits Codex or Anthropic account state from active accounts. The routing documentation describes account-bound quota evidence and scoring-only behavior.
Execution and dry-run validation
tests/quota-scoring.test.ts, tests/routing-profile.test.ts
Tests verify that unbound Codex and Anthropic candidates have no inferred account reference and report unknown quota, including when cached quota exists for an active account.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: review-ready

Suggested reviewers: wibias, ingwannu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main routing change: keeping quota unknown for unbound account candidates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/260808-1195-unbound-quota-unknown

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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/reference/configuration/routing.md`:
- Around line 156-166: The localized routing documentation pages for ja, ko, ru,
and zh-cn need the same quota-evidence behavior described in the English routing
page. Add localized text covering account-bound Codex and Anthropic quota
caches, including the dry-run fields candidates[].codexAccountId,
candidates[].accountRef, and candidates[].quota, while explicitly stating that
an active account is not a substitute and quota evidence does not affect account
selection or switching behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 683daa22-a041-4ddf-8611-ebd4c301f9f0

📥 Commits

Reviewing files that changed from the base of the PR and between f5147cb and 3fc962f.

📒 Files selected for processing (5)
  • docs-site/src/content/docs/reference/configuration/routing.md
  • src/router.ts
  • src/server/management/routing-profile-routes.ts
  • tests/quota-scoring.test.ts
  • tests/routing-profile.test.ts
💤 Files with no reviewable changes (2)
  • src/router.ts
  • src/server/management/routing-profile-routes.ts

Comment on lines +156 to +166
account-keyed Codex and Anthropic quota caches. A runtime candidate receives cached quota only when
the evidence already identifies the account. Unbound canonical `openai` and Anthropic candidates
remain unknown during policy evaluation because Pool selection, Direct caller identity, provider
rotation, and thread affinity are resolved after the policy chooses a provider/model; a process-active
account is not used as a substitute.
Quota evidence never changes account selection, session affinity, cooldowns, or switching behavior —
it only feeds policy scoring. To see quota-aware behavior in an API dry-run, supply account refs in
the candidate evidence sent to `POST /api/routing-profiles/dry-run`:
`candidates[].codexAccountId` (Codex pool, provider `openai`) or `candidates[].accountRef`
(Anthropic) derives the matching cached account quota; an explicit `candidates[].quota` object is
echoed as given. The CLI dry-run cannot supply these per-candidate account fields.

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# List routing documentation pages, including localized variants.
fd -t f -g 'routing.md' docs-site/src/content/docs | sort

# Inspect quota and account-routing statements in all routing pages.
rg -n -C 3 --glob 'routing.md' \
  'quota|accountRef|codexAccountId|active account|Pool|Anthropic|affinity|switching' \
  docs-site/src/content/docs

Repository: lidge-jun/opencodex

Length of output: 19417


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the quota/account-routing paragraphs across all routing docs, with line numbers.
for file in docs-site/src/content/docs/reference/configuration/routing.md \
  docs-site/src/content/docs/ja/reference/configuration/routing.md \
  docs-site/src/content/docs/ko/reference/configuration/routing.md \
  docs-site/src/content/docs/ru/reference/configuration/routing.md \
  docs-site/src/content/docs/zh-cn/reference/configuration/routing.md; do
  echo "===== $file ====="
  rg -n -C 4 --glob 'routing.md' \
    'quota|accountRef|codexAccountId|active account|active Pool account|Pool selection|Anthropic|affinity|switching|dry-run|Candidates' \
    "$file" || true
done

# Extract only routing docs into a small JSON report for deterministic comparison by file and quoted key terms.
python3 - <<'PY'
from pathlib import Path
terms = [
    "quota", "accountRef", "codexAccountId", "active account", "active Pool account",
    "Pool selection", "Anthropic", "affinity", "switching", "dry-run", "active"
]
for locale in ["", "ja", "ko", "ru", "zh-cn"]:
    path = Path("docs-site/src/content/docs") / f"{locale}reference/configuration/routing.md".replace("//", "/")
    if not path.exists():
        print(locale or "en", "missing")
        continue
    text = path.read_text()
    print(f"locale={locale or 'en'} lines={len(text.splitlines())}")
    for term in terms:
        hits = [i+1 for i,line in enumerate(text.splitlines()) if term in line]
        if hits:
            print(f"  {term}: {hits[:10]}{'...' if len(hits)>10 else ''}")
PY

Repository: lidge-jun/opencodex

Length of output: 18122


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Compare the exact routing profile evidence/quota sections across locales against the English source.
for locale in ja ko ru zh-cn; do
  en="docs-site/src/content/docs/reference/configuration/routing.md"
  loc="docs-site/src/content/docs/${locale}/reference/configuration/routing.md"
  lo=$(wc -l < "$loc")
  echo "===== $locale: $loc $lo lines ====="
  sed -n '94,170p' "$loc"
  echo
done

# Find any active/account quota phrasing that could contradict the English contract.
rg -n -i --glob 'routing.md' \
  'quota.*(account|active|process)|active.*(quota|accountRef|codexAccountId)|account.*(quota|cache)|can.*quota|supply.*quota|active Pool account|process-active' \
  docs-site/src/content/docs | sed -n '1,200p'

Repository: lidge-jun/opencodex

Length of output: 10717


Add the localized quota-evidence paragraphs to the routing docs.

The localized routing pages end before the English optimize.quota behavior, so docs-site/src/content/docs/{ja,ko,ru,zh-cn}/reference/configuration/routing.md can now contradict the source by omission. Add the matching account-bound quote and dry-run evidence text; do not present an active Codex or Anthropic account as a substitute for candidates[].codexAccountId / candidates[].accountRef.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs-site/src/content/docs/reference/configuration/routing.md` around lines
156 - 166, The localized routing documentation pages for ja, ko, ru, and zh-cn
need the same quota-evidence behavior described in the English routing page. Add
localized text covering account-bound Codex and Anthropic quota caches,
including the dry-run fields candidates[].codexAccountId,
candidates[].accountRef, and candidates[].quota, while explicitly stating that
an active account is not a substitute and quota evidence does not affect account
selection or switching behavior.

Sources: Path instructions, Learnings

@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: 3fc962f2cf

ℹ️ 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/router.ts
Comment on lines 511 to 514
quota: quotaEvidenceForCandidate({
provider: candidate.provider,
model: candidate.model,
...(candidate.provider === OPENAI_CODEX_PROVIDER_ID
&& providerCodexAccountMode(
OPENAI_CODEX_PROVIDER_ID,
config.providers[OPENAI_CODEX_PROVIDER_ID],
) === "pool"
? (() => {
const codexAccountId = getEffectiveActiveCodexAccountId(config);
return {
codexAccountId,
codexAccountPlan: codexAccountId
? config.codexAccounts?.find(account => account.id === codexAccountId)?.plan
: undefined,
};
})()
: {}),
accountRef: candidate.provider === "anthropic"
? getAccountSet("anthropic")?.activeAccountId
: undefined,
}),

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 Preserve provider-level quota evidence for Codex pools

For any live Pool-mode profile, this call now receives neither codexAccountId nor codexAccountPlan, and routing-profile candidates cannot configure those fields, so an openai candidate always gets { known: false } even when the reconciled pool has fresh quota data. The deleted path previously used the plan as a sentinel for quotaEvidenceForCandidate to aggregate every cached pool account via codexPoolQuotaEvidence—it did not attribute only account A's quota—so configurations using unknownEvidence.quota: "exclude" can now reject a healthy pool, while quota weighting and minQuotaHeadroom cease working on live Pool routes. Remove the active-account attribution but preserve provider-level aggregate evidence for the unbound pool, as already specified by tests/routing-policy-pool-quota.test.ts.

Useful? React with 👍 / 👎.

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.

1 participant