'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); }); });