Bundle of related fixes addressing QConnect echo handling and shuffle
authority. All four converge on the same architectural principle:
qbz must not invent state when the cloud is the source of truth.
1. Remove should_force_remote_track_restart and its echo-driven reload
The function fired whenever the cloud echoed SetState with
target_position_ms=0 for the same track currently playing. The cloud
re-emits this routinely on secondary field changes (next_track
corrections, queue_item_id refresh) — every echo triggered a
load_remote_track_into_player that interrupted in-progress audio.
Track-change cases continue to load via align_corebridge_queue_cursor
plus ensure_remote_track_loaded.
2. Reject echo seeks in apply_renderer_command_to_corebridge
Authoritative seek-to-zero is only honored when the command targets
a different track, or when local position is already near zero. If
command.current_track matches playback_state.track_id and target<=1s
while local_pos>2s, the seek is treated as echo and skipped. The
prior 2s threshold was insufficient to absorb cloud round-trip during
queue changes.
3. Drop has_loaded_audio gate from should_reload_remote_track
playback_state.track_id is updated by the audio thread only after
engine.append(source) succeeds. During the 1-3s buffer/decode window
of an initial load, has_loaded_audio is false even though loading is
in flight — the prior gate caused ensure_remote_track_loaded to
redundantly re-trigger load on every echo SetState arriving in that
window. This was the residual first-track hiccup.
4. Add load-attempt dedup across V2 play and ensure_remote_track_loaded
New sync_state.last_load_attempt: Option<(track_id, Instant)> with a
5s window. Two write sites:
- play_remote_renderer_track_if_active when active_renderer_is_local
(V2 frontend just dispatched a local play)
- ensure_remote_track_loaded when it triggers its own load
Read site: ensure_remote_track_loaded skips if last attempt for the
same track was within the window. Eliminates redundant loads when an
echo SetState arrives while a local play is still buffering.
5. Defer engine shuffle activation until cloud sends a valid order
The cloud broadcasts shuffle toggles in two stages: first a
QueueUpdated with shuffle_mode=true and shuffle_order=null, then
~400ms later a QueueUpdated with the computed shuffle_order. The
prior code applied set_queue_with_order with shuffle_enabled=true on
the first event, falling through to set_identity_shuffle_order_internal
— qbz inventing a sequence (0,1,2,...) that diverges from the order
the cloud is about to authorize. If the second event was delayed,
dropped, or raced against the first, qbz drifted from peer clients
(the long-standing "doble shuffle" symptom).
Now: effective_shuffle_enabled = shuffle_mode && core_shuffle_order.
is_some(). When the order is absent, the engine stays unshuffled and
waits for the second QueueUpdated. sync_corebridge_remote_shuffle_
projection short-circuits identically. Updated diagnostic log
surfaces remote_shuffle_mode, shuffle_order_present, and engine_
shuffle_enabled separately for future triage.
Tests: removed should_force_remote_track_restart test, simplified
should_reload_remote_track test to reflect the track-id-only contract.
cc