S11 (a1): live tracking — the read locked, the game watched

MLB statsapi + WNBA ESPN live boxscores -> per-player current values
(live:{sport}:{date} TTL 90s, /api/live/:sport + Next proxy). Pure
propState math (HIT / ON PACE / NEEDS N / HOLDS / LINE PASSED — never
red in-progress), attachLiveProgress strip join on nameKey+statType,
proximity-to-hit slate float, StatStrip LiveTracker in the ROW-GRAMMAR
outcome slot (spec amended + lock test updated). Grades never change
in-game — tracking, labeled as such. 2698 -> 2757 tests, web build 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kev
2026-07-12 00:45:29 -04:00
parent 14dc9cf270
commit b5d3fd14bb
18 changed files with 1666 additions and 18 deletions
+6 -1
View File
@@ -365,6 +365,9 @@ function buildPlayerStripsFromProps(gameProps, gradeIndex, deltaIndex, now = Dat
const delta = deltaIndex[`${gradeKey(p.player, p.stat_type || p.stat)}|${side}`];
byPlayer[pk].props.push({
stat: statShort(rec.stat_type || rec.stat),
// A1 S11 — the CANONICAL stat key (live-tracking join; `stat` above is
// the shortened display label and can't be joined on).
statType: String(rec.stat_type || rec.stat || '').toLowerCase(),
line: rec.line,
side,
grade: rec.grade,
@@ -391,7 +394,9 @@ function buildPlayerStripsFromProps(gameProps, gradeIndex, deltaIndex, now = Dat
});
} else {
byPlayer[pk].props.push({
stat: statShort(p.stat_type || p.stat), line: p.line, side: '', grade: null, awaiting: true,
stat: statShort(p.stat_type || p.stat),
statType: String(p.stat_type || p.stat || '').toLowerCase(),
line: p.line, side: '', grade: null, awaiting: true,
book: p.book || null,
bestBook: detectBestBook(p.books, p.direction || 'over', p.line),
});