Wave 3: Record by grade tier — shared TierRecord across dashboard, /u, ledger
Addition 2 (non-negotiable): the model's record must show PER GRADE TIER (A+ went X-Y, A X-Y, …) everywhere the record appears. A blended % hides the proof that higher grades win more — the tier calibration IS the credibility. The backend already computed `by_tier` in getModelAggregate; this is display propagation via ONE shared component (the class fix, not five one-offs). - web/src/lib/tierRecord.js — testable CommonJS row-builder. W-L counts ALWAYS (honest at any n); hit-% only when the upstream n≥20 gate passed (hit_pct != null), else "RECORD BUILDING · N settled". Order A+ A B C D F. A-tier is the only edge (green) tier — no glow below A, red reserved for outcomes. - web/src/components/vyndr/TierRecord.tsx — the ONE shared table. Presentational (byTier) for /u + ledger; self-fetch (/api/ledger/model, sport-scoped) for the dashboard. Fully self-hides until a tier has a settled read. - Ledger swaps its inline TierCalibration for the shared component (single source). /u PublicProfile renders it below the blended hero (by_tier added to the aggregate type; it already flows through the route + proxy untouched). Dashboard gains a compact per-tier surface. - Endpoint/proxy audit: profiles.js + ledger.js return the full aggregate (by_tier included); both Next proxies pass the body through — no threading needed. No change to the gate or math in getModelAggregate. Tests: tests/unit/tierRecord.test.js (row logic + tier order + edge contract + source-assert all three surfaces render the shared component). ledgerService test gains an A+-stands-alone bucketing case. Full suite green (243 suites / 2961 tests); web next build exits 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@ import { GradePill } from '@/components/GradeCard';
|
||||
// below as intelligence layers on top of the raw odds.
|
||||
import Slate from '@/components/Slate';
|
||||
// Session 55 — the self-learning loop's track record, live in the header.
|
||||
import { AccuracyBadge, Skeleton, SkeletonList } from '@/components/vyndr';
|
||||
import { AccuracyBadge, Skeleton, SkeletonList, TierRecord } from '@/components/vyndr';
|
||||
// Session 57 (Phase 0) — honest per-sport empty-slate copy.
|
||||
import { emptyStateCopy } from '@/lib/emptyState';
|
||||
// Session 59 (work-order 2.3) — the real pipeline schedule for waiting states.
|
||||
@@ -306,6 +306,15 @@ export default function DashboardPage() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Wave 3 (Addition 2) — the model's record BY GRADE TIER. Self-fetches
|
||||
/api/ledger/model (scoped to the selected sport) and fully self-hides
|
||||
until a tier has a settled read — no empty header. The SAME shared
|
||||
TierRecord that renders on /u and the ledger; the calibration
|
||||
gradient is the proof higher grades win more. */}
|
||||
<div style={{ marginTop: 28 }}>
|
||||
<TierRecord sport={sport} title="MODEL RECORD BY GRADE" dense />
|
||||
</div>
|
||||
|
||||
{/* Top grades tonight — DS2 (#1, #13, Part 6). Tonight's grades RANKED on
|
||||
the varying signal (selectTopGrades: tier → confidence → edge) so the
|
||||
row isn't identical-weight noise; when tonight is empty we fall back to
|
||||
|
||||
Reference in New Issue
Block a user