Backend engine for guided LED-chase calibration, driven by the upcoming
auto-calibration UI (phase 3) and first-run wizard (phase 4).
- solve_calibration(): pure function mapping start corner + direction + 4
corner-tap indices to per-edge LED counts, consistent with EDGE_ORDER/
EDGE_REVERSE so it round-trips through build_segments().
- CalibrationChaseMixin.set_calibration_pixel(): light a specific LED index
(+ optional window) on a device, reusing the device_test_mode idle-client
send path.
- CalibrationSession: single-active session with start/position/stop/cancel,
a 60s idle-timeout watchdog, and a concurrency lock so interleaved calls
can't corrupt the stop/restore bookkeeping — start() stops + remembers any
running target on the device and stop/cancel/timeout always restore it
(never leaves the device dark or stuck in chase).
- Routes /api/v1/calibration/{session,session/position,session/stop,
session/cancel,session/state,solve} (all AuthRequired, bounds-validated);
calibration is persisted by reusing the existing PUT /color-strip-sources/
{id} (hot-reloads running streams) rather than a duplicate endpoint.
- Tests: 19 solver pure-logic + 19 route/bounds. docs/API.md updated.
Part of the edge-calibration + first-run-wizard feature (Big Bang; intermediate
phase — full build/suite gated at the final phase).