v3.23.1 — Appetite Starvation, Closed at the Root
Hotfix on v3.23.0. The per-turn loop delivered auto-recalled blocks into the turn's context without emitting fetch credit; the appetite calibrator, fitting that censored telemetry, could adopt an all-zero curve that force-starved retrieval chain-wide while every dashboard stayed green.
Four fixes, one class:
cmd_turnnow emits fetch credit for blocks it delivers into context.- Appetite counts fetched | used — the same consumption credit the retrieval scorer trains on.
- Epoch-aware calibration: the curve fits only on offers recorded since the instrumentation marker exists; mixed censored history is excluded rather than averaged in.
- Degeneracy guard: an all-zero curve is refused at adoption, never silently installed.
- Bonus semantics fix: the curve maps to appetite by ceiling, not rounding — appetite is a cap, not a quota; a bucket mean of 0.25 no longer becomes a permanent per-turn cap of zero.
All five bundles scanned SAFE (4/100, LICENSE EA3 false-positive only); full tests/selftest.py PASS.
🤖 Generated with Claude Code