Files
vyndr/tests/unit/promiseAudit.test.js
T
builtbykev d242b11b4b S1 (a1): feature-promise audit — no claim survives unverified
PROMISE-AUDIT.md: every /pricing claim → verified/built/reworded.
BUILT (was vapor): alt line ladder + edge ranking (same-features regrade
at shifted lines, Desk-gated at the API), quarter-Kelly (engine quantile
P(win) x real captured odds — either missing → no sizing), free-tier
kill-condition locked previews. FIXED (was false): analyst 15/day cap vs
the Founder 'Unlimited reads' promise → analyst unlimited; every '40+
factors' claim (real count: 22 named features) reworded truthfully in 7
files. VERIFIED: cascade alerts (real, wired), phi correlation,
leg history, cross-book comparison, WC soccer, real-time feed.
Locked by tests/unit/promiseAudit.test.js. Jest now ignores
.claude/worktrees (parallel agents' suites no longer leak into runs).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 14:24:41 -04:00

86 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Session 62 (A1-S1) — the feature-promise locks. Every pricing claim that
// was vapor is now real, and these tests keep it that way.
const { quarterKelly, americanToDecimal } = require('../../src/utils/kelly');
const { applyTierGating } = require('../../src/utils/tierGating');
const { getScanLimit } = require('../../src/config/tiers');
const fs = require('fs');
const path = require('path');
const WEB = path.join(__dirname, '..', '..', 'web', 'src');
const read = (rel) => fs.readFileSync(path.join(WEB, rel), 'utf8');
describe('quarter-Kelly (pricing: "Quarter-Kelly sizing recommendations")', () => {
test('computes from real probability × real odds', () => {
// p=0.55 at -110: b=0.909, f=(0.909*0.55-0.45)/0.909 ≈ 0.055 → quarter ≈ 1.4%
const k = quarterKelly(0.55, -110);
expect(k.quarter).toBeCloseTo(0.0138, 3);
expect(k.pct).toBeCloseTo(1.4, 1);
});
test('no edge → null (Kelly says: no bet, never a fabricated size)', () => {
expect(quarterKelly(0.5, -110)).toBeNull();
});
test('missing inputs → null, never defaults', () => {
expect(quarterKelly(null, -110)).toBeNull();
expect(quarterKelly(0.6, null)).toBeNull();
expect(quarterKelly(1.2, -110)).toBeNull();
});
test('american conversion both signs', () => {
expect(americanToDecimal(-110)).toBeCloseTo(1.909, 3);
expect(americanToDecimal(150)).toBeCloseTo(2.5, 3);
});
});
describe('Desk-only gate at the API (alt ladder + kelly never leave the server below Desk)', () => {
const RESULT = { grade: 'A', confidence: 70, alt_lines: [{ line: 1.5, grade: 'A' }], kelly: { pct: 1.4 }, reasoning: { summary: 'x' }, kill_conditions_triggered: [] };
test('desk keeps both', () => {
const g = applyTierGating(RESULT, 'desk');
expect(g.alt_lines).toBeTruthy();
expect(g.kelly).toBeTruthy();
});
test('analyst loses both, keeps reasoning', () => {
const g = applyTierGating(RESULT, 'analyst');
expect(g.alt_lines).toBeUndefined();
expect(g.kelly).toBeUndefined();
expect(g.reasoning.summary).toBe('x');
});
test('free loses both AND gets locked reasoning', () => {
const g = applyTierGating(RESULT, 'free');
expect(g.alt_lines).toBeUndefined();
expect(g.kelly).toBeUndefined();
expect(g.reasoning.locked).toBe(true);
});
});
describe('read limits match the pricing page', () => {
test('free 3/day · africa 10/day · analyst unlimited (Founder promise) · desk unlimited', () => {
expect(getScanLimit('free')).toBe(3);
expect(getScanLimit('africa')).toBe(10);
expect(getScanLimit('analyst')).toBe(Infinity);
expect(getScanLimit('desk')).toBe(Infinity);
});
});
describe('no unverifiable factor-count claims anywhere', () => {
it.each([
'components/Pricing.tsx', 'app/help/page.tsx', 'app/about/page.tsx',
'app/upgrade/desk/page.tsx', 'components/GradeCard.tsx',
'components/vyndr/GradeResultCard.tsx', 'components/vyndr/ProcessingGrade.tsx',
])('%s carries no "40+" claim', (rel) => {
expect(read(rel)).not.toContain('40+');
});
});
describe('free tier sees the promised LOCKED PREVIEW of kill conditions', () => {
const { mapScanToGradeResult } = require('../../web/src/lib/gradeAdapter');
test('free gets code-only teaser chips; analyst gets reasons', () => {
const input = {
player: 'X', stat: 'hits', line: 1.5, direction: 'over', grade: 'B',
kill_conditions: [{ code: 'TRAP', reason: 'Multiple trap signals firing.' }],
};
const free = mapScanToGradeResult({ ...input, tier: 'free' });
expect(free.killConditions).toEqual(['TRAP — upgrade to see details']);
const paid = mapScanToGradeResult({ ...input, tier: 'analyst' });
expect(paid.killConditions).toEqual(['Multiple trap signals firing.']);
});
});