After the chunk-read refactor, the inner _drain coroutine assigns
to last_db_write_ts and last_pct_sample. Without nonlocal, Python
compiles these as locals of _drain, so any READ before the first
assignment raises UnboundLocalError.
In 1.0.0-55 / -57 the bug was hidden by gather(return_exceptions=
True), which silently swallowed the exception — the drain coroutine
ended immediately, the asyncssh channel buffer filled up, and the
remote badblocks blocked on pipe_write. THAT was the actual cause
of the "parser silently never works" symptom, not anything to do
with the chunk-read or tr-pipe logic itself.
1.0.0-57 dropped the gather (single drain after merging 2>&1), which
made the next deploy surface the bug as an explicit error_text on
the surface_validate stage: "cannot access local variable
'last_db_write_ts' where it is not associated with a value".
Fix: add both vars to the nonlocal declaration. pending_log_chunks
only gets .append/.clear (no reassignment) so it doesn't need
nonlocal.
This is the bug that's been hiding behind all the recent parser
work. Sorry for the round trips.