STATE: retention clock proven ticking via induced cron entrypoint

This commit is contained in:
Kev
2026-07-20 02:06:43 -04:00
parent 5a5e37e32e
commit e46c88e364
+35
View File
@@ -133,6 +133,41 @@ exist locally; harmless, the data restores completely.
--- ---
## 🟢 RETENTION CLOCK TICKS ON ITS OWN (2026-07-20 06:05 UTC)
Induced the REAL cron entrypoint rather than waiting for 14:00 UTC.
- **Cron capture needed NO wiring — verified in code.** `snapshotScheduler`'s
tick calls `runAll` = `snapshotService.runAllSnapshots``runSnapshot` per
sport → `gradeAndCacheSlate``onGraded` → retention. **The scheduled and
manual paths are the same function.** Nothing had been captured only because
no slot had fired since retention deployed (~02:55; slots 14/19/22/1/3).
- **PROVEN by induction:** `POST /api/internal/snapshot/all` (= `runAllSnapshots`,
the exact function the tick calls) wrote cycles at **06:03:23 mlb** and
**06:05:09 wnba**, 50 rows each, `cycle_hour_utc=6`, features 50/50.
*(The HTTP request gateway-timed-out at ~2 min; the job completed server-side —
verified in the DB, not from the response.)*
- **`archetype` FIXED — 50/50 on MLB** (was 0/100). Retention still COLLECTS at
grade time (only moment features exist) but now PERSISTS after enrichment via
`retentionService.mergeEnrichment`, which fills ONLY archetype/team/opponent
and never rewrites grade-time features or model output (test-locked).
- **🔶 `team`/`opponent` STILL NULL — upstream, not the merge.** The ENRICHED
grades themselves carry `team:null` (verified live: 0/25 with team, 25/25 with
archetype). `resolvePlayerStats` doesn't return `stats.team` for MLB, and
enrichment never sets `opponent` at all. Fixing that is an upstream change,
deliberately not made under this order.
- **WNBA archetype is null** — honest absence: WNBA stats don't resolve (Python
service offline), so there is nothing to classify from.
- **ZERO-WRITE ALARM ARMED** — `opsWatch.retentionZeroWriteAlarm` pages at
missed-snapshot severity when a slot GRADED props but retention wrote fewer
rows than the slate. `runSnapshot` now returns `retentionRows` so the tick can
evaluate it. Retention is best-effort by design, so a broken write is silent by
construction; this is the counterweight. Verified quiet on a healthy run
(gradeCount 25 → retentionRows 50).
- **INTRADAY DEFERRED (Phase 4).** `intradayRefreshService` calls
`analyzeViaEngine1` DIRECTLY — it never goes through `gradeAndCacheSlate`, so
there is no `onGraded` hook to reuse. Capturing it needs its own ctx +
snapshot_id + persist path and would ~5× row volume. Not small; not done.
- Outcome stamping still NOT implemented (depends on the settlement fix).
## 🟢 RETENTION LIVE — model_snapshots capturing (2026-07-20, migration 025 applied) ## 🟢 RETENTION LIVE — model_snapshots capturing (2026-07-20, migration 025 applied)
Phase 2 priority zero. **History now compounds from tonight.** Spec: Phase 2 priority zero. **History now compounds from tonight.** Spec:
`specs/snapshot-retention.md`. `specs/snapshot-retention.md`.