Un-claim CLV on the public profile; un-fabricate player-page FORM
Two Truth-Law fixes found by auditing the product logged-out. FIX 1 — /u/[handle] claimed a "CLV-verified record" with "closing-line value included" while ZERO closing-line value renders there. Verified live: GET /api/profiles/vyndr returns beat_close_pct null (gated behind CLV_CAPTURE_RELIABLE, unset while C4 is open). Eight instances found — two of them (the OG + portrait "CLV-VERIFIED RECORD · 30D" eyebrows) only by the post-removal residual sweep; two more printed the claim in exactly the no-record branch. Copy now describes what the page shows. The gated CLV-VERIFIED badge and the BEAT CLOSE figure are removed from the public profile, OG card and portrait card. DISPLAY ONLY: beat_close_pct, clvCaptureReliable() and the whole CLV data path are untouched, and the earned directional badge stays Analyst+Desk. The claim returns when CLV genuinely renders here. Also fixes the doubled "· VYNDR · VYNDR" title (layout's '%s · VYNDR' template already supplies the suffix); verified on composed output by serving the build and reading the real HTML, not on source. FIX 2 — the player page's FORM was `70 + 4 × (count of tonight's graded props)`. Nothing on the HTTP path ever sets stats.form, so that fallback WAS the live number: Josh Bell's "74" is 70 + 4×1 prop, confirmed against his live payload. MATCHUP was gradeFromForm(that number), with a hardcoded 'B' on the no-archetype branch — both fabricated letters with no opponent input on the path. Systemic: buildIntel is the unconditional path for every player and sport. FORM and MATCHUP now render "—" (kind 'plain', so no bar width or colour is computed off a null). gradeFromForm is deleted and the prop count is no longer passed into buildIntel. computeFormScore's hardcoded 75 now returns undefined. Induced across MLB/NBA/WNBA: all render cleanly, and real values (USAGE 3.6 AB/G, REST B2B) still render. Neither form value feeds the grade — engine1 reads raw l5_avg/l20_avg against the line and never a form key; buildIntelFields decorates the already-graded object. Grade inputs are byte-identical. Held (needs a per-sport headline-stat design call): a real player-level form metric + label disambiguation. Tests 3491 passed / 289 suites, web build exit 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCNgGSt5qvcLxaeQqa7Zpj
This commit is contained in:
+100
-1
@@ -1,5 +1,5 @@
|
||||
# VYNDR — STATE OF THE WORLD
|
||||
### As of `7ea0af2` (main, DEPLOYED + fingerprinted live), 2026-07-20. This file opens every future session. **Start with the CURRENT STATUS + OPEN ITEMS block below.**
|
||||
### As of `HEAD` on main (DEPLOYED + fingerprinted live), 2026-07-20. This file opens every future session. **Start with the CURRENT STATUS + OPEN ITEMS block below.**
|
||||
|
||||
---
|
||||
|
||||
@@ -131,6 +131,105 @@ exist locally; harmless, the data restores completely.
|
||||
`specs/snapshot-retention.md` (Phase 2 report + schema) ·
|
||||
`specs/audit-data/grade-collapse.md` · `specs/audit-data/gate-simulation.md`.
|
||||
|
||||
---
|
||||
|
||||
# 🟢 SESSION 65 — TWO TRUTH-LAW FIXES (2026-07-20, from Chrome's logged-out audit)
|
||||
Both found by auditing the product as a STRANGER sees it. Neither touches the
|
||||
triplet build; push scoring untouched.
|
||||
|
||||
## Doc drift corrected in this session
|
||||
The header of this file was stale at `7ea0af2` and this file carried **no record
|
||||
of the directional-CLV session** (`dcdad60` → `ca9ca34`: `src/services/
|
||||
directionalClv.js`, the Analyst+Desk server-gated `ClvBadge`, and removal of the
|
||||
legacy C4 CLV chip from five surfaces). `BUILD-STATE.md` is stale to April 2026 —
|
||||
**`specs/STATE.md` is the authoritative state file**; treat BUILD-STATE as archive.
|
||||
|
||||
## FIX 1 — "CLV-VERIFIED" UN-CLAIMED ON THE PUBLIC PROFILE (copy + 2 render blocks)
|
||||
`/u/[handle]` was titled **"CLV-verified record"** with the subhead **"closing-line
|
||||
value included"** while **zero** closing-line value renders there. Verified live,
|
||||
not assumed: `GET /api/profiles/vyndr` → `beat_close_pct: null` (gated behind
|
||||
`clvCaptureReliable()` / `CLV_CAPTURE_RELIABLE`, which is unset while C4 is open).
|
||||
A verification claim with nothing verified shown is an unearned claim, and it
|
||||
leaked the standing CLV hold onto a surface that had never been audited.
|
||||
|
||||
**EIGHT instances found — two of them ONLY by the post-removal residual sweep:**
|
||||
|
||||
| # | Where | Was |
|
||||
|---|---|---|
|
||||
| 1 | `u/[handle]/page.tsx` | `<title>` / `og:title` / `twitter:title` — "CLV-verified record" |
|
||||
| 2 | `u/[handle]/page.tsx` | meta + og + twitter description — "closing-line value included" |
|
||||
| 3 | `u/[handle]/opengraph-image.tsx` | no-record fallback tagline |
|
||||
| 4 | `u/[handle]/portrait/route.tsx` | no-record fallback tagline |
|
||||
| 5 | `PublicProfile.tsx` | house subhead — "closing-line value included" |
|
||||
| 6 | `PublicProfile.tsx` | `✓ CLV-VERIFIED` badge (gated, dark, one env flag from re-claiming) |
|
||||
| **7** | `opengraph-image.tsx` | **eyebrow `CLV-VERIFIED RECORD · 30D`** — missed in the first report |
|
||||
| **8** | `portrait/route.tsx` | **same eyebrow** — missed in the first report |
|
||||
|
||||
Instances 3 + 4 printed the verification claim **exactly when there is no record
|
||||
at all** (the `rec == null` branch), i.e. the claim was loudest where the data was
|
||||
most absent.
|
||||
|
||||
**Applied:** honest copy on 1–5 + 7–8 (settled record · wins and misses · nothing
|
||||
curated); the badge (6a) and the `BEAT CLOSE` figure (6b) REMOVED from the public
|
||||
profile, OG card and portrait card. **DISPLAY ONLY — `beat_close_pct`,
|
||||
`clvCaptureReliable()`, `closing_captures` and the whole CLV data path are
|
||||
untouched**, and the earned directional badge stays Analyst+Desk (never public).
|
||||
The claim returns here when CLV genuinely renders here.
|
||||
|
||||
**Title double-append fixed and VERIFIED ON COMPOSED OUTPUT, not source:** the page
|
||||
title carried its own `· VYNDR` while `layout.tsx`'s metadata template already
|
||||
appends `%s · VYNDR` → live was `…@vyndr · VYNDR · VYNDR`. Built the app, served
|
||||
it, and read the real HTML: `<title>Settled record — @vyndr · VYNDR</title>` —
|
||||
exactly one suffix. Note `openGraph`/`twitter` titles **bypass** the template, so
|
||||
they carry the brand suffix explicitly.
|
||||
|
||||
Both share images re-rendered locally (200 / image/png) and eyeballed: no overflow,
|
||||
no clip, no residual CLV scaffold.
|
||||
|
||||
## FIX 2 — FORM WAS FABRICATED ON THE PLAYER PAGE (un-fabricate; steps 2+3 HELD)
|
||||
Chrome saw Josh Bell as **FORM 74** (player page) and **Form 63** (generated read)
|
||||
in one session. Traced both. **Neither feeds the grade** — proven, not assumed:
|
||||
`engine1.gradeProp` runs at `analyzeViaEngine1.js:446`, `buildIntelFields` (which
|
||||
computes form) decorates the already-graded object at `:468`; `engine1.js` never
|
||||
reads a `form` key (only raw `l5_avg`/`l20_avg` **against the line**), and nothing
|
||||
in `src/` reads `result.form`. Grade inputs are byte-identical before/after.
|
||||
|
||||
- **63 is real** — `70 + (l5_avg / l20_avg − 1) × 60`, per-prop, per-stat.
|
||||
- **74 was manufactured** — `70 + 4 × (count of tonight's graded props)`, capped
|
||||
92. **Nothing on the HTTP path ever sets `stats.form`**, so that fallback WAS
|
||||
the live value. Confirmed empirically: Bell's payload carries `activeProps`
|
||||
length **1** → 70 + 4 = **74**, exact.
|
||||
- It **poisoned a second tile**: `MATCHUP` was `gradeFromForm(form)` — Bell's
|
||||
"B" was `gradeFromForm(74)`, from the prop count, with **no opponent input on
|
||||
that path at all**; the no-archetype branch hardcoded `'B'`. Both fabricated.
|
||||
- **SYSTEMIC, not Bell-specific** — `buildIntel` is the unconditional path for
|
||||
every player and every sport.
|
||||
|
||||
**Applied (absent renders absent):** FORM and MATCHUP now emit `kind:'plain'`
|
||||
with `'—'` when there is no real value — `'plain'` deliberately, so the page
|
||||
draws no progress bar and computes no width/colour off a null. `gradeFromForm`
|
||||
deleted; the prop count is no longer passed into `buildIntel` at all.
|
||||
`computeFormScore`'s hardcoded **75** (returned whenever the baseline was missing
|
||||
or zero) now returns `undefined` → the card's self-hiding intel section drops the
|
||||
row. Induced live across **MLB / NBA / WNBA**: all render `—` cleanly; real values
|
||||
(`USAGE 3.6 AB/G`, `REST B2B`) still render — the fix is surgical to fabrications.
|
||||
|
||||
**HELD (needs a per-sport headline-stat design call, deliberately NOT built):** a
|
||||
real player-level form metric + label disambiguation (page-level vs per-stat). It
|
||||
lands as `stats.form` / `stats.matchup` and lights these tiles straight back up.
|
||||
|
||||
### Audit of the same file (order item 10) — reported, NOT changed
|
||||
`toNum()` (`playerIntelService.js:18`) returns **0** for absent, feeding
|
||||
`classifierInput`: `k_rate` (`pa > 0 ? … : 0`), `ip_per_start`, `k9`, `saves`.
|
||||
These are **classifier inputs, not display** — a 0 there can misclassify an
|
||||
archetype (0% K-rate reads as elite contact). Same family as the `Number(null)
|
||||
=== 0` rule. `mlbLast10Rows` renders `${st.hits ?? 0}-${st.atBats ?? 0}`, which
|
||||
prints a real-looking `0-0` line if a game-log row lacks its stat object.
|
||||
**Ambiguous — changing classifier inputs shifts archetypes, so it needs its own
|
||||
order.** Display rows elsewhere (`mlbSeasonRows`, ESPN season rows) correctly use
|
||||
`?? '—'`.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 🟢 MLB opp_rank_stat LIVE — computed, CONSUMED, retained (2026-07-20 16:51 UTC)
|
||||
|
||||
Reference in New Issue
Block a user