Session 15: Intelligence hardening — park factors, weather, Tank01 prefetch, pace factors, signal audit, founder pricing fix (1405 tests)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+127
-2
@@ -1,10 +1,135 @@
|
||||
# VYNDR — Build State
|
||||
|
||||
## Last Updated
|
||||
2026-06-10
|
||||
2026-06-11
|
||||
|
||||
## Current Phase
|
||||
SHIP BUILD v14.0 — Africa checkout + Tank01 wiring + WNBA/MLB odds + UX polish (Session 14)
|
||||
SHIP BUILD v15.0 — Intelligence hardening + platform correctness (Session 15)
|
||||
|
||||
## Session 15 (2026-06-11) — SHIPPED
|
||||
|
||||
### Phase 0 — Correctness
|
||||
|
||||
- **Africa short-circuit removed** (`Pricing.tsx:152`). The Session 14
|
||||
backend handles 'africa' end-to-end: validation accepts it; missing
|
||||
`STRIPE_PRICE_AFRICA` returns a 503 with `code:'tier_unconfigured'`
|
||||
the existing inline error surface displays. The frontend short-
|
||||
circuit was blocking checkout even after the backend was ready.
|
||||
- **Odds + Sentry + welcome email audits**: all already correct from
|
||||
prior sessions. Documented for posterity; no fixes required.
|
||||
- **Poller → odds pipeline**: confirmed there's NO key-mismatch
|
||||
pipeline issue. Pollers handle game resolution
|
||||
(`game:{id}:status`, `poller:{SPORT}:heartbeat`); `oddsService`
|
||||
populates `odds:{sport}:{date}` on-demand. The "1 games shown but
|
||||
Slate empty" report would be a separate odds-api quota / key issue.
|
||||
- **Founder price fallback hardened**. `PRICE_MAP` no longer falls
|
||||
back to fake strings like `'price_analyst_monthly'` that would 400
|
||||
from Stripe in live mode. Missing env → `PRICE_UNCONFIGURED`
|
||||
sentinel → 503 with `code:'tier_unconfigured'`. Founder codes
|
||||
presented against an unwired founder-price env now fall back
|
||||
GRACEFULLY to the standard tier price rather than dropping the
|
||||
checkout — the founder discount is operator-controlled and
|
||||
shouldn't break the user's purchase.
|
||||
|
||||
### Phase 1 — Signal audit
|
||||
|
||||
Documented in a new comment block at the top of
|
||||
`src/services/intelligence/computeFeatures.js`. Every signal cited
|
||||
to its data source: injury (ESPN injury feed), coach (Supabase
|
||||
`coach_profiles` + JSON seed), consistency (game logs via
|
||||
`gameLogService`), Tank01 fields (Session 14 + 15 prefetch),
|
||||
soccer cascade (Session 9), park factors (Session 15 — static),
|
||||
weather (Session 15 — Open-Meteo), pace factors (Session 15 —
|
||||
static). No phantom signals.
|
||||
|
||||
### Phase 2 — MLB park factors
|
||||
|
||||
`src/data/parkFactors.js` — all 30 MLB parks indexed to 100 league
|
||||
average. FanGraphs 2024-25 three-year weighted data. Coors at hr=128,
|
||||
SF Oracle at hr=85 (the two extremes by design). `getParkFactor()`
|
||||
returns null on unknown teams so the feature extractor drops the
|
||||
signal cleanly rather than falsely reporting "neutral".
|
||||
|
||||
Wired into `computeFeatures.js` MLB branch — features pick up
|
||||
`park_hr`, `park_h`, `park_r`, `park_home` when the home team
|
||||
resolves.
|
||||
|
||||
### Phase 3 — Weather (Open-Meteo)
|
||||
|
||||
`src/services/weatherService.js` — Open-Meteo proxy (no API key
|
||||
required). 5-second hard timeout, 1-hour Redis cache, silent
|
||||
degrade on failure (never blocks the grade). Fahrenheit + mph units
|
||||
to match the bettors' mental model.
|
||||
|
||||
`src/data/venueCoordinates.js` — lat/lon + dome flag for all 30
|
||||
MLB venues and all 16 World Cup 2026 venues. Retractable stadiums
|
||||
are marked `dome:true` because operators close the roof when
|
||||
conditions warrant — weather doesn't drive grade in that case.
|
||||
|
||||
Wired into `computeFeatures.js` MLB branch — fetches weather when
|
||||
the home venue is outdoor + has finite coordinates.
|
||||
|
||||
### Phase 4 — Tank01 daily prefetch
|
||||
|
||||
`scripts/tank01-prefetch.js` — orchestrator that pulls the Redis
|
||||
cache keys Session 14's `tank01Augment.js` reads. Default budget
|
||||
≤80 requests/run, configurable via `--max=N`. NBA path pulls
|
||||
schedule + final-game box scores + daily odds. MLB path pulls
|
||||
scoreboard + final-game box scores (BvP pull awaits batter/pitcher
|
||||
ID resolution on the scoreboard payload).
|
||||
|
||||
Recommended trigger: extend the n8n "Morning Ops" workflow to
|
||||
exec the script daily at 7am UTC.
|
||||
|
||||
### Phase 5 — MLB matchup context
|
||||
|
||||
`src/services/intelligence/mlbContext.js` — pure functions for
|
||||
platoonAdvantage(pitcherHand, batterHand) and
|
||||
projectedPA(lineupPosition). Tested with all hand combinations +
|
||||
all lineup slots. Wiring into computeFeatures is deferred until
|
||||
odds-api carries those fields (it doesn't today).
|
||||
|
||||
### Phase 6 — NBA pace factors
|
||||
|
||||
`src/data/paceFactors.js` — all 30 NBA teams (NBA.com/stats 2024-25,
|
||||
indexed to 100). Legacy-abbreviation aliases (NJN→BKN, NOH→NOP,
|
||||
SEA→OKC, CHO→CHA) so historical lookups resolve. Wired into the NBA
|
||||
branch of `computeFeatures.js` — `pace_factor` (player's team) +
|
||||
`opp_pace_factor` (opponent).
|
||||
|
||||
### Tests added (Session 15)
|
||||
| Suite | Tests |
|
||||
|----------------------------------------|-------|
|
||||
| `tests/unit/parkFactors.test.js` | 14 |
|
||||
| `tests/unit/weatherService.test.js` | 14 |
|
||||
| `tests/unit/tank01Prefetch.test.js` | 14 |
|
||||
| `tests/unit/mlbContext.test.js` | 21 |
|
||||
| `tests/unit/paceFactors.test.js` | 12 |
|
||||
| **Session 15 total** | **75** |
|
||||
|
||||
### Quality gates
|
||||
- `npm test`: **1405 / 1405 passing** (1330 + 75 new), 108 suites,
|
||||
0 regressions. One pre-existing computeFeatures test was updated:
|
||||
the contract used to be "ESPN failure → empty features"; the
|
||||
contract is now "ESPN failure → static context augmentation
|
||||
(pace, park) still surfaces."
|
||||
- `web/npm run build`: clean
|
||||
- License audit: third-party deps remain permissive
|
||||
|
||||
### Honest gaps
|
||||
- Tank01 prefetch must be triggered by n8n/cron before the augmentor
|
||||
reads return data. Grades work as before until then.
|
||||
- BvP pull is no-op until probable-pitcher IDs land on the Tank01
|
||||
MLB scoreboard projection.
|
||||
- Phase 5 helpers tested but not wired — odds-api doesn't carry
|
||||
batter handedness or lineup position fields today.
|
||||
- Weather for soccer venues: only MLB is wired this session.
|
||||
Soccer venue weather is a 5-line follow-up in the soccer extractor.
|
||||
|
||||
### Coolify env (Session 15 additions)
|
||||
None new from this session.
|
||||
|
||||
---
|
||||
|
||||
## Session 14 (2026-06-11) — SHIPPED
|
||||
|
||||
|
||||
Reference in New Issue
Block a user