Session 44: Make it visible — VYNDR archetype names, grade intel, schedule fix, landing page (2061 tests)

Frontend + wiring only. Wires existing backend into the pages users see.

- VYNDR Original archetype rename (41) across archetypeService.js + lib/
  archetypes.js + ArchetypeBadge, each keeping legacyName (resolves stale data).
  Judge -> BOMBER. Old POWER PULL slot -> WHIFF strikeout-artist pitcher.
- BACKEND_HANDOFF.md: canonical frontend<->backend data contract.
- Grade card intel: scan/page.tsx now forwards the engine's intel fields
  (season_avg/form/usage/matchup_grade/archetype/...) into mapScanToGradeResult
  -> STAT CONTEXT + VYNDR INTELLIGENCE sections populate. The chain already
  preserved them (tierGating + /api/scan spread); the page was dropping them.
- Schedule freshness: slateAdapter.isRelevantGame drops completed games >24h
  old; Slate.filteredGames applies it. (TTL already 60s.)
- Landing: Features.tsx rewritten to user-facing copy (no Point-biserial/Zone
  14/ABS/Phi-coefficient).
- Depth chart Next proxies added (/api/stats/lineup|depth|cascade) - were 404.
- GameCard swap DEFERRED (Kev): legacy on-demand card stays as a bridge until
  the snapshot pipeline populates the grades cache; vyndr/GameCard swaps in then.

Backend 2045 -> 2061 tests (+16), 167 suites. Web build clean (exit 0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kev
2026-06-18 20:15:38 -04:00
parent 80683e71b4
commit 7969a4971a
26 changed files with 766 additions and 302 deletions
+27
View File
@@ -386,6 +386,33 @@ Built from the Claude Design "VYNDR Player Intelligence" bundle.
`matchesTeam` must guard empty names (`t.includes('')` is always true) — and
the schedule `find` checks `g.home`/`g.away`, not the game object.
## VYNDR Original Archetypes + Make-It-Visible (Session 44 — non-obvious)
- **Archetype names are VYNDR Originals** (TORCH/BOMBER/ALPHA/…), NOT the old
descriptive labels. The registry keys in `archetypeService.js` + the map keys
in `lib/archetypes.js` are the new names; each carries `legacyName`/`legacy`
(the old label, NEVER displayed). `getArchetype()` + `archetypeInfo()` +
`badgeStyle()` resolve legacy names → the canonical VYNDR name (defends stale
cached data). The `classify()` scorer objects use the new keys too — if you
edit a threshold, use the new key. Full mapping is in `BACKEND_HANDOFF.md`.
- **MLB power merge:** there's ONE power archetype (BOMBER) — it fires for any
high-HR bat (incl. high-K sluggers like Judge → BOMBER). The old POWER PULL
slot became WHIFF (strikeout-artist pitcher). Don't re-split power.
- **`BACKEND_HANDOFF.md`** (repo root) is the canonical frontend↔backend data
contract — update it in the same commit when an endpoint/component shape changes.
- **Grade-card intel gotcha:** the engine→tierGating→/api/scan chain already
preserves the intel fields (everything spreads `...result`/`...data`). The bug
was `scan/page.tsx` passing a hardcoded field subset to `mapScanToGradeResult`
— it must forward season_avg/last10_avg/form/usage/matchup_grade/rest/archetype
/archetype_blend/prop_dna (and `ScanResponse` must type them) or the card
sections stay hidden.
- **Stale games:** `slateAdapter.isRelevantGame(game, now)` drops completed games
>24h old; `Slate.filteredGames` applies it. Schedule TTL is 60s.
- **GameCard swap is DEFERRED** (Kev's call): the live Slate keeps the legacy
on-demand "Read" card as a bridge until the snapshot pipeline lands. The
on-demand grade model is being retired for a pre-graded snapshot model; the
vyndr/GameCard (playerStrips/pitchers) is built for that and swaps in then.
Don't swap it before the grades cache is populated (cards would be blank).
## Active Skills
- vyndr-voice (all user-facing output)
- prop-analysis (grading methodology)