- Rewrite ghost client tests to call real ChannelStatus and ClientManager code paths instead of reimplementing detection logic in test helpers
- Rewrite initializing state tests to invoke StreamManager.run() so the real finally block executes under test
- Replace hardcoded state list tests with assertions against ChannelState.PRE_ACTIVE frozenset
- Add missing SOURCE_BITRATE and FFMPEG_BITRATE constants to ChannelMetadataField (referenced by channel_status.py but never defined, causing AttributeError on detailed stats)
- Change ChannelState.PRE_ACTIVE from list to frozenset (immutable,
O(1) membership tests, no risk of silent mutation)
- Add optional client_ids parameter to ClientManager.remove_ghost_clients()
so callers that have already fetched SMEMBERS can pass it through,
eliminating a redundant Redis round-trip
- Pass pre-fetched client_ids from get_basic_channel_info() into
remove_ghost_clients() to remove the duplicate SMEMBERS call
- Write ERROR via ownership check OR state guard fallback when ownership TTL expired during retries
- Add INITIALIZING to cleanup task grace period monitoring
- Validate client SET entries against metadata hashes in orphaned channel cleanup; remove ghosts and clean up when no real clients remain
- Stats page self-heals by removing ghost SET entries on read
- Extract remove_ghost_clients() helper to ClientManager
- Add ChannelState.PRE_ACTIVE constant
- Fix 6 pre-existing NonOwnerWorkerKeepalive test failures