diff --git a/src/lib/fmt.test.ts b/src/lib/fmt.test.ts index 7b9f33c55..454617579 100644 --- a/src/lib/fmt.test.ts +++ b/src/lib/fmt.test.ts @@ -6,14 +6,22 @@ describe("fmtBytes", () => { expect(fmtBytes(0)).toBe("0 B"); expect(fmtBytes(512)).toBe("512 B"); }); - it("uses one decimal below 10 in larger units", () => { - expect(fmtBytes(1024)).toBe("1.0 KB"); - expect(fmtBytes(1536)).toBe("1.5 KB"); + it("uses IEC binary prefixes when scaling by powers of 1024", () => { + expect(fmtBytes(1024)).toBe("1.0 KiB"); + expect(fmtBytes(1536)).toBe("1.5 KiB"); + expect(fmtBytes(1024 ** 2)).toBe("1.0 MiB"); + expect(fmtBytes(1024 ** 3)).toBe("1.0 GiB"); + expect(fmtBytes(1024 ** 4)).toBe("1.0 TiB"); }); it("drops decimals at 10 and above", () => { - expect(fmtBytes(10 * 1024)).toBe("10 KB"); + expect(fmtBytes(10 * 1024)).toBe("10 KiB"); }); - it("caps at TB", () => { - expect(fmtBytes(1024 ** 5)).toBe("1024 TB"); + it("uses the complete IEC 80000-13:2025 binary-prefix ladder", () => { + expect(fmtBytes(1024 ** 5)).toBe("1.0 PiB"); + expect(fmtBytes(1024 ** 6)).toBe("1.0 EiB"); + expect(fmtBytes(1024 ** 7)).toBe("1.0 ZiB"); + expect(fmtBytes(1024 ** 8)).toBe("1.0 YiB"); + expect(fmtBytes(1024 ** 9)).toBe("1.0 RiB"); + expect(fmtBytes(1024 ** 10)).toBe("1.0 QiB"); }); }); diff --git a/src/lib/fmt.ts b/src/lib/fmt.ts index 95e22d1fa..df2c9156b 100644 --- a/src/lib/fmt.ts +++ b/src/lib/fmt.ts @@ -1,5 +1,24 @@ +/** + * Format a byte count with IEC 80000-13:2025 binary prefixes. + * + * Scaled values below ten retain one decimal place. Byte values and scaled + * values of ten or more use the existing whole-number presentation so callers + * keep a compact, consistent UI. + */ export function fmtBytes(n: number): string { - const units = ["B", "KB", "MB", "GB", "TB"]; + const units = [ + "B", + "KiB", + "MiB", + "GiB", + "TiB", + "PiB", + "EiB", + "ZiB", + "YiB", + "RiB", + "QiB", + ]; let v = n; let i = 0; while (v >= 1024 && i < units.length - 1) { diff --git a/src/lib/verdictBadge.test.ts b/src/lib/verdictBadge.test.ts index 5a86dc49f..d10e93e65 100644 --- a/src/lib/verdictBadge.test.ts +++ b/src/lib/verdictBadge.test.ts @@ -1,9 +1,14 @@ -import { describe, it, expect } from "vitest"; +import { describe, expect, it } from "vitest"; import { verdictBadge } from "./verdictBadge"; describe("verdictBadge", () => { - it("maps each verdict to a distinct label", () => { - expect(verdictBadge("safe").label).toBe("안전"); + it("keeps model advice distinct without presenting safe as deletion authorization", () => { + const safe = verdictBadge("safe"); + expect(safe.label).toBe("낮은 위험"); + expect(safe.title).toContain("자문"); + expect(safe.title).toContain("검증"); + expect(safe.title).not.toContain("삭제해도 안전"); + expect(verdictBadge("caution").label).toBe("주의"); expect(verdictBadge("keep").label).toBe("보관"); expect(verdictBadge("unrated").label).toBe("미판정"); diff --git a/src/lib/verdictBadge.ts b/src/lib/verdictBadge.ts index 2b2e11fd1..351005261 100644 --- a/src/lib/verdictBadge.ts +++ b/src/lib/verdictBadge.ts @@ -6,11 +6,11 @@ export interface VerdictBadge { title: string; } -/** LLM 삭제-안전 판정 → 배지 표시. 미상/미판정은 unrated로 폴백. 자문(advisory)일 뿐. */ +/** LLM 위험도 자문 결과 → 배지 표시. 미상/미판정은 unrated로 폴백하며 삭제 권한을 부여하지 않는다. */ export function verdictBadge(v: Verdict | string): VerdictBadge { switch (v) { case "safe": - return { label: "안전", cls: "badge-safe", title: "삭제해도 안전 (자문)" }; + return { label: "낮은 위험", cls: "badge-safe", title: "모델 자문: 낮은 위험 — 작업 전 검증 필요" }; case "caution": return { label: "주의", cls: "badge-caution", title: "삭제 주의 — 확인 권장 (자문)" }; case "keep":