Skip to content

refactor(codex,providers): split routing and quota behind facades - #4645

Merged
lidge-jun merged 4 commits into
codex/m2k-l4-inject-syncfrom
codex/m2k-l5-routing-quota
Sep 14, 2026
Merged

lidge-jun merged 4 commits into
codex/m2k-l4-inject-syncfrom
codex/m2k-l5-routing-quota

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

src/codex/routing.tssrc/providers/quota.ts를 파사드로 남기고 리프로 나눈다. 순수 이동이며 공개 export 표면은 이동 전과 같다.

파일 새 리프
src/codex/routing.ts 3,507 1,475 routing/cooldown-math.ts 274, routing/health-store.ts 402, routing/probe-lease.ts 358, routing/thread-affinity.ts 415, routing/selection.ts 698, routing/active-account.ts 194
src/providers/quota.ts 3,313 558 quota/report-cache.ts 319, quota/account-cache.ts 440, quota/vendor-probes-key.ts 1,243, quota/vendor-probes-oauth.ts 589, quota/antigravity.ts 295

두 파일 모두 계획보다 파사드가 두껍게 남았고 이유는 같다. 계획이 리프로 보낸 함수 일부가 그 리프를 다시 호출해서 순환이 생긴다. routing에서는 clearCodexUpstreamHealth 계열과 reconcileCodexActiveAfterExclusion, releaseDrainedCodexAccountPin이 그렇고, quota에서는 fetchAccountQuota와 explicit 계정 디스패처들이 oauth/key/antigravity 프로브를 호출하면서 그 프로브들이 다시 account-cache 상태를 기록한다. 그래서 디스패처는 파사드에 남기고 리프에서 상태 소유 모듈로 가는 단방향만 남겼다.

재시도 예산 범위는 건드리지 않았다. 새 모듈 어디에도 시도 카운터를 만들지 않았고, 링 전진과 active 커서 승격은 그대로 한 곳에 있다.

quota의 WeakMap 세 개(nativeMainReportGenerations, accountReportCurrent, routingEvidence)는 report-cache가 단독 소유한다. report 객체를 키로 쓰기 때문에 만드는 모듈과 읽는 모듈이 갈라지면 증거가 조용히 사라진다.

본문을 텍스트로 읽는 오라클 세 곳을 같이 고쳤다. config-save-boundary.test.tsGUARDED_FILEScodex/routing/active-account.ts를 더했고(setActiveCodexAccount가 그리로 갔다), provider-quota.test.ts.json( 금지 검사는 프로브가 옮겨간 리프 셋까지 읽게 했다. 파사드만 읽으면 프로브가 없는 파일을 검사하는 빈 가드가 된다.

Verification

  • bun scripts/structure-ssot.tsstructure/ SSOT checks passed (openai-tiers.md 451·518, runtime.md 342, gui-and-management-api.md 502의 백틱 경로를 새 소유 모듈로 교체한 뒤)
  • bun scripts/file-size-ratchet.tsfile-size ratchet passed
  • 파사드 export 표면 대조(origin/dev 기준): routing.ts 54 → 54, quota.ts 30 → 30, 누락 0
  • 로컬 typecheck·full suite·install은 실행하지 않았다. 타입 해석과 런타임 회귀는 이 PR head의 hosted CI가 증거다.

작업 중 이 스택의 래칫 게이트가 실제로 한 번 막았다. provider-quota.test.ts의 오라클을 넓히면서 파일이 3,763 → 3,772줄이 되자 GREW로 실패했고, ratchet:update는 캡을 올리지 못하므로 우회할 수 없어 같은 줄 수로 다시 썼다.

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.

Pure move. routing.ts 3507 -> 1475 with six leaves, quota.ts 3313 -> 558 with five leaves. Dispatchers that would close a cycle stay on the facade. Retry budget scope is unchanged; no new attempt counter exists in any leaf.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 14, 2026 16:24
@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • ^dev$
  • ^preview$

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 03aa563f-e522-415f-8c38-be06bf40b2b1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 14, 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-14T16:29:56.056116Z 3596985 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.

@github-actions github-actions Bot added the chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature). label Sep 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 52 / 80

이 PR은 제품 기능을 바꾸려는 것이 아니라, godfile round2 사이클 4에서 이미 약속한 대로 src/codex/routing.ts(지금 dev에서 3,507줄)와 src/providers/quota.ts(3,313줄)를 파사드 + 리프 모듈로 나누는 순수 이동이다. 작성자가 밝힌 대로 공개 export 표면은 이동 전과 같다(routing 54→54, quota 30→30; 누락 0). 재시도 예산 범위도 건드리지 않았고, 새 리프 어디에도 시도 카운터를 만들지 않았다. 링 전진과 active 커서 승격은 파사드에 그대로 남는다.

지금 dev HEAD는 627274b8f이고, tip은 #4546 비용 가드 스택의 wpc(#4624 identity domains) → wpe(#4625 spend ledger) → wpf(#4626 half-open probe lease / Retry-After)다. 패키지는 2.56.0이고 epic #4546은 아직 OPEN이며 다음 층은 wpd/wpa/wpb/wpg다. 이 PR base는 dev가 아니라 codex/m2k-l4-inject-sync(#4643 inject/sync 파사드)이므로 단독으로 dev에 올릴 수 있는 PR이 아니다. 다만 중요한 점은, 이 head를 현재 dev tip에 dry-merge 해 보면 routing.ts/quota.ts 충돌 없이 자동 머지가 된다. #4624·#4625·#4626이 건드린 것은 src/routing/identity-domains.ts · src/lib/spend-reservation-ledger.ts · src/routing/probe-lease.ts 쪽이고, 이 PR이 쪼개는 src/codex/routing.ts 본문과는 경로가 갈라진다. 그래서 types/config 분할과 무관하고, close-don't-rebase 대상도 아니다. m2k 스택 순서(#4635 로드맵 → #4636 래칫 → #4642 state/shim → #4643 inject/sync → #4645)만 지키면 된다.

나눈 모양은 040 계획과 대체로 맞다. routing 쪽은 cooldown-math.ts(274) · health-store.ts(402) · probe-lease.ts(358) · thread-affinity.ts(415) · selection.ts(698) · active-account.ts(194)이고, 파사드 잔여는 약 1,476줄이다. quota 쪽은 report-cache.ts(319) · account-cache.ts(440) · vendor-probes-key.ts(1,243) · vendor-probes-oauth.ts(589) · antigravity.ts(295)이고, 파사드는 558줄이다. 계획이 리프로 보낸 함수 일부가 그 리프를 다시 호출해 순환이 생기므로, clearCodexUpstreamHealth 계열 · reconcileCodexActiveAfterExclusion · releaseDrainedCodexAccountPin과 quota의 fetchAccountQuota / explicit 계정 디스패처는 파사드에 남긴 판단이 맞다. 상태 소유권도 계획대로다. health 맵은 health-store가, thread affinity 맵은 thread-affinity가, WeakMap 세 개(nativeMainReportGenerations · accountReportCurrent · routingEvidence)는 report-cache가 단독 소유한다. report 객체를 키로 쓰기 때문에 만드는 모듈과 읽는 모듈이 갈라지면 증거가 조용히 사라지는데, 그 함정을 피했다.

본문을 텍스트로 읽는 오라클도 같이 고쳤다. config-save-boundary.test.tsGUARDED_FILEScodex/routing/active-account.ts를 더했고(파사드 항목은 유지), provider-quota.test.ts.json( 금지 검사는 quota.ts · vendor-probes-key.ts · vendor-probes-oauth.ts · antigravity.ts까지 읽게 했다. quota-reset-detector.test.ts 주석의 0-survive 대립 경로도 account-cache.ts로 고쳤다. structure 쪽은 openai-tiers.md 451·518, runtime.md 342, gui-and-management-api.md 502의 백틱을 새 소유 모듈로 바꿨다. 작성자는 bun scripts/structure-ssot.tsfile-size-ratchet.ts를 로컬에서 통과시켰고, typecheck·full suite·install은 hosted CI에 맡긴다고 했다. 이 시각에 hygiene·changes·keyring ubuntu는 통과했고 Cross-platform test/gates는 아직 pending이다. base가 스택 브랜치라 enforce-target은 형제들과 같이 실패/취소될 수 있다.

형제 #4643과 같은 약점도 있다. tests/fixtures/file-size-baseline.json이 이 PR write set에 없다. 기준선은 여전히 src/codex/routing.ts:3507, src/providers/quota.ts:3313이다. 래칫이 SHRANK/NEW_OK로 통과한 것은 맞지만, --update로 캡을 내려 커밋하지 않으면 파사드가 다시 3,507·3,313까지 커져도 GREW가 안 난다. 쪼개기 승리를 잠그려면 기준선 하향이 같은 스택에 따라와야 한다. 또한 vendor-probes-key.ts가 1,243줄로 리프치고는 크다. 040 정정이 이미 ~1,230을 예상했으니 이번 사이클의 계약 안이지만, 다음 라운드 후보로 이름을 남겨 두는 편이 좋다.

경로 src/codex/routing/probe-lease.ts vs src/routing/probe-lease.ts - 이름이 같다. 전자는 이 PR이 codex/routing.ts에서 뽑은 계정 쿨다운 probe lease이고, 후자는 방금 dev에 오른 #4626 wpf의 비용 가드 half-open probe lease다. 경로가 달라 컴파일은 되지만, 문서·리뷰·검색에서 서로 헷갈리기 쉽다. 주석이나 structure에 “codex pool cooldown probe”와 “upstream recovery probe”를 한 줄로 구분해야 한다.
경로 tests/fixtures/file-size-baseline.json - 이 PR write set에 없음. routing.ts/quota.ts 줄 수 감소가 래칫 캡에 반영되지 않아, 쪼개기 후에도 예전 상한(3507/3313)까지 다시 커질 수 있다. bun scripts/file-size-ratchet.ts --update 결과를 같은 스택(또는 직후 PR)에 넣어야 승리가 잠긴다.
경로 src/providers/quota/vendor-probes-key.ts (1,243줄) - 2,000 미만이라 래칫은 통과하지만 리프치고는 여전히 크다. 이번 사이클 계약(~1,230) 안이므로 여기서 더 쪼개지 말되, round3 후보로 적어 두자.
경로 src/codex/routing.ts 잔여(~1,476줄) / selection.ts (698줄) - 디스패처를 파사드에 남긴 순환 회피는 맞다. 다만 파사드가 계획보다 두껍다. 다음 라운드에서 selection 내부의 plan-exclusion / reset-first 덩어리를 더 자를지 미리 정하자.
경로 structure/transports/inventory.md - 040이 표기한 Discovery/quota·진단 바인딩 문단은 이번 사이클에서 facade 유지를 허용했고, 일부는 사이클 8로 미뤘다. 고치지 않은 것은 계약과 맞지만, inventory가 여전히 옛 줄 번호를 암시하면 안 되므로 follow-up에서 facade 잔류를 명시하는 한 줄만 보태면 좋다.
CI / enforce-target - Cross-platform test·gates가 아직 pending이고, base가 dev가 아니라 스택 PR이라 enforce-target은 형제들과 같이 실패할 가능성이 크다. 머지 판단은 #4635#4636#4642→#4643이 dev에 오른 뒤, 이 head를 retarget하거나 merge-train으로 묶은 다음에 해야 한다.

메인테이너의 판단이 필요한 지점

너의 추천
닫지 말고 스택을 유지한다. 우선 #4635#4636#4642→#4643이 dev에 안정적으로 오른 뒤 이 PR을 이어서 머지한다. 머지 전에 (1) hosted CI(test/gates) 초록을 확인하고, (2) file-size-ratchet.ts --update로 routing/quota 캡을 내린 기준선 커밋을 같은 스택에 넣으며, (3) 두 probe-lease.ts의 역할 차이를 structure 또는 파일 머리 주석에 한 줄씩 적는다. types/config 분할과 무관하고 중복도 아니므로 close-don't-rebase 대상이 아니다. 우선순위 52 — 분해 방향·상태 소유권·오라클·export 패리티·현재 tip dry-merge 청정은 탄탄하지만, 스택 의존·CI pending·래칫 캡 미잠금·동명 probe-lease 혼동 때문에 지금 당장 merge train 맨 앞에 두지는 않는다.

이 댓글은 grok-bot이 작성했습니다

@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: 35969857f2

ℹ️ 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/routing/active-account.ts Outdated
@@ -0,0 +1,194 @@
import { saveConfigPreservingClaudeCode } from "../config";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P0 Badge Fix the config import from the nested routing module

Building the changed src/codex/routing.ts entry with Bun fails immediately because this path resolves to nonexistent src/codex/config.ts; the new leaf is one directory deeper than the old facade, so it must import ../../config. Since the facade statically imports this leaf, every proxy startup that loads Codex routing fails before serving requests.

AGENTS.md reference: src/AGENTS.md:L7-L8

Useful? React with 👍 / 👎.

let oldestIsDetour = false;
for (const [threadId, affinities] of threadAccountMap) {
for (const [scope, entry] of affinities) {
const candidateIsDetour = isModelDetourAffinityScope(scope);

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 Restore the model-detour scope predicate

When the affinity cache exceeds CODEX_THREAD_AFFINITY_MAX_ENTRIES (2,048 entries), pruneLruThreadAffinities executes this call, but the split omitted the previous isModelDetourAffinityScope definition. Bun therefore throws a ReferenceError during the bind that crosses the limit, leaving every subsequent new affinity bind liable to fail instead of evicting an entry; restore the predicate in this leaf.

AGENTS.md reference: src/AGENTS.md:L7-L8

Useful? React with 👍 / 👎.

…ta split

Fifteen symbols lost their binding: leaves that defined a symbol never exported it, quota type imports pointed at src/types instead of providers/quota-types, and isModelDetourAffinityScope lost its definition entirely while its call site survived. Imports and exports only; no declaration was moved or rewritten.
@lidge-jun lidge-jun added the test-exception-approved Maintainer approved a non-automated regression-test exception label Sep 14, 2026
@github-actions github-actions Bot removed the test-exception-approved Maintainer approved a non-automated regression-test exception label Sep 14, 2026
@lidge-jun lidge-jun added the test-exception-approved Maintainer approved a non-automated regression-test exception label Sep 14, 2026
The leaf sits one directory deeper than routing.ts, so ../config resolved to src/codex/config, which does not exist. Every test shard that loaded the routing graph failed at import time.
@lidge-jun
lidge-jun merged commit cf10995 into codex/m2k-l4-inject-sync Sep 14, 2026
26 checks passed
@lidge-jun
lidge-jun deleted the codex/m2k-l5-routing-quota branch September 14, 2026 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature). test-exception-approved Maintainer approved a non-automated regression-test exception

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant