Session 23: All-day intelligence layer — schedule, game lines, streaks, hot lists, stat filtering, ParlayAPI dead (1567 tests)

This commit is contained in:
Kev
2026-06-12 11:16:58 -04:00
parent 6ab49d4c37
commit 0538205fab
32 changed files with 2276 additions and 2 deletions
+91
View File
@@ -4,6 +4,97 @@
2026-06-12
## Current Phase
SHIP BUILD v23.0 — All-Day Intelligence Layer: schedule, game lines, streaks, hot lists, stat filtering (Session 23)
## Session 23 (2026-06-12) — SHIPPED
Built the all-day content layer that makes VYNDR an intelligence
terminal, not a prop-grading widget. EVERYTHING coexists: schedule,
stats, streaks, hot lists, and game lines all visible at once —
nothing replaces anything. When odds-api props are empty, the other
(free/cheap) layers keep the platform alive. NO odds-api credits were
spent this session.
Baseline 1505 → **1567 tests** (+62), 124 suites, zero regressions.
Web build clean.
### PHASE 1 — Schedule API (`/api/schedule/:sport`)
- `src/services/scheduleService.js` — cache-aside read of free ESPN
scoreboards. Reads `schedule:{sport}:{date}` first; on a miss it
self-heals by fetching ESPN directly (the same free endpoint the
pollers hit), normalizes, caches 60s. The platform is NEVER empty.
- Per-game `hasOdds` / `hasGameLines` flags read OTHER caches
(odds-api props, Tank01 lines) WITHOUT triggering a fetch.
- `src/routes/schedule.js` — returns an empty slate (never 5xx) on
error. Unknown sport → 404. Mounted in `app.js`.
### PHASE 2 — Tank01 Game Lines (`/api/gamelines/:sport`)
- Added `getMLBBettingOdds` to `tank01MlbAdapter` (NBA already had
`getNBABettingOdds`). 15-min cache TTL, shares RAPID_API_KEY quota.
- `src/routes/gameLines.js` — normalizes the book-by-book body
(bet365 / betmgm / caesars: ML, spread, total) into a flat shape,
parses teams from the `YYYYMMDD_AWAY@HOME` gameID. Missing key →
graceful `configured:false`. Adapter throw → empty, never 500.
### PHASE 3 — Streaks Engine (`/api/streaks/:sport`)
- `src/services/streaksService.js` — pure, data-driven. Consecutive
run from the latest game backward; collapses tiered specs (25+/20+
pts) to the more impressive one. NBA (14 specs incl. dd/td/PRA/hot-
shooter), MLB (9), NFL (5), soccer (4). Through VYNDR's lens —
"4-game 28+ scoring streak", not "31 PPG".
- `src/services/rosterLogs.js` — Redis-only roster loader (prefetch
blob fast-path, else SCAN over `gamelogs:{sport}:*`). Never throws.
### PHASE 4 — Hot Lists (`/api/hotlist/:sport`)
- `src/services/hotListService.js` — "hot" = ABOVE the player's own
baseline (explicit seasonAvg, else games outside the window), not
just high raw numbers. Ranked by delta, tie-broken by raw recent
average. Date-based 7-day window when rows carry dates.
### PHASE 5 — Stat Filtering
- `src/config/statFilters.js` (+ `web/src/config/statFilters.ts`
mirror). `?stat=` param on streaks/hotlist. Discovery endpoint
`GET /api/stats/filters/:sport`. `StatFilterPills` component.
### PHASE 6 — Unified Dashboard
- `StreaksPanel` + `HotListPanel` (headshots, tier-gated, self-hide
when empty), wired into the Slate below the games AND mounted as
landing-page teasers. Stat pills narrow both; schedule + game lines
stay visible regardless. Free tier sees 3, paid sees all.
### PHASE 7 — Cleanup
- ParlayAPI marked `status: 'dead'` in `src/config/providers.js`
(Chrome Claude: `api.parlayapi.io` unreachable on 2026-06-12).
Excluded from `getFallbackChain` + `getConfiguredProviders`; new
`isDeadProvider` helper. Config still resolves so adapter tests
(network-mocked) pass unchanged.
### Files created
- `src/services/scheduleService.js`, `src/routes/schedule.js`
- `src/routes/gameLines.js`
- `src/services/streaksService.js`, `src/routes/streaks.js`
- `src/services/hotListService.js`, `src/routes/hotlist.js`
- `src/services/rosterLogs.js`
- `src/config/statFilters.js`
- `web/src/config/statFilters.ts`
- `web/src/components/StatFilterPills.tsx`
- `web/src/components/StreaksPanel.tsx`
- `web/src/components/HotListPanel.tsx`
- 7 new test files (schedule, gamelines, streaks/hotlist routes,
streaksService, hotListService, rosterLogs, statFilters,
providersRegistry)
### Files modified
- `src/app.js` (mounted 4 routes)
- `src/services/adapters/tank01MlbAdapter.js` (getMLBBettingOdds)
- `src/routes/stats.js` (filters discovery endpoint)
- `src/config/providers.js` (ParlayAPI dead)
- `web/src/app/page.tsx`, `web/src/components/Slate.tsx`
- `tests/unit/tank01MlbAdapter.test.js`
---
## Previous Phase
SHIP BUILD v22.0 — Tracker-driven quota guard, env-configurable cache TTL, opt-in odds prewarmer (Session 22)
## Session 22 (2026-06-12) — SHIPPED