'use strict'; /** * B1 — the dCLV close leg reads PRICED captures only. * * THE TEST THE TWIN NEVER HAD. `attachClosingProb` got a `missed_reason` filter * during the CLV instrument repair and a comment explaining why; * `computeDirectionalForRow` did not, and nothing tested it, so the defect * survived while its sibling was fixed a foot away. * * The mechanism: `closing_captures` records a refusal for every prop x book x * side on every ~20-minute cycle AFTER first pitch, so a refusal ALWAYS carries * a later `captured_at` than the last real price. `latest-first` without a * filter therefore returns a refusal every time — measured 26,448 of 26,448 * identity groups — and `computeDirectionalClv` refuses on a `missedReason`. */ const ledgerService = require('../../src/services/ledgerService'); /** * A fake client that records the filters applied to `closing_captures` and * serves rows honouring them, so an unapplied filter fails the test. */ function fakeSb({ snaps, closes }) { const seen = { closing: null }; return { seen, from(table) { const st = { table, is: {}, notNull: [], order: null, asc: true }; const q = { select() { return q; }, eq() { return q; }, is(col, val) { st.is[col] = val; return q; }, not(col, op, val) { if (op === 'is' && val === null) st.notNull.push(col); return q; }, order(col, o) { st.order = col; st.asc = !o || o.ascending !== false; return q; }, limit(n) { if (table === 'model_snapshots') { const rows = [...snaps].sort((a, b) => (st.asc ? 1 : -1) * String(a.captured_at).localeCompare(String(b.captured_at))); return Promise.resolve({ data: rows.slice(0, n) }); } seen.closing = { ...st }; let rows = [...closes]; // Honour the filters the production select applies. if ('missed_reason' in st.is && st.is.missed_reason === null) rows = rows.filter((r) => r.missed_reason == null); for (const c of st.notNull) rows = rows.filter((r) => r[c] != null); rows.sort((a, b) => (st.asc ? 1 : -1) * String(a.captured_at).localeCompare(String(b.captured_at))); return Promise.resolve({ data: rows.slice(0, n) }); }, }; return q; }, }; } const ROW = { player_key: 'luis arraez', stat: 'total_bases', side: 'over', game_date: '2026-08-10' }; // The lock: both side prices, so it is de-viggable. const SNAPS = [{ fair_prob: 0.52, over_odds: -110, under_odds: -110, captured_at: '2026-08-10T14:00:00Z' }]; // The production shape: a real price, then refusals stamped after first pitch. const CLOSES = [ { over_odds: -140, under_odds: 120, missed_reason: null, captured_at: '2026-08-10T23:41:20Z' }, { over_odds: null, under_odds: null, missed_reason: 'missed_window', captured_at: '2026-08-11T01:21:09Z' }, { over_odds: null, under_odds: null, missed_reason: 'missed_window', captured_at: '2026-08-11T03:21:09Z' }, ]; const compute = ledgerService.__internals ? ledgerService.__internals.computeDirectionalForRow : null; describe('the close leg selects the latest PRICED capture', () => { it('applies the missed_reason filter (the fix)', async () => { const sb = fakeSb({ snaps: SNAPS, closes: CLOSES }); await ledgerService.__internals.computeDirectionalForRow(sb, 'mlb', ROW); expect(sb.seen.closing.is).toHaveProperty('missed_reason', null); }); it('requires BOTH side prices, matching its sibling', async () => { const sb = fakeSb({ snaps: SNAPS, closes: CLOSES }); await ledgerService.__internals.computeDirectionalForRow(sb, 'mlb', ROW); expect(sb.seen.closing.notNull).toEqual(expect.arrayContaining(['over_odds', 'under_odds'])); }); it('still takes the LATEST of the priced rows, not the earliest', async () => { const twoPriced = [ { over_odds: -200, under_odds: 170, missed_reason: null, captured_at: '2026-08-10T18:00:00Z' }, ...CLOSES, ]; const sb = fakeSb({ snaps: SNAPS, closes: twoPriced }); const out = await ledgerService.__internals.computeDirectionalForRow(sb, 'mlb', ROW); // -140/120 (23:41) not -200/170 (18:00): the later price wins. expect(sb.seen.closing.asc).toBe(false); expect(out.state).not.toBe('unknown'); }); it('RETURNS A REAL STATE where the unfiltered read returned unknown', async () => { const sb = fakeSb({ snaps: SNAPS, closes: CLOSES }); const out = await ledgerService.__internals.computeDirectionalForRow(sb, 'mlb', ROW); expect(['positive', 'negative', 'flat']).toContain(out.state); expect(out.clv).not.toBeNull(); expect(out.fair_close).not.toBeNull(); }); it('THE REGRESSION: an unfiltered read would have returned unknown on this data', async () => { // Proves the fixture actually exercises the bug — a test that passes on data // where the old code also worked proves nothing. const dclv = require('../../src/services/directionalClv'); const latestUnfiltered = [...CLOSES].sort((a, b) => String(b.captured_at).localeCompare(String(a.captured_at)))[0]; const old = dclv.computeDirectionalClv({ side: ROW.side, lockFairProb: 0.52, closeOverOdds: latestUnfiltered.over_odds, closeUnderOdds: latestUnfiltered.under_odds, missedReason: latestUnfiltered.missed_reason, }); expect(old.state).toBe('unknown'); expect(old.reason).toBe('missed_window'); }); it('a genuinely closeless identity is STILL unknown — absence is preserved', async () => { const onlyRefusals = CLOSES.filter((c) => c.missed_reason); const sb = fakeSb({ snaps: SNAPS, closes: onlyRefusals }); const out = await ledgerService.__internals.computeDirectionalForRow(sb, 'mlb', ROW); expect(out.state).toBe('unknown'); expect(out.reason).toBe('no_usable_close'); }); it('no retained lock => null, never a fabricated comparison', async () => { const sb = fakeSb({ snaps: [], closes: CLOSES }); expect(await ledgerService.__internals.computeDirectionalForRow(sb, 'mlb', ROW)).toBeNull(); }); }); describe('the two selects agree (the twin is no longer a twin)', () => { const src = require('fs').readFileSync( require('path').join(__dirname, '..', '..', 'src/services/ledgerService.js'), 'utf8'); it('BOTH closing_captures reads filter missed_reason', () => { const reads = src.split("from('closing_captures')").slice(1); expect(reads.length).toBeGreaterThanOrEqual(2); for (const r of reads) { const head = r.slice(0, 500); expect(head).toMatch(/\.is\('missed_reason', null\)/); } }); });