f5156dd16d
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
61 lines
2.8 KiB
JavaScript
61 lines
2.8 KiB
JavaScript
// Session 43 — engine attaches grade-card intelligence fields (stat context +
|
|
// VYNDR intelligence) from the feature vector, and gradeAdapter maps them.
|
|
|
|
const { __internals } = require('../../src/services/intelligence/analyzeViaEngine1');
|
|
const { buildIntelFields, computeFormScore, matchupGradeFromRank } = __internals;
|
|
const { mapScanToGradeResult } = require('../../web/src/lib/gradeAdapter');
|
|
|
|
describe('computeFormScore', () => {
|
|
it('trends above 70 when recent > baseline (hot)', () => {
|
|
expect(computeFormScore({ l5_avg: 30, l20_avg: 24 })).toBeGreaterThan(70);
|
|
});
|
|
it('trends below 70 when recent < baseline (cold)', () => {
|
|
expect(computeFormScore({ l5_avg: 18, l20_avg: 26 })).toBeLessThan(70);
|
|
});
|
|
it('undefined when there is no recent average', () => {
|
|
expect(computeFormScore({})).toBeUndefined();
|
|
});
|
|
// Session 65 — UN-FABRICATE. This branch used to `return 75`: a hardcoded
|
|
// constant rendered under the FORM label whenever the baseline was missing
|
|
// or zero. With no baseline there is no ratio, so the field is absent and
|
|
// the card's self-hiding intel section drops the row.
|
|
it('undefined (never a hardcoded 75) when the baseline is missing or zero', () => {
|
|
expect(computeFormScore({ l5_avg: 12 })).toBeUndefined();
|
|
expect(computeFormScore({ l5_avg: 12, l20_avg: 0 })).toBeUndefined();
|
|
expect(computeFormScore({ l5_avg: 12, l20_avg: 0, l10_avg: 0 })).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('matchupGradeFromRank', () => {
|
|
it('maps normalized opponent rank to a letter grade', () => {
|
|
expect(matchupGradeFromRank(0.9)).toBe('A');
|
|
expect(matchupGradeFromRank(0.55)).toBe('B+');
|
|
expect(matchupGradeFromRank(0.1)).toBe('C');
|
|
expect(matchupGradeFromRank(undefined)).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('buildIntelFields', () => {
|
|
it('builds stat context + form/usage/matchup/rest from features', () => {
|
|
const f = buildIntelFields({ l20_avg: 26.9, l10_avg: 28.4, l5_avg: 30.1, usage_rate: 31.2, opp_rank_stat: 0.7, rest_days: 2 });
|
|
expect(f.season_avg).toBe(26.9);
|
|
expect(f.last10_avg).toBe(28.4);
|
|
expect(f.form).toBeGreaterThan(70);
|
|
expect(f.usage).toBe('31.2%');
|
|
expect(f.matchup_grade).toBe('A');
|
|
expect(f.rest).toBe('2d rest');
|
|
});
|
|
|
|
it('omits fields with no data (so the card sections self-hide)', () => {
|
|
expect(buildIntelFields({})).toEqual({});
|
|
});
|
|
|
|
it('feeds straight into the grade card via gradeAdapter', () => {
|
|
const engineLike = { player: 'Wemby', stat: 'points', line: 26.5, grade: 'A', ...buildIntelFields({ l20_avg: 26.9, l10_avg: 28.4, l5_avg: 30, usage_rate: 31.2, opp_rank_stat: 0.7 }) };
|
|
const card = mapScanToGradeResult(engineLike);
|
|
expect(card.statContext).toMatchObject({ season: '26.9', last10: '28.4' });
|
|
expect(card.vyndrIntel.matchup).toBe('A');
|
|
expect(card.vyndrIntel.usage).toBe('31.2%');
|
|
});
|
|
});
|