fix(stream): keep recovery notifications and stop on the dispatcher

The FFmpeg ProcessFailed event arrives off-thread. Start recovery on the UI
dispatcher, publish retry status there, and route StopStream back to the
dispatcher before changing bound state or alert collections. This prevents a
recovery exception from becoming an unhandled WPF CollectionView crash.

AttentionAlertStackTests covers worker-thread recovery reporting and stop.
616 tests green, clean build with 0 warnings.
This commit is contained in:
2026-11-11 09:57:26 -08:00
parent 24077e58cf
commit 9621db29c9
4 changed files with 93 additions and 20 deletions
+10 -4
View File
@@ -1,18 +1,24 @@
# HANDOFF — 2026-11-11 (TASK 37 complete; TASK 69 queued)
# HANDOFF — 2026-11-11 (recovery fixes; creator UI order 1→2→3)
## State
- `main`. App code is pushed through `b265d42`; queue-only docs commits are local.
- `main`; `b265d42` is the latest pushed commit. Step-down audio fix `24077e5` and recovery-dispatcher
fix are local and verified; these fixes are not pushed yet.
- **Done:** TASK 35 scene-linked audio, TASK 55 disk hygiene, TASK 65 replay clips, TASK 37 defaults/current split.
- TASK 37: SQLite keeps an immutable default snapshot beside build-stamped current rows; App Settings can
restore the staged scene or all scenes, offline only. Webcam identity survives both restore paths.
- TASK 14·15 mic input gain was closed by creator test (−2.6 dB, works great); slices 16–18 remain.
- Verification: **615 tests green, clean build with 0 warnings** (`FAST=1 ./scripts/verify.sh`).
- Recovery incident: private test hit step-down on 85% loss; encoder restart reused a broken audio pipe.
Step-down now closes/recreates audio in order; recovery notifications/stops marshal to the dispatcher.
- Verification: **616 tests green, clean build with 0 warnings** (`FAST=1 ./scripts/verify.sh`). Creator test
was stable (~5.1 Mbps, 31 fps, 0.2% drop); its log showed no step-down/reconnect event.
- Steam remains blocked on Valve identity/tax review; no app IDs or store page.
## Next action
- Queue: **40·A/C/D → Move → 9·5 → 14·16/17/18 → 66 → 67 → 68 → 69 → 70 → 36**.
- First: creator-directed **1) global alert placement → 2) sticky click-to-dismiss alerts → 3) core-metric
change cues**, one test/commit each. Then resume **40·A/C/D → Move → 9·5 → 14·16/17/18 → 66 → 67 →
68 → 69 → 70 → 36**.
- Ask creator before TASK 68 about first-run ON-AIR default; before gold pass, settle the Release
single-instance mutex behavior.
- TASK 34 scheduling and TASK 50 recording publish are retired; YouTube owns those surfaces.