Skip to content

acpmux: a Codex chat's plan usage limits (5-hour, weekly, credits) are its usageLimits, as a Claude chat's - #34714

Merged
teamleaderleo merged 3 commits into
feat-cmux-nextfrom
lane/plan-usage-ring
Nov 4, 2026
Merged

teamleaderleo merged 3 commits into
feat-cmux-nextfrom
lane/plan-usage-ring

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Leo, 2026-11-04: "are we able to disable the context thing on the bottom right? i want to be able to right click disable it. what's its name?" and "likewise, i guess we can turn that into a 5h/weekly usage type thing instead as well for some people. i suppose it'd be relevant sometimes for SOME people to have that surfaced e.g in their session info thing."

References: Codex's ring popover ("Usage source: Your Pro plan / Weekly limit 10% left / Credits 56,766 credits / Manage usage") and Claude desktop's ("Plan usage limits · Ultra / 5-hour limit Resets at 10:00 PM 22% / Weekly · all models Resets Mon 3:00 PM 41%").

This is the acpmux half: the data. The composer ring's plan-usage mode, its popover and the Session Info section come in a follow-up web PR that reads this.

What changed

  • A Claude chat already kept its plan limits as the session detail's usageLimits (claude_stdio/usage_limits.rs, from Claude Code's rate_limit_event). A Codex chat now does too: codex app-server's account/rateLimits/updated, which cmux-codex-acp passes on as _meta.codexAppServer.rateLimits, is normalized (codex_app_server/usage_limits.rs) into the same shape: {windows: [{id, usedPercent, resetsAt?, windowMins?}], plan?, credits?}. The 5-hour window is session and the week weekly, as Claude's; any other length is named by its minutes. plan is Codex's planType; credits is {balance} or {unlimited: true}, only when the account holds some.
  • Nothing reported is nothing (no window and no credits gives no usageLimits), never a 0%. A snapshot for another limit id than codex is not the plan's and is ignored.
  • Workflow activities treated any reported usageLimits as "waiting on a limit". Every Claude Code chat reports limits, so its activities were always held as waiting, and Codex chats would now be too. They now read a limit as reached only when a window is used up (usage_limit_reached: a window at 100%).
  • No new reads, no scraping, no new auth: only what the harness already sends.

Tests

  • codex_app_server::usage_limits_tests (normalizer: Pro 5h+weekly+credits, weekly-only with unlimited credits, other window lengths, nothing reported is nothing, credits alone).
  • claude_stdio::usage_limits_tests::only_a_used_up_window_is_a_limit_reached.
  • hub_integration codex_usage_limits::a_codex_chat_keeps_its_accounts_usage_limits: the fake app-server ("codex-limits") sends two updates in a turn; the session detail holds the newest, and a chat with none has none.

Red: 6455e4f (tests only; the normalizer and helper do not exist). Green: the head.

Observed / Not run

  • Observed: the focused tests through the fleet runner on this PR's head (results in a comment below).
  • Not run: a live Codex session against a real account in a DEV build (comes with the web PR's verification).

Changelog

none (the data is shown by the follow-up web PR)

Agent session: agent session

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Makes a Codex chat's plan usage limits (5-hour, weekly, credits) available as its usageLimits, matching how a Claude chat's are kept, so the composer ring and Session Info read one shape for both.

  • Normalizes Codex's account/rateLimits/updated, passed on by cmux-codex-acp as _meta.codexAppServer.rateLimits, into usageLimits: the 5-hour window becomes session and the week weekly, plus plan and credits.
  • Nothing reported is nothing (never a 0%), and snapshots for a limit id other than codex are ignored; an empty plan snapshot clears the limits saved so far.
  • Workflow activities now treat a limit as reached only when a window is used up (100%) and has not reset; every Claude Code chat reports limits, which previously held its activities as waiting.

Written for commit bdeebf1. Summary will update on new commits.

View guided diff Turn on auto-fix

teamleaderleo and others added 2 commits November 4, 2026 03:21
…y a used-up window is a limit reached

Red: Codex's account/rateLimits/updated (cmux-codex-acp's
_meta.codexAppServer.rateLimits) never reaches the session's usageLimits,
and the normalizer and usage_limit_reached do not exist yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-9435bc58cd1ad61a49df
…aude chat's

codex app-server's account/rateLimits/updated (passed on by cmux-codex-acp
as _meta.codexAppServer.rateLimits) now becomes the session detail's
usageLimits in the shape Claude's take: the 5-hour window as session, the
week as weekly (with windowMins), plus plan and credits. Nothing reported is
nothing, never a zero; another limit id than codex is not the plan's.

Workflow activities read a limit as reached only when a window is used up
(usage_limit_reached), not whenever limits were reported: every Claude Code
chat reports them, which held its activities as waiting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-9435bc58cd1ad61a49df
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review bdeebf1: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr34714 -f ref=lane/plan-usage-ring -f platform=macos -f backend_mode=local

Shipped in:

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 4, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Focused tests at ac1db16 (run 41766866343): cargo test -p acpmux --lib usage_limit 10 passed (5 new Codex normalizer tests, 1 new usage_limit_reached test); --test hub_integration usage_limits 2 passed (new codex_usage_limits::a_codex_chat_keeps_its_accounts_usage_limits and the existing Claude one); --lib workflow 97 passed. Red: 6455e4f adds the tests without the normalizer or helper, so they do not build.

@blacksmith-sh

blacksmith-sh Bot commented Nov 4, 2026

Copy link
Copy Markdown

Found 5 test failures on Blacksmith runners:

Failures

Test View Logs
main.DeveloperIdAppTests.test_download_prints_the_active_profile_only/
test_download_prints_the_active_profile_only
View Logs
stubs: /System/Library/Frameworks/Security.framework/Versions/A/Security has no stub/
Security has no stub
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_CFRetain']/
CoreFoundation, missing 1: ['_CFRetain']
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_log2']/
CoreFoundation, missing 1: ['_log2']
View Logs
test_the_type_check_covers_every_webviews_test_file (main.WorkflowShape.test_the_ty
pe_check_covers_every_webviews_test_file)/
test_the_type_check_covers_every_webviews_test_file (main.WorkflowShape.test_the_ty
pe_check_covers_every_webviews_test_file)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at ac1db16

Reviewer: codex gpt-6.1-sol xhigh, fast tier.

Follow-ups: 2. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at ac1db16

Visual verdict: no images; Leo tries the build

Static review completed. The Python fake-server scenario passed; Rust tests could not run because cargo is unavailable.

  1. [P2] [follow-up] [category:correctness] [finding:F1] [outcome:pending] Clear saved limits when a Codex snapshot becomes empty — hub/permissions.rs:397. A credits-only snapshot followed by one reporting no windows and no credits normalizes to None, so this branch skips the replacement. Session detail consequently retains and persists the old balance. Distinguish an empty Codex snapshot from an ignored snapshot for another limit ID, and test that transition.

  2. [P2] [follow-up] [category:reliability] [finding:F2] [outcome:pending] Expire full windows before suppressing workflow recovery — claude_stdio/usage_limits.rs:94. A saved 100% window remains “reached” after resetsAt. For newly populated Codex limits, this can leave a stalled turn’s waiting flag true indefinitely: the recovery timer is disabled while waiting, so silence cannot trigger reevaluation. Respect the reset deadline and arrange a wake when it passes.

Follow-ups:

  • Clear saved limits after an empty Codex snapshot.
  • Reevaluate workflow waiting when a full window resets.

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

cmux-bot approves ac1db16: an independent review passed this exact head (router-review receipt by teamleaderleo). A push needs a new review; a later BLOCK at this head dismisses this approval.

…ed limits; a used-up window is reached only until it resets

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-9435bc58cd1ad61a49df
@cursor

cursor Bot commented Nov 4, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review follow-ups (router-review SHIP at ac1db16), handled at bdeebf1:

  • F1 (an empty Codex plan snapshot kept the old limits): fixed. A plan snapshot (is_plan_snapshot: no limitId, or codex) now always replaces the saved limits, and an empty one clears them. Another limit id still changes nothing. Test: only_the_plans_own_snapshot_replaces_the_saved_limits.
  • F2 (a used-up window held workflows as waiting after its reset): partly fixed. usage_limit_reached now ignores a window whose resetsAt has passed. Waking a waiting turn when the reset passes is filed as acpmux workflow: wake a turn held on a used-up plan window when it resets #34777.

The bdeebf1 diff adds no new behaviour beyond these two review items.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Focused tests at bdeebf1 (run 41772081422): cargo test -p acpmux --lib usage_limit, --test hub_integration usage_limits, --lib workflow and cargo clippy -p acpmux --lib -- -D warnings all pass. clippy --all-targets is red on base in hub/permissions/repo_sync_tests.rs (field_reassign_with_default), a file this PR does not touch.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at bdeebf1

Reviewer: codex gpt-6.1-sol xhigh, fast tier.

Follow-ups: 1. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at bdeebf1
Visual verdict: no images; Leo tries the build

  1. [P2] [follow-up] [category:reliability] [finding:F1] [outcome:pending] workflow_activity.rs:445 — Wake recovery when a limit resets. A full window sets waiting = true, disabling the deadline branch through its !waiting guard. If the chat stays silent across resetsAt, the helper is never reevaluated and stall recovery remains disabled indefinitely. Schedule a reset wake-up and cover this with a workflow test.

Rust tests could not run because cargo is unavailable. The Python two-update fixture passed.

Follow-ups:

  • Resume workflow stall recovery when a reported limit expires without another event.

@teamleaderleo
teamleaderleo merged commit 1749f76 into feat-cmux-next Nov 4, 2026
170 of 176 checks passed
@teamleaderleo
teamleaderleo deleted the lane/plan-usage-ring branch November 4, 2026 04:37

This branch was previously deployed

3 inactive deployments
artifacts — bdeebf11 Deployed Nov 4, 2026 by teamleaderleo via publish tree-addressed cmux-tui #109359
sentry-dsyms — bdeebf11 Deployed Nov 4, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #109359
ci-routing-agent — bdeebf11 Deployed Nov 4, 2026 by teamleaderleo via cmux-tui tree preflight #109359
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant