@@ -187,6 +187,46 @@ preference parameters (CPT) are themselves invariant.
187187> asymmetries measure different dimensions (who-wins vs goals), not a single latent.
188188> ` skewlib/extras.py:{shannon_entropy,entropy_by_league} ` , ` analysis/40_entropy_comoment.py ` .
189189
190+ ## Front O — The third observer (player-informed p) [ new data]
191+ ** Hypothesis (strong observer-invariance):** ANY observer's ` (p, skew) ` lands on
192+ ` (1−2p)/√(p(1−p)) ` — an observer's error decomposes into pure p-calibration
193+ (level) with ZERO shape distortion. ` /odds ` already triangulates two observers
194+ (results-only Elo × bookmaker, rank-corr 0.998). A third one built from a
195+ ** disjoint information set** — player attributes only: no match results, no odds —
196+ turns the duet into a panel and makes the invariance claim structural.
197+
198+ - ** O0 [ spike] Source audit** — Kaggle ` davidcariboo/player-scores ` (Transfermarkt
199+ mirror: 60k+ games, 400k+ historical market valuations, ` game_lineups ` ,
200+ ` appearances ` , national teams; weekly refresh, OSS pipeline
201+ ` dcaribou/transfermarkt-datasets ` ). Audit the coverage join vs the frozen
202+ archive (team-name mapping à la ` fdcanon.py ` ); license posture: raw dump stays
203+ in ` data/ ` (gitignored), only derived aggregates committed. Complement/fallback:
204+ SoFIFA (EA) player-rating dumps.
205+ - ** O1 [ new data] The observer** — ` skewlib/players.py ` : team state = log
206+ matchday-lineup market value (fallback: season squad value — decide in O0 by
207+ coverage), link ` strength gap → (pH, pD, pA) ` by ordered probit (reuse the
208+ ` model.py ` idiom), fitted on a train era DISJOINT from the evaluation window.
209+ Results touch only the low-dimensional link, never the state — the observer
210+ stays results-blind where it matters (same status Elo has: results feed its
211+ state, so the player observer is * more* blind, not less). Thin block
212+ ` analysis/55_third_observer.py ` .
213+ - ** O2 [ dataset∩new] The invariance test** — per-p-bucket realised skew vs the
214+ law for all three observers on the overlap sample; decompose each observer's
215+ error into ** calibration** (p level, Brier — free to differ) vs ** shape**
216+ (skew at realised frequency — predicted ≡ 0 for every observer). Bootstrap
217+ bands. The tri-observer overlay on the single law curve is the headline figure.
218+ - ** O3 [ live, optional] WC prospective hook** — national-team variant (tournament
219+ squad values) as a third p column in the World Cup ledger ` /odds ` triangulation,
220+ pre-registered for remaining fixtures. Descriptive only — Box C stands (no
221+ edge crossing); tiny-n disclaimer up front.
222+ - ** Build:** stamp → FINDINGS Phase → Timeline → ` build_lineage.py:PHASES ` →
223+ tag ` evidence/observer-3 ` . Site: third point series on ` /odds `
224+ (○ model, ● book, ◐ players).
225+ - ** Why it is safe for the positioning:** player data improves * nothing* we
226+ monetise — it deliberately produces a (probably worse-calibrated) p whose only
227+ job is to fall on the same curve. A worse Brier with zero shape residual is a
228+ BETTER result for the thesis than a sharper p.
229+
190230---
191231
192232## How to extend (architecture)
@@ -209,3 +249,7 @@ moment, double ADF+KPSS, report sensitivity.
209249> are DONE (W·P·B·C·E·D·F·G·H2 — 29 phases; see ` docs/LINEAGE.md ` ). Only those
210250> requiring ** external data** remain: Front A (tennis/cross-sport), D1 (opening→closing),
211251> H1 (rule changes). Vitor's decision: football on the frozen dataset first — fulfilled.
252+
253+ > ** NEXT external-data front** (planned 2026-07-06): ** Front O — the third
254+ > observer** (player-informed p from Transfermarkt valuations; disjoint
255+ > information set → strong observer-invariance test). Spike O0 first.
0 commit comments