Files
vyndr/specs/vyndr-roadmap.md
T
builtbykev 4e49ee0990 S9 (a1): slip reader — zero-API OCR
tesseract.js (self-hosted WASM, Apache-2.0) + pure per-book layout
parsers (DK/FD/MGM/Caesars) with per-field confidence and needs_review
honesty — the reader never guesses. POST /api/slips/parse (auth, free
1/day paid 10/day, 4MB cap) + Next proxy. Gated /slip page: upload or
paste, manual-correct UI, per-leg grades through the normal engine
(refusals render honestly), add-all to Parlay Lab, share card. Vision
model upgrade logged post-revenue. 2574 -> 2608 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:32:17 -04:00

160 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VYNDR Master Roadmap — Generated 2026-07-10 (Session 56)
The foundation document. Derived from the Session-56 data audit
(`specs/propline-audit.md`, verified against live MLB Stats / ESPN / Odds APIs).
Every session after this references it. Update it as sessions ship.
---
## Current coverage (verified 2026-07-10)
| Sport | Odds props | Grading | Features (l5/l20) | Outcomes settled | Status |
|-------|-----------|---------|-------------------|------------------|--------|
| MLB | ✅ PropLine + odds-api | ✅ | ✅ real (statsapi) | ✅ (S55, expanded S56) | **LIVE** |
| WNBA | ✅ odds-api/PropLine | ✅ | ⚠️ Python offline → thin | ❌ | **PARTIAL** |
| Soccer | ✅ odds-api only (no PropLine) | ⚠️ extractor only | ⚠️ | ❌ | **PARTIAL** |
| NBA | ⚠️ summer league only | ✅ | ⚠️ offline | ❌ | **OFF-SEASON (Oct)** |
| NFL | ⚠️ preseason | ⚠️ mapped, not e2e | ❌ | ❌ | **PRE-SEASON (Sep)** |
| NHL | ❌ off-season | ⚠️ mapped | ❌ | ❌ | **DARK (Oct)** |
**The core product is MLB.** It is the only sport that is live end-to-end
(odds → grade → real features → settled accuracy). Everything else is a
build-out target.
---
## Gap analysis (from the audit)
1. **Outcome settlement is MLB-only** — WNBA/NBA/soccer grades never settle, so
the accuracy record (the S55 trust engine) only reflects MLB. **Highest-value
gap.** Needs the ESPN box-score settle path (`espnStatsAdapter` already parses
the shape for season avgs).
2. **NBA/WNBA features depend on an offline Python nba_api service** — l5/l20 are
often empty; only season avgs survive (ESPN fallback). Needs an ESPN game-log
feature path so intel populates without the Python service.
3. **Soccer has no PropLine source** — odds-api backup only; no `SPORT_KEYS` entry.
Soccer grading isn't wired into the snapshot pipeline end-to-end.
4. **NFL mapped but not graded end-to-end** — markets normalize, but no feature/
outcome path. Wire before September.
5. ~~RBI silent-failure (rbis/rbi)~~**FIXED S56.**
6. ~~Under-requesting MLB markets~~**FIXED S56** (6 → 12 markets).
7. ~~No pipeline alerting / retry / missed-cron~~**FIXED S56.**
8. **No live calibration** — the accuracy record exists but doesn't yet feed back
into grade confidence (spec 2.3 from S55).
9. **`batter_strikeouts` (batter Ks)** mapped but not feature/settle-wired.
---
## Session plan (priority-ordered)
| Session | Focus | Ships | Scope |
|---------|-------|-------|-------|
| 57 | **WNBA/NBA outcome settlement** | ESPN box-score settle path in outcomeService → accuracy for basketball; WNBA goes fully live | M |
| 58 | **ESPN game-log features** | l5/l10/l20 for NBA/WNBA without the Python service → real intel on basketball grade cards | M |
| 59 | **Soccer end-to-end** | soccer into the snapshot pipeline (odds-api source), feature extractor wired, ESPN settle | L |
| 60 | **Live calibration** | accuracy record feeds grade-confidence adjustment (under/over-confident tiers nudge); "Model health: Calibrated/Learning" indicator | M |
| 61 | **NFL pre-season prep** | NFL feature + settle path (ESPN NFL boxscore) so Week 1 (Sep) is live | L |
| 62 | **Prop breadth** | `batter_strikeouts`, `triples`, pitcher `walks`; NBA `pra`/`turnovers` requested; WNBA extra markets | S |
| 63 | **Accuracy depth** | per-archetype hit rates, per-stat hit rates, player-level record ("VYNDR on Judge: 12-5"); ledger UI | M |
| 64 | **NBA regular-season readiness** | verify NBA pipeline for the Oct tip-off; depth-chart/cascade live | M |
Scope key: S ≈ ½ session, M ≈ 1 session, L ≈ 12 sessions.
> NOTE (Session 58): the numbered plan above predates the overhaul work
> order. The work order's phases (0 = kill the lies ✅ S57, 1 = truth
> infrastructure ✅ S58, 2 = slate UX, 3 = mobile, **2.5 below**, 4 = scan/
> parlay, 5 = records, 6 = landing/content) take sequencing priority; the
> table's items slot in where they don't conflict.
## Phase 2.5 — Intraday line refresh + directional movement (LOGGED Session 58)
Authoritative scope from the Phase 1 GO prompt. **Build after Phase 3
(mobile), before Phase 4.** During slate hours (~noonmidnight ET):
- Lightweight ODDS-ONLY refresh every 1530 min (no full re-grade run).
Recompute the signed delta per graded prop RELATIVE TO THE GRADED SIDE —
direction is the signal, not magnitude alone.
- **Moved WITH the grade** (market chasing our number): PropRow badge
`STEAM ▲ +N`. Good for the record; entry edge compressed. No re-grade.
- **Moved AGAINST the grade ≥ 1.0** (or odds-equivalent): auto re-grade THAT
PROP ONLY.
- Grade holds → badge `VALUE ▲ better entry` (better number, same read).
- Grade drops → update the grade with `revised_from_grade` set (column
already exists in `ledger_entries`) + a visible revision marker
(original grade struck through — the ledger UI already renders it).
Revisions are ALWAYS public — never silently regrade, per Ledger ethos.
- All displayed lines remain real book values from the refresh — the
refresh CAPTURES market numbers, never computes them.
- After ship: drop `SNAPSHOT_EXPECTED_INTERVAL` to the refresh cadence —
the HeartbeatBar SYNC badge (normal <1.5x · amber ≥1.5x · STALE ≥3x)
goes genuinely live with zero further UI changes.
## Phase 4.5 — WNBA settlement via ESPN box scores (DUE DATE, not "roadmap")
Logged Session 59. Pending-forever WNBA ledger rows are honest but become a
credibility hole past ~2 weeks of accumulation. **Due: within 2 weeks of
day one of the public record (by ~Jul 24 2026).** Scope: ESPN box-score
settle path in outcomeService + ledgerService `defaultGetPlayerStats`
(WNBA branch) so WNBA rows settle nightly like MLB. Build right after
Phase 4 (scan/parlay polish).
## Phase 5 addition — calibration by grade tier (logged Session 59)
Once settles mature: the MODEL tab shows A-tier hit% vs B-tier hit%
SEPARATELY (same n≥20 rule PER TIER — a tier below threshold shows
"building", never a %). The separation between tiers is the proof the
grades mean something. `ledger_entries.grade` already carries the tier;
this is an aggregate + UI change only.
---
## Stat-type coverage target (fully built)
- **MLB (batters):** hits, total_bases, home_runs, rbi, runs, doubles, triples,
walks, stolen_bases, batter_strikeouts. **(pitchers):** strikeouts, earned_runs,
hits_allowed, innings_pitched, outs, walks. *(Bold-new this session: doubles,
triples, outs, runs, walks requested + settleable.)*
- **NBA/WNBA:** points, rebounds, assists, threes, steals, blocks, turnovers, pra.
- **Soccer:** goals, shots, shots_on_target, tackles, cards, corners, saves,
passes, clean_sheet.
- **NFL:** passing/rushing/receiving yards, receptions, pass/rush/rec TDs,
anytime_td, interceptions, kicking_points.
## Sport coverage target
- **MLB** ✅ live now (settled accuracy).
- **WNBA** → live after S57 (settlement) + S58 (features).
- **Soccer** → live after S59.
- **NFL** → ready for September (S61).
- **NBA** → ready for October (S64).
- **NHL** → ready for October (fast-follow once NBA path exists; shares ESPN pattern).
---
## Slip Reader — vision-model upgrade (POST-REVENUE)
Session 9 (A1 board) shipped the zero-API Slip Reader: tesseract.js OCR
(self-hosted WASM, free) + rigid per-book layout parsers (DK/FD/MGM/Caesars)
with per-field confidence and needs_review honesty. That architecture is
deliberately conservative — it reads clean screenshots of the four big books
and refuses everything else.
The upgrade, when revenue funds it (zero-out-of-pocket rule): a vision model
(Claude-class multimodal) replaces the OCR+layout-parser pair — one call reads
ANY book, any theme, any crop, and returns structured legs with real
confidence. Costs per-call money, so it is gated on paid tiers paying for
themselves. The route contract (`POST /api/slips/parse``{ legs,
needs_review, source: 'user_slip' }`) is the stable interface; only the
extraction engine behind it swaps. Keep the never-guess rule: model output
below confidence threshold still nulls the field.
## Operating invariants (do not regress)
- Three stat_type whitelists stay in sync: `routes/analyze.js`, `routes/scan.js`,
`python/utils/validation.py`.
- A requested market MUST have a `MARKET_MAP` entry (else silent zero) AND, if
MLB, a `MLB_LOG_FIELD` entry in BOTH `featureCache` and `outcomeService` (else
no features / no settlement).
- The accuracy pill stays HONEST — "LEARNING" below MIN_SAMPLE, never a faked %.
- Pipeline alerts (ntfy) fire on success/failure/stale/overdue; the status probe
(`GET /api/internal/snapshot/status`) exposes `overdue`.