Skip to content

fix(grok): restore weekly Credits window on a zero-usage week - #4679

Merged
steipete merged 4 commits into
steipete:mainfrom
LeoLin990405:fix/grok-acp-zero-week
Oct 21, 2026
Merged

steipete merged 4 commits into
steipete:mainfrom
LeoLin990405:fix/grok-acp-zero-week

Conversation

@LeoLin990405

@LeoLin990405 LeoLin990405 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

On a zero-usage week, the ACP _x.ai/billing credits payload describes an active weekly period + prepaid balance but omits creditUsagePercent (proto3 zero scalars). Since 0.78.0's ACP billing support (#4595), GrokRPCClient.fetchBilling() accepts that snapshot because the prepaid balance is non-nil, GrokStatusProbe.fetch() marks billing as successful, and the Auto pipeline never reaches the web fallback that #3261/#3325 added for this exact shape. usage.primary is then missing for the whole first part of every weekly period (source: grok-cli, only providerCost remains) — reported in #4674 against 0.79.0, working on 0.77.0.

This PR applies the existing bounded, same-account usage enrichment to ACP credits whose percentage is unknown, while keeping the prepaid balance and leaving usage unknown when the retry cannot validate a percent.

Fixes #4674.

Root cause

  • GrokRPCClient.fetchBilling() accepts credits when credits.usedPercent != nil || credits.prepaidBalanceUSD != nil; a zero-usage-week payload passes on the prepaid balance alone.
  • GrokStatusProbe.fetch() sets hasBilling = true for that snapshot, so GrokCLIFetchStrategy returns source: grok-cli and the Auto pipeline ends before GrokWebFetchStrategy.
  • GrokUsageSnapshot.toUsageSnapshot() only creates primary from billing.monthlyUsedPercent or webBilling.usedPercent, so the wallet-only answer produces no rate window at all.
  • The CLI-proxy path already handles this with GrokOAuthFetchStrategy.resolvingUnknownUsage (six-second BoundedTaskJoin budget, grok.com bearer retry, strict wire-published/implicit-zero validation). ACP was simply not wired into it.

Fix

  • GrokStatusProbe gains an injectable enrichUnknownCredits seam plus a static enrichingUnknownCredits(_:credentials:budget:grpcBilling:) helper that reuses GrokOAuthFetchStrategy.resolvingUnknownUsage with the existing six-second budget and validation rules.
  • fetch() enriches ACP credits only when usedPercent == nil, before computing hasBilling. Enrichment is best-effort: CancellationError/URLError.cancelled propagate exactly like the existing enrichment path, while any other failure keeps the already-valid wallet-only billing.
  • The default seam short-circuits unless usedPercent == nil and a non-expired ~/.grok/auth.json credential exists, so missing/expired tokens never reach the network.
  • ACP period, plan, and prepaid balance remain authoritative via completing(with:): the merged snapshot keeps the ACP reset, window duration, and prepaid USD; only the percent comes from grok.com, and only if the strict validation accepts it. The grok-cli source label and the identity-only team path are unchanged.

Tests

New Tests/CodexBarTests/GrokACPUnknownUsageTests.swift, using a synthetic grok JSON-RPC fixture and dates relative to Date() (weekly period: start now-3d, end now+4d, so the bar cannot rot):

  • Failing-before-fix regression: active weekly ACP period + omitted percentage + $1.23 prepaid → usage.primary.usedPercent == 0, windowMinutes == 10080, resetsAt at the ACP period end, providerCost.balance == 1.23, source pipeline unchanged.
  • Enrichment returns unknown / throws / is canceled / times out under the budget → wallet-only billing is kept; primary stays absent; usage stays unknown; cancellation propagates.
  • Missing/expired credentials → the default seam returns without calling grpcBilling (no network), wallet retained.
  • Published ACP percentage → enrichment is never attempted (no extra request).
  • Enrichment with an unvalidated bare zero → cannot replace unknown usage; a wire-published grok.com percent adopts while keeping the ACP period/plan/wallet.

Commands run

Local environment has Command Line Tools Swift 5.10 only (no Swift 6.2 toolchain, no Xcode), so the SwiftPM test target cannot be built here; PR CI is the test gate.

  • git diff --check ✅
  • .build/lint-tools/bin/swiftformat Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift Tests/CodexBarTests/GrokACPUnknownUsageTests.swift --lint ✅ (pinned 0.63.0)
  • swiftc -parse Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift ✅; test file parsed via a sanitized copy (the 5.10 frontend predates Swift 6.2 backticked test names, which existing Grok suites already use) ✅
  • node Scripts/check-app-locales.mjs ✅
  • node Scripts/check-documentation-links.mjs ✅
  • swift test --filter 'GrokACPUnknownUsageTests|GrokFailedBillingWorkTests|GrokZeroUsageTests|GrokCreditsProxyFetcherTests' ⚠️ not runnable locally — relying on PR CI (macOS build+tests, Linux CLI build, lint/format/l10n).

Known residual behavior

  • When grok.com also has no valid percentage, usage remains unknown (no bar) instead of inventing 0%, and the prepaid balance is still published — matching the documented Grok: period-only CLI-proxy response reports 0% after Grok Build says free usage limit reached #3157 contract.
  • ACP billing responses without a percentage now make one bounded grok.com bearer request (at most ~6 s) per refresh; responses that publish a percentage make no extra request, and no browser cookies or Keychain access are involved.
  • The ACP path reports the enriched window under the existing grok-cli source label; the CLI-proxy path is unchanged.

Behavior proof (failing-before-fix → passing-after, through the shipped CLI)

Fork-owned GitHub Actions run on Ubuntu (forks cannot use this repo's xcode-27 runner, so the CLI-level proof runs on Linux; the macOS shipped suite is the PR CI lane below). Production tree is identical to this PR's head a7b3d1298; only a Linux mirror of the regression suite + proof workflow were added on the fork branch.

  • Proof workflow run: https://github.com/LeoLin990405/CodexBar/actions/runs/39551357207 (all steps green)
  • It builds CodexBarCLI, serves a synthetic grok agent stdio fixture answering _x.ai/billing with the zero-usage-week ACP payload (active weekly period, prepaidBalance.val=123, no creditUsagePercent), and a local TLS stub for the grok.com gRPC-web billing endpoint returning the validated active-period implicit-zero frame. No real network, accounts, or credentials are involved.

After fix — shipped CLI restores the weekly window and keeps the wallet:
CodexBarCLI usage --provider grok --source cli --format json →
"source":"grok-cli", "rateWindowLabels":{"primary":"Weekly"}, usage.primary = {"usedPercent":0,"windowMinutes":10080,"resetsAt":"<active period end>"}, providerCost.balance = 1.23.

After fix — wallet retained, usage unknown when enrichment is unavailable:
With the stub stopped: usage.primary = null, providerCost.balance = 1.23, source = grok-cli — the wallet-only ACP answer is still a successful result.

Before fix — same CLI, same stub, fix wiring reverted (only the 6-line enrichment call removed):
usage.primary = null, providerCost.balance = 1.23, source = grok-cli; focused regression also fails on that tree:
✘ Expectation failed: (snapshot.webBilling?.usedPercent → nil) == (0 → 0.0)
✘ Test run with 11 tests in 1 suite failed after 0.075 seconds with 4 issues.

So the regression test fails without the wiring and passes with it, and the user-visible symptom (usage.primary missing on a zero-usage week) is reproduced and fixed through the shipped CodexBarCLI usage entry point, with prepaid balance preserved in both states.

@clawsweeper

clawsweeper Bot commented Oct 21, 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 clawsweeper:intake:bug Preliminary submission classification; full source review pending. clawsweeper:intake:needs-repro Preliminary submission classification; full source review pending. labels Oct 21, 2026
@LeoLin990405
LeoLin990405 marked this pull request as ready for review October 21, 2026 04:59
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T10:19:41.757485Z 38d3d26 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed clawsweeper:intake:bug Preliminary submission classification; full source review pending. clawsweeper:intake:needs-repro Preliminary submission classification; full source review pending. labels Oct 21, 2026
@clawsweeper

clawsweeper Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex review: needs maintainer review before merge.

What this changes

This PR restores missing Grok weekly usage through the existing bounded bearer enrichment while retaining prepaid balances.

Example: ACP reports an active weekly period and $1.23 prepaid balance without a usage percentage, while grok.com validates zero usage.

  • Before: The CLI returns the $1.23 balance without a primary usage window.
  • After: The CLI returns a 0% weekly window lasting 10080 minutes and retains the $1.23 balance.

Review scores

Measure Result What it means
Overall readiness 🦞 diamond lobster (5/6) A focused, worthwhile regression repair with shipped-entry-point proof, passing reviewed-head checks, and no actionable findings.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (live_output): The supplied output and successful fork workflow exercise the unchanged production CLI on Linux through synthetic ACP and a real local TLS billing endpoint, restoring the weekly zero window and retaining $1.23 when enrichment is unavailable; removing the wiring reproduces the failure.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Product

Kind: Bug fix · Worth it: Yes · Fix scope: Complete
User problem: Grok users lose their weekly Credits window after rollover even though validated zero usage can be recovered.
Reason: The patch restores established quota behavior while respecting prior owner decisions to validate implicit zero and retain prepaid-only results.

Regression provenance

Possible regression — suspected (reviewed change). No predecessor PR is attributed.

Merge readiness

✅ Ready for maintainer review

Keep open for landing: this PR repairs a current Grok regression, preserves wallet-only billing, and has relevant shipped-CLI proof with passing checks; no blocking defects were found.

Priority: P2
Reviewed head: a7b3d1298754813c00f056f36c414b097759cd26

Before merge

None.

Findings

None.

Agent review details

How this fits together

The Grok status probe reads ACP billing and local credentials, optionally enriches unknown usage through grok.com, and converts the result into usage windows and prepaid balance for app and CLI consumers.

flowchart TD
  A[Grok ACP billing] --> B[Grok status probe]
  C[Captured Grok credentials] --> B
  B --> D[Bounded unknown usage resolver]
  D --> E[Grok bearer billing endpoint]
  E --> D
  D --> F[Usage snapshot]
  F --> G[App and CLI output]
Loading

Technical review

Best possible solution:

Land the focused ACP enrichment repair with the existing validation, timeout, cancellation, and wallet-preservation contracts intact.

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

Current-main source establishes the wallet-only short circuit, and the contributor's shipped-CLI proof demonstrates the missing window when the enrichment wiring is removed; this review executed no target code.

Is this the best way to solve the issue?

Reusing the existing resolver addresses the missing ACP integration without inferring zero from absent JSON fields or discarding useful prepaid billing.

AGENTS.md: found and applied where relevant.

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

Provenance checked

  • ACP billing acceptance keeps the original intent (d82bddb: Support the working ACP extension and retain current, legacy, and prepaid-only billing responses.)
  • Validated zero enrichment keeps the original intent (e7d0011: Accept omitted proto3 usage only from a complete active billing period while rejecting malformed or unclassified inferred zero.)
  • Terminal billing failures and optional work keeps the original intent (ad8b174: Avoid discarded local-history work after terminal billing failure while retaining successful and eligible identity-only paths.)

Testing

Proof path: shipped entry point.

Security

None.

Evidence

What I checked:

Likely related people:

  • Krzysztof Szumny: Raw commit d82bddb adds Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift:170 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: d82bddb55ef6; files: Sources/CodexBarCore/Providers/Grok/GrokStatusProbe.swift)

Review metrics

Metric Value Why it matters
Change distribution Production +60 lines; tests +363; documentation +8 The larger test portion supplies a synthetic ACP subprocess and covers enrichment acceptance, failure, cancellation, credentials, and balance preservation.

Root-cause cluster

Relationship: fixed_by_candidate
Canonical: #4674
Summary: This PR is the concrete fix candidate for the ACP wallet-only short circuit documented in the linked issue.

Members:

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

Labels

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient.
  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: The regression hides weekly quota information for one provider while prepaid balance and the rest of the runtime remain available.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.
  • proof: sufficient: Contributor real behavior proof is sufficient.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (1 earlier review cycle)
  • reviewed 2026-10-21T04:58:41.732Z sha 928ffca :: needs real behavior proof before merge. :: none

Reviewed October 21, 2026, 2:26 AM ET / 06:26 UTC (Revision 2).

The ACP `_x.ai/billing` credits payload can describe an active weekly period
and a prepaid balance while omitting `creditUsagePercent` right after a period
rollover. `GrokRPCClient.fetchBilling()` accepted that wallet-only snapshot, so
`GrokStatusProbe.fetch()` treated billing as successful and the auto pipeline
never reached the steipete#3261 web fallback; `toUsageSnapshot()` then had no primary
window for the rest of the week.

Reuse the existing bounded, same-account usage enrichment for ACP credits whose
percentage is unknown: ask the grok.com bearer surface with the same auth-file
token under the six-second budget and adopt only a wire-published percentage or
a parser-validated implicit zero for an active period. The ACP period, plan,
and prepaid balance stay authoritative, a failed or slow enrichment keeps the
already-valid wallet-only billing, and missing or expired tokens never reach
the network.

Adds synthetic ACP regression coverage for the zero-usage week, enrichment
unknown/failure/cancellation/timeout paths, credential guards, published-percent
no-retry behavior, and unknown-usage preservation. Updates docs/grok.md and the
0.79.1 changelog.

Refs steipete#4674
`CredentialsMode` is a parameter of an internal `@Test(arguments:)` entry
point, so declaring the nested enum private fails the macOS test-target
compile: "method must be declared private because its parameter uses a
private type". Nesting it in the internal suite already keeps it
test-target-local.

Refs steipete#4674
@LeoLin990405
LeoLin990405 force-pushed the fix/grok-acp-zero-week branch from 270f614 to a7b3d12 Compare October 21, 2026 05:43
LeoLin990405 added a commit to LeoLin990405/CodexBar that referenced this pull request Oct 21, 2026
Fork-only proof harness: mirrors the macOS `GrokACPUnknownUsageTests` into the
Linux test target (the same synthetic ACP fixture and probe paths are
platform-independent) and adds a GitHub-hosted Ubuntu workflow that

1. runs the focused regression on the fixed tree (expected green), then
2. applies a patch removing only the `GrokStatusProbe.fetch()` ACP enrichment
   wiring and reruns the same focused regression (expected red).

The workflow logs label each phase explicitly. This branch/workflow is proof
material for steipete#4679 and must not be merged upstream.

Refs steipete#4674
@LeoLin990405

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review — PR body now has a Behavior proof section: (1) fork-run bash Linux Proof B: shipped entry point CodexBarCLI usage --provider grok --source cli --format json restores usage.primary = {usedPercent:0, windowMinutes:10080, resetsAt:<active period end>} with providerCost.balance=1.23; (2) wallet-only retention when the enrichment stub is unavailable (primary=null, balance=1.23); (3) reverting only the 6-line enrichment wiring makes the focused regression red (4 issues) and removes the CLI window; (4) PR CI run 39551221293 on head a7b3d12 is fully green including swift-test-macos (33m19s). Proof workflow: https://github.com/LeoLin990405/CodexBar/actions/runs/39551357207

@clawsweeper

clawsweeper Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added clawsweeper:intake:bug Preliminary submission classification; full source review pending. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. clawsweeper:intake:bug Preliminary submission classification; full source review pending. labels Oct 21, 2026
Use the existing quota enrichment path for wallet-only ACP replies, preserving
validated zero usage and the ACP billing period without adding another fetch hook.
Keep the end-to-end synthetic ACP regression and remove duplicate result assembly.

Fixes steipete#4674

Co-authored-by: Zhongyue Lin <101193087+LeoLin990405@users.noreply.github.com>
steipete added a commit that referenced this pull request Oct 21, 2026
@steipete
steipete merged commit ad0c567 into steipete:main Oct 21, 2026
3 checks passed
@steipete

Copy link
Copy Markdown
Owner

Merged in ad0c567, thanks @LeoLin990405! A zero-usage week keeps Grok's weekly Credits window again. We routed ACP credits through the existing bounded enrichment resolver instead of a new path, so production code didn't grow, and kept a trimmed version of your tests. It will ship in the next release.

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: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor 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.

Grok: zero-usage week drops the weekly Credits window again in 0.79.0 (ACP billing short-circuits the #3261 fallback)

2 participants