Files
vyndr/specs/wave1-wiring.md
T

79 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC — WAVE 1: WIRE THE WORKING SURFACES + /marketplace HONESTY (shipped)
2026-07-31. Wiring + one copy pass. No grade, ledger, model, or scoring change.
## REVIEW ZERO — each surface proven BEFORE wiring
- **0.1 `/intelligence` vs `/system` — NOT duplicates; nothing to resolve away.** `System.dc.html`
is a MULTI-surface artboard (it contains TERMINAL, INTELLIGENCE and WIRE sections), not the design
for a distinct `/system` route. Its INTELLIGENCE section is **already realised** as the live
`app/intelligence/page.tsx`. **No `/system` page exists and none should be built as a second copy**
the prod 404 is correct. Only `/intelligence` was wired. ✅
- **0.2 `/intelligence` renders live + gates correctly.** Real feed (`/api/intelligence/feed`), 160
lines, zero placeholders. **Entitlement is enforced SERVER-side, not by blur**: the proxy requires
auth and limits by tier — **desk 50 signals / non-desk 8** — and returns `401 Not signed in` to an
anonymous caller (**verified live in prod**). So making it nav-reachable leaks nothing. ✅
- **0.3 `/slip` functions END TO END on a real slip.** Parsed the real DraftKings fixture:
**3/3 legs, `needs_review: false`**, leg 1 = `Aaron Judge · total_bases · over 1.5 @ -115`. ✅
**Honest limit recorded:** the parsers are layout-rigid. A slip in an unsupported layout yields
**zero legs rather than wrong ones** — correct per the NEVER-GUESS contract, but it means real-world
OCR hit-rate across layouts is **CANNOT DETERMINE** until real user slips arrive.
- **0.4 `/parlay` direct route hits the working surface.** `app/parlay/page.tsx` is the real
correlation builder on the **same `ParlayContext`** the drawer uses — not a separate unbuilt page. ✅
- **0.5 `/marketplace`** advertises four unbuilt things (API access · custom alerts · "The Edge"
playbook · merch capsule). **No performance/edge/profit claim was present** (the worse category —
clean). The capture was already REAL: `fetch('/api/waitlist')``src/routes/waitlist.js` upserts to
a `waitlist` table. The gap was tense: bodies read as present-tense descriptions.
## PHASE 1 — WIRED (all three passed)
`Nav.tsx MORE`: **Intelligence**, **Slip Reader**, **Marketplace** added; **Parlay Lab re-pointed from
`#parlay` (drawer-only) to `/parlay`** (the real page). The drawer is unaffected — `ParlayPanel` stays
mounted in the layout with its floating badge, its natural in-context use from a prop row.
**Gating change (one line, principled):** `/intelligence` added to `GATED_ROUTES`. Its feed 401s
signed-out, so an ungated nav link would land visitors on a permanently empty page. `/slip` was already
gated (personal surface). **`/parlay` deliberately stays OPEN** — it is the free parlay funnel and
gating it would be a monetization regression (same rule as dashboard/scan).
## PHASE 2 — /marketplace HONESTY PASS
Every item body now opens **"Not built yet."** / "Not written yet." / "Not produced yet." followed by
what is *planned*. The subhead is explicit: *"None of the below is built yet… joining a list records
your interest, nothing more. It is not a purchase, not a pre-order, and not a promise of a ship date."*
The playbook item carries **"No profit claim, no promised return."** The capture stays REAL (no fake
button). Unit-locked: every body must contain a not-yet marker, and the page must carry no
guaranteed/win-rate/ROI/beat-the-book language.
## PHASE 3 — VERIFY
Grade, ledger, model, scoring **untouched** (diff empty across `intelligence/`, `ledgerService`,
`outcomeService`, `gradeSlateService`). **315 suites / 3,920 tests green** (12 new), **web build exit 0**.
**Chrome audit manifest — Wave 1 additions:**
| surface | state | check |
|---|---|---|
| `/intelligence` | **signed-out** → should redirect to `/login` (now gated) | no empty-feed page |
| `/intelligence` | **free** vs **ENTITLED (Desk)** | free sees 8 signals + lock overlay; **Desk sees 50***entitled path needs Kev* |
| `/slip` | **free (signed-in)** | upload/paste → editable legs; unsupported layout → empty, not wrong |
| `/parlay` | **logged-out** | direct nav entry loads the full lab; free 2-leg cap + payout blur |
| `/marketplace` | logged-out | "Not built yet" on every item; Join waitlist records and confirms |
## TAGS
VERIFIED: 0.10.5, all wiring, gating, copy. **CANNOT DETERMINE: real-world slip OCR hit-rate across
book layouts** (no user slips yet). BLOCKED: none.
## POST-DEPLOY FINGERPRINT (commit `ff7f5d8`)
**Deploy CONFIRMED landed** — the new `/marketplace` copy is live in prod (`"None of the below is
built yet"`, `"Not built yet"`, `"not a pre-order"` all served). All four routes 200:
`/intelligence`, `/slip`, `/parlay`, `/marketplace`. `/api/intelligence/feed` **still returns
`{"error":"Not signed in."}`** to an anonymous caller — gating intact after the change.
**⚠️ The nav ENTRIES could not be verified by curl, and I am not claiming they were.** The MORE
dropdown's labels are not present in any JS chunk referenced by the initial `/dashboard` HTML.
**Control test proves this is a probe limitation, not a failure:** the PRE-EXISTING entries
`"Parlay Lab"` and `"The Report"` — live before this change — are **equally absent** from the same 18
sampled chunks, while `"Explore"` (also a main-nav item) is present. The dropdown is client-rendered
from a lazily-fetched chunk.
**→ Added to the Chrome audit manifest:** confirm the MORE dropdown actually shows **Intelligence ·
Slip Reader · Marketplace · Parlay Lab→/parlay**, and that a signed-out click on Intelligence lands on
`/login` (the new gate) rather than an empty feed. Checkable logged-out; no entitled session needed.