Sessions 29-30: Content templates + PropLine 3-key adapter + MLB Stats API + ESPN summary (1694 tests)

This commit is contained in:
Kev
2026-06-14 22:29:01 -04:00
parent 927c4a5c65
commit a3351e2135
14 changed files with 1091 additions and 27 deletions
+69 -1
View File
@@ -1,9 +1,77 @@
# VYNDR — Build State
## Last Updated
2026-06-12
2026-06-14
## Current Phase
SHIP BUILD v30.0 — Provider backbone: PropLine 3-key adapter, MLB Stats API, ESPN summary (Session 30)
## Session 30 (2026-06-14) — SHIPPED
Wired three VERIFIED-live data sources (Chrome infra session, Jun 14).
Props never go dark again: PropLine gives 3,000 req/day FREE vs odds-api's
500/month. Tank01 player props confirmed EMPTY — skipped entirely.
Backend 1660 → **1694 tests** (+34), 137 suites, zero regressions. Web
build clean.
### PHASE 1 — Traced existing architecture
Registry (`providers.js`) keyed by id (envKey presence = configured,
quotaType/quotaLimit, priority). `providerGateway.fetch(id, cb, opts)`
quota-checks via `quotaTracker`, falls over the `getFallbackChain` on
QUOTA failure only. Normalization lives in `utils/oddsNormalizer`
(`normalizeProps` filters books to ALLOWED_BOOKS + markets to MARKET_MAP).
### PHASE 2 — PropLine adapter + 3-key rotation
- `proplineAdapter.js` — thin (PropLine IS Odds-API-compatible → reuses
`normalizeProps`/`extractSpreads`). `?apiKey=` query auth, base
api.prop-line.com/v1. 3-key rotation: per-key daily usage in Redis
(`propline:usage:{i}:{date}`, in-memory fallback), picks least-used key
under the 900 threshold, returns null when all 3 exhausted (gateway
falls through). Routes through the gateway for the 3,000/day total cap.
- Registry: `propline` priority 1 (PRIMARY); `odds-api` dropped to 2.
- **Found + fixed a latent bug:** `MARKET_MAP` had NO MLB market keys, so
PropLine/odds-api MLB props would normalize to ZERO. Added batter_*/
pitcher_* keys → internal stat_types. Added `pinnacle` to ALLOWED_BOOKS.
- 12 tests. Self-eval 9/10.
### PHASE 3 — getOdds prefers PropLine + source tracking
- `getOdds()` tries PropLine first when `hasKeys()` (gated → zero impact on
existing tests/envs), falls back to odds-api. Response + cache carry a
`provider` field ('propline' | 'odds-api'). Extracted the shared
movement/cascade/snapshot block into `recordDownstream` (DRY). 5 tests.
Self-eval 9/10.
### PHASE 4 — MLB Stats API adapter
- `mlbStatsAdapter.js` — statsapi.mlb.com, FREE/no-auth/unlimited, NOT via
the gateway. `getScheduleWithPitchers`, `getPlayerGameLog`,
`getSeasonAverages`, `getBatterVsPitcher`. Cached TTLs (schedule 30m,
logs/season 6h, BvP 24h), stale-on-error. Registry `mlb-stats`
(`noAuth: true``getConfiguredProviders` now counts no-auth providers).
11 tests. Self-eval 9/10.
### PHASE 5 — ESPN summary enrichment
- `scheduleService.getGameSummary(sport, eventId)` → ESPN summary
(injuries, ESPN Bet odds, ATS, leaders, box score). Empty-default
shape, cached 10m, never throws. 7 tests. Self-eval 9/10.
### PHASE 6 — Registry + docs
- CLAUDE.md "Provider Strategy" section added.
### Files created
- `src/services/adapters/proplineAdapter.js`, `mlbStatsAdapter.js`
- `tests/unit/{proplineAdapter,oddsProviderPreference,mlbStatsAdapter,espnSummary}.test.js`
### Files modified
- `src/config/providers.js` (propline + mlb-stats, odds-api→priority 2,
isProviderConfigured/noAuth)
- `src/utils/oddsNormalizer.js` (MLB market keys + pinnacle)
- `src/services/oddsService.js` (PropLine-first + provider field + recordDownstream)
- `src/services/scheduleService.js` (getGameSummary), `CLAUDE.md`
---
## Previous Phase
SHIP BUILD v29.0 — Content generation templates: structured social/newsletter content from live data (Session 29)
## Session 29 (2026-06-13) — SHIPPED