diff --git a/specs/BOARD-2026-08-07.md b/specs/BOARD-2026-08-07.md new file mode 100644 index 0000000..1ba4d09 --- /dev/null +++ b/specs/BOARD-2026-08-07.md @@ -0,0 +1,132 @@ +# The real board — read from the repo, 2026-08-07 + +Inventory only. Every line cites a file or a query. Anything unverifiable is +marked UNKNOWN rather than asserted. + +--- + +## PHASE 0 — Design / terminal + +| item | state | evidence | +|---|---|---| +| **Scanner blue-boundary format** | **DONE** | `scan/page.tsx:715-717` — *"the blue boundary channel (`--priced-out`): line · BK odds · ◆ fair"* and *"renders NEUTRAL, not amber (blue-boundary law)"*. Amber survives only as an unrelated CTA (`:983`) and a status line (`:846`). | +| **MovementStrip** | **NOT-STARTED** *(as named)* | No component by that name. Movement renders via `GradeShift.tsx`, `GameCard.tsx`, `MarketBreadth.tsx`, `FuturesBoard.tsx`. **UNKNOWN whether the spec wants a distinct strip or is satisfied by these.** | +| **THE WIRE** | **PARTIAL** | `components/vyndr/NewsWire.tsx` exists and is mounted — but only inside `ExploreHub.tsx`. No standalone wire surface. | +| **Book comparison** | **PARTIAL — built, unmounted** | `vyndr/BookComparisonPanel.tsx` + `components/BookComparison.tsx` both exist; grep of `web/src/app` returns **zero** mounting pages. Same built-but-unread class the reachability guard was written for; **not covered by that guard** (contract is grade fields only). | +| **Article media** | **NOT-STARTED** | No component. `/blog` exists. | +| **Offseason hub** | **NOT-STARTED** | No component, no route. | +| **Terminal** | **DONE — deliberately retired** | `app/terminal/page.tsx` redirects to `/dashboard`; layouts preserved unrouted in `components/intel/TerminalTemplates.tsx` (S57). Not debt. | +| **Screen conversion (S36–39 arc)** | **DONE except one** | 47 route dirs under `app/`. `RouteStub` survives in exactly **one** file: `app/notifications/page.tsx`. Every other screen has a real page. | + +**Sports surfaces that exist as pages:** `soccer` (414 lines), `desk` (160), +`intelligence` (160), `marketplace` (123). No `fight` route. + +--- + +## PHASE 1 — Sports × role + +Archetype registry (`archetypeService.ARCHETYPES`): **nba 15, mlb 15, soccer 6, +wnba 5** — all four sports have real archetype registries, not names only. + +`snapshotService.ACTIVE_SPORTS = ['mlb','nba','wnba','soccer']` — the pipeline +runs all four. + +| sport · role | state | evidence | +|---|---|---| +| **MLB · batters** | **MODELED** | The whole session. `hitsFactors` (3 proven factors, transmitting), `servedGrade`, repaired champion, settled ledger. | +| **MLB · pitchers** | **SCAFFOLDED** | `model/pitcherEngine.js` (261 lines, own FLAME/SCALPEL/SINKER archetypes) — **read by no serving code** (grep: zero non-test consumers). Strikeouts n=57 settled vs a 500 gate. Base rate repaired by the shared `getStatRows` MLB fix. | +| **WNBA** | **SCAFFOLDED** | Archetypes exist; settles via ESPN box scores (376 rows historically); no factor model. Base-rate path fixed this session. | +| **NBA** | **SCAFFOLDED, dormant** | Archetypes exist; offline (Python service down, off-season). Base-rate paths fixed dormant at `55b210c`. | +| **Soccer** | **SCAFFOLDED** | 6 archetypes, a real `/soccer` page, feature extractor exists. No factor model, no settled outcomes. | + +**Nothing but MLB batters is MODELED.** Everything else is scaffolding with a +sound base rate and no proven factors. + +--- + +## PHASE 2 — Wiring / data-integrity debt + +### `edge_pct` — the flag is half right, and the diagnosis was wrong + +**Not a scale bug.** `analyzeViaEngine1.edgePctFor` computes +`(model − line) / line`, signed by direction — arithmetically correct. It +*explodes on small lines*: a 5.5 projection against a 0.5 line is a legitimate +1000%. Live top values: **900, 860, 700, 700, 660** on **68,364 rows**. + +**Consuming surfaces: 15 backend files + 10 frontend files.** But +`edge_pct` itself reaches a user only through `alt_lines` typing in +`scan/page.tsx:64` — the grade card's `edge` is computed independently in +`gradeAdapter` via `computeEdge`. So the blast radius is smaller than the file +count implies. + +**`ev_pct` DOES render** — 5 frontend files (`PriceTriplet`, `GradeResultCard`, +`LiveHeroProp`, scan page + route). The "ev_pct renders nowhere" flag is **stale**. +45,125 rows carry it. + +**Classification: PARTIAL — a real display defect (a 900% edge is not a sentence +we can defend), not a broken computation.** + +### `opp_rank_stat` + +`refreshTeamStats` is wired into `snapshotService:361`. **UNKNOWN whether it +populates in production** — not verifiable from the repo, needs a live probe. + +### A-emit + +**Resolved.** `servedGrade.UNISSUABLE = ['A+','A','A-']`; post-cutover serving +cannot emit one. Historical snapshot rows still carry engine1 A's — that is +retired data, not live behaviour. + +### Other + +| item | state | +|---|---| +| `VYNDR_INTERNAL_KEY` | present in `app.js`, `preflight.js`. **Rotation status UNKNOWN** from the repo. | +| void / DNP handling | handled in `ledgerService` (`:64`, `:698`) — absence means DNP/postponed/not-final. **The ~9% rate is UNVERIFIED** here. | +| **Guard coverage gap** | reachability contract covers **grade fields only** — 0 references to `edge_pct`/`ev_pct`. Book comparison and other unmounted components are **not** guarded. | + +--- + +## PHASE 3 — THE BOARD, ordered (half-done first) + +| # | item | lane | state | serving-path? | +|---|---|---|---|---| +| 1 | **Book comparison — built, unmounted** | design | PARTIAL | **N** | +| 2 | **`edge_pct` display defect (900%)** | integrity | PARTIAL | **Y** | +| 3 | **THE WIRE — only inside ExploreHub** | design | PARTIAL | **N** | +| 4 | **MLB pitchers — engine unwired** | sports | PARTIAL | **Y** | +| 5 | **`/notifications` RouteStub** | design | PARTIAL | **N** | +| 6 | Guard coverage → non-grade surfaces | integrity | NOT-STARTED | **N** | +| 7 | Article media | design | NOT-STARTED | **N** | +| 8 | Offseason hub | design | NOT-STARTED | **N** | +| 9 | MovementStrip *(if distinct from GradeShift)* | design | UNKNOWN | **N** | +| 10 | WNBA / NBA / Soccer factor models | sports | NOT-STARTED | **Y** | +| 11 | `opp_rank_stat` prod population | integrity | UNKNOWN | **Y** | +| 12 | Internal-key rotation | ops | UNKNOWN | **N** | + +### Accrual sensitivity + +**Isolated — buildable now without touching the re-audit clock (7 items):** +1, 3, 5, 6, 7, 8, 9 — all design/guard work, zero serving-path contact. + +**Serving-path — will muddy the accruing repaired-champion dates (5 items):** +2, 4, 10, 11, and any model work. Every one changes what a snapshot writes, so +rows produced after the change are not comparable to rows before it. **If any of +these ship, the eligible-date clock arguably restarts** — the same reasoning that +voided the shadow duel. + +**#2 (`edge_pct`) is the sharpest tension on the board:** it is a real honesty +defect a user can see, and fixing it touches the serving path mid-accrual. + +### The clock, today + +``` +eligible dates: 0 — no settled rows carry engine1@2026-08-07-fullwindow + calibration_refit 0/10 WAITING (~2 weeks) + hits_factor_lift 0/10 WAITING (~2 weeks) + prior_verdict_reaudit 0/14 WAITING (3+ weeks) + rbi_lineup_slot_gate 0/14 WAITING (3+ weeks) +``` + +Two tracks are now visible: **modeling is date-blocked**; **seven design/guard +items are buildable today with no clock impact.**