fix(livestream): don't let the idle-timeout finalizer end an active stream master
The idle-timeout finalizer (processFinalizeLivestreamTask) could set endedAt on the record an actively-streaming user was publishing under, taking the stream pre-live underneath a still-flowing ingest. Root cause: lastSeenAt only advances via the per-segment heartbeat (StreamSession.doUpdateLivestream), which is coupled to segment arrival and can lag behind actual ingestion. A ~60s ingest gap froze lastSeenAt; the 300s idle timer then fired while segments were still flowing, and endedAt was written onto the live record. Guard the finalizer: when lastSeenAt is stale but the record is still the streamer's latest livestream (no newer record supersedes it), reschedule the finalize for one more idle window instead of ending — giving a lagging heartbeat a chance to catch up. If the stream is truly abandoned, the heartbeat stays frozen and the next pass ends it. Superseded records (a newer one exists) are still ended, since they're no longer live. Also fix the related orphaned-finalize-task bug: startLivestream now ends any prior un-ended livestream for the repo before creating the new one, so the prior record's already-scheduled idle-timeout task hits its rec.EndedAt != nil early-skip instead of later writing a stale endedAt onto a replaced record. Verified against the 2026-07-06 production incident: segment manifests showed the stream went pre-live exactly when the idle timer fired on the live record (lastSeenAt frozen at the pre-gap heartbeat, endedAt = lastSeenAt at finalize). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>