Backend:
- client.go: handle the io.ReadAll error on the chat response (retry rather
than misparse a truncated read), and stop logging raw upstream response
bodies (log byte count instead of subtitle/model text).
- srt.go: reject negative/reversed cue time ranges in parseTimingLine.
- translator.go: fail fast on a nil client, non-positive batch size, or empty
target language instead of panicking / looping.
Frontend:
- VideoPlayer: clear the pending translation resume timer when the file
changes, so a stale 30s callback can't fire against the new media.
- useSubtitleTracks: dedup cues on source times, not delay-shifted display
times, so adjusting subtitle delay can't re-add the same cue.
- SubtitleMenu: only show "Translate with AI" when a translatable (non-live,
text/non-bitmap) source exists, matching the modal's filter.
- IntegrationsSettings: validate AI settings before saving (non-empty
endpoint/model when enabled, positive concurrency) instead of persisting an
unusable config.
- realtime-protocol: validate optional label/message fields are strings; add
parser tests for the subtitle_translation_* events.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>