Integrate spend reporting series (#3015–#3019) - #3026
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
Pinned calendars now reach cached Codex reads, vendor-reported costs keep their source, and shorter summaries no longer inherit snapshot-wide metered spend. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Cached day totals now honor overlay rates, including explicit free rates, without rereading custom-pricing.json for every usage row. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…imit. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Unreported rows no longer publish zero spend, estimated unpriced requests count once, and duplicate request IDs replace instead of aborting the cache write. Co-authored-by: Cursor <cursoragent@cursor.com>
…hboard. Co-authored-by: Cursor <cursoragent@cursor.com>
Shorter ranges no longer inherit snapshot-wide Cursor meters, uncovered heatmap days cannot drill down, and OpenCodex-only setups still load. Co-authored-by: Cursor <cursoragent@cursor.com>
… suite. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
A missing or empty usage.jsonl no longer counts as an OpenCodex source that can hide native Codex totals. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs changes before merge. Reviewed August 17, 2026, 8:54 PM ET / August 18, 2026, 00:54 UTC. ClawSweeper reviewWhat this changesThis PR integrates spend provenance, custom pricing, an opt-in OpenCodex log source, dashboard reporting controls, and expanded cost JSON output. Merge readinessKeep open: an OpenCodex usage record with class-level counts but no total undercounts reasoning tokens in the dashboard and CLI payload. Priority: P2 Review scores
Verification
How this fits togetherCodexBar reads local usage logs into cached cost snapshots, then renders those snapshots in the macOS spend dashboard and emits them through the CLI. The new OpenCodex path parses an optional usage log into the same reporting model while keeping its cache separate. flowchart LR
A[Native usage logs] --> C[Cost snapshot builder]
B[Optional OpenCodex usage log] --> D[OpenCodex parser]
D --> C
E[Pricing and timezone settings] --> C
C --> F[Spend dashboard]
C --> G[CLI JSON export]
Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Root-cause clusterRelationship: Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Include reasoningOutputTokens in the derived OpenCodex total and add a regression fixture with no explicit total before merging. Do we have a high-confidence way to reproduce the issue? Yes: parse an OpenCodex fixture containing input, output, and reasoning counts but no totalTokens; the derived total excludes reasoning while the displayed mix retains it. Is this the best way to solve the issue? No: the fallback must include reasoningOutputTokens so derived totals match the log’s token-class semantics when an explicit total is absent. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 318d88db29fe. LabelsLabel changes:
Label justifications:
EvidenceAcceptance criteria:
What I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 04affe82b4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if summary.totalCost != nil { | ||
| sawEstimate = true |
There was a problem hiding this comment.
Preserve vendor-reported provenance in dashboard groups
When a source reports vendor-metered daily spend without a separate meteredCostUSD—as OpenAI Admin, Mistral, and Groq now do—this classifies it as a list-price estimate solely because summary.totalCost exists. The loop never consults snapshot.costProvenance, so the dashboard presents actual vendor-reported amounts with the wrong provenance label; aggregate each snapshot's windowed provenance instead.
Useful? React with 👍 / 👎.
| if format == .json, | ||
| let openCodex = Self.loadOpenCodexCostPayload( | ||
| historyDays: historyDays, | ||
| calendar: bucketCalendar) | ||
| { | ||
| payload.append(openCodex) |
There was a problem hiding this comment.
Honor provider selection before appending OpenCodex
When OpenCodex import is enabled and its log exists, every JSON invocation appends this payload, even codexbar cost --provider claude --format json. The command help explicitly documents provider-scoped cost output and gives that Claude-only example (CLIHelp.swift:116-133), so automation expecting only the requested provider now receives unrelated Codex data; gate this append on a selection that includes Codex/OpenCodex.
Useful? React with 👍 / 👎.
| if let requests = self.requestCount, requests > 0 { | ||
| let priced = if self.costUSD != nil { | ||
| max(0, requests - unpriced - unmetered - estimated) | ||
| } else { | ||
| 0 |
There was a problem hiding this comment.
Count requests with missing prices as unpriced
For an entry with a positive requestCount, token usage, and costUSD == nil, the new fallback returns four zero counters instead of counting those requests as unpriced. Cursor produces exactly such rows when all events omit totalCents; for mixed days its existing known-cost accumulator also keeps a non-nil partial cost without emitting an unpriced counter, causing every request to be reported as priced. Propagate missing-price request counts or conservatively classify the uncovered requests so coverage cannot claim zero gaps.
Useful? React with 👍 / 👎.
| hourlyPoints: Self.hourlyPoints( | ||
| inputs: visibleInputs, | ||
| days: days, | ||
| now: now, | ||
| calendar: calculationCalendar), |
There was a problem hiding this comment.
Render the computed hourly activity series
The model computes and stores hourlyPoints, but a repo-wide search finds no consumer outside this property, builder, and helper; the dashboard still renders only tokenActivity through the daily/weekly/cumulative heatmap. Consequently the advertised hourly activity heatmap is unavailable in every configuration, so this series needs to be wired into a view rather than remaining dead model data.
Useful? React with 👍 / 👎.
Summary
This PR lands @Yuxin-Qiao's five-PR Usage & Spend stack as one current-main integration:
The original PRs shared one CI failure cause: their ProviderArchitectureGatekeeper anchors predated #3012 and #3014. This integration refreshes every shifted anchor/fingerprint and documents the genuinely new provider-specific clusters.
Review fixes
Thanks @Yuxin-Qiao for the complete stacked series and its regression coverage.
Validation
swiftformat Sources Testsswiftlint --strictmake checkswift test --filter 'CLICostTests|ProviderArchitectureGatekeeper'— 65 tests passedswift test --filter CostUsageBoundedProgressTests— 10 tests passedswift test --filter CostUsageStoreScaleProofTests— 3 tests passedmake test— 889 selections passed in 75 groups, with zero retries or timeoutsThe broad concurrent focused regex run completed the stack-specific suites successfully but loaded two existing performance gates heavily; both passed immediately in the isolated runs listed above.