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>
This commit is contained in:
@@ -406,6 +406,50 @@ async function analyzeViaEngine1(rawProp = {}) {
|
||||
// ledger model_value and rendered under the MODEL label on the card.
|
||||
legacy.projection = projection;
|
||||
|
||||
// Session 62 (A1-S1) — ALT LINE LADDER + EDGE RANKING. The pricing page
|
||||
// sold it; the adapter/card were already built for it; nothing produced
|
||||
// it. Re-grade the SAME feature vector at shifted lines (zero extra I/O)
|
||||
// and rank by edge. Attached for every graded result; the API tier gate
|
||||
// strips it below Desk.
|
||||
try {
|
||||
const baseLine = Number(prop.line);
|
||||
if (Number.isFinite(baseLine)) {
|
||||
const ladder = [-1, -0.5, 0, 0.5, 1]
|
||||
.map((shift) => Math.round((baseLine + shift) * 100) / 100)
|
||||
.filter((ln) => ln > 0)
|
||||
.map((ln) => {
|
||||
const shiftedProp = { ...prop, line: ln };
|
||||
const g = engine1.gradeProp({ features, trap, consistency, prop: shiftedProp });
|
||||
const adapted = toLegacyShape(g, {
|
||||
player: rawProp.player, stat_type: rawProp.stat_type,
|
||||
line: ln, direction: prop.direction, book: rawProp.book || 'unknown', sport: meta.sport,
|
||||
}, { edgePct: edgePctFor(features, { ...shiftedProp, stat_type: rawProp.stat_type, direction: prop.direction }) });
|
||||
return { line: ln, grade: adapted.grade, edge_pct: adapted.edge_pct, base: ln === baseLine };
|
||||
})
|
||||
.sort((a, b) => (Number(b.edge_pct) || 0) - (Number(a.edge_pct) || 0));
|
||||
if (ladder.length > 1) legacy.alt_lines = ladder;
|
||||
}
|
||||
} catch { /* the ladder is additive — never breaks the read */ }
|
||||
|
||||
// Session 62 (A1-S1) — QUARTER-KELLY. Real probability (quantile estimator
|
||||
// over the actual game logs) × real book odds, or nothing. Never derived
|
||||
// from confidence, never a default vig.
|
||||
try {
|
||||
const { estimateProbability } = require('./probabilityEstimator');
|
||||
const est = estimateProbability({ gameLogs: meta.gameLogs, line: prop.line, statType: rawProp.stat_type, features });
|
||||
const pWin = String(prop.direction || 'over').toLowerCase() === 'under'
|
||||
? (Number.isFinite(est.p_over) ? 1 - est.p_over : null)
|
||||
: (Number.isFinite(est.p_over) ? est.p_over : null);
|
||||
if (pWin != null) legacy.p_win = Math.round(pWin * 1000) / 1000;
|
||||
const sideOdds = String(prop.direction || 'over').toLowerCase() === 'under'
|
||||
? rawProp.under_odds : rawProp.over_odds;
|
||||
if (pWin != null && sideOdds != null) {
|
||||
const { quarterKelly } = require('../../utils/kelly');
|
||||
const k = quarterKelly(pWin, sideOdds);
|
||||
if (k) legacy.kelly = { ...k, odds: String(sideOdds) };
|
||||
}
|
||||
} catch { /* sizing is additive — absent beats wrong */ }
|
||||
|
||||
return legacy;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user