Files
vyndr/tests/unit/priceTriplet.test.js
T
builtbykev 8cf9cbfc26 Price-layer token foundation + the price triplet, built natively on it
PHASE 0 finding, reported before building: the token layer this order asked
me to establish ALREADY EXISTS and already matches HANDOFF.md exactly.
web/src/app/globals.css :root carries the design's surfaces, borders, text
ramp, fonts and grade colours byte-for-byte (aligned 2026-07-16), and
lib/colorContract.js already encodes the green-is-edge-only and
glow-is-A-tier-only laws with a test enforcing them. The stack is Tailwind v4
CSS-first (no config file) with components styled by inline style={{}} reading
var(--x) — 1,916 such reads — so CSS custom properties are the only vehicle
the stack natively consumes. Creating a second parallel layer would have meant
two competing sources of truth, so this EXTENDS the existing one.

PHASE 1 — additive only. globals.css gains one colour the system did not have,
the priced-out blue (#8fb2de + tints), plus a tokenized A-tier glow and the
fair-leg tints. The block writes the LAWS into the token layer itself — green
= takeable edge only, glow = A-tier only, amber = caution + the fair leg, red
= miss/negative only, blue = edge priced out, JetBrains Mono = all data — and
a test asserts every newly-declared name is new (zero collisions, zero
overrides). No existing hardcoded style was touched and no live surface was
migrated: the diff over existing files is 149 insertions, 0 deletions.

PHASE 2 — lib/valueState.js is the single verdict function; the component
renders what it returns and never re-derives one. VALUE fires only on
ev >= 2 AND a takeable price, mirroring src/config/valueEngine.js with a test
that cross-checks both files and fails on drift. Five states: VALUE (green),
EDGE-NOT-TAKEABLE (blue), NO EDGE (grey, stated at full voice), QUARANTINE
(model leg withheld, book+fair stand), REFUSAL (nothing rendered). Free tier
is gated at the wire — tierGating strips model_odds and sets
model_price_locked, so the lock is real rather than a blur over data already
sent; book and fair pass through on every tier because the fair leg is never
the paywall. Wired into the landing hero (data was already on /api/hero-prop)
and the read card, where the projection block reads first and the triplet sits
beside it, not in place of it. Ledger and public profile are out of scope —
no fair-odds columns exist there.

PHASE 3 — induced all six states in a real browser and read back computed
styles, not just markup. Green resolves on VALUE alone: rgb(0,212,160) on the
model leg and verdict; the +11.7%-EV-at-210 row renders rgb(143,178,222) blue
and a white model leg; quarantine shows MODEL "—" with book and fair intact;
refusal renders no legs at all; free tier renders a lock bar with book -120 and
fair -104 still honest. Landing hero on live data: book -153, fair -129, model
-343, VALUE +21.1% vs fair at +28.1% EV. At a real 390px column the three legs
hold at 117px each with no horizontal overflow and fair no smaller than its
neighbours.

Induction caught a real bug that markup review would not have: the "VS FAIR"
figure compared BOOK to fair, printing "VALUE · -6.5% VS FAIR" — a
contradiction on screen. The design's own two worked examples pin the formula
as MODEL minus FAIR in implied-probability percentage points; modelVsFair now
reproduces both exactly (+2.9 and -1.8) and a test locks them. The figure is
shown only when its sign agrees with the verdict, so a row that clears the EV
bar on the book price while our price sits level with fair leads with the EV
instead of a number that reads as a contradiction.

Tests 3539 passed / 290 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
2026-07-20 18:22:00 -04:00

302 lines
13 KiB
JavaScript

/* ============================================================
Session 66 — THE PRICE LAYER: token layer + the five honesty states.
Two things are locked here:
1. The TOKEN LAYER is additive and complete — the design bundle's values
exist in globals.css and match HANDOFF.md byte-for-byte.
2. The LAWS are enforceable, not folklore — the verdict function is the
single place "is this value?" is answered, and it can never say VALUE
on a juiced price.
============================================================ */
const fs = require('fs');
const path = require('path');
const ROOT = path.join(__dirname, '..', '..');
const read = (rel) => fs.readFileSync(path.join(ROOT, rel), 'utf8');
const CSS = read('web/src/app/globals.css');
const HANDOFF = read('specs/design-reference/HANDOFF.md');
const vs = require('../../web/src/lib/valueState');
const backendValue = require('../../src/config/valueEngine');
// ── 1. TOKEN LAYER — the design's values, present and correct ────────────
describe('token layer — HANDOFF values resolve in globals.css', () => {
// Each entry: [css custom property, expected hex, why it exists]
const TOKENS = [
['--bg-0', '#06060B'], // void
['--bg-1', '#0E0E14'], // card
['--bg-2', '#14141E'], // elevated
['--hairline', '#101018'], // row hairline
['--bg-deep', '#0A0A10'], // deep panel
['--border', '#1E1E2A'],
['--border-hi', '#2A2A38'],
['--text-0', '#F0F0F0'],
['--text-1', '#B8BCC8'],
['--text-2', '#707080'],
['--text-3', '#4a4a58'],
['--g-a', '#00d4a0'], // signal green
['--amber', '#ffb347'],
['--miss', '#FF4757'],
['--priced-out', '#8fb2de'], // NEW this session
];
test.each(TOKENS)('%s is declared as %s', (name, hex) => {
const m = CSS.match(new RegExp(`${name}\\s*:\\s*([^;]+);`));
expect(m).toBeTruthy();
expect(m[1].trim().toLowerCase()).toBe(hex.toLowerCase());
});
it('every hex above also appears in HANDOFF.md (design is the source)', () => {
// The priced-out blue comes from the triplet file, not HANDOFF's token list.
for (const [, hex] of TOKENS.filter(([n]) => n !== '--priced-out')) {
expect(HANDOFF.toLowerCase()).toContain(hex.toLowerCase());
}
});
it('grade colors follow the design: A green, B white, C grey, D/F red', () => {
expect(CSS).toMatch(/--g-a:\s*#00d4a0/i);
expect(CSS).toMatch(/--g-b:\s*#F0F0F0/i);
expect(CSS).toMatch(/--g-c:\s*#B8BCC8/i);
expect(CSS).toMatch(/--g-d:\s*#FF4757/i);
});
it('fonts: Inter for chrome, JetBrains Mono for ALL data', () => {
expect(CSS).toMatch(/--sans:[^;]*Inter/);
expect(CSS).toMatch(/--mono:[^;]*JetBrains Mono/);
});
it('the laws are written INTO the token layer, not left as folklore', () => {
const block = CSS.slice(CSS.indexOf('SESSION 66 — PRICE-LAYER TOKENS'));
expect(block).toMatch(/GREEN = EDGE ONLY/);
expect(block).toMatch(/GLOW = A-TIER ONLY/);
expect(block).toMatch(/AMBER = CAUTION/);
expect(block).toMatch(/RED = MISS \/ NEGATIVE only/i);
expect(block).toMatch(/BLUE = EDGE PRICED OUT/);
expect(block).toMatch(/JETBRAINS MONO = ALL DATA/);
});
it('is ADDITIVE — the new block declares only new names', () => {
// Bound the block to the Session-66 section itself: globals.css continues
// past :root with a11y/media layers that legitimately re-declare tokens.
const start = CSS.indexOf('SESSION 66 — PRICE-LAYER TOKENS');
const block = CSS.slice(start, CSS.indexOf('\n}', start));
const declared = [...block.matchAll(/^\s*(--[a-z0-9-]+)\s*:/gim)].map((m) => m[1]);
expect(declared.length).toBeGreaterThan(0);
// None of the newly-declared names may collide with a pre-existing token.
const before = CSS.slice(0, CSS.indexOf('SESSION 66 — PRICE-LAYER TOKENS'));
for (const name of declared) {
expect(before).not.toMatch(new RegExp(`^\\s*${name}\\s*:`, 'm'));
}
});
});
// ── 2. THE BAND — frontend law mirrors the backend engine ────────────────
describe('takeable band + EV threshold stay in sync with the backend', () => {
it('mirrors src/config/valueEngine.js exactly', () => {
expect(vs.TAKEABLE_ODDS_CEILING).toBe(backendValue.TAKEABLE_ODDS_CEILING);
expect(vs.TAKEABLE_ODDS_MAX).toBe(backendValue.TAKEABLE_ODDS_MAX);
expect(vs.VALUE_EV_THRESHOLD).toBe(backendValue.VALUE_EV_THRESHOLD);
});
it('agrees with the backend on isTakeable / isValue across the band', () => {
const prices = [-400, -210, -161, -160, -110, 100, 200, 201, 500, null, undefined, ''];
for (const p of prices) {
expect(vs.isTakeable(p)).toBe(backendValue.isTakeable(p));
for (const ev of [-58.7, 0, 1.9, 2, 11.7, 26.5]) {
expect(vs.isValue(p, ev)).toBe(backendValue.isValue(p, ev));
}
}
});
it('a missing price is NEVER takeable (Number(null) === 0 guard)', () => {
expect(vs.isTakeable(null)).toBe(false);
expect(vs.isTakeable('')).toBe(false);
expect(vs.isTakeable(undefined)).toBe(false);
});
});
// ── 3. THE FIVE HONESTY STATES ───────────────────────────────────────────
describe('deriveValueState — the single verdict function', () => {
const base = { book_odds: -120, fair_odds: -104, model_odds: -196, ev_pct: 21.4 };
it('VALUE — real edge at a takeable price (the live Petey Halpin row)', () => {
expect(vs.deriveValueState(base)).toBe(vs.STATES.VALUE);
});
it('PRICED OUT — positive EV at a juiced price (the live Josh Bell row)', () => {
// book -210, +11.7% EV: the engine refuses to call this value, and so do we.
const row = { book_odds: -210, fair_odds: -173, model_odds: -311, ev_pct: 11.7 };
expect(vs.deriveValueState(row)).toBe(vs.STATES.PRICED_OUT);
});
it('NEVER calls raw positive EV "value" — the whole point of state 2', () => {
for (const [book, ev] of [[-210, 11.7], [-190, 26.5], [-400, 60], [250, 30]]) {
const st = vs.deriveValueState({ book_odds: book, fair_odds: -150, model_odds: -300, ev_pct: ev });
expect(st).not.toBe(vs.STATES.VALUE);
expect(st).toBe(vs.STATES.PRICED_OUT);
}
});
it('EV below the threshold is NO EDGE even at a takeable price', () => {
expect(vs.deriveValueState({ ...base, ev_pct: 0.2 })).toBe(vs.STATES.NO_EDGE);
expect(vs.deriveValueState({ ...base, ev_pct: 1.99 })).toBe(vs.STATES.NO_EDGE);
expect(vs.deriveValueState({ ...base, ev_pct: 2 })).toBe(vs.STATES.VALUE); // boundary
});
it('QUARANTINE — model leg withheld, book + fair still stand', () => {
const row = { ...base, quarantine_reason: 'wrong_opponent_grade' };
expect(vs.deriveValueState(row)).toBe(vs.STATES.QUARANTINE);
});
it('REFUSAL — no fair price we would defend', () => {
expect(vs.deriveValueState({ ...base, fair_odds: null })).toBe(vs.STATES.REFUSAL);
expect(vs.deriveValueState({ ...base, book_odds: null })).toBe(vs.STATES.REFUSAL);
expect(vs.deriveValueState({ ...base, refused: true })).toBe(vs.STATES.REFUSAL);
expect(vs.deriveValueState({})).toBe(vs.STATES.REFUSAL);
});
it('a missing model price or EV withholds the verdict — never asserts NO EDGE', () => {
expect(vs.deriveValueState({ ...base, model_odds: null })).toBe(vs.STATES.QUARANTINE);
expect(vs.deriveValueState({ ...base, ev_pct: null })).toBe(vs.STATES.QUARANTINE);
});
it('a LOCKED model leg is neither quarantine nor refusal', () => {
const row = { ...base, model_price_locked: true };
expect(vs.deriveValueState(row)).toBe(vs.STATES.NO_VERDICT_LOCKED);
});
});
// ── 4. THE COLOR LAW ─────────────────────────────────────────────────────
describe('valueStateColor — green appears on exactly one state', () => {
it('VALUE is the ONLY green', () => {
expect(vs.valueStateColor(vs.STATES.VALUE)).toBe('var(--g-a)');
const others = [
vs.STATES.PRICED_OUT, vs.STATES.NO_EDGE, vs.STATES.QUARANTINE,
vs.STATES.REFUSAL, vs.STATES.NO_VERDICT_LOCKED,
];
for (const s of others) expect(vs.valueStateColor(s)).not.toBe('var(--g-a)');
});
it('PRICED OUT is the blue carve-out; NO EDGE is never red', () => {
expect(vs.valueStateColor(vs.STATES.PRICED_OUT)).toBe('var(--priced-out)');
// An honest "no" is the instrument working, not a loss.
expect(vs.valueStateColor(vs.STATES.NO_EDGE)).not.toBe('var(--miss)');
});
it('QUARANTINE is amber (caution), per the token law', () => {
expect(vs.valueStateColor(vs.STATES.QUARANTINE)).toBe('var(--amber)');
});
});
// ── 5. HONEST ABSENCE ────────────────────────────────────────────────────
describe('never prints a number it cannot stand behind', () => {
it('fmtOddsAmerican returns null for absence — never 0, never a placeholder', () => {
expect(vs.fmtOddsAmerican(null)).toBeNull();
expect(vs.fmtOddsAmerican('')).toBeNull();
expect(vs.fmtOddsAmerican(undefined)).toBeNull();
expect(vs.fmtOddsAmerican('abc')).toBeNull();
expect(vs.fmtOddsAmerican(-210)).toBe('-210');
expect(vs.fmtOddsAmerican(125)).toBe('+125');
});
it('modelVsFair is null unless BOTH legs are real', () => {
expect(vs.modelVsFair(null, -110)).toBeNull();
expect(vs.modelVsFair(-110, null)).toBeNull();
expect(typeof vs.modelVsFair(98, 110)).toBe('number');
});
it('reproduces the design file\'s own worked examples EXACTLY', () => {
// The design states these two figures; the formula was derived from them.
// STATE 1: book +125 · fair +110 · model +98 → "+2.9% VS FAIR"
expect(vs.modelVsFair(98, 110)).toBe(2.9);
// STATE 3: book +118 · fair +104 · model +112 → "-1.8% VS FAIR"
expect(vs.modelVsFair(112, 104)).toBe(-1.8);
});
it('compares MODEL to FAIR — not book to fair (the induction bug)', () => {
// Petey Halpin, live: book -120 · fair -104 · model -196. Our price is far
// shorter than fair, so the gap is strongly POSITIVE. Comparing the book
// to fair instead produced -6.5% on a VALUE row — a visible contradiction.
expect(vs.modelVsFair(-196, -104)).toBeGreaterThan(10);
});
});
// ── 6. THE COMPONENT carries the rulings ─────────────────────────────────
describe('PriceTriplet component', () => {
const src = read('web/src/components/vyndr/PriceTriplet.tsx');
it('uses ONLY tokens — no literal hex anywhere', () => {
const hexes = src.match(/#[0-9a-f]{3,8}\b/gi) || [];
expect(hexes).toEqual([]);
});
it('does not re-derive the verdict — it renders deriveValueState', () => {
expect(src).toContain('deriveValueState');
expect(src).not.toMatch(/ev_pct\s*>=\s*2/);
});
it('FAIR is the amber hero and is never locked', () => {
expect(src).toMatch(/label="FAIR"[\s\S]{0,200}var\(--amber\)/);
expect(src).not.toMatch(/label="FAIR"[\s\S]{0,200}locked/);
});
it('only the MODEL leg is lockable / withheld', () => {
expect(src).toMatch(/label="MODEL"[\s\S]{0,300}locked=\{modelLocked\}/);
});
it('carries no sample numbers from the design file', () => {
// Strip comments first — the docblock names the design's sample values in
// order to say they are a SPEC and must never ship as data.
const code = src.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
for (const sample of ['1,188', '1,115.5', '+125', '+110', '+98', '+130', '+116']) {
expect(code).not.toContain(sample);
}
});
it('REFUSAL renders no legs and no gauge', () => {
const refusal = src.slice(src.indexOf('STATES.REFUSAL'));
expect(refusal).toContain("CAN&rsquo;T PRICE THIS ONE");
});
});
// ── 7. THE SERVER GATE — fair is never the paywall ───────────────────────
describe('free-tier gate strips the model price at the wire', () => {
const { applyTierGating } = require('../../src/utils/tierGating');
const row = {
grade: 'B', book_odds: -120, fair_odds: -104, model_odds: -196, ev_pct: 21.4,
};
it('free: model_odds is REMOVED, book + fair survive', () => {
const out = applyTierGating(row, 'free');
expect(out.model_odds).toBeUndefined();
expect(out.book_odds).toBe(-120);
expect(out.fair_odds).toBe(-104);
expect(out.model_price_locked).toBe(true);
});
it('analyst + desk: the full triplet passes through', () => {
for (const tier of ['analyst', 'desk']) {
const out = applyTierGating(row, tier);
expect(out.model_odds).toBe(-196);
expect(out.model_price_locked).toBeUndefined();
}
});
it('the adapter turns a stripped row into a LOCK, not an absent leg', () => {
const { buildPriceTriplet } = require('../../web/src/lib/gradeAdapter');
const gated = applyTierGating(row, 'free');
const t = buildPriceTriplet(gated).priceTriplet;
expect(t.model_odds).toBeNull();
expect(t.model_price_locked).toBe(true);
expect(vs.deriveValueState(t)).toBe(vs.STATES.NO_VERDICT_LOCKED);
});
it('no book/fair → no price story at all (section hidden, not empty)', () => {
const { buildPriceTriplet } = require('../../web/src/lib/gradeAdapter');
expect(buildPriceTriplet({ grade: 'B' })).toEqual({});
expect(buildPriceTriplet({ book_odds: -120 })).toEqual({});
});
});