docs: tier redesign spec recorded (gate discriminator exists; counter is display-only; base is 3 users)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
This commit is contained in:
@@ -706,3 +706,21 @@ Backend untouched. Three pure modules, unit-locked:
|
|||||||
|
|
||||||
318 suites / 3,961 tests green, web build exit 0. **Mounting the modules into the live row components
|
318 suites / 3,961 tests green, web build exit 0. **Mounting the modules into the live row components
|
||||||
is a follow-up**; the visuals go to the Chrome audit.
|
is a follow-up**; the visuals go to the Chrome audit.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# TIER REDESIGN SPEC — 2026-07-31 → `specs/tier-redesign-spec.md`
|
||||||
|
|
||||||
|
Option 2 (settled-free / live-paid) designed, not built. **FREE** = full data aggregator + the
|
||||||
|
**complete settled record** (letter, reasoning, edge, outcome — browsable) as the proof hook.
|
||||||
|
**ANALYST $14.99→$24.99** = tonight's live grades + reasoning + edge. **DESK $44.99→$59.99** = +
|
||||||
|
alt ladder, Kelly, portfolio, engine2.
|
||||||
|
|
||||||
|
**The gate already has its discriminator:** `/api/snapshot` merges per-grade `outcome` (live WNBA:
|
||||||
|
5 of 25 settled), so `outcome != null ⇒ free`, `null ⇒ paid`, with no new pipeline. Filter whole
|
||||||
|
grades server-side, never infer resolution from time, fail closed to LIVE.
|
||||||
|
|
||||||
|
**Two findings that reshape the plan:** (a) founder pricing is gated by **code + expiry, not seat
|
||||||
|
count** — the real counter (`/api/founders/count`, live 0/100) only displays and is cached 300s, so
|
||||||
|
making it a transactional gate is a genuine build; (b) the user base is **3 free, 0 paid**, so the
|
||||||
|
migration is a courtesy note, not a mass event — effort belongs on the settled-record proof surface.
|
||||||
|
|||||||
@@ -967,6 +967,46 @@
|
|||||||
> unlimited scans, and Desk capabilities. **The one gate that is declared but not enforced is board
|
> 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.
|
> reasoning** — which is exactly the decision the D1-close rationale mount is waiting on.
|
||||||
|
|
||||||
|
> ## 🧾 TIER REDESIGN SPEC 2026-07-31 (report-first) → **`specs/tier-redesign-spec.md`**
|
||||||
|
> Option 2 (settled-free / live-paid) designed + sequenced. **Nothing built; no tier, price, gate or
|
||||||
|
> Stripe object changed.**
|
||||||
|
> **0.2 — THE LADDER IS HALF-EXPRESSIBLE TODAY, AND THE GATE IS THE WRONG THING.** `PRICE_MAP`
|
||||||
|
> already separates founder from standing objects (`STRIPE_PRICE_ANALYST[_FOUNDER]`,
|
||||||
|
> `STRIPE_PRICE_DESK[_FOUNDER]`), so **lifetime grandfathering is NATIVE** — a sub created against a
|
||||||
|
> founder price stays on it. **🔴 But founder access is gated by CODE + EXPIRY, not seat count**
|
||||||
|
> (`FOUNDER2026/VYNDR/BETONBLK/EARLYBIRD`, expiry 2026-12-31) — **anyone with a code gets founder
|
||||||
|
> pricing at ANY seat number.** A real Stripe-derived counter exists (`/api/founders/count`, **live
|
||||||
|
> `{claimed:0, total:100}`**) but only DISPLAYS, and is **cached 300s** — a cached read cannot enforce
|
||||||
|
> "slot 100 and 101 differ permanently." **Making the counter the GATE, uncached and transactional at
|
||||||
|
> checkout-session creation (plus retiring the code bypass), is a real build.**
|
||||||
|
> **0.3 — THE PAID→FREE FLIP POINT ALREADY EXISTS ON THE SERVED PAYLOAD.** Settlement writes
|
||||||
|
> `ledger_entries.outcome` + `settled_at`, and `/api/snapshot` already merges per-grade results —
|
||||||
|
> **live WNBA: 25 grades, 5 carrying `outcome:{result:'hit',actual:1}`.** So the discriminator
|
||||||
|
> (`outcome != null`) is present on the exact object to be gated. **No new pipeline needed.**
|
||||||
|
> **🔴 0.4 — THE MIGRATION IS NOT WHAT THE ORDER ASSUMES: `users` holds 3 users, ALL free, created
|
||||||
|
> Jun 12-19, and ZERO paid.** There is no warm mass base. The "founder launch to existing users" is a
|
||||||
|
> **courtesy note to 3 people**, and **the launch's real audience is people who have not signed up
|
||||||
|
> yet** — so effort belongs on the settled-record proof surface, not on migration machinery.
|
||||||
|
> **THE TABLE:** FREE = full data aggregator **+ the COMPLETE settled record** (letter · reasoning ·
|
||||||
|
> edge · outcome, browsable/filterable) — a complete product, not a demo, and the proof hook that
|
||||||
|
> sells. ANALYST **$14.99→$24.99** = tonight's LIVE grades + reasoning + edge, unlimited. DESK
|
||||||
|
> **$44.99→$59.99** = + alt ladder · Kelly · portfolio · engine2.
|
||||||
|
> **REASONING + GRADE + EDGE ARE ONE PAID UNIT WHILE LIVE** (the reasoning IS the grade's argument;
|
||||||
|
> splitting them sells a claim without its defence) **and all three go free together at resolution** —
|
||||||
|
> which also converts today's unenforced board-reasoning leak into a **deliberate rule**.
|
||||||
|
> **THE GATE:** `outcome == null` ⇒ LIVE ⇒ Analyst+ · `outcome != null` ⇒ SETTLED ⇒ everyone.
|
||||||
|
> **Filter whole grades server-side (not field-strips)** so a live grade cannot leak partially ·
|
||||||
|
> **never infer resolution from time or game status, only from a written outcome** (a game can be
|
||||||
|
> final before the settle pass runs) · **fail closed to LIVE** so a settle failure withholds rather
|
||||||
|
> than exposes · `void`/`unrecoverable` are terminal ⇒ free.
|
||||||
|
> **BUILD ORDER:** (1) the settled/live gate — depends on nothing new · (2) the free settled-record
|
||||||
|
> surface — **flagged as arguably shipping WITH (1), since gating live grades without it leaves free
|
||||||
|
> users with no graded content at all** · (3) Stripe ladder + transactional counter + grandfather rule
|
||||||
|
> + retire the code gate · (4) the founder note to the 3 · (5) pricing visuals (**already designed** in
|
||||||
|
> the package — no new design needed).
|
||||||
|
> **CANNOT DETERMINE: whether the four Stripe price objects exist in the dashboard** (env not readable
|
||||||
|
> here) — flagged as a prerequisite for build 3.
|
||||||
|
|
||||||
- **Redirect EXISTS + WIRED:** `closingCapture.buildCaptureRows`→`closing_captures` (append-only,
|
- **Redirect EXISTS + WIRED:** `closingCapture.buildCaptureRows`→`closing_captures` (append-only,
|
||||||
provenance: captured_at/book/line_type/both-prices/missed_reason) via `intradayRefreshService:221`
|
provenance: captured_at/book/line_type/both-prices/missed_reason) via `intradayRefreshService:221`
|
||||||
+ internal endpoint; `ledgerService.attachClosingProb`→`closing_prob` (de-vigs both raw sides,
|
+ internal endpoint; `ledgerService.attachClosingProb`→`closing_prob` (de-vigs both raw sides,
|
||||||
|
|||||||
Reference in New Issue
Block a user