- src/lib/model/inplay.ts: in-play win probability — remaining goals modelled as
time-scaled Poisson processes convolved with the current score; recomputed each
tick. 4 vitest cases (locks at FT, lead grows decisive over time, sums to 1).
- ESPN summary normalizer extended with the live event timeline (keyEvents);
preview now carries liveStats + events. Scheduler refreshes LIVE matches'
summaries every live tick (~20s) for fresh stats/timeline.
- /match/:num is now a live match center: when live it shows in-play win
probability (driven by the WS score/clock), match stats bars and an event
timeline, polling while live; preview content for scheduled games, recap when
finished. Verified with a simulated live state (94% live vs 81% pre-match).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Persistence via Node's built-in node:sqlite (zero native deps) on a Docker
volume: response cache, source health, fixture↔provider id map, per-fixture
enrichment, ingest log. Runtime bumped to node:24-slim + --experimental-sqlite.
- Resilient fetcher: DB cache + per-source rate-limit + jittered backoff +
circuit-breaker (blocked sources trip + skip; UI reads DB, never breaks).
- ESPN hidden API as the PRIMARY rich source (works from the VPS where SofaScore
403s): scoreboard (live scores w/ clock) + summary (venue, H2H, recent form,
lineups, team stats). football-data / SofaScore are fallbacks.
- Scheduler: maps all 72 group fixtures to ESPN event ids, polls live on a
dynamic cadence, enriches imminent fixtures into match_ext. /api/sources/health.
- Verified: DB populates (real H2H + form for opening matches), 22 tests pass,
Docker image runs node:sqlite on the volume and persists across restart.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>