# silly-kicks — TODO

Quick-reference action items. Architectural decisions live in [docs/superpowers/adrs/](docs/superpowers/adrs/).

**Last updated**: 2026-06-12. **Current release**: silly-kicks 4.26.0 (tracking geometry now emitted in the per-action SPADL LTR frame — systemic orientation bug fixed at one canonical seam via `tracking/_action_orientation.py`; ~50% of tracking action rows (away-team actions) had wrong `pre_shot_gk_*`/`defensive_line_*`/`team_shape_*`/`pressure_*`/`nearest_defender_distance`/`ghost_gk_*`; `compute_team_shape` made orientation-aware; mirror-symmetry guard; VAEP/tracking-retrain trigger — re-materialize all tracking action-context; ADR-028). Prior: 4.25.0 (GS null-actor duel/foul events emit NaN `team_id`/`player_id` instead of sentinel `0`; GS ids nullable `Int64`; ADR-001-legal canonical-player self-heal; `convert_to_atomic` preserves source id dtype). Per-version history lives in [CHANGELOG.md](CHANGELOG.md).

**New (4.24.0): `pitch_control_at_ball__spearman` redesign** — Wicked. The Spearman PPCF is degenerate (0.5 fallback) within ~18 m of the ball (ball beats any player's reaction time to near cells), and the column samples linked-action START points → ~0.5 for every well-linked action in production (informationally dead; declared structural constant in the liveness gate; flagged to the lakehouse in the 4.24.0 changelog). Redesign options: sample at the action END point (ball travel time > 0), an integration window past the reaction time, or a potential-control variant. Touches every PC consumer — needs its own ADR.

---

## On Deck

Items are ranked top-to-bottom by specification completeness, then by additional implementation effort needed.

| Size | What it means |
|------|---------------|
| **Monstah** | Multi-phase epic |
| **Wicked** | Looks small, surprisingly impactful |
| **Dunkin'** | Quick run, keeps things moving |

### Tier 6 — Novel synthesis (true research)

| # | Task | Size | Source | Notes |
|---|------|------|--------|-------|
| TF-19 | **GKDV — GK Deterrent Value** composition + audit harness | Monstah | Le et al. 2017 (ghosting); arXiv:2505.11841 (causal-crossing); arXiv:2512.10355 (DEFCON-GNN — prevention-focused EPV-reduction); novel synthesis — closes 2026-05-01 deterrent-investigation literature gap | **GKDV Layer 3 — headline metric.** **Depends on: TF-15, TF-16, TF-17, TF-18.** For every frame in possession in the final third, compute `Δ_attempt(action) = P(action \| actual_GK) − P(action \| ghost_GK)` for action ∈ {shot, cross, key_pass}, weight by realized-or-expected outcome value, and sum across the build-up window. Negative GKDV ⇒ deterrent effect detected. **Validation strategy needs design:** GK-coach qualitative annotation set; correlation with conceded xG; expected-sign test on known sweeper-keepers (Alisson, Ter Stegen, Neuer should score strongly negative on aggressive presses) vs. line-keepers. Sample-size analysis required. **References:** Le et al. 2017 (ghosting). "Framing Causal Questions in Sports Analytics: A Case Study of Crossing in Soccer." arXiv:2505.11841 (2025). "Better Prevent than Tackle: Valuing Defense in Soccer Based on Graph Neural Networks." arXiv:2512.10355 (2025) — DEFCON-GNN; compose-able comparator (per-defender EPV-reduction credit). **DAS counterfactual arm (post TF-28):** `Δ_DAS = DAS(actual_GK) − DAS(ghost_GK)` is a physics-grounded alternative/complementary signal to the attempt-probability decomposition; DAS was explicitly designed for hypotheticals (Bischofberger & Baca 2026). Consider as `method=` flavor on GKDV composition or as validation cross-check against Layer 2 probability surfaces. **Cover shadow signal (post TF-30):** `blocking_score(actual_GK) − blocking_score(ghost_GK)` provides lane-specific deterrent signal complementary to the pitch-control and DAS counterfactuals; particularly relevant for shot-lane obstruction. **Ghost-GK substitution constraint (ex-`kde_backend` guard, obsoleted by ADR-016 / 4.14.0):** the counterfactual `P(action | ghost_GK)` MUST substitute `predict_mean()` (the deterministic, `kde_backend`-free boosted HGBR position now written to `ghost_gk_x/y`), **not** the KDE mode/argmax via `predict_density`. Then no train/serve backend pin/metadata/assert is needed (the old ~6 m NGP mode-skew can't touch the served point). Revisit a `kde_backend` pin only if a variant deliberately consumes the density mode or `ghost_gk_density_spread`. TF-16/TF-17 never bound this (both train on the resolved/defending GK). Two PR cycles' worth realistically; spec + plan as own scoping cycle; likely needs its own ADR. ~400 LOC + audit notebook + held-out validation set. |

**GKDV research program (TF-15..TF-19).** TF-15 through TF-19 form a coherent research arc towards the **GK Deterrent Value** metric — a per-frame measure of how much the defending goalkeeper's actual position depresses opponent attempt-probabilities (shot / cross / key pass) relative to a league-average "ghost" GK in the same frame state. Origin: 2026-05-01 deterrent-effect investigation; closes the published-literature gap that no GK-evaluation framework today (StatsBomb four-pillar, Lamberts GVM, Sloan SAC data-driven framework, Anzer & Bauer xGOT, Driblab Goals Prevented) measures positioning-as-deterrent. **Foundation:** TF-7 (pitch control) + TF-13 (frame-based GK ID) + TF-14 (defensive-line geometry). **Layer 1:** TF-15 (threat-weighted GK influence primitives; shipped 3.10.0). **Layer 2:** TF-16 / TF-17 / TF-18 (decision-probability surfaces for shot-occurrence and cross-attempt + ghost-GK regression; **TF-18 fully shipped 3.24.0** — model code 3.19.0, training pipeline 3.20.0, bundled trained weights 3.24.0; **TF-16 FULLY shipped — code 4.1.0, trained weights 4.9.0 (PR-S80): bundled `public` xS model trained on 81 matches against the 4.7.0 carrier defaults; the pre-registered two-candidate test found owner-tier GS data degraded public-held-out PR-AUC in all 5 folds, so the reproducible public-only model shipped**; **TF-17 code shipped 4.11.0 (PR-A)** — `XCrossAttempt` model + training pipeline + HPO objective + the novel GK-confounder block, ships untrained; weights (PR-B) + the causal ATT/ATNT validation harness (PR-C) follow). **Layer 3:** TF-19 (composition + validation harness) — **xS + cross arms both UNBLOCKED (TF-16, TF-17, TF-18 all fully shipped)**. **Sequencing:** **TF-17 FULLY shipped** (PR-A code 4.11.0 + PR-B trained weights + PR-C causal harness, 4.18.0; the GK-confounder extension was the most research-heavy item — split across three PRs per ADR-011); TF-19 is two PR cycles and gets its own ADR. **External complements:** DAS (Bischofberger & Baca 2026, `accessible-space` on PyPI; TF-28, shipped 3.8.0) provides physics-based counterfactual space valuation; cover shadows (Cascioli et al. 2025; TF-30, shipped 3.11.0) provide lane-specific pass-obstruction metrics. Both can serve as independent cross-checks on the probability-surface decomposition in TF-19.

---

## Technical Debt

### Blocked or Deferred

- **TF-7 cross-family pitch-control cache in VAEP xfns (deferred).** `add_*`
  aggregators accept `pitch_control_cache` (3.25.0); the `*_xfns` VAEP transformers
  do not yet thread a shared cache across feature families in one pass (each keeps
  its own per-frame precompute). Wiring the VAEP feature framework to inject one
  shared `PitchControlCache` across xfns would extend cross-family reuse to the
  VAEP path. Additive (no API churn). Also extend `pitch_control_cache` to
  `player_influence`/`space_creation` callers' shared-pass usage (already wired on
  the aggregators; lakehouse pre-builds one cache like it pre-links).
- **Gradient Sports own-goal/cross-goal capture — SHIPPED 4.13.0 (ADR-018).** `RE`+`G` → `bad_touch`+
  `owngoal` (post-LTR geometry tripwire), `CR`+`G` → cross + synthetic shot, `nonEvent` voided-event
  exclusion, and own goals counted in VAEP labels for all providers. Owner-gated e2e validates the 3 real
  WC2022 own goals + the g3853 disallowed-goal exclusion. Synthesized rows (cross-goal shot, foul) carry
  the new `is_synthetic` GS schema column (provenance, shipped in 4.13.0). **Residual follow-up:**
  **Codebook confirmation** — the `RE`+`G` ≡ own-goal rule + `nonEvent` semantics rest on the full
  WC2022 empirical catalog (the PFF FC Change Log is not a semantic data dictionary); confirm against an
  official PFF codebook if one becomes available, and whether OGs can surface under other event types
  (e.g. `CL` deflection — none seen in WC2022).
- **ADR-code reconciliation sweep.** Periodically verify that documented ADRs
  (`docs/superpowers/adrs/ADR-*.md`) still match the codebase. Check that stated
  constraints (e.g. "zero Spark imports in domain") hold in practice and that
  superseded decisions are updated. Frequency: once per minor release cycle.

---

## Research & Future Work

ReSpo.Vision tracking adapter — licensing-blocked. Track here when licensing clears.

**TF-23 (Dunkin'):** Native Sportec-XML loader inside silly-kicks. **Demand-gated deferral.** Currently the architectural intent (per `silly_kicks/spadl/sportec.py` docstring) routes raw-XML ingestion through the kloppy gateway; the native converter takes pre-DataFrame'd events. PR-S23 deferred adding a native loader. Pure parser implementation (no metric design); replicable from kloppy's source + the provider XSD. The only value proposition is a kloppy-free ingestion path — and the known consumer (luxury-lakehouse) already receives Sportec as a parsed DataFrame upstream (`bronze.idsse_events`, Bassek-2025 parse), so it never touches raw XML. Surface this only if/when a kloppy-free raw-XML consumer actually materialises. **Metrica-CSV half retired 2026-06-08:** the only public Metrica data is the 3 hand-curated, anonymized sample games (oldest ~5 yrs old, frozen, no roster/names); a native CSV loader would be pure kloppy duplication validated against dead sample data with no possible consumer (the lakehouse ingests Metrica via the kloppy gateway). No evolving-data basis can ever materialise from the public path.

**TF-35 (Wicked):** Off-ball run type classification — overlap / underlap / far side / advance / support taxonomy. **Priority-deferred; no published academic anchor.** TF-4 (shipped 3.9.0) detects off-ball runners and emits `n_off_ball_runners_toward_goal_pre_window` as a scalar count. A richer classification of *how* teammates run (overlap on the outside, underlap inside, advance beyond the ball, support behind it, far-side weak-side runs) would enable per-type VAEP features and scouting-layer aggregations. **Reference:** Gradient Sports blog, "Measuring Off-Ball Movement Using Broadcast Tracking & Event Data" (Schram, 2026-05-06) — describes a hierarchical run-type classification + 15-control-point spatial normalization + additive modifiers (in behind, into box, distance band, ball receipt). Commercial product description, not peer-reviewed; Gradient's zone definitions are proprietary and would need independent specification. The 15-control-point normalization (duration-invariant spatial profile) is a clean engineering pattern worth adopting if this ships. **Implementation sketch:** extend `_off_ball_runs.py` with a `run_type` categorical column per runner; requires ball-carrier-relative lateral position (inside/outside) + lapping-point detection for overlap/underlap; pitch zone definitions for wing/halfspace/centre. ~200–300 LOC on top of TF-4. **Demand signal:** overlap/underlap/advance/support are standard coaching vocabulary used daily in training and match review — quantifying them bridges the analytics-coaching communication gap directly. Value is higher than pure analytics novelty suggests; any consumer building tools for coaching staff would benefit. **Published anchor (conceptual, non-reproducible):** Esposito et al. (2026), "Classifying the invisible game: a structured taxonomy of off-the-ball behaviors," IJSSC, DOI 10.1177/17479541261427153 — a 4-axis off-ball-behavior taxonomy (Possession-Function × Unit-of-Analysis × Performance-Dimension × Behavioral-Type, where a run is BT-Run). Supplies the academic framing TF-35 lacks but gives NO computable run-type geometry (overlap/underlap/advance/support remain undefined), so it does not by itself unblock the build. Its broader value is feature-catalog / docstring vocabulary across the whole tracking-feature layer (a documentation-pass concern, not a feature). Reviewed by H. Sotudeh (TF-39 author). **Revisit if/when:** a published paper formalises the taxonomy with reproducible definitions, or consumer demand materialises for coaching-vocabulary-aligned run metrics. Origin: 2026-05-13 Gradient Sports blog investigation; Esposito anchor added 2026-06-05.

**TF-37 (Wicked):** Pose-estimation features for xG, VAEP, and GKDV. **Data-availability-blocked; high value when unblocked.** Body keypoint data (trunk angle, knee flexion, foot orientation at ball contact) from pose estimation enables three concrete value-adds: **(a) Player-adjusted xG** — current xG treats all shooters as interchangeable; pose features at shot moment make xG per-shooter per-shot. Slots into lakehouse xG-v2 as additional input features. Hirn et al. (FAU Erlangen-Nürnberg, 2026; LISS SAC poster, paper forthcoming) demonstrated improved Brier score on 101 controlled-drill shots using tree-based models with pose features vs. positional-only baselines. **(b) GK pose at shot moment** — GK body orientation, set position, weight distribution at shot time is a stronger signal than centroid position alone. Feeds directly into GKDV research program (TF-15..TF-19); a GK leaning left vs. set square has different save probability regardless of (x, y). **(c) VAEP pose features** — body orientation at action time (not just shots) could inform pass technique quality, dribble body lean, aerial duel posture. New `_frame_aware` xfn category in `tracking.features`. **Blocker:** no tracking provider silly-kicks currently supports (Sportec, Metrica, SkillCorner, Gradient Sports, kloppy gateway) ships body keypoint data. When a provider makes pose features available, the silly-kicks schema (`TRACKING_FRAMES_COLUMNS`) would need per-player-per-frame keypoint columns or a linked keypoint DataFrame. **Hirn et al. limitations:** 9-participant controlled drill (not match data), right-foot only, self-acknowledged need for real-game validation. Watch for the published paper. **Revisit if/when:** a tracking provider supported by silly-kicks ships body keypoint features, or a new provider with pose data is added via kloppy. Origin: 2026-05-13 LISS SAC poster investigation.

**TF-38 (Monstah):** CDF center-origin coordinate system — switch internal representation from bottom-left `[0, 105] × [0, 68]` to center-origin `[-52.5, 52.5] × [-34, 34]`. **Next-major (5.0.0) breaking change; bundle with other breaking-change candidates.** (4.0.0 was consumed by the symmetric fail-loud ET-direction change, PR-S70 — ADR-010; the two breaking changes were not bundled because TF-38 is not yet ready: it has its own prereqs below.) The CDF coordinate system (arXiv:2505.15820, v1.0.0, Anzer/Bekkers/Davis/Van Haaren, Dec 2024) is already the de facto industry standard: 8/14 tracking provider aliases natively use center-origin meters (SecondSpectrum, SkillCorner, PFF, GradientSports, Sportec:tracking, HawkEye, Signality — per fast-forward alias table). LTR invariant is preserved (home attacks positive-x); only the origin shifts. **Simplifies:** GradientSports events/tracking + Sportec tracking become passthrough (drop +52.5/+34.0 offset); SkillCorner rescale simplifies; DAS `_to_das_coords()` deleted entirely; mirroring becomes negation (`-x` instead of `field_length - x`); midfield checks `x < 0` instead of `x < 52.5`. **Blast radius:** every coordinate-touching constant, constraint, converter, feature, test, and downstream consumer. ~30 files, ~2800 test assertions. **Prereqs:** (1) inventory all 4.0 breaking-change candidates to bundle; (2) kloppy center-origin target coordinate system support (currently targets bottom-left 105×68). **IEEE 3715 status:** PAR approved 2025-11-04 (active working group, chair: Jesse Davis, IEEE EMB Society); not yet published as ratified standard. The arXiv paper (v1.0.0) is the pre-standard spec; IEEE ratification is in progress. The center-origin convention itself predates IEEE submission and is independently justified by provider convergence. **Trained-model impact (xS TF-16 / Ghost-GK TF-18): NO retrain required.** Both train on goal-relative features in *physical units* (metres/radians) via the shared `_geometry` transform, which is **translation-invariant**: once `goal_x` parameterizes to `±pitch_length/2`, every goal-relative feature value is numerically identical pre/post origin-shift, so the booster/KDE weights (which live in goal-relative space) are untouched. TF-38 updates the *transform code*, not the *weights* — and this is a positive argument for training these models now rather than waiting for 5.0.0. **Required of the TF-38 PR:** (a) a goal-relative feature-parity regression gate (old-origin vs new-origin frames → byte-identical extracted features) that also proves no raw-coordinate leak in any feature; (b) honour each model's `metadata.json`-recorded `pitch_length`/`pitch_width` (added by the TF-16 weights cycle as the metadata template) and fail loud on mismatch. **Caveat:** invariance holds ONLY because TF-38 is a pure translation (105×68 m preserved); a future *rescale* or unit change WOULD force a retrain. Established 2026-06-02 (TF-16 weights brainstorm). Origin: 2026-05-26 lakehouse CDF investigation.

**TF-46 (Monstah):** Set-piece (corner) defensive-role inference + role-conditioned ghosting. **Research direction; strategic — silly-kicks has no set-piece layer today; needs its own brainstorm/spec before any build.** Source: Groom, Belo, Rice, Anderson & Wang (2026), "A Machine Learning Framework for Off-Ball Defensive Role and Performance Evaluation in Football," arXiv:2601.00748. Core = a **covariate-dependent Hidden Markov Model (CDHMM)** inferring, label-free, time-resolved corner defensive roles (man-marking defender→attacker + zonal) + team/delivery-specific (inswing/outswing) zonal structures from tracking; coach metrics (marking tightness γₒ per 3×3 m bin, zonal dwell, β transition dynamics). Valuation: **role-conditioned ghosts** (counterfactual = average same-role/same-team defender) + **role-based defensive credit attribution** (couples roles with outcome models). **Architectural fit (the appeal):** the role-inference core is an HMM + linear covariate-dependent transitions (EM), **not a neural net** — compatible with silly-kicks' no-NN scipy/sklearn idiom (unlike the corner-RL/TacticAI GNN line, arXiv:2606.06353, which is out of scope); the valuation layer is outcome-model-agnostic → slot in silly-kicks' own xT / xShotOccurrence / VAEP in place of the paper's GNNs. **Connects to the GKDV program (TF-15..19):** role-conditioned ghosting is the tactically-contextual answer to ghost-GK's "average behavior lacks tactical context" limitation (see the ghost-GK section of NOTICE); role-based credit attribution sits next to TF-19 + DEFCON (Kim et al., already a TF-19 comparator). **Scope/blockers:** Monstah multi-component (CDHMM + EM + per-team/per-delivery fitting + role inference + ghosting + attribution); trained-model feature (ADR-011, per-team/per-delivery CDHMMs); **new corner domain = strategic expansion decision**, not a drop-in feature; data-availability (per-team/per-delivery models need many corners/team — paper used 14,678 corners across 4 PL seasons; assess vs WC2022 GS + pining corpora). Methods EM math + covariate set + appendix need a full re-read at spec time (the 2026-06-05 audit read the conceptual sections; docling truncated the Methods). **Revisit if/when:** a deliberate decision to open a set-piece feature layer in silly-kicks, or consumer demand for corner defensive-role / man-marking metrics materialises. Origin: 2026-06-05 LinkedIn/PDF audit; companion to the out-of-scope corner-RL paper arXiv:2606.06353.

**TF-47 (Wicked):** KNN / per-source-context **conditional** xT — the follow-on research arc for the 4.17.0 pluggable xT (`xthreat/`, SK-xT-1, ADR-021). Extend the transition family with a `method="knn"` flavor: KNN over `(source_zone[, context])` → destination, the path to a per-source-context *conditional* xT (the headline of the ExT poster). **Deferred — not blocked by silly-kicks, but:** the method (Salimi, Salmankhah & Nodin 2026, "ExT," LISS Football Analytics Symposium) is a **pre-publication poster**, not implemented anywhere (the lakehouse has docstring stubs only), and the conditional *context* features (e.g. last-defender position, opponents between ball and goal) are **tracking-join-dependent** — the event↔tracking join stays consumer-side, so only the KNN *consumer* is library-shaped. The SK-xT-1 string-dispatch transition family + `GridSpec` + held-out-NLL evaluator make this a clean drop-in `method="knn"` + `KNNParams` when it lands. **Revisit if/when:** the ExT paper publishes (update NOTICE from the poster to the paper), or consumer demand for conditional xT materialises. Decision context: ADR-021 (scope: KNN/conditional deferred). Origin: 2026-06-07 SK-xT-1 promotion (lakehouse-proposed).


**Restart-coordinate enrichment — Phase 2: canonical promotion (deferred; follow-up from 4.22.0 / ADR-025).** Phase 1 shipped 4.22.0 (`add_restart_coordinates` emits imputed coords as **new** `enriched_*` columns; additive, no retrain). Phase 2 promotes those to the **canonical** `start_x/start_y/end_x/end_y` so VAEP/xT/calibration consume them directly. **Blast radius (why deferred):** a coordinated retrain of every trained model (VAEP, xT, calibration) + re-baseline of every coordinate-touching golden + promotion of the geometry tripwire to a hard converter-level gate. **Recipe + the `enriched_*`-is-NaN-for-unresolved caveat** are in ADR-025 ("Phase-2 promotion recipe"). **Revisit if/when:** a consumer needs imputed restart coords inside a trained model, or the coordinate-quality gap is prioritised for the canonical contract. Origin: 2026-06-10 general-enrichment Phase 1.
