Avoid rounding near-perfect compare pass rates to 100%.

With a few fails among tens of thousands of rows, 1-decimal rounding hid residual failures; keep extra precision so the UI never shows 100% when fails remain.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-10-09 09:31:04 +08:00
parent 8a79e962a8
commit 1653a31b16
2 changed files with 57 additions and 7 deletions

View file

@ -204,6 +204,27 @@ def normalize_store_unchanged(raw: Any) -> str:
return m if m in _STORE_UNCHANGED_MODES else "auto"
def compute_pass_rate(*, success: int, fail: int, empty_as: float = 100.0) -> float:
"""Pass rate for cutover UI.
With million-row sheets, 3 fails / 50k can round to 100.0% at 1 decimal —
never report 100 when any fail remains; add decimals until it stays < 100.
"""
s = max(0, int(success or 0))
f = max(0, int(fail or 0))
judged = s + f
if judged <= 0:
return float(empty_as)
rate = (s / judged) * 100.0
if f <= 0:
return round(rate, 1)
for nd in (1, 2, 3, 4):
r = round(rate, nd)
if r < 100.0:
return r
return 99.9999
def resolve_unchanged_policy(
mode: str, *, before_n: int, after_n: int
) -> dict[str, Any]:
@ -2885,7 +2906,9 @@ def _enrich_summary(summary: dict[str, Any], sheets: list[dict[str, Any]]) -> di
matched = changed + unchanged
diff_count = fail_count
pass_rate = (
round((success_count / judged) * 100, 1) if judged else (100.0 if total == 0 else 0.0)
compute_pass_rate(success=success_count, fail=fail_count, empty_as=100.0 if total == 0 else 0.0)
if judged
else (100.0 if total == 0 else 0.0)
)
diff_rate = round((fail_count / judged) * 100, 1) if judged else 0.0
@ -2920,7 +2943,11 @@ def _enrich_summary(summary: dict[str, Any], sheets: list[dict[str, Any]]) -> di
# Pending sheets must not look like "100% pass"
"pass_rate": None
if pending
else (round((su / sj) * 100, 1) if sj else (100.0 if st == 0 else 0.0)),
else (
compute_pass_rate(success=su, fail=sf, empty_as=100.0 if st == 0 else 0.0)
if sj
else (100.0 if st == 0 else 0.0)
),
}
)

View file

@ -1376,7 +1376,22 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
const fail = sheetFailOf(c);
const ok = sheetSuccessOf(c);
const judged = fail + ok;
return judged ? Math.round((ok / judged) * 1000) / 10 : 100;
if (!judged) return 100;
const rate = (ok / judged) * 100;
if (fail <= 0) return Math.round(rate * 10) / 10;
// 3 fails / 50k ≈ 99.994% — 1-decimal round becomes 100%; keep digits until < 100
for (const nd of [1, 2, 3, 4]) {
const r = Math.round(rate * 10 ** nd) / 10 ** nd;
if (r < 100) return r;
}
return 99.9999;
};
const formatPassRate = (rate: number | null | undefined) => {
if (rate === null || rate === undefined || Number.isNaN(rate)) return "…";
// Trim trailing zeros but keep enough precision for near-100 rates
const s = Number(rate).toFixed(4).replace(/\.?0+$/, "");
return `${s}%`;
};
const summary = runDetail?.summary || {};
@ -3591,7 +3606,15 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
pass_rate: pending
? null
: judged
? Math.round((unchanged / judged) * 1000) / 10
? (() => {
const rate = (unchanged / judged) * 100;
if (fail <= 0) return Math.round(rate * 10) / 10;
for (const nd of [1, 2, 3, 4]) {
const r = Math.round(rate * 10 ** nd) / 10 ** nd;
if (r < 100) return r;
}
return 99.9999;
})()
: 100,
};
})
@ -3641,7 +3664,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
title={
pending
? `${label} · ${t("bizCompare.sheetPending")}`
: `${label} · ${t("bizCompare.kindFail")} ${fail} · ${t("bizCompare.kindSuccess")} ${ok} · ${t("bizCompare.passRateShort")} ${rate ?? "…"}%`
: `${label} · ${t("bizCompare.kindFail")} ${fail} · ${t("bizCompare.kindSuccess")} ${ok} · ${t("bizCompare.passRateShort")} ${formatPassRate(rate)}`
}
>
<span className="bs-cmp-nav__dot" aria-hidden />
@ -3658,7 +3681,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
{pending ? "—" : ok}
</span>
<span className="bs-cmp-nav__num bs-cmp-nav__num--rate">
{pending || rate === null ? "…" : `${rate}%`}
{pending || rate === null ? "…" : formatPassRate(rate)}
</span>
</span>
</button>
@ -3714,7 +3737,7 @@ export function BizComparePage({ pageMode = "all" }: { pageMode?: BizComparePage
<span className="bs-cmp-strip__pass-value">
{activeSheetPending || activePassRate === null
? "…"
: `${activePassRate}%`}
: formatPassRate(activePassRate)}
</span>
</div>
<div className="bs-cmp-strip__kinds" role="group">