STATE: Session 72 — Tier-1 live, Tier-2 harness forward-accrual (no historical OOS)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCNgGSt5qvcLxaeQqa7Zpj
This commit is contained in:
+72
-1
@@ -1,5 +1,5 @@
|
||||
# VYNDR — STATE OF THE WORLD
|
||||
### As of `f2da9dd` (main, DEPLOYED), 2026-07-21. This file opens every future session. **Start with the CURRENT STATUS + OPEN ITEMS block below.**
|
||||
### As of `927e867` (main, DEPLOYED), 2026-07-21. This file opens every future session. **Start with the CURRENT STATUS + OPEN ITEMS block below.**
|
||||
|
||||
---
|
||||
|
||||
@@ -131,6 +131,77 @@ exist locally; harmless, the data restores completely.
|
||||
`specs/snapshot-retention.md` (Phase 2 report + schema) ·
|
||||
`specs/audit-data/grade-collapse.md` · `specs/audit-data/gate-simulation.md`.
|
||||
|
||||
---
|
||||
|
||||
# 🟢 SESSION 72 — TIER-1 MAPPINGS LIVE + TIER-2 HARNESS (2026-07-21)
|
||||
|
||||
## 🔴 PHASE 0 GATE — NO HISTORICAL OOS IS POSSIBLE (and why)
|
||||
`statcast_aggregates` is **overwritten nightly by design** (Layer 1 = full
|
||||
re-pull upsert) → season-TO-DATE only, **no point-in-time history**. Classifying
|
||||
a player for a Jul-15 game with today's aggregate feeds in Jul 15–21 →
|
||||
**look-ahead leakage**, making any "out-of-sample" verdict worthless.
|
||||
**→ The harness reads the archetype vector RETAINED at grade time (S70
|
||||
instrument) and runs FORWARD-ACCRUAL.** Reported, not worked around.
|
||||
*(If point-in-time archetypes are ever wanted, Layer 1 must retain a dated
|
||||
snapshot per refresh — a real schema change, not a query.)*
|
||||
|
||||
## Canonical names — asserted, not assumed
|
||||
Every mapping references the axis keys the classifier **emits**; a test walks
|
||||
both maps against `BATTER_AXES`/`PITCHER_AXES`. **A non-existent key would look
|
||||
wired and never fire** — that's the failure this guards.
|
||||
|
||||
## TIER 1 — LIVE (tautological, directional, MLB-only)
|
||||
| Axis (canonical) | Labels | Stat | Dir |
|
||||
|---|---|---|---|
|
||||
| `strikeout` | PUNCHOUT / WHIFF | strikeouts | ↑ |
|
||||
| `ground_ball` | SINKER / SEAM | home_runs_allowed | ↓ |
|
||||
| `fly_ball` | FLY BALL / ELEVATOR | home_runs_allowed | ↑ |
|
||||
| `control` | SURGEON ARM / PINPOINT | walks_allowed | ↓ |
|
||||
| `power` | SLUGGER / BOMBER | total_bases, home_runs | ↑ |
|
||||
| `contact` | TECHNICIAN / SURGEON | hits ↑, strikeouts ↓ | |
|
||||
| `patience` | GRINDER / SNIPER | walks | ↑ |
|
||||
|
||||
Average player untouched; UNDER mirrors OVER exactly.
|
||||
**SPEED (BURNER→SB) is HONESTLY ABSENT** — SB never reached the aggregate store,
|
||||
so Layer 2 shelved the axis. `BATTER_MAP.stolen_bases = {}`, not invented.
|
||||
|
||||
## TIER-2 HARNESS — `src/services/mappingHarness.js`
|
||||
Three hurdles a plausible-but-worthless mapping fails:
|
||||
1. **MARGINAL, not correlation** — scores the archetype against the
|
||||
**projection's RESIDUAL** (`outcome − p_win`). If the projection already
|
||||
knows it → `REJECT (redundant)`. **This is the double-counting catch.**
|
||||
2. **OOS split by DATE, never random** — rows from one game share pitcher/park/
|
||||
lineup; a random split leaks.
|
||||
3. **Direction validated from held-out data; a contradicted sign is REJECTED,
|
||||
never silently flipped** (flipping = fitting noise).
|
||||
Floors: `MIN_ROWS 200 · MIN_HELD_OUT 60 · MIN_EFFECT 0.02` → else `INSUFFICIENT`.
|
||||
|
||||
**Lifecycle encoded: `nominated → live → claimed`.** A survivor RUNS LIVE and is
|
||||
measured; **only the quantified public claim waits.** Nothing sits dark.
|
||||
|
||||
## Real candidate, end-to-end
|
||||
`GROUND-BALL → hits_allowed` → **INSUFFICIENT — 0 / 200 settled rows**, because
|
||||
no settled row carries `p_win` yet (S70 instrument starts at the next new lock).
|
||||
Correct and expected verdict.
|
||||
|
||||
## Gotcha worth keeping
|
||||
My first synthetic fixture **aliased the carrier selector against the outcome
|
||||
draw** and manufactured a 0.038 effect where zero was injected. The harness
|
||||
rejected it correctly — but via the SIGN reason, not redundancy, which is how I
|
||||
found the fixture bug. Draw now uses a coprime modulus. *Lesson: when a harness
|
||||
gives the right verdict for the wrong reason, check the fixture.*
|
||||
|
||||
## Still blocking everything downstream
|
||||
**No settled row carries `p_win`/`p_win_challenger` yet.** Tier-1 adjusts real
|
||||
projections now, but neither it nor any Tier-2 candidate can be evaluated until
|
||||
volume accrues. Verify:
|
||||
```sql
|
||||
select count(p_win) champion, count(p_win_challenger) challenger,
|
||||
count(*) filter (where challenger_delta <> 0) moved
|
||||
from ledger_entries where user_id is null;
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 🟡 SESSION 71 — LAYER 3 STEP 2: CHALLENGER PROJECTION (2026-07-21)
|
||||
|
||||
Reference in New Issue
Block a user