889a96584a
`grade` is a band label over `p_win` and nothing else. `servedGrade.gradeFor`
reads exactly { p_win, refused, refusal_reason, insufficient_data,
factor_adjustment } -- no line, no odds, no edge, no side -- and
`gradeFreeze.TOLERANCES.MAX_LETTER_MISMATCH` is 0, so the served letter MUST
equal the band of the served probability.
The intraday refresh re-graded an adversely-moved prop AT THE CURRENT LINE and
then copied only `res.grade` onto the row for the LOCKED line, discarding the
p_win that produced it. Two defects in one write: the letter stopped matching
the probability beside it, and the letter answered a different proposition than
the claim it was stamped on.
MEASURED on ledger_entries in the current model era
(engine1@2026-08-07-fullwindow): 30,047 unrevised rows carry ZERO letter/p_win
mismatches; all 9 intraday-revised rows are mismatched. The revision was the
sole producer of incoherent authoritative rows. The pre-cutover era is
uninterpretable here (its `grade` was the engine index, not a p_win band, and
mismatches 49.4% of the time WITHOUT any revision) -- which is exactly why the
control was run before quoting a rate.
Simulated over the 57 historical revisions: in the current era, keeping the
published grade restores coherence on 9 of 9.
So the adverse branch now records the move and stops there. No grader is
invoked, no ledger revision is applied, and the grade-rank comparator is
deleted rather than parked -- a dead comparator beside the code is how the
mutation gets re-wired. A production coherence gate compares every output row
to its input on every BELIEF field and, on any divergence, publishes the
untouched slate instead.
History is untouched: the 57 existing `revised_from_grade` rows keep their
values, and the UI that renders them is unchanged. Forward-only.
Lineage is not touched and stays OFF.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQJeAG8vcDoL5zkiaJyVb8
189 lines
9.1 KiB
JavaScript
189 lines
9.1 KiB
JavaScript
// Session 60 (night2/D) — Phase 2.5 intraday refresh, as amended by the
|
||
// INTRADAY BELIEF INTEGRITY repair. Direction is still the signal: WITH the
|
||
// grade = STEAM, AGAINST = recorded with its signed delta. The re-grade branch
|
||
// is GONE — `grade` is a band label over p_win, so a market move may not
|
||
// restate it. All lines are real feed values; the refresh recaptures the close.
|
||
|
||
const { runIntradayRefresh, inSlateHours, __internals } = require('../../src/services/intradayRefreshService');
|
||
const { signedDelta, trackHistory, HISTORY_CAP } = __internals;
|
||
|
||
const NOW = '2026-07-11T20:00:00.000Z';
|
||
|
||
function harness({ grades, oddsProps, analyzeResult }) {
|
||
const store = new Map([[`snapshot:mlb:latest`, { sport: 'mlb', updated_at: NOW, grades, deltas: [] }]]);
|
||
const calls = { analyze: [], revisions: [], closing: 0, ticker: [] };
|
||
const deps = {
|
||
cacheGet: async (k) => store.get(k) ?? null,
|
||
cacheSet: async (k, v) => { store.set(k, v); },
|
||
getOdds: async () => ({ props: oddsProps }),
|
||
analyze: async (prop) => { calls.analyze.push(prop); return analyzeResult; },
|
||
ledger: {
|
||
applyRevision: async (sport, rev) => { calls.revisions.push(rev); return { revised: true }; },
|
||
captureClosing: async () => { calls.closing += 1; return { updated: 0 }; },
|
||
},
|
||
pushTickerItems: async (events) => { calls.ticker.push(...events); },
|
||
now: () => NOW,
|
||
};
|
||
return { deps, store, calls };
|
||
}
|
||
|
||
const GRADE = {
|
||
player: 'Aaron Judge', stat_type: 'home_runs', line: 0.5, direction: 'over',
|
||
grade: 'A', confidence: 78, gradedAt: { line: 0.5, odds: -115, timestamp: NOW },
|
||
};
|
||
const prop = (line) => ({ player: 'Aaron Judge', stat_type: 'home_runs', line, book: 'draftkings' });
|
||
|
||
describe('signedDelta — relative to the graded side', () => {
|
||
test('over: rising line = positive (market chasing the over)', () => {
|
||
expect(signedDelta('over', 1.5, 2.5)).toBe(1);
|
||
expect(signedDelta('over', 1.5, 1.0)).toBe(-0.5);
|
||
});
|
||
test('under: falling line = positive', () => {
|
||
expect(signedDelta('under', 1.5, 1.0)).toBe(0.5);
|
||
expect(signedDelta('under', 1.5, 2.5)).toBe(-1);
|
||
});
|
||
test('missing values → null, never a fabricated zero', () => {
|
||
expect(signedDelta('over', null, 2)).toBeNull();
|
||
});
|
||
});
|
||
|
||
describe('runIntradayRefresh — directional handling', () => {
|
||
test('moved WITH the grade → STEAM, NO re-grade', async () => {
|
||
const { deps, store, calls } = harness({ grades: [GRADE], oddsProps: [prop(1.5)], analyzeResult: null });
|
||
const res = await runIntradayRefresh('mlb', deps);
|
||
expect(res).toMatchObject({ status: 'ok', steam: 1, against: 0, belief_mutations: 0 });
|
||
expect(calls.analyze).toHaveLength(0); // steam never re-grades
|
||
const snap = store.get('snapshot:mlb:latest');
|
||
expect(snap.grades[0].movement).toMatchObject({ kind: 'steam', delta: 1, currentLine: 1.5 });
|
||
expect(calls.ticker.length).toBeGreaterThan(0); // ≥1.0 move → ticker MOVE
|
||
expect(calls.ticker[0].text).toContain('o0.5 → o1.5');
|
||
});
|
||
|
||
test('moved AGAINST >= 1.0 records the move and NEVER re-grades', async () => {
|
||
const { deps, store, calls } = harness({
|
||
grades: [{ ...GRADE, gradedAt: { line: 2.5, odds: -110, timestamp: NOW }, line: 2.5 }],
|
||
oddsProps: [prop(1.5)],
|
||
analyzeResult: { grade: 'C', confidence: 40, p_win: 0.31 },
|
||
});
|
||
const res = await runIntradayRefresh('mlb', deps);
|
||
expect(res).toMatchObject({ against: 1, belief_mutations: 0 });
|
||
// The grader is never consulted. Injecting one and finding it untouched is
|
||
// the point: the torn state is unreachable, not merely unwritten.
|
||
expect(calls.analyze).toHaveLength(0);
|
||
expect(calls.revisions).toHaveLength(0);
|
||
const g = store.get('snapshot:mlb:latest').grades[0];
|
||
expect(g.movement).toMatchObject({ kind: 'against', delta: -1, currentLine: 1.5 });
|
||
expect(g.grade).toBe('A');
|
||
expect(g.revised_from_grade).toBeUndefined();
|
||
});
|
||
|
||
test('a favourable grade the old branch would have adopted is still refused', async () => {
|
||
const { deps, store, calls } = harness({
|
||
grades: [{ ...GRADE, grade: 'C', gradedAt: { line: 2.5, odds: -110, timestamp: NOW }, line: 2.5 }],
|
||
oddsProps: [prop(1.5)],
|
||
analyzeResult: { grade: 'B+', confidence: 82, p_win: 0.81 },
|
||
});
|
||
await runIntradayRefresh('mlb', deps);
|
||
expect(calls.analyze).toHaveLength(0);
|
||
expect(store.get('snapshot:mlb:latest').grades[0].grade).toBe('C');
|
||
});
|
||
|
||
test('a row already carrying a historical revised_from_grade is left alone', async () => {
|
||
const already = { ...GRADE, grade: 'B', revised_from_grade: 'A', gradedAt: { line: 2.5, odds: null, timestamp: NOW }, line: 2.5 };
|
||
const { deps, store } = harness({ grades: [already], oddsProps: [prop(1.5)], analyzeResult: { grade: 'C' } });
|
||
await runIntradayRefresh('mlb', deps);
|
||
const g = store.get('snapshot:mlb:latest').grades[0];
|
||
// History is preserved verbatim — the repair is forward-only.
|
||
expect(g.revised_from_grade).toBe('A');
|
||
expect(g.grade).toBe('B');
|
||
});
|
||
|
||
test('prop gone from the feed → frozen untouched; close recaptured every run', async () => {
|
||
const { deps, store, calls } = harness({ grades: [GRADE], oddsProps: [prop(0.5)], analyzeResult: null });
|
||
const res = await runIntradayRefresh('mlb', deps);
|
||
expect(res.checked).toBe(1);
|
||
expect(store.get('snapshot:mlb:latest').grades[0].movement).toBeNull(); // <0.5 noise
|
||
expect(calls.closing).toBe(1); // refresh-fidelity closing capture
|
||
});
|
||
|
||
test('no snapshot → honest skip, zero quota spent', async () => {
|
||
const calls = { odds: 0 };
|
||
const res = await runIntradayRefresh('mlb', {
|
||
cacheGet: async () => null,
|
||
cacheSet: async () => {},
|
||
getOdds: async () => { calls.odds += 1; return { props: [] }; },
|
||
ledger: {}, pushTickerItems: async () => {}, now: () => NOW,
|
||
});
|
||
expect(res.status).toBe('skipped');
|
||
expect(calls.odds).toBe(0);
|
||
});
|
||
});
|
||
|
||
// S6 (A1 board) — sparkline fuel: {t, line} history capture on each grade's
|
||
// movement tracking, persisted inside the snapshot write-back (no new keys).
|
||
describe('trackHistory — real {t, line} points, seeded, deduped, capped', () => {
|
||
const LOCK_TS = '2026-07-11T14:00:00.000Z';
|
||
const g = (extra = {}) => ({ ...GRADE, gradedAt: { line: 0.5, odds: -115, timestamp: LOCK_TS }, ...extra });
|
||
|
||
test('first capture seeds the LOCKED line at its own timestamp, then the move', () => {
|
||
const h = trackHistory(g(), 1.5, NOW);
|
||
expect(h).toEqual([{ t: LOCK_TS, line: 0.5 }, { t: NOW, line: 1.5 }]);
|
||
});
|
||
|
||
test('a flat line never appends a duplicate point (a point means it MOVED)', () => {
|
||
const h = trackHistory(g(), 0.5, NOW); // current == locked
|
||
expect(h).toEqual([{ t: LOCK_TS, line: 0.5 }]);
|
||
const again = trackHistory(g({ history: h }), 0.5, '2026-07-11T21:00:00.000Z');
|
||
expect(again).toHaveLength(1);
|
||
});
|
||
|
||
test('an unparseable current line appends nothing (real points only)', () => {
|
||
expect(trackHistory(g(), null, NOW)).toBeUndefined();
|
||
const prior = [{ t: LOCK_TS, line: 0.5 }];
|
||
expect(trackHistory(g({ history: prior }), 'n/a', NOW)).toBe(prior);
|
||
});
|
||
|
||
test('capped at 24 points, newest kept', () => {
|
||
const prior = Array.from({ length: HISTORY_CAP }, (_, i) => ({ t: `t${i}`, line: i }));
|
||
const h = trackHistory(g({ history: prior }), 99, NOW);
|
||
expect(h).toHaveLength(HISTORY_CAP);
|
||
expect(h[HISTORY_CAP - 1]).toEqual({ t: NOW, line: 99 });
|
||
expect(h[0]).toEqual({ t: 't1', line: 1 }); // oldest point aged out
|
||
});
|
||
});
|
||
|
||
describe('runIntradayRefresh — history rides the snapshot write-back', () => {
|
||
test('a steam move persists history on the grade (locked point + current)', async () => {
|
||
const { deps, store } = harness({ grades: [GRADE], oddsProps: [prop(1.5)], analyzeResult: null });
|
||
await runIntradayRefresh('mlb', deps);
|
||
const snap = store.get('snapshot:mlb:latest');
|
||
expect(snap.grades[0].history).toEqual([
|
||
{ t: NOW, line: 0.5 }, // seeded from the lock (gradedAt.timestamp === NOW here)
|
||
{ t: NOW, line: 1.5 },
|
||
]);
|
||
// grades:{sport} carries the same enriched grades.
|
||
expect(store.get('grades:mlb').grades[0].history).toHaveLength(2);
|
||
});
|
||
|
||
test('a flat run keeps a single seeded point — the sparkline stays hidden (<3)', async () => {
|
||
const { deps, store } = harness({ grades: [GRADE], oddsProps: [prop(0.5)], analyzeResult: null });
|
||
await runIntradayRefresh('mlb', deps);
|
||
expect(store.get('snapshot:mlb:latest').grades[0].history).toEqual([{ t: NOW, line: 0.5 }]);
|
||
});
|
||
|
||
test('a prop gone from the feed leaves prior history untouched', async () => {
|
||
const withHist = { ...GRADE, stat_type: 'hits', history: [{ t: 'x', line: 1 }] };
|
||
const { deps, store } = harness({ grades: [withHist], oddsProps: [prop(1.5)], analyzeResult: null });
|
||
await runIntradayRefresh('mlb', deps);
|
||
const frozen = store.get('snapshot:mlb:latest').grades.find((g) => g.stat_type === 'hits');
|
||
expect(frozen.history).toEqual([{ t: 'x', line: 1 }]);
|
||
});
|
||
});
|
||
|
||
describe('inSlateHours — noon–midnight ET', () => {
|
||
test('3 PM ET yes, 4 AM ET no', () => {
|
||
expect(inSlateHours(new Date('2026-07-11T19:00:00Z'))).toBe(true); // 3 PM EDT
|
||
expect(inSlateHours(new Date('2026-07-11T08:00:00Z'))).toBe(false); // 4 AM EDT
|
||
});
|
||
});
|