Skip to content

fix(anthropic): show inactive model-scoped quota rows without routing on them - #8186

Merged
lidge-jun merged 8 commits into
lidge-jun:devfrom
junhoi-pk:fix/anthropic-inactive-scoped-quota-rows
Nov 10, 2026
Merged

lidge-jun merged 8 commits into
lidge-jun:devfrom
junhoi-pk:fix/anthropic-inactive-scoped-quota-rows

Conversation

@junhoi-pk

@junhoi-pk junhoi-pk commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

On the Claude account list, an account whose Fable weekly limit is not the binding one shows no Fable bar, while Claude's own usage page shows it. Claude's usage endpoint reports that row as an inactive weekly_scoped limit and, for current accounts, sends no legacy seven_day_fable key at all. A real Max response (values verbatim, identifiers removed):

{ "kind": "session",       "percent": 35, "is_active": false },
{ "kind": "weekly_all",    "percent": 91, "is_active": true, "severity": "critical" },
{ "kind": "weekly_scoped", "percent": 4,  "is_active": false, "scope": { "model": { "display_name": "Fable" } } }
"weekly_scoped_shares": [{ "limit_index": 2, "used_percent_of_weekly": 2, "allowance_percent_of_weekly": 50 }]

anthropicUsageBuckets dropped scoped rows with is_active: false on purpose for routing (#8088), and nothing else published them, so no path could draw the bar.

  • Inactive scoped rows are now published as display-only ProviderQuota.displayWindows, carrying weeklyAllowancePercent from weekly_scoped_shares. Routing, exhaustion, cooldown recovery, pool assembly and reset ordering still read only customWindows; a test pins that their output is identical with and without display rows, including a 100% display-only Fable row. The binding weekly_all (91%) still routes.
  • The account bars show Fable's own percent (4%, never the weekly-scale used_percent_of_weekly), its reset time, the line "Up to 50% of your weekly limit" (Claude's wording), and a neutral "Not in effect now" tag. Any Fable bar with a reported share, active or not, now shows the share line. Strings are in all eleven locales.
  • The decision follows the response, never the plan name: a Fable row shows on Pro, Max 5x, Team or Ultra alike, and a response with no Fable row (the Team/Max shapes in the fixtures) gets no bar. No plan-name logic gates quota windows.
  • Display-only rows stay on the account card. The GUI projection keeps them in a separate AccountQuota.displayWindows field, so the quota summary headline and severity, tray rows and urgency sorting, which read customWindows, never see them. A routed row with the same label (a later rate-limit header observation) wins.
  • The Claude CLI provider reads the same usage endpoint, so it gets the same rows; its on-disk snapshot loader now validates displayWindows like customWindows. A weekly share read back from disk (account cache or snapshot) must be a number in (0, 100]. ocx provider quota and ocx account refresh print display-only rows after routed windows through terminalSafeText, e.g. Fable 4% (up to 50% of weekly; not in effect).
  • Docs: structure/providers/anthropic-account-pool.md, structure/providers/claude-cli-replay.md, and the Claude Code guide.

Refs #8110 (the display half; this PR deliberately leaves routing on inactive scoped rows unchanged).

This carries @junhoi-pk's change (b4fd3f8) and resolves the maintainer hold on it: the display-only rows no longer reach the summary headline or tray, the weekly share is attached, and the screenshot is below. It also merges dev, including #8295 (Mistral budget display), which touched the same quota files; both features are kept.

Before (dev): the same Max account shows only the 5-hour and weekly bars.

before

After: Fable appears at 4% with its reset, its weekly share, and the not-in-effect tag.

after

Captured from the real ProviderAccountQuota component with the production CSS bundle (dark theme).

Co-authored-by: junhoipark junhoi.pk@gmail.com

Verification

Failing first, then passing after each fix:

  • bun test tests/providers/provider-anthropic-usage-windows.test.ts: the owner-response case failed without weeklyAllowancePercent on the display row; an out-of-range cached share was kept. Both pass now.
  • bun test tests/providers/provider-quota-claude-cli.test.ts: a malformed displayWindows snapshot, and one with an out-of-range share, reached /api/provider-quotas; both are rejected now.
  • cd gui && bun test tests/provider-quota-model-id.test.ts tests/quota-display-only-window.test.tsx: a display-only-only report became the summary headline, and the bars had no share or tag; both pass now.
  • bun test tests/cli/cli-headless-parity.test.ts: the CLI line omitted the display row and printed an out-of-range share; both pass now.

After merging dev (#8295) at 34fe145:

  • Server-side focused set (Anthropic usage windows and adapters, Claude CLI quota and admission, CLI parity and key quota, Mistral budget, layout, Lab boundary, import-cycle, file-size and structure guards): 1,897 pass, 0 fail.
  • GUI quota, summary, tray, capacity, current-quota, i18n and Mistral budget tests: 171 pass, 0 fail.
  • bun run typecheck (2,378 files), bun run typecheck:gui:if-changed, bun run lint:gui, bun run privacy:scan, bun run structure:check: all pass.
  • The final head 582292e only adds dev's docs commit a5d088f (docs: clarify Claude OAuth client version errors #8482) through a clean merge; the PR diff against dev is line-for-line identical to the reviewed head 34fe145 (index hashes aside).

bun run test:changed at 085d25b (1,823 files): 42,635 pass, 108 skip, 31 fail, none in code this PR touches. 16 passed when their files ran alone (load timeouts). 15 Codex launcher cases failed identically on unmodified origin/dev in the same environment and pass on a later rerun after the host's OpenCodex service was restored, so they reflected local host state. Hosted CI covers the final head.

Reviews: independent code and security reviews at 085d25b (PASS WITH NOTES; the low security finding on unbounded disk shares was fixed with tests, the P3 notes were rebutted), then fresh final code and security reviews at 34fe145 (both PASS).

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.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • Required local validation passed; commands, results, and any full-suite exception are documented.

  • I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Caution

Review failed

The pull request is closed.

Walkthrough

Inactive Anthropic model-scoped quota rows are now reported as display-only windows. The CLI and GUI show these windows with their weekly allowance share and inactive status, while quota routing continues to use active windows.

Changes: Anthropic quota window extraction and retention

Layer / File(s) Summary
Separate inactive rows from routed quota data
src/providers/quota-types.ts, src/providers/quota/anthropic-usage-windows.ts, src/providers/quota/account-cache.ts, tests/fixtures/anthropic-usage-shapes.ts, tests/providers/provider-anthropic-usage-windows.test.ts, structure/providers/anthropic-account-pool.md
The Anthropic usage parser returns inactive scoped rows separately and attaches recognized weekly-share data to routed and display-only rows. Cache normalization applies to both window types. Tests check that display-only rows do not affect routing, quota calculations, or reset ordering.
Propagate display windows through quota reports
src/providers/claude-cli-usage.ts, src/providers/claude-cli-usage-state.ts, src/cli/account-api.ts, src/cli/account-extended.ts, tests/providers/provider-quota-claude-cli.test.ts, tests/cli/cli-headless-parity.test.ts, structure/providers/claude-cli-replay.md
The Claude CLI parser and quota DTOs carry display-only windows. Snapshot validation checks their rows, and CLI output includes unshadowed display windows with an inactive label and weekly share.
Project and render quota display windows
gui/src/codex-quota-utils.ts, gui/src/provider-workspace/report.ts, gui/src/components/QuotaBars.tsx, gui/src/i18n/*.ts, gui/src/styles/provider-quota.css, gui/tests/provider-quota-model-id.test.ts, gui/tests/quota-display-only-window.test.tsx, docs-site/src/content/docs/guides/claude-code.md
The GUI keeps display-only rows separate, gives routed rows precedence when labels match, and renders inactive status, reset details, and weekly allowance shares. Locale strings, styles, documentation, and tests cover the display changes.

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

Severity of issue fixed: Low

Sequence Diagram(s)

sequenceDiagram
  participant AnthropicUsageResponse
  participant anthropicUsageBuckets
  participant ClaudeCliUsageParser
  participant ProviderQuota
  participant QuotaBars
  AnthropicUsageResponse->>anthropicUsageBuckets: provide scoped usage rows
  anthropicUsageBuckets->>ClaudeCliUsageParser: return routed and display buckets
  ClaudeCliUsageParser->>ProviderQuota: set customWindows and displayWindows
  ProviderQuota->>QuotaBars: provide quota readings
  QuotaBars->>QuotaBars: render inactive status and weekly share
Loading

Possibly related issues

  • lidge-jun/opencodex#8110 — The issue describes inactive Anthropic weekly-scoped rows missing from quota displays; this change exposes those rows as display-only windows.
  • lidge-jun/opencodex#3375 — This change exposes additional per-account Anthropic quota state in displays, but does not address the issue’s separate pool lifecycle requirements.

Possibly related PRs

  • lidge-jun/opencodex#8469 — Both changes use weeklyAllowancePercent for model-scoped quota rows; this PR also carries the share on inactive display-only rows.
  • lidge-jun/opencodex#7916 — Both changes use the Claude CLI quota-report flow; this PR adds validation and reporting for display-only windows.
Merge Risk: Low · previous review 085d2

Malformed saved quota data could show an odd account bar, but normal quota reports are unaffected. The change is mergeable with awareness of that narrow display issue.

Pre-merge checks: Passed 4 · Inconclusive 1

Failed Failed checks: 1 inconclusive

Check name Status Explanation Resolution
Docstring Coverage Inconclusive Docstring coverage is 46.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main change: display inactive Anthropic model-scoped quota rows without using them for routing.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 46.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 15 functions across 21 files. (10 skipped: 4 unsupported, 6 too large.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

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

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ Required local validation passed; commands, results, and any full-suite exception are documented.
  • ✅ I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

✅ 4/4 boxes ticked.

This pull request has been marked Ready for Review.
The review-ready label marks this PR as ready; review automation runs independently.
Maintainers notified: @lidge-jun @Ingwannu

Hygiene

✅ Deterministic PR hygiene checks passed.

@lidge-jun

Copy link
Copy Markdown
Owner

Maintainer review (contributor-backlog lane), head b4fd3f8cff, trial-merged with dev 0fac612a93.

Holding this one. The intent is right and routing really is unchanged: every routing consumer still reads only customWindows, familyEnumeration and rawAnthropicUsageWindows are byte-identical, and the new usage-window tests fail on dev (3) and pass here (36), alongside the JEV/quota-pool neighbours.

What blocks.

  1. Display-only rows escape the account card. quotaFromUnknown (gui/src/provider-workspace/report.ts ~165) merges displayWindows into customWindows, and that merged list feeds buildQuotaSummary (gui/src/quota-summary.ts ~156) and the tray's quotaWindows (gui/src/pages/tray/TrayAccounts.tsx ~18). pickHeadline falls back to any measured window without modelId when no fixed window matches, and these rows never carry modelId. A report whose only measurement is displayWindows: [{label:"Fable", percent:55}] therefore produces the summary headline {"id":"Fable","percent":55}, and the inactive row also gains a tray entry. That is a visible change outside the card this PR describes.
    Change: mark these rows as display-only through the projection (a displayOnly flag, or set modelId), exclude them from pickHeadline, from summaryWindows severity, and from the tray rows, and add a quota-summary test asserting a display-only row never becomes the headline.
  2. Screenshot. The PR changes gui/, so enforce-target needs a screenshot of the account card in the description (drag it into the editor; please do not commit it).

Small, non-blocking: src/providers/quota/account-cache.ts ~98-113 reads quota[field] while writing result[field]; fine today, but worth a one-line comment.

…-quota

# Conflicts:
#	src/providers/claude-cli-usage.ts
An inactive Fable row with no legacy seven_day_fable key now keeps its
weekly_scoped_shares allowance, so the dashboard can say how much of the
week Fable may use. Routing still reads only customWindows; a pinned test
shows pool windows, family percents and reset ordering are identical with
and without display rows. The Claude CLI snapshot loader now validates
displayWindows like customWindows.
The projection merged an inactive Anthropic model limit into
customWindows, so a report whose only reading was display-only Fable
became the quota summary headline, and the row reached the tray and
urgency sorting too. AccountQuota now carries those rows in their own
displayWindows field; only QuotaBars draws them, after the routed rows,
tagged "Not in effect now". Every Fable bar with a reported share shows
"Up to 50% of your weekly limit" under its label, in all eleven locales.

ocx provider quota and ocx account refresh print display-only rows the
same way, after routed windows, with the same routed-label precedence.
@github-actions
github-actions Bot marked this pull request as ready for review November 10, 2026 15:45

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

Additional comments: 1

structure/providers/anthropic-account-pool.md-204-204: 1

204-204: Trivial · Maintainability & Code Quality · Low value

Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Fix the awkward phrase in the documentation.

"whether or not it binds, regardless of plan name" is redundant. LanguageTool flags it. Shorten it.

Proposed fix

-never read, so Fable shows whether or not it binds, regardless of plan name. The GUI keeps them in
+never read, so Fable shows whether it binds or not, whatever the plan name. The GUI keeps them in

Source: Linters/SAST tools

Review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between e9fdc00 and 085d25b.

Files selected for processing: 31

  • docs-site/src/content/docs/guides/claude-code.md
  • gui/src/codex-quota-utils.ts
  • gui/src/components/QuotaBars.tsx
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/fr.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/pt.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/tr.ts
  • gui/src/i18n/vi.ts
  • gui/src/i18n/zh-TW.ts
  • gui/src/i18n/zh.ts
  • gui/src/provider-workspace/report.ts
  • gui/src/styles/provider-quota.css
  • gui/tests/provider-quota-model-id.test.ts
  • gui/tests/quota-display-only-window.test.tsx
  • src/cli/account-api.ts
  • src/cli/account-extended.ts
  • src/providers/claude-cli-usage-state.ts
  • src/providers/claude-cli-usage.ts
  • src/providers/quota-types.ts
  • src/providers/quota/account-cache.ts
  • src/providers/quota/anthropic-usage-windows.ts
  • structure/providers/anthropic-account-pool.md
  • structure/providers/claude-cli-replay.md
  • tests/cli/cli-headless-parity.test.ts
  • tests/fixtures/anthropic-usage-shapes.ts
  • tests/providers/provider-anthropic-usage-windows.test.ts
  • tests/providers/provider-quota-claude-cli.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

A hand-edited account cache or Claude CLI snapshot could carry a
weeklyAllowancePercent of 1e9 or a string, which reached the API and
made ocx provider quota print "up to 1000000000% of weekly". The account
cache now drops a share outside (0, 100] and keeps the measurement, the
snapshot loader rejects such a file as it already does other malformed
rows, and the CLI prints only a valid share. Routing never reads this
field from display rows; the GUI already bounded it.
@github-actions
github-actions Bot marked this pull request as draft November 10, 2026 16:51
…-quota

# Conflicts:
#	gui/src/codex-quota-utils.ts
#	gui/src/components/QuotaBars.tsx
#	gui/src/provider-workspace/report.ts
#	src/cli/account-api.ts
#	src/cli/account-extended.ts
@github-actions
github-actions Bot marked this pull request as ready for review November 10, 2026 17:09
@lidge-jun

Copy link
Copy Markdown
Owner

Maintainer judgment (carry lane), merge head 582292ecf0.

Value. Accounts whose Fable limit is not the binding one (Pro, Max 5x, Team, Ultra alike) showed no Fable bar, because Claude reports that row as an inactive weekly_scoped limit with no legacy seven_day_fable. They now show Fable's own percent, its reset, Claude's "Up to 50% of your weekly limit" line and a neutral "Not in effect now" tag. A response with no Fable row still gets no bar, and no plan-name logic decides either way. Refs #8110 (display half).

UX scope. Only the account quota bars (QuotaBars) draw display-only rows. The quota summary headline and severity, tray rows and urgency sorting read customWindows only, which resolves the earlier hold. ocx provider quota and ocx account refresh print the row after routed windows. Copy is in all eleven locales; before/after captures are in the description.

Regression risk for existing users (routing unchanged). Inactive scoped rows go to a separate displayWindows field. Routing, exhaustion, cooldown recovery, pool assembly, reset ordering, usage admission and the decision sink still read only customWindows, and rawAnthropicUsageWindows still takes .buckets only. A test runs the real owner response and shows pool windows, pooled windows, reset ordering and every family percent are identical with no display rows, with the 4% Fable row, and with a forced 100% one. The binding weekly_all 91% still routes. The inactive-session behaviour from #8088 is unchanged. Values read back from disk are validated: a malformed display row is dropped, and a weekly share outside (0, 100] is removed.

Windows. Data handling and React rendering only: no paths, processes or platform APIs. Not run on Windows locally.

Reviews.

  • At 085d25bb00, independent code and security reviews (anthropic/claude-opus-5-5) both returned PASS WITH NOTES. The low security finding was fixed with red-first tests in d5781b494c. The P3 notes were rebutted, with reasons in the review ledger.
  • At 34fe145068, after merging dev's Show Mistral API and Vibe budget usage #8295 (Mistral budget display, five overlapping files, both features kept), fresh final code and security reviews (gpt-6.1-terra, xhigh) both returned PASS.

Reviewed head to merge head. 34fe145068..582292ecf0 is one dev merge. Its diff, ignoring index and hunk headers, equals dev commit a5d088f1bd (#8482, docs) exactly. The PR's own diff against dev is unchanged line for line. The only overlapping file is docs-site/src/content/docs/guides/claude-code.md, which keeps both the #8482 "Claude OAuth client-version errors" section and this PR's inactive-Fable paragraph.

Checks at 582292ecf0.

  • Focused server tests (Fable fixture, routing invariance, disk share bounds, Claude CLI, CLI output, Anthropic routing and threshold): 239 pass, 0 fail.
  • GUI display-only separation, summary, tray and Mistral budget tests: 44 pass, 0 fail.
  • bun run typecheck and the GUI tsc -b pass.
  • No hosted check has failed on this head; pending CI was not awaited.

NOT RUN: full bun run test (the last local test:changed was at 085d25bb00, with no failures in touched code), a live dashboard against a real Claude account, Windows.

@lidge-jun
lidge-jun merged commit 937c819 into lidge-jun:dev Nov 10, 2026
33 of 35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants