Skip to content

Surface token mix, coverage, sessions, and OpenCodex on the spend dashboard - #3017

Merged
steipete merged 12 commits into
steipete:mainfrom
Yuxin-Qiao:feat/spend-b-dashboard
Aug 18, 2026
Merged

Surface token mix, coverage, sessions, and OpenCodex on the spend dashboard#3017
steipete merged 12 commits into
steipete:mainfrom
Yuxin-Qiao:feat/spend-b-dashboard

Conversation

@Yuxin-Qiao

@Yuxin-Qiao Yuxin-Qiao commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add Input/Output/Cache/Reasoning mix, coverage chips, 90-day range, and heatmap day drill-down.
  • Show sessions, Codex projects, and plan-metered vs list-price columns without calling them billed.
  • Wire the opt-in OpenCodex source and dual-ledger toggle so proxy logs stay on a separate row.

Stacked PR 4/5 (Wave B). Depends on the OpenCodex parser PR; keep 7/30/90/All and the existing 365-day scan window.

Review follow-up

  • KPI metered spend is shown only for the full snapshot window (selectedDay == nil && days >= snapshot.historyDays).
  • Hidden sources still appear in the filter (availableSources).
  • Uncovered heatmap days do not produce a drill-down selection.
  • OpenCodex-only still loads when costUsageEnabled and openCodexUsageLogsEnabled are on, even with empty providerIDs.
  • Cached Codex dashboard loads keep the pinned calendar.

Test plan

Fixtures only. No Keychain, no live accounts, no ~/.opencodex.

CODEXBAR_SUPPRESS_TEST_KEYCHAIN_ACCESS=1 swift test --filter \
  'metered spend stays on the snapshot window|uncovered heatmap days do not produce|OpenCodex-only configuration still starts a dashboard load'
✔ metered spend stays on the snapshot window instead of a shorter range
✔ uncovered heatmap days do not produce a drill-down selection
✔ OpenCodex-only configuration still starts a dashboard load
  • Focused dashboard/heatmap/OpenCodex-only tests above
  • CODEXBAR_SUPPRESS_TEST_KEYCHAIN_ACCESS=1 swift test --filter SpendDashboardModelTests --filter ShareStatsTests
  • Token mix shows — when classes are missing, not a fake split of total
  • Coverage-gap heatmap days are not clickable as zero activity
  • OpenCodex and native Codex remain two groups when both have data

Co-authored-by: Cursor <cursoragent@cursor.com>
@clawsweeper

clawsweeper Bot commented Aug 17, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

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

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

if let meteredCost = summary.input.snapshot.meteredCostUSD {
sawMetered = true
metered = (metered ?? 0) + meteredCost * summary.costMultiplier

P1 Badge Scope metered spend to the selected range

For Cursor, meteredCostUSD covers the snapshot's full fetch window, which the spend-dashboard loader fixes at SpendDashboardSource.scanDays (365 days). Adding that value directly here means the “Plan metered” figure remains the 365-day total when the user selects 7, 30, or 90 days—or drills into one day—while the neighboring estimated spend is windowed from daily entries. This presents spend for the wrong period; metered costs need daily buckets or should be withheld where the requested window differs from the snapshot window.


private var sourceIDs: [String] {
Array(Set(self.model.groups.flatMap(\.providers).map(\.id))).sorted()
}

P2 Badge Keep hidden sources available for re-enabling

When a user unchecks a source, its ID is persisted in spendDashboardHiddenSourceIDs, the model rebuild filters that provider out, and this list is then recomputed only from the already-filtered model. The unchecked source therefore disappears from the filter UI immediately and cannot be checked again without manually clearing defaults. Build the choices from the loaded/unfiltered source inventory, or retain metadata for hidden IDs.


private func handleTap(at location: CGPoint, pitch: CGFloat) {
guard let onSelectDay, let index = self.cellIndex(at: location, pitch: pitch) else { return }
let day = self.series.date(at: index).map { self.series.calendar.startOfDay(for: $0) }
onSelectDay(day == self.selectedDay ? nil : day)

P2 Badge Reject taps on uncovered heatmap days

When a visible day has series.isCovered[index] == false, cellIndex still returns it because it checks only the date's visibility, so tapping an “Unavailable” coverage-gap cell calls selectDay. The resulting drill-down has no established data and can make an unknown day appear like zero activity; require coverage before invoking the selection callback.

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Aug 17, 2026
@clawsweeper

clawsweeper Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed August 17, 2026, 4:12 PM ET / 20:12 UTC.

ClawSweeper review

What this changes

The PR adds token mix, coverage, sessions, source filtering, a 90-day range, and opt-in OpenCodex usage to CodexBar’s spend dashboard.

Merge readiness

Blocked until real behavior proof from a real setup is added - 12 items remain

Keep open. The feature is not on current main, but four current-head reporting defects and missing real dashboard proof block merge; the broadened OpenCodex and custom-pricing scope also needs product confirmation.

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

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The branch has useful fixture coverage but several reporting defects and no real after-fix dashboard proof.
Proof confidence 🦪 silver shellfish (2/6) Needs real behavior proof before merge: The PR body provides fixture-based Swift test output only; add redacted after-fix dashboard proof showing filtering, day drill-down, and native/OpenCodex separation before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🦪 silver shellfish (2/6) 4 actionable review findings remain.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: The PR body provides fixture-based Swift test output only; add redacted after-fix dashboard proof showing filtering, day drill-down, and native/OpenCodex separation before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 5 items Current-main check: This capability is introduced by the PR branch rather than current main; the diff adds the new provenance model and dashboard aggregation surface.
Selected-day scope defect: Provider rows are built from full-range summaries before selected-day summaries are computed, while those rows supply the displayed group totals.
Provenance defect: The dashboard treats every non-nil daily cost as an estimate even though snapshots explicitly carry vendor-metered provenance; the shared window helper already distinguishes these cases.
Findings 4 actionable findings [P2] Preserve vendor-reported provenance in dashboard groups
[P2] Propagate unknown token classes through aggregation
[P2] Honor matching partial pricing overrides
Security None None.

How this fits together

The spend dashboard combines cached provider snapshots with persisted dashboard settings to produce time-windowed totals, rows, charts, and heatmap drill-downs. Those derived values then feed the native SwiftUI preferences pane and its JSON export.

flowchart LR
A[Provider usage snapshots] --> C[Dashboard loader]
B[Dashboard settings] --> C
C --> D[Windowed spend model]
D --> E[Totals and breakdowns]
D --> F[Heatmap day selection]
E --> G[Dashboard and export]
F --> G
Loading

Decision needed

Question Recommendation
Should CodexBar core own the combined OpenCodex local-log cache and custom-pricing overlay alongside this spend-dashboard expansion, or should those capabilities be separately approved and landed? Split and sponsor the dashboard path: Keep the dashboard reporting work, but require separately scoped approval for OpenCodex persistence and custom pricing before they become core behavior.

Why: The branch introduces two durable user-facing data/configuration surfaces in addition to dashboard presentation, so a code-only review cannot establish the intended long-term product boundary.

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: The PR body provides fixture-based Swift test output only; add redacted after-fix dashboard proof showing filtering, day drill-down, and native/OpenCodex separation before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Preserve vendor-reported provenance in dashboard groups (P2) - A vendor-metered snapshot with ordinary daily costs but no separate meteredCostUSD sets sawEstimate, so the group is labeled list-price (and mixed groups are mislabeled). Derive the selected-window result from each snapshot’s costProvenance.
  • Propagate unknown token classes through aggregation (P2) - nil is documented as an unestablished token class, but add keeps a known subtotal when another entry is nil. Aggregated dashboard and model mix values can therefore look complete while omitting a source or day; retain unknownness once an included contribution lacks the class.
  • Honor matching partial pricing overrides (P2) - A matching override that lacks a rate needed by a row returns nil, then this path falls back to bundled/models.dev rates. That contradicts the overlay’s missing-rate-is-unknown contract and can display a price the user did not define; fall back only when no override matched.
  • Scope all display totals to the selected day (P2) - Provider rows are built from summaries before scopedSummaries is applied, and those full-range rows drive the headline totals; projects and sessions are also built from the unscoped collection. Selecting a heatmap day therefore mixes day-level breakdowns with range-level totals and export values.
  • Resolve merge risk (P1) - A selected heatmap day currently leaves headline totals, subscriptions, sessions, projects, and exported provider values on the wider range.
  • Resolve merge risk (P1) - Vendor-reported spend can be labeled as a list-price estimate, and a partial user pricing override can silently substitute default prices.
  • Resolve merge risk (P1) - The PR adds persisted settings, a local SQLite cache, and pricing behavior without after-fix proof from a real dashboard setup.
  • Complete next step (P2) - Maintainer confirmation of the combined OpenCodex and custom-pricing scope is needed before a repair lane should reshape this broad feature branch.
  • Improve patch quality - Fix the four aggregation and accounting findings with focused regressions.
  • Improve patch quality - Provide a redacted real dashboard screenshot, recording, or runtime output; update the PR body to trigger re-review, or ask a maintainer to comment @clawsweeper re-review if needed.

Findings

  • [P2] Preserve vendor-reported provenance in dashboard groups — Sources/CodexBar/SpendDashboardModel.swift:464-471
  • [P2] Propagate unknown token classes through aggregation — Sources/CodexBarCore/CostProvenance.swift:116-121
  • [P2] Honor matching partial pricing overrides — Sources/CodexBarCore/Vendored/CostUsage/CostUsagePricing+Overlay.swift:14-27
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Changed surface 70 files, +3,975 / -291 lines The change crosses dashboard UI, aggregation, settings, local storage, localization, and Core parsing.
Production versus tests production +2,710/-285; tests +761/-6; resources +504/-0 Most growth is production behavior, so the fixture-only test plan does not yet provide proportional real-behavior confidence.

Merge-risk options

Maintainer options:

  1. Repair accounting and day-scope contracts (recommended)
    Use selected-day summaries for every displayed day-scoped value, retain vendor provenance, and make matching partial overrides fail unknown rather than fall back.
  2. Reduce the feature boundary
    Split the OpenCodex cache and custom-pricing configuration from the dashboard presentation work if maintainers do not want those new core surfaces together.

Technical review

Best possible solution:

Stage the approved dashboard direction into a narrower, consistently scoped reporting implementation, preserve unknown and vendor-reported accounting semantics, and attach redacted real-dashboard proof before merge.

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

Yes, from source: a vendor-metered snapshot without meteredCostUSD, a partial matching custom price, or a selected heatmap day reaches the incorrect reporting paths. These source reproductions were not executed because this is a read-only review.

Is this the best way to solve the issue?

No. The current combined path has inconsistent accounting semantics and needs a maintainer decision on the new persistent OpenCodex and pricing-config surfaces; a staged, tested implementation is safer.

Full review comments:

  • [P2] Preserve vendor-reported provenance in dashboard groups — Sources/CodexBar/SpendDashboardModel.swift:464-471
    A vendor-metered snapshot with ordinary daily costs but no separate meteredCostUSD sets sawEstimate, so the group is labeled list-price (and mixed groups are mislabeled). Derive the selected-window result from each snapshot’s costProvenance.
    Confidence: 0.99
  • [P2] Propagate unknown token classes through aggregation — Sources/CodexBarCore/CostProvenance.swift:116-121
    nil is documented as an unestablished token class, but add keeps a known subtotal when another entry is nil. Aggregated dashboard and model mix values can therefore look complete while omitting a source or day; retain unknownness once an included contribution lacks the class.
    Confidence: 0.98
  • [P2] Honor matching partial pricing overrides — Sources/CodexBarCore/Vendored/CostUsage/CostUsagePricing+Overlay.swift:14-27
    A matching override that lacks a rate needed by a row returns nil, then this path falls back to bundled/models.dev rates. That contradicts the overlay’s missing-rate-is-unknown contract and can display a price the user did not define; fall back only when no override matched.
    Confidence: 0.99
  • [P2] Scope all display totals to the selected day — Sources/CodexBar/SpendDashboardModel.swift:429-430
    Provider rows are built from summaries before scopedSummaries is applied, and those full-range rows drive the headline totals; projects and sessions are also built from the unscoped collection. Selecting a heatmap day therefore mixes day-level breakdowns with range-level totals and export values.
    Confidence: 0.99

Overall correctness: patch is incorrect
Overall confidence: 0.99

AGENTS.md: found and applied where relevant.

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

Labels

Label justifications:

  • P2: The defects can misstate spend-dashboard reporting but do not create an emergency availability or security failure.
  • merge-risk: 🚨 compatibility: Persisted dashboard settings and custom pricing can change how existing local usage data and user-defined rates are interpreted.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body provides fixture-based Swift test output only; add redacted after-fix dashboard proof showing filtering, day drill-down, and native/OpenCodex separation before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

Likely related people:

  • steipete: Recent main-history commits corrected partial spend totals and dashboard architecture coverage. (role: recent area contributor; confidence: high; commits: 6407d3ce3346, af4430df5d7d; files: Sources/CodexBar/SpendDashboardModel.swift)
  • Yuxin-Qiao: Prior merged spend-dashboard range work and the current branch both touch the dashboard model. (role: feature-history contributor; confidence: high; commits: 0b0279c6eba2, b8a0652aad66; files: Sources/CodexBar/SpendDashboardModel.swift, Sources/CodexBarCore/CostProvenance.swift)

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-08-17T18:22:37.538Z sha 2c6d24f :: needs real behavior proof before merge. :: [P1] Scope plan-metered spend to the selected range | [P2] Keep hidden sources available for re-enabling | [P2] Reject taps on uncovered heatmap days

Yuxin-Qiao and others added 11 commits August 18, 2026 02:53
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>
@Yuxin-Qiao
Yuxin-Qiao force-pushed the feat/spend-b-dashboard branch from 2c6d24f to b8a0652 Compare August 17, 2026 19:26
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 17, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@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: b8a0652aad

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +468 to +472
let provenance: CostProvenance = switch (sawMetered, sawEstimate) {
case (true, true): .mixed
case (true, false): .vendorMetered
case (false, true): .listPriceEstimate
case (false, false): .unknown

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 Preserve vendor-reported provenance in currency groups

When OpenAI Admin, Mistral, or Groq supplies a snapshot marked .vendorMetered, its ordinary daily cost makes sawEstimate true while sawMetered remains false because that flag only checks the separate meteredCostUSD field. The dashboard therefore labels vendor-reported spend as listPriceEstimate, and a group combining that spend with actual estimates is also mislabeled instead of .mixed; derive this result from each snapshot's costProvenance for the selected window.

Useful? React with 👍 / 👎.

Comment on lines +116 to +121
public mutating func merge(_ other: CostUsageTokenMix) {
self.inputTokens = Self.add(self.inputTokens, other.inputTokens)
self.outputTokens = Self.add(self.outputTokens, other.outputTokens)
self.cacheReadTokens = Self.add(self.cacheReadTokens, other.cacheReadTokens)
self.cacheCreationTokens = Self.add(self.cacheCreationTokens, other.cacheCreationTokens)
self.reasoningTokens = Self.add(self.reasoningTokens, other.reasoningTokens)

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 Keep incomplete token classes unknown when aggregating

When multiple days or providers are merged and one reports a token class while another leaves that class nil, add treats the missing value as an identity and publishes the known subtotal. This contradicts the type's nil-means-unestablished contract and makes the new dashboard token-mix fields appear complete even though they omit part of the selected usage; aggregation needs to distinguish the initially empty accumulator from an unknown contribution.

Useful? React with 👍 / 👎.

Comment on lines +14 to +23
if let cost = (customPricing ?? self.customPricingOverlay()).estimatedCodexCostUSD(
model: model,
inputTokens: inputTokens,
cachedInputTokens: cachedInputTokens,
outputTokens: outputTokens,
cacheWriteInputTokens: cacheWriteInputTokens)
{
return cost
}
guard let pricing = self.resolvedCodexPricing(

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 Stop falling back after a matching partial pricing override

If custom-pricing.json contains a matching model entry but omits a rate needed by the current row—for example, it specifies only input while the request has output tokens—estimatedCodexCostUSD returns nil and this wrapper silently prices the row with bundled/models.dev rates. That violates the overlay's stated missing-field-is-unknown behavior and can produce costs the user explicitly declined to define; both this path and the analogous aggregate path should only fall back when no override entry matched.

Useful? React with 👍 / 👎.

Comment on lines 429 to +430
let providers = Self.providerRows(summaries)
let modelSummaries = summaries.filter { summary in
let scopedSummaries = Self.summaries(summaries, matching: selectedDay)

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 Scope all dashboard totals to the selected day

After a heatmap day is selected, only model rows, token mix, and coverage use scopedSummaries; provider rows are built from the full-window summaries, and those rows subsequently drive the displayed total spend and tracked-token totals. The UI therefore shows a selected date next to day-scoped breakdowns while retaining 7/30/90-day headline and subscription values (and the export carries that inconsistent state), so the selected-day scope should be applied consistently or clearly limited to a separate drill-down.

Useful? React with 👍 / 👎.

@steipete
steipete merged commit b8a0652 into steipete:main Aug 18, 2026
7 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants