The last three unvalidated setters, beside `p_draw`, `score_sigma` and
`convergence`, which all assert eagerly. Measured before choosing bounds:
beta = 0 -> works, pi 0.0211 (vs 0.0193 at the default)
beta = -4.17 -> bit-identical to +4.17
sigma = -8.33 -> bit-identical to +8.33
sigma = 0 -> NonFiniteResult, current_skill returns tau: NaN
sigma = inf -> same
mu = NaN -> same
So the bounds are not the obvious ones. `beta = 0` is legitimate and
meaningful — performance is then exactly skill, and the fit moves
measurably rather than degenerating — so zero is allowed and a test pins
that it reaches a different answer, since "allowed" would otherwise be
indistinguishable from "unchecked".
The negative cases are the quiet ones. `sigma` and `beta` enter inference
only as squares, so a negative value behaves as its absolute value and
the sign is dropped without comment. That is the same defect
`Member::with_drift_scale` already rejects, for the reason already
written there.
The non-finite cases are detected today — `converge` reports
NonFiniteResult — but a caller who reads `current_skill` first is handed
`tau: NaN`, so rejecting at the boundary is what actually closes it.
BREAKING CHANGE: `HistoryBuilder::mu`, `sigma` and `beta` now panic on
values they previously accepted, matching the existing behaviour of
`p_draw`, `score_sigma` and `convergence`.
Refs #18
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hcFjNDmHXZF8URGLku5zZ