feat(topbar): REC/ON-AIR pills are radio-exclusive (record-OR-live)

The record-OR-live ruling (2026-09-01) was documented in ai.md but the
'pills = radios' UI constraint never landed — both pills could be armed and
StartSession/BuildEncoderOptions would dual-encode to the YouTube ingest AND
a local file at once, streaming a concurrent disk write off the same ingested
Kbps (cripples the stream on mid-range chassis; 'the VOD is already the copy').
The pill setters now clear one another (silent mutual clear); the dual-block
ffmpeg machinery stays generic and unreachable from the UI by design.
This commit is contained in:
2026-09-20 09:56:07 -07:00
parent 5a1993b6db
commit 94e114bfdf
4 changed files with 91 additions and 9 deletions
+13 -1
View File
@@ -1,4 +1,4 @@
# HANDOFF — 2026-09-20 (cross-table z-order bug fixed: webcam between sources survives reload; defaults/current split queued as TASK 37)
# HANDOFF — 2026-09-20 (cross-table z-order bug fixed; REC/ON-AIR pills now radio-exclusive; defaults/current split queued as TASK 37)
## Branch / Commit State
@@ -36,6 +36,18 @@ shape `scene[0-4].layerList.[default|current].elementList`; config-file vs secon
decided (`TASKS/task-37-defaults-current-split.md` has both + facts). **Process rule established:**
capture out-of-scope needed work in TASKS.md rather than bolting it onto the in-flight change.
## ✅ Committed — REC/ON-AIR pills are radio-exclusive (2026-09-20)
**Gap found:** the record-OR-live ruling (2026-09-01) was documented but the "pills = radios" UI
constraint never landed — the two pills were independent toggles, so a creator COULD arm both and
`StartSession`/`BuildEncoderOptions` would happily dual-encode (RTMP + `-f mp4`) — the exact thing the
ruling forbids (a concurrent disk write streams from the same sustained ingest Kbps and cripples the
stream on mid-range chassis; "the VOD is already the copy"). Fix: mutual clear in both pill setters
(`RecordPillOn`/`OnAirPillOn` in `MainViewModel.Streaming.cs`) — arming one clears the other (silent
mutual clear, creator's choice). The dual-block ffmpeg machinery stays generic/unreachable by design.
Test `PillRadioTests` (RealApp + temp DB): REC→ON-AIR clears REC; ON-AIR→REC clears ON-AIR; single
pill still arms Start. **310/310 pass.**
## ✅ Committed earlier — layer-list drag-to-reorder persists (2026-09-18, `f91bf87` + below)
`StagedScene.Elements` reorder (RemoveAt/Insert) bypasses SceneGraph's mutation surface, so the drop