docs: tier structure recorded — free board uncapped, board reasoning ungated vs config intent

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
This commit is contained in:
Kev
2026-07-31 06:41:15 -04:00
parent 844ab96f21
commit c6ef4cfb2b
+37
View File
@@ -930,6 +930,43 @@
> **⚠️ HONEST SCOPE NOTE: the three modules are built and unit-locked, but MOUNTING them into the
> live row components is a follow-up** — the visual result belongs in the Chrome audit.
> ## 💰 TIER STRUCTURE PULL 2026-07-31 (report-only) → **`specs/tier-structure-pull.md`**
> Real numbers from config + live ANONYMOUS prod probes. Nothing changed.
> **THE FREE BOARD IS UNCAPPED.** `/api/snapshot` applies **no count limit** — the only gate is
> `stripModelPrice(grades, tier)` (`routes/snapshot.js:106-107`); no slice, no volume branch.
> **Live anon right now: MLB 5 · WNBA 25 = the entire board.** The **3 scans/day** cap
> (`config/tiers.js` free) rations the **SCAN path only**.
> **Free sees the grade in full** (`grade_visible: true` on every tier): letter · confidence ·
> `edge_pct` · **and VYNDR's own `projection`**. **Edge fields are correctly stripped** —
> `p_win`/`ev_pct`/`model_odds`/`value`/`takeable` **ALL absent** from the anon payload, with
> `model_price_locked: true` so the card shows a lock teaser, not an absent leg. **That half of the
> gate works exactly as designed.**
> **🔴 THE HEADLINE — THE TWO PATHS DISAGREE ON REASONING.** **SCAN redacts it**
> (`tierGating.js` → `lockReasoning` + `lockKillConditions` + `tier_gated` + upgrade hint, driven by
> `free.reasoning_visible: false`). **BOARD serves it in full** — `snapshotGating.MODEL_FIELDS` is
> `[model_odds, p_win, ev_pct, value, takeable]` and **`reasoning` is not in the list**. Verified
> live, anonymously: full `reasoning.summary` *("Natasha Cloud is averaging 5.8 assists over his last
> 5 games…")* **plus a kill condition WITH its reason**.
> **INTENT — the config says OVERSIGHT, not funnel.** `config/tiers.js` declares
> **`free: { reasoning_visible: false }`** with the comment *"blurred — frontend renders
> tier-locked."* Scan implements it; the board never got the same treatment (`MODEL_FIELDS` was
> written in S67 to close the *model-price* leak and lists only the five price-derived fields).
> **A funnel would be declared in config, not contradicted by it.** ⚖️ **Counterweight flagged for
> Kev:** board reasoning is genuinely good marketing and the whole data layer is already free, so
> closing it is a **monetization TIGHTENING — a business call, not a fabrication fix.**
> **FREE IS A REAL DATA AGGREGATOR, not just a limited graded view** — schedule · per-book lines ·
> player stats · streaks · hot lists · team hubs · public record, **all public + uncapped** (probed
> live 200).
> **PAID AS CODED:** **analyst $14.99 · desk $44.99** (`checkout.js:4`). **Analyst = unlimited reads**;
> Desk differentiates on CAPABILITY (alt ladder · Kelly · portfolio · engine2), not on rationing.
> `africa` ($4.99) is defined but **activation blocked on a DB CHECK constraint**. `api_access` is
> **false on every tier**. Deliberate carve-out: **`book_odds`/`fair_odds` pass through on ALL tiers** —
> *the de-vigged fair number is the hook and is NEVER the paywall; only our own price gates.*
> **THE LINE TODAY, one sentence:** free already gets the **entire graded board + the model's
> projection + (on the board only) the model's full explanation**; paid buys the **price/edge math**,
> unlimited scans, and Desk capabilities. **The one gate that is declared but not enforced is board
> reasoning** — which is exactly the decision the D1-close rationale mount is waiting on.
- **Redirect EXISTS + WIRED:** `closingCapture.buildCaptureRows``closing_captures` (append-only,
provenance: captured_at/book/line_type/both-prices/missed_reason) via `intradayRefreshService:221`
+ internal endpoint; `ledgerService.attachClosingProb``closing_prob` (de-vigs both raw sides,