The update popup kept the last 64 KiB of raw bytes and decoded the
whole buffer on every refresh. Cutting the buffer, or reading a chunk
that ended inside a multi-byte sequence, made the UTF-8 decode fail and
sent everything through the GB18030 fallback, garbling the display.
Clip the retained tail at a UTF-8 boundary and decode still-growing
streams with an incremental decoder that holds back an incomplete
trailing sequence instead of treating it as corruption.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>