Skip to main content

ADR-0034 — Provider coverage flags are the read-path contract

  • Status: Accepted
  • Date: 2026-08-27
  • Related: ADR-0021 (quarantine over guess), ADR-0033, docs/architecture/data-plane-integration.md §1 gate 3, §5

Context​

TheSports refuses nothing we pay for: 107 of 169 documented endpoints answer, and all 62 refusals map 1:1 onto proposal line items we did not buy. Entitlement is not the problem. Coverage is — endpoints that answer code: 0 and return thin or empty data for most matches.

Measured 2026-08-27 from the whitelisted host:

surfaceendpointpopulated
Football lineupsmatch/lineup/detail2 of 12 live; coverage.lineup set on 117 of 379 (31%) of a day's matches
Football post-match player statsmatch/player_stats/detail2 of 20 finished, across 20 distinct competitions
Football post-match team statsmatch/team_stats/detail2 of 20
Football goal build-upmatch/goal/line/detail1 of 20
Football text commentarytlive3 of 111 live observations (2.7%), pooled — 0/33 and 0/40 (2026-08-27), 0/12 finished, 3 of 38 distinct live matches (2026-08-29). Competition-gated, see the amendment below
Cricket oddsodds/history11 of 41 matches (27%), BET365 only, eu only
Cricket standingsseason/table/detail13 of 33 seasons (39%)
Cricket bracketsbracket/season0 of 33 seasons
Basketball standingsseason/recent/table/detail4 of 8 — exactly the seasons with has_table=1
Basketball shot chartsmatch/shoot/point5 of 12

The provider publishes flags that predict this, and they were measured to be reliable:

  • coverage.lineup — cricket: flag 1 → data on 28 of 29, flag 0 → data on 0 of 4. Football: exactly the 2 of 12 that carried the flag.
  • season/list.has_table — basketball: predicts standings exactly, 4 of 4 both ways.
  • coverage.mlive — does not predict match/live/history. It is not a general-purpose "has data" flag and must not be used as one. Confirmed a second time, on an independent surface, 2026-08-29: it also fails to predict the cricket ball timeline, and from the other direction — 8yomo3c8woy9m0j carries mlive: 0 in the diary while streaming 146 deliveries in timeline[].overs that grew by 10 in eight minutes, and zp5rzpcogdnpq82 carries mlive: 1 and also streams. Cricket ball-by-ball is therefore gated on the presence of timeline[].overs itself, never on the flag; a flag gate would have suppressed a live, correct, growing feed. A flag that fails to predict on two independent surfaces is not a weak flag, it is the wrong instrument.

The proposal sells against league counts — "1970+ leagues", "All leagues" — and never discloses a coverage tier. That gap is the single largest commercial ambiguity in the contract, and it is also the largest design hazard: a tab designed against the proposal is a tab that is empty most of the time.

Decision​

The read path reads the coverage flag before it reads the data, and a field's measured coverage decides whether it is a surface at all.

  1. Flag-gate the call. Where a flag exists and was measured to predict, the read path consults it and does not issue the call when it is 0. A flag that does not predict (coverage.mlive) may not be used as if it did.
  2. Three tiers of product commitment, assigned from measured coverage:
    • ≥ ~85% — a surface. May be a permanent element. (Cricket lineups 85%; cricket post-match cards 23/23; basketball trend 12/12.)
    • ~30–85% — an enhancement. Renders when present, is absent when not, and never occupies a labelled tab or a reserved slot that can be empty. (Football lineups 31%.)
    • < ~30% — not a surface. Not built, and not designed. (Football post-match player and team stats 10%, goal-line 5%, cricket odds 27%, football commentary 2.7%.)
  3. Absence stays absent. A missing value renders as nothing — never 0, never a dash, never the last known number. This is financial-security.md §1 applied to display data: a blank score is honest, a stale or invented one is not.
  4. Every coverage number in a design document carries its date and its sample. "2 of 20 finished matches across 20 distinct competitions, 2026-08-27" — not "rare".

Consequences​

  • Several surfaces that the provider's proposal implies are available are hereby not designed: a football commentary feed, a football post-match statistics tab, a football goal-map, and a cricket odds surface.
  • Cricket odds are explicitly out: 27% of matches, one book, moneyline only, with asia and bs never returned across 41 matches. A 27%-covered price is worse than no price.
  • Coverage ratios must be re-measured before any surface is promoted between tiers, and the measurement is cheap — one sweep from the whitelisted host.
  • The coverage boundary is the strongest item to put to the provider commercially: which competitions are in our coverage for lineups / player stats / goal-line, and what tier expands it.

Amendment — 2026-08-29: the tlive evidence was wrong, the decision is not​

The evidence is corrected. The tier assignment and the decision are unchanged.

This ADR recorded football tlive as 0 of 33 live and 0 of 12 finished and called it "never once" — an absolute claim resting on three null probes. It is false. Re-measured 2026-08-29 02:31–02:41 UTC over 38 distinct live matches, tlive is populated on 3, with real English commentary at minute granularity:

  • "45'+7' First Half ends, Necaxa 0, Cruz Azul 1."
  • "2' Attempt blocked. Daniel González (CF Atlante)'s right foot shot. Jhojan Julio assists."

Pooled over the same population and stated with dates — 0/33 and 0/40 (2026-08-27), 0/12 finished, 3/38 (2026-08-29) — that is 3 of 111 live observations, ≈ 2.7%. Still tier 3, still not a surface, still not built. A single snapshot read in isolation gives 3/26 = 11.5%, which is above this ADR's own 10% bar and would not have carried the conclusion; the pooled figure is the defensible one.

But the shape is coverage, not noise, and that is the part worth recording. Joined to football/match/diary, all three sit in two competitions and those competitions are fully covered:

competitionlive matches in windowwith tlive
9k82rekhp6repzj22 (100%)
p3glrw7hevqdyjv11 (100%)
all 30 others found in the diary300

No coverage flag predicts it. The payload carries only mlive, lineup and gif. All three tlive matches have lineup: 1 — but so do 10 matches without it (3 of 13 = 23%, useless as a gate). gif: 1 appears on 2 of the 3 and on only 1 of the other 30, but the third tlive match has gif: 0, so it does not predict either.

The general rule this adds to §1. Where a flag exists and predicts, gate on the flag. Where no flag predicts but the payload itself proves presence, gate on the payload: render the surface if and only if the field is non-empty for this match, inline and self-gating, never as a labelled tab. Do not build a hand-maintained competition allowlist — it encodes a snapshot of provider coverage and rots silently as that coverage moves. The cricket ball timeline is gated this way for the same reason (see the mlive bullet above).