'use strict'; /** * Which stats may serve a calibrated number. * * The thing these protect is the meaning of PROVISIONAL: a provisional deploy * that cannot be taken away is just a deploy. */ const { createRegistry, STATUS, PROMOTION_DATE_CLUSTERS } = require('../../src/services/model/calibrationRegistry'); const MAP = [{ lo: 0.5, hi: 0.7, value: 0.55, n: 300 }]; const GOOD = { lodo_pass: true, ci: [-0.0061, -0.0045], map: MAP, certified_bands: [[0.6, 0.8]], date_clusters: 7, at: '2026-08-06' }; describe('deploy needs BOTH gates', () => { it('deploys when LODO passes and the interval excludes zero', () => { const r = createRegistry(); expect(r.deploy('total_bases', GOOD).status).toBe(STATUS.PROVISIONAL); }); it('refuses on a LODO failure however good the interval', () => { const r = createRegistry(); const out = r.deploy('runs', { ...GOOD, lodo_pass: false }); expect(out.ok).toBe(false); expect(out.reason).toMatch(/date-driven/); }); it('refuses when the interval spans zero however clean the LODO', () => { const r = createRegistry(); const out = r.deploy('hits', { ...GOOD, ci: [-0.01, 0.002] }); expect(out.ok).toBe(false); expect(out.reason).toMatch(/does not exclude zero/); }); it('refuses without a map — there is nothing to serve', () => { const r = createRegistry(); expect(r.deploy('hits', { ...GOOD, map: null }).ok).toBe(false); }); }); describe('auto-demotion is what makes provisional honest', () => { it('demotes on the first date where the interval stops excluding zero', () => { const r = createRegistry(); r.deploy('total_bases', GOOD); const out = r.reverify('total_bases', { ci: [-0.004, 0.001], date: '2026-08-07' }); expect(out.status).toBe(STATUS.NONE); expect(out.reason).toBe('ci_no_longer_excludes_zero'); expect(out.breaking_date).toBe('2026-08-07'); expect(r.serves('total_bases', 0.65).serve).toBe(false); }); it('demotes when the favourite over-prediction flips sign', () => { // A flip means the correction is now pushing the wrong way. const r = createRegistry(); r.deploy('total_bases', GOOD); const out = r.reverify('total_bases', { ci: [-0.006, -0.004], favourite_bias: -0.03, date: '2026-08-08' }); expect(out.status).toBe(STATUS.NONE); expect(out.reason).toBe('favourite_bias_flipped'); }); it('logs the demotion with its breaking date', () => { const r = createRegistry(); r.deploy('total_bases', GOOD); r.reverify('total_bases', { ci: [0.001, 0.004], date: '2026-08-09' }); const ev = r.log().find((e) => e.event === 'auto_demoted'); expect(ev).toMatchObject({ stat: 'total_bases', at: '2026-08-09' }); }); it('stays deployed while both conditions hold', () => { const r = createRegistry(); r.deploy('total_bases', GOOD); const out = r.reverify('total_bases', { ci: [-0.007, -0.003], favourite_bias: 0.17, date: '2026-08-07' }); expect(out.status).toBe(STATUS.PROVISIONAL); expect(out.changed).toBe(false); }); }); describe('the >=40 date-cluster bar is the PROMOTION bar, not the deploy bar', () => { it('does not block deployment', () => { const r = createRegistry(); expect(r.deploy('total_bases', { ...GOOD, date_clusters: 7 }).ok).toBe(true); }); it('promotes out of provisional once it is met', () => { const r = createRegistry(); r.deploy('total_bases', GOOD); const out = r.reverify('total_bases', { ci: [-0.006, -0.004], date_clusters: PROMOTION_DATE_CLUSTERS, date: '2026-09-15' }); expect(out.status).toBe(STATUS.PROMOTED); }); it('does not promote while the interval has stopped holding', () => { const r = createRegistry(); r.deploy('total_bases', GOOD); const out = r.reverify('total_bases', { ci: [-0.001, 0.003], date_clusters: 60, date: '2026-09-15' }); expect(out.status).toBe(STATUS.NONE); }); }); describe('serving is band-limited', () => { it('serves inside the certified band and refuses outside it', () => { const r = createRegistry(); r.deploy('total_bases', GOOD); expect(r.serves('total_bases', 0.65).serve).toBe(true); expect(r.serves('total_bases', 0.65).provisional).toBe(true); expect(r.serves('total_bases', 0.95).serve).toBe(false); expect(r.serves('total_bases', 0.95).reason).toMatch(/outside the certified band/); }); it('an undeployed stat never serves', () => { const r = createRegistry(); expect(r.serves('hits', 0.6).serve).toBe(false); expect(r.serves('hits', 0.6).reason).toBe('not deployed'); }); it('a missing p_win serves nothing', () => { const r = createRegistry(); r.deploy('total_bases', GOOD); expect(r.serves('total_bases', null).serve).toBe(false); }); }); describe('the LODO held-row threshold is power-derived, not operator-chosen', () => { const { LODO_MIN_HELD_ROWS, LODO_THRESHOLD_BASIS } = require('../../src/services/model/calibrationRegistry'); it('is the value its own stated derivation produces', () => { // n* = (SD(d) / |effect|)^2 -- recomputed here so the constant cannot drift // away from the basis that justifies it. const { per_row_brier_diff_sd: sd, pooled_effect_abs_mean: eff } = LODO_THRESHOLD_BASIS; expect(Math.ceil((sd / eff) ** 2)).toBe(LODO_MIN_HELD_ROWS); }); it('carries its derivation basis, and was derived blind', () => { expect(LODO_THRESHOLD_BASIS.rule).toBe('n* = (SD(d) / |effect|)^2'); expect(LODO_THRESHOLD_BASIS.derived_blind).toBe(true); expect(LODO_THRESHOLD_BASIS.pooled_rows).toBeGreaterThan(1000); }); it('rejects the thresholds that were previously chosen by hand', () => { // 20 was the operator-chosen value whose verdict moved with it; anything // below n* cannot distinguish a reversal from a coin flip. for (const weak of [10, 20, 25, 30, 50]) { const se = LODO_THRESHOLD_BASIS.per_row_brier_diff_sd / Math.sqrt(weak); expect(LODO_THRESHOLD_BASIS.pooled_effect_abs_mean).toBeLessThan(se); expect(weak).toBeLessThan(LODO_MIN_HELD_ROWS); } }); it('is informative at the committed value', () => { const se = LODO_THRESHOLD_BASIS.per_row_brier_diff_sd / Math.sqrt(LODO_MIN_HELD_ROWS); expect(LODO_THRESHOLD_BASIS.pooled_effect_abs_mean).toBeGreaterThanOrEqual(se * 0.99); }); });