'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 test is a COHERENT pair, not a bar plus an unrelated rule', () => { const { LODO_K, LODO_TEST, LODO_POWER_FLOOR } = require('../../src/services/model/calibrationRegistry'); const normCdf = (z) => { const t = 1 / (1 + 0.2316419 * Math.abs(z)); const d = 0.3989422804014327 * Math.exp(-z * z / 2); const p = d * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429)))); return z >= 0 ? 1 - p : p; }; const binomPmf = (n, k, p) => { let logC = 0; for (let i = 0; i < k; i += 1) logC += Math.log(n - i) - Math.log(i + 1); return Math.exp(logC + k * Math.log(p) + (n - k) * Math.log(1 - p)); }; const tail = (n, c, p) => { let s = 0; for (let k = c + 1; k <= n; k += 1) s += binomPmf(n, k, p); return s; }; it('each n* is what its own (sigma_row, g) produce — no pooled value', () => { for (const [stat, t] of Object.entries(LODO_TEST)) { expect(Math.ceil(LODO_K ** 2 * (t.sigma_row / Math.abs(t.g)) ** 2)).toBe(t.n_star); } // And the four differ, which is exactly why one pooled number mis-credited them. const stars = Object.values(LODO_TEST).map((t) => t.n_star); expect(new Set(stars).size).toBeGreaterThan(1); }); it('each cutoff is the smallest one holding the false-positive rate at 0.05', () => { const p = normCdf(-LODO_K); for (const [stat, t] of Object.entries(LODO_TEST)) { expect(tail(t.informative_drops, t.cutoff, p)).toBeLessThanOrEqual(0.05); if (t.cutoff > 0) expect(tail(t.informative_drops, t.cutoff - 1, p)).toBeGreaterThan(0.05); expect(t.fp).toBeCloseTo(tail(t.informative_drops, t.cutoff, p), 3); } }); it('the OLD rule is demonstrably incoherent — it failed stable stats ~half the time', () => { // Zero-reversal rule at a 1-SE bar, on four informative drops. const pNoise = normCdf(-1); const falseFail = 1 - (1 - pNoise) ** 4; expect(falseFail).toBeGreaterThan(0.45); expect(falseFail).toBeLessThan(0.55); }); it('every stat falls below the power floor, so none may claim LODO stability', () => { // A gate that cannot fail is not a gate. This is the honest state at this // date count, and the floor makes it structural rather than a footnote. for (const [stat, t] of Object.entries(LODO_TEST)) { expect(t.power).toBeLessThan(LODO_POWER_FLOOR); } }); it('the stale pooled threshold is nulled so nothing can read it', () => { const { LODO_MIN_HELD_ROWS } = require('../../src/services/model/calibrationRegistry'); expect(LODO_MIN_HELD_ROWS).toBeNull(); }); });