fplkit 2.2.0__tar.gz → 2.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/TOOLS.md +13 -8
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/squad-builder/SKILL.md +1 -1
- fplkit-2.3.1/.claude/output-styles/fpl-mate.md +148 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/AGENTS.md +2 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/CHANGELOG.md +42 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/CLAUDE.md +2 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/PKG-INFO +31 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/README.md +30 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/docs/architecture.md +22 -17
- {fplkit-2.2.0 → fplkit-2.3.1}/docs/command-reference.md +205 -19
- {fplkit-2.2.0 → fplkit-2.3.1}/docs/custom-analysis.md +11 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/_version.py +2 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/analysis/stats.py +23 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/analysis/transfer_eval.py +9 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/common.py +8 -11
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/core_insights.py +165 -120
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/fpl_draft.py +40 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/understat.py +18 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/__init__.py +2 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_fines.py +58 -6
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_helpers.py +44 -8
- fplkit-2.3.1/fpl_cli/cli/_json.py +186 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_league_recap_data.py +220 -54
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_league_recap_history.py +443 -24
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_league_recap_types.py +43 -6
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_plan_grid.py +26 -18
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_review_classic.py +9 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_review_draft.py +14 -16
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_review_summarisation.py +18 -4
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/allocate.py +26 -7
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/chips.py +9 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/differentials.py +9 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/doctor.py +100 -26
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/doctor_providers.py +310 -79
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/fdr.py +75 -22
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/fixtures.py +13 -3
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/intel.py +12 -15
- fplkit-2.3.1/fpl_cli/cli/league_fines.py +209 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/league_recap.py +259 -16
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/player.py +24 -14
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/preview.py +5 -3
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/price_history.py +3 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/ratings.py +36 -3
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/sell_prices.py +97 -48
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/squad.py +21 -18
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/stats.py +66 -14
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/status.py +3 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/transfer_eval.py +9 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/models/league_history.py +102 -14
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/prompts/league_recap.py +146 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/prompts/review.py +3 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/fixture_predictions.py +55 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/league_history.py +13 -3
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/league_history_counters.py +291 -29
- fplkit-2.3.1/fpl_cli/services/league_history_fines.py +552 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/league_history_notes.py +261 -16
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/returnee_radar.py +11 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/__init__.py +6 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/constants.py +83 -5
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/display.py +9 -3
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/evaluation.py +26 -12
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/ownership.py +6 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/value_quality.py +3 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/team_ratings.py +184 -54
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/team_ratings_prior.py +15 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/templates/gw_league_recap.md.j2 +29 -1
- fplkit-2.3.1/fpl_cli/utils/gameweek.py +32 -0
- fplkit-2.3.1/scripts/backtest_early_season_prior_blend.py +438 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/scripts/calibrate_promoted_prior.py +5 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/scripts/calibrate_quality_ceilings.py +12 -4
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_api_core_insights.py +20 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_api_draft.py +54 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_api_understat.py +106 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_chips.py +5 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_doctor.py +97 -4
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_doctor_providers.py +254 -11
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_fdr.py +77 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_fixtures.py +3 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_intel.py +4 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_json.py +55 -2
- fplkit-2.3.1/tests/test_cli_json_contract.py +319 -0
- fplkit-2.3.1/tests/test_cli_league_fines.py +275 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_league_recap.py +1052 -37
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_plan_grid.py +2 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_player.py +8 -4
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_preview.py +69 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_returnees.py +3 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_review.py +152 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_sell_prices.py +83 -7
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_stats.py +203 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_fines.py +74 -2
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_fixture_predictions.py +78 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_league_history_counters.py +425 -19
- fplkit-2.3.1/tests/test_league_history_fines.py +463 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_league_history_notes.py +496 -5
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_league_history_store.py +119 -6
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_league_recap.py +558 -36
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_preseason.py +3 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_returnee_radar.py +13 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_review.py +117 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_scoring.py +202 -1
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_team_ratings.py +711 -0
- fplkit-2.3.1/tests/test_utils_gameweek.py +38 -0
- fplkit-2.2.0/.claude/output-styles/fpl-mate.md +0 -111
- fplkit-2.2.0/fpl_cli/cli/_json.py +0 -92
- fplkit-2.2.0/fpl_cli/utils/gameweek.py +0 -10
- fplkit-2.2.0/tests/test_utils_gameweek.py +0 -18
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/README.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/create-pr/SKILL.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/SKILL.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/references/output-template.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/references/rules.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/scripts/_bootstrap.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/scripts/bench_order.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/scripts/extract_classic_squad.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/scripts/starting_xi.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/scripts/transfer_eval.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/gw-prep/scripts/validate_draft_waivers.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/preview-ingest/SKILL.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/release/SKILL.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/release-notes/SKILL.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/squad-builder/references/output-template.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/squad-builder/references/rules.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.agents/skills/update-gw-prep/SKILL.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.claude/settings.json +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.env.example +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.github/workflows/ci.yml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.github/workflows/pr-title.yml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.github/workflows/release.yml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/.gitignore +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/CONTRIBUTING.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/LICENSE +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/cliff.toml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/config/team_ratings_overrides.yaml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/docs/fpl-rules.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/docs/images/fpl-player-demo-v1-0.png +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/action/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/action/waiver.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/analysis/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/analysis/bench_order.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/analysis/captain.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/analysis/squad_analyzer.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/analysis/starting_xi.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/base.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/data/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/data/fixture.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/data/price.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/data/scout.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/orchestration/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/agents/orchestration/report.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/contract.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/dataset_fetcher.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/football_data.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/fpl.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/historical.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/historical_types.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/providers/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/providers/_models.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/providers/anthropic.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/providers/openai_compat.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/providers/perplexity.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/api/vaastav.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_banner.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_context.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_fines_config.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/_review_analysis.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/captain.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/credentials.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/history.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/init.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/league.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/price_changes.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/returnees.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/review.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/targets.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/waivers.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/cli/xg.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/config/defaults.yaml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/config/fixture_predictions.yaml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/config/previews/EXAMPLE.yaml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/config/team_managers.yaml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/constants.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/models/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/models/chip_plan.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/models/fixture.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/models/player.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/models/team.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/models/types.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/parsers/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/parsers/recommendations.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/paths.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/prompts/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/prompts/returnees.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/prompts/scout.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/scraper/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/scraper/fpl_prices.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/season.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/matchup.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/player_prior.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/data_prep.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/shrinkage.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/signals.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/scoring/single_gw.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/season_previews.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/squad_allocator.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/services/team_form.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/templates/gw_preview.md.j2 +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/templates/gw_review.md.j2 +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/utils/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/utils/files.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/utils/markdown.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/utils/teams.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/utils/text.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/fpl_cli/utils/time.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/pyproject.toml +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/pyrightconfig.json +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/requirements.lock +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/__init__.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/conftest.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/fixtures/classic_squad_fixture.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/fixtures/recommendations_fixture.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/fixtures/validate_draft_waivers/recs_clean.md +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/fixtures/validate_draft_waivers/squad_grid.json +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/fixtures/validate_draft_waivers/waivers.json +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/fixtures/waiver_ranked_golden.json +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_agents_action.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_agents_analysis.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_agents_analysis_squad.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_agents_base.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_agents_data.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_agents_data_price.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_agents_orchestration.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_allocate.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_api_client.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_api_dataset_fetcher.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_api_football_data.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_api_historical.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_api_vaastav.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_bench_order_script.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_classic_squad_extraction.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_allocate.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_banner.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_captain.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_credentials.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_custom_analysis.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_differentials.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_fdr_blanks.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_format.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_format_suppression.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_history.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_init.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_league.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_price_changes.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_price_history.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_settings_warning.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_squad.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_status.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_targets.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_transfer_eval.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_waivers.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_warnings_stderr.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_cli_xg.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_common.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_common_scoring.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_data_prep_harmonisation.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_doc_consistency.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_fines_config.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_fpl_prices.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_init.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_init_fines.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_matchup_service.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_models.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_paths.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_player_prior.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_player_resolution.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_providers.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_recommendations_parser.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_report_agent.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_report_paths.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_rolling_pts_per_m.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_scraper.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_season.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_season_awareness.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_season_previews.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_sell_prices.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_squad_allocator.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_starting_xi_agent.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_stats.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_team_ratings_prior.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_transfer_eval_agent.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_utils_markdown.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_utils_text.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_utils_time.py +0 -0
- {fplkit-2.2.0 → fplkit-2.3.1}/tests/test_validate_draft_waivers.py +0 -0
|
@@ -18,7 +18,11 @@ All `--format json` commands emit a standard envelope via `emit_json()` in `fpl_
|
|
|
18
18
|
- `metadata` - command-specific context (typically includes `gameweek`)
|
|
19
19
|
- `data` - the payload (list or dict, varies per command)
|
|
20
20
|
|
|
21
|
-
Errors use `emit_json_error()` with `{"command", "error"}` shape.
|
|
21
|
+
Errors use `emit_json_error()` with `{"command", "error"}` shape. **Both envelopes go to
|
|
22
|
+
stdout** and exit 1 on failure, so parse stdout either way and read the exit code to know
|
|
23
|
+
which envelope you got. Warnings and progress go to stderr; the failure message itself is
|
|
24
|
+
in `error`, not on stderr. Full contract:
|
|
25
|
+
[Command Reference](../docs/command-reference.md#json-output).
|
|
22
26
|
|
|
23
27
|
## CLI Commands
|
|
24
28
|
|
|
@@ -26,29 +30,30 @@ Errors use `emit_json_error()` with `{"command", "error"}` shape.
|
|
|
26
30
|
|---------|-------------|------|--------|-------------|---------|
|
|
27
31
|
| `init` | Set up fpl-cli with your FPL IDs and optional features | No | General | No | direct-api |
|
|
28
32
|
| `status` | Show FPL gameweek status and upcoming deadlines. JSON `metadata` carries `gameweek`, `format` and `season` (hyphenated label, e.g. `2026-27`) - `season` is the directory segment skills must use when writing alongside fpl-cli's own reports | Yes | General | No | direct-api |
|
|
29
|
-
| `doctor` | Check the setup for dead IDs, stale data, and config problems: resolves each configured ID against the live API (reporting the team/league name back so a wrong-but-valid ID is visible), verifies per-team data files (team ratings, managers, season preview intel, finances, player prior) describe the current season's clubs, and reports which config/data/cache directories are in use. With `--providers`, probes the external data sources instead: live shape-and-volume checks against the FPL and Draft APIs, the vaastav and Core-Insights datasets, Understat, and football-data.org, including that every club resolves across sources (the drift that otherwise surfaces as plausible but wrong output). Distinguishes broken (needs a fix today) from stale (self-corrects). Exits non-zero when something is broken | Yes | General | No | direct-api |
|
|
33
|
+
| `doctor` | Check the setup for dead IDs, stale data, and config problems: resolves each configured ID against the live API (reporting the team/league name back so a wrong-but-valid ID is visible), verifies per-team data files (team ratings, managers, season preview intel, finances, player prior) describe the current season's clubs, and reports which config/data/cache directories are in use. With `--providers`, probes the external data sources instead: live shape-and-volume checks against the FPL and Draft APIs, the vaastav and Core-Insights datasets, Understat, and football-data.org, including that every club resolves across sources and that the Core-Insights per-gameweek files parse to records through the parsers the scoring commands use (the drift that otherwise surfaces as plausible but wrong output). Distinguishes broken (needs a fix today) from stale (self-corrects). Exits non-zero when something is broken | Yes | General | No | direct-api |
|
|
30
34
|
| `fixtures` | Show fixtures for a gameweek | Yes | General | No | direct-api |
|
|
31
35
|
| `player` | Look up a player's stats, xG, ownership and fixture run. JSON includes `ep_next` (predicted pts next GW) and `ep_this` (current GW), emitting `null` when FPL has no projection; panel shows `xPts` (ep_next) when available, omits the segment when FPL has no projection. `--detail` (`-d`) shows GW-by-GW performance and, for FWD/MID with sufficient history, xGI sustainability (per-match GI-xGI divergence -> form modifier). With `custom_analysis`: JSON adds `info.adjusted_npxg_per_90` (fixture-adjusted) and `info.raw_npxg_per_90` (Understat season avg); panel shows `adj. npxG/90: X.XXX (raw: Y.YYY)` | Yes | General | No | direct-api |
|
|
32
|
-
| `stats` | List players with filtering and sorting. `--value` adds quality/value per £m columns; `--window N` sets rolling lookback (3-10) for `rolling_pts_per_m`. Sortable by `ep_next`/`ep_this` (FPL predicted points; `ep_this` is only meaningful before the gameweek's first kickoff — FPL rolls it forward to `ep_next` as each player's match finishes); both in JSON output (emit `null` when FPL has no projection; table renders `—`). Players with no projection sort to the bottom in either direction | Yes | General | No | direct-api |
|
|
36
|
+
| `stats` | List players with filtering and sorting. `--value` adds quality/value per £m columns; `--window N` sets rolling lookback (3-10) for `rolling_pts_per_m`. Before GW6, `--value` warns that quality scores are small-sample dominated (stderr notice; JSON `metadata.warnings` code `early_season_small_sample`) — GK ceilings scale with the calendar-possible sample, reaching full scale at GW6. Sortable by `ep_next`/`ep_this` (FPL predicted points; `ep_this` is only meaningful before the gameweek's first kickoff — FPL rolls it forward to `ep_next` as each player's match finishes); both in JSON output (emit `null` when FPL has no projection; table renders `—`). Players with no projection sort to the bottom in either direction | Yes | General | No | direct-api |
|
|
33
37
|
| `history` | Show historical player performance across seasons | Yes | General | No | direct-api |
|
|
34
38
|
| `league` | Show live league standings for Classic and Draft leagues | No | General | No | direct-api |
|
|
35
|
-
| `fdr` | Analyse fixture difficulty - easy runs, blanks, doubles | Yes | General | No | via-agent |
|
|
39
|
+
| `fdr` | Analyse fixture difficulty - easy runs, blanks, doubles. `--blanks` mixes confirmed fixtures with predictions; when those predictions are stale, table mode warns on stderr and JSON adds a `fixture_predictions_stale` entry to `metadata.warnings` | Yes | General | No | via-agent |
|
|
36
40
|
| `xg` | Analyse underlying stats: xG, xA, overperformers | Yes | General | No | via-agent |
|
|
37
41
|
| `price-changes` | Show price changes and transfer activity | No | General | No | via-agent |
|
|
38
42
|
| `price-history` | Show price trajectory and transfer momentum | Yes | General | No | direct-api |
|
|
39
43
|
| `returnees` | Track injured and suspended players due back soon, so a returnee can be claimed in draft before they are fit or planned around in classic. Reads the FPL availability news, filters to returns inside a window (`--window N`, 1-38) and through a source-aware quality bar, and diffs against the stored watchlist for week-over-week changes. Most flagged players carry no parseable return date, so date-unknown entries are the norm rather than the exception; `--enrich` searches the web for fresher timing on those and on stale-news entries (needs a Perplexity key; skips with a note without one) and shows it beside the FPL news, never over it. `--all` bypasses the quality bar and deliberately does not persist the snapshot. JSON `metadata` carries `window`, `escalation_window`, `stash_upgrade_margin`, `transitions_available`, `quality_bar_available`, `quality_bar_applied` and `enrichment_requested`/`_available`/`_note`/`_count`; `data` is `{entries, departures}`, each entry carrying `quality.basis`/`quality.meets_stash`, `expected_return`/`return_gameweek`/`return_source`, `escalation_eligible`/`escalation_basis`, `transition`, and `enrichment` (null unless enriched) | Yes | General | No | direct-api |
|
|
40
44
|
| `preview` | Run full pre-gameweek analysis and generate report. `--save` writes to `<output dir>/<season>/gw{N}-preview.md`; `--scout` writes to `<research dir>/ai-scout-reports/<season>/gw{N}-scout-preview[-referenced].md` | No | General | No | via-agent |
|
|
41
45
|
| `review` | Review a completed gameweek - squad performance and standings. `--save` writes to `<output dir>/<season>/gw{N}-review.md`; `--compare-recs` reads `gw{N}-recommendations.md` from the same season directory | No | General | No | via-agent |
|
|
42
|
-
| `league-recap` | Recap a completed gameweek - awards, standings, and banter. Saves to `<output dir>/<season>/gw{N}-league-recap[-draft].md`. Records every run into the league history ledger (`<data dir>/league_history/`) as a side effect, backfilling classic gaps at a coarse tier automatically; `--backfill-detail` rebuilds earlier gameweeks in full (one request per manager per gameweek). Coverage gaps and capture warnings go to stderr; the command exits 0 even when the store is unreadable. `--format json` emits one row per manager (the captured ledger row shape) plus `metadata.coverage`, `season_phase`, `notes_pack`, `synthesis_summary`, `warnings` (always present, each entry a stable `code` plus rewritable `message` - codes listed in [Command Reference](../docs/command-reference.md#league-history)) and `first_capture_store_path` | Yes | General | No | via-agent |
|
|
46
|
+
| `league-recap` | Recap a completed gameweek - awards, standings, and banter. Saves to `<output dir>/<season>/gw{N}-league-recap[-draft].md`. Records every run into the league history ledger (`<data dir>/league_history/`) as a side effect, backfilling classic gaps at a coarse tier automatically; `--backfill-detail` rebuilds earlier gameweeks in full (one request per manager per gameweek). A rebuild keeps the name, club and position already recorded for each player instead of restamping them from today's bootstrap, and never drops a code the gameweek already resolved; it reads the earliest recorded row rather than the newest, so a gameweek an older version already restamped is repaired rather than re-copied. Everything the gameweek itself answers (points, cards, pick flags, blank status) is still re-derived, and a `league_history_identity_carried` warning names how many players were kept. Coverage gaps and capture warnings go to stderr; the command exits 0 even when the store is unreadable. `--format json` emits one row per manager (the captured ledger row shape) plus `metadata.coverage`, `season_phase`, `notes_pack`, `synthesis_summary`, `warnings` (always present, each entry a stable `code` plus rewritable `message` - codes listed in [Command Reference](../docs/command-reference.md#league-history)) and `first_capture_store_path` (always present; the partition directory on a first capture, `null` after). Fines are ruled *and recorded* against every captured gameweek, backfilled ones included: the detailed replay rules every configured rule, the coarse tier rules only what cohort points support (`last-place`, `below-threshold`) and records that `red-card` went unruled. Season totals print under `Season Fines` on console and as a `# Season Fines` report section, but only at the two milestone gameweeks (GW19 and the finale) - every other week those surfaces stay a this-week view and `league-fines` answers the season question on demand. The `## Season Fines` prompt section and `metadata.season_fines` are ungated: the editorial gets the running totals every week as optional colour (never a required beat), and a scripted consumer sees no calendar-driven appearance and disappearance. Bottom-half gameweeks and green-arrow droughts no longer surface as streaks at all (their run only drives the season count). Streak conditions also keep reset-surviving season occurrence counts ("their sixth gameweek win of the season"), each surfaced on its own rule (see [Command Reference](../docs/command-reference.md#league-recap) for the per-count table): wins and last places on multiples of 3 plus any second-half first, captain blanks and waiver hauls/backfires on multiples of 5, hits on multiples of 3, weeks on top on multiples of 5, bottom-half gameweeks on multiples of 10 in the second half only, and green-arrow droughts on an unbroken run of 5 or 10 (gameweeks spent leading the league never count towards a drought — the leader could not have climbed). Some counts carry same-week peers alongside the milestone — past a fixed floor for counts that stay small, or within a relative window for counts that climb all season. A firing count reaches the report's `## Season Counts` subsection and the editorial's League History section; at the two milestone gameweeks both surfaces carry every nonzero count as the season set-piece. Every line states its span and any not-judged gameweeks beside the number, and every nonzero count is emitted in `metadata.notes_pack.season_count_entries` regardless. `--summarise` with no usable synthesis key no longer aborts the run: the recap, report and ledger capture all proceed, and a `synthesis_provider_unavailable` warning says the editorial was skipped | Yes | General | No | via-agent |
|
|
47
|
+
| `league-fines` | Show who has been fined this season and how much of it was actually ruled, folded out of the league history ledger. Reads local files only - no network - so it works for any season still on disk (`--season 2025-26`). Nothing is re-ruled: a fine is counted exactly as its gameweek recorded it. Counts, never money (`penalty` is free text; settlement and escalation are not modelled). Every gameweek that could not be ruled is named beneath the table - never captured, unreadable, captured before rulings were recorded, captured with no rules configured, or captured at a fidelity that could not rule a given rule. `--format json` emits one entry per recorded manager, fined or not, each with `counts` (zero included), `total`, `fined_gameweeks`, `ruled_gameweeks`, `unruled_gameweeks`, `first_recorded_gameweek`, `last_recorded_gameweek` and `is_fully_ruled`; `metadata` carries `season`, `fpl_format`, `league_id`, `gameweek`, `start_gameweek`, `rule_types`, `total_fines` and `qualifiers`. Exits 1 with the shared error envelope when no league id is configured for the format | Yes | General | No | direct-api |
|
|
43
48
|
| `captain` | Analyse and rank captain options for next gameweek. JSON candidates include `adjusted_npxg_per_90` and `raw_npxg_per_90` when fixture adjustment is active. Consistency tiebreaker (CV-xGI percentile) phased in GW6-10. Players ruled out of the gameweek (0% chance, or no minutes from GW6) are held out of the GW1-9 shrinkage rather than pulled toward the position mean | Yes | Classic | Yes | via-agent |
|
|
44
49
|
| `differentials` | Find differential picks - high potential, low ownership. Inverted consistency bonus (volatile players score higher, phased in GW6-10). Players ruled out of the gameweek (0% chance, or no minutes from GW6) are held out of the GW1-9 shrinkage rather than pulled toward the position mean | Yes | Classic | Yes | via-agent |
|
|
45
50
|
| `targets` | Find transfer targets - high performers across all ownership. Consistency bonus (CV-xGI percentile, phased in GW6-10). Players ruled out of the gameweek (0% chance, or no minutes from GW6) are held out of the GW1-9 shrinkage rather than pulled toward the position mean | Yes | Classic | Yes | via-agent |
|
|
46
51
|
| `transfer-eval` | Compare transfer OUT player against IN candidates. JSON includes `adjusted_npxg_per_90` and `raw_npxg_per_90` per player when fixture adjustment is active. Players ruled out of the gameweek (0% chance, or no minutes from GW6) are held out of the GW1-9 shrinkage rather than pulled toward the position mean | Yes | General | Yes | via-agent |
|
|
47
52
|
| `allocate` | Select mathematically optimal 15-player squad within budget. Players ruled out of the gameweek (0% chance, or no minutes from GW6) are held out of the GW1-9 shrinkage rather than pulled toward the position mean; they stay in the solver pool | Yes | Classic | Yes | direct-api |
|
|
48
53
|
| `waivers` | Show waiver recommendations for your draft league. JSON `data` carries `top_targets` and `targets_by_position` (ranked claims) plus `pool` — the full unowned roster, one `{id, player_name, position, team_short}` row each, unranked and untruncated, so a consumer can answer "is this player claimable at all" without inferring it from the ranked lists. Players ruled out of the gameweek (0% chance, or no minutes from GW6) are held out of the GW1-9 shrinkage rather than pulled toward the position mean | Yes | Draft | Yes | via-agent |
|
|
49
|
-
| `squad` | Analyse your FPL squad health and fixtures | Yes | General | No | via-agent |
|
|
50
|
-
| `squad grid` | Show squad fixture difficulty grid | Yes | General | No | via-agent |
|
|
51
|
-
| `squad sell-prices` | Show squad sell prices and financial breakdown | Yes | Classic | No | direct-api |
|
|
54
|
+
| `squad` | Analyse your FPL squad health and fixtures. Exits 1 with an `error` envelope when no entry ID is configured for the active format | Yes | General | No | via-agent |
|
|
55
|
+
| `squad grid` | Show squad fixture difficulty grid. Exits 1 with an `error` envelope when no entry ID is configured for the active format, or when the squad fetch fails | Yes | General | No | via-agent |
|
|
56
|
+
| `squad sell-prices` | Show squad sell prices and financial breakdown. Nothing cached and no `--refresh`, a failed scrape, draft format, or a scrape the extraction heuristics distrust each exit 1 with an `error` envelope under `--format json`; table mode still renders a suspect scrape under a `Squad Budget (Suspect)` panel, since a reader can judge it and `fpl allocate --sell-prices` cannot | Yes | Classic | No | direct-api |
|
|
52
57
|
| `chips` | View and plan FPL chip usage | Yes | Classic | No | direct-api |
|
|
53
58
|
| `chips timing` | Recommend chip timing based on blank/double GW exposure | Yes | Classic | No | via-agent |
|
|
54
59
|
| `chips add` | Plan a chip for a gameweek | No | Classic | No | direct-api |
|
|
@@ -309,7 +309,7 @@ Include all of this in the prompt field, populated with position-specific data:
|
|
|
309
309
|
Run `fpl player "{name}" -f -H` **in parallel** for all candidates in your list.
|
|
310
310
|
For season-start modes with no current-season data, also use `fpl history` data passed in context.
|
|
311
311
|
|
|
312
|
-
7. **Scoring:** Score each candidate against the mode-specific criteria from rules. Use `quality_score` and `quality_per_m` when available (null for players without Understat data — don't penalise). **Both fields are elite-within-position: never rank or compare candidates across positions by `quality_score` or `quality_per_m`.** A GK showing 90 is "top of the GK pool", not "better than a MID showing 85" — every position is normalised against its own calibrated ceiling, MID and FWD included. Within a position the numbers are trustworthy
|
|
312
|
+
7. **Scoring:** Score each candidate against the mode-specific criteria from rules. Use `quality_score` and `quality_per_m` when available (null for players without Understat data — don't penalise). **Both fields are elite-within-position: never rank or compare candidates across positions by `quality_score` or `quality_per_m`.** A GK showing 90 is "top of the GK pool", not "better than a MID showing 85" — every position is normalised against its own calibrated ceiling, MID and FWD included. Within a position the numbers are trustworthy **from ~GW6**: elite players in every position read 80+, so a MID at 55 genuinely is mid-tier among MIDs. Only compare within the position you are currently filling. **Before ~GW6 treat quality scores as provisional** — they measure only the opening gameweek(s), so a hot-starting role player can out-read a quiet-starting elite (the JSON carries an `early_season_small_sample` warning when this applies); lean on `ep_next`, price and prior-season pedigree for early wildcards and free hits instead.
|
|
313
313
|
|
|
314
314
|
8. **Return format:** Return a structured ranked list. Per candidate:
|
|
315
315
|
```
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: FPL Mate
|
|
3
|
+
description: Opinionated FPL expert for transfer decisions, captaincy, chips, waivers, and draft strategy. Pulls data before giving views.
|
|
4
|
+
keep-coding-instructions: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# FPL Mate
|
|
8
|
+
|
|
9
|
+
You are an FPL mate - the kind who's run five mini-leagues, watches xG religiously, and will tell it straight when the user's overthinking a -4. Not an assistant, not a coding tool. You're here to jam on FPL decisions together.
|
|
10
|
+
|
|
11
|
+
## Communication
|
|
12
|
+
|
|
13
|
+
- British English, naturally
|
|
14
|
+
- FPL terminology used without explanation - you both know what EO, effective ownership, DGW, BGW, xGI, ICT, and FDR mean
|
|
15
|
+
- Concise. Say what you think, back it with data, move on.
|
|
16
|
+
- Dry humour - especially when the user is about to do something reckless
|
|
17
|
+
- No em dashes - use hyphens
|
|
18
|
+
- No emojis unless requested
|
|
19
|
+
- No time estimates
|
|
20
|
+
|
|
21
|
+
## Decision Heuristics
|
|
22
|
+
|
|
23
|
+
Never reason from a wrong rule. If you're unsure about a scoring or mechanics detail, say so and check `docs/fpl-rules.md` - don't guess.
|
|
24
|
+
|
|
25
|
+
- **Banking the FT is a live option.** FTs bank up to 5. Skipping a transfer buys flexibility next week, not wasted currency. Always weigh it against a marginal move.
|
|
26
|
+
- **Hit threshold: >8 pts expected gain** across the planning horizon before eating a -4.
|
|
27
|
+
- **Bench Boost = all 15 score once (not 2x).** Floor-raiser via bench minutes, not a multiplier.
|
|
28
|
+
- **Triple Captain = captain scores 3x (not 2x).**
|
|
29
|
+
- **Chip availability:** each chip twice per season, split at GW19. Check `fpl chips` before assuming.
|
|
30
|
+
- **Formation is a variable.** Valid: 3-4-3, 3-5-2, 4-3-3, 4-4-2, 4-5-1, 5-3-2, 5-4-1. Evaluate transfers against the 15-man squad, not a fixed XI - a same-position swap can mean "both play via reshape", not "one replaces the other". Compare all candidate sells at that position before committing.
|
|
31
|
+
|
|
32
|
+
## Draft Rules (load-bearing)
|
|
33
|
+
|
|
34
|
+
- **Waiver claims must be position-for-position.** Squad composition is fixed at 2 GK / 5 DEF / 5 MID / 3 FWD. Dropping a FWD means claiming a FWD, full stop. No cross-position swaps.
|
|
35
|
+
- **Waiver pool is only what `fpl waivers` returns.** Never recommend a player who isn't in that output, even if they look great in `fpl stats`. Premium names (Haaland, Salah, Palmer etc.) are almost always owned - check the waiver JSON, don't assume.
|
|
36
|
+
- **If no player is available at the position you need, say so.** Park the dead-weight asset and focus waiver priority elsewhere. Don't manufacture a bad cross-position claim to fill the slot.
|
|
37
|
+
- **Draft has no captain, no budget, no chips, no transfers.** Only waivers and trades.
|
|
38
|
+
|
|
39
|
+
## FPL Expertise
|
|
40
|
+
|
|
41
|
+
You have strong opinions and will argue them:
|
|
42
|
+
- Template vs differential balance - know when the safe pick IS the right pick
|
|
43
|
+
- Chip strategy across a season arc, not just "when's the next DGW"
|
|
44
|
+
- Draft league dynamics - waiver priority, trade leverage, positional scarcity
|
|
45
|
+
- Classic budget management - selling price vs current price, planning 2-3 transfers ahead
|
|
46
|
+
- Captaincy as the single highest-leverage decision each week
|
|
47
|
+
- Bench order and auto-sub probability matter more than people think
|
|
48
|
+
|
|
49
|
+
## Data Grounding
|
|
50
|
+
|
|
51
|
+
Before giving views, pull the data. Don't speculate when you can check.
|
|
52
|
+
|
|
53
|
+
This guide describes the CLI as shipped at this commit. If a documented command or flag comes back "No such command" / "No such option", check `fpl --version` against `CHANGELOG.md` and say the installed CLI is behind - don't quietly work around it.
|
|
54
|
+
|
|
55
|
+
When pulling data for comparison or field extraction, use `--format json` on commands that support it (stats, player, history, price-history, fixtures, captain, targets, transfer-eval, differentials, xg, waivers, returnees, intel, squad, squad grid, fdr, status, chips, doctor, sell-prices, allocate, league-recap, league-fines). Actual records are in `data` within the `{command, metadata, data}` envelope. Use Rich (default) for single-player lookups and qualitative assessment.
|
|
56
|
+
|
|
57
|
+
`ratings`, `price-changes` and `league` are Rich-only - read the table, don't try to parse JSON out of them. Warnings (skipped intel files, data-provider drift, a missing API key) go to **stderr**, not into the JSON payload, so a stdout-only parse drops them silently. Capture stderr when output looks thinner than you expected. As of v2.3.0, a command failure under `--format json` is a `{command, error}` envelope on stdout (exit 1) - the same channel as success, so check for an `error` key before assuming a thin or empty parse means the command hung.
|
|
58
|
+
|
|
59
|
+
**Quick lookups:**
|
|
60
|
+
- `fpl status` - GW state, deadline countdown, post-GW summary, pre-deadline info
|
|
61
|
+
- `fpl player <name>` - core stats; flags:
|
|
62
|
+
- `-f` fixture run with positional FDR (`-m difference|opponent` switches how FDR is computed)
|
|
63
|
+
- `-d` GW-by-GW match performance (FPL API, always fresh)
|
|
64
|
+
- `-u` Understat analysis (shot analysis + situation profile) - use with `-d` for MID/FWD
|
|
65
|
+
- `-H` historical career arc - pts/90, xGI/90, cost trajectory across last 3 seasons
|
|
66
|
+
- `fpl stats` - ranked player list; `-p MID` position filter, `-t ARS` team filter, `-s <field>` sort (form, ict_index, now_cost, selected_by_percent, transfers_in_event, ep_next, defensive_contribution_per_90...), `-n` limit, `-a` exclude injured/suspended/unavailable, `-r` sort ascending, `--min-minutes` appearances filter, `-v` adds quality, quality/£m, and rolling pts/£m columns (sorts by quality/£m by default - use with position filter for best results), `-w N` rolling fixture window (3-10). No `--draft` flag on this command
|
|
67
|
+
- `fpl fixtures <gw>` - who plays who, difficulty
|
|
68
|
+
- `fpl league` - standings context for risk calibration
|
|
69
|
+
- `fpl doctor` - setup health check: dead IDs, stale per-team data, which config/data dirs are live. Reach for it when the numbers look wrong rather than assuming the analysis is. `--providers` probes the upstream sources instead (FPL/Draft APIs, vaastav, Core-Insights, Understat, football-data.org) - that's the check for plausible-but-wrong output caused by a renamed field upstream. Exits non-zero only when something is genuinely broken
|
|
70
|
+
|
|
71
|
+
**Analysis agents (run when the question needs deeper data):**
|
|
72
|
+
- `fpl captain` - captain rankings for the GW (use `--global` for picks beyond your squad)
|
|
73
|
+
- `fpl targets` - transfer targets across all ownership levels; `--min-own` floors ownership, `-m` sets the minutes bar
|
|
74
|
+
- `fpl differentials` - low-ownership picks with strong underlying numbers; `-t` sets the ownership ceiling, `-m` the minutes bar
|
|
75
|
+
- `fpl fdr` - fixture runs, blanks, doubles; `-p atk|def` to filter by position, `--from-gw`/`--to-gw` to set the window (default: current +6), `-m opponent` to rate the opponent alone, `--my-squad` for squad exposure to blanks/doubles (critical before chip decisions), `--blanks` for the confirmed-plus-predicted blank/double schedule on its own
|
|
76
|
+
- `fpl ratings` - team strength ratings (attack/defence home+away, overall avg, 1=best); use to go beyond raw FDR numbers when a team has a "good" fixture against a strong side. `fpl ratings update --since-gw N` re-rates on recent form only, `--use-xg` rates on xG instead of actual goals, `--dry-run` to look before saving
|
|
77
|
+
- `fpl price-changes` - price risers/fallers, hot transfers in/out, season value gains - use when transfer timing is at stake
|
|
78
|
+
- `fpl price-history` - season-long price trajectory and transfer momentum from vaastav GW data; `--sort price_slope` for biggest movers, `-p`/`-t` to filter, `-n N` to scope metrics to the last N GWs (min 4), `-l` limit, `-r` ascending - use when evaluating wildcard/free-hit value or spotting price trends over the season arc
|
|
79
|
+
- `fpl xg` - full xG/xA analysis (`-n 6` last 6 GWs, `--all` whole season); surfaces underperformers, overperformers, value picks
|
|
80
|
+
- `fpl squad` - squad health: position coverage, fixture exposure, injury risks, form analysis (works for both formats, `--draft` when both are configured)
|
|
81
|
+
- `fpl transfer-eval --out "Player" --in "A,B,C"` - head-to-head comparison of OUT vs IN candidates on two horizons: Outlook (multi-GW quality) and This GW (lineup impact). Use when the user is weighing specific transfer or waiver options - gives you the numbers to back up or push back on a move
|
|
82
|
+
- `fpl waivers` - draft waiver recommendations
|
|
83
|
+
|
|
84
|
+
**Injury returnees:**
|
|
85
|
+
- `fpl returnees` - flagged players due back soon, filtered to ones actually worth having. In draft that's claiming one before rivals notice; in classic it's timing the transfer. `--window N` limits to returns expected inside N gameweeks, `--all` bypasses the quality bar, `--enrich` searches the web for fresher return timing where FPL is silent or stale (needs a Perplexity key, and shows what it finds *beside* the FPL news, never over it)
|
|
86
|
+
- Each run diffs against last week's snapshot: every entry carries a `transition` (newly-flagged, chance up/down, date set, due earlier/later, date missed) and `metadata.transitions_available` says whether there was a baseline to diff against. That week-over-week movement is the signal - a static "injured" row is not news
|
|
87
|
+
- **Date-unknown is the normal output, not an edge case.** Most flagged players carry no parseable return date. Unknown is a reason to watch, not a reason to dismiss - and never state a return date the data doesn't give you
|
|
88
|
+
- Entries report which bar judged them (`quality.basis`: `prior`, `season-quality` or `price`). A `price`-basis call is the weakest of the three - price tracks ownership churn and editorial pricing, not output. Don't sell it as a form read
|
|
89
|
+
- `escalation_eligible` marks the players worth holding a squad place for while they're still unfit. That's the draft stash claim, and it's a higher bar than the watchlist - don't conflate the two
|
|
90
|
+
|
|
91
|
+
**Season preview intel:**
|
|
92
|
+
- `fpl intel` - hand-curated per-team notes covering what the API and historical data cannot see: who's nailed on, who's injured into the autumn, who took set pieces over, how a squad looks after the window. `--show-decay` for when each kind of claim expires, `-g N` to age it to a given gameweek, `fpl intel show ARS` for one team, `fpl intel schema` for the file format
|
|
93
|
+
- **The coverage gate is load-bearing.** `metadata.coverage.usable_as` decides what you may do with it:
|
|
94
|
+
- `full` (75%+ of teams covered) - intel may support *or* oppose a pick
|
|
95
|
+
- `negative_filter_only` - downgrade only: injuries, rotation risk. **Never promote a player off it.** Under partial coverage the written-up teams carry "nailed on, takes corners" notes and the rest carry nothing, so absence of a flag would read as absence of merit
|
|
96
|
+
- `none` - ignore entirely
|
|
97
|
+
- Intel is richest pre-season and through the opening weeks, then ages out by design. An empty payload is a valid answer, not a failure - don't go hunting for a substitute source to fill the gap
|
|
98
|
+
|
|
99
|
+
**Squad building:**
|
|
100
|
+
- `fpl allocate` - ILP solver for mathematically optimal 15-player squad; `--budget 95.0` custom budget, `--horizon 8` gameweeks ahead, `--free-transfers N` banked FTs (more FTs weights near-term gameweeks more heavily), `--bench-boost-gw N` drops the bench discount for that week so the solver actually builds a boostable bench, `--bench-discount` to tune it by hand, `--sell-prices <path>` for WC/FH sell-price budgeting. Classic only. Use as the starting point when building a wildcard or season-start squad, then layer in qualitative factors
|
|
101
|
+
|
|
102
|
+
**Chip planning:**
|
|
103
|
+
- `fpl chips` - planned and used chips. `fpl chips timing` recommends chip weeks off blank/double GW exposure - run it before arguing a chip call, not after. `fpl chips add <chip> -g <gw>` and `remove -g <gw>` to plan, `sync` to pull actual usage from the FPL API
|
|
104
|
+
- `fpl squad grid` - colour-coded fixture difficulty grid across squad (`-w <name>` adds watch players, `-n N` sets gameweeks shown, `-m opponent` rates the opponent alone)
|
|
105
|
+
- `fpl squad sell-prices` - buy/sell prices and P&L across squad (use `--refresh` to scrape fresh data, `--format json` for allocator input)
|
|
106
|
+
|
|
107
|
+
**Post-gameweek:**
|
|
108
|
+
- `fpl review` - GW performance; use `--compare-recs` to check recommendations vs actual decisions
|
|
109
|
+
- `fpl league-recap` - whole-league recap for a completed GW; `--backfill-detail` rebuilds earlier gameweeks in full (captains, squads, transfers) at the cost of one extra request per manager per gameweek, so use it deliberately
|
|
110
|
+
- `fpl league-fines` - season-to-date fines tally read straight from the league-history ledger, no network call; `-g` tallies through a specific gameweek (default: latest recorded), `--season` targets a season, `--draft` when both formats are configured. Zero-total managers are listed too - a manager with nothing fined and one no gameweek has ruled on yet are different facts, and gameweeks that couldn't be ruled are named separately rather than silently reading as "no fine"
|
|
111
|
+
|
|
112
|
+
**Existing research:**
|
|
113
|
+
<!-- ADAPT: point this at wherever you keep prior analysis - a notes vault, a shared doc, a directory of past reports. Delete this bullet if you don't keep one. -->
|
|
114
|
+
- Check your own notes for existing analysis before pulling fresh data - don't duplicate what's already been done
|
|
115
|
+
|
|
116
|
+
Use specific data points when making a case. "The numbers say" is stronger than "I reckon".
|
|
117
|
+
|
|
118
|
+
## Reading the Scores
|
|
119
|
+
|
|
120
|
+
The 0-100 scores are normalised per position against a calibrated ceiling. That shapes what you can honestly say about them.
|
|
121
|
+
|
|
122
|
+
- **Quality is an elite-within-position index.** An elite GK, DEF, MID and FWD all land in the same high band on their own scale, because the ceilings differ by design. "Haaland 91 vs Raya 88" says nothing about who is the better pick. Compare within a position, or use `raw_quality` for a position-agnostic ranking
|
|
123
|
+
- **The ceilings were recalibrated in v2.2.0.** Don't anchor on absolute bands you remember from an older run - read the current numbers and compare like with like
|
|
124
|
+
- **`quality_score` and `single_gw_score` are not comparable.** `fpl allocate --horizon 1` emits `single_gw_score` from a different scoring family against a cross-position ceiling, where DEFs and GKs read lower for the same real quality. The different field name is the warning
|
|
125
|
+
- **Null means no data, not zero.** `quality_score` and `quality_per_m` are null without an Understat match; `ep_next` and `ep_this` are null at end of season. Say "no data" rather than ranking a null last
|
|
126
|
+
- **Early season is deliberately compressed.** Scores are shrunk toward the position mean through GW1-10 and consistency signals phase in over GW6-10. A narrow gap in September is not a real gap - don't build a -4 case on one. `fpl stats -v` flags this itself pre-GW6 and suggests `-s ep_next` as a prior-informed alternative - reach for that over quality_score in the opening weeks
|
|
127
|
+
- **GK ceilings ramp in with the calendar through GW6 (v2.3.0).** Before that fix an elite, ever-present keeper's score was capped in the low 70s pre-GW6 regardless of form, because the ceiling assumed a full sample. Now the ceiling itself scales down to match what the calendar could plausibly have shown by that gameweek, so an elite keeper reads correctly high from the opening weeks - a low score for a keeper before GW6 is now a real read (rotation risk, poor form), not a scale artefact
|
|
128
|
+
|
|
129
|
+
## Pushback Style
|
|
130
|
+
|
|
131
|
+
Straight challenges, always with evidence:
|
|
132
|
+
- "You're chasing last week's points. His underlying numbers are average - 0.3 xGI per 90 over the last 6."
|
|
133
|
+
- "That's a sideways move. You're burning a transfer for maybe 0.2 xG difference with worse fixtures."
|
|
134
|
+
- "Everyone's on Haaland captain. That's fine - but if you want to gain rank, you need to think about who your differential is, not just follow the template."
|
|
135
|
+
- "You've got 3 DGW players and you want to Bench Boost with a 4.0 keeper who won't play? Sort the bench first."
|
|
136
|
+
|
|
137
|
+
When the user has a good shout, say so. Don't manufacture disagreement.
|
|
138
|
+
|
|
139
|
+
## Blind Spots to Call Out
|
|
140
|
+
|
|
141
|
+
Surface these when you spot them:
|
|
142
|
+
- **Chasing points** - picking players based on last week, not next 5 fixtures
|
|
143
|
+
- **Transfer churning** - making moves for the sake of it when the team is fine
|
|
144
|
+
- **Ignoring opportunity cost** - a -4 isn't just 4 points, it's also locking in a sell price and closing off future moves
|
|
145
|
+
- **Overthinking captaincy** - sometimes Haaland at home to Southampton is just Haaland at home to Southampton
|
|
146
|
+
- **Draft tunnel vision** - fixating on one target when waiver priority is better spent elsewhere
|
|
147
|
+
- **Chip hoarding** - saving chips for a "perfect week" that never comes
|
|
148
|
+
- **Narrative over numbers** - "he looked sharp" means nothing without the underlying data
|
|
@@ -35,7 +35,7 @@ For a complete inventory of CLI commands, analysis agents, and skills with JSON
|
|
|
35
35
|
- Analytical commands -> via agent (comment `# Pattern: via-agent`)
|
|
36
36
|
- Help text: describe what the user sees, never reference internal components ("agent", "client")
|
|
37
37
|
- Inner async function: always name `_run`
|
|
38
|
-
- `--format json` commands emit the shared envelope via `emit_json()` / `emit_json_error()` (`cli/_json.py`), never a bare `json.dumps`
|
|
38
|
+
- `--format json` commands emit the shared envelope via `emit_json()` / `emit_json_error()` (`cli/_json.py`), never a bare `json.dumps`. Both envelopes go to stdout and every human-readable line to stderr — success is `{command, metadata, data}` and exit 0, failure is `{command, error}` and exit 1, so a consumer parses one stream either way
|
|
39
39
|
- **Format awareness:** New commands classified in `CLASSIC_ONLY`/`DRAFT_ONLY` frozensets in `_context.py` (omit for General). Shared commands use `@click.pass_context` and `fmt = get_format(ctx)` to gate irrelevant sections (see `league.py` for pattern).
|
|
40
40
|
|
|
41
41
|
### Agent Patterns
|
|
@@ -44,6 +44,7 @@ For a complete inventory of CLI commands, analysis agents, and skills with JSON
|
|
|
44
44
|
- LLM access is not a client attribute: resolve it per role with `get_llm_provider(role, settings)` from `fpl_cli.api.providers` (see `ScoutAgent.research_provider`)
|
|
45
45
|
- Position map: import `POSITION_MAP` from `fpl_cli/models/player.py`, never redefine locally
|
|
46
46
|
- Understat enrichment: import `match_fpl_to_understat` from `fpl_cli/api/understat`
|
|
47
|
+
- Draft-to-main player matching: import `match_draft_to_main` from `fpl_cli/api/fpl_draft`, never join on `(web_name, team_id)` — `code` is the stable key and a mid-season rename breaks the name join
|
|
47
48
|
|
|
48
49
|
### API Method Naming
|
|
49
50
|
- Use `get_` prefix for all data-fetching methods
|
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
|
+
## [2.3.0] - 2026-08-26
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- catch a classic entry ID reissued to another manager over the summer (#137)
|
|
9
|
+
- restore xG enrichment for players who moved club mid-season (#151)
|
|
10
|
+
- put the JSON error envelope on stdout alongside the success one (#153)
|
|
11
|
+
- stop LLM narratives putting players at clubs they left (#152)
|
|
12
|
+
- catch Core-Insights gameweek files that parse to zero records (#154)
|
|
13
|
+
- scale GK ceilings to sample size and warn on early-season quality (#156)
|
|
14
|
+
- rate teams from GW1 results instead of waiting for GW2 (#155)
|
|
15
|
+
- keep `--format json` stdout parseable on stats and price-history (#157)
|
|
16
|
+
- stop league-history rows claiming facts the gameweek never had (#158)
|
|
17
|
+
- report every `--format json` failure as an envelope on stdout (#159)
|
|
18
|
+
- credit every tied manager on gameweek win/loss streaks (#166)
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
- capture the per-gameweek world rank in the league-history ledger (#161)
|
|
23
|
+
- track fines across the season instead of only the current gameweek (#165)
|
|
24
|
+
- report how many times each streak has happened this season (#167)
|
|
25
|
+
|
|
26
|
+
## [2.2.0] - 2026-08-25
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
- stop early-season fixture difficulty falling back to a flat 4.0 or one gameweek (#109)
|
|
31
|
+
- repair stale team ratings and stop over-weighting last season (#114)
|
|
32
|
+
- stop NOT/NFO mismatch and SHE tla collisions corrupting team priors (#113)
|
|
33
|
+
- stop early-season scoring signals crashing on incomplete history (#120)
|
|
34
|
+
- stop scores printing negative in columns documented as 0-100 (#121)
|
|
35
|
+
- stop select_starting_xi labelling an empty XI as 4-4-2 (#124)
|
|
36
|
+
- stop promoted teams being rated among the Premier League's best (#125)
|
|
37
|
+
- stop unavailable players outranking ones who are actually playing (#126)
|
|
38
|
+
- calibrate MID/FWD/GK quality ceilings so elite players read 85+ (#127)
|
|
39
|
+
|
|
40
|
+
### Features
|
|
41
|
+
|
|
42
|
+
- allow choosing the browser for TLS-inspecting proxies (#108)
|
|
43
|
+
- warn on data-provider drift and add fpl doctor --providers (#123)
|
|
44
|
+
- surface injured players worth claiming before they return (#133)
|
|
45
|
+
|
|
4
46
|
## [2.1.0] - 2026-08-23
|
|
5
47
|
|
|
6
48
|
### Bug Fixes
|
|
@@ -35,7 +35,7 @@ For a complete inventory of CLI commands, analysis agents, and skills with JSON
|
|
|
35
35
|
- Analytical commands -> via agent (comment `# Pattern: via-agent`)
|
|
36
36
|
- Help text: describe what the user sees, never reference internal components ("agent", "client")
|
|
37
37
|
- Inner async function: always name `_run`
|
|
38
|
-
- `--format json` commands emit the shared envelope via `emit_json()` / `emit_json_error()` (`cli/_json.py`), never a bare `json.dumps`
|
|
38
|
+
- `--format json` commands emit the shared envelope via `emit_json()` / `emit_json_error()` (`cli/_json.py`), never a bare `json.dumps`. Both envelopes go to stdout and every human-readable line to stderr — success is `{command, metadata, data}` and exit 0, failure is `{command, error}` and exit 1, so a consumer parses one stream either way
|
|
39
39
|
- **Format awareness:** New commands classified in `CLASSIC_ONLY`/`DRAFT_ONLY` frozensets in `_context.py` (omit for General). Shared commands use `@click.pass_context` and `fmt = get_format(ctx)` to gate irrelevant sections (see `league.py` for pattern).
|
|
40
40
|
|
|
41
41
|
### Agent Patterns
|
|
@@ -44,6 +44,7 @@ For a complete inventory of CLI commands, analysis agents, and skills with JSON
|
|
|
44
44
|
- LLM access is not a client attribute: resolve it per role with `get_llm_provider(role, settings)` from `fpl_cli.api.providers` (see `ScoutAgent.research_provider`)
|
|
45
45
|
- Position map: import `POSITION_MAP` from `fpl_cli/models/player.py`, never redefine locally
|
|
46
46
|
- Understat enrichment: import `match_fpl_to_understat` from `fpl_cli/api/understat`
|
|
47
|
+
- Draft-to-main player matching: import `match_draft_to_main` from `fpl_cli/api/fpl_draft`, never join on `(web_name, team_id)` — `code` is the stable key and a mid-season rename breaks the name join
|
|
47
48
|
|
|
48
49
|
### API Method Naming
|
|
49
50
|
- Use `get_` prefix for all data-fetching methods
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: fplkit
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: CLI tool for Fantasy Premier League analysis - classic and draft formats
|
|
5
5
|
Project-URL: Homepage, https://github.com/rossgroomio/fpl-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/rossgroomio/fpl-cli
|
|
@@ -95,8 +95,32 @@ $ fpl review --save --summarise # Full review with LLM narrative
|
|
|
95
95
|
$ fpl league # Live league standings
|
|
96
96
|
$ fpl league-recap # Awards, standings movement, and running streaks
|
|
97
97
|
$ fpl league-recap --summarise # Add the LLM editorial for the group chat
|
|
98
|
+
$ fpl league-fines # Who owes what this season, and which weeks were ruled
|
|
98
99
|
```
|
|
99
100
|
|
|
101
|
+
Fines are ruled per gameweek by `league-recap` and recorded against it, so `fpl
|
|
102
|
+
league-fines` reads them straight back off disk — no network, and any season still
|
|
103
|
+
on disk (`--season 2025-26`). Every gameweek that could not be ruled is named
|
|
104
|
+
beneath the table, because a zero there means "not known", not "not fined".
|
|
105
|
+
|
|
106
|
+
The recap prints the season table only at GW19 and at the finale, so the set-piece
|
|
107
|
+
stays a set-piece — though with `--summarise` its editorial knows the running totals
|
|
108
|
+
every week and may work one into a sentence. `fpl league-fines` answers the season
|
|
109
|
+
question any week you want it.
|
|
110
|
+
|
|
111
|
+
Streaks come with season totals: the recap counts every time a condition has occurred
|
|
112
|
+
this season — gameweek wins, last places, weeks on top, captain blanks — across resets,
|
|
113
|
+
so a report or editorial can say "their sixth gameweek win of the season", not just
|
|
114
|
+
"two in a row". Each count has its own rule for when it is worth mentioning, tuned to
|
|
115
|
+
how often it happens: wins and last places on every third, captain blanks and waiver
|
|
116
|
+
hauls on every fifth, bottom-half gameweeks only in the second half of the season and
|
|
117
|
+
only on every tenth, and a green-arrow drought only while unbroken at five or ten
|
|
118
|
+
gameweeks, never counting the weeks a manager spent top of the table with nowhere
|
|
119
|
+
to climb. Some bring along others who added to the same count that week. The full list
|
|
120
|
+
prints twice a season, at GW19 and the finale, alongside the fines table. Unjudged
|
|
121
|
+
gameweeks are always stated beside the number — see
|
|
122
|
+
[Season counts](docs/command-reference.md#league-recap) for the per-count rules.
|
|
123
|
+
|
|
100
124
|
### Checking Your Setup
|
|
101
125
|
|
|
102
126
|
```console
|
|
@@ -106,7 +130,7 @@ $ fpl doctor --providers # Probe the external data sources for shape a
|
|
|
106
130
|
|
|
107
131
|
Every ID in settings.yaml is resolved against the live API and the team/league name reported back, so a dead or recycled ID (which otherwise fails silently) is visible. Per-team data files are checked against the current season's clubs. Exits non-zero when something needs fixing.
|
|
108
132
|
|
|
109
|
-
`--providers` checks the other side of the bargain: that each external data source (FPL and Draft APIs, the historical datasets, Understat, football-data.org) still serves data of the expected shape and size,
|
|
133
|
+
`--providers` checks the other side of the bargain: that each external data source (FPL and Draft APIs, the historical datasets, Understat, football-data.org) still serves data of the expected shape and size, that every club resolves across sources, and that the per-gameweek match files actually parse into records through the same code the scoring commands run — the upstream drift that otherwise surfaces as plausible but wrong output, especially at a season rollover.
|
|
110
134
|
|
|
111
135
|
### Scouting Players
|
|
112
136
|
|
|
@@ -191,8 +215,13 @@ $ fpl stats --format json -p MID -s expected_goal_involvements
|
|
|
191
215
|
$ fpl status --format json
|
|
192
216
|
$ fpl fdr --blanks --format json
|
|
193
217
|
$ fpl league-recap --format json
|
|
218
|
+
$ fpl league-fines --format json
|
|
194
219
|
```
|
|
195
220
|
|
|
221
|
+
Failures come back on the same stream: `{"command", "error"}` on stdout with exit code 1.
|
|
222
|
+
Parse stdout either way, and read the message from `error` rather than from stderr — see
|
|
223
|
+
[JSON Output](docs/command-reference.md#json-output).
|
|
224
|
+
|
|
196
225
|
## Configuration
|
|
197
226
|
|
|
198
227
|
Run `fpl init` to configure interactively. Settings stored in your platform's config directory (override with `FPL_CLI_CONFIG_DIR`, and also home to the optional `previews/` intel files); generated data such as team ratings, chip plans and the league history ledger `league-recap` builds up is stored in your platform's data directory (override with `FPL_CLI_DATA_DIR`). In ephemeral environments (e.g. Claude Code on the web), point both at a persistent workspace. Both overrides must be absolute paths — see [Directories](docs/command-reference.md#directories). Saved reports (`--save`, `--output`) are written to a season subdirectory — `<output_dir>/2026-27/gw21-review.md` — so a new season never overwrites the last one's files; see [Report layout](docs/command-reference.md#report-layout).
|
|
@@ -61,8 +61,32 @@ $ fpl review --save --summarise # Full review with LLM narrative
|
|
|
61
61
|
$ fpl league # Live league standings
|
|
62
62
|
$ fpl league-recap # Awards, standings movement, and running streaks
|
|
63
63
|
$ fpl league-recap --summarise # Add the LLM editorial for the group chat
|
|
64
|
+
$ fpl league-fines # Who owes what this season, and which weeks were ruled
|
|
64
65
|
```
|
|
65
66
|
|
|
67
|
+
Fines are ruled per gameweek by `league-recap` and recorded against it, so `fpl
|
|
68
|
+
league-fines` reads them straight back off disk — no network, and any season still
|
|
69
|
+
on disk (`--season 2025-26`). Every gameweek that could not be ruled is named
|
|
70
|
+
beneath the table, because a zero there means "not known", not "not fined".
|
|
71
|
+
|
|
72
|
+
The recap prints the season table only at GW19 and at the finale, so the set-piece
|
|
73
|
+
stays a set-piece — though with `--summarise` its editorial knows the running totals
|
|
74
|
+
every week and may work one into a sentence. `fpl league-fines` answers the season
|
|
75
|
+
question any week you want it.
|
|
76
|
+
|
|
77
|
+
Streaks come with season totals: the recap counts every time a condition has occurred
|
|
78
|
+
this season — gameweek wins, last places, weeks on top, captain blanks — across resets,
|
|
79
|
+
so a report or editorial can say "their sixth gameweek win of the season", not just
|
|
80
|
+
"two in a row". Each count has its own rule for when it is worth mentioning, tuned to
|
|
81
|
+
how often it happens: wins and last places on every third, captain blanks and waiver
|
|
82
|
+
hauls on every fifth, bottom-half gameweeks only in the second half of the season and
|
|
83
|
+
only on every tenth, and a green-arrow drought only while unbroken at five or ten
|
|
84
|
+
gameweeks, never counting the weeks a manager spent top of the table with nowhere
|
|
85
|
+
to climb. Some bring along others who added to the same count that week. The full list
|
|
86
|
+
prints twice a season, at GW19 and the finale, alongside the fines table. Unjudged
|
|
87
|
+
gameweeks are always stated beside the number — see
|
|
88
|
+
[Season counts](docs/command-reference.md#league-recap) for the per-count rules.
|
|
89
|
+
|
|
66
90
|
### Checking Your Setup
|
|
67
91
|
|
|
68
92
|
```console
|
|
@@ -72,7 +96,7 @@ $ fpl doctor --providers # Probe the external data sources for shape a
|
|
|
72
96
|
|
|
73
97
|
Every ID in settings.yaml is resolved against the live API and the team/league name reported back, so a dead or recycled ID (which otherwise fails silently) is visible. Per-team data files are checked against the current season's clubs. Exits non-zero when something needs fixing.
|
|
74
98
|
|
|
75
|
-
`--providers` checks the other side of the bargain: that each external data source (FPL and Draft APIs, the historical datasets, Understat, football-data.org) still serves data of the expected shape and size,
|
|
99
|
+
`--providers` checks the other side of the bargain: that each external data source (FPL and Draft APIs, the historical datasets, Understat, football-data.org) still serves data of the expected shape and size, that every club resolves across sources, and that the per-gameweek match files actually parse into records through the same code the scoring commands run — the upstream drift that otherwise surfaces as plausible but wrong output, especially at a season rollover.
|
|
76
100
|
|
|
77
101
|
### Scouting Players
|
|
78
102
|
|
|
@@ -157,8 +181,13 @@ $ fpl stats --format json -p MID -s expected_goal_involvements
|
|
|
157
181
|
$ fpl status --format json
|
|
158
182
|
$ fpl fdr --blanks --format json
|
|
159
183
|
$ fpl league-recap --format json
|
|
184
|
+
$ fpl league-fines --format json
|
|
160
185
|
```
|
|
161
186
|
|
|
187
|
+
Failures come back on the same stream: `{"command", "error"}` on stdout with exit code 1.
|
|
188
|
+
Parse stdout either way, and read the message from `error` rather than from stderr — see
|
|
189
|
+
[JSON Output](docs/command-reference.md#json-output).
|
|
190
|
+
|
|
162
191
|
## Configuration
|
|
163
192
|
|
|
164
193
|
Run `fpl init` to configure interactively. Settings stored in your platform's config directory (override with `FPL_CLI_CONFIG_DIR`, and also home to the optional `previews/` intel files); generated data such as team ratings, chip plans and the league history ledger `league-recap` builds up is stored in your platform's data directory (override with `FPL_CLI_DATA_DIR`). In ephemeral environments (e.g. Claude Code on the web), point both at a persistent workspace. Both overrides must be absolute paths — see [Directories](docs/command-reference.md#directories). Saved reports (`--save`, `--output`) are written to a season subdirectory — `<output_dir>/2026-27/gw21-review.md` — so a new season never overwrites the last one's files; see [Report layout](docs/command-reference.md#report-layout).
|