Skip to content

Price unreported Cursor events and show real spend coverage - #3129

Open
Yuxin-Qiao wants to merge 10 commits into
steipete:mainfrom
Yuxin-Qiao:codex/spend-pricing-fallback
Open

Price unreported Cursor events and show real spend coverage#3129
Yuxin-Qiao wants to merge 10 commits into
steipete:mainfrom
Yuxin-Qiao:codex/spend-pricing-fallback

Conversation

@Yuxin-Qiao

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

Copy link
Copy Markdown
Contributor

Summary

  • Add CostUsagePricing.listPriceFallbackCostUSD, a shared catalog-only fallback that resolves an unreported cost from the bundled Codex/OpenAI table first and Claude/first-party models.dev routing second. No network access and no provider-name literals.
  • Price Cursor events whose vendor omitted totalCents from that fallback. Estimated events now contribute their list-price value to daily cost and are counted via the existing estimatedRequestCount field; models absent from both tables stay honestly nil.
  • Stop zeroing the overview coverage line when some selected providers have no spend data. It now reports the real minimum covered day count across providers, so partial subscriptions show e.g. Coverage: 30 / 30 instead of a misleading Coverage: 0 / 30.
  • Fix disjoint cache accounting: Codex route folds Cursor cache tokens into total input (subset contract), Claude route keeps disjoint counters (input/cacheRead/cacheCreation) to avoid double-billing cached Muse events.
  • Track catalog-missing events as unpricedRequestCount so a mixed priced/unpriced day does not report the missing-price request as priced via coverage.
  • Classify rejected reported costs (negative or non-finite totalCents) as unpriced.
  • Isolate Cursor estimates from Codex custom pricing: pass customPricing: .empty to the Codex lookup so a user’s custom-pricing.json (exact or partial) cannot change Cursor’s catalog-only estimate, preserving the documented boundary.

Real behavior proof (after fix, catalog-only, redacted)

No live Cursor cookie is stored in this repo; proof is via deterministic daily aggregation from the same code path the app uses for CursorUsageEventsFetcher.makeDailyReport. All values are computed from bundled pricing tables, no network.

# Case A: cached Muse event without vendor cost (disjoint pricing)
input=100 cacheRead=200 cacheCreation=300 output=50 model=claude-sonnet-4-20250514
bundled claudeCostUSD = 0.002235
dailyReport: costUSD=0.002235 estimatedRequestCount=1

# Case B: mixed priced + catalog-missing same day
day events: [claude-4.5-sonnet 100c (priced), fixture-model nil (missing catalog)]
dailyReport: costUSD=1.0 requestCount=2 unpricedRequestCount=1
coverageCounts: priced=1 unpriced=1

# Case C: mixed valid + rejected cost same day
day events: [claude-4.5-sonnet 100c (valid), gpt-5 -1c (rejected)]
dailyReport: costUSD=1.0 requestCount=2 unpricedRequestCount=1
coverageCounts: priced=1 unpriced=1

# Case D: Cursor with custom-pricing overlay (catalog-only)
custom-pricing.json contains exact gpt-5 entry and partial entry
Cursor event gpt-5 200 input 20 output nil -> still priced from bundled catalog 0.00045, not overlay

Focused regressions:

  • estimatesPriceCachedClaudeTokensWithoutDoubleBilling
  • mixedPricedAndCatalogMissingDayCountsUnpricedRequests
  • mixedValidAndRejectedCostCountsUnpricedRequests

Commands

  • swift test --filter CursorUsageEventsFetcherTests - 33/33 passed
  • swift test --filter OverviewSpendSummaryTests - 5/5 passed
  • swift test --filter ProviderArchitectureGatekeeperTests - 38/38 passed
  • swiftformat Sources Tests
  • swiftlint --strict - 0 violations
  • ./Scripts/lint.sh lint - passes

@clawsweeper

clawsweeper Bot commented Aug 21, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

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

@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: 9fb5d824e6

ℹ️ 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 +624 to +626
inputTokens: usage.inputTokens,
cachedInputTokens: usage.cacheReadTokens,
cacheWriteInputTokens: usage.cacheWriteTokens,

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 Cursor's disjoint cache-token accounting

When an unpriced OpenAI event contains cache tokens, this passes Cursor's disjoint counters directly to codexCostUSD, whose contract treats cached and cache-write tokens as subsets of inputTokens. Cursor instead computes totals by adding all four counters, so an event with 100 input and 900 cache-read tokens is priced as only 100 cached tokens, dropping the uncached input and 800 cached tokens. Normalize the counters to Codex's total-input convention, or use pricing logic that accepts disjoint counters, before publishing the estimate.

Useful? React with 👍 / 👎.

var modelsForDay = days[dayKey] ?? [:]
var accumulator = modelsForDay[model] ?? ModelAccumulator()
accumulator.add(usage)
accumulator.add(usage, estimatedCents: Self.estimatedListPriceCents(for: usage, model: model))

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 Pass the event date into fallback pricing

For historical Cursor events without totalCents, this call omits the event timestamp even though the fallback exposes pricingDate. It therefore always uses current rates; for example, GPT-5.6 Terra/Luna events before the 2026-07-30 cutoff are repriced using the post-cut rates, and the normal 30-day Cursor window can span that boundary. Pass the already-derived event date through so each estimate uses the tariff effective when the usage occurred.

Useful? React with 👍 / 👎.

@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 21, 2026
@clawsweeper

clawsweeper Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codex review: needs changes before merge. Reviewed August 22, 2026, 6:42 AM ET / 10:42 UTC.

ClawSweeper review

What this changes

This PR estimates missing Cursor event costs from bundled model catalogs, improves spend coverage reporting, and tracks priced versus unpriced request coverage.

Merge readiness

⚠️ Needs maintainer review before merge - 3 items remain

Keep open: malformed non-finite Cursor costs are still treated as missing and replaced with catalog estimates, so one P2 correction is needed before merge.

Priority: P2
Reviewed head: 3fa975aecf317e805c432ebdeed26892cae10b01

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The patch has focused proof and regressions, but the malformed-cost classification defect blocks merge readiness.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (live_output): The PR body provides redacted deterministic after-fix aggregation output from the production daily-report path, including cached-token, mixed-coverage, rejected-cost, and custom-pricing cases.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Verification

Check Result Evidence
Real behavior Verified Sufficient (live_output): The PR body provides redacted deterministic after-fix aggregation output from the production daily-report path, including cached-token, mixed-coverage, rejected-cost, and custom-pricing cases.
Evidence reviewed 5 items Malformed values collapse to missing: The lenient numeric decoder returns nil for non-finite numeric strings, so it does not preserve the distinction between an absent totalCents field and a malformed present value.
Fallback consumes collapsed state: The new fallback estimates whenever totalCents is nil; therefore a known-model event carrying "NaN" or "Infinity" is counted as estimated instead of unpriced.
Existing test demonstrates the prerequisite: The invalid-number decoding test asserts that string "Infinity" becomes totalCents == nil, but does not exercise the new known-model catalog fallback afterward.
Findings 1 actionable finding [P2] Preserve invalid totalCents instead of estimating it
Security None None.

Live Verification

Command: swift test --filter CursorUsageEventsFetcherTests

Result: FAIL (failed) — execution before step 1 run: sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz

sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.22.0.tgz

Assertions:

  • FAIL expect_output: CursorUsageEventsFetcherTests

How this fits together

Cursor usage events are decoded into daily cost reports, which feed the cached spend history and the overview dashboard. The new fallback sits between event decoding and daily aggregation, assigning a catalog estimate when Cursor has no vendor cost.

flowchart LR
    A[Cursor usage event] --> B[Event cost decoder]
    B --> C{Vendor cost state}
    C -->|Missing| D[Catalog price fallback]
    C -->|Valid| E[Reported cost]
    C -->|Invalid| F[Unpriced request]
    D --> G[Daily cost report]
    E --> G
    F --> G
    G --> H[Spend dashboard and cache]
Loading

Before merge

  • Preserve invalid totalCents instead of estimating it (P2) - CursorEventNumber.double turns present non-finite strings such as "NaN" and "Infinity" into nil. This new nil check then treats them as omitted vendor costs and catalog-prices known models, reporting them as estimated rather than unpriced. Preserve field presence or an invalid-cost state before this fallback, and cover the decoded JSON path.
  • Resolve merge risk (P1) - Known-model events with malformed non-finite vendor costs can display a catalog estimate, masking rejected provider data as priced coverage.
  • Complete next step (P2) - A narrow decoder-state and regression-test repair can resolve the remaining merge blocker without changing the intended catalog fallback.

Findings

  • [P2] Preserve invalid totalCents instead of estimating it — Sources/CodexBarCore/Providers/Cursor/CursorUsageEventsFetcher.swift:649
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production versus test growth production +101/-9, tests +145/-11 The catalog fallback and persisted coverage representation are accompanied by substantial focused regression coverage.

Merge-risk options

Maintainer options:

  1. Preserve malformed-cost state (recommended)
    Track whether totalCents was present but invalid, estimate only absent or null values, and add JSON decoding regressions for non-finite strings.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Track totalCents presence during decoding; estimate only when absent or null; add regressions for string NaN and Infinity values.

Technical review

Best possible solution:

Represent vendor cost as missing, valid, or invalid so only genuinely absent or null values receive a catalog estimate and malformed values remain unpriced.

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

Yes—source inspection gives a high-confidence path: decode a known-model Cursor event with string "NaN" or "Infinity" totalCents, then aggregate it; the decoder yields nil and the new fallback prices it.

Is this the best way to solve the issue?

No—the fallback is appropriate for genuinely omitted costs, but it must not treat malformed reported costs as omissions.

Full review comments:

  • [P2] Preserve invalid totalCents instead of estimating it — Sources/CodexBarCore/Providers/Cursor/CursorUsageEventsFetcher.swift:649
    CursorEventNumber.double turns present non-finite strings such as "NaN" and "Infinity" into nil. This new nil check then treats them as omitted vendor costs and catalog-prices known models, reporting them as estimated rather than unpriced. Preserve field presence or an invalid-cost state before this fallback, and cover the decoded JSON path.
    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 27c7f334e3c4.

Labels

Label justifications:

  • P2: The incorrect classification affects spend accuracy and coverage for malformed Cursor cost events, but has bounded scope.
  • merge-risk: 🚨 compatibility: Merging changes displayed historical Cursor spend and coverage classifications for existing cached event data.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (live_output): The PR body provides redacted deterministic after-fix aggregation output from the production daily-report path, including cached-token, mixed-coverage, rejected-cost, and custom-pricing cases.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body provides redacted deterministic after-fix aggregation output from the production daily-report path, including cached-token, mixed-coverage, rejected-cost, and custom-pricing cases.

Evidence

Acceptance criteria:

  • [P1] swift test --filter CursorUsageEventsFetcherTests.
  • [P1] swift test --filter OverviewSpendSummaryTests.
  • [P1] ./Scripts/lint.sh lint.

What I checked:

Likely related people:

  • Ethan Clinick: Introduced the Cursor token-cost report that this fallback extends. (role: feature introducer; confidence: high; commits: 2209a9b63945; files: Sources/CodexBarCore/Providers/Cursor/CursorUsageEventsFetcher.swift)
  • Yuxin Qiao: Prior Cursor cost-invalidity and spend-cache work appears in the feature history before this PR's final correction. (role: recent adjacent contributor; confidence: medium; commits: f6395d05b663, 0d7af47ec882; files: Sources/CodexBarCore/Providers/Cursor/CursorUsageEventsFetcher.swift, Sources/CodexBarCore/CostUsageModels.swift)

Rank-up moves

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

  • Preserve invalid totalCents presence and add a regression proving known models with string NaN or Infinity remain unpriced.

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 (8 earlier review cycles)
  • reviewed 2026-08-21T20:02:26.749Z sha 9fb5d82 :: needs real behavior proof before merge. :: [P1] Preserve Cursor's disjoint cache-token accounting | [P2] Pass each event date to fallback pricing
  • reviewed 2026-08-21T20:14:14.940Z sha a8b565e :: needs real behavior proof before merge. :: [P1] Normalize Cursor cache counters before OpenAI pricing | [P2] Pass the event date into fallback pricing
  • reviewed 2026-08-21T22:04:00.414Z sha 7eed14f :: needs real behavior proof before merge. :: [P1] Keep Cursor cache counters disjoint for Claude pricing | [P2] Mark catalog-missing Cursor events as unpriced
  • reviewed 2026-08-22T02:06:07.305Z sha 45160c5 :: needs real behavior proof before merge. :: [P2] Classify rejected reported costs as unpriced
  • reviewed 2026-08-22T02:24:02.241Z sha ecfde41 :: needs real behavior proof before merge. :: [P2] Classify rejected reported costs as unpriced
  • reviewed 2026-08-22T03:16:59.648Z sha 380c1e5 :: needs real behavior proof before merge. :: [P2] Bypass Codex custom pricing for Cursor estimates
  • reviewed 2026-08-22T04:46:30.258Z sha f0a148b :: needs changes before merge. :: [P3] Remove or correct the unused catalog fallback
  • reviewed 2026-08-22T07:16:30.719Z sha 1aba446 :: needs changes before merge. :: [P2] Normalize Cursor Claude model aliases | [P2] Preserve coverage for valid same-model requests

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 21, 2026

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

ℹ️ 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 +630 to +632
inputTokens: usage.inputTokens + usage.cacheReadTokens + usage.cacheWriteTokens,
cachedInputTokens: usage.cacheReadTokens,
cacheWriteInputTokens: usage.cacheWriteTokens,

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 disjoint input for the Claude fallback

When totalCents is absent for a Claude-routed Cursor event containing cache reads or writes, this folded input count reaches the Claude branch of listPriceFallbackCostUSD, where inputTokens, cache reads, and cache creation are treated as disjoint counters. Cached tokens are therefore billed once at the full input rate and again at their cache rate, and the inflated count can also trigger long-context pricing. The fresh evidence relative to the earlier cache-accounting comment is that the updated call now adds both cache counters before invoking a helper that can select Claude; normalize only for the Codex branch or let the helper accept Cursor's disjoint counters.

Useful? React with 👍 / 👎.

Comment on lines +609 to +613
requestCount: requestCount,
costUSD: costUSD,
modelsUsed: models.keys.sorted(),
modelBreakdowns: Self.sortedBreakdowns(breakdowns))
modelBreakdowns: Self.sortedBreakdowns(breakdowns),
estimatedRequestCount: estimatedRequestCount > 0 ? estimatedRequestCount : nil)

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 failed pricing fallbacks as unpriced

When one Cursor day contains both a catalog-priced estimate and an unrecognized event whose totalCents is absent, the recognized event makes costUSD non-nil while this entry records only estimatedRequestCount. CostUsageDailyReport.Entry.coverageCounts consequently classifies every remaining request as priced, so the dashboard reports Unpriced 0 even though the unrecognized event has no cost. Track fallback failures in unpricedRequestCount when constructing the entry.

Useful? React with 👍 / 👎.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 22, 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.

@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: 45160c53d3

ℹ️ 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 +523 to +529
if usage.totalCents == nil {
if estimatedCents != nil {
self.estimatedRequests += 1
} else {
self.unpricedRequests += 1
}
}

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 invalid reported costs as unpriced

When Cursor supplies a negative totalCents—a case already covered by reports do not revive a model cost after an invalid cents event—the value is non-nil, so this block records neither an estimate nor an unpriced request even though checkedKnownCostSum rejects the cost. If another model on the same day has a valid cost, the day remains non-nil and coverageCounts consequently classifies the invalid-cost request as priced; if it is the only model, the request disappears from coverage entirely. Validate totalCents before this branch and increment unpricedRequests whenever the reported cost is rejected.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Aug 22, 2026
@Yuxin-Qiao
Yuxin-Qiao force-pushed the codex/spend-pricing-fallback branch from 45160c5 to bd3b0be Compare August 22, 2026 02:14
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 22, 2026

Copy link
Copy Markdown

🦞👀
Exact review queued.

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: 380c1e5807

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

model: String) -> Double?
{
guard usage.totalCents == nil else { return nil }
if let usd = CostUsagePricing.codexCostUSD(

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 Bypass Codex custom pricing for Cursor estimates

When a user has an exact model entry in custom-pricing.json, this overload implicitly loads that overlay before consulting catalog rates, so an unreported Cursor gpt-* event is priced using the user's native Codex override—or becomes unpriced when the override is partial. This contradicts docs/model-pricing.md, which explicitly says Cursor does not read the overlay, and makes Cursor spend depend on unrelated provider configuration; pass an empty custom-pricing value for this lookup.

Useful? React with 👍 / 👎.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 22, 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:

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 22, 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.

@clawsweeper clawsweeper Bot added 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. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 22, 2026
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 22, 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: bf9b16bf61

ℹ️ 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 +649 to +651
if let usd = CostUsagePricing.claudeCostUSD(
model: model,
inputTokens: usage.inputTokens,

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 Map Cursor Claude aliases before fallback pricing

When totalCents is missing for Cursor's claude-4.5-sonnet spelling—the spelling already used by Cursor fixtures in CursorUsageEventsFetcherTests.swift—both lookups return nil: the OpenAI lookup does not recognize it, while the bundled Claude table uses claude-sonnet-4-5 and normalizeClaudeModel does not reorder this alias. Without a cached models.dev entry, these known Claude events therefore remain unpriced, defeating the new fallback for a model that the endpoint demonstrably emits; map Cursor's Claude aliases to the catalog identity before this call.

Useful? React with 👍 / 👎.

Comment on lines +523 to +525
if let totalCents = usage.totalCents {
if totalCents < 0 || !totalCents.isFinite {
self.unpricedRequests += 1

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 coverage for valid same-model requests

When one model has both a valid reported cost and a rejected negative/non-finite cost, checkedKnownCostSum invalidates the entire model accumulator, but this branch marks only the rejected request as unpriced. If that is the day's only model, the resulting entry has costUSD == nil, so Entry.coverageCounts forces priced to zero and the valid request disappears from coverage (for two requests it reports only Unpriced 1). The fresh evidence beyond the earlier mixed-model case is that a same-model valid/invalid pair follows the accumulator's fail-closed path and never receives the sibling model cost that made the existing test pass.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added 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. and removed status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Aug 22, 2026
Cursor emits claude-4.5-sonnet while bundled Claude catalog keys on claude-sonnet-4-5; map alias before fallback pricing so catalog estimates are not silently missed.

When the same model has both valid and rejected (negative/non-finite) costs, aggregate costUSD fails closed but per-event priced coverage must still be visible; track per-event pricedRequests and expose via pricedRequestCount to keep coverageCounts honest.
@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 22, 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.

@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: 3fa975aecf

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

eventDate: Date,
model: String) -> Double?
{
guard usage.totalCents == nil else { return nil }

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 invalid totalCents distinct from omissions

When Cursor returns a string-encoded non-finite cost such as "totalCents":"NaN" or "Infinity", CursorEventNumber.double collapses the present-but-invalid value to nil, so this guard treats it as an omitted cost, applies fallback pricing, and counts the request as estimated instead of unpriced. The fresh evidence relative to the earlier invalid-cost comment is the decoder's explicit non-finite-to-nil conversion before this branch; preserve whether the field was invalid so only genuinely absent/null costs are estimated.

Useful? React with 👍 / 👎.

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. proof: sufficient Contributor real behavior proof is sufficient. 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.

1 participant