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:
+1
-1
File diff suppressed because one or more lines are too long
@@ -10,8 +10,9 @@ import { buildTierRows } from '@/lib/tierRecord';
|
||||
/**
|
||||
* PublicProfile (A1 Session 10) — the public ledger record for one handle.
|
||||
*
|
||||
* DATA SEMANTICS: every row here is a REAL settled ledger entry — outcome,
|
||||
* actual value, closing-line value. Nothing curated: publishing shows the
|
||||
* DATA SEMANTICS: every row here is a REAL settled ledger entry — outcome and
|
||||
* actual value. No closing-line value renders on this public surface (Session
|
||||
* 65 un-claim). Nothing curated: publishing shows the
|
||||
* ENTIRE settled record, misses included. The header NEVER renders a
|
||||
* percentage under min_sample (20) settles — it shows RECORD BUILDING.
|
||||
*
|
||||
@@ -133,7 +134,7 @@ export default function PublicProfile({ handle }: { handle: string }) {
|
||||
</h1>
|
||||
<p style={{ color: 'var(--text-secondary)', fontSize: 15 }}>
|
||||
{isHouse
|
||||
? 'The VYNDR model’s public record. Every graded read, wins and misses, closing-line value included.'
|
||||
? 'The VYNDR model’s public record. Every graded read, wins and misses. Nothing curated.'
|
||||
: 'Every settled read. Wins and misses. Nothing curated.'}
|
||||
</p>
|
||||
</header>
|
||||
@@ -172,13 +173,21 @@ export default function PublicProfile({ handle }: { handle: string }) {
|
||||
/**
|
||||
* The record HERO (DS4 · billboard — DESIGN-SPEC Part 3 + Part 6 #4). This is
|
||||
* the shareable surface Kev pitches partners with. One bold figure among muted
|
||||
* context: the HIT RATE as a large mono tabular number, beat-close as the
|
||||
* secondary bold figure, the raw record demoted. CLV-VERIFIED badge only when
|
||||
* closing-line value is actually tracked (honest — never a decorative badge).
|
||||
* context: the HIT RATE as a large mono tabular number, the raw record demoted.
|
||||
* Session 65 removed the closing-value figure + verification badge — see the
|
||||
* un-claim note inside.
|
||||
*/
|
||||
function RecordHeader({ agg, minSample }: { agg: ProfileAggregate | null; minSample: number }) {
|
||||
const ready = Boolean(agg && agg.settled >= minSample && agg.hit_pct != null);
|
||||
const clvVerified = Boolean(ready && agg && agg.beat_close_pct != null);
|
||||
// Session 65 — UN-CLAIM. The closing-value verification badge and the
|
||||
// secondary close-beat figure were REMOVED from this public surface. Both
|
||||
// read `beat_close_pct`, derived from the legacy overwritable `closing_line`
|
||||
// (C4 open). The badge was gated behind CLV_CAPTURE_RELIABLE — one env flag
|
||||
// away from re-asserting verification on the same data Session 64 deleted
|
||||
// from these rows as untrustworthy. Removal is DISPLAY ONLY: the aggregate,
|
||||
// `clvCaptureReliable()` and the whole closing-value data path are untouched,
|
||||
// and the earned directional badge stays Analyst+Desk (never public). The
|
||||
// claim returns here when closing value genuinely renders here.
|
||||
return (
|
||||
<div
|
||||
className="surface diagonal-cut"
|
||||
@@ -190,11 +199,6 @@ function RecordHeader({ agg, minSample }: { agg: ProfileAggregate | null; minSam
|
||||
<span className="mono" style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.1em', color: 'var(--text-tertiary)' }}>
|
||||
RECORD · LAST 30D
|
||||
</span>
|
||||
{clvVerified && (
|
||||
<span className="mono" style={{ fontSize: 10.5, fontWeight: 800, letterSpacing: '0.08em', color: 'var(--g-a, #00D4A0)', border: '1px solid var(--g-a, #00D4A0)', borderRadius: 999, padding: '3px 10px', background: 'color-mix(in srgb, var(--g-a, #00D4A0) 12%, transparent)' }}>
|
||||
✓ CLV-VERIFIED
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{/* HERO figures — hit rate is the largest thing on the page. */}
|
||||
<div style={{ display: 'flex', gap: 40, flexWrap: 'wrap', alignItems: 'flex-end' }}>
|
||||
@@ -206,16 +210,6 @@ function RecordHeader({ agg, minSample }: { agg: ProfileAggregate | null; minSam
|
||||
HIT RATE · {agg.hits}-{agg.misses}
|
||||
</div>
|
||||
</div>
|
||||
{agg.beat_close_pct != null && (
|
||||
<div>
|
||||
<div className="mono" style={{ fontSize: 40, fontWeight: 800, lineHeight: 0.95, letterSpacing: '-0.02em', color: 'var(--text-primary)', fontVariantNumeric: 'tabular-nums' }}>
|
||||
{agg.beat_close_pct}%
|
||||
</div>
|
||||
<div className="mono" style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: '0.12em', color: 'var(--text-tertiary)', marginTop: 4 }}>
|
||||
BEAT CLOSE
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div style={{ marginLeft: 'auto' }}>
|
||||
<div className="mono" style={{ fontSize: 14, fontWeight: 600, color: 'var(--text-tertiary)', fontVariantNumeric: 'tabular-nums' }}>
|
||||
{agg.pending} pending
|
||||
|
||||
@@ -2,7 +2,8 @@ import { ImageResponse } from 'next/og';
|
||||
|
||||
// A1 Session 10 · elevated DS4 — every shared /u/:handle link unfurls as a
|
||||
// record card at social crop (1200×630). The billboard now carries the REAL
|
||||
// record (hit% + beat-close%) when the handle is published + past the n-gate,
|
||||
// record (hit%) when the handle is published + past the n-gate (Session 65
|
||||
// removed beat-close% — see the un-claim note below),
|
||||
// so the timeline (customer #1) sees the proof, not just a tagline. Self-hosted
|
||||
// standalone build → Node runtime (NOT edge; Session-53 rule).
|
||||
export const alt = 'VYNDR Public Ledger';
|
||||
@@ -49,7 +50,7 @@ export default async function Image({ params }: { params: Promise<{ handle: stri
|
||||
<div style={{ display: 'flex', position: 'absolute', top: 0, left: 0, right: 0, height: 6, background: '#00D4A0' }} />
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{ display: 'flex', fontSize: 26, letterSpacing: '0.22em', color: '#00D4A0', fontWeight: 700 }}>
|
||||
{rec ? (rec.house ? 'VYNDR MODEL · PUBLIC RECORD' : 'CLV-VERIFIED RECORD · 30D') : 'PUBLIC LEDGER'}
|
||||
{rec ? (rec.house ? 'VYNDR MODEL · PUBLIC RECORD' : 'SETTLED RECORD · 30D') : 'PUBLIC LEDGER'}
|
||||
</div>
|
||||
<div style={{ display: 'flex', fontSize: 72, fontWeight: 900, letterSpacing: '-0.02em', marginTop: 14, color: '#FFFFFF' }}>
|
||||
{rec?.house ? 'VYNDR MODEL' : `@${h}`}
|
||||
@@ -60,16 +61,15 @@ export default async function Image({ params }: { params: Promise<{ handle: stri
|
||||
<div style={{ display: 'flex', fontSize: 128, fontWeight: 900, lineHeight: 1, color: '#00D4A0' }}>{rec.hit_pct}%</div>
|
||||
<div style={{ display: 'flex', fontSize: 22, letterSpacing: '0.14em', color: '#7A7A8E', marginTop: 8 }}>HIT RATE · {rec.hits}-{rec.misses}</div>
|
||||
</div>
|
||||
{rec.beat_close_pct != null && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{ display: 'flex', fontSize: 92, fontWeight: 900, lineHeight: 1, color: '#FFFFFF' }}>{rec.beat_close_pct}%</div>
|
||||
<div style={{ display: 'flex', fontSize: 22, letterSpacing: '0.14em', color: '#7A7A8E', marginTop: 8 }}>BEAT CLOSE</div>
|
||||
</div>
|
||||
)}
|
||||
{/* Session 65 — the secondary close-beat figure was REMOVED from
|
||||
this public share card. It rendered beat_close_pct, derived from
|
||||
the legacy overwritable closing_line (C4 open: closing == locked
|
||||
on ~95% of rows). Display removal only — the aggregate + its gate
|
||||
in ledgerService are untouched. */}
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ display: 'flex', fontSize: 28, color: '#7A7A8E', marginTop: 20 }}>
|
||||
CLV-verified record · every settled read · misses included
|
||||
Every settled read · wins and misses · nothing curated
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -12,13 +12,23 @@ import PublicProfile from './PublicProfile';
|
||||
export async function generateMetadata({ params }: { params: Promise<{ handle: string }> }): Promise<Metadata> {
|
||||
const { handle } = await params;
|
||||
const h = decodeURIComponent(handle || '').slice(0, 20).toLowerCase();
|
||||
const title = `CLV-verified record — @${h} · VYNDR`;
|
||||
const description = `@${h}'s settled betting record on VYNDR — every read, every result, closing-line value included. Nothing curated, nothing deleted.`;
|
||||
// Session 65 — UN-CLAIM. The title/description previously asserted a
|
||||
// closing-line-verified record while ZERO closing-line value
|
||||
// renders on this surface (beat_close_pct is null until C4 is fixed and
|
||||
// CLV_CAPTURE_RELIABLE flips; the earned directional badge is Analyst+Desk
|
||||
// and never reaches this public page). Copy now describes exactly what the
|
||||
// page shows. The claim returns, earned, when CLV genuinely renders here.
|
||||
// NOTE: layout.tsx's metadata template appends " · VYNDR" — do not repeat it.
|
||||
const title = `Settled record — @${h}`;
|
||||
const description = `@${h}'s settled betting record on VYNDR — every graded read, every result, wins and misses. Nothing curated, nothing deleted.`;
|
||||
// openGraph/twitter titles bypass the layout template, so they carry the
|
||||
// brand suffix explicitly; the page <title> must not (it would double it).
|
||||
const socialTitle = `${title} · VYNDR`;
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
openGraph: { title, description },
|
||||
twitter: { card: 'summary_large_image', title, description },
|
||||
openGraph: { title: socialTitle, description },
|
||||
twitter: { card: 'summary_large_image', title: socialTitle, description },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ export async function GET(
|
||||
const h = decodeURIComponent(handle || '').slice(0, 20).toLowerCase() || 'handle';
|
||||
const rec = await fetchRecord(h);
|
||||
const heading = rec?.house ? 'VYNDR MODEL' : `@${h}`;
|
||||
const eyebrow = rec ? (rec.house ? 'VYNDR MODEL · PUBLIC RECORD' : 'CLV-VERIFIED RECORD · 30D') : 'PUBLIC LEDGER';
|
||||
const eyebrow = rec ? (rec.house ? 'VYNDR MODEL · PUBLIC RECORD' : 'SETTLED RECORD · 30D') : 'PUBLIC LEDGER';
|
||||
|
||||
return new ImageResponse(
|
||||
(
|
||||
@@ -88,16 +88,13 @@ export async function GET(
|
||||
<div style={{ display: 'flex', fontSize: 240, fontWeight: 900, lineHeight: 1, color: '#00D4A0' }}>{rec.hit_pct}%</div>
|
||||
<div style={{ display: 'flex', fontSize: 30, letterSpacing: '0.14em', color: '#7A7A8E', marginTop: 12 }}>HIT RATE · {rec.hits}-{rec.misses}</div>
|
||||
</div>
|
||||
{rec.beat_close_pct != null && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{ display: 'flex', fontSize: 128, fontWeight: 900, lineHeight: 1, color: '#FFFFFF' }}>{rec.beat_close_pct}%</div>
|
||||
<div style={{ display: 'flex', fontSize: 30, letterSpacing: '0.14em', color: '#7A7A8E', marginTop: 12 }}>BEAT CLOSE</div>
|
||||
</div>
|
||||
)}
|
||||
{/* Session 65 — the close-beat figure was removed from the public
|
||||
portrait card (legacy C4 closing_line derivation). Display
|
||||
removal only; the data path is untouched. */}
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ display: 'flex', fontSize: 40, color: '#7A7A8E', lineHeight: 1.4 }}>
|
||||
CLV-verified record · every settled read · misses included
|
||||
Every settled read · wins and misses · nothing curated
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user