Skip to content

Integrate spend reporting series (#3015–#3019) - #3026

Merged
steipete merged 17 commits into
mainfrom
fix/spend-series-3015-3019
Aug 18, 2026
Merged

Integrate spend reporting series (#3015–#3019)#3026
steipete merged 17 commits into
mainfrom
fix/spend-series-3015-3019

Conversation

@steipete

Copy link
Copy Markdown
Owner

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

  • Keeps all OpenCodex source access read-only. The SQLite cache now lives under CodexBar's own cache directory and never creates or writes beneath OPENCODEX_HOME or ~/.opencodex.
  • Preserves partial custom-pricing rows as unknown when a required token-class rate is missing; an explicit zero remains free, and overlay fingerprints invalidate pricing caches.
  • Confirms timezone changes rebuild cached rows from raw events instead of shifting or combining existing day buckets.
  • Keeps OpenCodex JSON opt-in and summarizes JSON coverage/provenance with the same pinned bucket calendar used by the scanner.
  • Preserves the newer Fix Claude vendor pricing after #3002 #3012 vendor-pricing and feat: add Grok SuperGrok paste and source picker #3014 account/config semantics from main.

Thanks @Yuxin-Qiao for the complete stacked series and its regression coverage.

Validation

  • swiftformat Sources Tests
  • swiftlint --strict
  • make check
  • swift test --filter 'CLICostTests|ProviderArchitectureGatekeeper' — 65 tests passed
  • swift test --filter CostUsageBoundedProgressTests — 10 tests passed
  • swift test --filter CostUsageStoreScaleProofTests — 3 tests passed
  • make test — 889 selections passed in 75 groups, with zero retries or timeouts
  • Autoreview: clean, no accepted/actionable findings

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

Yuxin-Qiao and others added 17 commits August 18, 2026 02:00
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>
Land the #3015-#3019 stack with refreshed architecture gates and repaired cache, pricing, and export contracts.

Co-authored-by: Yuxin Qiao <104957188+Yuxin-Qiao@users.noreply.github.com>
@clawsweeper

clawsweeper Bot commented Aug 18, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

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

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. 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 Aug 18, 2026
@clawsweeper

clawsweeper Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codex review: needs changes before merge. Reviewed August 17, 2026, 8:54 PM ET / August 18, 2026, 00:54 UTC.

ClawSweeper review

What this changes

This PR integrates spend provenance, custom pricing, an opt-in OpenCodex log source, dashboard reporting controls, and expanded cost JSON output.

Merge readiness

⚠️ Ready for maintainer review - 3 items remain

Keep open: an OpenCodex usage record with class-level counts but no total undercounts reasoning tokens in the dashboard and CLI payload.

Priority: P2
Reviewed head: 04affe82b437f0100bba8320ca563dd420fc5972

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The integration has strong stated automated validation but contains one focused reporting-correctness defect.
Proof confidence 🌊 off-meta tidepool Not applicable: This maintainer-authored PR has substantial reported automated validation; the external-contributor proof gate does not apply.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Verification

Check Result Evidence
Real behavior Not applicable Not applicable: This maintainer-authored PR has substantial reported automated validation; the external-contributor proof gate does not apply.
Evidence reviewed 4 items Reasoning is omitted from fallback totals: When an OpenCodex row lacks totalTokens, the fallback sums input, output, cache-read, and cache-write tokens but omits reasoningOutputTokens.
The omitted value feeds user-visible totals: The aggregator uses resolvedTotalTokens for daily, session, and model totals while separately preserving reasoning tokens.
Fixture semantics include reasoning in total tokens: The added parser fixture represents five input, one output, and three reasoning tokens as a total of nine, confirming reasoning belongs in a derived total when an explicit total is unavailable.
Findings 1 actionable finding [P2] Include reasoning in derived OpenCodex totals
Security None None.

How this fits together

CodexBar 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]
Loading

Before merge

  • Include reasoning in derived OpenCodex totals (P2) - When totalTokens is absent, this fallback omits reasoningOutputTokens, even though the parser fixtures treat reasoning as part of the total. Those rows therefore under-report daily, session, model, dashboard, and JSON token totals; add the reasoning count and cover the no-explicit-total case.
  • Resolve merge risk (P1) - OpenCodex records that omit totalTokens will under-report token totals whenever reasoningOutputTokens is present.
  • Complete next step (P2) - A small, source-proven correction and regression test can repair the only identified blocker without changing product direction.

Findings

  • [P2] Include reasoning in derived OpenCodex totals — Sources/CodexBarCore/Vendored/OpenCodexUsage/OpenCodexUsageModels.swift:45-50
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Change volume 75 files affected; production +2,910/-298, tests +940/-69 The combined integration spans scanner persistence, UI, CLI, and tests, so the focused reporting regression should be fixed before merge.

Root-cause cluster

Relationship: canonical
Canonical: #3026
Summary: This PR is the intended combined integration for five overlapping stacked spend-reporting PRs; the remaining defect is within the combined OpenCodex implementation.

Members:

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

Merge-risk options

Maintainer options:

  1. Decide the mitigation before merge
    Include reasoningOutputTokens in the derived OpenCodex total and add a regression fixture with no explicit total before merging.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best 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:

  • [P2] Include reasoning in derived OpenCodex totals — Sources/CodexBarCore/Vendored/OpenCodexUsage/OpenCodexUsageModels.swift:45-50
    When totalTokens is absent, this fallback omits reasoningOutputTokens, even though the parser fixtures treat reasoning as part of the total. Those rows therefore under-report daily, session, model, dashboard, and JSON token totals; add the reasoning count and cover the no-explicit-total case.
    Confidence: 0.98

Overall correctness: patch is incorrect
Overall confidence: 0.98

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 318d88db29fe.

Labels

Label changes:

  • add P2: The new optional reporting path can produce inaccurate token totals but does not affect core runtime availability.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🌊 off-meta tidepool and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: This maintainer-authored PR has substantial reported automated validation; the external-contributor proof gate does not apply.

Label justifications:

  • P2: The new optional reporting path can produce inaccurate token totals but does not affect core runtime availability.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🌊 off-meta tidepool and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: This maintainer-authored PR has substantial reported automated validation; the external-contributor proof gate does not apply.

Evidence

Acceptance criteria:

  • [P1] CODEXBAR_SUPPRESS_TEST_KEYCHAIN_ACCESS=1 swift test --filter OpenCodexUsageParserTests.
  • [P1] CODEXBAR_SUPPRESS_TEST_KEYCHAIN_ACCESS=1 make check.
  • [P1] CODEXBAR_SUPPRESS_TEST_KEYCHAIN_ACCESS=1 make test.

What I checked:

Likely related people:

  • Yuxin-Qiao: The PR’s OpenCodex parser and reporting commits are authored by Yuxin Qiao, and local feature-history sampling shows the largest contribution count across the affected paths. (role: feature implementation contributor; confidence: high; commits: 197bd61ddb40, a532d413d35e; files: Sources/CodexBarCore/Vendored/OpenCodexUsage/OpenCodexUsageModels.swift, Sources/CodexBarCore/Vendored/OpenCodexUsage/OpenCodexUsageAggregator.swift)
  • steipete: Peter Steinberger integrated the stack at the current PR head and has recent history on the dashboard and CLI integration paths. (role: integration owner and recent area contributor; confidence: high; commits: bbb5cd73af04, 04affe82b437; files: Sources/CodexBar/SpendDashboardController.swift, Sources/CodexBarCLI/CLICostCommand.swift)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Add the derived-total regression fixture and rerun the focused OpenCodex parser tests plus the required suite.

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.

@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: 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".

Comment on lines +465 to +466
if summary.totalCost != nil {
sawEstimate = 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.

P1 Badge 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 👍 / 👎.

Comment on lines +123 to +128
if format == .json,
let openCodex = Self.loadOpenCodexCostPayload(
historyDays: historyDays,
calendar: bucketCalendar)
{
payload.append(openCodex)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +432 to +436
if let requests = self.requestCount, requests > 0 {
let priced = if self.costUSD != nil {
max(0, requests - unpriced - unmetered - estimated)
} else {
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 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 👍 / 👎.

Comment on lines +331 to +335
hourlyPoints: Self.hourlyPoints(
inputs: visibleInputs,
days: days,
now: now,
calendar: calculationCalendar),

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 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 👍 / 👎.

@steipete
steipete merged commit 4dd5e42 into main Aug 18, 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. 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