From dfa84ee7bb7d66b6662c689fa1af441ba163e76b Mon Sep 17 00:00:00 2001 From: EdisonJwa Date: Fri, 15 May 2026 22:46:51 +0800 Subject: [PATCH] =?UTF-8?q?docs(spec):=20baseline=200.9.5=20=E2=80=94=20v1?= =?UTF-8?q?=20audio=20+=20PTT=20lifecycle=20redesign?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add SysRS-303/304, SysDes-149/150/151, SRS-204/205/206/207, SAD-081/082/083, SDD-094/095/096/097, DEC-029/030. Captures the v1 lifecycle redesign: - Drop manual Start-audio button; audio engine is bound to voice-channel join/leave (ensure_running on first join, shutdown_if_idle on last leave). Output stream opens regardless of mic-permission state so listen-only is a first-class flow. - TransmitMode enum (Ptt / Continuous / VoiceActivity-reserved). Default Ptt on fresh install. Persisted per identity. - PTT release tail: 200 ms default (0-500 ms configurable) before transmit gate closes, avoiding clipped trailing syllables. - Hard-mute toggle overrides transmit gate regardless of mode/PTT. - Bridge surface: drop start_audio/stop_audio; add voice_join(channel_id) / voice_leave() and BridgeEvent::VoiceState. DEC-029 rejects Flutter global-hotkey packages (hotkey_manager, super_hot_key) for PTT: they wrap RegisterHotKey/RegisterEventHotKey which consume the key and don't fire key-up, wrong primitive for PTT. Native Rust DesktopPttBackend (SDD-083/084/085) stays authoritative. DEC-030 defers Voice Activity Detection to P1. RMS / WebRTC VAD / Silero VAD trade-off review (binary-size, dependency-surface, CPU profile) postponed; TransmitMode::VoiceActivity reserved on the enum surface so a P1 increment is non-breaking. Validator clean: 304/151/207/83/97 IDs, strict layered sourcing preserved, no new warnings beyond the pre-existing 35 old-package-name filenames. --- docs/architecture/desktop-ptt-architecture.md | 14 ++++++ docs/architecture/sad.md | 35 ++++++++++++++ docs/architecture/sdd.md | 44 ++++++++++++++++++ docs/architecture/sysdes.md | 46 ++++++++++++++++++- docs/governance/document-index.md | 3 +- docs/governance/product-decision-register.md | 7 +++ docs/governance/traceability-matrix.md | 24 ++++++++++ docs/requirements/srs.md | 44 ++++++++++++++++++ docs/requirements/sysrs.md | 17 +++++++ 9 files changed, 232 insertions(+), 2 deletions(-) diff --git a/docs/architecture/desktop-ptt-architecture.md b/docs/architecture/desktop-ptt-architecture.md index 35e7de9..9c29102 100644 --- a/docs/architecture/desktop-ptt-architecture.md +++ b/docs/architecture/desktop-ptt-architecture.md @@ -197,3 +197,17 @@ SysDes-142..148 -> SYS4-SIV-016 |---|---|---| | 0.9.3 | 2026-05-15 | Initial baseline-candidate architecture for capability-based desktop Push-to-Talk. Codifies the owner rulings for PTT-OPEN-001 through PTT-OPEN-006 as DEC-023 through DEC-028. | | 0.9.4 | 2026-05-15 | Promoted the Linux GNOME-Wayland backend from probe-only to the live `CreateSession` + `BindShortcuts` + `Activated` / `Deactivated` session flow. Owns an async tokio task with a dedicated `zbus::Connection`; publishes descriptor transitions through a `watch::Sender` consumed by `chanora_core::ChanoraSession::start_audio`. Adds the privacy-safe `trigger_description` classifier and the cancellation / failure path (downgrade to `L0Focused` + re-emit). Updates the Flutter UI to skip the in-app capture dialog on the portal backend (Q3a) and surface a SnackBar redirecting the user to the desktop's own dialog. | + +## 8. v0.9.5 lifecycle and mode-picker addendum + +This addendum captures the v1 audio + PTT lifecycle refactor recorded in SysRS-303..304, SysDes-149..151, SRS-204..207, SAD-081..083, and SDD-094..097. It does not change the desktop PTT backend design captured in §1–§7; it constrains how the backends are owned and how the rest of the audio path is exposed to the UI. + +1. **No "Start audio" button anywhere.** The audio engine lifecycle is bound to voice-channel membership. Input and output streams open on the user's first voice-channel join of the session and close on the last voice-channel leave. The bridge surface drops `start_audio` / `stop_audio` and exposes `voice_join(channel_id) -> Result<(), VoiceError>` and `voice_leave() -> Result<(), VoiceError>`; `AudioEngine::ensure_running()` is invoked implicitly by `voice_join` and is idempotent. The Voice Bar renders from `BridgeEvent::VoiceState { in_channel, transmit_mode, mute, release_tail_ms }` and contains no manual-start affordance. Microphone permission is requested at app first launch rather than at first channel join; the output stream opens regardless of permission state, so listen-only is a first-class flow. +2. **Transmit modes for v1 are `Ptt` and `Continuous`; `VoiceActivity` is reserved but not implemented.** `TransmitMode` is a `#[repr(u8)]` enum mirrored across the bridge; the default on fresh install is `Ptt`; the setting is persisted per identity in the identity store. The settings page renders `VoiceActivity` as a disabled "coming soon" radio row until DEC-030 is resolved and a VAD backend is allocated. +3. **200 ms PTT release tail (configurable 0–500 ms).** A `ReleaseTailTimer` tokio adapter sits between the `DesktopPttBackend` `transmit` signal and `AudioTransmitGate::set()`. Key-down forwards `true` immediately; key-up starts a sleep of `release_tail_ms` (default 200, matching the TeamSpeak / Mumble default) before the gate closes; a key-down within the sleep window cancels the pending close. The tail affects only `transmit_active`; `capture_active` is unaffected. The adapter is independent of the missed-key-up watchdog (SAD-079 / SDD-092). +4. **Hard-mute overrides everything.** The Voice Bar hard-mute toggle is applied by the `TransmitModeSelector` as a final clamp on `transmit_active` and takes precedence over the active transmit mode, the PTT key state, and every other internal signal. Hard-mute is in-session only and resets on the next voice-channel join. +5. **Cross-references.** **DEC-029** locks the v1 PTT capture path to the native Rust `DesktopPttBackend` trait + per-OS implementations (SDD-083 / SDD-084 / SDD-085) and rejects Flutter global-hotkey packages such as `hotkey_manager` and `super_hot_key`, which wrap the OS `RegisterHotKey` semantics, consume the key, drop key-up events, and skip mouse side-buttons. **DEC-030** defers Voice Activity Detection to P1 pending a backend trade-off review (RMS vs WebRTC VAD vs Silero VAD); the enum surface is preserved so a P1 increment is non-breaking. + +| Version | Date | Description | +|---|---|---| +| 0.9.5 | 2026-05-15 | Added the v0.9.5 lifecycle and mode-picker addendum capturing the no-manual-start audio engine bound to voice-channel membership, the v1 transmit-mode set (`Ptt` default + `Continuous`, with `VoiceActivity` reserved per DEC-030), the 200 ms (0–500 ms) PTT release tail, and the hard-mute override. Cross-references DEC-029 (native PTT backend locked) and DEC-030 (VAD deferred to P1). | diff --git a/docs/architecture/sad.md b/docs/architecture/sad.md index 9f52d84..4f80854 100644 --- a/docs/architecture/sad.md +++ b/docs/architecture/sad.md @@ -1364,6 +1364,33 @@ Communication evidence is maintained through change history and baseline approva - Source SRS: SRS-200 - Verification method: Unit Test, Platform Test, UI Review +**SAD-081**: The software architecture shall remove the `start_audio` and `stop_audio` bridge calls from the public bridge surface and shall replace them with `voice_join(channel_id) -> Result<(), VoiceError>` and `voice_leave() -> Result<(), VoiceError>`. The audio engine's `ensure_running()` private method shall be invoked from the `voice_join` handler on first call of the session and shall be idempotent; the `voice_leave` handler shall call a private `shutdown_if_idle()` that closes the input and output streams when no voice channels remain. The Voice Bar UI shall not surface any manual-start affordance and shall instead key off the bridge event stream `BridgeEvent::VoiceState { in_channel, transmit_mode, mute, release_tail_ms }`, which the audio subsystem publishes on every lifecycle transition. + +- Status: Baseline Candidate +- Type: Software Architecture Item +- Stage: P0 / MVP +- Allocated to: Audio, Bridge, Flutter UI +- Source SRS: SRS-204 +- Verification method: Integration Test, UI Review + +**SAD-082**: The software architecture shall add a `ReleaseTailTimer` element to the audio subsystem, owned by the `PttController` and acting as an adapter between the `DesktopPttBackend` `transmit` signal and the `AudioTransmitGate::set()` call. On key-down the adapter forwards `true` immediately; on key-up the adapter starts a tokio sleep of `release_tail_ms` (default 200, configurable 0–500); a key-down within the sleep window cancels the pending close; a timer expiration calls `AudioTransmitGate::set(false)`. The adapter is independent of the missed-key-up watchdog defined in SAD-079 and does not interact with `capture_active`. + +- Status: Baseline Candidate +- Type: Software Architecture Item +- Stage: P0 / MVP +- Allocated to: Audio +- Source SRS: SRS-206 +- Verification method: Unit Test, Integration Test + +**SAD-083**: The software architecture shall add a `TransmitModeSelector` element owned by the audio engine that consults the current `TransmitMode` from the identity store on every state evaluation. In `Ptt` mode the selector defers to the `PttController` + `ReleaseTailTimer` pipeline; in `Continuous` mode the selector sets `transmit_active = !mute` while `in_channel` is true and clears `transmit_active` otherwise; in `VoiceActivity` mode (placeholder per DEC-030) the selector shall behave identically to `Continuous` until a VAD implementation is allocated in a later baseline. The selector shall be the only writer of `transmit_active` other than the missed-key-up watchdog defined in SAD-079, and the hard-mute toggle defined in SRS-207 shall be applied by the selector as a final clamp on the output value. + +- Status: Baseline Candidate +- Type: Software Architecture Item +- Stage: P0 / MVP +- Allocated to: Audio +- Source SRS: SRS-205, SRS-207 +- Verification method: Unit Test, Integration Test + ## 27. Updated SRS-to-SAD Coverage Matrix | SRS Range | SAD Coverage | @@ -1372,6 +1399,7 @@ Communication evidence is maintained through change history and baseline approva | SRS-185 through SRS-194 | Covered by `SAD-061` through `SAD-070` | | SRS-195 through SRS-199, SRS-201 through SRS-203 | Covered by `SAD-071` through `SAD-079` | | SRS-200 | Covered by `SAD-080` | +| SRS-204 through SRS-207 | Covered by `SAD-081` through `SAD-083` | ## Baseline Candidate 0.9.1 Update @@ -1400,3 +1428,10 @@ Communication evidence is maintained through change history and baseline approva | Version | Date | Description | |---|---|---| | 0.9.4 | 2026-05-15 | Added `SAD-080` to close the SRS-200 coverage gap surfaced by a P0 traceability audit. The earlier baseline matrix folded SRS-200 under the `SRS-195..203 -> SAD-071..079` range without giving it a dedicated SAD item; the new entry restores the strict one-to-many SRS-to-SAD discipline (SRS-200 is now sourced by SAD-080; SAD-080 is in turn covered by the new SDD-093). No other rows mutate; the existing PTT SAD items (071..079) retain their original SRS sources. | + + +## Baseline Candidate 0.9.5 Update + +| Version | Date | Description | +|---|---|---| +| 0.9.5 | 2026-05-15 | Added v1 audio + PTT lifecycle architecture items SAD-081 through SAD-083 sourced from SRS-204..207: dropped the `start_audio` / `stop_audio` bridge calls and replaced them with `voice_join(channel_id)` / `voice_leave()` keyed off implicit engine init plus `BridgeEvent::VoiceState`; added the `ReleaseTailTimer` adapter on the `DesktopPttBackend` → `AudioTransmitGate` path (default 200 ms, range 0–500 ms, key-down within window cancels the pending close); added the `TransmitModeSelector` element as the sole writer of `transmit_active` (other than the SAD-079 watchdog) with hard-mute applied as a final clamp and `VoiceActivity` mapped to `Continuous` until DEC-030 resolves. Strict layered sourcing preserved (`SAD -> SRS` only). | diff --git a/docs/architecture/sdd.md b/docs/architecture/sdd.md index 5bb9352..759e595 100644 --- a/docs/architecture/sdd.md +++ b/docs/architecture/sdd.md @@ -1122,6 +1122,42 @@ The registry supports consistency between architecture, detailed design, impleme - Source SAD: SAD-080 - Verification method: Unit Test, Platform Test (Windows / macOS / Linux), UI Review +**SDD-094**: `chanora_bridge::voice::voice_join(channel_id: ChannelId) -> Result<(), VoiceError>` and `chanora_bridge::voice::voice_leave() -> Result<(), VoiceError>` shall be the only public-bridge voice lifecycle calls. Internally `chanora_audio::engine::AudioEngine::ensure_running()` shall be idempotent and shall open the cpal input and output streams on the first call of the session; `chanora_audio::engine::AudioEngine::shutdown_if_idle()` shall be called from `voice_leave` and shall close both streams when no voice channels remain. The Flutter widget tree shall subscribe to `BridgeEvent::VoiceState { in_channel, transmit_mode, mute, release_tail_ms }` through the existing FRB stream and shall render the Voice Bar from that stream. The pre-existing `start_audio` and `stop_audio` FRB symbols shall be deleted from `crates/chanora_bridge/src/api.rs` together with their generated bindings; the corresponding caller in `apps/chanora_flutter/lib/main.dart` shall be removed. + +- Status: Draft +- Type: Software Detailed Design Item +- Stage: P0 / MVP +- Software unit: `chanora_bridge::voice`, `chanora_audio::engine::AudioEngine`, `BridgeEvent::VoiceState`, `apps/chanora_flutter/lib/main.dart` +- Source SAD: SAD-081 +- Verification method: Integration Test, UI Review + +**SDD-095**: `chanora_audio::TransmitMode` shall be a `#[repr(u8)]` Rust enum with variants `Ptt = 0`, `Continuous = 1`, `VoiceActivity = 2`. Persistence shall be provided by `chanora_storage::IdentityStore::set_transmit_mode(&self, mode: TransmitMode)` and `chanora_storage::IdentityStore::get_transmit_mode(&self) -> TransmitMode`, the latter returning `TransmitMode::Ptt` on first read for a fresh install. The bridge surface shall carry the enum across the FFI boundary via `mirror` codegen as `BridgeTransmitMode`. The Flutter settings page in `apps/chanora_flutter/lib/widgets/voice_settings.dart` shall render three radio rows; the `VoiceActivity` row shall be rendered with `enabled: false` and a "Coming soon" trailing label until DEC-030 is resolved and an implementation is allocated. + +- Status: Draft +- Type: Software Detailed Design Item +- Stage: P0 / MVP +- Software unit: `chanora_audio::TransmitMode`, `chanora_storage::IdentityStore::{set_transmit_mode, get_transmit_mode}`, `BridgeTransmitMode`, `apps/chanora_flutter/lib/widgets/voice_settings.dart` +- Source SAD: SAD-083 +- Verification method: Unit Test, UI Review + +**SDD-096**: `chanora_audio::release_tail::ReleaseTailTimer` shall be a tokio-task-owning struct exposing `arm(&self, gate: AudioTransmitGate, tail_ms: u32)`, `key_down(&self)`, `key_up(&self)`, and `cancel(&self)`. Internally the struct shall hold a `tokio::sync::watch::Sender` plus a `JoinHandle<()>` for the pending close. `key_down` shall abort any pending close handle and shall set `transmit_active = true` via the gate; `key_up` shall abort the prior close handle and shall spawn a new task that sleeps for `tail_ms` milliseconds and then sets `transmit_active = false`. The struct shall use no `unsafe`, no mutex, and shall rely only on atomic refcounts on the watch handle. The configuration value `release_tail_ms` shall live in the identity store next to `transmit_mode`, with a default of 200 and validated range 0–500 inclusive on every write. + +- Status: Draft +- Type: Software Detailed Design Item +- Stage: P0 / MVP +- Software unit: `chanora_audio::release_tail::ReleaseTailTimer`, `chanora_storage::IdentityStore` (`release_tail_ms`) +- Source SAD: SAD-082 +- Verification method: Unit Test, Integration Test + +**SDD-097**: `apps/chanora_flutter/lib/widgets/voice_bar.dart` shall replace the existing `_AudioControls` widget in `apps/chanora_flutter/lib/main.dart` as the rendering surface for voice state. Its input shall be the `BridgeEvent::VoiceState` stream; its children, in render order, shall be: the channel-name pill (visible only when `in_channel` is true); the mode badge (`PTT: ` / `Continuous` / `Voice activity (coming soon)`); the hard-mute toggle button; the release-tail and threshold disclosure; the level meter; and the PTT capability badge already specified in SDD-091. The "Start audio" button shall be removed from the widget tree. The settings dialog in `apps/chanora_flutter/lib/widgets/voice_settings.dart` shall render the `TransmitMode` radio group, the bind-key button, and a release-tail slider over the range 0–500 ms with step 25 ms; the dialog shall never expose a "Start audio" affordance. + +- Status: Draft +- Type: Software Detailed Design Item +- Stage: P0 / MVP +- Software unit: `apps/chanora_flutter/lib/widgets/voice_bar.dart`, `apps/chanora_flutter/lib/widgets/voice_settings.dart`, `apps/chanora_flutter/lib/main.dart` +- Source SAD: SAD-081, SAD-083 +- Verification method: UI Review, Widget Test + ## 11. Updated SAD-to-SDD Coverage Matrix | SAD Range | SDD Coverage | @@ -1130,6 +1166,7 @@ The registry supports consistency between architecture, detailed design, impleme | SAD-061 through SAD-070 | Covered by `SDD-071` through `SDD-080` | | SAD-071 through SAD-079 | Covered by `SDD-081` through `SDD-092` | | SAD-080 | Covered by `SDD-093` | +| SAD-081 through SAD-083 | Covered by `SDD-094` through `SDD-097` | ## Baseline Candidate 0.9.1 Update @@ -1158,3 +1195,10 @@ The registry supports consistency between architecture, detailed design, impleme | Version | Date | Description | |---|---|---| | 0.9.4 | 2026-05-15 | Added `SDD-093` covering `SAD-080`. `SDD-093` fixes the `PttInputClass` enum surface, the cross-backend rebind contract for `MouseSideButton`, and the Flutter side-button capture path against the `PointerEvent.buttons` bitmask. Strict layered sourcing preserved (`SDD -> SAD` only). | + + +## Baseline Candidate 0.9.5 Update + +| Version | Date | Description | +|---|---|---| +| 0.9.5 | 2026-05-15 | Added v1 audio + PTT lifecycle detailed design SDD-094 through SDD-097 sourced from SAD-081..083: bridge surface drops `start_audio` / `stop_audio` and exposes `chanora_bridge::voice::voice_join` / `voice_leave` with idempotent `AudioEngine::ensure_running` and `shutdown_if_idle`, `chanora_audio::TransmitMode` as `#[repr(u8)]` enum persisted via `chanora_storage::IdentityStore::{set,get}_transmit_mode` and mirrored across FRB as `BridgeTransmitMode`, `chanora_audio::release_tail::ReleaseTailTimer` as a tokio-task-owning adapter on the watch handle (no `unsafe`, no mutex; configurable 0–500 ms via `release_tail_ms`), and the new `apps/chanora_flutter/lib/widgets/voice_bar.dart` + `voice_settings.dart` surfaces replacing the legacy `_AudioControls` widget. Strict layered sourcing preserved (`SDD -> SAD` only). | diff --git a/docs/architecture/sysdes.md b/docs/architecture/sysdes.md index 1a9d49a..df6a32d 100644 --- a/docs/architecture/sysdes.md +++ b/docs/architecture/sysdes.md @@ -2852,15 +2852,52 @@ This SysDes version covers all known SysRS requirements from `SysRS-001` through - ASPICE SYS.3 alignment: Architecture constraints - Allocated SysRS: SysRS-298 +**SysDes-149**: The system architecture shall define a `TransmitMode` element carried as an enum at the audio + bridge + UI boundary with variants `Ptt`, `Continuous`, and a reserved `VoiceActivity` placeholder that has no allocated implementation in this baseline (deferred per DEC-030). The active mode shall be persisted in the identity store; the UI shall surface `VoiceActivity` as a disabled "coming soon" option until an implementation is allocated in a later baseline. + +- Status: Baseline Candidate +- Type: Subsystem Interface +- Stage: P0 / MVP +- Allocated to: Audio Engine, Bridge, Flutter UI +- Downstream artifact: SRS, SAD, SDD, Verification +- Verification method: Unit Test, UI Review +- Verification owner: Audio Owner + UX Owner +- ASPICE SYS.3 alignment: Element behaviour, interface definition +- Allocated SysRS: SysRS-303 + +**SysDes-150**: The audio engine lifecycle shall be allocated to voice-channel membership: the input and output streams shall open on the user's first voice-channel join of the session and shall close on the last voice-channel leave. The output-stream open shall be independent of the microphone-permission state so listen-only remains a first-class flow. No manual start affordance shall be exposed at any system interface (bridge, UI, or otherwise). A user-facing hard-mute element shall force the transmit gate closed and shall take precedence over the active transmit mode, the PTT key state, and every other internal signal. + +- Status: Baseline Candidate +- Type: Lifecycle Allocation +- Stage: P0 / MVP +- Allocated to: Audio Engine, Bridge, Flutter UI +- Downstream artifact: SRS, SAD, SDD, Verification +- Verification method: Integration Test, UI Review +- Verification owner: Audio Owner + Software Architect +- ASPICE SYS.3 alignment: Element behaviour, lifecycle +- Allocated SysRS: SysRS-303 + +**SysDes-151**: A release-tail element shall be allocated to the audio subsystem as a system-level timer adapter on the `transmit_active` atomic defined in SysDes-144, parameterised by a configurable release-tail period (default 200 ms; user-configurable range 0–500 ms). When the PTT backend signals key-up, the adapter shall delay the `true → false` transition of `transmit_active` by the configured period; the adapter shall not affect `capture_active`. + +- Status: Baseline Candidate +- Type: Subsystem Element +- Stage: P0 / MVP +- Allocated to: Audio Engine +- Downstream artifact: SRS, SAD, SDD, Verification +- Verification method: Unit Test, Integration Test +- Verification owner: Audio Owner +- ASPICE SYS.3 alignment: Element behaviour +- Allocated SysRS: SysRS-304 + ## 17. Updated SysRS Coverage Statement -This SysDes version covers all known SysRS requirements from `SysRS-001` through `SysRS-302`. +This SysDes version covers all known SysRS requirements from `SysRS-001` through `SysRS-304`. | SysRS Range | SysDes Coverage | |---|---| | SysRS-001 through SysRS-285 | Covered by inherited SysDes baseline `SysDes-001` through `SysDes-132` | | SysRS-286 through SysRS-295 | Covered by `SysDes-133` through `SysDes-141` | | SysRS-296 through SysRS-302 | Covered by `SysDes-142` through `SysDes-148` | +| SysRS-303 through SysRS-304 | Covered by `SysDes-149` through `SysDes-151` | ## Baseline Candidate 0.9.1 Update @@ -2882,3 +2919,10 @@ This SysDes version covers all known SysRS requirements from `SysRS-001` through | Version | Date | Description | |---|---|---| | 0.9.3 | 2026-05-15 | Added desktop PTT subsystem allocation SysDes-142 through SysDes-148: Platform PTT Backend layer, typed `PttCapabilityLevel` cross-interface, audio-pipeline split into `capture_active` and `transmit_active`, per-OS backend allocation (Windows Raw-Input ladder, macOS permission-aware, Linux GNOME-Wayland portal), diagnostics sanitizer for raw key events, UI capability badge, release-record evidence requirement. | + + +## Baseline Candidate 0.9.5 Update + +| Version | Date | Description | +|---|---|---| +| 0.9.5 | 2026-05-15 | Added v1 audio + PTT lifecycle allocation SysDes-149 through SysDes-151 sourced from SysRS-303 / SysRS-304: `TransmitMode` enum element (`Ptt` / `Continuous` / reserved `VoiceActivity` per DEC-030) at the audio + bridge + UI boundary, audio engine lifecycle bound to voice-channel membership with no manual start affordance and a listen-only path independent of mic permission, hard-mute override element, and the release-tail timer adapter (default 200 ms, range 0–500 ms) on `transmit_active`. Strict layered sourcing preserved (`SysDes -> SysRS` only). | diff --git a/docs/governance/document-index.md b/docs/governance/document-index.md index d2676a5..62e4510 100644 --- a/docs/governance/document-index.md +++ b/docs/governance/document-index.md @@ -1,7 +1,7 @@ # Document Index **Document type:** Configuration / Documentation Control -**Version:** 0.9.2 +**Version:** 0.9.5 **Status:** Baseline Candidate **Language:** English **Product:** Chanora @@ -86,3 +86,4 @@ SysDes -> SYS.4 |---|---|---| | 0.9.2 | 2026-05-14 | Converted documentation package to repository-oriented docs folder structure and updated internal filename references. | | 0.9.3 | 2026-05-15 | Added `docs/architecture/desktop-ptt-architecture.md` to the controlled document set. | +| 0.9.5 | 2026-05-15 | Bumped controlled-set version to 0.9.5 for the v1 audio + PTT lifecycle refactor: SysRS-303..304, SysDes-149..151, SRS-204..207, SAD-081..083, SDD-094..097, and two new governance decisions DEC-029 (Flutter global-hotkey packages rejected for PTT) and DEC-030 (Voice Activity Detection deferred to P1). No controlled files added or removed; existing files updated in place under strict layered sourcing. | diff --git a/docs/governance/product-decision-register.md b/docs/governance/product-decision-register.md index d6f0fb3..a1914dd 100644 --- a/docs/governance/product-decision-register.md +++ b/docs/governance/product-decision-register.md @@ -58,6 +58,8 @@ A decision marked **Proposed / Owner Confirmation Required** is a recommended de | DEC-026 | Mouse side-button support in first desktop PTT release | **Supported on Windows and macOS; Linux follows whatever the GlobalShortcuts portal exposes.** Resolves PTT-OPEN-004. The Raw Input backend (Windows) and the Event Tap backend (macOS) shall accept Mouse4 / Mouse5 bindings; the Linux portal binding accepts whatever the session exposes and the release notes shall not over-claim. | Accepted | Product Owner + UX Owner | Common dedicated PTT input class; shipping in MVP avoids a follow-up. | | DEC-027 | PTT diagnostics privacy posture | **Capability and availability state only — no raw key codes ever leave the device.** Resolves PTT-OPEN-005. The diagnostic export shall name only `PttCapabilityLevel`, `backend_id`, `bound_input_class`, and `fallback_exercised`; the user's actual key value (scan code, virtual key, keysym) shall never be logged, persisted, or exported. `PttSanitizer` enforces this at write time. | Accepted | Security Reviewer + Privacy Reviewer | Closes a clear privacy risk that the gen2 review flagged; aligns with DEC-016. | | DEC-028 | Missed-key-up watchdog requirement | **P0.** Resolves PTT-OPEN-006. The audio engine shall include a missed-key-up watchdog that clears `transmit_active` after a configured ceiling (default 30 s) when no key-up event arrives. The watchdog is a P0 release-gate item rather than an implementation-level concern because the failure mode (stuck transmission after the user has released the binding) is user-visible and reputation-relevant. | Accepted | Audio Owner + Software Architect | Prevents stuck-PTT bug class regardless of platform-input quirks. | +| DEC-029 | Flutter global-hotkey packages rejected for PTT | **Use the native Rust `DesktopPttBackend` trait + per-OS implementations (already specified in SDD-083 / SDD-084 / SDD-085); do not adopt `hotkey_manager`, `super_hot_key`, or any equivalent pub.dev package for PTT.** Rationale: those packages wrap the OS `RegisterHotKey` / `RegisterEventHotKey` semantics — they consume the key (suppressing it from other applications), they do not deliver a key-up event, and they do not support mouse side-buttons. PTT requires the opposite primitive (observe, do not consume, deliver both up and down). | Accepted | Software Architect + Audio Owner | Locks the v1 PTT capture path to the native backend; removes ambiguity for future maintainers tempted to "simplify" via a Flutter package. | +| DEC-030 | Voice activity detection deferred to P1 | **`TransmitMode::VoiceActivity` ships as a reserved enum variant with no v1 implementation.** The settings UI shows it as a disabled "coming soon" option. The actual implementation choice is deferred to a future baseline. Rationale: three viable backends were compared (RMS energy threshold — trivial but quality-poor; WebRTC VAD via the `webrtc-vad` crate — frozen-but-stable C++ BSD-3 dep, ~200 KB binary, industry baseline; Silero VAD via ONNX Runtime — best quality but ~8–16 MB binary uplift per platform plus an ONNX-runtime dependency surface). The v1 dependency-surface budget does not have room for the trade-off review required to pick correctly. Choosing too early risks either user-visible quality regression (RMS) or a forced ONNX adoption (Silero) before there is a comparable need for ML inference elsewhere (noise suppression, AEC). | Accepted | Audio Owner + Product Owner | Locks v1 to PTT + Continuous; preserves the enum surface so a P1 increment is non-breaking. | ## 4. Accepted MVP Defaults @@ -106,6 +108,8 @@ two were modified from the original recommendation (marked **MODIFIED**). | Apple App Store SDK gate | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | Diagnostics upload policy | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | Crash reporting | Yes if included | Yes if included | Yes if included | Yes if included | Yes if included | Yes | Yes | +| Flutter hotkey packages rejected for PTT (DEC-029) | No | Yes | Yes | Yes | Yes | Yes | No | +| VAD deferred to P1 (DEC-030) | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ## 6. Decisions That Must Be Confirmed By You @@ -153,6 +157,8 @@ release but is not an open decision: | DEC-026 | Product Owner / UX Owner | Mouse side-button support | Accepted (Windows + macOS; Linux portal-dependent) | 2026-05-15 | Resolves PTT-OPEN-004. | | DEC-027 | Security / Privacy Reviewer | PTT diagnostics privacy posture | Accepted (capability + availability only, no key codes) | 2026-05-15 | Resolves PTT-OPEN-005. | | DEC-028 | Audio Owner / Software Architect | Missed-key-up watchdog | Accepted (P0) | 2026-05-15 | Resolves PTT-OPEN-006. | +| DEC-029 | Software Architect / Audio Owner | Flutter global-hotkey packages rejected for PTT | Accepted | 2026-05-15 | Native `DesktopPttBackend` is the v1 PTT capture path; pub.dev hotkey packages consume the key, drop key-up events, and skip mouse side-buttons. | +| DEC-030 | Audio Owner / Product Owner | Voice activity detection deferred to P1 | Accepted (deferred to P1) | 2026-05-15 | `TransmitMode::VoiceActivity` reserved on the enum surface; UI shows "coming soon"; backend choice (RMS / WebRTC / Silero) deferred for dependency-surface review. | ## 8. Change History @@ -211,3 +217,4 @@ release but is not an open decision: | 0.9.8 | 2026-05-15 | DEC-001 release-sequence progress recorded for the polished Internal Beta and the External Beta milestones, plus the first MVP-public release candidate. **`v0.3.0-beta.1`** ("Internal Beta polish") added the supervisor + reconnect-with-watchdog path (A.6), OS-connectivity-aware backoff (A.6.1), persistent identity at rest as a plain 0600 file (A.2), the redacted in-memory log sink + user-initiated diagnostic export per DEC-016 (A.3), the `SnapshotChanged` lifecycle event for UI auto-refresh (A.4), and the `mobile_voice_preset` config-surface plumb-through (A.5). **`v0.4.0-beta.2`** ("External Beta") added the server-password input, channel join via tap, self mute (input + output), master output gain, SQLite-backed bookmark list, ChaCha20-Poly1305 encryption of the identity at rest with the DEK in a separate `identity.dek` file, Android `AudioManager.setMode(MODE_IN_COMMUNICATION)` routing engagement via JNI, and the `.github/workflows/ci.yml` pipeline. **`v1.0.0-rc.1`** ("MVP Public release candidate") closes the v0.4 DEK-on-disk weakness on every keyring-reachable platform: `chanora_storage::IdentityFileStore` now stores the DEK in the OS keyring (Linux Secret Service via D-Bus / macOS Keychain / Windows Credential Manager / iOS Keychain via the `keyring` crate) and migrates pre-existing file-fallback installs into the keyring opportunistically; bookmark server passwords are ChaCha20-Poly1305-encrypted under the same per-install DEK and the legacy plain `password TEXT` column is upgraded into a new `password_blob BLOB` column on the next `update()`; `SessionEvent::SnapshotChanged` now fires on any tree mutation (the in-channel-move blind spot from A.4 is closed); the in-app About dialog surfaces DEC-018 / DEC-019 / DEC-020. New `docs/governance/legal-review-readiness.md` carries the DEC-012 handoff package (trademark check, non-affiliation wording, third-party license posture, `cargo about` deliverables, `cargo deny` lifelines); new `docs/governance/staged-release-plan.md` enumerates the DEC-002 platform staging (Linux + Android sideload GA on DEC-012 sign-off; Windows, macOS, iOS gate on per-platform signed-build availability). No decision rows change; DEC-012 remains the sole outstanding release gate. | | 0.9.9 | 2026-05-15 | Recorded six new accepted decisions DEC-023 through DEC-028 closing the gen2 desktop-PTT review's open questions PTT-OPEN-001 through PTT-OPEN-006: Windows Global PTT is P0/MVP (DEC-023), macOS Global PTT is P0/MVP with permission UX (DEC-024), the officially-tested Linux environment is GNOME-on-Wayland only (DEC-025), mouse side buttons are supported on Windows + macOS and Linux follows the portal (DEC-026), PTT diagnostics carry capability/availability only with no raw key codes (DEC-027), and the missed-key-up watchdog is a P0 release-gate requirement (DEC-028). No prior decision rows are mutated. | | 0.9.10 | 2026-05-15 | Code-side promotion: the Linux GNOME-Wayland backend (DEC-025) is now a live `org.freedesktop.portal.GlobalShortcuts` session — `CreateSession` + `BindShortcuts` + `Activated` / `Deactivated` signal subscription scoped to the session handle, owned by a dedicated tokio task per backend instance. The Flutter "Configure" button on Linux portal delegates to the portal's own system dialog (Q3a) rather than the in-app `_PttBindingCaptureDialog`. Descriptor transitions broadcast via a `watch::Sender` consumed by `chanora_core::ChanoraSession::start_audio` and forwarded to `SessionEvent::PttCapability`. Cancellation / failure path downgrades to `L0Focused` and re-emits. No decision rows mutate. | +| 0.9.11 | 2026-05-15 | Added DEC-029 and DEC-030 covering the v1 audio + PTT lifecycle redesign. DEC-029 rejects Flutter global-hotkey packages (`hotkey_manager`, `super_hot_key`, equivalents) for PTT — they consume the key, do not deliver key-up, and do not support mouse side-buttons; the native Rust `DesktopPttBackend` already specified in SDD-083 / SDD-084 / SDD-085 is the v1 capture path. DEC-030 defers Voice Activity Detection to P1: `TransmitMode::VoiceActivity` ships as a reserved enum variant with no v1 implementation pending a backend trade-off review (RMS vs WebRTC VAD vs Silero VAD differ by ~8–16 MB and an ONNX-runtime dependency surface). No prior decision rows mutate; §5 impact matrix and §7 open-decision log gain matching rows. | diff --git a/docs/governance/traceability-matrix.md b/docs/governance/traceability-matrix.md index ab53c9f..e86e220 100644 --- a/docs/governance/traceability-matrix.md +++ b/docs/governance/traceability-matrix.md @@ -235,3 +235,27 @@ No forbidden direct links introduced: SRS continues to source from SysDes only, | Version | Date | Description | |---|---|---| | 0.9.4 | 2026-05-15 | Corrected SRS-200 traceability row: SAD coverage moves from the narrative `SAD-072..074` annotation to the dedicated `SAD-080`, with SDD coverage in the new `SDD-093`. The change preserves strict layer discipline (SRS-200 -> SAD-080 -> SDD-093). No other rows mutate. | + + +## v1 Audio + PTT Lifecycle Traceability Addendum (Baseline Candidate 0.9.5) + +Strict layered sourcing for the v1 audio + PTT lifecycle chain: + +```text +SysRS-303..304 + -> SysDes-149..151 + -> SRS-204..207 + -> SAD-081..083 + -> SDD-094..097 +``` + +| SysRS | SysDes | SRS | SAD | SDD | Cross-reference | +|---|---|---|---|---|---| +| SysRS-303 (Transmit modes, lifecycle, listen-only, hard-mute) | SysDes-149, SysDes-150 | SRS-204, SRS-205, SRS-207 | SAD-081, SAD-083 | SDD-094, SDD-095, SDD-097 | DEC-029 (native PTT backend locked), DEC-030 (VAD deferred) | +| SysRS-304 (PTT release tail) | SysDes-151 | SRS-206 | SAD-082 | SDD-096 | — | + +No forbidden direct links introduced: SRS continues to source from SysDes only, SAD from SRS only, SDD from SAD only. DEC-029 / DEC-030 are governance cross-references and do not act as engineering-layer direct sources. + +| Version | Date | Description | +|---|---|---| +| 0.9.5 | 2026-05-15 | Added v1 audio + PTT lifecycle traceability rows covering SysRS-303..304 -> SysDes-149..151 -> SRS-204..207 -> SAD-081..083 -> SDD-094..097, with DEC-029 (Flutter hotkey packages rejected) and DEC-030 (VAD deferred to P1) recorded as governance cross-references. | diff --git a/docs/requirements/srs.md b/docs/requirements/srs.md index eacdec7..7f68512 100644 --- a/docs/requirements/srs.md +++ b/docs/requirements/srs.md @@ -2587,6 +2587,42 @@ This section extends the ASPICE SWE.1 Software Requirements Specification. The s - Source SysDes: SysDes-142, SysDes-144 - Verification method: Unit Test, Integration Test +**SRS-204**: The audio engine shall open the input and output streams on the user's first voice-channel join of the session and shall close them on the last voice-channel leave. The software shall expose no `start_audio` or equivalent manual-start operation at the bridge surface and shall expose no manual-start affordance in the UI; the bridge shall instead expose `voice_join(channel_id)` and `voice_leave()` operations and the audio engine shall initialise implicitly on the first `voice_join`. Output-stream opening shall not depend on the microphone-permission grant state, so listen-only is a first-class flow. + +- Status: Baseline Candidate +- Type: Software Lifecycle Requirement +- Stage: P0 / MVP +- Allocated to: Audio, Bridge, Flutter UI +- Source SysDes: SysDes-150 +- Verification method: Integration Test, UI Review + +**SRS-205**: The software shall represent the user's voice transmit mode as a `TransmitMode` enum with variants `Ptt`, `Continuous`, and `VoiceActivity` (the last reserved with no v1 implementation per DEC-030). The setting shall be persisted per identity via the identity store. The default value for a fresh install shall be `Ptt`. The UI shall render `VoiceActivity` as a disabled "coming soon" option until an implementation is allocated in a later baseline. + +- Status: Baseline Candidate +- Type: Software Interface Requirement +- Stage: P0 / MVP +- Allocated to: Audio, Bridge, Flutter UI +- Source SysDes: SysDes-149 +- Verification method: Unit Test, UI Review + +**SRS-206**: The software shall expose a `release_tail_ms` configuration value (default 200 ms, validated range 0 through 500 ms inclusive) and shall delay the `true → false` transition of `transmit_active` by `release_tail_ms` after the PTT backend reports key-up. Where the user re-presses the bound input within the tail window, the pending close timer shall be cancelled and `transmit_active` shall remain true. The release tail shall not affect `capture_active`. + +- Status: Baseline Candidate +- Type: Software Behavioural Requirement +- Stage: P0 / MVP +- Allocated to: Audio +- Source SysDes: SysDes-151 +- Verification method: Unit Test, Integration Test + +**SRS-207**: The software shall expose a hard-mute toggle in the Voice Bar UI. While hard-mute is engaged, `transmit_active` shall be forced false regardless of the active transmit mode, the PTT key state, or any other internal signal. Hard-mute state shall be persisted in-session only and shall reset to off when the user joins a new voice channel. + +- Status: Baseline Candidate +- Type: Software Behavioural Requirement +- Stage: P0 / MVP +- Allocated to: Audio, Flutter UI +- Source SysDes: SysDes-150 +- Verification method: Functional Test, UI Review + ## 17. Updated SRS to SysDes Coverage Statement | SysDes Range | SRS Coverage | @@ -2594,6 +2630,7 @@ This section extends the ASPICE SWE.1 Software Requirements Specification. The s | SysDes-001 through SysDes-132 | Covered by inherited SRS baseline `SRS-001` through `SRS-184` | | SysDes-133 through SysDes-141 | Covered by `SRS-185` through `SRS-194` | | SysDes-142 through SysDes-148 | Covered by `SRS-195` through `SRS-203` | +| SysDes-149 through SysDes-151 | Covered by `SRS-204` through `SRS-207` | ## Baseline Candidate 0.9.1 Update @@ -2615,3 +2652,10 @@ This section extends the ASPICE SWE.1 Software Requirements Specification. The s | Version | Date | Description | |---|---|---| | 0.9.3 | 2026-05-15 | Added desktop PTT software requirements SRS-195 through SRS-203: `DesktopPttBackend` trait + per-platform implementations, `PttCapabilityLevel` enum, Windows Raw-Input ladder, macOS permission-aware backend, Linux GNOME-Wayland GlobalShortcuts portal backend, mouse-side-button support per DEC-027, `capture_active` / `transmit_active` split, sanitised diagnostics, missed-key-up watchdog per DEC-028. Sourcing remains strict (`SRS -> SysDes` only). | + + +## Baseline Candidate 0.9.5 Update + +| Version | Date | Description | +|---|---|---| +| 0.9.5 | 2026-05-15 | Added v1 audio + PTT lifecycle software requirements SRS-204 through SRS-207 sourced from SysDes-149..151: bridge surface drops `start_audio` / `stop_audio` and adds `voice_join(channel_id)` / `voice_leave()`, audio engine opens streams on first voice-channel join and closes on last leave with output independent of mic-permission state, `TransmitMode` enum (`Ptt` default, `Continuous`, reserved `VoiceActivity` per DEC-030) persisted per identity, `release_tail_ms` (default 200, range 0–500) gate on the `true → false` transition of `transmit_active` with re-press cancellation, Voice Bar hard-mute override of `transmit_active`. Strict layered sourcing preserved (`SRS -> SysDes` only). | diff --git a/docs/requirements/sysrs.md b/docs/requirements/sysrs.md index b12380e..3a50cbb 100644 --- a/docs/requirements/sysrs.md +++ b/docs/requirements/sysrs.md @@ -1924,6 +1924,16 @@ This section converts the baseline product decisions into auditable system-level - Priority: P0 - Verification: Privacy Review, Security Audit, Diagnostic Inspection +**SysRS-303**: The Chanora application system shall define the v1 voice transmit mode set as `Ptt` and `Continuous`, with `VoiceActivity` reserved on the enum surface but unimplemented in this baseline (deferred per DEC-030). The default mode on a fresh install shall be `Ptt`; the user-selected mode shall be persisted per identity. The audio engine lifecycle shall be bound to voice-channel membership: input and output streams shall open on the user's first voice-channel join of the session and shall close on the last voice-channel leave, with no manual start affordance exposed at any system interface. The output stream shall open regardless of microphone-permission state so listen-only is a first-class flow. A user-facing hard-mute toggle shall force the transmit gate closed and shall override the active transmit mode, the PTT key state, and every other internal signal. + +- Priority: P0 +- Verification: Functional Test, UX Review + +**SysRS-304**: The Chanora application system shall apply a configurable PTT release-tail interval between the moment the bound PTT input reports key-up and the moment the transmit gate closes, so that the trailing syllable of a spoken word is not clipped at word boundaries. The default release-tail value shall be 200 ms (matching the TeamSpeak / Mumble default); the user-configurable range shall be 0 ms through 500 ms inclusive. The release tail shall not affect the input-stream capture lifecycle; it shall affect only the transmit gate. + +- Priority: P0 +- Verification: Functional Test, UX Review + ## 32. Change History Addendum @@ -1943,3 +1953,10 @@ This section converts the baseline product decisions into auditable system-level | Version | Date | Description | |---|---|---| | 0.9.3 | 2026-05-15 | Added desktop Push-to-Talk requirements SysRS-296 through SysRS-302: mandatory Focused PTT on Windows/macOS/Linux, capability-dependent Global PTT, capability-level exposure to UI and release record, Windows Raw Input + low-level-hook + Focused fallback ladder, macOS permission-aware Global PTT, Linux capability-dependent Global PTT (GNOME on Wayland officially-tested per DEC-026), and the privacy rule prohibiting raw key-event history in logs and diagnostic exports. Owner-resolved gen2 review questions PTT-OPEN-001..006 land as DEC-023..028 in the product decision register. | + + +## Baseline Candidate 0.9.5 Update + +| Version | Date | Description | +|---|---|---| +| 0.9.5 | 2026-05-15 | Added v1 audio + PTT lifecycle requirements SysRS-303 and SysRS-304 capturing the no-manual-start audio engine bound to voice-channel membership, the v1 transmit-mode set (`Ptt` default + `Continuous`, with `VoiceActivity` reserved per DEC-030), the listen-only flow (output independent of mic permission), the hard-mute override, and the 200 ms (0–500 ms) PTT release tail for word-boundary anti-clipping. |