M1-13: start a recording from a control #38
No reviewers
Labels
No labels
area/agent
area/capture
area/editor
area/geo
area/security
area/sync
area/transcription
area/ui
area/vault
area/voice-memos
blocked
milestone/M1
milestone/M2
milestone/M3
milestone/M4
needs-decision
needs-hardware
p0
p1
p2
type/bug
type/enhancement
type/feature
type/idea
type/infrastructure
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Stash/stash-ios!38
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "m1-13-control-widget"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #19.
A Record control for Control Center, the lock screen and the Action Button. Tapping it brings
Stash forward and starts a memo. Stopping stays on the Live Activity from issue 07, which appears
the moment the recording starts and already shows the elapsed time and the microphone.
The device answered the issue's open question, and it changed the design
The issue asked whether iOS would start a recording from a locked phone. The answer is broader:
an app cannot start audio recording from the background at all. A Control Center tap with the
phone unlocked was refused at
AVAudioSession.setActive(true)— and nothing appeared at the tap,because there was no foreground to show the failure in.
AudioRecordingIntentdoes not change that. It buys execution in the app's process and the systemrecording indicator; it does not buy permission to start a session in the background.
So the control declares itself foreground. What it saves is finding the app, not the unlock. Wes
was given the choice between that and dropping the control, and kept it. The reasoning, including
the rejected alternatives, is in
stash-docs.What the reviews changed
AudioRecordingIntentandLiveActivityIntent. Dropping eithercompiles and produces a control that records nothing, so both are asserted in tests.
AudioRecordingIntentmakes the Live Activity a condition of the recording continuing —Apple stops the audio without one. So it is requested before the file writer exists, and a
refusal fails the start with nothing left behind; and it is watched, so a recording whose activity
is dismissed is finalised rather than left claiming to record.
speech setup is not shown as recorded time.
unlinkrather thanremoveItem, deactivates the audio session, andends transcription. The documents directory is the user's and writable from the Files app.
A microphone anything can start is a bigger surface than a Control Center button asks for.
Validated
make lintclean.make test— 158 passing in 16 suites.make buildandmake runclean.On the device, all eight tests passed: Control Center and lock screen placement, a warm start, a
cold start after force-quitting, a second tap while recording, stop from the Live Activity, the
locked case through Face ID, the Live-Activities-off refusal leaving no memo behind, and swiping the
activity away mid-recording.
Not validated
perform(), theStashApphandler registration, the failed-start cleanup, the activity watcher andthe launch-sweep race have no automated test.
StashTestsis logic only — no engine, noActivityKit, no device — so all five are covered by the device pass alone, and a regression in any
of them would be found by a person rather than by CI.
.woodpecker/build.ymlis still pending for want of a macOS agent. Pending is not green.Known limit, not fixed here
iOS ends a Live Activity after about eight hours, which ends a control-started recording. It ends
cleanly — the memo and transcript are complete — but it ends. Renewing the activity or capping a
recording's length is its own piece of work and worth its own issue.
Decision record:
stash-docs›decisions/2026-08-08-starting-a-recording-from-a-control.md.Plan, four Codex reviews and the dispositions:
.agent/m1-13-control-widget/.