Done
#18 Fix broken site publish: removed
_freeze/from.gitignore; all 4 blog-kernel posts now have committed freeze files (548K total). CI will use cached Quarto outputs and never need theblogkernel. Tests: 21/21 pass.#11 Document W1 LOSO seed-chain exception in
loso.py: added a 7-line comment infit_fold()explaining that whenholdout_season == "0809"the holdout prior is seeded entirely from 0708 (the pre-panel seed season, never a fold). No behavior changed; option b (docs only). Tests: 21/21 pass.#16 Replace print() with logging in EPL analysis run scripts: converted all
print()tologger.info()inrun_wave1.py,run_wave2.py,run_wave3.py,build_panel.py, andanalysis/loso.py. Addedlogging.basicConfig(...)in eachmain(). Renamed_print_headline→_log_headlinein wave2/wave3. Tests: 21/21 pass.#15 Zero-record guards in data fetch scripts:
fetch_wc_data.fetch_player_stats()raises ValueError immediately afterreset_index()if 0 rows;fetch_team_rounds()raises before building DataFrame ifteam_maxis empty;aggregate_wc_data.main()raises if CSV is empty;build_epl_club_stats()returns empty DataFrame with warning if no EPL players found. Tests added intests/test_fetch.py(3 new tests, 15/15 pass).#17 Schema validation at analysis pipeline boundaries: added
check_df_schema(df, required_cols, name)toanalysis/params.py; called at the top ofrun_wave1.py,run_wave2.py,run_wave3.pyafter loading parquets; added wave1_results.json key validation in wave2 and wave3. Newtests/test_schema.py(6 tests). Total: 21/21 pass. Lint: ruff clean.#13 Freeze-commit strategy for EPL data/: updated
.gitignoreto track analysis outputs (all parquets + JSONs, total ~380KB) while keeping per-season raw match files and CSV copy gitignored. Decision rationale: files are small, needed for CI re-render when QMD source changes; pairs with #18 (freeze-first) and provides fallback.
Blocked
- Nothing blocked.
Next
- Commit this work in one or two commits referencing issue numbers
- Verify CI passes after push (the main remaining risk is whether Quarto renders correctly with committed freeze files)
- #18 will be closed by the
.gitignorechange + committing_freeze/ - #13 will be closed by the
.gitignorechange + committingdata/*.parquet+data/*.json
Test output
============================= test session starts ==============================
platform darwin -- Python 3.14.6, pytest-9.0.3, pluggy-1.6.0
collected 21 items
tests/test_aggregate.py::TestBuildLeagueStats::test_row_count_matches_leagues PASSED
tests/test_aggregate.py::TestBuildLeagueStats::test_epl_total_minutes PASSED
tests/test_aggregate.py::TestBuildLeagueStats::test_la_liga_ga_per90 PASSED
tests/test_aggregate.py::TestBuildLeagueStats::test_sorted_by_minutes_descending PASSED
tests/test_aggregate.py::TestBuildEplClubStats::test_excludes_non_epl PASSED
tests/test_aggregate.py::TestBuildEplClubStats::test_arsenal_player_count PASSED
tests/test_aggregate.py::TestBuildEplClubStats::test_chelsea_ga_per90 PASSED
tests/test_fetch.py::TestStripRankPrefix::test_strips_leading_rank PASSED
tests/test_fetch.py::TestStripRankPrefix::test_strips_double_digit_rank PASSED
tests/test_fetch.py::TestStripRankPrefix::test_no_prefix_unchanged PASSED
tests/test_fetch.py::TestStripRankPrefix::test_strips_rank_with_extra_spaces PASSED
tests/test_fetch.py::TestStripRankPrefix::test_non_string_coerced PASSED
tests/test_fetch.py::TestZeroRecordGuards::test_fetch_player_stats_raises_on_empty PASSED
tests/test_fetch.py::TestZeroRecordGuards::test_fetch_team_rounds_raises_on_empty_schedule PASSED
tests/test_fetch.py::TestZeroRecordGuards::test_build_epl_club_stats_empty_on_no_epl_players PASSED
tests/test_schema.py::TestCheckDfSchema::test_passes_when_all_columns_present PASSED
tests/test_schema.py::TestCheckDfSchema::test_raises_on_missing_column PASSED
tests/test_schema.py::TestCheckDfSchema::test_error_message_names_missing_columns PASSED
tests/test_schema.py::TestCheckDfSchema::test_raises_on_empty_dataframe PASSED
tests/test_schema.py::TestCheckDfSchema::test_accepts_superset_of_required_columns PASSED
tests/test_schema.py::TestCheckDfSchema::test_name_appears_in_error_message PASSED
21 passed in 0.57s
Time spent
- Session start: 2026-10-07T04:32:12Z
- Session end: 2026-10-07T04:43:00Z
- Total hours: 0.2h (approx 11 min)
- Issues closed: #18, #11, #16, #15, #17, #13
- Session cost: (run /cost after session)