`log_observation` grew request_id, session_key and session_dir in the middle
of its signature in 6e729ad, and made the trailing three keyword-only.
seed_energy.py still passed six positionals, so every run raised:
TypeError: log_observation() missing 3 required keyword-only arguments:
'prompt_tokens', 'completion_tokens', and 'telemetry'
after making one real, billed completion. TypeError is not a
RequestException, so the per-sample `except` did not catch it and the whole
sweep aborted. llm-router-seed.timer has been failing every six hours since,
spending money and writing nothing.
What that froze: `eco`, and the `energy` figure `routing.within_budget`
enforces objective.max_energy_per_request against. Both silently kept whatever
they had, while /health went on reporting the axis as covered -- the exact
"silent empty axis" failure scoring_coverage() was written to prevent, arriving
through a door it does not watch.
The call now passes those arguments by keyword, and passes `payload["id"]` as
the request_id that positional drift had been dropping. That id is the join key
POST /outcome attributes reports through, so the sweep's own rows were also
unreportable.
--max-tokens is fixed in the same pass, because it was the same class of lie:
argparse parsed it, the banner printed it, and sample_once hardcoded 400. Rows
from `--max-tokens 800` were recorded as ordinary seed_reference samples and
folded into the same median, mixing two workload shapes in the one axis that
exists to hold the workload constant across models.
The test runs main() end to end with sample_once stubbed, rather than asserting
anything about a signature -- this class of drift should be caught wherever it
next appears, not only where it appeared this time.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkcSD2Jzkxo1Kw27ecfXJ
4.8 KiB
4.8 KiB