require_measured_rates_in_xi has no production caller — the optimiser can start a position-prior-rated player #32

Closed
opened 2026-09-13 14:46:00 +02:00 by solvreven · 1 comment
Owner

Found 2026-09-13 while running the optimiser for a GW7 wildcard.

backend/web/optimize.py defines require_measured_rates_in_xi(xi, by_id) with a docstring explaining why rate priors must be refused in the XI ("an invented rate inside a maximisation objective steers selection toward the players whose numbers were invented"). It is unit-tested in tests/web/test_provenance.py and called by nothing: not by autocomplete, not by _solve, not by /api/autocomplete. The candidate dicts the route builds do not even carry rates_source, so a caller could not apply it.

_require_trusted_pool checks AVAILABILITY provenance only. So a player whose start is trusted but whose xG/xA are the position anchor can be placed in the XI by "Complete my squad".

The pool today contains 0 such players with start_prob >= 0.05, so this does not bite on the current cache — which is exactly why it has stayed invisible.

Suggested direction: carry rates_source into the candidates and constrain the MILP so a prior-rated player can hold a bench slot but never an XI place (y_i = 0), rather than refusing the whole solve after the fact. A wiring test that fails when the route stops passing the field.

**Found 2026-09-13** while running the optimiser for a GW7 wildcard. `backend/web/optimize.py` defines `require_measured_rates_in_xi(xi, by_id)` with a docstring explaining why rate priors must be refused in the XI ("an invented rate inside a maximisation objective steers selection toward the players whose numbers were invented"). It is unit-tested in `tests/web/test_provenance.py` and **called by nothing**: not by `autocomplete`, not by `_solve`, not by `/api/autocomplete`. The candidate dicts the route builds do not even carry `rates_source`, so a caller could not apply it. `_require_trusted_pool` checks AVAILABILITY provenance only. So a player whose start is trusted but whose xG/xA are the position anchor can be placed in the XI by "Complete my squad". The pool today contains 0 such players with start_prob >= 0.05, so this does not bite on the current cache — which is exactly why it has stayed invisible. Suggested direction: carry `rates_source` into the candidates and constrain the MILP so a prior-rated player can hold a bench slot but never an XI place (y_i = 0), rather than refusing the whole solve after the fact. A wiring test that fails when the route stops passing the field.
Collaborator

Fixed in #40, merged into feat/captaincy-board, so it reaches main with #31. The fix follows the suggested direction:

  • _solve bounds a prior-rated candidate's XI variable at zero, so he can hold a bench slot but not an XI place.
  • The route now carries rates_source.
  • autocomplete checks every XI it returns with require_measured_rates_in_xi.

There are three tests, one per connection, and cutting any one connection turns its own test red. Leaving this open until it's on main.

🤖 Generated with Claude Code

Fixed in #40, merged into `feat/captaincy-board`, so it reaches `main` with #31. The fix follows the suggested direction: - `_solve` bounds a prior-rated candidate's XI variable at zero, so he can hold a bench slot but not an XI place. - The route now carries `rates_source`. - `autocomplete` checks every XI it returns with `require_measured_rates_in_xi`. There are three tests, one per connection, and cutting any one connection turns its own test red. Leaving this open until it's on `main`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
solvreven/FPL#32
No description provided.