evalsense 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/describe.ts","../src/core/eval-test.ts","../src/dataset/loader.ts","../src/dataset/run-model.ts","../src/dataset/alignment.ts","../src/dataset/integrity.ts","../src/statistics/classification.ts","../src/statistics/distribution.ts","../src/assertions/binarize.ts","../src/assertions/field-selector.ts","../src/assertions/expect-stats.ts"],"names":["getCurrentSuite","setCurrentSuite","addSuite","test","addTestToCurrentSuite","path","resolve","extname","readFileSync","DatasetError","IntegrityError","buildConfusionMatrix","getTruePositives","getFalsePositives","getFalseNegatives","getSupport","recordAssertion","AssertionError","recordFieldMetrics","aligned"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * describe() implementation - Jest-like test suite grouping\n */\n\nimport type { Suite, TestFn } from \"./types.js\";\nimport { getCurrentSuite, setCurrentSuite, addSuite } from \"./context.js\";\n\n/**\n * Creates a test suite that groups related eval tests\n *\n * @example\n * ```ts\n * describe(\"Sentiment classifier\", () => {\n * evalTest(\"accuracy above 80%\", async () => {\n * // test implementation\n * });\n * });\n * ```\n */\nexport function describe(name: string, fn: () => void): void {\n const parentSuite = getCurrentSuite();\n\n const suite: Suite = {\n name,\n tests: [],\n beforeAll: [],\n afterAll: [],\n beforeEach: [],\n afterEach: [],\n };\n\n // Set this as the current suite for nested evalTest() calls\n setCurrentSuite(suite);\n\n // Execute the suite definition function\n // This will register all evalTest() calls within\n try {\n fn();\n } finally {\n // Restore parent suite context (for nested describes)\n setCurrentSuite(parentSuite);\n }\n\n // Add the suite to the global context\n addSuite(suite);\n}\n\n/**\n * Lifecycle hook - runs once before all tests in the suite\n */\nexport function beforeAll(fn: TestFn): void {\n const suite = getCurrentSuite();\n if (!suite) {\n throw new Error(\"beforeAll() must be called inside a describe() block\");\n }\n suite.beforeAll?.push(fn);\n}\n\n/**\n * Lifecycle hook - runs once after all tests in the suite\n */\nexport function afterAll(fn: TestFn): void {\n const suite = getCurrentSuite();\n if (!suite) {\n throw new Error(\"afterAll() must be called inside a describe() block\");\n }\n suite.afterAll?.push(fn);\n}\n\n/**\n * Lifecycle hook - runs before each test in the suite\n */\nexport function beforeEach(fn: TestFn): void {\n const suite = getCurrentSuite();\n if (!suite) {\n throw new Error(\"beforeEach() must be called inside a describe() block\");\n }\n suite.beforeEach?.push(fn);\n}\n\n/**\n * Lifecycle hook - runs after each test in the suite\n */\nexport function afterEach(fn: TestFn): void {\n const suite = getCurrentSuite();\n if (!suite) {\n throw new Error(\"afterEach() must be called inside a describe() block\");\n }\n suite.afterEach?.push(fn);\n}\n","/**\n * evalTest() implementation - defines an individual evaluation test\n */\n\nimport type { EvalTest, TestFn } from \"./types.js\";\nimport { getCurrentSuite, addTestToCurrentSuite } from \"./context.js\";\n\n/**\n * Defines an individual evaluation test within a describe() block\n *\n * @example\n * ```ts\n * evalTest(\"accuracy above 80%\", async () => {\n * const dataset = loadDataset(\"./data.json\");\n * const predictions = await runModel(dataset, classify);\n *\n * expectStats(predictions)\n * .field(\"sentiment\")\n * .toHaveAccuracyAbove(0.8);\n * });\n * ```\n */\nexport function evalTest(name: string, fn: TestFn): void {\n const currentSuite = getCurrentSuite();\n\n if (!currentSuite) {\n throw new Error(\"evalTest() must be called inside a describe() block\");\n }\n\n const test: EvalTest = {\n name,\n fn,\n };\n\n addTestToCurrentSuite(test);\n}\n\n/**\n * Alias for evalTest - some users may prefer \"test\" or \"it\"\n */\nexport const test = evalTest;\nexport const it = evalTest;\n\n/**\n * Skipped test - registers but doesn't run\n */\nexport function evalTestSkip(name: string, _fn: TestFn): void {\n const currentSuite = getCurrentSuite();\n\n if (!currentSuite) {\n throw new Error(\"evalTest.skip() must be called inside a describe() block\");\n }\n\n const test: EvalTest = {\n name: `[SKIPPED] ${name}`,\n fn: async () => {\n // No-op - test is skipped\n },\n };\n\n addTestToCurrentSuite(test);\n}\n\n/**\n * Focused test - only runs this test (TODO: implement filtering)\n */\nexport function evalTestOnly(name: string, fn: TestFn): void {\n const currentSuite = getCurrentSuite();\n\n if (!currentSuite) {\n throw new Error(\"evalTest.only() must be called inside a describe() block\");\n }\n\n const test: EvalTest = {\n name: `[ONLY] ${name}`,\n fn,\n };\n\n addTestToCurrentSuite(test);\n}\n\n// Attach skip and only as properties\nevalTest.skip = evalTestSkip;\nevalTest.only = evalTestOnly;\n","/**\n * Dataset loading functionality\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { resolve, extname } from \"node:path\";\nimport type { Dataset } from \"../core/types.js\";\nimport { DatasetError } from \"../core/errors.js\";\n\n/**\n * Loads a dataset from a JSON or NDJSON file\n *\n * @param path - Path to the dataset file (relative to cwd or absolute)\n * @returns Dataset with records and metadata\n *\n * @example\n * ```ts\n * const dataset = loadDataset(\"./fixtures/sentiment.json\");\n * // dataset.records = [{ id: \"1\", text: \"...\", sentiment: \"positive\" }, ...]\n * ```\n */\nexport function loadDataset<T extends Record<string, unknown> = Record<string, unknown>>(\n path: string\n): Dataset<T> {\n const absolutePath = resolve(process.cwd(), path);\n const ext = extname(absolutePath).toLowerCase();\n\n let records: T[];\n\n try {\n const content = readFileSync(absolutePath, \"utf-8\");\n\n if (ext === \".ndjson\" || ext === \".jsonl\") {\n records = parseNDJSON<T>(content);\n } else if (ext === \".json\") {\n records = parseJSON<T>(content);\n } else {\n throw new DatasetError(\n `Unsupported file format: ${ext}. Use .json, .ndjson, or .jsonl`,\n path\n );\n }\n } catch (error) {\n if (error instanceof DatasetError) {\n throw error;\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new DatasetError(`Failed to load dataset from ${path}: ${message}`, path);\n }\n\n return {\n records,\n metadata: {\n source: path,\n count: records.length,\n loadedAt: new Date(),\n },\n };\n}\n\n/**\n * Parses JSON array content\n */\nfunction parseJSON<T>(content: string): T[] {\n const parsed: unknown = JSON.parse(content);\n\n if (!Array.isArray(parsed)) {\n throw new DatasetError(\"JSON dataset must be an array of records\");\n }\n\n return parsed as T[];\n}\n\n/**\n * Parses NDJSON (newline-delimited JSON) content\n */\nfunction parseNDJSON<T>(content: string): T[] {\n const lines = content.split(\"\\n\").filter((line) => line.trim() !== \"\");\n const records: T[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line === undefined) continue;\n\n try {\n records.push(JSON.parse(line) as T);\n } catch {\n throw new DatasetError(`Invalid JSON at line ${i + 1} in NDJSON file`);\n }\n }\n\n return records;\n}\n\n/**\n * Creates a dataset from an array of records (for testing/programmatic use)\n */\nexport function createDataset<T extends Record<string, unknown>>(\n records: T[],\n source = \"inline\"\n): Dataset<T> {\n return {\n records,\n metadata: {\n source,\n count: records.length,\n loadedAt: new Date(),\n },\n };\n}\n","/**\n * runModel() - executes a model function against a dataset\n */\n\nimport type { Dataset, Prediction, AlignedRecord } from \"../core/types.js\";\nimport { DatasetError } from \"../core/errors.js\";\n\n/**\n * Model function signature - takes a record and returns a prediction\n */\nexport type ModelFn<T> = (record: T) => Prediction | Promise<Prediction>;\n\n/**\n * Result of running a model on a dataset\n */\nexport interface ModelRunResult {\n predictions: Prediction[];\n aligned: AlignedRecord[];\n duration: number;\n}\n\n/**\n * Runs a model function against each record in a dataset\n *\n * @param dataset - The dataset to process\n * @param modelFn - Function that processes each record and returns a prediction\n * @returns Aligned predictions with actual vs expected values\n *\n * @example\n * ```ts\n * const result = await runModel(dataset, (record) => ({\n * id: record.id,\n * sentiment: classify(record.text)\n * }));\n * ```\n */\nexport async function runModel<T extends Record<string, unknown>>(\n dataset: Dataset<T>,\n modelFn: ModelFn<T>\n): Promise<ModelRunResult> {\n const startTime = Date.now();\n const predictions: Prediction[] = [];\n const aligned: AlignedRecord[] = [];\n\n for (const record of dataset.records) {\n const id = getRecordId(record);\n\n // Run the model function\n const prediction = await modelFn(record);\n\n // Validate prediction has matching ID\n if (prediction.id !== id) {\n throw new DatasetError(\n `Prediction ID mismatch: expected \"${id}\", got \"${prediction.id}\". ` +\n `Model function must return the same ID as the input record.`\n );\n }\n\n predictions.push(prediction);\n\n // Create aligned record (actual = prediction, expected = original record)\n aligned.push({\n id,\n actual: { ...prediction },\n expected: { ...record },\n });\n }\n\n return {\n predictions,\n aligned,\n duration: Date.now() - startTime,\n };\n}\n\n/**\n * Extracts the ID from a record (supports \"id\" or \"_id\" fields)\n */\nfunction getRecordId(record: Record<string, unknown>): string {\n const id = record.id ?? record._id;\n\n if (id === undefined || id === null) {\n throw new DatasetError(\n 'Dataset records must have an \"id\" or \"_id\" field for alignment'\n );\n }\n\n return String(id);\n}\n\n/**\n * Runs model in parallel with concurrency limit\n */\nexport async function runModelParallel<T extends Record<string, unknown>>(\n dataset: Dataset<T>,\n modelFn: ModelFn<T>,\n concurrency = 10\n): Promise<ModelRunResult> {\n const startTime = Date.now();\n const results: Array<{ prediction: Prediction; record: T }> = [];\n\n // Process in batches\n for (let i = 0; i < dataset.records.length; i += concurrency) {\n const batch = dataset.records.slice(i, i + concurrency);\n const batchResults = await Promise.all(\n batch.map(async (record) => {\n const prediction = await modelFn(record);\n return { prediction, record };\n })\n );\n results.push(...batchResults);\n }\n\n // Build predictions and aligned arrays in original order\n const predictions: Prediction[] = [];\n const aligned: AlignedRecord[] = [];\n\n for (const { prediction, record } of results) {\n const id = getRecordId(record);\n\n if (prediction.id !== id) {\n throw new DatasetError(\n `Prediction ID mismatch: expected \"${id}\", got \"${prediction.id}\".`\n );\n }\n\n predictions.push(prediction);\n aligned.push({\n id,\n actual: { ...prediction },\n expected: { ...record },\n });\n }\n\n return {\n predictions,\n aligned,\n duration: Date.now() - startTime,\n };\n}\n","/**\n * Dataset alignment utilities\n * Aligns predictions with ground truth by ID\n */\n\nimport type { Prediction, AlignedRecord } from \"../core/types.js\";\nimport { IntegrityError } from \"../core/errors.js\";\n\n/**\n * Options for alignment\n */\nexport interface AlignOptions {\n /** Whether to throw on missing IDs (default: false) */\n strict?: boolean;\n /** Field to use as ID (default: \"id\") */\n idField?: string;\n}\n\n/**\n * Aligns predictions with expected values by ID\n *\n * @param predictions - Model predictions with IDs\n * @param expected - Ground truth records with IDs\n * @param options - Alignment options\n * @returns Array of aligned records\n */\nexport function alignByKey(\n predictions: Prediction[],\n expected: Array<Record<string, unknown>>,\n options: AlignOptions = {}\n): AlignedRecord[] {\n const { strict = false, idField = \"id\" } = options;\n\n // Build lookup map for expected values\n const expectedMap = new Map<string, Record<string, unknown>>();\n for (const record of expected) {\n const id = String(record[idField] ?? record._id);\n expectedMap.set(id, record);\n }\n\n const aligned: AlignedRecord[] = [];\n const missingIds: string[] = [];\n\n for (const prediction of predictions) {\n const id = prediction.id;\n const expectedRecord = expectedMap.get(id);\n\n if (!expectedRecord) {\n missingIds.push(id);\n if (strict) {\n continue;\n }\n // In non-strict mode, include with empty expected\n aligned.push({\n id,\n actual: { ...prediction },\n expected: {},\n });\n } else {\n aligned.push({\n id,\n actual: { ...prediction },\n expected: { ...expectedRecord },\n });\n }\n }\n\n if (strict && missingIds.length > 0) {\n throw new IntegrityError(\n `${missingIds.length} prediction(s) have no matching expected record`,\n missingIds\n );\n }\n\n return aligned;\n}\n\n/**\n * Extracts field values from aligned records for statistical analysis\n *\n * @param aligned - Aligned records\n * @param field - Field name to extract\n * @returns Object with actual and expected arrays\n */\nexport function extractFieldValues(\n aligned: AlignedRecord[],\n field: string\n): { actual: unknown[]; expected: unknown[]; ids: string[] } {\n const actual: unknown[] = [];\n const expected: unknown[] = [];\n const ids: string[] = [];\n\n for (const record of aligned) {\n actual.push(record.actual[field]);\n expected.push(record.expected[field]);\n ids.push(record.id);\n }\n\n return { actual, expected, ids };\n}\n\n/**\n * Filters aligned records to only those with values in both actual and expected\n */\nexport function filterComplete(\n aligned: AlignedRecord[],\n field: string\n): AlignedRecord[] {\n return aligned.filter((record) => {\n const actualValue = record.actual[field];\n const expectedValue = record.expected[field];\n return actualValue !== undefined && expectedValue !== undefined;\n });\n}\n","/**\n * Dataset integrity checks\n */\n\nimport type { Dataset, IntegrityResult, Prediction } from \"../core/types.js\";\nimport { IntegrityError } from \"../core/errors.js\";\n\n/**\n * Options for integrity checks\n */\nexport interface IntegrityOptions {\n /** Required fields that must be present in each record */\n requiredFields?: string[];\n /** Whether to throw on integrity failures (default: false) */\n throwOnFailure?: boolean;\n}\n\n/**\n * Checks dataset integrity - validates IDs and required fields\n *\n * @param dataset - Dataset to check\n * @param options - Integrity check options\n * @returns Integrity result with details\n */\nexport function checkIntegrity<T extends Record<string, unknown>>(\n dataset: Dataset<T>,\n options: IntegrityOptions = {}\n): IntegrityResult {\n const { requiredFields = [], throwOnFailure = false } = options;\n\n const seenIds = new Map<string, number>();\n const missingIds: string[] = [];\n const duplicateIds: string[] = [];\n const missingFields: Array<{ id: string; fields: string[] }> = [];\n\n for (let i = 0; i < dataset.records.length; i++) {\n const record = dataset.records[i];\n if (!record) continue;\n\n // Check for ID\n const id = record.id ?? record._id;\n if (id === undefined || id === null) {\n missingIds.push(`record[${i}]`);\n } else {\n const idStr = String(id);\n const previousIndex = seenIds.get(idStr);\n if (previousIndex !== undefined) {\n duplicateIds.push(idStr);\n } else {\n seenIds.set(idStr, i);\n }\n }\n\n // Check for required fields\n if (requiredFields.length > 0) {\n const missing = requiredFields.filter(\n (field) => record[field] === undefined\n );\n if (missing.length > 0) {\n missingFields.push({\n id: String(id ?? `record[${i}]`),\n fields: missing,\n });\n }\n }\n }\n\n const valid =\n missingIds.length === 0 &&\n duplicateIds.length === 0 &&\n missingFields.length === 0;\n\n const result: IntegrityResult = {\n valid,\n totalRecords: dataset.records.length,\n missingIds,\n duplicateIds,\n missingFields,\n };\n\n if (throwOnFailure && !valid) {\n const issues: string[] = [];\n if (missingIds.length > 0) {\n issues.push(`${missingIds.length} record(s) missing ID`);\n }\n if (duplicateIds.length > 0) {\n issues.push(`${duplicateIds.length} duplicate ID(s): ${duplicateIds.slice(0, 3).join(\", \")}${duplicateIds.length > 3 ? \"...\" : \"\"}`);\n }\n if (missingFields.length > 0) {\n issues.push(`${missingFields.length} record(s) missing required fields`);\n }\n throw new IntegrityError(`Dataset integrity check failed: ${issues.join(\"; \")}`);\n }\n\n return result;\n}\n\n/**\n * Validates predictions against a dataset\n */\nexport function validatePredictions(\n predictions: Prediction[],\n expectedIds: string[]\n): { valid: boolean; missing: string[]; extra: string[] } {\n const predictionIds = new Set(predictions.map((p) => p.id));\n const expectedIdSet = new Set(expectedIds);\n\n const missing = expectedIds.filter((id) => !predictionIds.has(id));\n const extra = predictions\n .map((p) => p.id)\n .filter((id) => !expectedIdSet.has(id));\n\n return {\n valid: missing.length === 0 && extra.length === 0,\n missing,\n extra,\n };\n}\n\n/**\n * Checks if a value is a valid numeric value (not NaN, Infinity, etc.)\n */\nexport function isValidNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\n/**\n * Checks if a value is a valid string label\n */\nexport function isValidLabel(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n","/**\n * Classification metrics computation\n */\n\nimport type { ConfusionMatrix, ClassificationMetrics, ClassMetrics } from \"../core/types.js\";\nimport {\n buildConfusionMatrix,\n getTruePositives,\n getFalsePositives,\n getFalseNegatives,\n getSupport,\n} from \"./confusion-matrix.js\";\n\n/**\n * Computes all classification metrics from actual and expected values\n */\nexport function computeClassificationMetrics(\n actual: unknown[],\n expected: unknown[]\n): ClassificationMetrics {\n const confusionMatrix = buildConfusionMatrix(actual, expected);\n return computeMetricsFromMatrix(confusionMatrix);\n}\n\n/**\n * Computes classification metrics from a pre-built confusion matrix\n */\nexport function computeMetricsFromMatrix(cm: ConfusionMatrix): ClassificationMetrics {\n const perClass: Record<string, ClassMetrics> = {};\n let totalSupport = 0;\n let correctPredictions = 0;\n\n // Compute per-class metrics\n for (const label of cm.labels) {\n const tp = getTruePositives(cm, label);\n const fp = getFalsePositives(cm, label);\n const fn = getFalseNegatives(cm, label);\n const support = getSupport(cm, label);\n\n const precision = tp + fp > 0 ? tp / (tp + fp) : 0;\n const recall = tp + fn > 0 ? tp / (tp + fn) : 0;\n const f1 = precision + recall > 0 ? (2 * precision * recall) / (precision + recall) : 0;\n\n perClass[label] = { precision, recall, f1, support };\n totalSupport += support;\n correctPredictions += tp;\n }\n\n // Compute accuracy\n const accuracy = totalSupport > 0 ? correctPredictions / totalSupport : 0;\n\n // Compute macro averages (unweighted mean)\n const classCount = cm.labels.length;\n const macroAvg = {\n precision:\n classCount > 0\n ? Object.values(perClass).reduce((sum, m) => sum + m.precision, 0) / classCount\n : 0,\n recall:\n classCount > 0\n ? Object.values(perClass).reduce((sum, m) => sum + m.recall, 0) / classCount\n : 0,\n f1:\n classCount > 0\n ? Object.values(perClass).reduce((sum, m) => sum + m.f1, 0) / classCount\n : 0,\n };\n\n // Compute weighted averages\n const weightedAvg = {\n precision:\n totalSupport > 0\n ? Object.values(perClass).reduce((sum, m) => sum + m.precision * m.support, 0) /\n totalSupport\n : 0,\n recall:\n totalSupport > 0\n ? Object.values(perClass).reduce((sum, m) => sum + m.recall * m.support, 0) / totalSupport\n : 0,\n f1:\n totalSupport > 0\n ? Object.values(perClass).reduce((sum, m) => sum + m.f1 * m.support, 0) / totalSupport\n : 0,\n };\n\n return {\n accuracy,\n perClass,\n macroAvg,\n weightedAvg,\n confusionMatrix: cm,\n };\n}\n\n/**\n * Computes precision for a specific class\n */\nexport function computePrecision(actual: unknown[], expected: unknown[], targetClass: string): number {\n const cm = buildConfusionMatrix(actual, expected);\n const tp = getTruePositives(cm, targetClass);\n const fp = getFalsePositives(cm, targetClass);\n return tp + fp > 0 ? tp / (tp + fp) : 0;\n}\n\n/**\n * Computes recall for a specific class\n */\nexport function computeRecall(actual: unknown[], expected: unknown[], targetClass: string): number {\n const cm = buildConfusionMatrix(actual, expected);\n const tp = getTruePositives(cm, targetClass);\n const fn = getFalseNegatives(cm, targetClass);\n return tp + fn > 0 ? tp / (tp + fn) : 0;\n}\n\n/**\n * Computes F1 score for a specific class\n */\nexport function computeF1(actual: unknown[], expected: unknown[], targetClass: string): number {\n const precision = computePrecision(actual, expected, targetClass);\n const recall = computeRecall(actual, expected, targetClass);\n return precision + recall > 0 ? (2 * precision * recall) / (precision + recall) : 0;\n}\n\n/**\n * Computes overall accuracy\n */\nexport function computeAccuracy(actual: unknown[], expected: unknown[]): number {\n if (actual.length !== expected.length || actual.length === 0) {\n return 0;\n }\n\n let correct = 0;\n let total = 0;\n\n for (let i = 0; i < actual.length; i++) {\n const a = actual[i];\n const e = expected[i];\n if (a !== undefined && a !== null && e !== undefined && e !== null) {\n total++;\n if (String(a) === String(e)) {\n correct++;\n }\n }\n }\n\n return total > 0 ? correct / total : 0;\n}\n","/**\n * Distribution analysis utilities for percentage-based assertions.\n * These functions operate on actual values only (no ground truth required).\n */\n\n/**\n * Filters an array to only include numeric values.\n * Removes null, undefined, NaN, and non-numeric types.\n *\n * @param values - Array of values to filter\n * @returns Array containing only valid numeric values\n *\n * @example\n * filterNumericValues([1, 2, null, \"3\", 4, undefined, NaN])\n * // Returns: [1, 2, 4]\n */\nexport function filterNumericValues(values: unknown[]): number[] {\n return values.filter(\n (v): v is number =>\n typeof v === \"number\" && !Number.isNaN(v) && v !== null && v !== undefined\n );\n}\n\n/**\n * Calculates the percentage of values that are below or equal to a threshold.\n *\n * @param values - Array of numeric values\n * @param threshold - Threshold value for comparison\n * @returns Percentage (0-1) of values <= threshold. Returns 0 for empty arrays.\n *\n * @example\n * calculatePercentageBelow([1, 2, 3, 4, 5], 3)\n * // Returns: 0.6 (60% of values are <= 3)\n */\nexport function calculatePercentageBelow(\n values: number[],\n threshold: number\n): number {\n if (values.length === 0) {\n return 0;\n }\n\n const countBelow = values.filter((v) => v <= threshold).length;\n return countBelow / values.length;\n}\n\n/**\n * Calculates the percentage of values that are above a threshold.\n *\n * @param values - Array of numeric values\n * @param threshold - Threshold value for comparison\n * @returns Percentage (0-1) of values > threshold. Returns 0 for empty arrays.\n *\n * @example\n * calculatePercentageAbove([1, 2, 3, 4, 5], 3)\n * // Returns: 0.4 (40% of values are > 3)\n */\nexport function calculatePercentageAbove(\n values: number[],\n threshold: number\n): number {\n if (values.length === 0) {\n return 0;\n }\n\n const countAbove = values.filter((v) => v > threshold).length;\n return countAbove / values.length;\n}\n","/**\n * BinarizeSelector - transforms continuous scores to binary for classification metrics\n */\n\nimport type { AlignedRecord, AssertionResult, FieldMetricResult } from \"../core/types.js\";\nimport { recordAssertion, recordFieldMetrics } from \"../core/context.js\";\nimport { AssertionError } from \"../core/errors.js\";\nimport { computeClassificationMetrics } from \"../statistics/classification.js\";\n\n/**\n * Selector for binarized fields (continuous → binary threshold)\n */\nexport class BinarizeSelector {\n private fieldName: string;\n private threshold: number;\n private binaryActual: string[];\n private binaryExpected: string[];\n private assertions: AssertionResult[] = [];\n\n constructor(aligned: AlignedRecord[], fieldName: string, threshold: number) {\n this.fieldName = fieldName;\n this.threshold = threshold;\n\n // Binarize values\n this.binaryActual = [];\n this.binaryExpected = [];\n\n for (const record of aligned) {\n const actualVal = record.actual[fieldName];\n const expectedVal = record.expected[fieldName];\n\n // Binarize actual (numeric score → true/false)\n if (typeof actualVal === \"number\") {\n this.binaryActual.push(actualVal >= threshold ? \"true\" : \"false\");\n } else if (typeof actualVal === \"boolean\") {\n this.binaryActual.push(String(actualVal));\n } else {\n this.binaryActual.push(String(actualVal));\n }\n\n // Expected can be boolean, number, or string\n if (typeof expectedVal === \"number\") {\n this.binaryExpected.push(expectedVal >= threshold ? \"true\" : \"false\");\n } else if (typeof expectedVal === \"boolean\") {\n this.binaryExpected.push(String(expectedVal));\n } else {\n this.binaryExpected.push(String(expectedVal));\n }\n }\n }\n\n /**\n * Asserts that accuracy is above a threshold\n */\n toHaveAccuracyAbove(threshold: number): this {\n const metrics = computeClassificationMetrics(this.binaryActual, this.binaryExpected);\n const passed = metrics.accuracy >= threshold;\n\n const result: AssertionResult = {\n type: \"accuracy\",\n passed,\n message: passed\n ? `Accuracy ${(metrics.accuracy * 100).toFixed(1)}% is above ${(threshold * 100).toFixed(1)}% (binarized at ${this.threshold})`\n : `Accuracy ${(metrics.accuracy * 100).toFixed(1)}% is below threshold ${(threshold * 100).toFixed(1)}% (binarized at ${this.threshold})`,\n expected: threshold,\n actual: metrics.accuracy,\n field: this.fieldName,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, threshold, metrics.accuracy, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that precision is above a threshold\n * @param classOrThreshold - Either the class (true/false) or threshold\n * @param threshold - Threshold when class is specified\n */\n toHavePrecisionAbove(classOrThreshold: boolean | number, threshold?: number): this {\n const metrics = computeClassificationMetrics(this.binaryActual, this.binaryExpected);\n\n let actualPrecision: number;\n let targetClass: string | undefined;\n let actualThreshold: number;\n\n if (typeof classOrThreshold === \"number\") {\n actualPrecision = metrics.macroAvg.precision;\n actualThreshold = classOrThreshold;\n } else {\n targetClass = String(classOrThreshold);\n actualThreshold = threshold!;\n const classMetrics = metrics.perClass[targetClass];\n if (!classMetrics) {\n throw new AssertionError(\n `Class \"${targetClass}\" not found in binarized predictions`,\n targetClass,\n Object.keys(metrics.perClass),\n this.fieldName\n );\n }\n actualPrecision = classMetrics.precision;\n }\n\n const passed = actualPrecision >= actualThreshold;\n\n const result: AssertionResult = {\n type: \"precision\",\n passed,\n message: passed\n ? `Precision${targetClass ? ` for ${targetClass}` : \"\"} ${(actualPrecision * 100).toFixed(1)}% is above ${(actualThreshold * 100).toFixed(1)}%`\n : `Precision${targetClass ? ` for ${targetClass}` : \"\"} ${(actualPrecision * 100).toFixed(1)}% is below threshold ${(actualThreshold * 100).toFixed(1)}%`,\n expected: actualThreshold,\n actual: actualPrecision,\n field: this.fieldName,\n class: targetClass,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, actualThreshold, actualPrecision, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that recall is above a threshold\n * @param classOrThreshold - Either the class (true/false) or threshold\n * @param threshold - Threshold when class is specified\n */\n toHaveRecallAbove(classOrThreshold: boolean | number, threshold?: number): this {\n const metrics = computeClassificationMetrics(this.binaryActual, this.binaryExpected);\n\n let actualRecall: number;\n let targetClass: string | undefined;\n let actualThreshold: number;\n\n if (typeof classOrThreshold === \"number\") {\n actualRecall = metrics.macroAvg.recall;\n actualThreshold = classOrThreshold;\n } else {\n targetClass = String(classOrThreshold);\n actualThreshold = threshold!;\n const classMetrics = metrics.perClass[targetClass];\n if (!classMetrics) {\n throw new AssertionError(\n `Class \"${targetClass}\" not found in binarized predictions`,\n targetClass,\n Object.keys(metrics.perClass),\n this.fieldName\n );\n }\n actualRecall = classMetrics.recall;\n }\n\n const passed = actualRecall >= actualThreshold;\n\n const result: AssertionResult = {\n type: \"recall\",\n passed,\n message: passed\n ? `Recall${targetClass ? ` for ${targetClass}` : \"\"} ${(actualRecall * 100).toFixed(1)}% is above ${(actualThreshold * 100).toFixed(1)}%`\n : `Recall${targetClass ? ` for ${targetClass}` : \"\"} ${(actualRecall * 100).toFixed(1)}% is below threshold ${(actualThreshold * 100).toFixed(1)}%`,\n expected: actualThreshold,\n actual: actualRecall,\n field: this.fieldName,\n class: targetClass,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, actualThreshold, actualRecall, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that F1 score is above a threshold\n */\n toHaveF1Above(classOrThreshold: boolean | number, threshold?: number): this {\n const metrics = computeClassificationMetrics(this.binaryActual, this.binaryExpected);\n\n let actualF1: number;\n let targetClass: string | undefined;\n let actualThreshold: number;\n\n if (typeof classOrThreshold === \"number\") {\n actualF1 = metrics.macroAvg.f1;\n actualThreshold = classOrThreshold;\n } else {\n targetClass = String(classOrThreshold);\n actualThreshold = threshold!;\n const classMetrics = metrics.perClass[targetClass];\n if (!classMetrics) {\n throw new AssertionError(\n `Class \"${targetClass}\" not found in binarized predictions`,\n targetClass,\n Object.keys(metrics.perClass),\n this.fieldName\n );\n }\n actualF1 = classMetrics.f1;\n }\n\n const passed = actualF1 >= actualThreshold;\n\n const result: AssertionResult = {\n type: \"f1\",\n passed,\n message: passed\n ? `F1${targetClass ? ` for ${targetClass}` : \"\"} ${(actualF1 * 100).toFixed(1)}% is above ${(actualThreshold * 100).toFixed(1)}%`\n : `F1${targetClass ? ` for ${targetClass}` : \"\"} ${(actualF1 * 100).toFixed(1)}% is below threshold ${(actualThreshold * 100).toFixed(1)}%`,\n expected: actualThreshold,\n actual: actualF1,\n field: this.fieldName,\n class: targetClass,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, actualThreshold, actualF1, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Includes the confusion matrix in the report\n */\n toHaveConfusionMatrix(): this {\n const metrics = computeClassificationMetrics(this.binaryActual, this.binaryExpected);\n\n const fieldResult: FieldMetricResult = {\n field: this.fieldName,\n metrics,\n binarized: true,\n binarizeThreshold: this.threshold,\n };\n\n recordFieldMetrics(fieldResult);\n\n const result: AssertionResult = {\n type: \"confusionMatrix\",\n passed: true,\n message: `Confusion matrix recorded for binarized field \"${this.fieldName}\" (threshold: ${this.threshold})`,\n field: this.fieldName,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n return this;\n }\n\n /**\n * Gets computed metrics\n */\n getMetrics() {\n return computeClassificationMetrics(this.binaryActual, this.binaryExpected);\n }\n\n /**\n * Gets all assertions made\n */\n getAssertions(): AssertionResult[] {\n return this.assertions;\n }\n}\n","/**\n * FieldSelector - selects a field for statistical assertions\n */\n\nimport type { AlignedRecord, AssertionResult, FieldMetricResult } from \"../core/types.js\";\nimport { recordAssertion, recordFieldMetrics } from \"../core/context.js\";\nimport { AssertionError } from \"../core/errors.js\";\nimport { extractFieldValues } from \"../dataset/alignment.js\";\nimport { computeClassificationMetrics } from \"../statistics/classification.js\";\nimport {\n filterNumericValues,\n calculatePercentageBelow,\n calculatePercentageAbove,\n} from \"../statistics/distribution.js\";\nimport { BinarizeSelector } from \"./binarize.js\";\n\n/**\n * Field selector for building assertions on a specific field\n */\nexport class FieldSelector {\n private aligned: AlignedRecord[];\n private fieldName: string;\n private actualValues: unknown[];\n private expectedValues: unknown[];\n private assertions: AssertionResult[] = [];\n\n constructor(aligned: AlignedRecord[], fieldName: string) {\n this.aligned = aligned;\n this.fieldName = fieldName;\n\n const extracted = extractFieldValues(aligned, fieldName);\n this.actualValues = extracted.actual;\n this.expectedValues = extracted.expected;\n }\n\n /**\n * Transforms continuous scores to binary classification using a threshold\n */\n binarize(threshold: number): BinarizeSelector {\n return new BinarizeSelector(this.aligned, this.fieldName, threshold);\n }\n\n /**\n * Validates that ground truth exists for classification metrics.\n * Throws a clear error if expected values are missing.\n */\n private validateGroundTruth(): void {\n const hasExpected = this.expectedValues.some(\n (v) => v !== undefined && v !== null\n );\n if (!hasExpected) {\n throw new AssertionError(\n `Classification metric requires ground truth, but field \"${this.fieldName}\" has no expected values. ` +\n `Use expectStats(predictions, groundTruth) to provide expected values.`,\n undefined,\n undefined,\n this.fieldName\n );\n }\n }\n\n /**\n * Asserts that accuracy is above a threshold\n */\n toHaveAccuracyAbove(threshold: number): this {\n this.validateGroundTruth();\n const metrics = computeClassificationMetrics(this.actualValues, this.expectedValues);\n const passed = metrics.accuracy >= threshold;\n\n const result: AssertionResult = {\n type: \"accuracy\",\n passed,\n message: passed\n ? `Accuracy ${(metrics.accuracy * 100).toFixed(1)}% is above ${(threshold * 100).toFixed(1)}%`\n : `Accuracy ${(metrics.accuracy * 100).toFixed(1)}% is below threshold ${(threshold * 100).toFixed(1)}%`,\n expected: threshold,\n actual: metrics.accuracy,\n field: this.fieldName,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, threshold, metrics.accuracy, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that precision is above a threshold\n * @param classOrThreshold - Either the class name or threshold (if class is omitted, uses macro average)\n * @param threshold - Threshold when class is specified\n */\n toHavePrecisionAbove(classOrThreshold: string | number, threshold?: number): this {\n this.validateGroundTruth();\n const metrics = computeClassificationMetrics(this.actualValues, this.expectedValues);\n\n let actualPrecision: number;\n let targetClass: string | undefined;\n let actualThreshold: number;\n\n if (typeof classOrThreshold === \"number\") {\n // Macro average precision\n actualPrecision = metrics.macroAvg.precision;\n actualThreshold = classOrThreshold;\n } else {\n // Per-class precision\n targetClass = classOrThreshold;\n actualThreshold = threshold!;\n const classMetrics = metrics.perClass[targetClass];\n if (!classMetrics) {\n throw new AssertionError(\n `Class \"${targetClass}\" not found in predictions`,\n targetClass,\n Object.keys(metrics.perClass),\n this.fieldName\n );\n }\n actualPrecision = classMetrics.precision;\n }\n\n const passed = actualPrecision >= actualThreshold;\n\n const result: AssertionResult = {\n type: \"precision\",\n passed,\n message: passed\n ? `Precision${targetClass ? ` for \"${targetClass}\"` : \"\"} ${(actualPrecision * 100).toFixed(1)}% is above ${(actualThreshold * 100).toFixed(1)}%`\n : `Precision${targetClass ? ` for \"${targetClass}\"` : \"\"} ${(actualPrecision * 100).toFixed(1)}% is below threshold ${(actualThreshold * 100).toFixed(1)}%`,\n expected: actualThreshold,\n actual: actualPrecision,\n field: this.fieldName,\n class: targetClass,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, actualThreshold, actualPrecision, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that recall is above a threshold\n * @param classOrThreshold - Either the class name or threshold (if class is omitted, uses macro average)\n * @param threshold - Threshold when class is specified\n */\n toHaveRecallAbove(classOrThreshold: string | number, threshold?: number): this {\n this.validateGroundTruth();\n const metrics = computeClassificationMetrics(this.actualValues, this.expectedValues);\n\n let actualRecall: number;\n let targetClass: string | undefined;\n let actualThreshold: number;\n\n if (typeof classOrThreshold === \"number\") {\n // Macro average recall\n actualRecall = metrics.macroAvg.recall;\n actualThreshold = classOrThreshold;\n } else {\n // Per-class recall\n targetClass = classOrThreshold;\n actualThreshold = threshold!;\n const classMetrics = metrics.perClass[targetClass];\n if (!classMetrics) {\n throw new AssertionError(\n `Class \"${targetClass}\" not found in predictions`,\n targetClass,\n Object.keys(metrics.perClass),\n this.fieldName\n );\n }\n actualRecall = classMetrics.recall;\n }\n\n const passed = actualRecall >= actualThreshold;\n\n const result: AssertionResult = {\n type: \"recall\",\n passed,\n message: passed\n ? `Recall${targetClass ? ` for \"${targetClass}\"` : \"\"} ${(actualRecall * 100).toFixed(1)}% is above ${(actualThreshold * 100).toFixed(1)}%`\n : `Recall${targetClass ? ` for \"${targetClass}\"` : \"\"} ${(actualRecall * 100).toFixed(1)}% is below threshold ${(actualThreshold * 100).toFixed(1)}%`,\n expected: actualThreshold,\n actual: actualRecall,\n field: this.fieldName,\n class: targetClass,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, actualThreshold, actualRecall, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that F1 score is above a threshold\n * @param classOrThreshold - Either the class name or threshold (if class is omitted, uses macro average)\n * @param threshold - Threshold when class is specified\n */\n toHaveF1Above(classOrThreshold: string | number, threshold?: number): this {\n this.validateGroundTruth();\n const metrics = computeClassificationMetrics(this.actualValues, this.expectedValues);\n\n let actualF1: number;\n let targetClass: string | undefined;\n let actualThreshold: number;\n\n if (typeof classOrThreshold === \"number\") {\n // Macro average F1\n actualF1 = metrics.macroAvg.f1;\n actualThreshold = classOrThreshold;\n } else {\n // Per-class F1\n targetClass = classOrThreshold;\n actualThreshold = threshold!;\n const classMetrics = metrics.perClass[targetClass];\n if (!classMetrics) {\n throw new AssertionError(\n `Class \"${targetClass}\" not found in predictions`,\n targetClass,\n Object.keys(metrics.perClass),\n this.fieldName\n );\n }\n actualF1 = classMetrics.f1;\n }\n\n const passed = actualF1 >= actualThreshold;\n\n const result: AssertionResult = {\n type: \"f1\",\n passed,\n message: passed\n ? `F1${targetClass ? ` for \"${targetClass}\"` : \"\"} ${(actualF1 * 100).toFixed(1)}% is above ${(actualThreshold * 100).toFixed(1)}%`\n : `F1${targetClass ? ` for \"${targetClass}\"` : \"\"} ${(actualF1 * 100).toFixed(1)}% is below threshold ${(actualThreshold * 100).toFixed(1)}%`,\n expected: actualThreshold,\n actual: actualF1,\n field: this.fieldName,\n class: targetClass,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, actualThreshold, actualF1, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Includes the confusion matrix in the report\n */\n toHaveConfusionMatrix(): this {\n const metrics = computeClassificationMetrics(this.actualValues, this.expectedValues);\n\n const fieldResult: FieldMetricResult = {\n field: this.fieldName,\n metrics,\n binarized: false,\n };\n\n recordFieldMetrics(fieldResult);\n\n const result: AssertionResult = {\n type: \"confusionMatrix\",\n passed: true,\n message: `Confusion matrix recorded for field \"${this.fieldName}\"`,\n field: this.fieldName,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n return this;\n }\n\n /**\n * Asserts that a percentage of values are below or equal to a threshold.\n * This is a distributional assertion that only looks at actual values (no ground truth required).\n *\n * @param valueThreshold - The value threshold to compare against\n * @param percentageThreshold - The minimum percentage (0-1) of values that should be <= valueThreshold\n * @returns this for method chaining\n *\n * @example\n * // Assert that 90% of confidence scores are below 0.5\n * expectStats(predictions)\n * .field(\"confidence\")\n * .toHavePercentageBelow(0.5, 0.9)\n */\n toHavePercentageBelow(valueThreshold: number, percentageThreshold: number): this {\n // Filter to numeric values only\n const numericActual = filterNumericValues(this.actualValues);\n\n // Validate: throw if no numeric values found\n if (numericActual.length === 0) {\n throw new AssertionError(\n `Field '${this.fieldName}' contains no numeric values (found 0 numeric out of ${this.actualValues.length} total values)`,\n percentageThreshold,\n undefined,\n this.fieldName\n );\n }\n\n // Calculate actual percentage\n const actualPercentage = calculatePercentageBelow(numericActual, valueThreshold);\n const passed = actualPercentage >= percentageThreshold;\n\n // Create AssertionResult\n const result: AssertionResult = {\n type: \"percentageBelow\",\n passed,\n message: passed\n ? `${(actualPercentage * 100).toFixed(1)}% of '${this.fieldName}' values are below or equal to ${valueThreshold} (expected >= ${(percentageThreshold * 100).toFixed(1)}%)`\n : `Only ${(actualPercentage * 100).toFixed(1)}% of '${this.fieldName}' values are below or equal to ${valueThreshold} (expected >= ${(percentageThreshold * 100).toFixed(1)}%)`,\n expected: percentageThreshold,\n actual: actualPercentage,\n field: this.fieldName,\n };\n\n // Record and throw if failed\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, percentageThreshold, actualPercentage, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that a percentage of values are above a threshold.\n * This is a distributional assertion that only looks at actual values (no ground truth required).\n *\n * @param valueThreshold - The value threshold to compare against\n * @param percentageThreshold - The minimum percentage (0-1) of values that should be > valueThreshold\n * @returns this for method chaining\n *\n * @example\n * // Assert that 80% of quality scores are above 0.7\n * expectStats(predictions)\n * .field(\"quality\")\n * .toHavePercentageAbove(0.7, 0.8)\n */\n toHavePercentageAbove(valueThreshold: number, percentageThreshold: number): this {\n // Filter to numeric values only\n const numericActual = filterNumericValues(this.actualValues);\n\n // Validate: throw if no numeric values found\n if (numericActual.length === 0) {\n throw new AssertionError(\n `Field '${this.fieldName}' contains no numeric values (found 0 numeric out of ${this.actualValues.length} total values)`,\n percentageThreshold,\n undefined,\n this.fieldName\n );\n }\n\n // Calculate actual percentage\n const actualPercentage = calculatePercentageAbove(numericActual, valueThreshold);\n const passed = actualPercentage >= percentageThreshold;\n\n // Create AssertionResult\n const result: AssertionResult = {\n type: \"percentageAbove\",\n passed,\n message: passed\n ? `${(actualPercentage * 100).toFixed(1)}% of '${this.fieldName}' values are above ${valueThreshold} (expected >= ${(percentageThreshold * 100).toFixed(1)}%)`\n : `Only ${(actualPercentage * 100).toFixed(1)}% of '${this.fieldName}' values are above ${valueThreshold} (expected >= ${(percentageThreshold * 100).toFixed(1)}%)`,\n expected: percentageThreshold,\n actual: actualPercentage,\n field: this.fieldName,\n };\n\n // Record and throw if failed\n this.assertions.push(result);\n recordAssertion(result);\n\n if (!passed) {\n throw new AssertionError(result.message, percentageThreshold, actualPercentage, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Gets the computed metrics for this field\n */\n getMetrics() {\n return computeClassificationMetrics(this.actualValues, this.expectedValues);\n }\n\n /**\n * Gets all assertions made on this field\n */\n getAssertions(): AssertionResult[] {\n return this.assertions;\n }\n}\n","/**\n * expectStats() - fluent assertion API for statistical evaluation\n */\n\nimport type { ModelRunResult } from \"../dataset/run-model.js\";\nimport type { Prediction, AlignedRecord } from \"../core/types.js\";\nimport { alignByKey } from \"../dataset/alignment.js\";\nimport { FieldSelector } from \"./field-selector.js\";\n\n/**\n * Input types that expectStats() accepts\n */\nexport type StatsInput = ModelRunResult | Prediction[] | AlignedRecord[];\n\n/**\n * Normalizes input to aligned records format\n */\nfunction normalizeInput(input: StatsInput): AlignedRecord[] {\n // ModelRunResult\n if (\"aligned\" in input && Array.isArray(input.aligned)) {\n return input.aligned;\n }\n\n // Array of predictions or aligned records\n if (Array.isArray(input)) {\n if (input.length === 0) {\n return [];\n }\n\n // Check if it's already AlignedRecord[]\n const first = input[0];\n if (first && \"actual\" in first && \"expected\" in first) {\n return input as AlignedRecord[];\n }\n\n // It's Prediction[] - convert to AlignedRecord with empty expected\n return (input as Prediction[]).map((p) => ({\n id: p.id,\n actual: { ...p },\n expected: {},\n }));\n }\n\n throw new Error(\"Invalid input to expectStats(): expected ModelRunResult, Prediction[], or AlignedRecord[]\");\n}\n\n/**\n * Entry point for statistical assertions.\n *\n * Supports two usage patterns:\n * 1. Single argument: predictions without ground truth (for distribution assertions)\n * 2. Two arguments: predictions with ground truth (for classification metrics)\n *\n * @param inputOrActual - Either StatsInput (one-arg) or Prediction[] (two-arg)\n * @param expected - Ground truth data (optional, only for two-arg usage)\n * @returns ExpectStats instance for chaining assertions\n *\n * @example\n * // Pattern 1: Distribution assertions (no ground truth)\n * expectStats(predictions)\n * .field(\"confidence\")\n * .toHavePercentageBelow(0.5, 0.9);\n *\n * @example\n * // Pattern 1b: Judge validation (with ground truth)\n * expectStats(judgeOutputs, humanLabels)\n * .field(\"hallucinated\")\n * .toHaveRecallAbove(true, 0.85)\n * .toHavePrecisionAbove(true, 0.8);\n */\nexport function expectStats(input: StatsInput): ExpectStats;\nexport function expectStats(\n actual: Prediction[],\n expected: Array<Record<string, unknown>>\n): ExpectStats;\nexport function expectStats(\n inputOrActual: StatsInput | Prediction[],\n expected?: Array<Record<string, unknown>>\n): ExpectStats {\n // Two-argument case: align predictions with ground truth\n if (expected !== undefined) {\n if (!Array.isArray(inputOrActual)) {\n throw new Error(\n \"When using two-argument expectStats(), first argument must be Prediction[]\"\n );\n }\n const aligned = alignByKey(inputOrActual as Prediction[], expected);\n return new ExpectStats(aligned);\n }\n\n // One-argument case: use existing normalization logic\n const aligned = normalizeInput(inputOrActual as StatsInput);\n return new ExpectStats(aligned);\n}\n\n/**\n * Main stats expectation class\n */\nexport class ExpectStats {\n private aligned: AlignedRecord[];\n\n constructor(aligned: AlignedRecord[]) {\n this.aligned = aligned;\n }\n\n /**\n * Selects a field to evaluate\n */\n field(fieldName: string): FieldSelector {\n return new FieldSelector(this.aligned, fieldName);\n }\n\n /**\n * Gets the raw aligned records (for advanced use)\n */\n getAligned(): AlignedRecord[] {\n return this.aligned;\n }\n\n /**\n * Gets the count of records\n */\n count(): number {\n return this.aligned.length;\n }\n}\n"]}