'use strict'; /** * The forward adjudication of a bet made against the measurement. * * We serve the map that scored WORSE in-window, on an argument the sample * cannot test. These lock the rule that decides whether that argument survives — * written before any forward date exists, so the bar cannot drift toward * whichever answer arrives. */ const duel = require('../../src/services/model/calibrationDuel'); /** Forward rows where `edge` favours the shadow when positive. */ function rows(dates, perDate, edge, seed = 2) { let s = seed; const rnd = () => (s = (s * 1103515245 + 12345) % 2147483648) / 2147483648; const out = []; for (let d = 0; d < dates; d += 1) { for (let i = 0; i < perDate; i += 1) { const won = rnd() < 0.6 ? 1 : 0; const err = 0.25 + rnd() * 0.1; out.push({ date: `2026-09-${String(d + 1).padStart(2, '0')}`, fitted_through: '2026-08-31', won, served: won ? 1 - err : err, shadow: won ? 1 - err + edge : err - edge, }); } } return out; } describe('the rule is pre-registered and cannot be met early', () => { it('is PENDING below the forward-date bar, whatever the numbers say', () => { // Even with the shadow winning decisively, 5 dates is not a verdict. const v = duel.adjudicate(rows(5, 40, 0.15)); expect(v.verdict).toBe('PENDING'); expect(v.dates_needed).toBe(duel.MIN_FORWARD_DATES - 5); expect(v.action).toMatch(/keep serving/); }); it('REFUTES the bet when isotonic wins out-of-window at the bar', () => { const v = duel.adjudicate(rows(12, 40, 0.15)); expect(v.verdict).toBe('REFUTED'); expect(v.ci[1]).toBeLessThan(0); expect(v.action).toMatch(/REVERT/); }); it('UPHOLDS the bet when the served map is not beaten', () => { const v = duel.adjudicate(rows(12, 40, -0.15)); expect(v.verdict).toBe('UPHELD'); expect(v.action).toMatch(/keep serving/); }); it('UPHOLDS on a tie — the burden is on refutation, not on us', () => { const v = duel.adjudicate(rows(12, 40, 0)); expect(v.verdict).toBe('UPHELD'); }); }); describe('only genuinely out-of-window dates count', () => { it('drops rows inside the fit window — that would score memorisation', () => { const inWindow = rows(12, 40, 0.15).map((r) => ({ ...r, fitted_through: '2026-12-31' })); const v = duel.adjudicate(inWindow); expect(v.verdict).toBe('PENDING'); expect(v.forward_dates).toBe(0); }); it('drops rows with no fit provenance rather than assuming they are forward', () => { const noProv = rows(12, 40, 0.15).map(({ fitted_through, ...r }) => r); expect(duel.adjudicate(noProv).forward_dates).toBe(0); }); it('drops rows missing either map — a duel needs both entrants', () => { const half = rows(12, 40, 0.15).map((r) => ({ ...r, shadow: null })); expect(duel.adjudicate(half).forward_dates).toBe(0); }); });