From 7b619fbbddcf73511730942e08fbe88db2c2c83d Mon Sep 17 00:00:00 2001 From: "Sharad." Date: Sat, 12 Sep 2026 14:30:48 +0000 Subject: [PATCH] fix: reject non-finite scorer weights in suite validation Fixes #29 Co-authored-by: Sharad. --- src/scorers/util.ts | 3 ++- src/suite.ts | 4 ++-- tests/suite.test.ts | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/scorers/util.ts b/src/scorers/util.ts index 4a82776..6d9c4de 100644 --- a/src/scorers/util.ts +++ b/src/scorers/util.ts @@ -9,7 +9,8 @@ export function clamp01(n: number): number { /** Read the weight from a spec, defaulting to 1 and rejecting negatives. */ export function specWeight(spec: ScorerSpec): number { const w = typeof spec.weight === "number" ? spec.weight : 1; - return w < 0 ? 0 : w; + if (!Number.isFinite(w) || w < 0) return 0; + return w; } /** Convenience builder that fills in the boilerplate of a {@link ScoreResult}. */ diff --git a/src/suite.ts b/src/suite.ts index 214c139..1439e08 100644 --- a/src/suite.ts +++ b/src/suite.ts @@ -137,8 +137,8 @@ function validateScorer(data: unknown, caseId: string, index: number): ScorerSpe ); if (s.weight !== undefined) { assert( - typeof s.weight === "number" && s.weight >= 0, - `case "${caseId}" scorers[${index}].weight must be a non-negative number`, + typeof s.weight === "number" && Number.isFinite(s.weight) && s.weight >= 0, + `case "${caseId}" scorers[${index}].weight must be a finite non-negative number`, ); } return s as ScorerSpec; diff --git a/tests/suite.test.ts b/tests/suite.test.ts index 70dcc91..e9cba7a 100644 --- a/tests/suite.test.ts +++ b/tests/suite.test.ts @@ -72,6 +72,24 @@ cases: ).toThrow(/at least one scorer/); }); + it.each([Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NaN])( + "rejects non-finite scorer weight (%s)", + (weight) => { + expect(() => + validateSuite({ + name: "d", + cases: [ + { + id: "x", + input: { prompt: "a" }, + scorers: [{ type: "regex", weight }], + }, + ], + }), + ).toThrow(/scorers\[0\]\.weight/); + }, + ); + it("rejects an out-of-range threshold", () => { expect(() => validateSuite({