Skip to content

feat(grok): decode the product breakdown on the grok.com billing path - #4041

Merged
steipete merged 4 commits into
steipete:mainfrom
olddonkey:feat/grok-grpc-product-usage
Sep 27, 2026
Merged

steipete merged 4 commits into
steipete:mainfrom
olddonkey:feat/grok-grpc-product-usage

Conversation

@olddonkey

Copy link
Copy Markdown
Contributor

What this PR does

Follow-up to #3988. The Grok "Usage breakdown" rows come only from the CLI credits proxy. When the grok CLI login is gone, CodexBar falls back to grok.com GetGrokCreditsConfig. That response carries the same per-product shares, but they were never decoded, so the rows silently disappear while the weekly bar stays.

This happened on a real account. At 07:53 UTC grok's silent token refresh got RefreshTokenRejected, and grok deleted ~/.grok/auth.json (grok's own log: "auth: cleared credentials after permanent refresh failure", "disk_mutation": "file deleted (no scopes left)"). From then on the card showed the bar without the breakdown until grok login.

This PR decodes the breakdown on the grok.com path too, with the same guard as the proxy path.

The wire shape

GetGrokCreditsConfig config (field 1) has the aggregate at [1, 1] and repeated [1, 7] entries {1: product id (varint), 2: percent (float, omitted when 0)}. Live response for the same account at the same moment the CLI proxy reported creditUsagePercent 6 = GrokChat 4 + GrokBuild 2:

1: fixed32 6.0
7: { 1: 4, 2: fixed32 4.0 }
7: { 1: 2, 2: fixed32 2.0 }

Only ids verified against live proxy samples are named: 2 = GrokBuild, 4 = GrokChat. Other ids we have seen (5, 7, 8) stay unnamed.

Rules

Products are decoded only from a single complete data frame whose aggregate is wire-published at [1, 1]. They go through the same all-or-nothing add-up guard as the proxy (moved to a shared GrokProductUsage.composing, with unchanged proxy behavior). The breakdown is dropped when:

  • an entry is malformed, lacks an id, or repeats an id;
  • a percent is negative or non-finite;
  • an unnamed id has a nonzero share, because a share we can't label would make the list incomplete;
  • the shares don't add up to the aggregate within 1 pp.

An unnamed id with a zero or omitted share is simply skipped. The aggregate, reset, and wire-published/implicit-zero flags are computed exactly as before; products never affect them or throw.

Proof

Live: grok.com GetGrokCreditsConfig fetched with the auth.json bearer (no cookies, no Keychain) and parsed by this branch:

surface: grok.com GetGrokCreditsConfig (bearer, gRPC-web)
fetched: 2026-09-26T21:58:06Z
usedPercent: 6.0 wirePublished: true
productUsage: ["GrokChat=4.0", "GrokBuild=2.0"]
primary: 6.0 secondary: nil tertiary: nil
section Usage breakdown: Grok Chat 4%, Grok Build 2%

Menu card: the production UsageMenuCardView rendered offscreen from that live snapshot with hidePersonalInfo on (how). There is no plan label or pace here, because this path has no tier or window duration. That is unchanged.

Before (main: grok.com path shows no breakdown) After (this PR)
Before: weekly bar only After: weekly bar plus Grok Chat 4% and Grok Build 2%

Tests

New GrokWebBillingProductUsageTests:

  • The live grok.com response, verbatim (120 bytes including the trailer frame), decodes to [GrokChat 4, GrokBuild 2] and renders one bar plus the two rows.
  • A routing test: the cookie fallback (GrokWebFetchStrategy) now shows the rows.
  • Synthetic frames for each drop rule: unnamed nonzero id, missing or duplicate id, truncated entry, wrong wire types, negative or NaN percent, non-composing shares, implicit-zero payload, two data frames, and an aggregate that isn't [1, 1].
  • Unnamed zero-share ids are skipped and unknown entry fields are ignored.
  • Every case also asserts that the aggregate, reset, and flags equal the same payload without the [1, 7] entries.

Existing GrokCreditsProxyFetcherTests and GrokWebBillingFetcherTests pass unchanged.

Commands run:

  • make check: 0 violations
  • make test: exit 0; 129/129 groups passed on the first run (1,426 selections, 0 failures, 0 timeouts, 1,233 s) on d0a11a4aa; it merges cleanly with current main

🤖 Generated with Claude Code

The "Usage breakdown" rows came only from the CLI credits proxy. When the
grok CLI login is gone (grok deletes ~/.grok/auth.json after a rejected
refresh), CodexBar falls back to grok.com GetGrokCreditsConfig, which
carries the same shares but was never paired, so the rows vanished.

Decode the repeated [1, 7] entries ({1: product id, 2: float percent,
omitted = 0}) from a single complete data frame whose aggregate is
[1, 1], and run them through the same all-or-nothing add-up guard as the
proxy (now a shared GrokProductUsage.composing). Only live-verified ids
are named (2 = GrokBuild, 4 = GrokChat); an unnamed id with a nonzero
share, a malformed or duplicate entry, or a mismatched sum drops the
breakdown. The aggregate, reset, and usage flags are unchanged.

The live grok.com response (6 = Chat 4 + Build 2) is checked in verbatim
as a fixture.

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

clawsweeper Bot commented Sep 26, 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. proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. 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. labels Sep 26, 2026
@clawsweeper

clawsweeper Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed September 27, 2026, 2:22 PM ET / 18:22 UTC (Revision 4).

ClawSweeper review

What this changes

The branch decodes product shares from grok.com billing responses, displays them in CodexBar’s existing Grok usage breakdown, and shares a bounded protobuf reader with reset-coupon parsing.

Merge readiness

✅ Ready for maintainer review

Current main still loses the Grok product breakdown on the grok.com billing path. This PR addresses that distinct gap with live visual proof and focused coverage; I found no concrete introduced defect.

Priority: P2
Reviewed head: 6234655f9d7eaca6c7ee42a745feebe95402c748

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) Live response evidence, visible before-and-after proof, and focused coverage support a good, reviewable patch.
Proof confidence 🦞 diamond lobster (5/6) ✨ media proof bonus Sufficient (screenshot): A live grok.com billing response fetched with the Grok bearer credential was parsed by the branch and rendered through the production menu card; the inspected after image shows Grok Chat 4% and Grok Build 2% beneath the 6% weekly total. The later shared-reader revision retains that path and adds fixture coverage. No stored-data contract changes.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (screenshot): A live grok.com billing response fetched with the Grok bearer credential was parsed by the branch and rendered through the production menu card; the inspected after image shows Grok Chat 4% and Grok Build 2% beneath the 6% weekly total. The later shared-reader revision retains that path and adds fixture coverage. No stored-data contract changes.
Evidence reviewed 6 items Current-main gap: The grok.com parser returns a billing snapshot without product shares, and the documentation identifies the CLI proxy as the existing source of breakdown rows.
Guarded fallback decoding: The branch accepts product shares only from one complete payload with a published config aggregate, then checks that named shares compose the total.
Regression coverage: A captured billing frame is asserted to produce the two product rows in the usage model and CLI JSON; additional cases cover malformed entries and fallback routing.
Findings None None.
Security None None.

How this fits together

CodexBar gets Grok usage from a CLI credits proxy or grok.com billing. The selected snapshot feeds the menu card and CLI JSON output.

flowchart LR
A[Grok credentials] --> B{Billing source}
B --> C[CLI credits proxy]
B --> D[grok.com billing]
C --> E[Validated product shares]
D --> E
E --> F[Usage snapshot]
F --> G[Menu card and CLI]
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Source and test delta production +154/-217 lines; tests +374 lines The shared reader reduces net production code while adding focused billing coverage.

Technical review

Best possible solution:

Populate the existing usage-details model from validated shares in the same grok.com response, preserving its aggregate and reset values.

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

Yes, from source and the captured response: current main omits shares on the grok.com path, while the frame specifies the missing rows. This read-only review did not execute the app.

Is this the best way to solve the issue?

Yes. The branch uses the existing details section and composition guard without adding another request or UI path.

AGENTS.md: found and applied where relevant.

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

Labels

Label changes:

No label changes.

Label justifications:

  • P2: The missing breakdown affects a limited Grok fallback path while the primary usage total remains available.
  • 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 (screenshot): A live grok.com billing response fetched with the Grok bearer credential was parsed by the branch and rendered through the production menu card; the inspected after image shows Grok Chat 4% and Grok Build 2% beneath the 6% weekly total. The later shared-reader revision retains that path and adds fixture coverage. No stored-data contract changes.
  • proof: sufficient: Contributor real behavior proof is sufficient. A live grok.com billing response fetched with the Grok bearer credential was parsed by the branch and rendered through the production menu card; the inspected after image shows Grok Chat 4% and Grok Build 2% beneath the 6% weekly total. The later shared-reader revision retains that path and adds fixture coverage. No stored-data contract changes.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. A live grok.com billing response fetched with the Grok bearer credential was parsed by the branch and rendered through the production menu card; the inspected after image shows Grok Chat 4% and Grok Build 2% beneath the 6% weekly total. The later shared-reader revision retains that path and adds fixture coverage. No stored-data contract changes.

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 (3 earlier review cycles)
  • reviewed 2026-09-26T22:28:18.902Z sha d0a11a4 :: needs maintainer review before merge. :: none
  • reviewed 2026-09-27T14:12:31.183Z sha b9ea0da :: blocked before merge. :: none
  • reviewed 2026-09-27T18:02:19.403Z sha c31f0cc :: needs maintainer review before merge. :: none

steipete and others added 2 commits September 27, 2026 07:07
Retain the grok.com product breakdown while sharing one bounded wire reader with quota and reset-coupon parsing. Reject ambiguous scalar fields and malformed frame flags, and cover the shared CLI JSON detail section.

Merge main ca85f2d without rewriting contributor history. Refs steipete#4041.

Co-authored-by: olddonkey <olddonkeyblog@gmail.com>
Resolve the 0.68.1 unreleased CHANGELOG section by keeping main's
entries and placing the Grok (steipete#4041) line under its existing Fixed list.

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 27, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@steipete
steipete merged commit efe6904 into steipete:main Sep 27, 2026
9 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: 🐚 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