Commit Graph

5 Commits

Author SHA1 Message Date
builtbykev 1372e6bcf7 Order Zero Phases 1-3: keyed verification, ruler_version boundary, report
PHASE 1 (measured on the live prod feed with the real key):

- WNBA is NOT thin at the feed -- 4.21 books/prop vs MLB's 3.61. It was
  allow-list-starved exactly as MLB was. This removes one candidate
  explanation for its anti-predictive result; it does not explain it, and
  WNBA stays abstaining.
- We cannot see 64.8% of the MLB slate at all (zero admitted books).
- Exchanges are real (smarkets 27%, novig 22%, kalshi 15% on MLB) but
  pinnacle, matchbook and polymarket measured 0% on BOTH sports. There is
  no sharp anchor for player props. The consensus is a MARKET consensus,
  not a SHARP one -- recorded as a permanent limitation, not a milestone.
- DFS is the trap, quantified: prizepicks covers 82% of MLB props, the
  highest in the feed. Admitting it "for breadth" would have looked like
  the biggest available win. Permanently excluded.
- Endpoints: /context WORKS and is FREE (umpire, roof, pitcher handedness,
  lineup confirmation -- richer than what we hand-built). /odds/closing and
  /movement are REDACTED (full structure, zero prices). /results and
  /exports/resolved-props are 403.
- The $19/mo question is answered: soccer IS graded, ~15 competitions in 30
  days (MLS 41k, Liga MX 15k, Brasileirao 12k, UCL/Europa/Conference). Our
  "soccer grades into a void" is a Pro-tier problem, not a data problem.
  NBA is absent because it is July -- seasonal, not inferable either way.

PHASE 2 delta, corrected: MLB mean +1.50 pts, median 0, p90 +10.0, 17.0%
of comparable props move >=5 pts, one-directional (the incumbent prices
the over below the exchange-inclusive consensus). WNBA symmetric and
tight. The median prop does not move -- the change is a right-skewed
minority. That the rulers DIFFER is established; that the new one is
BETTER is not, and that is the re-run.

PHASE 2 item 6: ledger_entries.ruler_version applied to prod, 1,384
existing rows backfilled to v1_first_book (a statement of fact -- every
row to date was produced by the first-book rule). ledgerService stamps
CURRENT_RULER_VERSION on new rows. Never pool edge or CLV across it.

Repo migration numbering lags prod; 025_ledger_ruler_version.sql records
the DDL for review.

PHASE 3: MLB isotonic p_win remains PROVISIONAL -- calibrated against
v1_first_book, does not promote until re-run on the consensus ruler.

NOT LIVE, deliberately: ALLOWED_BOOKS unchanged, served slate
byte-identical, CURRENT_RULER_VERSION still v1_first_book, no live path
calls consensusRuler.

Gates: 4,022 tests passed / 322 suites; next build exit 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
2026-07-31 23:52:28 -04:00
builtbykev 293367917c Order Zero: book-breadth test + accrual clock correction (measure-only)
STEP 0 disproved the premise before any request was fired. PropLine's
OpenAPI contract states verbatim that `bookmakers` omitted = ALL books,
so proplineAdapter omitting it is correct and always was. Firing a
guessed param would have RESTRICTED the response and produced exactly
the false negative the order warned about.

The real cause is ours: PropLine sends 18 books; oddsNormalizer
ALLOWED_BOOKS intersects them at exactly 5 -- which is precisely the
"5 MLB books" the 2.18 audit measured. Measured on real public data
(no key, no quota): 4.41 books/prop from the feed, 1.50 after our
filter, and 12 of 34 props go invisible entirely.

Also corrected: "73% single-book" is the long tail of deep props
sole-posted by DraftKings or Bovada. On the core props we grade, the
market is 10-12 books wide. pinnacle appears on 0 of 40 MLB props --
the independent low-vig references present on 100% of core props are
exchanges (novig/smarkets/kalshi). DFS pick'em also covers 100% but is
not a market price and must never enter a consensus.

Verdict is outcome (d) ALREADY OPEN, not (a)/(b)/(c) -- all three
assumed the feed was the constraint. Ruler change scoped (not built):
split one allow-list into takeable/reference/excluded, fair_prob_lock
becomes a median consensus with n>=2 or a labelled fallback. Gated on
exchange price validation + the WNBA measurement, which needs the
PropLine key (prod-only, absent locally). MLB isotonic p_win declared
PROVISIONAL until re-run on the real ruler.

Side finding: we use 1 of 29 endpoints. /odds/closing, /movement,
/odds/history, /best-line, /ev, /results, /exports/resolved-props,
/context (free) map directly onto documented gaps -- and resolution
across 33 sports suggests "no free settled feed for NBA/soccer" may be
a $19/mo problem, not a data problem. Documented, not verified.

Plan edits: §10.1 rewritten, §10.2/§10.5 corrected, and §11 adds the
sequential post-completion accrual clock -- pre-completion data does
not count, no pooling across the completion boundary, two clocks
stated separately, per-sport clocks, verification gate before any
accrual, users onboarded to a complete product only. §9.1's "6-10
weeks out" corrected: that is accrual duration, not distance to the
answer. The ruler change independently forces the same no-pooling
boundary by arithmetic.

No API key was used, printed, or committed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
2026-07-31 23:19:23 -04:00
builtbykev c98338ef23 plan: add §10 — aggregator + paid-model gaps, and the one root cause behind both
Answers "what makes this the top product, not just a finished one."

THE REFRAME: the aggregator gap and the model gap are the SAME gap in two places.
Our "market" is often ONE book — MLB props are 73% single-book, and
proplineAdapter sends only {apiKey, markets} with NO regions/bookmakers param
(:152), so we take PropLine's default response. That single fact causes four
problems we had been treating as unrelated: no line shopping (the category's #1
free hook), a fair_prob_lock that is a de-vigged single soft book rather than a
consensus (the bent ruler the model is judged against), weak CLV (cannot measure
beat-the-close against one book), and no steam/disagreement detection (needs >=2
books to exist).

So the highest-leverage unblocked action in the whole plan is a cheap API test:
does PropLine return more books with a regions/bookmakers param on our tier? One
request, and if it works it upgrades the free product, the model's denominator and
the CLV instrument simultaneously.

Aggregator gaps catalogued: book breadth, true consensus, historical odds archive
(started — closing_captures 844k rows, lock_lines new, but in-grade history capped
at 24 points, so no full open->close series), market breadth (11 live vs the
category's 50+), ingested alt-line ladders, injury/lineup wire, player news.

Paid-model gaps catalogued: distribution instead of a point (distribution.js
already computes survival probabilities and rungs but is proj-v1.1, ledger-only
and lost to the champion); opportunity/playing-time projected FIRST with its own
uncertainty (the single biggest available modelling gain); per-stat models instead
of one additive index; matchup granularity that actually reaches the grade;
applied calibration; a backtest harness (blocked by the archive gap — you cannot
backtest a price you never stored); CLV as north star.

THE PATTERN: almost every model capability is ALREADY BUILT AND DISCONNECTED.
VYNDR does not have a building problem, it has a connection-and-proof problem plus
one genuine ingestion gap that starves both halves. The expensive part is largely
done, but no new feature fixes it.

Ordering principle recorded: get MLB genuinely good BEFORE replicating across six
sports — a copied-six-times thin model is six times the maintenance for the same
absent edge.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
2026-07-31 22:35:16 -04:00
builtbykev 37ee952e26 plan: add §9 — what is actually missing for the product to work, not just be built
The phases counted unbuilt code. This section names what is missing for VYNDR to
do what it claims, including the parts that are not builds.

THE CENTRAL GAP: there is no demonstrated edge yet. Every measurement this session
returned null, negative or unproven — served grade r~0.005 and inverted; all three
p_win-vs-fair_prob formulations negative on both sports and both splits; p_win
alone on MLB holdout p~0.07; WNBA negative; CLV null by guard; ROI-by-grade likely
an artifact. The product's core claim is not currently supported by our own data,
and building all 23 orders without closing this leaves a well-built product that
does not do the thing it sells. What closes it is sample and honest iteration, not
code — roughly 6-10 weeks at the current accrual, a clock engineering cannot
shorten and that must not be faked.

Also named: the projection is thin (l5/l20 + opponent rank + rest + usage, with
similarity/archetypes/conditions/Bayesian all built and disconnected, so
connecting them is a hypothesis not a guarantee); it is a one-sport product today
(NBA and soccer do not even settle); there are 3 users and 0 paid so nothing is
validated by usage; there is NO distribution path at all, which appears in no
phase and belongs on the board as its own track; the last mile is unclosed
(push-to-book is a teaser, no affiliate live); and operational fragility remains
(single box, two-sport settlement, three credentials flagged including a Stripe
live key that transited a transcript, no staging).

The honest summary: the truth infrastructure is genuinely well built and this
codebase does not lie about what it knows. What is not yet true is that the model
beats the market — not disproven, unmeasured at adequate n. The finish line is 23
orders PLUS a verdict from accrued data we cannot rush, and the discipline to
report that verdict honestly if it says the edge is not there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
2026-07-31 22:16:11 -04:00
builtbykev e3ca1650d9 plan: specs/MASTER-PLAN.md — single source of truth, 7 phases, ~23 orders, defined END
Consolidation only. Nothing built, wired or promoted.

NOTHING WAS RE-VERIFIED and no query was run — all 22 artifacts produced this
session plus the completion matrix were taken as KNOWN, per the order's own clause.
The verification ledger at the top of the plan lists exactly what was taken as
known and which four items remain genuinely open (sport order, board-reasoning
gating, the CLV flag, team colours) — each open because it needs a decision or a
build, not a query.

The plan captures all six tracks in one document: per-sport models (MLB's 8-layer
stack with each layer marked BUILT/PARTIAL/NOT-WIRED, plus the sport order),
design implementation (61 catalogued items), surfaces, the resolution tail, the
sport boundary, and the Chrome audit.

The through-line it makes visible: MLB's layers 2, 3, 5 and 6 are BUILT AND NOT
CONNECTED, while layer 8 (the grade ladder) is connected and meaningless
(r~0.005, inverted). MLB's fix is connection, not construction.

Phasing is by dependency: MLB model truth -> resolution tail -> surfaces/design
(parallel lane) -> sport boundary -> sport rollout (one order per sport) ->
monetization finish -> Chrome audit and hardening. ~23 orders total, ~11 unblocked
today, so "how many sessions left" now has a real answer.

DEFINITION OF DONE is explicit and countable: MLB layers 1-8 connected with a
monotone held-out-proven ladder; every listed sport finished on the same template
or explicitly abstaining with its reason recorded; all 61 design items built; every
surface reachable and honest; the resolution pipeline firing end-to-end; the sport
boundary a registry; the Chrome audit passed; and the record publishable on its own
terms with no claim outrunning its evidence.

STATE.md now points at the plan and is demoted to history.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
2026-07-31 22:15:10 -04:00