Skip to content

fix(capability-src): correct float-to-string truncation in shared JSON writer - #272

Merged
enricopiovesan merged 1 commit into
mainfrom
claude/fix-json-float-truncation-catalog-coverage
Aug 18, 2026
Merged

fix(capability-src): correct float-to-string truncation in shared JSON writer#272
enricopiovesan merged 1 commit into
mainfrom
claude/fix-json-float-truncation-catalog-coverage

Conversation

@enricopiovesan

Copy link
Copy Markdown
Contributor

Summary

  • Fixes a float-formatting bug in wasi-capability-runtime's hand-rolled
    JSON writer (json.rs, shared no_std code used by every capability-src
    WASM binary, including catalog-builder). write_number scaled a
    fraction by 1_000_000.0 and truncated via as i64 to extract six
    decimal digits. 65.6 * 1_000_000.0 is 65599999.99999999 in f64 (not
    exactly representable), so truncating silently produced "65.599999"
    instead of "65.600000" for any value whose scaled representation fell
    just under an integer boundary.
  • Surfaced live: the catalog at registry.traverse-framework.com showed
    "65.599999% covered" and "66.099999% covered" on two capability
    cards, even though the actual measured cargo llvm-cov coverage was
    cleanly 65.6% / 66.1%. Every other coverage badge on the site happened
    to scale to an exact or above-boundary value and so rendered fine —
    this was a latent bug for years, only visible for specific unlucky
    decimals.
  • Fix: add a round-half-up epsilon (+ 0.5) before the truncating cast —
    the standard technique for correct rounding without f64::round (this
    function deliberately avoids f64::round/abs/fract since those pull
    in libm symbols not linked into this no_std wasm32-unknown-unknown
    binary; the fix keeps that constraint, casts and integer arithmetic
    only).
  • Verified against the real deployed artifact, not just unit tests: ran
    scripts/ci/gather_catalog_data.py for real (98 capabilities, live
    cargo llvm-cov measurements) and fed the output through the actual
    wasm32-unknown-unknown release build of catalog-builder.wasm via
    wasmtime. Diffing the regenerated catalog.json against the currently
    live one shows exactly the two corrupted fields fixed
    (65.59999965.600000, 66.09999966.100000) and nothing else
    changed.

No open issue tracks this — found via direct inspection of the live
catalog. capability-src/ is not currently covered by any approved
spec's governs list (this crate isn't a published registry capability,
per its own doc comment — it's shared build tooling), so 001-registry- foundation is cited as the closest applicable spec, matching this repo's
existing precedent for capability-src-only changes (e.g. #264).

Governing Spec

  • 001-registry-foundation

Definition of Done

  • write_number produces correct digits for values whose * 1_000_000.0 scaling isn't exactly representable in f64.
  • No change to whole-number or already-exact fractional formatting.

Validation

  • cargo test --manifest-path capability-src/wasi-capability-runtime/Cargo.toml (7 tests, including 2 new regression tests: exact reproduction of the 65.6/66.1 bug, and a 0.0–99.9-by-0.1 round-trip sweep)
  • cargo build --release --target wasm32-unknown-unknown --manifest-path capability-src/catalog-builder/Cargo.toml
  • End-to-end: real gather_catalog_data.py output piped through the real catalog-builder.wasm via wasmtime, diffed against the currently-live catalog.json — only the two known-corrupted fields changed, to the correct values

Test plan

  • CI green (build-catalog regenerates catalog.json on merge; live badges should show 65.6%/66.1% after the next deploy)

…N writer

wasi-capability-runtime's write_number scaled a fraction by 1_000_000.0
and truncated via `as i64`. Because that scaled value is often not
exactly representable in f64 (e.g. 65.6 * 1_000_000.0 == 65599999.99999999),
truncating silently produced "65.599999" instead of "65.600000" -- visible
live as "65.599999% covered" / "66.099999% covered" badges on the catalog
for capabilities whose real cargo llvm-cov coverage was a clean 65.6% /
66.1%. Adds a round-half-up epsilon before the truncating cast (still no
f64::round/libm, per this function's existing no_std constraint).

Verified end-to-end against the real deployed artifact: ran
gather_catalog_data.py for real and piped it through the actual
wasm32-unknown-unknown release build of catalog-builder.wasm via wasmtime;
diffing against the currently-live catalog.json shows only the two known-
corrupted fields corrected, nothing else changed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@enricopiovesan
enricopiovesan enabled auto-merge (squash) August 18, 2026 05:15
@enricopiovesan
enricopiovesan merged commit f6240c3 into main Aug 18, 2026
9 checks passed
@enricopiovesan
enricopiovesan deleted the claude/fix-json-float-truncation-catalog-coverage branch August 18, 2026 05:15
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