Honesty pass: remove every live fabrication (REMOVE/HIDE only, no feature cut)

Six live untruths corrected — no grade/snapshot/scorer/pipeline touched:
1. /compare — hardcoded Jokic A+/Wembanyama A + fake VERDICT replaced with an
   honest in-development state; removed from Nav + BottomTabBar (route still
   resolves, never the sample). Real two-player build is later.
2. Pricing — founder Desk $34.99→$44.99 (matches lib/checkout.js), Analyst
   $14.99; removed the struck $19.99/$44.99 "regular" numbers and DeskShowcase's
   stale $34.99. First-100 counter is real (ClaimMeter → Stripe countFounderSeats);
   no fake "first 50" desk claim added (no such counter exists).
3. FAQ "NexaPay" → Stripe (verified: live checkout is Next→Express→checkout.stripe.com).
4. FAQ + Features "Brier/CLV published from day one" removed (not surfaced yet) —
   returns when real. Backend Brier compute untouched.
5. MobileEdgeBoard removed from the Slate — its edge% feed was a miscalibrated
   placeholder (masked >40% as "—"); phones now show the real game cards.
6. Price triplet — never-computed model/EV now derives NO_MODEL (honest absent,
   MODEL "—" / "NOT PRICED", no verdict) instead of QUARANTINE's false "we
   suppressed our price / a leg is poisoned" copy. Fixes grade card + LiveHeroProp.

Full suite 3833 green, web build exit 0. Tests updated to the new honest contracts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VsztNChZ7vEvSR61AuMhD1
This commit is contained in:
Kev
2026-07-27 06:04:00 -04:00
parent be6b4a2849
commit 6bc18d823c
16 changed files with 100 additions and 132 deletions
+10 -7
View File
@@ -36,13 +36,16 @@ describe('Pricing — Desk is the hero, real prices, single primary CTA', () =>
expect(tierBlock(pricing, 'desk')).toBe('true');
});
test('real prices only — Desk $34.99 founder / $44.99 regular, Analyst $14.99/$19.99, Free 5 reads', () => {
expect(pricing).toMatch(/id: 'desk'[\s\S]*?price: '\$34\.99'/);
expect(pricing).toMatch(/id: 'desk'[\s\S]*?originalPrice: '\$44\.99'/);
test('real founder prices only — Desk $44.99, Analyst $14.99, no struck/unwired "regular" number, Free 5 reads', () => {
// Honesty pass: founder Desk = $44.99 (matches lib/checkout.js); Analyst = $14.99.
// The struck "regular" numbers ($19.99 / $34.99) were removed — the post-founder
// price is not wired, and we do not promise a figure that isn't.
expect(pricing).toMatch(/id: 'desk'[\s\S]*?price: '\$44\.99'/);
expect(pricing).toMatch(/id: 'analyst'[\s\S]*?price: '\$14\.99'/);
expect(pricing).toMatch(/id: 'analyst'[\s\S]*?originalPrice: '\$19\.99'/);
expect(pricing).toContain('5 reads to try the model');
// no fabricated legacy price
// no stale/fabricated founder numbers anywhere in the grid
expect(pricing).not.toContain('$34.99');
expect(pricing).not.toContain("originalPrice: '$19.99'");
expect(pricing).not.toContain("originalPrice: '$24.99'");
expect(pricing).not.toContain("originalPrice: '$49.99'");
});
@@ -55,8 +58,8 @@ describe('Pricing — Desk is the hero, real prices, single primary CTA', () =>
expect(showcase).toContain('Every grade, every alt line, live.');
expect(showcase).not.toContain('$1M');
expect(showcase).not.toContain('1M terminal');
expect(showcase).toContain('$44.99'); // the conversion hook figure
expect(showcase).toContain('$34.99'); // the founder price
expect(showcase).toContain('$44.99'); // the founder price (first 100)
expect(showcase).not.toContain('$34.99'); // stale founder price — removed
// real feature visuals fill the right half (kills the dead half, #8)
expect(showcase).toContain('ALT LINE LADDER');
expect(showcase).toContain('QUARTER-KELLY');
+13 -7
View File
@@ -157,9 +157,13 @@ describe('deriveValueState — the single verdict function', () => {
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 missing model price or EV → NO_MODEL (absent leg), never NO EDGE and never QUARANTINE', () => {
// Honesty pass: never-computed is NOT a deliberate quarantine, so it must
// not wear QUARANTINE's "we suppressed / a leg is poisoned" copy.
expect(vs.deriveValueState({ ...base, model_odds: null })).toBe(vs.STATES.NO_MODEL);
expect(vs.deriveValueState({ ...base, ev_pct: null })).toBe(vs.STATES.NO_MODEL);
// A real quarantine_reason still quarantines (distinct from never-computed).
expect(vs.deriveValueState({ ...base, model_odds: null, quarantine_reason: 'x' })).toBe(vs.STATES.QUARANTINE);
});
it('a LOCKED model leg is neither quarantine nor refusal', () => {
@@ -174,7 +178,7 @@ describe('valueStateColor — green appears on exactly one state', () => {
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,
vs.STATES.REFUSAL, vs.STATES.NO_VERDICT_LOCKED, vs.STATES.NO_MODEL,
];
for (const s of others) expect(vs.valueStateColor(s)).not.toBe('var(--g-a)');
});
@@ -263,11 +267,13 @@ describe('PriceTriplet component', () => {
// ── 6b. CONSUMERS MUST FORWARD THE LOCK FLAG ─────────────────────────────
describe('a gated model leg never wears quarantine copy', () => {
it('deriveValueState separates GATED from WITHHELD', () => {
it('deriveValueState separates GATED (locked) from NEVER-COMPUTED — neither is QUARANTINE', () => {
const gated = { book_odds: -153, fair_odds: -129, model_odds: null, ev_pct: null, model_price_locked: true };
const withheld = { book_odds: -153, fair_odds: -129, model_odds: null, ev_pct: null };
const neverComputed = { book_odds: -153, fair_odds: -129, model_odds: null, ev_pct: null };
expect(vs.deriveValueState(gated)).toBe(vs.STATES.NO_VERDICT_LOCKED);
expect(vs.deriveValueState(withheld)).toBe(vs.STATES.QUARANTINE);
// Honesty pass: a never-computed model leg is NO_MODEL (absent), NOT quarantine
// — it must not claim we "suppressed" a price we never produced.
expect(vs.deriveValueState(neverComputed)).toBe(vs.STATES.NO_MODEL);
});
it('LiveHeroProp forwards model_price_locked (live bug: it did not)', () => {
+3 -1
View File
@@ -43,9 +43,11 @@ describe('Phase F — BottomTabBar (5-tab spec)', () => {
describe('Phase F — More bottom sheet', () => {
const src = read('components/BottomTabBar.tsx');
it('lists the secondary routes', () => {
['/compare', '/tracker', '/blog', '/invite', '/pricing', '/account', '/help', '/about', '/responsible-gambling'].forEach((href) =>
// Compare removed from nav (honesty pass — in development, no real feed).
['/tracker', '/blog', '/invite', '/pricing', '/account', '/help', '/about', '/responsible-gambling'].forEach((href) =>
expect(src).toContain(href),
);
expect(src).not.toContain('/compare');
});
it('slides up with a dismissible backdrop', () => {
expect(src).toContain('sheet-up');
+13 -20
View File
@@ -182,23 +182,14 @@ describe('M1 — mobile foundation is wired (structural, not visual)', () => {
describe('M4 — mobile structural rules locked (source, not visual)', () => {
const css = read('app/globals.css');
it('the flat EDGE BOARD is the mobile board; game cards are desktop-only', () => {
// Design screen 01: <768px shows the flat edge-ranked board, ≥768px keeps
// the game-grouped cards.
expect(css).toMatch(/\.edge-board-mobile\s*\{\s*display:\s*none/);
expect(css).toMatch(/@media\s*\(max-width:\s*767px\)[^]*?\.edge-board-mobile\s*\{\s*display:\s*block/);
expect(css).toMatch(/\.edge-board-desktop\s*\{\s*display:\s*none\s*!important/);
it('the fabricated mobile edge board is REMOVED — phones show the real game cards', () => {
// Honesty pass: MobileEdgeBoard's edge% feed was a miscalibrated placeholder
// (it masked any value >40% to "—"). It renders nowhere until a real edge
// feed exists. The Slate no longer imports or renders it; mobile now shows
// the same real game cards as desktop.
const slate = read('components/Slate.tsx');
expect(slate).toMatch(/MobileEdgeBoard/);
expect(slate).toMatch(/flattenToEdgeBoard/);
});
it('the mobile edge board renders matchup chips + tier grade + one hero edge%', () => {
const b = read('components/vyndr/MobileEdgeBoard.tsx');
expect(b).toMatch(/TeamChip/); // Rev 3 matchup chips
expect(b).toMatch(/GradeBadge/); // tier-colored grade
expect(b).toMatch(/var\(--miss\)/); // negative edge = red by sign
expect(b).toMatch(/rampOpacity/); // Design's ranked opacity ramp
expect(slate).not.toMatch(/MobileEdgeBoard/);
expect(slate).not.toMatch(/flattenToEdgeBoard/);
});
it('document still never scrolls sideways on phones (overflow contained)', () => {
@@ -290,12 +281,14 @@ describe('P1-7 — edge board guards the broken edge placeholder', () => {
});
});
// ── P1-8 lock — Compare verdict makes no unverifiable "tonight" claim ────────
describe('P1-8 — Compare verdict is time-honest (form, not a phantom game)', () => {
// ── P1-8 lock — Compare ships NO fabrication (honest in-development state) ────
describe('P1-8 — Compare carries no hardcoded grades or phantom verdict', () => {
const compare = read('app/compare/page.tsx');
it('the sample verdict never claims "tonight" (NBA has 0 games in July)', () => {
it('no sample players, no fake verdict, no "tonight" claim — honest in-dev', () => {
expect(compare).not.toMatch(/edge tonight/i);
expect(compare).toMatch(/on current form/i);
expect(compare).not.toMatch(/Joki|Wembanyama/);
expect(compare).not.toContain('VYNDR VERDICT');
expect(compare).toMatch(/IN DEVELOPMENT/i);
});
});
+4 -3
View File
@@ -84,10 +84,11 @@ describe('Phase E.3 — stubs are now real pages', () => {
it.each(pages)('/%s is no longer a RouteStub', (p) => {
expect(read(`app/${p}/page.tsx`)).not.toContain('RouteStub');
});
it('compare renders two player inputs + a verdict', () => {
it('compare shows an honest in-development state — no sample grades, no fake verdict', () => {
const src = read('app/compare/page.tsx');
expect((src.match(/TerminalInput/g) || []).length).toBeGreaterThanOrEqual(2);
expect(src).toContain('VYNDR VERDICT');
expect(src).toMatch(/IN DEVELOPMENT/i);
expect(src).not.toContain('VYNDR VERDICT');
expect(src).not.toMatch(/Joki|Wembanyama/); // no hardcoded sample players
});
it('invite renders the 3-friends referral messaging', () => {
expect(read('app/invite/page.tsx')).toContain('3 friends');