mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-11 21:59:38 +01:00
fix: enforce accounting coverage and recovery regression gates
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
c1102f05d4
commit
ec91c9c709
45 files changed
+5400
-20
No files matched your search
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { addCents, centsToUnits, centsToUsd, compareCents, formatUsdExact, MAX_MONEY_UNITS, normalizeCents, subtractCents, unitsToCents, usdToCents } from "./money.js";
|
||||
|
||||
describe("fixed-point money", () => {
|
||||
it.each([
|
||||
["0.00000005", "0.0000001"], ["-0.00000005", "-0.0000001"],
|
||||
["0.000000049", "0.0000000"], ["1e-7", "0.0000001"],
|
||||
["12345678901234567.1234567", "12345678901234567.1234567"],
|
||||
])("normalizes %s exactly", (input, expected) => expect(normalizeCents(input)).toBe(expected));
|
||||
it("does exact arithmetic beyond floating-point precision", () => {
|
||||
expect(addCents("12345678901234567.1234567", "0.0000001")).toBe("12345678901234567.1234568");
|
||||
expect(subtractCents("9007199254740992.0000001", "9007199254740992")).toBe("0.0000001");
|
||||
expect(compareCents("9007199254740992.0000001", "9007199254740992")).toBe(1);
|
||||
expect(addCents(0.1, 0.2)).toBe("0.3000000");
|
||||
});
|
||||
it("converts USD without intermediate multiplication or double rounding", () => {
|
||||
expect(usdToCents("0.000000001")).toBe("0.0000001");
|
||||
expect(usdToCents("0.00000000049")).toBe("0.0000000");
|
||||
expect(usdToCents("0.0123456789")).toBe("1.2345679");
|
||||
expect(formatUsdExact("4.5")).toBe("$0.05");
|
||||
});
|
||||
it("round-trips the full database range", () => expect(centsToUnits(unitsToCents(MAX_MONEY_UNITS))).toBe(MAX_MONEY_UNITS));
|
||||
it.each(["0.0000001", "9007199254740992.0000001", "-0.0000001", unitsToCents(MAX_MONEY_UNITS)])("preserves an editable USD value for %s cents", cents => {
|
||||
expect(usdToCents(centsToUsd(cents))).toBe(cents);
|
||||
});
|
||||
it.each(["NaN", "Infinity", "", " 1", "1.2.3", "1e101", "100000000000000000", Number.NaN, Number.POSITIVE_INFINITY, Number.MAX_SAFE_INTEGER + 1])("rejects invalid/out-of-range %s", input => {
|
||||
expect(() => centsToUnits(input)).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -7,9 +7,27 @@ import {
|
||||
companySkillInstallCatalogSchema,
|
||||
companySkillInstallUpdateSchema,
|
||||
companySkillResetSchema,
|
||||
companySkillTestRunCostSummarySchema,
|
||||
companySkillUpdateStatusSchema,
|
||||
} from "./company-skill.js";
|
||||
|
||||
describe("skill test run cost summary", () => {
|
||||
const tokens = { inputTokens: 10, cachedInputTokens: 5, outputTokens: 2 };
|
||||
|
||||
it.each([0, 0.0000001, 0.1234567, 25, 4_000_000_000.125])("preserves valid cents: %s", (costCents) => {
|
||||
const response = { ...tokens, costCents };
|
||||
expect(companySkillTestRunCostSummarySchema.parse(response)).toEqual(response);
|
||||
});
|
||||
|
||||
it.each([-0.0000001, -1, NaN, Infinity, -Infinity, "0.1234567", null])("rejects invalid cents: %s", (costCents) => {
|
||||
expect(companySkillTestRunCostSummarySchema.safeParse({ ...tokens, costCents }).success).toBe(false);
|
||||
});
|
||||
|
||||
it.each(["inputTokens", "cachedInputTokens", "outputTokens"])("still requires whole %s", (field) => {
|
||||
expect(companySkillTestRunCostSummarySchema.safeParse({ ...tokens, costCents: 0.1234567, [field]: 0.5 }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
const catalogSkill = {
|
||||
id: "paperclipai:bundled:software-development:review",
|
||||
key: "paperclipai/bundled/software-development/review",
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { statusCardRefreshPolicySchema } from "./status-card.js";
|
||||
import { statusCardRefreshPolicySchema, statusCardSchema, statusCardUpdateSchema } from "./status-card.js";
|
||||
|
||||
describe.each([
|
||||
["status card daily spend", statusCardSchema.pick({ todayCostCents: true }), "todayCostCents"],
|
||||
["status card update spend", statusCardUpdateSchema.pick({ costCents: true }), "costCents"],
|
||||
] as const)("%s", (_name, schema, field) => {
|
||||
it.each([0, 0.0000001, 0.1234567, 25, 4_000_000_000.125])("preserves valid cents: %s", (amount) => {
|
||||
expect(schema.parse({ [field]: amount })).toEqual({ [field]: amount });
|
||||
});
|
||||
|
||||
it.each([-0.0000001, -1, NaN, Infinity, -Infinity, "0.1234567", null])("rejects invalid cents: %s", (amount) => {
|
||||
expect(schema.safeParse({ [field]: amount }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("statusCardRefreshPolicySchema", () => {
|
||||
it("accepts valid IANA timezones", () => {
|
||||
|
||||
Reference in new issue
Block a user