Skip to content

feat(grok): show product usage breakdown under the weekly bar - #3975

Closed
olddonkey wants to merge 3 commits into
steipete:mainfrom
olddonkey:feat/grok-product-usage-breakdown
Closed

olddonkey wants to merge 3 commits into
steipete:mainfrom
olddonkey:feat/grok-product-usage-breakdown

Conversation

@olddonkey

@olddonkey olddonkey commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

Grok's card has one weekly bar, and it doesn't say which Grok product used the week. The credits endpoint already reports that split (productUsage), and CodexBar was discarding it. This PR shows it as plain text rows under the same single bar:

Weekly: 94% left
Grok Chat: 4%          ← new "Usage breakdown" rows
Grok Build: 2%

No new bars and no per-product limits are claimed. Grok still has exactly one quota.

This supersedes #3900, which was closed because a single Build-only sample couldn't establish what the product percentages are measured against (#2989). This PR adds the missing evidence: live payloads below 100% with two products.

Percentage basis: live evidence

The same account was sampled on 2026-09-25, and the CLI proxy GET /v1/billing?format=credits and grok.com GetGrokCreditsConfig returned identical values. Between samples the only thing that changed was grok.com chat usage, and GrokChat (grok.com product id 4) appeared as a second entry:

UTC creditUsagePercent GrokBuild (id 2) GrokChat (id 4) Sum of products
before 1 1 — 1
00:46 2 1 1 2
00:50 3 1 2 3
00:53 4 1 3 4
00:58 6 2 4 6
earlier (#2989, @gianpaj) 100 Build 46, App Builder 45, Chat 7, Automations 2 100

Every sample sums to the aggregate, including the unequal splits. A "share of usage" reading would make the rows sum to 100 regardless of the aggregate, so each product is a percentage of the same weekly pool. Values are whole percents on both surfaces. All four live payloads are checked into the tests verbatim.

Voice: grok CLI 1.0.41's voice mode is dictation over wss://api.x.ai/v1/stt. About 3 hours of transcribed audio produced no billing change and no product entry, so this PR contains no Voice fixture. Voice would still render correctly under the guard below (an unknown product name passes through as its raw ID), but I couldn't observe it.

Guard

The rows assume "shares add up to the total", and the code checks that on every response:

  • Products are attached only when the aggregate is the wire creditUsagePercent, and only when they sum to its raw (unclamped) value within 1 percentage point.
  • They are never shown under the on-demand used/cap fallback, a period-only answer, or a total borrowed from grok.com (completing(with:) keeps only its own products).
  • If a response ever breaks this, the rows disappear and the card goes back to today's single bar.

Proof

Everything here comes from the same account at the same moment (2026-09-25 04:54 UTC). The runs used an isolated CFFIXED_USER_HOME, CODEXBAR_DISABLE_KEYCHAIN_ACCESS=1, and --source oauth, so only ~/.grok/auth.json was read: no Keychain, no browser cookies. Email is redacted.

Before: released CodexBar 0.65.0, CodexBarCLI usage --provider grok --source oauth

== Grok 1.0.41 (grok-cli-proxy) ==
Weekly: 94% left [===========-]
Pace: 57% in reserve | Expected 63% used | Lasts until reset
Resets in 2d 13h
Last 30 days: 5.4M tokens
Account: <redacted-email>
Plan: Supergrok Heavy

After: this branch, same command

== Grok 1.0.41 (grok-cli-proxy) ==
Weekly: 94% left [===========-]
Pace: 57% in reserve | Expected 63% used | Lasts until reset
Resets in 2d 13h
Grok Chat: 4%
Grok Build: 2%
Last 30 days: 5.4M tokens
Account: <redacted-email>
Plan: Supergrok Heavy

--format json for the same run still shows exactly one window:
"primary": {"usedPercent": 6, "windowMinutes": 10080}, "secondary": null, "tertiary": null, plus
"details": [{"title": "Usage breakdown", "rows": [{"label": "Grok Chat", "value": "4%"}, {"label": "Grok Build", "value": "2%"}]}].

Menu card (production UsageMenuCardView rendered offscreen from that live snapshot with hidePersonalInfo on; see how it was rendered):

Before (0.65.0 drops productUsage) After (this PR) After (dark)
Before: single weekly bar After: weekly bar with Grok Chat 4% and Grok Build 2% rows After, dark

Changes

  • GrokCreditsProxyFetcher: all-or-nothing, fail-soft productUsage decoding. A single malformed entry or a non-array value drops the whole breakdown, so a partial list can't pass the sum check as if it were complete. It never changes the weekly total, the reset, the window, or the wire-published/implicit-zero flags. It also applies the composition guard above. (c56e731c7, after ClawSweeper's first review: Chat 5 plus a malformed Build entry under a total of 6 used to render as a complete breakdown.)
  • GrokWebBillingSnapshot.productUsage is a new defaulted field. applying(subscriptionTier:) carries it; completing(with:) keeps only its own.
  • GrokUsageSnapshot.toUsageSnapshot() adds a Usage breakdown section only when the weekly bar exists.
    • Zero-usage products are dropped, rows are sorted by share, and known IDs map to display names.
    • Values use UsageFormatter.percentString, and the section reuses the existing Usage breakdown string, so there's no new localization.
  • GrokProviderDescriptor: both fetch strategies used to replace details with the reset-coupon section. One helper now puts the coupon section first and then the breakdown.
  • docs/grok.md documents the mapping and the evidence.
  • .github/pr-proof/grok-product-usage/ contains the card renders.

Tests

  • The four live multi-product payloads, verbatim: wire order, exact values, and the sum equals the total. The 6 = 4 + 2 payload renders one bar plus Grok Chat 4% / Grok Build 2% rows.
  • The earlier single-product live payload.
  • Guard: mismatched sums are dropped, sums within rounding are kept, and overage is checked against the raw value. There are no rows under the on-demand ratio, a period-only answer, or a grok.com-borrowed total (published 12% and implicit 0%).
  • Fail-soft decoding matrix. Any malformed entry drops the whole breakdown, including the near-tolerance case (total 6, Chat 5 + malformed Build) and an exact-remainder case.
  • Coupon + breakdown ordering in both strategies, and a menu-card test showing the metric count stays at 1.

Commands run:

  • make check: 0 violations
  • make test: exit 0; 126/126 groups passed on the first run (1,391 selections, 0 failures, 0 timeouts, 928 s) on head c56e731c7. Main's newer commits don't touch Grok, and the branch merges cleanly with them.

🤖 Generated with Claude Code

olddonkey and others added 2 commits September 24, 2026 21:41
The Grok credits proxy (`/v1/billing?format=credits`) publishes a
`productUsage` array next to `creditUsagePercent`, but the decoder
dropped it. Show it as plain "Usage breakdown" text rows under the single
weekly bar, never as extra rate windows or progress bars.

Product shares are percentages of the same weekly pool as the aggregate:
every observed payload sums to it, including below-100% multi-product
samples (2 = 1+1, 3 = 2+1, 4 = 3+1, 6 = 4+2 for GrokBuild + GrokChat).
The display is guarded accordingly:

- decode `productUsage` fail-soft; malformed entries never affect the
  weekly total or period
- attach products only when the aggregate is the wire
  `creditUsagePercent` and the shares sum to its raw value within 1 pp;
  never under the on-demand `used/cap` fallback or a period-only answer
- `completing(with:)` keeps only its own products, so a grok.com total
  never carries proxy shares
- keep reset-credit rows first and append the breakdown instead of
  replacing `details` wholesale in both Grok fetch strategies

Supersedes steipete#3900 (closed pending per-product evidence, see steipete#2989).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Four live `?format=credits` payloads from one account (2026-09-25),
below 100% with two products after grok.com chat usage:
2 = 1+1, 3 = 2+1, 4 = 3+1, 6 = 4+2 (GrokBuild + GrokChat). Each parses to
its wire products and sums to the weekly total; the 6 = 4+2 payload
renders one bar plus "Grok Chat 4%" / "Grok Build 2%" rows.

Also refresh the card renders from a live two-product snapshot and
document the samples (grok.com chat = GetGrokCreditsConfig product id 4).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@clawsweeper

clawsweeper Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. 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. labels Sep 25, 2026
@clawsweeper

clawsweeper Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Codex review: blocked before merge. Reviewed September 25, 2026, 2:43 AM ET / 06:43 UTC (Revision 2).

ClawSweeper review

What this changes

The branch decodes Grok billing product percentages and displays them as text rows beneath the existing weekly quota bar, with tests, documentation, and menu-card proof images.

Merge readiness

⛔ Blocked before merge - 3 items remain

Current main and v0.66.0 still omit Grok product rows, so this PR remains useful. The latest head fixes the prior incomplete-breakdown finding and has convincing live proof. The remaining blocker is the repository owner's approval of the user-facing percentage interpretation.

Priority: P2
Reviewed head: c56e731c732e5410776f3ddea8d551d5af6d5503
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) Live CLI and visual evidence support a focused patch with the earlier decoder defect repaired; product meaning still awaits owner approval.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (terminal): Same-account OAuth CLI output shows one weekly window before and after, with Chat 4% and Build 2% rows after the change; inspected production-view renders show those rows in light and dark appearance. The latest commit only changes malformed-entry handling, with focused regression coverage. The new snapshot field is runtime data, so no stored-data migration applies.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): Same-account OAuth CLI output shows one weekly window before and after, with Chat 4% and Build 2% rows after the change; inspected production-view renders show those rows in light and dark appearance. The latest commit only changes malformed-entry handling, with focused regression coverage. The new snapshot field is runtime data, so no stored-data migration applies.
Evidence reviewed 8 items Current main and release: The current-main and v0.66.0 Grok snapshot projection have no product detail rows; the release credits parser does not decode productUsage.
Complete decoding repair: The current head decodes the product array as a whole, so one malformed entry suppresses all product rows while leaving the weekly total intact.
Prior finding covered: A focused case now checks the previously reported total-6 response with valid Chat 5 and malformed Build 1, and expects no breakdown.
Findings None None.
Security None None.

How this fits together

CodexBar's Grok provider turns billing responses into a usage snapshot. The CLI and menu card then display its weekly quota bar and supporting details.

flowchart TD
  A[Grok billing response] --> B[Decode weekly total and products]
  B --> C{Complete products compose total?}
  C -->|Yes| D[One bar with product rows]
  C -->|No| E[One bar only]
  D --> F[CLI and menu card]
  E --> F
Loading

Decision needed

Question Recommendation
Do the new below-100% multi-product samples justify labeling Grok productUsage values as shares of the weekly credit pool? Approve guarded rows: Accept the documented interpretation for complete, matching values from the same billing response.

Why: The owner previously withheld this user-facing interpretation when only a Build sample was available; the new evidence changes the basis for that decision but does not itself record approval.

Before merge

  • Resolve merge risk (P1) - The UI and docs call product percentages shares of one weekly pool. The new samples support that reading, but the owner has not approved it after closing the earlier proposal over the field contract.
  • Complete next step (P2) - Obtain the repository owner's decision on the documented Grok product-percentage interpretation before merge.
  • Resolve maintainer decision - Resolve the maintainer decision shown above before merge.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and test delta production +119/-19 lines; tests +472/-2 lines The production addition is bounded parser and presentation work with substantial focused coverage.

Root-cause cluster

Relationship: canonical
Canonical: #3975
Summary: This PR replaces a closed, unmerged attempt at the same display and overlaps only part of the broader product-quota request.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge-risk options

Maintainer options:

  1. Approve the guarded interpretation (recommended)
    Accept product rows for complete same-response compositions while preserving the single quota bar.
  2. Hold the product rows
    Defer this display until the owner has a stronger upstream field contract.

Technical review

Best possible solution:

Retain one Grok quota bar and show product rows only for complete, same-response values that compose its total, subject to the owner's approval of that interpretation.

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

Not applicable as a bug reproduction: this adds provider detail. The before and after CLI output and inspected card renders establish the requested display difference.

Is this the best way to solve the issue?

Yes, subject to owner approval: text rows retain Grok's single quota bar, and complete same-response validation avoids attaching product values to a fallback total.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against b9844e4d74e6.

Labels

Label changes:

  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): Same-account OAuth CLI output shows one weekly window before and after, with Chat 4% and Build 2% rows after the change; inspected production-view renders show those rows in light and dark appearance. The latest commit only changes malformed-entry handling, with focused regression coverage. The new snapshot field is runtime data, so no stored-data migration applies.
  • remove status: ⏳ waiting on author: Current PR status label is status: 👀 ready for maintainer look.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.

Label justifications:

  • P2: This is a bounded Grok display improvement with limited user impact.
  • merge-risk: 🚨 other: Merging would endorse a provider percentage interpretation the owner has not yet approved.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): Same-account OAuth CLI output shows one weekly window before and after, with Chat 4% and Build 2% rows after the change; inspected production-view renders show those rows in light and dark appearance. The latest commit only changes malformed-entry handling, with focused regression coverage. The new snapshot field is runtime data, so no stored-data migration applies.
  • proof: sufficient: Contributor real behavior proof is sufficient. Same-account OAuth CLI output shows one weekly window before and after, with Chat 4% and Build 2% rows after the change; inspected production-view renders show those rows in light and dark appearance. The latest commit only changes malformed-entry handling, with focused regression coverage. The new snapshot field is runtime data, so no stored-data migration applies.

Evidence

What I checked:

Likely related people:

  • steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • olddonkey: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • Aleksey Yakovlev: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
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.

Workflow

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

History

Review history (1 earlier review cycle)
  • reviewed 2026-09-25T05:21:55.060Z sha d869b4a :: blocked before merge. :: [P2] Suppress incomplete breakdowns after a product entry fails decoding

Malformed `productUsage` entries were dropped one by one before the 1 pp
composition check, so an incomplete list could still pass it: with
`creditUsagePercent: 6`, a valid Chat 5 plus a malformed Build entry left
5, within tolerance, and rendered as a complete "Usage breakdown".

Decode products all-or-nothing: a single malformed entry (or a non-array
value) now yields no breakdown. The weekly total, period, tier, and
usage flags are unchanged, and unknown product names or zero-usage
entries remain valid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@olddonkey

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@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 status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Sep 25, 2026
@steipete

Copy link
Copy Markdown
Owner

Thanks @olddonkey. Landed on main via #3988 with your co-author credit and changelog thanks, and it ships in the next release. The breakdown reads the per-product shares already present in the credits response and renders them through the shared detail rows under the weekly bar, so there are no extra requests. Malformed or mismatched shares leave the main quota intact, and the reset-credit enrichment paths now preserve the rows instead of replacing them. The regression test fails on the old code and passes after the change; verification here is fixture-based because no live Grok account was available on this Mac.

pasogott pushed a commit to pasogott/CodexBar that referenced this pull request Sep 25, 2026
Carry the validated per-product shares from Grok's existing billing response through the web billing snapshot into ordinary detail rows under the weekly bar, with no extra requests; inconsistent or malformed shares omit the breakdown while keeping the main quota. Adopts steipete#3975.

Closes steipete#3975

Co-authored-by: olddonkey <olddonkeyblog@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants