POST /api/test/run takes an optional iterations count (the PWA's
Iterations field): the run repeats, successful iterations are discarded
(steps/log cleared, only load.done and the timing grow), the first error
stops the loop and keeps that iteration's report, a stop ends it after
the current iteration, and a card session change between iterations is
an error. The SCP80 counter state is shared across iterations, so
packets continue from what the previous run consumed.
The status gains a load block (iteration/done/failed_iteration/
elapsed_ms/avg_ms; disabled for a normal run). The suite runner was
split into a per-iteration body (_test_suite_execute_once) + the
single-run finaliser, and two load workers own the loops.
Review fixes: a raised runner error finalises as error (no stuck
running state), a suite-internal session change is an error, a stopped
member ends the suite loop, the final status keeps a warning from any
iteration, avg_ms covers the attempted iterations, and each suite
iteration's counters_before is read fresh.
1041 Python + 1069 frontend; simple-v475.