report: D1-close Review Zero — mount not performed, three findings
Nothing changed: no mount, no row edit, no data threading. Docs only. 1. THE RATIONALE DOES NOT REACH THE ROW. StripProp carries stat/line/side/grade/ gradedAt/delta/awaiting/outcome/movement/revisedFrom/book/bestBook/dead/ history — no reasoning, no kill_conditions_triggered — and buildPlayerStripsFromProps never threads them. Mounting the hover needs a new field on the strip contract threaded through the slate adapter: additive, but a data-path change rather than a mount. 2. THE 0.3 PREMISE INVERTS — THE RATIONALE IS ALREADY PUBLIC. Verified live and anonymously against prod: /api/snapshot/wnba returns reasoning.summary with no locked flag plus kill_conditions_triggered. stripModelPrice removes model_odds/p_win/ev_pct/value/takeable but NOT reasoning. So the full model rationale already ships to every anonymous browser on the main board, while the same content IS tier-gated on the scan path (tierGating.js). Mounting the hover would leak nothing new, but would surface content that is currently shipped-but-unrendered, and the product gates it in one place while serving it openly in another. That is a monetization/consistency decision, so it is reported with three options rather than resolved unilaterally. 3. ROW-GRAMMAR IS LAW AND LOCKS StatStrip's SOURCE ORDER. rowGrammar.test.js asserts element order via src.indexOf on the component source; adding a rationale affordance or a team chip moves those offsets, so specs/ROW-GRAMMAR.md and the test must be amended in the same commit. That makes this spec-amending work needing its own slot decisions, not an additive mount. Safely mountable with no blockers: reveal.js (wraps the row list, no StatStrip internals, no new data, no grammar slot). teamChips needs a grammar slot; rowRationale needs the data threading AND the gating decision AND a slot. Recommends splitting D1-close into: mount reveal now; a ROW-GRAMMAR amendment order for the chip + rationale slots; then the rationale mount once the gating decision is made. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# D1 CLOSE — REVIEW ZERO FINDINGS (report; mount NOT performed)
|
||||
2026-07-31. Nothing changed: no mount, no row edit, no data threading.
|
||||
`git diff` = docs only.
|
||||
|
||||
## Why this stopped at Review Zero
|
||||
|
||||
The order scopes this as "mount only — NO row refactor." Reading the real components shows the
|
||||
mount is **not** a mount, and one finding needs a decision before anything is surfaced.
|
||||
|
||||
### 0.1/0.2 — THE RATIONALE DOES NOT REACH THE ROW (VERIFIED)
|
||||
`StripProp` (`components/vyndr/StatStrip.tsx`) carries stat · line · side · grade · gradedAt ·
|
||||
delta · awaiting · outcome · movement · revisedFrom · book · bestBook · dead · history —
|
||||
**no `reasoning`, no `kill_conditions_triggered`.** `buildPlayerStripsFromProps` never threads
|
||||
them either. So mounting the hover requires **adding a field to the strip contract and threading
|
||||
it through the slate adapter** — additive, but a data-path change, not a mount.
|
||||
|
||||
### 0.3 — THE PREMISE INVERTS: THE RATIONALE IS **ALREADY PUBLIC** (VERIFIED LIVE)
|
||||
The order asks me to ensure "a free-tier user's hover shows nothing, not the paid reasoning."
|
||||
Measured against prod, anonymously:
|
||||
|
||||
GET https://api.vyndr.app/api/snapshot/wnba (no auth)
|
||||
reasoning.summary present : True
|
||||
reasoning.locked : None
|
||||
kill_conditions_triggered : 1
|
||||
|
||||
**`stripModelPrice` strips `model_odds`/`p_win`/`ev_pct`/`value`/`takeable` — it does NOT strip
|
||||
`reasoning` or `kill_conditions_triggered`.** So the full model rationale is already shipped to
|
||||
every anonymous browser on the main board endpoint.
|
||||
|
||||
**Two consequences, and they pull in opposite directions:**
|
||||
1. Mounting the hover **leaks nothing new** — it renders bytes the browser already has.
|
||||
2. But it **surfaces** something currently shipped-but-unrendered, and the same content **IS**
|
||||
tier-gated on the scan path (`utils/tierGating.js` redacts `reasoning` for free tier). So the
|
||||
product currently gates the reasoning in one place and serves it openly in another.
|
||||
|
||||
**This is a monetization/consistency decision, not an implementation detail** — which is why it
|
||||
is reported rather than resolved unilaterally. Three coherent options:
|
||||
- **(a)** Gate `reasoning` on `/api/snapshot` the way scan does, then mount the hover for entitled
|
||||
viewers only. Consistent, but removes content free users already receive.
|
||||
- **(b)** Accept it as intentionally free (board reasoning is the funnel) and mount for everyone.
|
||||
Consistent the other way; makes the scan-path gating the odd one out.
|
||||
- **(c)** Leave the payload alone and don't surface it. Status quo.
|
||||
|
||||
### THE THIRD BLOCKER — ROW-GRAMMAR IS LAW AND LOCKS StatStrip's SOURCE ORDER (VERIFIED)
|
||||
`tests/unit/rowGrammar.test.js` asserts StatStrip's element order by **`src.indexOf(...)` on the
|
||||
component source** (slots: identity → viability → stat+line → market context → model output →
|
||||
outcome → actions → provenance). Adding a rationale affordance or a team chip **moves those
|
||||
offsets**, so `specs/ROW-GRAMMAR.md` and the test must be amended **in the same commit** — per
|
||||
CLAUDE.md, that spec is LAW. That makes this a spec-amending change, not an additive mount, and
|
||||
the amendment needs its own slot decision (where does a rationale affordance sit in the grammar?
|
||||
where does a team chip sit relative to identity?).
|
||||
|
||||
## WHAT IS SAFELY MOUNTABLE WITHOUT ANY OF THE ABOVE
|
||||
- **`reveal.js`** — wraps the row LIST, touches no StatStrip internals, no new data, no grammar
|
||||
slot. This one is genuinely a mount.
|
||||
- **`teamChips.js`** — needs a grammar slot (it sits before the team abbr, inside identity), so it
|
||||
is small but spec-touching.
|
||||
- **`rowRationale.js`** — needs the data threading AND the gating decision AND a grammar slot.
|
||||
|
||||
## RECOMMENDATION
|
||||
Split D1-close into: **(1)** mount `reveal` now (no blockers), **(2)** a ROW-GRAMMAR amendment
|
||||
order that adds the team-chip slot + the rationale-affordance slot to the spec and test, and
|
||||
**(3)** the rationale mount, after the gating decision above is made.
|
||||
|
||||
## TAGS
|
||||
VERIFIED: strip contract lacks reasoning; anon snapshot serves reasoning + kills; ROW-GRAMMAR
|
||||
locks source order. CANNOT DETERMINE: none. **BLOCKED: the rationale mount — on a
|
||||
gating decision (a/b/c) and a ROW-GRAMMAR amendment.**
|
||||
Reference in New Issue
Block a user