'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const { validateResults, stablePairOrder, isLowBit, formatMetric, promptFor, fixturesFrom, routingFrame } = require('../experiments/lab.js'); function fixture() { const condition = id => ({ id, output: 'Captured answer', model: 'Flint', quant: id === 'a' ? 'Q4_1' : 'Q8_0' }); const base = key => ({ cases: [{ id: key + '-one', title: 'Test', prompt: 'A real test prompt', conditions: [condition('a'), condition('b')] }] }); const data = { schema_version: 1, provenance: { runner: 'test-fixture' }, experiments: Object.fromEntries(['reroute', 'quant', 'surgery', 'memory'].map(key => [key, base(key)])) }; data.experiments.memory.cases[0].choices = ['old', 'new']; return data; } test('accepts compatible results without modifying captured values', () => { const data = fixture(), original = JSON.stringify(data); assert.equal(validateResults(data), data); assert.equal(JSON.stringify(data), original); }); test('rejects missing or incomplete experiments instead of filling fake answers', () => { const data = fixture(); delete data.experiments.surgery; assert.throws(() => validateResults(data), /surgery/); const missing = fixture(); delete missing.experiments.quant.cases[0].conditions[0].output; assert.throws(() => validateResults(missing), /captured answer/); }); test('rejects duplicate case and condition identifiers', () => { const data = fixture(); data.experiments.quant.cases.push(structuredClone(data.experiments.quant.cases[0])); assert.throws(() => validateResults(data), /repeated case/); const other = fixture(); other.experiments.quant.cases[0].conditions[1].id = 'a'; assert.throws(() => validateResults(other), /condition ID/); }); test('blind ordering is stable, unbiased across IDs, and preserves source arrays', () => { const conditions = [{ id: 'a' }, { id: 'b' }], original = structuredClone(conditions); assert.deepEqual(stablePairOrder('case-x', conditions), stablePairOrder('case-x', conditions)); const first = new Set(Array.from({ length: 20 }, (_, i) => stablePairOrder('case-' + i, conditions)[0].id)); assert.equal(first.size, 2); assert.deepEqual(conditions, original); }); test('recognizes actual Q4 variants without classifying Q8 or 14-bit as Q4', () => { for (const quant of ['Q4_1', 'Q4_K_M', '4-bit']) assert.equal(isLowBit({ quant }), true); for (const quant of ['Q8_0', '14-bit', 'F16']) assert.equal(isLowBit({ quant }), false); }); test('routing frames enforce real expert bounds and weight correspondence', () => { const data = fixture(), condition = data.experiments.reroute.cases[0].conditions[0]; condition.routing = { layer: 3, expert_count: 256, tokens: [{ token: ' blue', experts: [0, 255], weights: [0.3, 0.7] }] }; validateResults(data); assert.equal(routingFrame(condition, 0).token, ' blue'); assert.equal(routingFrame(condition, 1), null); condition.routing.tokens[0].experts[1] = 256; assert.throws(() => validateResults(data), /expert index/); condition.routing.tokens[0].experts[1] = 255; condition.routing.tokens[0].weights = [1]; assert.throws(() => validateResults(data), /weights/); }); test('fixtures include condition-specific prompts and intervention controls', () => { const data = fixture(), item = data.experiments.surgery.cases[0]; item.intervention = { kind: 'activation_ablation', description: 'Zero one block output' }; item.prompts = [{ id: 'control', text: 'Control prompt' }]; item.conditions[0].prompt_id = 'control'; item.conditions[1].prompt = 'Changed prompt'; assert.equal(promptFor(item, item.conditions[0]), 'Control prompt'); const out = fixturesFrom(data); assert.equal(out.experiments.surgery.cases[0].conditions[1].prompt, 'Changed prompt'); assert.deepEqual(out.experiments.surgery.cases[0].intervention, item.intervention); assert.equal(out.experiments.surgery.cases[0].conditions[0].output, undefined); }); test('formats measurements without adding invented units or percentages', () => { assert.equal(formatMetric(0.25), '0.25'); assert.equal(formatMetric(false), 'No'); assert.equal(formatMetric(1024), '1,024'); });