Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/pomodoro-timer/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class GradientProgressBar extends Widget {

const attrs = styleToCellAttrs(this._style);

const label = this._showLabel ? ` ${Math.round(this._value * 100)}%` : '';
const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | rg '(^examples/pomodoro-timer/src/index\.tsx$|^packages/dev-server/src/devtools\.ts$)' || true

echo
echo "Relevant lines:"
for f in examples/pomodoro-timer/src/index.tsx packages/dev-server/src/devtools.ts; do
  if [ -f "$f" ]; then
    echo "---- $f ----"
    nl -ba "$f" | sed -n '170,190p;70,90p'
  fi
done

echo
echo "Behavior probe for post-scale epsilon with Number.EPSILON:"
node - <<'JS'
const original = Object.getOwnPropertyDescriptor(Number, 'EPSILON');
console.log('Number.EPSILON default:', Number.EPSILON);
console.log('Number.EPSILON default in binary:', Number.EPSILON.toString(2));

function roundedExpr(value, scale) {
  return Math.round(value * scale + Number.EPSILON) / scale;
}

const cases = [0.0, 0.1, 0.33, 0.5, 1.0];
console.log('\nDecimal values, scale 1000 decimal places (scaled + Number.EPSILON):');
for (const value of cases) {
  const raw = value * 1e3 + Number.EPSILON;
  const rounded = Math.round(value * 1e3 + Number.EPSILON) / 1e3;
  console.log(`${value} -> raw=${raw} rawExact=${value * 1e3} rounded=${rounded}`);
}

console.log('\nDecimal values, scale 100 decimal places (value*100 + Number.EPSILON):');
for (const value of cases) {
  const scaled = value * 100;
  const raw = scaled + Number.EPSILON;
  const rounded = Math.round(scaled + Number.EPSILON) / 100;
  console.log(`${value} -> scaled=${scaled} raw=${raw} rounded=${rounded}`);
}

console.log('\nValues whose scaled nextFloat equals EPSILON + scaled?');
for (let i = 1; i <= 200; i++) {
  const v = i / 25.0;
  const scaled = v * 100;
  const next = Math.nextAfter(scaled, Number.POSITIVE_INFINITY);
  if ((next - scaled) < Number.EPSILON || (next - scaled) === Number.EPSILON) {
    const raw = scaled + Number.EPSILON;
    const nextRaw = next + Number.EPSILON;
    const sameFloor = Math.floor(raw) === Math.floor(nextRaw);
    console.log(`${v} scaled=${scaled} nextScaled=${next} scaledNextStep=${next - scaled} rawFloor=${Math.floor(raw)} rawNextFloor=${Math.floor(nextRaw)} sameRound=${sameFloor}`);
  }
}
JS

Repository: Karanjot786/TermUI

Length of output: 343


🏁 Script executed:

#!/bin/bash
set -euo pipefail

wc -l examples/pomodoro-timer/src/index.tsx packages/dev-server/src/devtools.ts

echo "Relevant lines using awk:"
awk 'NR>=175 && NR<=190 || NR>=70 && NR<=90 {printf "%5d:%s\n",NR,$0}' examples/pomodoro-timer/src/index.tsx packages/dev-server/src/devtools.ts

echo
echo "Behavior probe for post-scale Number.EPSILON:"
node - <<'JS'
function report(label, scale, values) {
  console.log(label);
  for (const v of values) {
    const scaled = v * scale;
    const raw = scaled + Number.EPSILON;
    const round = Math.round(scaled + Number.EPSILON);
    const final = Math.round(scaled + Number.EPSILON) / scale;
    console.log(`${v} scale${scale} scaled=${scaled} scaled+eps=${raw} round=${round} final=${final}`);
  }
}

report('examples/pomodoro-timer expression: Math.round(this._value * 100 + Number.EPSILON)', 100, [0, 0.5, 1]);
report('packages/dev-server expression: Math.round(fps * 10 + Number.EPSILON) / 10', 10, [1, 2.5, 10]);

console.log('Number.EPSILON:', Number.EPSILON, Number.EPSILON.toString(2));

console.log('Scaled steps for nearby values where post-scale rounding is preserved:');
for (let i = 1; i <= 12; i++) {
  const v = i / 3;
  const scaled = v * 100;
  const next = Math.nextAfter(scaled, 0);
  const prev = Math.nextAfter(scaled, Number.POSITIVE_INFINITY);
  console.log(`${v} scaled=${scaled} prevStep=${Math.abs(scaled-prev)} nextStep=${Math.abs(scaled-next)}`);
}
JS

Repository: Karanjot786/TermUI

Length of output: 2770


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Node version:"
node --version 2>&1 || true

echo "Floating-point epsilon behavior probe:"
node - <<'JS'
console.log('Number.EPSILON:', Number.EPSILON);

for (const scale of [10, 100]) {
  console.log(`\nPost-scale round at scale ${scale}:`);
  const inputs = new Map([
    [0, 0],
    [0.1 * 1e9 / 1e9, Math.round(0.1 * scale + Number.EPSILON) / scale],
    [0.33, Math.round(0.33 * scale + Number.EPSILON) / scale],
    [0.5, Math.round(0.5 * scale + Number.EPSILON) / scale],
    [1, Math.round(1 * scale + Number.EPSILON) / scale],
  ]);
  for (const [v, final] of inputs.entries()) {
    const scaled = v * scale;
    const epsilonAdded = scaled + Number.EPSILON;
    console.log(`${String(v)} -> scaled=${scaled} +eps=${epsilonAdded} -> ${final}`);
  }

  console.log(`Pre-scale epsilon at scale ${scale}:`);
  for (const [v, final] of inputs.entries()) {
    const pre = Math.round(v + Number.EPSILON * scale) / scale;
    const scaled = prevFloat = v * scale;
    console.log(`${String(v)} -> scaled=${scaled} -> pre-eps result ${pre}`);
  }
}

console.log('\nInspect rounding expression result for 1/3 and 1/30:');
const v13 = 1 / 3;
console.log(`1/3 * 100 = ${(v13 * 100).toString()} -> Math.round(...+eps) = ${Math.round(v13 * 100 + Number.EPSILON)} -> final = ${Math.round(v13 * 100 + Number.EPSILON) / 100}`);
console.log(`1/3 * 10 = ${(v13 * 10).toString()} -> Math.round(...+eps) = ${Math.round(v13 * 10 + Number.EPSILON)} -> final = ${Math.round(v13 * 10 + Number.EPSILON) / 10}`);

console.log('\nUse next/fprev float around scaled inputs where possible:');
const scaled = 50;
const next = scaled + Number.EPSILON;
console.log(`scaled=50, next float around ${scaled}:`, Math.nextAfter ? Math.nextAfter(scaled, Number.POSITIVE_INFINITY) : 'Math.nextAfter unavailable');
console.log(`50 + Number.EPSILON === 50:`, 50 + Number.EPSILON === 50);
JS

Repository: Karanjot786/TermUI

Length of output: 1510


Don’t apply Number.EPSILON after the decimal scale.

Number.EPSILON is 2^-52; after multiplying by 10 or 100, it is smaller than one floating-point step at the scaled value and can be discarded. Use a scaled epsilon before Math.round, or remove this if it was added to compensate for an earlier rounding error.

📍 Affects 2 files
  • examples/pomodoro-timer/src/index.tsx#L185-L185 (this comment)
  • packages/dev-server/src/devtools.ts#L81-L81
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/pomodoro-timer/src/index.tsx` at line 185, The percentage rounding
in the label calculation applies Number.EPSILON at the wrong scale. Update the
expression in the label-building method around _showLabel and also the
corresponding calculation in packages/dev-server/src/devtools.ts:81 to use an
appropriately scaled epsilon before Math.round, or remove the epsilon if it only
compensates for an earlier rounding error.

const barWidth = Math.max(0, width - label.length);
const filled = this._value <= 0 ? 0 : Math.round(barWidth * this._value);
const empty = barWidth - filled;
Expand Down
2 changes: 1 addition & 1 deletion examples/widget-gallery/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class WidgetGalleryApp extends Widget {
}

// Tab switching: 1-6
const num = parseInt(event.key);
const num = parseInt(event.key, 10);
if (num >= 1 && num <= 6) {
this._switchTab(num - 1);
return true;
Expand Down
2 changes: 1 addition & 1 deletion packages/dev-server/src/devtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class DevTools {
renderTimeMs: timeMs,
widgetCount,
lastRenderAt: now,
fps: Math.round(fps * 10) / 10,
fps: Math.round(fps * 10 + Number.EPSILON) / 10,
memoryMB: Math.round((process.memoryUsage?.().heapUsed ?? 0) / 1024 / 1024 * 10) / 10,
};
}
Expand Down
Loading