fix: a player on position rate priors can sit on the bench, never start (#32) #40

Merged
kristofferopsahl merged 1 commit from fix/rate-priors-never-start into feat/captaincy-board 2026-09-19 00:26:14 +02:00
Collaborator

Targets feat/captaincy-board (#31), where the optimiser and the autocomplete route currently live. Closes #32 once it reaches main.

require_measured_rates_in_xi stated the rule and was unit-tested, and nothing called it. The autocomplete candidates didn't carry rates_source, and _require_trusted_pool checks availability provenance only. So "Complete my squad" could start a player whose start probability was trusted but whose xG/xA were the position anchor.

Following the issue's suggested direction:

  • _solve fixes a prior-rated candidate's XI variable at zero. He can be bought for the bench but can't start. This is a bound, not an after-the-fact refusal, and it mirrors how an unscored locked pick is already handled.
  • The route passes rates_source into the candidates.
  • autocomplete checks every XI it returns with require_measured_rates_in_xi, which now has a caller. One predicate, _on_rate_priors, serves both the bound and the check.

Tests: tests/web/test_rate_priors_never_start.py has three tests, one per connection. Each was red before the change, and cutting any one connection turns only its own test red:

cut red
route drops rates_source test_the_route_never_starts_…
_solve bound removed test_the_route_…, test_the_solve_bars_him_…
post-check removed test_autocomplete_checks_every_xi_it_returns

A locked prior-rated player is kept in the fifteen, on the bench.

Not changed: scripts/backtest_app_vs_entry.py also calls autocomplete. Its candidates carry no rates_source, so it solves exactly as before.

  • [test] suite on this branch: 1551 passed, 96 skipped, the branch's 1548 plus these 3.

🤖 Generated with Claude Code

Targets `feat/captaincy-board` (#31), where the optimiser and the autocomplete route currently live. Closes #32 once it reaches `main`. `require_measured_rates_in_xi` stated the rule and was unit-tested, and nothing called it. The autocomplete candidates didn't carry `rates_source`, and `_require_trusted_pool` checks availability provenance only. So "Complete my squad" could start a player whose start probability was trusted but whose xG/xA were the position anchor. **Following the issue's suggested direction:** - `_solve` fixes a prior-rated candidate's XI variable at zero. He can be bought for the bench but can't start. This is a bound, not an after-the-fact refusal, and it mirrors how an unscored locked pick is already handled. - The route passes `rates_source` into the candidates. - `autocomplete` checks every XI it returns with `require_measured_rates_in_xi`, which now has a caller. One predicate, `_on_rate_priors`, serves both the bound and the check. **Tests:** `tests/web/test_rate_priors_never_start.py` has three tests, one per connection. Each was red before the change, and cutting any one connection turns only its own test red: | cut | red | |---|---| | route drops `rates_source` | `test_the_route_never_starts_…` | | `_solve` bound removed | `test_the_route_…`, `test_the_solve_bars_him_…` | | post-check removed | `test_autocomplete_checks_every_xi_it_returns` | A locked prior-rated player is kept in the fifteen, on the bench. **Not changed:** `scripts/backtest_app_vs_entry.py` also calls `autocomplete`. Its candidates carry no `rates_source`, so it solves exactly as before. - `[test]` suite on this branch: **1551 passed, 96 skipped**, the branch's 1548 plus these 3. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix: a player on position rate priors can sit on the bench, never start
All checks were successful
CI / syntax (pull_request) Successful in 9s
CI / tests (pull_request) Successful in 1m13s
CI / wheel (pull_request) Successful in 28s
b3c5534829
#32. require_measured_rates_in_xi stated the rule and was unit-tested,
and nothing called it; the autocomplete candidates did not even carry
rates_source. _require_trusted_pool checks availability provenance
only, so a player with a trusted start and position-anchor xG/xA could
be put in the XI by "Complete my squad".

As the issue proposed, it is a bound rather than a refusal: _solve fixes
a prior-rated candidate's XI variable at zero, so he can be bought for
the bench but cannot start. The route now passes rates_source, and
autocomplete checks every XI it returns with require_measured_rates_in_xi,
which finally has a caller. One predicate, _on_rate_priors, serves both.

Three tests, one per connection; cutting the route field, the bound or
the post-check each turns its own test RED. The issue counted no such
player with start_prob >= 0.05 on 2026-09-13, so squads built from that
cache would not change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kristofferopsahl merged commit 82397abf7a into feat/captaincy-board 2026-09-19 00:26:14 +02:00
kristofferopsahl deleted branch fix/rate-priors-never-start 2026-09-19 00:26:14 +02:00
Sign in to join this conversation.
No description provided.