Skip to content

fix(tracking): ADR-028 RC4 -- unoriented SkillCorner frames + paired GkCompletionModel retrain -- silly-kicks 4.73.0 (PR-S141, ADR-051) #501

fix(tracking): ADR-028 RC4 -- unoriented SkillCorner frames + paired GkCompletionModel retrain -- silly-kicks 4.73.0 (PR-S141, ADR-051)

fix(tracking): ADR-028 RC4 -- unoriented SkillCorner frames + paired GkCompletionModel retrain -- silly-kicks 4.73.0 (PR-S141, ADR-051) #501

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions: read-all
# A newer push/PR update supersedes an in-flight run for the same ref instead of
# queueing, so CI resources aren't spent on stale commits.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- run: pip install ruff==0.15.7 pyright==1.1.409 pandas-stubs==2.3.3.260113
- run: ruff check silly_kicks/ tests/ scripts/
- run: ruff format --check silly_kicks/ tests/ scripts/
- run: pip install -e ".[test]"
# config-driven include: silly_kicks + tests + scripts (pyproject [tool.pyright])
- run: pyright
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ["3.10", "3.11", "3.12"]
exclude:
- os: windows-latest
python-version: "3.10"
- os: windows-latest
python-version: "3.11"
include:
# Augments the existing ubuntu-3.12 leg (GitHub merges a matching include rather
# than creating a new leg) with primary: true -- the single source of truth for
# "which leg runs the platform-invariant @slow set + the benchmark step". See ADR-023.
- os: ubuntu-latest
python-version: "3.12"
primary: true
env:
# Strict mode: promote the in-converter direction-of-play invariant
# assertion in `silly_kicks.spadl.utils._finalize_output` (PR-S22 /
# ADR-006) from default-warn to raise, AND promote the input-convention
# validator's `on_mismatch` resolution from "warn" to "raise". Catches
# home_team_id-heuristic regressions in test fixtures and any future
# loader-shape drift in consumer pipelines that pin against silly-kicks
# main. See feedback_home_team_id_heuristic_fragile.md.
SILLY_KICKS_ASSERT_INVARIANTS: "1"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}
# `das` (accessible-space) is installed on EVERY leg, not just the primary one: the
# TF-28 DAS suites are all `importorskip`-guarded, so without the extra they SKIP
# rather than fail, and they had therefore never run in CI at all. gkdv's DAS arm
# (TF-19 PR-3) is a second consumer of that subsystem, whose correctness depends on a
# direction-inference subtlety inside it -- a guard that never runs is not a guard.
# The arm's own STRUCTURAL direction-pinning guard needs no extra and runs regardless.
- run: pip install -e ".[kloppy,xgboost,das,test]"
# Bulk suite (serial). xdist `-n auto` was reverted: on the 4-core/7GB CI runners it
# regressed py3.12 from pass to a memory/JIT-pressure kill (4x heavy ML imports + 4x numba
# compiles + the ghost-GK suite), the opposite of the 16-core local speedup. The dominant
# ghost-GK cost is instead cut at the source (exact cpu-numba KDE backend + shrunk golden).
# Perf budgets are now deterministic structural guards in the bulk (no wall-clock), so this
# step is stable; the pure benchmark *measurements* run single-threaded below for clean timing.
#
# Slow-test gating (ADR-023): the platform-/interpreter-INVARIANT heavy tests (train-script
# smokes, same-run internal-consistency/parity, calibration cache-equivalence) carry
# @pytest.mark.slow and run ONCE on the primary leg (ubuntu-3.12); every other leg runs the
# full fast/contract suite with `not slow`. Version-sensitive tests (golden/snapshot/absolute)
# are deliberately NOT marked slow -- they stay on all legs (OS + interpreter axes). The
# partition is structural (matrix.primary) and guarded by tests/test_ci_slow_gating_wired.py.
# Mutually-exclusive `if:`s keep every leg at exactly ONE bulk pytest process.
- if: ${{ !matrix.primary }}
run: pytest tests/ -m "not e2e and not slow" --benchmark-skip --tb=short --durations=25
- if: ${{ matrix.primary }}
run: pytest tests/ -m "not e2e" --benchmark-skip --tb=short --durations=25
# Benchmark measurements (no hard timing asserts after the structural-guard conversion), run
# single-threaded on the primary leg only so the recorded numbers are clean trend data.
- if: ${{ matrix.primary }}
run: pytest tests/ -m "not e2e" --benchmark-only --tb=short
# Public-API doctest enforcement (PR-S124). Initial scope: the PUBLIC surface only --
# `--ignore-glob="*/_[!_]*.py"` skips single-underscore private modules while KEEPING dunder
# `__init__.py`, so runnable examples on non-underscore modules are executed and stay honest.
# Private-module examples are kept CORRECT (the whole package sweep is clean) but are
# deliberately NOT executed here, to bound CI wall-clock. Runs on EVERY leg because doctest
# output (repr) is version-sensitive; verified green on py3.10 + py3.14. No `addopts` in
# pyproject, and `testpaths` is ignored when a path is passed, so no `-o` override is needed.
- run: pytest --doctest-modules silly_kicks/ --ignore-glob="*/_[!_]*.py" --tb=short