Skip to content

fmtCost uses inconsistent precision thresholds: ≤$0.01 shows more decimals than $0.01+ values #11

Description

@devinoldenburg

Summary

fmtCost() in plugins/tps/format.js formats monetary values with three precision tiers. The transition from 4 decimal places (for values < $0.01) to 3 decimal places (for values >= $0.01) is visually inconsistent: a $0.0050 cost shows more digits than a $0.012 cost.

Root Cause

File: plugins/tps/format.js:58-64

export function fmtCost(value) {
  const n = Number(value);
  if (!Number.isFinite(n) || n === 0) return "$0";
  if (n < 0.01) return "$" + n.toFixed(4);
  if (n < 1) return "$" + n.toFixed(3);
  return "$" + n.toFixed(2);
}

The thresholds create a jump:

Value Condition toFixed Output
0.005 < 0.01 toFixed(4) "$0.0050"
0.0123 >= 0.01, < 1 toFixed(3) "$0.012"
0.0099 < 0.01 toFixed(4) "$0.0099"
0.0100 >= 0.01, < 1 toFixed(3) "$0.010"

A cost of 0.005 (half a cent) renders as $0.0050 — 3 significant digits with a trailing zero. A cost of 0.0123 (1.2 cents) renders as $0.012 — only 2 significant digits, with the final digit silently truncated. This is backwards: smaller values show more precision with less meaningful trailing digits, while larger values discard meaningful digits.

The existing test at tests/format.test.mjs:52-53 asserts this behavior:

assert.equal(fmtCost(0.005), "$0.0050");
assert.equal(fmtCost(0.0123), "$0.012");

The assertion treats both as correct, but the inconsistency between them is the bug.

Impact

  • Visual inconsistency. Two costs side by side in the TUI render with different decimal precision for no semantic reason.
  • Information loss. 0.0123 truncated to 0.012 loses 0.0003 in a context where the showCost feature is explicitly opt-in and users who enable it likely care about precision.
  • Misleading for small costs. A $0.0050 display implies sub-millicent precision that API billing doesn't actually provide — it's just a rendering artifact of toFixed(4).

Expected Behavior

Consistent significant-digit display across the full range, e.g.:

  • < $0.01 → 4 significant figures ("$0.0050", "$0.0123")
  • < $1 → 3-4 significant figures depending on magnitude
  • = $1 → 2 decimal places

Or, simpler: always show 4 decimal places for values < $1 and 2 for >= $1, aligning with how API billing costs are typically displayed.

Suggested Fix

Option A — uniform sub-dollar precision:

if (n < 1) return "$" + n.toFixed(4);
return "$" + n.toFixed(2);

Option B — significant-figures approach (more complex but strictly better):

if (n < 0.01) return "$" + n.toPrecision(2);
if (n < 1) return "$" + n.toPrecision(3);
return "$" + n.toFixed(2);

Option B produces: 0.005 → "$0.0050", 0.0123 → "$0.0123", 0.123 → "$0.123", 1.50 → "$1.50".

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions