Skip to content

Cap Codex session display when weekly quota is exhausted#1930

Merged
steipete merged 11 commits into
steipete:mainfrom
Yuxin-Qiao:fix/codex-weekly-caps-session-display
Jul 6, 2026
Merged

Cap Codex session display when weekly quota is exhausted#1930
steipete merged 11 commits into
steipete:mainfrom
Yuxin-Qiao:fix/codex-weekly-caps-session-display

Conversation

@Yuxin-Qiao

@Yuxin-Qiao Yuxin-Qiao commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • When Codex's weekly lane is exhausted (binding cap), CodexConsumerProjection now shows the session lane as 0% remaining and uses the weekly reset time instead of a misleading 99% / 5-hour countdown.
  • Aligns menu card, menu bar, icon, and widget usage rows with the existing burn-down widget semantics (secondaryGloballyCapsPrimary).
  • Adds regression tests and screenshots documenting the upstream Codex UI mismatch.

Upstream Codex UI (misleading)

Codex settings still show 99% on the 5-hour limit while weekly is 0%

CodexBar after this fix

CodexBar session row capped to 0% with weekly reset time

Upstream report: openai/codex#31214

Test plan

  • swift test --filter CodexConsumerProjectionTests
  • make check

@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codex review: needs changes before merge. Reviewed July 6, 2026, 3:53 AM ET / 07:53 UTC.

Summary
The PR changes Codex quota projection and menu/widget rendering so an exhausted weekly Codex lane caps the displayed session lane, with regression tests and screenshots.

Reproducibility: yes. From source, a persisted Codex widget entry with session and weekly windows both exhausted and both resetsAt values <= now still maps row.window.remainingPercent to 0 before the weekly-cap guard returns inactive rows.

Review metrics: 2 noteworthy metrics.

  • Diff size: 24 files changed (+1157/-110). The change spans projection, menu-bar rendering, widget serialization/rendering, screenshots, and tests, so stale widget behavior needs direct review.
  • Widget snapshot schema: 1 optional field added. Adding WidgetUsageRowSnapshot.window is backward-decodable, but it puts persisted widget rows on the upgrade path that this PR changes.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Filter expired exhausted persisted widget windows before building display rows.
  • [P2] Add a regression where both saved Codex windows are exhausted and both reset times have passed.

Risk before merge

  • [P1] Read-only review did not run the reported Swift tests or make check; the remaining concern is source-reproducible from the widget row path.

Maintainer options:

  1. Decide the mitigation before merge
    Land the weekly-cap display behavior after widget rows share the menu-bar projection’s reset-aware handling for expired persisted quota windows.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] A narrow automated repair can address the remaining widget stale-window blocker without a product decision.

Security
Cleared: The diff touches Swift app/widget rendering, tests, screenshots, and changelog text; no concrete security or supply-chain regression was found.

Review findings

  • [P2] Filter expired saved quota windows before rendering — Sources/CodexBarWidget/CodexBarWidgetViews.swift:640
Review details

Best possible solution:

Land the weekly-cap display behavior after widget rows share the menu-bar projection’s reset-aware handling for expired persisted quota windows.

Do we have a high-confidence way to reproduce the issue?

Yes. From source, a persisted Codex widget entry with session and weekly windows both exhausted and both resetsAt values <= now still maps row.window.remainingPercent to 0 before the weekly-cap guard returns inactive rows.

Is this the best way to solve the issue?

No, not yet. The projection and menu-bar path are narrow, but the widget row path still needs reset-aware filtering for expired saved windows before this is the best maintainable fix.

Full review comments:

  • [P2] Filter expired saved quota windows before rendering — Sources/CodexBarWidget/CodexBarWidgetViews.swift:640
    This still converts persisted row.window values directly into widget percentages before checking whether the weekly cap is active. If the widget reloads a saved Codex snapshot after both the session and weekly reset times have elapsed, and both saved windows were exhausted, the guard in applyingCodexWeeklyCap returns these raw rows and the full/switcher widgets keep showing both quotas at 0% until the app writes a fresh snapshot. Filter or reset expired exhausted windows here, matching the menu-bar projection behavior.
    Confidence: 0.89

Overall correctness: patch is incorrect
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 76a63dc55939.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix screenshots, and the inspected screenshot directly shows the Codex menu/menu-bar display capped by the weekly reset; no extra contributor proof is needed for that visible path.
  • add proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The PR body includes after-fix screenshots, and the inspected screenshot directly shows the Codex menu/menu-bar display capped by the weekly reset; no extra contributor proof is needed for that visible path.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (screenshot): The PR body includes after-fix screenshots, and the inspected screenshot directly shows the Codex menu/menu-bar display capped by the weekly reset; no extra contributor proof is needed for that visible path.

Label justifications:

  • P2: This is a normal-priority correctness fix for Codex quota display with limited blast radius to menu/widget quota presentation.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (screenshot): The PR body includes after-fix screenshots, and the inspected screenshot directly shows the Codex menu/menu-bar display capped by the weekly reset; no extra contributor proof is needed for that visible path.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix screenshots, and the inspected screenshot directly shows the Codex menu/menu-bar display capped by the weekly reset; no extra contributor proof is needed for that visible path.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The PR body includes after-fix screenshots, and the inspected screenshot directly shows the Codex menu/menu-bar display capped by the weekly reset; no extra contributor proof is needed for that visible path.
Evidence reviewed

Acceptance criteria:

  • [P1] swift test --filter CodexBarWidgetProviderTests.
  • [P1] swift test --filter CodexLegacyWidgetSnapshotTests.
  • [P1] swift test --filter CodexConsumerProjectionTests.
  • [P1] make check.

What I checked:

Likely related people:

  • steipete: Peter Steinberger owns much of the recent Codex/widget surface in current main and authored the latest branch commits that reshaped this PR. (role: recent area contributor; confidence: high; commits: a3454640cf53, 37114d21920c, 7feeebba015f; files: Sources/CodexBar/Providers/Codex/CodexConsumerProjection.swift, Sources/CodexBarWidget/CodexBarWidgetViews.swift, Sources/CodexBar/UsageStore+WidgetSnapshot.swift)
  • ratulsarna: Ratul Sarna introduced CodexConsumerProjection and moved history, icon, widget, and menu-bar consumers onto that projection path. (role: projection introducer; confidence: high; commits: c0df637e4b70, f7e7e933d160, d41be3a95326; files: Sources/CodexBar/Providers/Codex/CodexConsumerProjection.swift, Sources/CodexBar/UsageStore+WidgetSnapshot.swift, Sources/CodexBarWidget/CodexBarWidgetViews.swift)
  • JoeVenner: JoeVenner’s current-main Kimi widget support commit recently touched the shared widget rendering path involved in this PR. (role: recent widget contributor; confidence: medium; commits: 76a63dc55939; files: Sources/CodexBarWidget/CodexBarWidgetViews.swift, Sources/CodexBar/UsageStore+WidgetSnapshot.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (3 earlier review cycles)
  • reviewed 2026-07-06T04:08:11.403Z sha 3a952ef :: needs changes before merge. :: [P2] Retarget the reset even when the session is also exhausted
  • reviewed 2026-07-06T04:13:58.196Z sha 3a952ef :: needs changes before merge. :: [P2] Retarget the reset even when the session is also exhausted
  • reviewed 2026-07-06T04:30:34.298Z sha 417b8b2 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal priority bug or improvement with limited blast radius. labels Jul 6, 2026

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

ℹ️ 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 on lines +426 to +427
guard self.weeklyCapsSession(weekly: weekly, now: now),
session.remainingPercent > 0

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 Use weekly reset even when session is already empty

When the weekly bucket is exhausted and the 5-hour bucket is also already at 0%, this extra session.remainingPercent > 0 guard returns the raw session window, so the session row keeps showing the 5-hour reset instead of the later weekly reset even though the weekly cap is still binding. Users who have depleted both buckets will still see the misleading short reset this change is trying to avoid; the weekly reset should be substituted whenever weeklyCapsSession is true, not only when the session has remaining quota.

Useful? React with 👍 / 👎.

Comment on lines +434 to +435
resetsAt: weekly?.resetsAt ?? session.resetsAt,
resetDescription: weekly?.resetDescription ?? session.resetDescription,

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 Avoid showing a 5h reset when weekly reset is unknown

When the Codex CLI/parser gives an exhausted weekly window without reset metadata, weeklyCapsSession still treats it as binding, but this fallback copies the session reset into the synthetic capped row. In that scenario the UI shows 0% session quota with the 5-hour reset time, implying the cap clears in 5h even though the weekly reset is unknown; the synthetic window should leave reset metadata unknown unless it can use the weekly reset.

Useful? React with 👍 / 👎.

private static func weeklyCapsSession(weekly: RateWindow?, now: Date) -> Bool {
guard let weekly else { return false }
guard weekly.remainingPercent <= 0 else { return false }
return weekly.resetsAt.map { $0 > now } ?? true

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 Compare the weekly reset against render time

This expiry check depends entirely on Context.now, but several display paths build Codex projections with snapshot.updatedAt rather than the current render time (for example the icon resolver and widget rows). If the snapshot was captured before the weekly reset and no successful refresh lands afterward, $0 > now stays true for those paths, so the session/icon/widget remain capped at 0 even after the weekly reset has passed; display projections need to evaluate this cap against the current timeline/render time.

Useful? React with 👍 / 👎.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

Addressed the review feedback in 417b8b2:

  1. Both lanes exhausted — removed the session.remainingPercent > 0 gate; the session row now always adopts the weekly reset/description whenever weeklyCapsSession is active.
  2. Unknown weekly reset — capped session rows no longer fall back to the 5h reset metadata when weekly reset is missing.
  3. Render time — cap expiry is evaluated against Date() at display time, so a stale snapshot does not keep the session capped after the weekly reset has passed.

Added regressions for the both-exhausted, unknown-weekly-reset, and stale-snapshot cases. swift test --filter CodexConsumerProjectionTests and make check pass locally.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 6, 2026
Yuxin-Qiao and others added 10 commits July 5, 2026 22:06
When the weekly lane is the binding cap, show 0% session remaining and the weekly reset time so the menu card and menu bar do not imply usable 5-hour quota.

Co-authored-by: Cursor <cursoragent@cursor.com>
Retarget the session reset whenever the weekly cap is active, omit the 5h reset when weekly reset metadata is missing, and evaluate cap expiry against render time.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
@steipete steipete force-pushed the fix/codex-weekly-caps-session-display branch from 417b8b2 to 6c136ef Compare July 6, 2026 07:35
Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>

@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: 6c136ef4f4

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

WidgetUsageRow(
id: row.id,
title: row.title,
percentLeft: row.window?.remainingPercent ?? row.percentLeft)

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 Stop rendering expired Codex widget quotas

When the widget reloads from a persisted Codex snapshot after reset times have passed, this still renders each row from the raw row.window?.remainingPercent. If both the session and weekly buckets were exhausted in the saved snapshot and both resetsAt values have elapsed while the app has not written a fresh snapshot, the full/switcher widgets keep showing both quotas at 0%; applyingCodexWeeklyCap only handles an active weekly cap and then returns these stale zeros. Filter or ignore expired exhausted windows here, matching the menu-bar projection's reset-aware behavior.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. and removed proof: sufficient Contributor real behavior proof is sufficient. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jul 6, 2026
@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 6, 2026
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Maintainer proof for exact head 7feeebba015f48333d6896b79beaec09dba6fe69:

  • Public Model Identifier Gate: PASS. No public model identifiers added or changed; screenshots contain provider/quota UI only.
  • make check: PASS (SwiftFormat 0/1290; SwiftLint 0/1289; repository checks green).
  • make test: PASS, all 48 local shards.
  • Linux-equivalent lint: ./Scripts/lint.sh lint-linux PASS, 0 violations.
  • Focused regression/behavior validation: PASS for active and expired weekly caps, both-lane later/unknown resets, menu/card/icon/widget surfaces, combined metric/ranking, reset repaint scheduling, raw history/snapshot preservation, and decoded legacy widget caches.
  • Autoreview: clean; no accepted/actionable findings.
  • Packaged app: CodexBar.app built from the candidate; executable present; codesign --verify --deep --strict PASS; bundle com.steipete.codexbar version 0.40.1.
  • Hosted CI/security: exact-head required checks green, including four macOS shards and both Linux builds.
  • Dependencies: no package, lockfile, or project dependency changes.

Validation used deterministic fixtures only; no real provider, browser, Keychain, or account mutation.

@steipete steipete merged commit ff1c6c7 into steipete:main Jul 6, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants