diff --git a/specs/free-proof-surface-review-zero.md b/specs/free-proof-surface-review-zero.md new file mode 100644 index 0000000..35fece3 --- /dev/null +++ b/specs/free-proof-surface-review-zero.md @@ -0,0 +1,82 @@ +# FREE PROOF SURFACE — REVIEW ZERO (report; surface NOT built) +2026-07-31. Nothing built. `git diff` = docs only. + +The order's premise is that this is assembly over existing honest aggregates ("Code's *cheap* +claim — verify it"). **Verified: it is NOT cheap, and three of the four things the surface is +supposed to lead with have no data source today.** Building the page anyway would mean +inventing numbers — the one thing the order forbids most explicitly. + +## 0.1 — FILTERABILITY: **THE ENDPOINTS ARE NOT FILTERABLE. VERIFIED BY PROBE.** +`/api/ledger/accuracy` accepts nothing. Live: + + ?sport=mlb -> overall.total 937 + ?sport=wnba -> overall.total 937 + ?window=7 -> overall.total 937 + +Identical payload every time — the params are ignored (the `req.query.sport/tier` reads at +`routes/ledger.js:61-63` belong to a DIFFERENT route, not `/accuracy` at `:68`). + +**What CAN be sliced today:** `/api/accuracy` returns a real **`sports` map** (`mlb`, `wnba`) +each with its own `sample`/`byGrade`/`min_sample`, and `/api/ledger/model` returns `by_tier`. +So **sport and tier are servable client-side from existing payloads.** +**TIME WINDOW IS NOT.** `window_days` is fixed at **30** inside `getModelAggregate`; there is no +param and no historical series. **"Accuracy over time" has no data source** — it needs a backend +param (or a stored daily series), which is a build, not assembly. + +## 0.3 — 🔴 CLV CANNOT LEAD WITH A NUMBER. THE CANONICAL AGGREGATE RETURNS NULL. +CLV *is* exposed — `/api/ledger/model` → `aggregate` — and here is the live payload: + + settled 937 · hits 547 · misses 390 · hit_pct 58 · pending 91 + clv_sample 937 · clv_beat 34 · clv_faded … · clv_flat … + beat_close_pct = null ← the number the surface was to lead with + clv_distribution = null + window_days 30 · min_sample 20 + +`beat_close_pct` and `clv_distribution` are **null by design**: `ledgerService` publishes them +only when `clvCaptureReliable() && settled >= 20 && clv_sample > 0`. The reliability guard is +false — the capture is still the starved instrument the 07-28 repair improved but did not +finish (closing_prob 59→406 of ~1,250 rows). + +**So the honest CLV headline today is an ABSENCE, not a percentage.** And the temptation to +avoid is precise: `clv_beat / clv_sample` = **34/937 = 3.6%** is computable and would be +**wrong** — it is null *because the instrument is not trustworthy*, not because nobody did the +division. **Publishing 3.6% as "beat close" would be exactly the marketing fabrication this +order forbids.** CLV leads with *"tracking since … · building · not yet publishable"* and names +why — which is defensible, but it is a different surface from the one specced. + +## 0.2 — HONEST-RECORD LAWS: **ALREADY HONORED. PRESERVE, DON'T REBUILD.** +`/api/ledger/accuracy` buckets: **A `{hits:1,total:2,pct:null}` · B `{309/512, pct:60}` · +C `{235/413, pct:57}` · D `{1/5, pct:null}` · F `{1/5, pct:null}`.** Thin tiers already return +**`pct: null`, not a rounded number** — the hollow law is enforced at the source. **C at 57% is +genuinely below B at 60%**, which is the honest, unflattering truth and must be shown as-is. + +## 0.4 — CALIBRATION CURVE: **NO DATA SOURCE.** +The pack's S4 curve needs *claimed vs actual per probability bucket*. `clv_distribution` is null, +and there is **no claimed-vs-actual endpoint at all**. The 07-26 calibration diagnosis was a +one-off read-only measurement, never wired to a served surface. **The curve cannot be assembled +from anything live** — it is a build. + +## WHAT IS ACTUALLY BUILDABLE NOW (honest assembly, no new metrics) +1. **Tier hit-rates by sport** — real: overall 937 @ 58%, plus per-sport `mlb`/`wnba` splits and + `byGrade` buckets **with the existing `pct:null` hollows preserved**. +2. **Sport + tier filtering** — client-side over `/api/accuracy`'s `sports` map. No backend work. +3. **The capped 3-call rotating sample** — already served on the snapshot (Build 1), resolved-only. +4. **Honest state copy** — "tracking since · n building · promising, accruing", and the CLV panel + as an explicit *not-yet-publishable* state naming the reliability guard. + +## WHAT NEEDS A BUILD FIRST (and should be its own order) +- **CLV as a leading number** ← blocked on capture reliability, not on presentation. +- **Accuracy over time** ← needs a windowed param or a stored daily series. +- **Calibration curve** ← needs a claimed-vs-actual endpoint. + +## RECOMMENDATION +Ship the surface as **tier-record-forward with an honest CLV "building" panel**, not +CLV-forward — because CLV-forward with a null cannot lead, and CLV-forward with 3.6% would be a +lie. Then unblock CLV (capture reliability) and add the curve/time-series as their own orders. +That keeps the strongest claim of the premise intact — *a real thin honest record +out-credibilizes a fake fat one* — without inventing a single number. + +## TAGS +VERIFIED: filter params ignored (probed); `beat_close_pct`/`clv_distribution` null on the live +canonical aggregate; hollow law already enforced at source; no calibration endpoint exists. +CANNOT DETERMINE: none. **BLOCKED: CLV-forward lead, accuracy-over-time, calibration curve.**