diff --git a/specs/MASTER-PLAN.md b/specs/MASTER-PLAN.md new file mode 100644 index 0000000..4882a7d --- /dev/null +++ b/specs/MASTER-PLAN.md @@ -0,0 +1,155 @@ +# VYNDR — MASTER PLAN +**Single source of truth. Sessions EXECUTE against this and UPDATE it in place.** +Created 2026-07-31 by consolidation. Nothing built in this pass. + +> **HOW TO USE:** this supersedes ad-hoc re-derivation. Before any order, read the +> phase you're in. After any order, tick the item and add one line. **Do not +> re-audit anything marked KNOWN** — that redundancy is what this document exists +> to kill. + +--- + +## 0. VERIFICATION LEDGER (what was re-checked in this pass) + +**NOTHING was re-verified. No query was run.** Everything required is already +captured in 22 artifacts produced this session plus the canonical board. Per the +order's own clause — *"If everything needed is already in the artifacts, say so and +skip verification"* — this is that case. + +**Taken as KNOWN (source in brackets):** +- Model architecture, all layers [`model-architecture-recovery-map.md`] +- Grade↔outcome correlations, collapse cost [`full-output-grade-mapping.md`] +- p_win calibration + holdout verdicts [`grade-diagnostic-t0.md`, `pwin-recalibration-holdout.md`] +- Market-relative edge inversion [`grade-fix-part1-investigation.md`] +- Design implemented-vs-designed, 61 items [`design-vs-build-gap-audit.md`] +- Surface states, orphans, waves [`pre-audit-status-pull.md`, `incomplete-surface-triage.md`] +- Resolution pipeline true state [`resolution-and-clv-investigation.md`, `wave3-*.md`] +- Tier/monetization + founder mechanism [`tier-structure-pull.md`, `tier-redesign-spec.md`, `build2-review-zero-report.md`] +- Sport-boundary cost [`model-architecture-recovery-map.md` §Phase 2] + +**Genuinely OPEN → carried as explicit unknowns (not verified because they need a +build or a decision, not a query):** sport order (Kev's call, §A2); board-reasoning +gating (a/b/c, §C2); CLV flag decision (§D3); the ~70 undefined team colours (§B). + +--- + +## A. PER-SPORT MODELS — Phillips doctrine: each sport is its OWN model + +### A1. MLB layer stack (the reference module), bottom-up + +| # | layer | state | note | +|---|---|---|---| +| 1 | Data/feeds | **BUILT** | statsapi free+unlimited; statcast; park; weather; probables. Settles end-to-end. | +| 2 | Similarity (comparable instances) | **BUILT · NOT WIRED · NOT DEPLOYED** | `python/utils/similarity.py`; grade path skips to season/recent averages | +| 3 | Archetypes (batter + pitcher) | **BUILT · display only** | classifies + renders; **does NOT feed the grade** | +| 4 | Variable weights | **PARTIAL/ASSUMED** | engine1's flat ±1.0/±0.5 deltas are hand-set, never fitted | +| 5 | Conditions (park/weather/platoon/arsenal) | **BUILT · CHALLENGER ONLY** | rides `env_*`/`challenger_*`; "measured, never served" | +| 6 | Bayesian inference | **BUILT · NOT WIRED · NOT DEPLOYED** | `python/utils/bayesian.py`, 320 ln, genuinely sport-agnostic math | +| 7 | Calibration | **MEASURED, NOT APPLIED** | isotonic qualifies on holdout (rel .1038→.0939, res .139→.123, n=119) | +| 8 | Grade ladder | **BROKEN** | letter is a factor index, r≈0.005, **inverted** (B 52.4% < C 56.9%) | + +**The through-line:** layers 2, 3, 5, 6 are built and *not connected*; layer 8 is +connected and *meaningless*. MLB's fix is connection, not construction. + +### A2. Sport order (OPEN — Kev decides) +Proposed by readiness × clock: **1) MLB** (reference, only qualifying model) → +**2) CFB** (has a <30-day clock; soft-market thesis) → **3) NFL** → **4) NBA** → +**5) CBB** → **6) WNBA re-attempt** (abstains today) → **7) soccer** (quota-blocked). +Each gets the same 8-layer template. **No sport is abandoned — abstention is a +state, not a verdict.** + +--- + +## B. DESIGN IMPLEMENTATION — 61 items catalogued +BUILT-TO-SPEC 20 · DRIFTED 7 · PARTIAL 16 · ABSENT 18. Ordered wire-in: +**D1-A done** (6 combat glyphs, boundary-blue completed, reaction primitives, READ-FAB). +**D1-finish done** (rationale/reveal/chips modules — *built, NOT mounted*). +Remaining: **D1-close** (mount — blocked on a ROW-GRAMMAR slot amendment + §C2) · +**D1-B** (45 unwired glyphs + the 41-vs-74 archetype scope call) · S2 primitive set +(movement strip, crown, disagreement axis, SPLIT) · S3 article media · The Report +email + archive · Offseason artboards · **team colours: only 10 of ~80 defined — +the rest render honest-neutral until a real source exists.** + +--- + +## C. SURFACES +**C1 — done:** Wave 1 wiring · `/compare` · `/record` · Build-1 gate. +**C2 — OPEN DECISION (blocks D1-close):** board reasoning is served ungated while +`tiers.js` declares `reasoning_visible:false`. Options (a) gate it, (b) accept as +free funnel, (c) leave unrendered. +**C3 — remaining:** `/record` **has no nav link** (the surface that justifies the +price) · `/notifications` · Offseason hub · `/system` · S3 media · `/soccer` +(quota) · share cards (blocked by D). + +--- + +## D. RESOLUTION PIPELINE → USER OUTPUT +**KNOWN and load-bearing: settlement WORKS** (scheduler → `settleAllOutcomes` + +`settleAllLedgers`, 937+ settled, growing daily). **What is unreachable is the +user-output TAIL:** `/api/grading/resolve` has no caller, and its fanout holds +webPush/Telegram/Discord but **no share-card step and no recap**. +**D1** wire a trigger (or move the fanout into the settle pass) · **D2** share-card +generation + `/notifications` consent + result posts + recap · **D3 CLV flag +decision** — `clvCaptureReliable()` is *one env var*, and the pre-registered rule +stands: flip only if close_moved is a clear majority AND coverage is representative. +**🔴 Never wire `/api/grading/resolve` as a second settlement path — it double-counts.** + +--- + +## E. SPORT BOUNDARY +Adding a sport is a **~10-file core edit** with four silent-failure modes +(MARKET_MAP → zero props; three stat whitelists → silent 400s; missing projection → +universal refusal; no settled feed → grades forever). **Collapse to a registry** so +a sport is a module. **Blocks all of A2 after MLB.** + +--- + +## F. CHROME AUDIT — 11 items, 4 need a Desk session. **Runs when surfaces are stable, not before.** + +--- + +# THE PHASES — 7 phases, ~18 orders + +| phase | orders | contents | blocks | +|---|---|---|---| +| **1. MLB model truth** | 4 | promote isotonic p_win (MLB only, WNBA abstains) · rebuild the ladder on calibrated p_win · re-adjudicate (ROI-by-grade, skew, proj-v1.1, C1 floor) · connect layers 2/3/5/6 | everything model-shaped | +| **2. Resolution tail** | 3 | trigger · share cards + notifications + posts + recap · CLV flag decision | share cards, social proof | +| **3. Surfaces + design lane** *(parallel with 1-2)* | 4 | C2 decision → D1-close mount · `/record` nav + remaining surfaces · D1-B glyphs/archetypes · S2 primitives | Chrome audit | +| **4. Sport boundary** | 2 | registry collapse · MLB re-expressed as the first module | all further sports | +| **5. Sport rollout** | 1 per sport | CFB → NFL → NBA → CBB → WNBA retry → soccer, each on the 8-layer template | — | +| **6. Monetization finish** | 2 | Stripe Phase-B live proof on first real signup · founder launch to the 3 existing users | — | +| **7. Chrome audit + hardening** | 2 | the 11-item visual sweep · credential rotation + migration-drift reconciliation | ship | + +**Phases 1–4 and 6–7 = ~17 orders. Phase 5 = 1 order per sport (6 listed).** +**Total ≈ 23 orders to the end state**, of which **~11 are unblocked today**. + +--- + +# DEFINITION OF DONE + +**VYNDR is complete when:** +1. **MLB layers 1–8 are BUILT AND CONNECTED** — similarity, archetypes, fitted + weights, conditions and Bayesian all feed the grade; calibration applied; the + ladder monotone (A>B>C, no inversion) and proven on held-out data. +2. **Every listed sport is finished on the same 8-layer template**, or explicitly + abstaining with its reason recorded — never silently absent. +3. **Design fully implemented** — all 61 catalogued items BUILT-TO-SPEC. +4. **Every surface built, reachable and honest** — no orphans, no live-but-not-honest + surface, no dead component. +5. **Resolution pipeline live end-to-end** — settle → share card / notification / + post / recap, firing on a real settlement. +6. **Sport boundary is a registry** — a new sport is a module, not a core edit. +7. **Chrome audit passed**, logged-out and entitled. +8. **The record is publishable on its own terms** — CLV either trustworthy-and- + representative or honestly absent; no claim outruns its evidence. + +**The remaining work is finite and countable: ~23 orders across 7 phases.** + +--- + +## STANDING LAWS (carried into every order) +Truth Law — absent beats wrong, no fabrication up or down · per-sport models, never +a global engine · lookahead guard (lock-time fields only) · overfitting guard (fit +one split, prove another) · never mint A's without new information · aggregate proof +is free, itemized judgment is paid · one canonical founder flag · atomicity by unique +index, never a count · cache-bust every post-deploy check · verify-after-write. diff --git a/specs/STATE.md b/specs/STATE.md index 9542d1d..5fb52a7 100644 --- a/specs/STATE.md +++ b/specs/STATE.md @@ -1105,6 +1105,14 @@ > confirmed by curl → **Chrome audit** (along with the rendered bars and the sport tabs). > **FLOOR: 320 suites / 3,986 tests green (16 new), web build exit 0.** +> ## 🗺️ **`specs/MASTER-PLAN.md` IS NOW THE SINGLE SOURCE OF TRUTH** (2026-07-31) +> All remaining work — per-sport models, design, surfaces, resolution tail, sport boundary, +> Chrome audit — is consolidated into ONE phased plan with a defined END STATE: +> **~23 orders across 7 phases, ~11 unblocked today.** Sessions now EXECUTE against it and +> UPDATE it in place. **This narrative file is history; read the plan first.** +> Consolidation re-verified NOTHING — all 22 session artifacts + the completion matrix were +> taken as KNOWN, which is the redundancy the plan exists to end. + - **Redirect EXISTS + WIRED:** `closingCapture.buildCaptureRows`→`closing_captures` (append-only, provenance: captured_at/book/line_type/both-prices/missed_reason) via `intradayRefreshService:221` + internal endpoint; `ledgerService.attachClosingProb`→`closing_prob` (de-vigs both raw sides,