Session 61 (pre-merge): live-verification fixes from day-one rows

1. [settlement] armed boot line — settlement WAS scheduled (the tick runs
   settleAllOutcomes + settleAllLedgers FIRST at every snapshot slot,
   src/snapshotScheduler.js) but was invisible at boot. Now verifiable
   from logs forever.
2. Null locked_odds root cause (4 day-one rows, all betmgm SB unders):
   genuinely absent in the DB — the first-seen book row carried no juice
   for that side. indexOdds/indexProps now PREFER a book row with both
   sides priced (still a real row, never synthesized). Display was
   correct: absent beats wrong.
3. Verified retry-safe: 'Odds data temporarily unavailable' is the
   odds-api quota gate (oddsService:423) — thrown BEFORE any spend or
   cache write; runSnapshot errors write nothing; the next cron retries
   fresh with PropLine first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kev
2026-07-11 10:16:27 -04:00
parent 7a35c96781
commit 4d2b27d1d0
4 changed files with 37 additions and 4 deletions
+19
View File
@@ -252,3 +252,22 @@ describe('getModelAggregate — per-tier calibration (n≥20 per tier)', () => {
expect(agg.by_tier.B.hit_pct).toBeNull(); // under 20 → building
});
});
// Session 61 — the odds index prefers a fully-priced book row (the null
// locked_odds rows from day one: first-seen betmgm SB unders had no juice
// while another book priced both sides).
describe('indexProps — prefers a book row with both sides priced', () => {
const { indexProps } = ledger.__internals;
test('a later both-sided row replaces a one-sided first row', () => {
const oneSided = { player: 'A Guy', stat_type: 'stolen_bases', line: 0.5, book: 'betmgm', over_odds: 120, under_odds: null };
const bothSided = { player: 'A Guy', stat_type: 'stolen_bases', line: 0.5, book: 'fanduel', over_odds: 130, under_odds: -170 };
const idx = indexProps([oneSided, bothSided]);
expect(idx['a guy|stolen_bases'].book).toBe('fanduel');
});
test('a both-sided first row is never displaced', () => {
const bothSided = { player: 'A Guy', stat_type: 'hits', line: 1.5, book: 'fanduel', over_odds: -110, under_odds: -110 };
const oneSided = { player: 'A Guy', stat_type: 'hits', line: 1.5, book: 'betmgm', over_odds: -115, under_odds: null };
const idx = indexProps([bothSided, oneSided]);
expect(idx['a guy|hits'].book).toBe('fanduel');
});
});