evalsense 0.3.0 → 0.3.2
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.
- package/README.md +89 -66
- package/dist/{chunk-DFC6FRTG.cjs → chunk-BFGA2NUB.cjs} +67 -8
- package/dist/chunk-BFGA2NUB.cjs.map +1 -0
- package/dist/{chunk-JPVZL45G.js → chunk-IYLSY7NX.js} +67 -8
- package/dist/chunk-IYLSY7NX.js.map +1 -0
- package/dist/cli.cjs +11 -11
- package/dist/cli.js +1 -1
- package/dist/index.cjs +101 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +23 -55
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-DFC6FRTG.cjs.map +0 -1
- package/dist/chunk-JPVZL45G.js.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +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/regression.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('Dataset records must have an \"id\" or \"_id\" field for alignment');\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(`Prediction ID mismatch: expected \"${id}\", got \"${prediction.id}\".`);\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(aligned: AlignedRecord[], field: string): 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((field) => record[field] === undefined);\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 = missingIds.length === 0 && duplicateIds.length === 0 && 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(\n `${duplicateIds.length} duplicate ID(s): ${duplicateIds.slice(0, 3).join(\", \")}${duplicateIds.length > 3 ? \"...\" : \"\"}`\n );\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.map((p) => p.id).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: classCount > 0 ? Object.values(perClass).reduce((sum, m) => sum + m.f1, 0) / classCount : 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(\n actual: unknown[],\n expected: unknown[],\n targetClass: string\n): 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 * Regression metrics computation\n */\n\nimport type { RegressionMetrics } from \"../core/types.js\";\n\n/**\n * Computes all regression metrics from actual and expected values\n */\nexport function computeRegressionMetrics(actual: number[], expected: number[]): RegressionMetrics {\n if (actual.length !== expected.length) {\n throw new Error(\n `Array length mismatch: actual has ${actual.length} elements, expected has ${expected.length}`\n );\n }\n\n const n = actual.length;\n if (n === 0) {\n return { mae: 0, mse: 0, rmse: 0, r2: 0 };\n }\n\n const mae = computeMAE(actual, expected);\n const mse = computeMSE(actual, expected);\n const rmse = Math.sqrt(mse);\n const r2 = computeR2(actual, expected);\n\n return { mae, mse, rmse, r2 };\n}\n\n/**\n * Computes Mean Absolute Error\n */\nexport function computeMAE(actual: number[], expected: number[]): number {\n if (actual.length !== expected.length || actual.length === 0) {\n return 0;\n }\n\n let sum = 0;\n for (let i = 0; i < actual.length; i++) {\n sum += Math.abs((actual[i] ?? 0) - (expected[i] ?? 0));\n }\n\n return sum / actual.length;\n}\n\n/**\n * Computes Mean Squared Error\n */\nexport function computeMSE(actual: number[], expected: number[]): number {\n if (actual.length !== expected.length || actual.length === 0) {\n return 0;\n }\n\n let sum = 0;\n for (let i = 0; i < actual.length; i++) {\n const diff = (actual[i] ?? 0) - (expected[i] ?? 0);\n sum += diff * diff;\n }\n\n return sum / actual.length;\n}\n\n/**\n * Computes Root Mean Squared Error\n */\nexport function computeRMSE(actual: number[], expected: number[]): number {\n return Math.sqrt(computeMSE(actual, expected));\n}\n\n/**\n * Computes R-squared (coefficient of determination)\n */\nexport function computeR2(actual: number[], expected: number[]): number {\n if (actual.length !== expected.length || actual.length === 0) {\n return 0;\n }\n\n // Calculate mean of expected values\n let meanExpected = 0;\n for (const val of expected) {\n meanExpected += val ?? 0;\n }\n meanExpected /= expected.length;\n\n // Calculate total sum of squares and residual sum of squares\n let ssTotal = 0;\n let ssResidual = 0;\n\n for (let i = 0; i < actual.length; i++) {\n const exp = expected[i] ?? 0;\n const act = actual[i] ?? 0;\n ssTotal += (exp - meanExpected) ** 2;\n ssResidual += (exp - act) ** 2;\n }\n\n // R² = 1 - (SS_res / SS_tot)\n if (ssTotal === 0) {\n return ssResidual === 0 ? 1 : 0;\n }\n\n return 1 - ssResidual / ssTotal;\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 => 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(values: number[], threshold: number): 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(values: number[], threshold: number): 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 { computeRegressionMetrics } from \"../statistics/regression.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((v) => v !== undefined && v !== null);\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(\n result.message,\n percentageThreshold,\n actualPercentage,\n this.fieldName\n );\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(\n result.message,\n percentageThreshold,\n actualPercentage,\n this.fieldName\n );\n }\n\n return this;\n }\n\n // ============================================================================\n // Regression Assertions\n // ============================================================================\n\n /**\n * Validates that ground truth exists and both arrays contain numeric values.\n * Returns the filtered numeric arrays for regression metrics.\n */\n private validateRegressionInputs(): { actual: number[]; expected: number[] } {\n this.validateGroundTruth();\n\n const numericActual = filterNumericValues(this.actualValues);\n const numericExpected = filterNumericValues(this.expectedValues);\n\n if (numericActual.length === 0) {\n throw new AssertionError(\n `Regression metric requires numeric values, but field \"${this.fieldName}\" has no numeric actual values.`,\n undefined,\n undefined,\n this.fieldName\n );\n }\n\n if (numericExpected.length === 0) {\n throw new AssertionError(\n `Regression metric requires numeric values, but field \"${this.fieldName}\" has no numeric expected values.`,\n undefined,\n undefined,\n this.fieldName\n );\n }\n\n if (numericActual.length !== numericExpected.length) {\n throw new AssertionError(\n `Regression metric requires equal-length arrays, but got ${numericActual.length} actual and ${numericExpected.length} expected values.`,\n numericExpected.length,\n numericActual.length,\n this.fieldName\n );\n }\n\n return { actual: numericActual, expected: numericExpected };\n }\n\n /**\n * Asserts that Mean Absolute Error is below a threshold.\n * Requires numeric values in both actual and expected.\n *\n * @param threshold - Maximum allowed MAE\n * @returns this for method chaining\n *\n * @example\n * expectStats(predictions, groundTruth)\n * .field(\"score\")\n * .toHaveMAEBelow(0.1)\n */\n toHaveMAEBelow(threshold: number): this {\n const { actual, expected } = this.validateRegressionInputs();\n const metrics = computeRegressionMetrics(actual, expected);\n const passed = metrics.mae <= threshold;\n\n const result: AssertionResult = {\n type: \"mae\",\n passed,\n message: passed\n ? `MAE ${metrics.mae.toFixed(4)} is below ${threshold}`\n : `MAE ${metrics.mae.toFixed(4)} exceeds threshold ${threshold}`,\n expected: threshold,\n actual: metrics.mae,\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.mae, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that Root Mean Squared Error is below a threshold.\n * Requires numeric values in both actual and expected.\n *\n * @param threshold - Maximum allowed RMSE\n * @returns this for method chaining\n *\n * @example\n * expectStats(predictions, groundTruth)\n * .field(\"score\")\n * .toHaveRMSEBelow(0.15)\n */\n toHaveRMSEBelow(threshold: number): this {\n const { actual, expected } = this.validateRegressionInputs();\n const metrics = computeRegressionMetrics(actual, expected);\n const passed = metrics.rmse <= threshold;\n\n const result: AssertionResult = {\n type: \"rmse\",\n passed,\n message: passed\n ? `RMSE ${metrics.rmse.toFixed(4)} is below ${threshold}`\n : `RMSE ${metrics.rmse.toFixed(4)} exceeds threshold ${threshold}`,\n expected: threshold,\n actual: metrics.rmse,\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.rmse, this.fieldName);\n }\n\n return this;\n }\n\n /**\n * Asserts that R-squared (coefficient of determination) is above a threshold.\n * R² measures how well the predictions explain the variance in expected values.\n * R² = 1.0 means perfect prediction, R² = 0 means prediction is no better than mean.\n * Requires numeric values in both actual and expected.\n *\n * @param threshold - Minimum required R² value (0-1)\n * @returns this for method chaining\n *\n * @example\n * expectStats(predictions, groundTruth)\n * .field(\"score\")\n * .toHaveR2Above(0.8)\n */\n toHaveR2Above(threshold: number): this {\n const { actual, expected } = this.validateRegressionInputs();\n const metrics = computeRegressionMetrics(actual, expected);\n const passed = metrics.r2 >= threshold;\n\n const result: AssertionResult = {\n type: \"r2\",\n passed,\n message: passed\n ? `R² ${metrics.r2.toFixed(4)} is above ${threshold}`\n : `R² ${metrics.r2.toFixed(4)} is below threshold ${threshold}`,\n expected: threshold,\n actual: metrics.r2,\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.r2, 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 * Options for expectStats when using two-argument form\n */\nexport interface ExpectStatsOptions {\n /**\n * Field to use as ID for alignment (default: \"id\")\n * Also checks \"_id\" as fallback for expected records.\n */\n idField?: string;\n\n /**\n * Whether to throw on missing IDs (default: false)\n * When true, throws if any prediction has no matching expected record.\n */\n strict?: boolean;\n}\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(\n \"Invalid input to expectStats(): expected ModelRunResult, Prediction[], or AlignedRecord[]\"\n );\n}\n\n/**\n * Entry point for statistical assertions.\n *\n * Supports multiple usage patterns:\n * 1. Single argument: predictions without ground truth (for distribution assertions)\n * 2. Two arguments: predictions with ground truth (for classification/regression metrics)\n * 3. Three arguments: predictions with ground truth and options (for custom ID field)\n *\n * @param inputOrActual - Either StatsInput (one-arg) or Prediction[] (two/three-arg)\n * @param expected - Ground truth data (optional, only for two/three-arg usage)\n * @param options - Alignment options (optional, only for three-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 2: Classification with ground truth\n * expectStats(judgeOutputs, humanLabels)\n * .field(\"hallucinated\")\n * .toHaveRecallAbove(true, 0.85)\n * .toHavePrecisionAbove(true, 0.8);\n *\n * @example\n * // Pattern 3: Custom ID field\n * expectStats(predictions, groundTruth, { idField: 'uuid' })\n * .field(\"score\")\n * .toHaveAccuracyAbove(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 actual: Prediction[],\n expected: Array<Record<string, unknown>>,\n options: ExpectStatsOptions\n): ExpectStats;\nexport function expectStats(\n inputOrActual: StatsInput | Prediction[],\n expected?: Array<Record<string, unknown>>,\n options?: ExpectStatsOptions\n): ExpectStats {\n // Two or three argument case: align predictions with ground truth\n if (expected !== undefined) {\n if (!Array.isArray(inputOrActual)) {\n throw new Error(\"When using two-argument expectStats(), first argument must be Prediction[]\");\n }\n const alignOptions = options ? { idField: options.idField, strict: options.strict } : undefined;\n const aligned = alignByKey(inputOrActual as Prediction[], expected, alignOptions);\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"]}
|
|
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/regression.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('Dataset records must have an \"id\" or \"_id\" field for alignment');\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(`Prediction ID mismatch: expected \"${id}\", got \"${prediction.id}\".`);\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 in both arrays (default: \"id\") - legacy option */\n idField?: string;\n /** Field to use as ID in predictions array (default: \"id\") */\n predictionIdField?: string;\n /** Field to use as ID in expected/ground truth array (default: \"id\") */\n expectedIdField?: 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, predictionIdField, expectedIdField } = options;\n\n // Determine which fields to use for IDs\n // Priority: specific field options > legacy idField > default \"id\"\n const predIdField = predictionIdField ?? idField ?? \"id\";\n const expIdField = expectedIdField ?? idField ?? \"id\";\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[expIdField] ?? record._id);\n if (!id || id === \"undefined\") {\n throw new IntegrityError(\n `Expected record missing ${expIdField} field: ${JSON.stringify(record)}`\n );\n }\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 = String((prediction as Record<string, unknown>)[predIdField]);\n if (!id || id === \"undefined\") {\n throw new IntegrityError(\n `Prediction missing ${predIdField} field: ${JSON.stringify(prediction)}`\n );\n }\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(aligned: AlignedRecord[], field: string): 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((field) => record[field] === undefined);\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 = missingIds.length === 0 && duplicateIds.length === 0 && 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(\n `${duplicateIds.length} duplicate ID(s): ${duplicateIds.slice(0, 3).join(\", \")}${duplicateIds.length > 3 ? \"...\" : \"\"}`\n );\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.map((p) => p.id).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: classCount > 0 ? Object.values(perClass).reduce((sum, m) => sum + m.f1, 0) / classCount : 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(\n actual: unknown[],\n expected: unknown[],\n targetClass: string\n): 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 * Regression metrics computation\n */\n\nimport type { RegressionMetrics } from \"../core/types.js\";\n\n/**\n * Computes all regression metrics from actual and expected values\n */\nexport function computeRegressionMetrics(actual: number[], expected: number[]): RegressionMetrics {\n if (actual.length !== expected.length) {\n throw new Error(\n `Array length mismatch: actual has ${actual.length} elements, expected has ${expected.length}`\n );\n }\n\n const n = actual.length;\n if (n === 0) {\n return { mae: 0, mse: 0, rmse: 0, r2: 0 };\n }\n\n const mae = computeMAE(actual, expected);\n const mse = computeMSE(actual, expected);\n const rmse = Math.sqrt(mse);\n const r2 = computeR2(actual, expected);\n\n return { mae, mse, rmse, r2 };\n}\n\n/**\n * Computes Mean Absolute Error\n */\nexport function computeMAE(actual: number[], expected: number[]): number {\n if (actual.length !== expected.length || actual.length === 0) {\n return 0;\n }\n\n let sum = 0;\n for (let i = 0; i < actual.length; i++) {\n sum += Math.abs((actual[i] ?? 0) - (expected[i] ?? 0));\n }\n\n return sum / actual.length;\n}\n\n/**\n * Computes Mean Squared Error\n */\nexport function computeMSE(actual: number[], expected: number[]): number {\n if (actual.length !== expected.length || actual.length === 0) {\n return 0;\n }\n\n let sum = 0;\n for (let i = 0; i < actual.length; i++) {\n const diff = (actual[i] ?? 0) - (expected[i] ?? 0);\n sum += diff * diff;\n }\n\n return sum / actual.length;\n}\n\n/**\n * Computes Root Mean Squared Error\n */\nexport function computeRMSE(actual: number[], expected: number[]): number {\n return Math.sqrt(computeMSE(actual, expected));\n}\n\n/**\n * Computes R-squared (coefficient of determination)\n */\nexport function computeR2(actual: number[], expected: number[]): number {\n if (actual.length !== expected.length || actual.length === 0) {\n return 0;\n }\n\n // Calculate mean of expected values\n let meanExpected = 0;\n for (const val of expected) {\n meanExpected += val ?? 0;\n }\n meanExpected /= expected.length;\n\n // Calculate total sum of squares and residual sum of squares\n let ssTotal = 0;\n let ssResidual = 0;\n\n for (let i = 0; i < actual.length; i++) {\n const exp = expected[i] ?? 0;\n const act = actual[i] ?? 0;\n ssTotal += (exp - meanExpected) ** 2;\n ssResidual += (exp - act) ** 2;\n }\n\n // R² = 1 - (SS_res / SS_tot)\n if (ssTotal === 0) {\n return ssResidual === 0 ? 1 : 0;\n }\n\n return 1 - ssResidual / ssTotal;\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 => 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(values: number[], threshold: number): 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(values: number[], threshold: number): 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 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 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 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 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 { computeRegressionMetrics } from \"../statistics/regression.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((v) => v !== undefined && v !== null);\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 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 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 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 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 assertion\n this.assertions.push(result);\n recordAssertion(result);\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 assertion\n this.assertions.push(result);\n recordAssertion(result);\n\n return this;\n }\n\n // ============================================================================\n // Regression Assertions\n // ============================================================================\n\n /**\n * Validates that ground truth exists and both arrays contain numeric values.\n * Returns the filtered numeric arrays for regression metrics.\n */\n private validateRegressionInputs(): { actual: number[]; expected: number[] } {\n this.validateGroundTruth();\n\n const numericActual = filterNumericValues(this.actualValues);\n const numericExpected = filterNumericValues(this.expectedValues);\n\n if (numericActual.length === 0) {\n throw new AssertionError(\n `Regression metric requires numeric values, but field \"${this.fieldName}\" has no numeric actual values.`,\n undefined,\n undefined,\n this.fieldName\n );\n }\n\n if (numericExpected.length === 0) {\n throw new AssertionError(\n `Regression metric requires numeric values, but field \"${this.fieldName}\" has no numeric expected values.`,\n undefined,\n undefined,\n this.fieldName\n );\n }\n\n if (numericActual.length !== numericExpected.length) {\n throw new AssertionError(\n `Regression metric requires equal-length arrays, but got ${numericActual.length} actual and ${numericExpected.length} expected values.`,\n numericExpected.length,\n numericActual.length,\n this.fieldName\n );\n }\n\n return { actual: numericActual, expected: numericExpected };\n }\n\n /**\n * Asserts that Mean Absolute Error is below a threshold.\n * Requires numeric values in both actual and expected.\n *\n * @param threshold - Maximum allowed MAE\n * @returns this for method chaining\n *\n * @example\n * expectStats(predictions, groundTruth)\n * .field(\"score\")\n * .toHaveMAEBelow(0.1)\n */\n toHaveMAEBelow(threshold: number): this {\n const { actual, expected } = this.validateRegressionInputs();\n const metrics = computeRegressionMetrics(actual, expected);\n const passed = metrics.mae <= threshold;\n\n const result: AssertionResult = {\n type: \"mae\",\n passed,\n message: passed\n ? `MAE ${metrics.mae.toFixed(4)} is below ${threshold}`\n : `MAE ${metrics.mae.toFixed(4)} exceeds threshold ${threshold}`,\n expected: threshold,\n actual: metrics.mae,\n field: this.fieldName,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n return this;\n }\n\n /**\n * Asserts that Root Mean Squared Error is below a threshold.\n * Requires numeric values in both actual and expected.\n *\n * @param threshold - Maximum allowed RMSE\n * @returns this for method chaining\n *\n * @example\n * expectStats(predictions, groundTruth)\n * .field(\"score\")\n * .toHaveRMSEBelow(0.15)\n */\n toHaveRMSEBelow(threshold: number): this {\n const { actual, expected } = this.validateRegressionInputs();\n const metrics = computeRegressionMetrics(actual, expected);\n const passed = metrics.rmse <= threshold;\n\n const result: AssertionResult = {\n type: \"rmse\",\n passed,\n message: passed\n ? `RMSE ${metrics.rmse.toFixed(4)} is below ${threshold}`\n : `RMSE ${metrics.rmse.toFixed(4)} exceeds threshold ${threshold}`,\n expected: threshold,\n actual: metrics.rmse,\n field: this.fieldName,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\n\n return this;\n }\n\n /**\n * Asserts that R-squared (coefficient of determination) is above a threshold.\n * R² measures how well the predictions explain the variance in expected values.\n * R² = 1.0 means perfect prediction, R² = 0 means prediction is no better than mean.\n * Requires numeric values in both actual and expected.\n *\n * @param threshold - Minimum required R² value (0-1)\n * @returns this for method chaining\n *\n * @example\n * expectStats(predictions, groundTruth)\n * .field(\"score\")\n * .toHaveR2Above(0.8)\n */\n toHaveR2Above(threshold: number): this {\n const { actual, expected } = this.validateRegressionInputs();\n const metrics = computeRegressionMetrics(actual, expected);\n const passed = metrics.r2 >= threshold;\n\n const result: AssertionResult = {\n type: \"r2\",\n passed,\n message: passed\n ? `R² ${metrics.r2.toFixed(4)} is above ${threshold}`\n : `R² ${metrics.r2.toFixed(4)} is below threshold ${threshold}`,\n expected: threshold,\n actual: metrics.r2,\n field: this.fieldName,\n };\n\n this.assertions.push(result);\n recordAssertion(result);\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 * Options for expectStats when using two-argument form\n */\nexport interface ExpectStatsOptions {\n /**\n * Field to use as ID in both arrays (default: \"id\") - legacy option\n * Also checks \"_id\" as fallback for expected records.\n */\n idField?: string;\n\n /**\n * Field to use as ID in predictions array (default: \"id\")\n */\n predictionIdField?: string;\n\n /**\n * Field to use as ID in expected/ground truth array (default: \"id\")\n */\n expectedIdField?: string;\n\n /**\n * Whether to throw on missing IDs (default: false)\n * When true, throws if any prediction has no matching expected record.\n */\n strict?: boolean;\n}\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(\n \"Invalid input to expectStats(): expected ModelRunResult, Prediction[], or AlignedRecord[]\"\n );\n}\n\n/**\n * Entry point for statistical assertions.\n *\n * Supports multiple usage patterns:\n * 1. Single argument: predictions without ground truth (for distribution assertions)\n * 2. Two arguments: predictions with ground truth (for classification/regression metrics)\n * 3. Three arguments: predictions with ground truth and options (for custom ID field)\n *\n * @param inputOrActual - Either StatsInput (one-arg) or Prediction[] (two/three-arg)\n * @param expected - Ground truth data (optional, only for two/three-arg usage)\n * @param options - Alignment options (optional, only for three-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 2: Classification with ground truth\n * expectStats(judgeOutputs, humanLabels)\n * .field(\"hallucinated\")\n * .toHaveRecallAbove(true, 0.85)\n * .toHavePrecisionAbove(true, 0.8);\n *\n * @example\n * // Pattern 3: Custom ID field\n * expectStats(predictions, groundTruth, { idField: 'uuid' })\n * .field(\"score\")\n * .toHaveAccuracyAbove(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 actual: Prediction[],\n expected: Array<Record<string, unknown>>,\n options: ExpectStatsOptions\n): ExpectStats;\nexport function expectStats(\n inputOrActual: StatsInput | Prediction[],\n expected?: Array<Record<string, unknown>>,\n options?: ExpectStatsOptions\n): ExpectStats {\n // Two or three argument case: align predictions with ground truth\n if (expected !== undefined) {\n if (!Array.isArray(inputOrActual)) {\n throw new Error(\"When using two-argument expectStats(), first argument must be Prediction[]\");\n }\n const alignOptions = options\n ? {\n idField: options.idField,\n predictionIdField: options.predictionIdField,\n expectedIdField: options.expectedIdField,\n strict: options.strict,\n }\n : undefined;\n const aligned = alignByKey(inputOrActual as Prediction[], expected, alignOptions);\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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -143,8 +143,12 @@ declare function runModelParallel<T extends Record<string, unknown>>(dataset: Da
|
|
|
143
143
|
interface AlignOptions {
|
|
144
144
|
/** Whether to throw on missing IDs (default: false) */
|
|
145
145
|
strict?: boolean;
|
|
146
|
-
/** Field to use as ID (default: "id") */
|
|
146
|
+
/** Field to use as ID in both arrays (default: "id") - legacy option */
|
|
147
147
|
idField?: string;
|
|
148
|
+
/** Field to use as ID in predictions array (default: "id") */
|
|
149
|
+
predictionIdField?: string;
|
|
150
|
+
/** Field to use as ID in expected/ground truth array (default: "id") */
|
|
151
|
+
expectedIdField?: string;
|
|
148
152
|
}
|
|
149
153
|
/**
|
|
150
154
|
* Aligns predictions with expected values by ID
|
|
@@ -390,10 +394,18 @@ type StatsInput = ModelRunResult | Prediction[] | AlignedRecord[];
|
|
|
390
394
|
*/
|
|
391
395
|
interface ExpectStatsOptions {
|
|
392
396
|
/**
|
|
393
|
-
* Field to use as ID
|
|
397
|
+
* Field to use as ID in both arrays (default: "id") - legacy option
|
|
394
398
|
* Also checks "_id" as fallback for expected records.
|
|
395
399
|
*/
|
|
396
400
|
idField?: string;
|
|
401
|
+
/**
|
|
402
|
+
* Field to use as ID in predictions array (default: "id")
|
|
403
|
+
*/
|
|
404
|
+
predictionIdField?: string;
|
|
405
|
+
/**
|
|
406
|
+
* Field to use as ID in expected/ground truth array (default: "id")
|
|
407
|
+
*/
|
|
408
|
+
expectedIdField?: string;
|
|
397
409
|
/**
|
|
398
410
|
* Whether to throw on missing IDs (default: false)
|
|
399
411
|
* When true, throws if any prediction has no matching expected record.
|
|
@@ -590,6 +602,10 @@ declare class ConsoleReporter {
|
|
|
590
602
|
* Applies color if enabled
|
|
591
603
|
*/
|
|
592
604
|
private color;
|
|
605
|
+
/**
|
|
606
|
+
* Formats a value for display
|
|
607
|
+
*/
|
|
608
|
+
private formatValue;
|
|
593
609
|
/**
|
|
594
610
|
* Logs a line
|
|
595
611
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -143,8 +143,12 @@ declare function runModelParallel<T extends Record<string, unknown>>(dataset: Da
|
|
|
143
143
|
interface AlignOptions {
|
|
144
144
|
/** Whether to throw on missing IDs (default: false) */
|
|
145
145
|
strict?: boolean;
|
|
146
|
-
/** Field to use as ID (default: "id") */
|
|
146
|
+
/** Field to use as ID in both arrays (default: "id") - legacy option */
|
|
147
147
|
idField?: string;
|
|
148
|
+
/** Field to use as ID in predictions array (default: "id") */
|
|
149
|
+
predictionIdField?: string;
|
|
150
|
+
/** Field to use as ID in expected/ground truth array (default: "id") */
|
|
151
|
+
expectedIdField?: string;
|
|
148
152
|
}
|
|
149
153
|
/**
|
|
150
154
|
* Aligns predictions with expected values by ID
|
|
@@ -390,10 +394,18 @@ type StatsInput = ModelRunResult | Prediction[] | AlignedRecord[];
|
|
|
390
394
|
*/
|
|
391
395
|
interface ExpectStatsOptions {
|
|
392
396
|
/**
|
|
393
|
-
* Field to use as ID
|
|
397
|
+
* Field to use as ID in both arrays (default: "id") - legacy option
|
|
394
398
|
* Also checks "_id" as fallback for expected records.
|
|
395
399
|
*/
|
|
396
400
|
idField?: string;
|
|
401
|
+
/**
|
|
402
|
+
* Field to use as ID in predictions array (default: "id")
|
|
403
|
+
*/
|
|
404
|
+
predictionIdField?: string;
|
|
405
|
+
/**
|
|
406
|
+
* Field to use as ID in expected/ground truth array (default: "id")
|
|
407
|
+
*/
|
|
408
|
+
expectedIdField?: string;
|
|
397
409
|
/**
|
|
398
410
|
* Whether to throw on missing IDs (default: false)
|
|
399
411
|
* When true, throws if any prediction has no matching expected record.
|
|
@@ -590,6 +602,10 @@ declare class ConsoleReporter {
|
|
|
590
602
|
* Applies color if enabled
|
|
591
603
|
*/
|
|
592
604
|
private color;
|
|
605
|
+
/**
|
|
606
|
+
* Formats a value for display
|
|
607
|
+
*/
|
|
608
|
+
private formatValue;
|
|
593
609
|
/**
|
|
594
610
|
* Logs a line
|
|
595
611
|
*/
|