Repository navigation
Record screen decisions live in App code with few tests (refactor) #552
Description
Summary
Most of what the Record screen decides (which alerts show, the status chips, the record block, the Copy summary, what the watch and Live Activity show) is worked out in App code with few tests. Nothing changes on screen; the aim is to move those decisions into the Kit where they can be tested.
Why it matters
The Record screen is what an operator watches during a show, and its alert order and wording are where regressions would hurt most. Today a change there is checked only by eye.
Done when
- Interface agreed with Eric in a grilling session first, done in small stacked PRs.
- A Kit "Record screen state" module takes one snapshot in and gives chips, alerts, the record block, the Copy summary, the watch status and Live Activity content out, with tests through that interface.
-
RecordScreenModelkeeps platform glue only, and the glue left in App/ has tests inAppTests(App test coverage isn't on Codecov yet #679). - Eric's device check on a TestFlight build: the alerts and chips look the same as before through a Take with no Drive and a Mixer Link loss.
Details
Rating: Strong (architecture review of 2026-10-13). Eric (from comment 2026-10-14): do this first, in small stacked PRs, plus an App unit test target for the glue that stays in App/.
Today. RecordScreenModel spans App/RecordScreen.swift:647-1840, about 1,200 lines and 60-odd functions. It runs the polling loop, device listing (availableDevices(), line 1752), route-change filtering, assembles the alerts by hand in raisedAlerts (line 968: arm, idle, record, Destination, Drive rejoin, shortfall, interruption, no signal, routing, power, Copy summary, move report, setup hint, Soundcheck), the chips (chips, line 925), Templates (startShow(from:) 1337 and applyDefaultTemplate 1370), Pro offers and the watch and Live Activity status. It has 14 #if os blocks and 6 UserDefaults sites.
Since the review.
- An
AppTeststarget exists (AppVersionTests,DriveFolderModelTests,MeterGridTests,SupportMailTests); App test coverage isn't on Codecov yet #679 now tracks its coverage on Codecov. - Take control through one seam: the Take sequencer owns every Take action and event (Strong) #551 (Take control through the sequencer) and Mixer session: the Mixer Link offer and connect policy out of the App (Speculative) #556 (Mixer session) are closed and took the Take actions and the Mixer Link policy out of the model.
- Gain on the Mixer: one module for auto-gain, clip protection and the gain log (Worth exploring) #554 (Mixer gain) took auto-gain and clip protection wiring out.
- Copies of a Take: one module keyed by Destination kind (Strong; top recommendation) #550 (Copies of a Take) gave the chips and alerts one Copy model (
TakeCopies).
Direction. A Kit "Record screen state" module: one snapshot of Recorder, sequencer, Drive, Mixer Link, power and License in; chips, alerts, record block, Copy summary, watch status, Live Activity content and announcements out. It would absorb several one-function deciders (RecordAvailability, Soundcheck.shouldOffer, NoSignalAlert) and #553's problem list. Don't propose the interface here; settle it in a grilling session first.
Verified on main 2026-10-21 at 2e43ca8
Activity
Take control, PR 2: the App places Markers and starts and ends Shows …
A stale Mixer Link never moves gain: clip protection, auto-gain and t…
A stale Mixer Link never moves gain: clip protection, auto-gain and t…
Mixer session, PR 2: the App reads the Mixer Link through MixerSessio…
Skeyelab commentedon Oct 14, 2026
Eric (2026-10-14): do this first, in small stacked PRs, and also add an App unit test target that runs on the Mac (see the new issue) for the glue that stays in App/. The App folder has no tests today, so RecordScreenModel's ~1,000 lines are untested.
https://claude.ai/code/session_01K4ihr1i6m1uuUswAENvJKJ
[-]Record screen state: move RecordScreenModel's decisions into a tested Kit module (Strong)[/-][+]Record screen decisions live in App code with few tests (refactor)[/+]Skeyelab commentedon Oct 27, 2026
Triage: ready-for-human
Per "Done when", the interface is agreed with Eric in a grilling session first. After that, this splits into small stacked PRs for an agent.
Skeyelab commentedon Oct 27, 2026
Agent brief (grilling session with Eric, 2026-10-27)
Summary: The Record screen's chips, alerts, record block, Copy summary, watch status, Live Activity problems, header text and VoiceOver announcements come from one tested Kit value, fed a snapshot of plain facts once a second.
Since the issue was written: the single deciders already live in the Kit (status chips, Destination, no-signal and Drive-rejoin alerts, record availability, watch status, swiped alerts, announcements). What is left in the App is the assembly: which alerts are raised and in what order, the screen's memory between seconds, and passing the same facts to each decider.
Eric's decisions:
Behavior that must not change: every alert's wording, tone, priority and order; which alert shows and the count of the rest; when a swiped alert comes back; the green banner's fade; the watch and Live Activity problems; VoiceOver announcing a change once.
Done when:
Out of scope: any change on screen, new alerts, reordering, wording edits, Pro offers, Templates, no-signal detection, the polling loop, Mixer Link or Take control (already moved in #551 and #556).
Timing (Eric): start now; no tag until #963 and these PRs have run on main. Then v1.1.18 is tagged
[internal]for Eric's device Take.The Record screen's alerts and their memory live in a tested Kit value (
Chips, record block, Copy summary, watch status, header text and anno…
AppTests cover the App glue that fills the Record screen snapshot, th…
AppTests cover the App glue that fills the Record screen snapshot, th…
Skeyelab commentedon Oct 27, 2026
All three PRs merged: #978, #979, #980. The only open item is Eric's device check on a TestFlight build (v1.1.18 [internal]): the alerts and chips should look and behave as before through a Take with no Drive and a Mixer Link loss. Close this when that passes.