From a2530fe97be16ffda9670b0f0bdbc221334d0258 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Thu, 17 Sep 2026 05:02:33 +0100 Subject: [PATCH] spec: instant sounds are session-scoped; listener sleep is acknowledged and queryable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rebased onto dev to drop the already-merged #253 commit so the branch fast-forwards cleanly. Adds CHANGELOG.md entries for AUDIO-IN-1 §6.3 (sleep acknowledgement and query) and AUDIO-1 §4.2 (instant-sound session scope), and states in §6.3 that a repeated ovos.listener.sleep while already asleep still gets the acknowledgement reply. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 21 +++++++++++++++++++++ audio-in.md | 41 ++++++++++++++++++++++++++++++----------- audio-out.md | 17 ++++++++++++----- 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe7a3ec..41cb5c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,14 @@ revision record. ## OVOS-AUDIO-1 — Audio Output Service +### 3 + +- §4.2 — an instant sound carries the §4.1 session scope: the audio + output service MUST only play an instant sound whose + `context.session.session_id` matches a session it is configured to + serve locally. Matches the enqueue rule already in §4.1; no wire + shape changes. + ### 2 - §4.0 (new) — one audio-format rule for all audio payloads: the @@ -505,6 +513,19 @@ version 2: its `{{ … }}` sequences become substitution points, and its ## OVOS-AUDIO-IN-1 — Audio Input Service +### 3 + +- §6.3 — sleep entry is now acknowledged: the audio input service + MUST reply on `ovos.listener.sleep.response` (OVOS-MSG-1 §5.3 + `response` derivation) once sleep mode has been entered. Supersedes + the version-2 entry below, which called sleep entry unacknowledged + by design. §6.3 also adds `ovos.listener.sleep.query`, answered on + `ovos.listener.sleep.query.response` with an `asleep` bool, so a + component can read current sleep state instead of inferring it from + the last-seen lifecycle signal. A repeated `ovos.listener.sleep` + received while already asleep still gets the `.response` + acknowledgement; sleep mode does not change. + ### 2 - §6.4 — `ovos.listener.wake`, the controller's request to leave sleep diff --git a/audio-in.md b/audio-in.md index ebf3ab8..dea9190 100644 --- a/audio-in.md +++ b/audio-in.md @@ -225,10 +225,13 @@ No payload. The session is identified by `context.session.session_id` of this Message. On receipt the audio input service enters sleep mode and suspends -capture until it is awoken (§6.4). Sleep entry is **unacknowledged -by design**: no confirmation Message is emitted on entering sleep. -The only sleep-related emission is `ovos.listener.awoken` on the -sleep→awake transition (§6.4). +capture until it is awoken (§6.4). The audio input service **MUST** +acknowledge the request via the `response` derivation (OVOS-MSG-1 +§5.3) — on `ovos.listener.sleep.response` — once sleep mode has been +entered. The reply carries no payload; it exists so a controller can +confirm sleep took effect rather than assuming it from silence. A +request received while already asleep **MUST** get the same reply; +sleep mode does not change and the request is not an error. **Sleep is device-scoped.** Although the `ovos.listener.sleep` request rides a session like every Message, sleep mode is a @@ -243,13 +246,23 @@ device-scope effect — capture suspended or resumed for every session — is identical no matter which session's identifier the Message carries. -No topic in this specification lets a component query current -listener state (awake, asleep, capturing) on demand. This is a -**deliberate omission**: sleep and record signals (§6.1–§6.4) are -edge-triggered notifications, not a queryable state store. A -deployment that needs to synchronize to current state on connect -(e.g. a bridge attaching mid-session) derives it from the last-seen -lifecycle signal rather than polling for one. +**Sleep state is queryable.** A component MAY query current sleep +state by emitting: + +`ovos.listener.sleep.query` + +Request payload: none. + +The audio input service **MUST** reply via the `response` derivation +(OVOS-MSG-1 §5.3) — on `ovos.listener.sleep.query.response` — with: + +| Field | Type | Required | Meaning | +|-------|------|----------|---------| +| `asleep` | bool | yes | `true` if the device is currently in sleep mode, `false` otherwise. | + +This query is the only queryable listener state this specification +defines; capture activity (§6.1, §6.2) remains an edge-triggered +notification, not a queryable state store. ### 6.4 Wake request and awoken @@ -316,6 +329,9 @@ word (push-to-talk, `ovos.mic.listen`) emit no wake-word signal. | `ovos.listener.record.ended` | audio-input → broadcast | Voice-command capture ended (§6.2). | | `ovos.listener.sleep` | controller → audio-input | Enter device-wide sleep mode and suspend capture (§6.3). | | `ovos.listener.wake` | controller → audio-input | Leave sleep mode and resume capture (§6.4). | +| `ovos.listener.sleep.response` | audio-input → controller | Sleep mode entered (§6.3). | +| `ovos.listener.sleep.query` | any component → audio-input | Query current sleep state (§6.3). | +| `ovos.listener.sleep.query.response` | audio-input → requester | Current sleep state (§6.3). | | `ovos.listener.awoken` | audio-input → broadcast | Left sleep mode (§6.4). | | `ovos.mic.listen` | any component → audio-input | Re-open the user input channel; consumed here, defined in OVOS-AUDIO-1 §4.4. | | `ovos.stt.failed` | audio-input → broadcast | Capture yielded no usable transcription; terminal, no lifecycle follows (§5). | @@ -344,6 +360,9 @@ word (push-to-talk, `ovos.mic.listen`) emit no wake-word signal. sessions while asleep (§6.3); - leave sleep mode on `ovos.listener.wake`, treating a request received while awake as a no-op (§6.4); +- reply to `ovos.listener.sleep` once sleep mode has been entered, + and reply to `ovos.listener.sleep.query` with current sleep state + (§6.3); - emit `ovos.listener.awoken` on the sleep→awake transition (§6.4). ### An audio input service **SHOULD**: diff --git a/audio-out.md b/audio-out.md index 2e5dfaa..72cfa96 100644 --- a/audio-out.md +++ b/audio-out.md @@ -258,10 +258,16 @@ stream (§4.0). ### 4.2 Instant sounds -Instant sounds are played via `ovos.audio.play_sound`. They start -immediately on receipt, play over any audio currently in progress -from the scheduled queue, MAY overlap each other, and are **not** -affected by stop signals (§6). +Instant sounds are played via `ovos.audio.play_sound`. They carry +the session scope defined in §4.1: the audio output service MUST +only play an instant sound whose `context.session.session_id` +matches a session it is configured to serve locally. Playback starts +immediately on receipt, over any audio currently in progress from +the scheduled queue, and instant sounds MAY overlap each other. They +are **not** affected by stop signals (§6): an instant sound is a +short acknowledgement or error cue, and anything longer belongs on +the scheduled queue, where it takes its turn with speech and is +stoppable there. **Play-sound topic** `ovos.audio.play_sound`: @@ -448,7 +454,8 @@ obligation on receiving a stop signal is the sequence above. time in FIFO order (§4.1); - support queued sound playback via `ovos.audio.queue` (§4.1); - play instant sounds immediately on `ovos.audio.play_sound` without - queuing or stopping scheduled playback (§4.2); + queuing or stopping scheduled playback, only for a session it is + configured to serve locally (§4.2); - emit `ovos.audio.output.started` when a playback session begins (§5.1); - emit `ovos.audio.output.ended` when a playback session ends (§5.2);