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:
@@ -132,7 +132,7 @@ describe('GradeResultCard — the letter is hero, edge is sign-colored', () => {
|
||||
});
|
||||
|
||||
// ── 4. /u public profile — the shareable record billboard (#4) ────────────
|
||||
describe('PublicProfile — the record hero + CLV-verified badge', () => {
|
||||
describe('PublicProfile — the record hero (Session 65: no CLV claim)', () => {
|
||||
const src = read('app/u/[handle]/PublicProfile.tsx');
|
||||
|
||||
test('the hit rate is the bold hero figure (large mono tabular)', () => {
|
||||
@@ -141,14 +141,15 @@ describe('PublicProfile — the record hero + CLV-verified badge', () => {
|
||||
expect(src).toContain('HIT RATE');
|
||||
});
|
||||
|
||||
test('beat-close is the secondary bold figure', () => {
|
||||
expect(src).toContain('{agg.beat_close_pct}%');
|
||||
expect(src).toContain('BEAT CLOSE');
|
||||
});
|
||||
|
||||
test('CLV-VERIFIED badge is HONEST — only when closing value is tracked', () => {
|
||||
expect(src).toContain('✓ CLV-VERIFIED');
|
||||
expect(src).toMatch(/clvVerified = Boolean\(ready && agg && agg\.beat_close_pct != null\)/);
|
||||
// Session 65 — UN-CLAIM. The beat-close figure and the ✓ CLV-VERIFIED badge
|
||||
// are GONE from this public surface: both read beat_close_pct, derived from
|
||||
// the legacy overwritable closing_line (C4 open). Display removal only — the
|
||||
// aggregate and its CLV_CAPTURE_RELIABLE gate in ledgerService are untouched.
|
||||
test('no closing-line claim renders on the public record hero', () => {
|
||||
expect(src).not.toContain('{agg.beat_close_pct}%');
|
||||
expect(src).not.toContain('BEAT CLOSE');
|
||||
expect(src).not.toContain('CLV-VERIFIED');
|
||||
expect(src).not.toMatch(/clvVerified/);
|
||||
});
|
||||
|
||||
test('still honors the n-gate: RECORD BUILDING under min_sample', () => {
|
||||
@@ -170,13 +171,15 @@ describe('/u opengraph-image — real record at 1200x630 social crop', () => {
|
||||
expect(src).toMatch(/size = \{ width: 1200, height: 630 \}/);
|
||||
});
|
||||
|
||||
test('renders the real hit% / beat-close% when the record is published', () => {
|
||||
test('renders the real hit% when the record is published, and claims no CLV', () => {
|
||||
expect(src).toContain('{rec.hit_pct}%');
|
||||
expect(src).toContain('{rec.beat_close_pct}%');
|
||||
expect(src).toContain('CLV-VERIFIED RECORD');
|
||||
// Session 65 — beat-close% + the CLV-VERIFIED eyebrow are un-claimed here.
|
||||
expect(src).not.toContain('{rec.beat_close_pct}%');
|
||||
expect(src).not.toMatch(/CLV-VERIFIED|CLV-verified/);
|
||||
expect(src).toContain('SETTLED RECORD · 30D');
|
||||
});
|
||||
|
||||
test('falls back gracefully to the tagline when there is no record', () => {
|
||||
expect(src).toContain('every settled read · misses included');
|
||||
test('falls back gracefully to an honest tagline when there is no record', () => {
|
||||
expect(src).toContain('Every settled read · wins and misses · nothing curated');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user