Session 56: Full audit — PropLine + boxscore + pipeline + sport coverage (2289 tests)
Research (verified against live MLB Stats / ESPN / The Odds APIs): - specs/propline-audit.md — every stat_type mapped against our 4-layer pipeline; real MLB boxscore fields; sport coverage status; pipeline gap analysis. - specs/vyndr-roadmap.md — priority-ordered Sessions 57–64 + coverage targets. - scripts/propline-audit.js + specs/audit-data/ (raw capture). Headline bug: oddsNormalizer mapped batter_rbis → 'rbis' while the whole grade/feature/outcome chain keys on 'rbi' — every PropLine RBI prop silently failed to grade AND settle. Fixed (+ regression test). Phase 4 — wired missing MLB stats end-to-end: - PropLine MLB markets 6 → 12 (+runs, walks, doubles, earned_runs, hits_allowed, outs — same request, no extra quota). - doubles/outs/triples added to featureCache + outcomeService MLB_LOG_FIELD and all three grade whitelists (analyze/scan/validation.py). Phase 6 — pipeline resilience: - opsNotify.js: ntfy alerts (never throws, test-disabled). Snapshot success/ stale/failure alerts; retry-once on hard odds error (not on empty slate). - Missed-cron watchdog (mostRecentExpectedSlot/isSnapshotOverdue); status probe now returns `overdue`. Coverage truth: MLB is the only end-to-end-live sport; outcome settlement is MLB-only (WNBA/NBA/soccer never settle) — documented as the #1 roadmap gap. Backend 2276 → 2289 tests (+13). Web build exit 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -658,6 +658,32 @@ snapshot, locked to the line, and read from cache.
|
||||
+ the ClaimMeter pitch). That expiry lapsing — NOT a tier-limit change — was the
|
||||
cause of the "4 stripe test failures." Operators override via `FOUNDER_CODE_EXPIRY`.
|
||||
|
||||
## Data Audit + Pipeline Resilience (Session 56 — non-obvious)
|
||||
- **`specs/propline-audit.md` + `specs/vyndr-roadmap.md` are the source of truth**
|
||||
for data coverage + the session plan. Re-run `node scripts/propline-audit.js`
|
||||
(writes raw JSON to stdout; live sections need network) to refresh.
|
||||
- **A market only fully works if it's wired at FOUR layers:** requested in
|
||||
`proplineAdapter.MARKETS`, mapped in `oddsNormalizer.MARKET_MAP`, whitelisted in
|
||||
all three grade gates (`routes/analyze.js`, `routes/scan.js`,
|
||||
`python/utils/validation.py`), AND (for MLB) present in `MLB_LOG_FIELD` in BOTH
|
||||
`featureCache` and `outcomeService`. Miss the map → silent zero; miss the log
|
||||
field → no features + no settlement. `batter_rbis` was mapped to `rbis` while
|
||||
everything else keyed on `rbi` — a 4-layer desync that silently killed RBI
|
||||
props. It's `rbi` now; a normalizer test locks it.
|
||||
- **The streaks/hotlist path uses its own `rbis` key** built from raw MLB stats —
|
||||
independent of the odds normalizer. Don't "unify" them; the split is intentional.
|
||||
- **MLB is the ONLY end-to-end-live sport.** Outcome settlement is MLB-only
|
||||
(WNBA/NBA/soccer grades never settle → `accuracy` reflects MLB only). Fixing
|
||||
that (ESPN box-score settle path) is roadmap Session 57.
|
||||
- **`src/utils/opsNotify.js`** pushes pipeline alerts to ntfy (`vyndr-pipeline-
|
||||
kev2026`). It NEVER throws and is auto-disabled under `NODE_ENV==='test'` /
|
||||
`PIPELINE_ALERTS=0` (inject `fetchImpl` to test it). `snapshotService` alerts on
|
||||
success/stale/failure; `snapshotScheduler` has a per-minute missed-cron watchdog
|
||||
(`isSnapshotOverdue`, exposed as `overdue` on the status probe).
|
||||
- **Snapshot retry rule:** retry-once ONLY on a thrown/null odds response (a
|
||||
transient provider blip). A successful-but-empty slate is NOT retried — that's a
|
||||
legit off-hours empty slate, and retrying would waste quota + add 60s latency.
|
||||
|
||||
## Active Skills
|
||||
- vyndr-voice (all user-facing output)
|
||||
- prop-analysis (grading methodology)
|
||||
|
||||
Reference in New Issue
Block a user