Skip to content

fix(report): stop summaries rendering an empty cost as "-0.00" - #1056

Merged
junhoyeo merged 2 commits into
mainfrom
fix/summary-negative-zero-cost
Aug 6, 2026
Merged

fix(report): stop summaries rendering an empty cost as "-0.00"#1056
junhoyeo merged 2 commits into
mainfrom
fix/summary-negative-zero-cost

Conversation

@junhoyeo

@junhoyeo junhoyeo commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Summary

calculate_summary returns -0.0 for an empty or all-zero contribution set, and the CLI renders it as $-0.00.

Reproduced end-to-end on main (healthy pricing, every row excluded from the submission):

  Warning: excluded 1 unpriced weird/totally-unpriced-model message(s) (150 tokens): no authoritative model-to-price mapping.
    Total tokens: 0
    Total cost: $-0.00
  No usage data found to submit.

Cause

Rust's impl Sum for f64 folds from -0.0, not 0.0. That is deliberate upstream: -0.0 is the additive identity that preserves the sign of every addend (-0.0 + x == x for all x, whereas 0.0 + -0.0 == +0.0 would discard it). So [].iter().sum::<f64>() is -0.0 — bits 0x8000000000000000 — and {:.2} prints -0.00.

The three report aggregators in lib.rs already normalize this with a trailing + 0.0. calculate_summary in aggregator.rs was the one site that missed the idiom.

Why no test caught it

test_calculate_summary_empty asserted:

assert_eq!(summary.total_cost, 0.0);

-0.0 == 0.0 is true under IEEE 754, so that assertion passes on the buggy value. It now additionally asserts the sign bit, and a companion test pins the rendered string.

Tests

  • cargo test -p tokscale-core --lib — 1,489 passed, 0 failed
  • cargo fmt --all --check clean
  • Mutation check: dropping the + 0.0 again makes test_calculate_summary_empty fail; with it, all 5 calculate_summary tests pass

Note

Found while auditing the batch merged in #1037, #1045, #1051 and #1055 — it is pre-existing and independent of all four.


Summary by cubic

Fixes summary cost rendering so empty summaries show "$0.00", not "$-0.00". Normalizes the f64 sum and tightens tests and comments to prevent regressions.

  • Bug Fixes
    • Normalize calculate_summary total cost with sum::<f64>() + 0.0; clarify only empty sets (or all -0.0) would format as negative zero.
    • Add tests in tokscale-core for non-negative zero and "$0.00" on empty summaries, plus a boundary test proving a single +0.0 contribution already yields +0.0.

Written for commit f09abf8. Summary will update on new commits.

Review in cubic

`Sum for f64` folds from `-0.0` — the additive identity that preserves the
sign of every addend — so summing an empty or all-zero set yields `-0.0`,
and the CLI's `format!("${:.2}", ..)` renders that as "$-0.00". Users hit
it whenever a submission excluded every row: "Total cost: $-0.00" next to
"Total tokens: 0".

The three report aggregators in lib.rs already normalize with a trailing
`+ 0.0`; calculate_summary was the one site that missed it.

test_calculate_summary_empty asserted `total_cost == 0.0`, which is true
for `-0.0` under IEEE, so it could never catch this. It now also asserts
the sign bit, and a companion test pins the rendered string.

Confidence: high
Scope-risk: narrow
Directive: `+ 0.0` on an f64 sum is deliberate sign normalization, not
redundant arithmetic — do not "simplify" it away
Not-tested: whether any frontend consumer of the JSON summary distinguishes
-0.0 from 0.0
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
tokscale Ignored Ignored Preview Aug 6, 2026 11:17pm

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 1 file

Re-trigger cubic

…vers

The comment said an "empty (or all-zero)" sum yields -0.0. Only the empty
fold reaches the identity untouched; a single +0.0 addend already normalized
it, since -0.0 + 0.0 == +0.0. As written it implied every zero-cost day was
affected. An all--0.0 set does still fold to -0.0, so that case is named.

Adds a test pinning the boundary, so the distinction is checkable rather
than asserted in prose.

Confidence: high
Scope-risk: narrow
@junhoyeo
junhoyeo merged commit 7c0dadf into main Aug 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant