Files
vyndr/tests/unit/structuralGuards.test.js
T
builtbykev 8c764c22a4 Structural hardening: unknown-is-not-zero + takeability-is-book-identity
Both guards are ADDITIVE. The full suite (4,111 -> 4,126 tests, 331 suites)
passes unchanged through the migration, which is the evidence that no
currently-correct output moved: served path, champion, reference ruler and
the four accruing challengers are byte-identical.

GUARD 1 -- src/utils/known.js. Number(null)===0 has produced at least SIX
separate defects here, including one in a module written the same week its
author documented the trap. Per-module vigilance has demonstrably failed,
so the rule lives in one place and SEVEN sites now delegate: platoonSplits,
projectionChallenger, challengerProjection, contactChallenger,
statcastAggregateService, consensusRuler, gradeRanking -- plus
compoundTotalBases moved onto knownRate.

Two functions, deliberately: knownNumber (any finite number -- a REAL 0 is
a fact and must survive) and knownRate (non-negative, rejects booleans --
for counts/rates where `true` or -1 is broken, not thin). Collapsing them
is how the next variant gets in. firstKnown() exists because `a || b`
discards a measured 0 and `a ?? b` does not.

MY OWN GUARD HAD THE BUG IT EXISTS TO PREVENT, and its own test caught it:
Number([]) === 0, so an empty array coerced to a measured ZERO. Same trap
wearing a different type. Both helpers now reject objects outright.

GUARD 2 -- src/config/takeability.js. Takeability is BOOK IDENTITY and
never price shape. Baseball prop markets are genuinely thin, juiced and
one-sided, and all three are NORMAL structure: betrivers and hardrockbet
legitimately quote one side only (5 such rows surfaced in yesterday's
re-stamp), and a hits-over at -300 is a real placeable bet. A rule that
inferred un-takeability from price extremity or one-sidedness would throw
those away while still admitting a DFS book at an ordinary -119 -- exactly
backwards, because the -119 is the fake one.

THE DISTINCTION THAT MUST NOT COLLAPSE, now enforced by test:
  isTakeableMarket(book)  -- CAN it be bet?     (identity)
  isWithinPriceBand(odds) -- SHOULD we promote? (policy band, floor -160)
A -300 DraftKings prop is takeable AND out of band; a PrizePicks -119 is in
band AND not takeable. Independent axes.

FLAGGED, NOT SILENTLY CHANGED: the ledger's `takeable` column is the
PRICE-BAND answer, and its name predates this distinction. Four challengers
and the ranking gate read it, so renaming or redefining it is its own
order -- doing it here would have changed correct current behaviour under
cover of a hardening change.

Fixtures are REAL prod rows from the 2026-08-02 re-stamp, not invented.

Gates: 4,126 tests / 331 suites green; next build exit 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
2026-08-02 17:25:40 -04:00

150 lines
6.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.
'use strict';
/**
* STRUCTURAL GUARDS (2026-08-02) — two recurring failure families, locked.
*
* Both are the same principle: never silently convert something ABSENT or THIN
* into a false DEFINITE value.
*
* GUARD 1 unknown ≠ zero (`Number(null) === 0`, 6× recurring)
* GUARD 2 takeability = book identity, never price shape
*
* The fixtures are REAL rows from prod (2026-08-02 re-stamp), not invented.
*/
const { knownNumber, knownRate, isKnown, firstKnown } = require('../../src/utils/known');
const { isTakeableMarket, isWithinPriceBand, assessQuote } = require('../../src/config/takeability');
// ─────────────────────────────── GUARD 1 ───────────────────────────────
describe('GUARD 1 — unknown is not zero', () => {
it('every absent form is UNKNOWN, never 0', () => {
for (const v of [null, undefined, '', NaN, 'abc', {}, []]) {
expect(knownNumber(v)).toBeNull();
expect(isKnown(v)).toBe(false);
}
});
it('a REAL zero survives — 0 rest days is a fact, not an absence', () => {
expect(knownNumber(0)).toBe(0);
expect(isKnown(0)).toBe(true);
expect(knownRate(0)).toBe(0);
});
it('Infinity is not a measurement', () => {
expect(knownNumber(Infinity)).toBeNull();
expect(knownNumber(-Infinity)).toBeNull();
});
it('knownRate additionally rejects booleans and negatives', () => {
expect(knownRate(true)).toBeNull(); // Number(true) === 1
expect(knownRate(false)).toBeNull(); // Number(false) === 0 — the trap
expect(knownRate(-0.5)).toBeNull();
expect(knownNumber(-0.5)).toBe(-0.5); // a signed gap is legitimately negative
});
it('firstKnown prefers a present 0 over a later fallback (|| gets this wrong)', () => {
expect(firstKnown(0, 5)).toBe(0);
expect(firstKnown(null, 5)).toBe(5);
expect(firstKnown(null, undefined, '')).toBeNull();
});
it('REAL FIXTURE — a null triple rate must not read as "never triples"', () => {
const tb = require('../../src/services/projection/compoundTotalBases');
// Same components, one with an UNKNOWN triple rate vs a MEASURED zero.
const unknown = tb.tbPmf({ singles: 0.6, doubles: 0.2, triples: null, home_runs: 0.15 });
const zero = tb.tbPmf({ singles: 0.6, doubles: 0.2, triples: 0, home_runs: 0.15 });
// Both are computable, and an unknown component contributes nothing —
// but it must do so by being SKIPPED, not by being asserted as zero.
expect(unknown).not.toBeNull();
expect(zero).not.toBeNull();
// The guard that matters: no component usable at all → null, not a flat curve.
expect(tb.tbPmf({ singles: null, doubles: null, triples: null, home_runs: null })).toBeNull();
expect(tb.tbPmf({ singles: false })).toBeNull();
});
it('the migrated sites all delegate to the ONE rule', () => {
// Semantics must be identical across every migrated module, or the
// migration reintroduced drift.
const mods = [
require('../../src/utils/gradeRanking').strictNum,
require('../../src/services/consensusRuler').__internals.num,
];
for (const fn of mods) {
expect(fn(null)).toBeNull();
expect(fn('')).toBeNull();
expect(fn(0)).toBe(0);
expect(fn('2.5')).toBe(2.5);
}
});
});
// ─────────────────────────────── GUARD 2 ───────────────────────────────
describe('GUARD 2 — takeability is BOOK IDENTITY, never price shape', () => {
it('REAL FIXTURE — one-sided takeable markets are TAKEABLE', () => {
// Verified in prod: betrivers and hardrockbet quote one side only on real
// props (5 such rows surfaced in the 2026-08-02 re-stamp). One-sidedness is
// normal baseball market structure, not a defect.
expect(isTakeableMarket('betrivers')).toBe(true);
expect(isTakeableMarket('hardrockbet')).toBe(true);
// A one-sided quote: the other side is genuinely absent, and takeability
// does not depend on it at all.
expect(assessQuote({ book: 'betrivers', odds: 6600 }).takeable).toBe(true);
expect(assessQuote({ book: 'hardrockbet', odds: 400 }).takeable).toBe(true);
});
it('REAL FIXTURE — an extreme price is still TAKEABLE (steep juice is a price)', () => {
// Ohtani hits-over at -266 and Schwarber hits-over at -209 are real,
// placeable DraftKings bets.
for (const odds of [-266, -209, -300, -1400, 4900]) {
expect(assessQuote({ book: 'draftkings', odds }).takeable).toBe(true);
}
});
it('REAL FIXTURE — a DFS book at an ordinary -119 is NOT takeable', () => {
// The ordinary-looking price is the fake one: PrizePicks is not a
// sportsbook. Book identity decides, price shape never does.
for (const book of ['prizepicks', 'underdog', 'sleeper', 'dabble']) {
expect(isTakeableMarket(book)).toBe(false);
expect(assessQuote({ book, odds: -119 }).takeable).toBe(false);
}
});
it('exchanges and offshore are not takeable however normal the price looks', () => {
for (const book of ['kalshi', 'novig', 'smarkets', 'bovada', 'onexbet', 'pinnacle']) {
expect(isTakeableMarket(book)).toBe(false);
}
});
it('an ABSENT book is not takeable — we cannot assert a market we cannot name', () => {
for (const b of [null, undefined, '', 'not_a_book']) expect(isTakeableMarket(b)).toBe(false);
});
it('THE DISTINCTION: takeable and price-band are independent axes', () => {
// A -300 DraftKings prop is a REAL bet we would not promote. Both true.
const steep = assessQuote({ book: 'draftkings', odds: -300 });
expect(steep.takeable).toBe(true);
expect(steep.within_price_band).toBe(false);
const normal = assessQuote({ book: 'draftkings', odds: -110 });
expect(normal.takeable).toBe(true);
expect(normal.within_price_band).toBe(true);
// ...and a DFS book inside the band is still not takeable.
const dfs = assessQuote({ book: 'prizepicks', odds: -119 });
expect(dfs.takeable).toBe(false);
expect(dfs.within_price_band).toBe(true);
});
it('an UNKNOWN price is not an out-of-band price', () => {
expect(assessQuote({ book: 'draftkings', odds: null }).within_price_band).toBeNull();
expect(assessQuote({ book: 'draftkings' }).takeable).toBe(true); // book still decides
});
it('no drift: the canonical rule IS bookRoles.isTakeableBook', () => {
const { isTakeableBook } = require('../../src/config/bookRoles');
for (const b of ['draftkings', 'prizepicks', 'pinnacle', 'betrivers', null]) {
expect(isTakeableMarket(b)).toBe(isTakeableBook(b));
}
});
});