The gap
There is no audio in the native runtime — neither a primitive nor an API. The native host renders through JavaScriptCore, which has no Web Audio API, so AudioContext is undefined on a native screen.
As with video, enableAudioRecording exists; the gap is playback and synthesis.
What it blocks
HQ.training's Relax studio. resources/functions/relaxation.ts builds its breathwork audio with Web Audio directly:
private context: AudioContext | null = null
…
const Audio = globalThis.AudioContext || (globalThis as any).webkitAudioContext
const context: AudioContext = new Audio()This is not file playback — it is a breath pacer and ambient sound synthesised in the browser. Every breathwork class, the BOLT test and the guided plans depend on it, so /m/relax cannot become a native screen at all while the runtime has no audio.
Two possible shapes, and they are not equivalent
A playback primitive — an Audio node, or a capability that plays a file — would cover ambient sound if we pre-rendered the beds to files. It would not cover the pacer, whose timing is generated.
AudioContext in the native runtime — an implementation of the subset actually used (oscillator, gain, scheduling against the audio clock) backed by AVAudioEngine on iOS and AudioTrack/Oboe on Android — would cover both and would let existing web code run unchanged on a native screen.
The second is the larger piece of work and the one that actually unblocks this screen. I would rather raise it honestly than ask for the smaller thing and discover it does not help.
Worth noting it is not all-or-nothing: scheduling a handful of oscillator and gain nodes against a sample clock is a small fraction of Web Audio, and is most of what a breath pacer needs.