docs(opportunities): reality-audit — flat envelopes + live-verified field contracts for ev/arbitrage/middles/low-hold#276
Merged
Conversation
Fixes audit C7/H18/H19/H20 + MED/LOW (verified vs live :3003):
- envelope {success, ..., meta:{source,summary,filters}} -> flat
{data, pagination, updated_at}; pagination gains count/total/next_cursor;
remove the fictional Meta Summary section + JS meta.count/meta.summary reads
- field renames: game_id->event_id, market->market_type, game->event_name,
confidence_score->confidence (JSON rows, schema, prose, intro callout)
- devig_method value is UPPERCASE (POWER), not "power"
- 401 unauthorized -> missing_api_key/invalid_api_key; 403 feature_required ->
tier_restricted (+tier/required_tier); 429 retry_after = Unix-ms
- drop non-existent deprecated aliases ev_percent / devig_book; note circa is
also used as a sharp anchor; document emitted fields odds_probability,
sportsbooks[], deep_link
- group event_name uses "Away @ Home"
`market` query param kept (real filter alias). EN only; locales tracked separately.
Type: docs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…V no-op
Fixes audit C8/H21/H22 + MED/LOW (verified vs live :3003):
- envelope {success, ..., meta:{source,summary,filters,books_analyzed}} -> flat
{data, pagination, updated_at}; pagination gains count/total; JS stops reading meta
- leg implied_probability -> odds_probability; remove leg timestamp (not emitted);
document emitted leg fields odds_id, deep_link, line
- top-level: document emitted estimated_net_profit_percent, league_label, market_label
- remove format=csv param + CSV Format section (S4 #4, approved no-op)
- 401 unauthorized -> missing_api_key/invalid_api_key; 403 +tier/required_tier;
429 retry_after = Unix-ms; nested-ref logo host -> cdn.sharpapi.io; X-Request-Id
EN only; de/es/pt-BR backfill tracked separately.
Type: docs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ional summary
Fixes audit C9/H23/H24/H25 + MED/LOW (verified vs live :3003):
middles (list):
- envelope {success, ..., meta:{count,total,source,pagination,summary,filters}} ->
flat {data, pagination, updated_at}
- side1/side2 nested odds:{american,decimal,probability,fair_probability} -> FLAT
odds_american/odds_decimal/odds_probability/fair_probability; remove side deep_link
(not emitted); document side selection_id/market_id/external_event_id
- min_size param is a no-op -> documented min_profit (filters roi_percentage) (S4 #5);
size-based advice now points at sort=middle_size
- detail endpoint returns {data, updated_at} and 404 for unknown/malformed id
- document market_label/league_label; 401/403 codes; logo host; X-Request-Id
middles-summary (C9):
- response body was wholly fictional -> real {data:{total, by_sport, by_league}},
each bucket {count, avg_quality_score, avg_expected_value}; rewrite examples +
field table; drop success/meta; cache note 10s -> ~250ms; 401/403 codes
EN only; de/es/pt-BR backfill tracked separately.
Type: docs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tom deep_links
Fixes audit H26 + MED/LOW (verified vs live :3003):
- envelope {success, ..., meta:{source,summary,filters}} -> flat
{data, pagination, updated_at}; pagination gains count
- side1/2/3 nested odds:{american,decimal,implied_probability,fair_probability}
-> FLAT odds_american/odds_decimal/odds_probability/fair_probability
- remove per-side deep_links {book:url} (never emitted) + the deep-links callout
and Best-Practice claim; document side selection_id/market_id/external_event_id
- document row market_label/league_label
- 401 unauthorized -> missing_api_key/invalid_api_key; 403 +tier/required_tier;
429 retry_after = Unix-ms; X-Request-Id format
EN only; de/es/pt-BR backfill tracked separately.
Type: docs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… corrected thresholds, reserved ref blocks Re-verified all four opportunity endpoints (+ middles summary/detail) against the live API on top of the 2026-06-26 audit commits: - All five Success(200) examples replaced with verbatim live responses (captured 2026-07-02), so every field name/shape shown is real. - middles: HIGH_PROBABILITY threshold is >35% (not 15%) and STALE_ODDS is >300s (not 30s) — both confirmed empirically against live rows (82 rows in (0.15,0.35] carry no flag; 133 rows aged 30-300s carry no flag). Documented alt_side1/alt_side2, is_team_total, team_name, worst_case_pnl; middle_probability now notes the per-sport calibration (refreshed 2026-07-02, mlb totals 0.65->0.58). - ev: documented always-present fields the page missed (display_selection, market_id, partner_fair_probability, cross_ref_count/dispersion, single_sharp_period, est_correction_s, is_alternate_line) + conditional team_side/market_segment/ is_suspended; fixed X-Request-Id example format; noted the ~0.1% engine EV floor. - arbitrage: documented the working `state` query param (default pa, appends ?state= to leg deep_links — verified live) and completed the warnings vocab (HIGH_PROFIT_SUSPICIOUS, LIVE_STALE_ODDS). - low_hold: dropped the `state` param row + examples (no deep links on this endpoint -> no-op, verified); documented the 308 redirect from /low-hold and /lowhold to the canonical /low_hold path. - all: the "New (May 2026)" nested ref blocks (home/away/*_ref) are NOT emitted on any opportunities endpoint today (0/200 live EV rows, 0 arb legs, 0 middle sides; engines carry no ref fields) — re-marked Reserved/not-currently-emitted; they are live only on /odds for atlas-mapped books. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- middles: worst_case_pnl is the RAW worst-case PnL (positive on guaranteed-profit middles); worst_case_loss is the same value clamped to <= 0 — they diverge on every guaranteed-profit middle (live: worst_case_loss=0, worst_case_pnl=5.77, GUARANTEED_PROFIT). Source: pkg/middlesengine/compute.go WorstCaseLoss=min(0,x) vs WorstCasePnl=x. - arbitrage: LOW_IMPLIED_TOTAL marked Reserved / not currently emitted — the in-process arbengine never stamps it (0 of 12 qualifying 2-leg <96% rows in fresh live sample; stamping exists only in legacy transforms.go path). - arbitrage: leg deep_link typed string|null (was string|undefined) — key is always present, explicit null when absent (59/59 live legs carry the key: 54 valued, 5 null, 0 omitted). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collaborator
Author
|
Merge gate (auto-classified): gate=docs — auto-classified by the gate-log enforcer (14min after merge, no Posted by |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this carries
The opportunities piece of the 2026-06-26 docs reality-audit (
origin/docs/audit-2026-06-26-fixes), cherry-picked ontomainand then re-verified against the live API on 2026-07-02:opportunities-ev— flat envelope + correct field contractopportunities-arbitrage— flat envelope; fix leg fields; drop CSV no-opopportunities-middles+opportunities-middles-summary— flat envelope + flat sides; rewrite fictional summaryopportunities-low-hold— flat envelope + flat sides; remove phantom deep_linksPlus one new commit (010113c) fixing drift found during today's live re-verification. The WIP commit 83fb982 touches none of this family's pages, so no WIP hunks apply here.
Live verification (2026-07-02, direct backend)
GET /opportunities/ev(Pro+)next_cursor) match. Live rows carry fields the page missed —display_selection,market_id,partner_fair_probability,cross_ref_count/cross_ref_dispersion,single_sharp_period,est_correction_s,is_alternate_line, conditionalteam_side/market_segment— now documented. Example replaced with a verbatim live 2-row response. Filters spot-checked live (min_ev,devig_book=circa, sort modes); tier gate (ev= pro+) and 401/429 shapes verified againsttiers.go/ratelimit.go.GET /opportunities/arbitrage(Hobby+)min_profitfilter works; engine default floor 0.5 confirmed (min live profit 0.53 with no param). Added the workingstateparam (defaultpa, appends?state=to leg deep_links — verified live) and completed the warnings vocab (HIGH_PROFIT_SUSPICIOUS,LIVE_STALE_ODDSobserved live/in engine). Example replaced with a verbatim live response.GET /opportunities/middles(Pro+)HIGH_PROBABILITYfires above 35% (doc said 15%) andSTALE_ODDSabove 300s (doc said 30s) — both confirmed empirically (82 live rows in (0.15,0.35] carry no flag; 133 rows aged 30–300s carry no flag) and againstpkg/middlesengine/compute.go. Documented live-presentalt_side1/alt_side2/is_team_total/team_name/worst_case_pnl. Re today's mlb calibration merge (0.65→0.58): no doc example hardcoded a stale probability claim; themiddle_probabilitydescription now names the per-sport calibration explicitly. Example replaced with a verbatim live response that genuinely trips all three warnings.GET /opportunities/middles/summary{data:{total, by_sport, by_league}, updated_at}with{count, avg_quality_score, avg_expected_value}buckets matches live exactly; example replaced with a verbatim live?sport=baseballresponse. Stale "~250ms cache" note corrected (reads the same in-process engine result).GET /opportunities/middles/:id{data, updated_at}; unknown id → 404not_found(note: ids churn fast — an expired id also 404s).GET /opportunities/low_hold(Pro+)stateparam removed (no deep links on this endpoint → verified no-op), examples de-stated; documented the live308 Permanent Redirectfrom/low-holdand/lowholdto the canonical/low_hold. Default hold-ascending sort andmax_holdfilter confirmed live. Example replaced with a verbatim live response.missing_api_keyshape verified live; 403tier_restricted+ tier mapping (ev/middles/low_hold = pro+, arbitrage = hobby+) verified againsttiers.go; 429 limits (hobby 120/min, pro 300/min) verified againstratelimit.go.Cross-cutting drift fixed
The "New (May 2026)" nested reference blocks (
home/away/sport_ref/league_ref/market_ref/sportsbook_ref) are not emitted on any opportunities endpoint today — 0/200 live EV rows, 0 arb legs, 0 middle sides; the EV/arb/middles engine structs carry no ref fields, soaddNestedRefsis a no-op on these paths. They ARE live on/oddsfor atlas-mapped books. All three pages now mark these blocks Reserved — not currently emitted on this endpoint instead of claiming every row carries them.Validation
@mdx-js/mdx3.1.1 (compile(), docs#271 verifier pattern).openapi.json/openapi-version.json/sitemap.xml/account-keys.mdxuntouched (owned by the final spec piece). Commit 9a9af03 is NOT part of this piece.Follow-up
Type: docs