Full P0 Android documentation chain: - SysRS: API 24 → API 28 reconciliation per DEC-004 (SysRS-288); add SysRS-305 (Android in-call audio mode), SysRS-306 (RECORD_AUDIO runtime timing). - SysDes: SysDes-152 (in-call audio mode subsystem), SysDes-153 (RECORD_AUDIO permission flow), SysDes-154 (Android voice audio backend), SysDes-155 (macOS runtime baseline). - SRS: SRS-187 → API 28; add SRS-208 (in-call audio mode), SRS-209 (RECORD_AUDIO + listen-only fallback), SRS-210..215 (Android voice audio backend latency/preset/AEC/usage/sharing/foreground service); retarget SysDes anchors from generic SysDes-135 to SysDes-152/153/154. - SAD: SAD-063 refreshed (API 28); add SAD-084 (audio mode controller), SAD-085 (permission adapter with listen-only), SAD-086 (foreground service), SAD-087 (macOS runtime baseline); formalize cross-cutting + platform-specific allocation pattern in §24.1. - SDD: expand SDD-028 (BackIntentService); refresh SDD-073 (build config); add SDD-105 (JNI bootstrap), SDD-106 (permission requester), SDD-107 (foreground service), SDD-108 (audio mode controller), SDD-109 (AAB pipeline), SDD-110 (PTT capability), SDD-111..116 (Android voice audio backend), SDD-118 (Android bridge build automation), SDD-119 (iOS/macOS bridge build automation back-fill). - Verification: create android-p0-acceptance.md TC-1..TC-18; add SWE4-UV-040..052, SWE5-IV-016..026, SWE6-SV-018..030, SYS4-SIV-015 strengthened + SYS4-SIV-017/018. - Governance: traceability matrix v0.9.9 with end-to-end chain closure; DEC-032 documents the temporary abiFilters reduction to arm64-v8a only and its restore-by gate. Trace: full chain SysRS → SysDes → SRS → SAD → SDD → Code → Verification.
628 lines
34 KiB
Markdown
628 lines
34 KiB
Markdown
|
|
# Chanora SWE.4 Software Unit Verification Plan
|
|
|
|
**Document type:** Software Unit Verification Plan
|
|
**Process alignment:** ASPICE SWE.4 Software Unit Verification
|
|
**Version:** 0.9.14
|
|
**Status:** Baseline Candidate
|
|
**Language:** English
|
|
**Product:** Chanora
|
|
**Verification object:** Software units defined by SDD
|
|
**Direct source layer:** SDD only
|
|
|
|
**Repo path:** `docs/verification/swe4-unit-verification-plan.md` ---
|
|
|
|
## 1. Purpose
|
|
|
|
This document defines the software unit verification strategy for Chanora. It verifies that software units implement the Software Detailed Design.
|
|
|
|
This document is downstream of SDD and shall not bypass the document hierarchy.
|
|
|
|
```text
|
|
SysRS -> SysDes -> SRS -> SAD -> SDD -> SWE.4 Unit Verification
|
|
```
|
|
|
|
Direct source rule:
|
|
|
|
```text
|
|
SWE.4 unit verification items shall link directly to SDD only.
|
|
```
|
|
|
|
## 2. Verification Scope
|
|
|
|
In scope:
|
|
|
|
- Flutter unit tests
|
|
- Flutter widget-level unit verification where a widget is treated as a software unit
|
|
- Dart static analysis
|
|
- Dart code review
|
|
- Rust unit tests
|
|
- Rust static analysis
|
|
- Rust code review
|
|
- Unit-level regression verification
|
|
- Unit-level interface boundary tests
|
|
- Unit-level localization, Unicode, design-token, and diagnostics verification
|
|
|
|
Out of scope:
|
|
|
|
- Software integration verification across components; handled by SWE.5.
|
|
- Fully integrated software verification against SRS; handled by SWE.6.
|
|
- System integration verification against SysDes; handled by SYS.4.
|
|
|
|
## 3. Unit Verification Strategy
|
|
|
|
| Verification type | Applies to | Purpose |
|
|
|---|---|---|
|
|
| Static analysis | Dart, Rust | Detect structural, lint, safety, style, and maintainability issues |
|
|
| Code review | Dart, Rust, build scripts | Confirm design compliance and maintainability |
|
|
| Unit tests | Dart, Rust | Verify individual units against SDD behavior |
|
|
| Widget tests | Flutter widgets | Verify component rendering, semantics, and state behavior |
|
|
| Golden tests | Design-system components | Verify stable UI rendering where appropriate |
|
|
| Localization tests | Localization service and accessibility labels | Verify fallback, keys, and localized display strings |
|
|
| Unicode tests | Protocol/bridge/text-boundary units | Verify UTF-8 and multilingual content handling |
|
|
| Regression tests | Changed units | Confirm unchanged behavior remains valid after modifications |
|
|
|
|
## 4. Entry Criteria
|
|
|
|
| Criterion | Description |
|
|
|---|---|
|
|
| SDD baseline available | Unit design items and source SAD links are available. |
|
|
| Unit implementation available | The unit exists in source code or executable test double form. |
|
|
| Unit test environment available | Flutter and/or Rust test infrastructure is configured. |
|
|
| Verification measure defined | Test, review, or static analysis objective is defined. |
|
|
| Pass/fail criteria defined | Expected result is objective and reviewable. |
|
|
|
|
## 5. Exit Criteria
|
|
|
|
| Criterion | Description |
|
|
|---|---|
|
|
| Selected unit verification measures executed | Tests, reviews, and analyses required for the release scope are complete. |
|
|
| Results recorded | Verification results are stored in test reports or review records. |
|
|
| Nonconformances recorded | Failures are recorded for problem resolution. |
|
|
| Traceability complete | Each unit verification item traces to SDD and result evidence. |
|
|
| Regression scope complete | Changed units have selected regression measures executed. |
|
|
|
|
## 6. Unit Verification Measures
|
|
|
|
**SWE4-UV-001**: Verify `ChanoraApp` initialization order.
|
|
|
|
- Source SDD: SDD-001, SDD-045
|
|
- Verification method: Flutter unit/integration test
|
|
- Pass criteria: Theme, localization, platform services, routing, and adaptive shell initialize before feature rendering.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-002**: Verify `ChanoraThemeFactory` Material 3 theme creation.
|
|
|
|
- Source SDD: SDD-002, SDD-003
|
|
- Verification method: Dart unit test
|
|
- Pass criteria: Light and dark Material 3 ThemeData objects are created with valid ColorScheme and TextTheme values.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-003**: Verify `ChanoraSemanticColors` connection token behavior.
|
|
|
|
- Source SDD: SDD-004, SDD-006
|
|
- Verification method: Dart unit test
|
|
- Pass criteria: All connection semantic roles are present and do not require feature-screen hardcoding.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-004**: Verify voice semantic token behavior.
|
|
|
|
- Source SDD: SDD-005, SDD-006
|
|
- Verification method: Dart unit test
|
|
- Pass criteria: Speaking, muted, deafened, and push-to-talk active states are available through semantic tokens.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-005**: Verify feature widgets use theme accessors rather than hardcoded semantic values.
|
|
|
|
- Source SDD: SDD-010
|
|
- Verification method: Static inspection
|
|
- Pass criteria: Feature widgets do not construct product semantic token values directly.
|
|
- Evidence: Review record
|
|
|
|
**SWE4-UV-006**: Verify adaptive shell window classification.
|
|
|
|
- Source SDD: SDD-011, SDD-012
|
|
- Verification method: Dart unit test
|
|
- Pass criteria: Compact, medium, and expanded classes are selected deterministically.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-007**: Verify `CompactShell` layout behavior.
|
|
|
|
- Source SDD: SDD-013
|
|
- Verification method: Flutter widget test
|
|
- Pass criteria: Compact shell renders a single-column layout and mobile navigation entry points.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-008**: Verify `MediumShell` layout behavior.
|
|
|
|
- Source SDD: SDD-014
|
|
- Verification method: Flutter widget test
|
|
- Pass criteria: Medium shell renders side navigation or navigation rail behavior.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-009**: Verify `ExpandedShell` persistent pane behavior.
|
|
|
|
- Source SDD: SDD-015
|
|
- Verification method: Flutter widget test
|
|
- Pass criteria: Expanded shell renders persistent side pane and VoiceBar slot.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-010**: Verify connection status presentation uses non-color-only cues.
|
|
|
|
- Source SDD: SDD-016, SDD-022
|
|
- Verification method: Dart unit test, widget test
|
|
- Pass criteria: The presenter exposes label, icon, semantic label, and severity token.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-011**: Verify `ChanoraVoiceBar` exposed properties.
|
|
|
|
- Source SDD: SDD-017, SDD-018
|
|
- Verification method: Flutter widget test
|
|
- Pass criteria: Mute, deaf, push-to-talk, input meter, current channel, and latency properties render correctly.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-012**: Verify `ChanoraChannelTree` data and interaction behavior.
|
|
|
|
- Source SDD: SDD-019, SDD-020
|
|
- Verification method: Flutter widget test
|
|
- Pass criteria: Channel hierarchy, selected state, expansion state, join intent, and context-menu intent operate as designed.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-013**: Verify `ChanoraClientTile` state semantics.
|
|
|
|
- Source SDD: SDD-021
|
|
- Verification method: Widget test, accessibility test
|
|
- Pass criteria: Client status is available through text/icon/semantic cues and not color alone.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-014**: Verify localized semantic labels for icon-only buttons.
|
|
|
|
- Source SDD: SDD-024, SDD-031, SDD-032
|
|
- Verification method: Accessibility test, localization unit test
|
|
- Pass criteria: Icon-only controls expose localized semantic labels with fallback.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-015**: Verify keyboard focus traversal.
|
|
|
|
- Source SDD: SDD-025
|
|
- Verification method: Widget test
|
|
- Pass criteria: Primary interactive controls can be traversed in a logical order.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-016**: Verify text-scale resilience of critical controls.
|
|
|
|
- Source SDD: SDD-026
|
|
- Verification method: Accessibility widget test
|
|
- Pass criteria: Critical controls remain reachable under increased text scale.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-017**: Verify platform inset service unit behavior.
|
|
|
|
- Source SDD: SDD-027, SDD-030
|
|
- Verification method: Unit test with platform test doubles
|
|
- Pass criteria: Insets are normalized and exposed to the shell.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-018**: Verify back intent service behavior.
|
|
|
|
- Source SDD: SDD-028
|
|
- Verification method: Unit test with platform test doubles
|
|
- Pass criteria: Platform back events map to expected route-level intents.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-019**: Verify localization fallback.
|
|
|
|
- Source SDD: SDD-031, SDD-032, SDD-033
|
|
- Verification method: Unit test
|
|
- Pass criteria: Missing localized strings fall back deterministically.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-020**: Verify server-content pass-through.
|
|
|
|
- Source SDD: SDD-034
|
|
- Verification method: Unit test
|
|
- Pass criteria: Server-provided content is not translated by product localization.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-021**: Verify Unicode text boundary behavior.
|
|
|
|
- Source SDD: SDD-035, SDD-036, SDD-037
|
|
- Verification method: Unit test
|
|
- Pass criteria: Valid multilingual Unicode content is preserved; invalid external encodings are handled at boundaries.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-022**: Verify diagnostic Unicode preservation and redaction behavior.
|
|
|
|
- Source SDD: SDD-038, SDD-041, SDD-050, SDD-054
|
|
- Verification method: Unit test, security review
|
|
- Pass criteria: Secrets are redacted while multilingual content is preserved.
|
|
- Evidence: Test result, review record
|
|
|
|
**SWE4-UV-023**: Verify locale-aware formatting.
|
|
|
|
- Source SDD: SDD-040
|
|
- Verification method: Unit test
|
|
- Pass criteria: Dates, times, numbers, and timestamps format through localization utilities.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-024**: Verify traceability checker behavior.
|
|
|
|
- Source SDD: SDD-043, SDD-044, SDD-055, SDD-056, SDD-066, SDD-067
|
|
- Verification method: Unit test / script test
|
|
- Pass criteria: Invalid direct-layer references are detected.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-025**: Verify bridge DTO safety.
|
|
|
|
- Source SDD: SDD-046
|
|
- Verification method: Unit test, static inspection
|
|
- Pass criteria: Bridge DTOs do not expose internal Rust implementation types.
|
|
- Evidence: Test result, review record
|
|
|
|
**SWE4-UV-026**: Verify Rust core event mapping.
|
|
|
|
- Source SDD: SDD-047
|
|
- Verification method: Rust unit test
|
|
- Pass criteria: Core events map deterministically to view model deltas.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-027**: Verify voice view model separation from DSP.
|
|
|
|
- Source SDD: SDD-048
|
|
- Verification method: Code review, unit test
|
|
- Pass criteria: Voice UI receives status values and does not perform audio DSP.
|
|
- Evidence: Review record, test result
|
|
|
|
**SWE4-UV-028**: Verify storage facade isolation.
|
|
|
|
- Source SDD: SDD-049
|
|
- Verification method: Static inspection, unit test
|
|
- Pass criteria: Feature widgets do not directly call database APIs.
|
|
- Evidence: Review record, test result
|
|
|
|
**SWE4-UV-029**: Verify interface detail catalog completeness.
|
|
|
|
- Source SDD: SDD-059, SDD-060
|
|
- Verification method: Review
|
|
- Pass criteria: Unit-level interface entries include required details where applicable.
|
|
- Evidence: Review record
|
|
|
|
**SWE4-UV-030**: Verify unit construction and review records.
|
|
|
|
- Source SDD: SDD-064, SDD-065, SDD-068, SDD-069, SDD-070
|
|
- Verification method: Review
|
|
- Pass criteria: Unit construction, review, verification handoff, and registry records exist for release scope units.
|
|
- Evidence: Review record
|
|
|
|
## 7. Traceability Matrix
|
|
|
|
| SDD Range | SWE.4 Coverage |
|
|
|---|---|
|
|
| SDD-001 through SDD-010 | SWE4-UV-001 through SWE4-UV-005 |
|
|
| SDD-011 through SDD-018 | SWE4-UV-006 through SWE4-UV-011 |
|
|
| SDD-019 through SDD-026 | SWE4-UV-012 through SWE4-UV-016 |
|
|
| SDD-027 through SDD-037 | SWE4-UV-017 through SWE4-UV-021 |
|
|
| SDD-038 through SDD-050 | SWE4-UV-022 through SWE4-UV-028 |
|
|
| SDD-051 through SDD-070 | SWE4-UV-029 through SWE4-UV-030 |
|
|
|
|
## 8. Result Reporting
|
|
|
|
Unit verification results shall be summarized in a unit verification summary report including:
|
|
|
|
- verification scope
|
|
- selected verification measures
|
|
- skipped measures and rationale
|
|
- pass/fail result
|
|
- nonconformances
|
|
- regression scope
|
|
- residual risks
|
|
- release recommendation
|
|
|
|
## 9. Change History
|
|
|
|
| Version | Date | Description |
|
|
|---|---|---|
|
|
| 0.1.0 | 2026-05-14 | Initial SWE.4 unit verification plan derived from SDD v0.3. |
|
|
|
|
---
|
|
|
|
## 10. Platform Decision Unit Verification Addendum
|
|
|
|
**SWE4-UV-031**: Verify iOS and Android build configuration units.
|
|
|
|
- Source SDD: SDD-071, SDD-072, SDD-073
|
|
- Verification method: Static inspection, platform test
|
|
- Pass criteria: iOS minimum runtime, Apple SDK gate, Android minimum runtime, and Android target SDK configuration are inspectable and match release policy.
|
|
- Evidence: Test result, release inspection
|
|
|
|
**SWE4-UV-032**: Verify single active connection enforcement.
|
|
|
|
- Source SDD: SDD-074
|
|
- Verification method: Unit test
|
|
- Pass criteria: Attempting to create a second active MVP connection is rejected or routed through a controlled disconnect/switch policy.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-033**: Verify audio processing defaults and backend selection.
|
|
|
|
- Source SDD: SDD-075, SDD-076
|
|
- Verification method: Unit test, audio test
|
|
- Pass criteria: AEC, AGC, Noise Suppression, and High-Pass Filter default to enabled where supported and stable; backend selector prefers platform-native processing.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-034**: Verify local database, secret storage, bridge, and diagnostics privacy gate units.
|
|
|
|
- Source SDD: SDD-077, SDD-078, SDD-079, SDD-080
|
|
- Verification method: Unit test, security inspection
|
|
- Pass criteria: Non-secret storage, secret storage, typed bridge DTOs, and disabled automatic upload/crash behavior match detailed design.
|
|
- Evidence: Test result, security review
|
|
|
|
**SWE4-UV-035**: Verify `DesktopPttBackend` trait + `PttCapabilityLevel` enum + `FocusedPttBackend` units.
|
|
|
|
- Source SDD: SDD-081, SDD-082, SDD-087
|
|
- Verification method: Unit test
|
|
- Pass criteria: Trait surface compiles for every implementation; enum `as_str()` mapping is unambiguous; `FocusedPttBackend` reports `L0Focused` and forwards `set_ptt` events into `AudioTransmitGate` unchanged.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-036**: Verify Windows / macOS / Linux platform backend units in isolation.
|
|
|
|
- Source SDD: SDD-083, SDD-084, SDD-085, SDD-086
|
|
- Verification method: Unit test (with mocked OS surfaces), Platform Test (Windows / macOS / GNOME-Wayland reference hosts)
|
|
- Pass criteria: Each backend reports the expected `PttCapabilityLevel` for the current host configuration; the ladder falls through to `FocusedPttBackend` when its preferred OS API is unavailable.
|
|
- Evidence: Test result, platform-test trace
|
|
|
|
**SWE4-UV-037**: Verify `PttController` + `AudioTransmitGate` units.
|
|
|
|
- Source SDD: SDD-088, SDD-089
|
|
- Verification method: Unit test
|
|
- Pass criteria: `PttController::set_binding` rebinds the active backend without dropping `AudioTransmitGate`; `AudioTransmitGate::subscribe()` returns a `watch::Receiver` that delivers every transition the gate observes.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-038**: Verify `PttSanitizer` and `PttCapabilityBadge` units.
|
|
|
|
- Source SDD: SDD-090, SDD-091
|
|
- Verification method: Unit test, UI review
|
|
- Pass criteria: `PttSanitizer` drops records whose field names match the banned list (`key_code`, `scan_code`, `virtual_key`, `vk`, `keysym`, `keysym_string`, `key_sequence`); `PttCapabilityBadge` renders the correct label and explanation sheet for each `PttCapabilityLevel`.
|
|
- Evidence: Test result, UI screenshot
|
|
|
|
**SWE4-UV-039**: Verify `MissedKeyUpWatchdog` unit.
|
|
|
|
- Source SDD: SDD-092
|
|
- Verification method: Unit test (tokio time-paused)
|
|
- Pass criteria: After a simulated `false -> true -> (timeout elapsed)` sequence the watchdog calls `AudioTransmitGate::set(false)` exactly once and emits a sanitised diagnostic record naming only `capability_level` and `backend_id`.
|
|
- Evidence: Test result
|
|
|
|
| SDD Range | SWE.4 Coverage |
|
|
|---|---|
|
|
| SDD-071 through SDD-080 | SWE4-UV-031 through SWE4-UV-034 |
|
|
| SDD-081 through SDD-092 | SWE4-UV-035 through SWE4-UV-039 |
|
|
|
|
|
|
## Baseline Candidate 0.9.1 Update
|
|
|
|
| Version | Date | Description |
|
|
|---|---|---|
|
|
| 0.9.1 | 2026-05-14 | Updated baseline after product decision closure: Apple App Store SDK gate uses Xcode 26+ and iOS 26 / iPadOS 26 SDK+ since 2026-04-28, platform baselines and decision traceability propagated across the document set. |
|
|
|
|
|
|
## Baseline Candidate 0.9.2 Update
|
|
|
|
| Version | Date | Description |
|
|
|---|---|---|
|
|
| 0.9.2 | 2026-05-14 | Corrected Apple App Store Connect upload gate to 2026-04-28 and checked full-package naming, references, and coverage. |
|
|
|
|
|
|
## Baseline Candidate 0.9.3 Update
|
|
|
|
| Version | Date | Description |
|
|
|---|---|---|
|
|
| 0.9.3 | 2026-05-15 | Added desktop PTT unit-verification items SWE4-UV-035 through SWE4-UV-039: `DesktopPttBackend` trait + `PttCapabilityLevel`, platform backends, `PttController` + `AudioTransmitGate`, `PttSanitizer` + `PttCapabilityBadge`, `MissedKeyUpWatchdog`. |
|
|
|
|
|
|
## 11. Android P0 Unit Verification Addendum
|
|
|
|
**SWE4-UV-040**: Verify Android build configuration unit (`SDD-073` expanded).
|
|
|
|
- Source SDD: SDD-073
|
|
- Verification method: Gradle task assertion + static inspection of `android/app/build.gradle.kts`
|
|
- Pass criteria: `minSdk` literal equals `28` (DEC-004); `ndk.abiFilters` set equals `{arm64-v8a, armeabi-v7a, x86_64}` (per SDD-073 item 4 and SDD-118 item 3, `x86` 32-bit is explicitly out of scope and shall not be in the set); release `signingConfig` references the CI signing key reference (not debug); R8/ProGuard `minifyEnabled = true` on release; `bundle { abi.enableSplit = true }`; assemble target produces an AAB artifact at `app/build/outputs/bundle/release/app-release.aab`.
|
|
- Evidence: Gradle log + manifest dump
|
|
|
|
**SWE4-UV-041**: Verify `AndroidPermissionRequester` state machine (`SDD-106`).
|
|
|
|
- Source SDD: SDD-106
|
|
- Source SRS: SRS-209
|
|
- Verification method: Dart/Kotlin unit test with a permission-platform test double
|
|
- Pass criteria: State transitions are exhaustive for `{granted, denied, permanently_denied, revoked_mid_session}`; transitioning out of `granted` clamps `AudioTransmitGate::set(false)`; re-entering `granted` does NOT auto-transmit (requires explicit user gesture); permanently-denied surfaces a settings-deep-link intent rather than re-prompting.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-042**: Verify `BackIntentService` Android branches (`SDD-028` expanded).
|
|
|
|
- Source SDD: SDD-028
|
|
- Source SRS: SRS-163
|
|
- Verification method: Dart unit test with platform-channel test double for both `OnBackInvokedCallback` (API 33+) and `OnBackPressedDispatcher` (API ≤ 32) paths.
|
|
- Pass criteria: Modal-first rule — if a modal is open, back closes the modal and does not pop the route. PTT-active-ignore — while `transmit_active == true` the back event is consumed without effect. Route-pop ordering — otherwise the topmost non-modal route pops. The API 33+ branch registers a `OnBackInvokedCallback` at `PRIORITY_DEFAULT`; the pre-33 branch registers an `OnBackPressedCallback`. Switching API level in the test double switches the active branch deterministically.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-043**: Verify `AndroidJniBootstrap` library load and init ordering (`SDD-105`).
|
|
|
|
- Source SDD: SDD-105
|
|
- Verification method: Instrumented unit test on Android (or Robolectric where applicable)
|
|
- Pass criteria: `System.loadLibrary("chanora_bridge")` is invoked from the `Application` subclass `onCreate` (not from an Activity); `JNI_OnLoad` runs exactly once per process and captures the `JavaVM*`; bridge init occurs before any FFI call from Dart; double-init is a no-op.
|
|
- Evidence: Test result + logcat trace
|
|
|
|
**SWE4-UV-044**: Verify `AndroidVoiceForegroundService` lifecycle unit (`SDD-107`).
|
|
|
|
- Source SDD: SDD-107
|
|
- Source SRS: SRS-111
|
|
- Verification method: Kotlin unit test + Robolectric `ServiceController`
|
|
- Pass criteria: `startForeground` is called within 5 s of `onStartCommand` (API 26+ requirement); notification channel exists with `IMPORTANCE_LOW`; `foregroundServiceType` includes `microphone` on API 30+; service stops cleanly on disconnect intent and does not leak its wakelock; restart policy is `START_NOT_STICKY` (no auto-respawn after force-stop).
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-045**: Verify `AndroidAudioModeController` snapshot/restore + refcount (`SDD-108`).
|
|
|
|
- Source SDD: SDD-108
|
|
- Source SRS: SRS-208
|
|
- Source SysRS: SysRS-305
|
|
- Verification method: Kotlin unit test with `AudioManager` test double
|
|
- Pass criteria: First acquire snapshots prior `AudioManager.getMode()` and sets `MODE_IN_COMMUNICATION`; nested acquires increment refcount without re-snapshotting; matched release decrements; final release restores the snapshotted prior mode exactly once; when `AudioManager` is unavailable (e.g. injected null), controller logs a sanitized warning and degrades to no-op without throwing.
|
|
- Evidence: Test result
|
|
|
|
**SWE4-UV-046**: Verify `AndroidPttCapability` reports `L0Focused` and pins `FocusedPttBackend` (`SDD-110`).
|
|
|
|
- Source SDD: SDD-110
|
|
- Verification method: Rust + Dart unit test
|
|
- Pass criteria: On `target_os = "android"` the `DesktopPttBackend` factory returns `FocusedPttBackend` unconditionally (no ladder evaluation); `PttCapabilityBadge` renders the localized `L0Focused` label with the Android-specific explanation string; no Android branch attempts to bind global hotkeys.
|
|
- Evidence: Test result + UI screenshot
|
|
|
|
| SDD Range | SWE.4 Coverage |
|
|
|---|---|
|
|
| SDD-028 (expanded) | SWE4-UV-042 |
|
|
| SDD-073 (refreshed) | SWE4-UV-040 |
|
|
| SDD-105 | SWE4-UV-043 |
|
|
| SDD-106 | SWE4-UV-041 |
|
|
| SDD-107 | SWE4-UV-044 |
|
|
| SDD-108 | SWE4-UV-045 |
|
|
| SDD-110 | SWE4-UV-046 |
|
|
|
|
|
|
### Android voice audio backend unit-verification items (SDD-111..SDD-116 wave)
|
|
|
|
**SWE4-UV-047**: Verify `AndroidVoiceStreamConfig` builder records requested vs. achieved fields.
|
|
|
|
- Source SDD: SDD-112 (config struct), SDD-111 (trait surface)
|
|
- Source SRS: SRS-210, SRS-211, SRS-213, SRS-214
|
|
- Source SAD: SAD-077, SAD-081
|
|
- Verification method: Rust unit test with a fake Oboe builder return path (no device)
|
|
- Pass criteria: Given a `MobileVoiceStreamConfig` requesting `PERFORMANCE_MODE_LOW_LATENCY`, input preset `VoiceCommunication`, output usage `VoiceCommunication`, content type `Speech`, and sharing mode `Exclusive`, the resulting `AndroidVoiceStreamConfig` records the requested values verbatim AND exposes `achieved_*` accessors populated from the fake builder's grant values. Mismatch between requested and achieved is observable via the accessors with no panics. Both input and output stream configs are independently recorded.
|
|
- Evidence: Rust unit test result
|
|
- SDD-116 matrix row satisfied: none directly (unit-level; matrix consumes the accessors per-device)
|
|
|
|
**SWE4-UV-048**: Verify input preset fallback ladder is observable at each step.
|
|
|
|
- Source SDD: SDD-111 (trait surface, open() error pathway), SDD-112 (preset field)
|
|
- Source SRS: SRS-211
|
|
- Source SAD: SAD-077
|
|
- Verification method: Rust unit test with a scripted Oboe builder mock that returns `ErrorIllegalArgument` for successive presets
|
|
- Pass criteria: With the mock denying `VoiceCommunication`, `open()` retries with `VoicePerformance`; with the mock denying both, `open()` retries with `Generic` (`Unprocessed`/default). Each retry is recorded in a structured field (e.g. `attempted_presets: Vec<InputPreset>`) and the final `achieved_input_preset()` returns the preset that was granted. If all presets fail, `open()` returns `BackendError::InputPresetUnavailable` (or the SDD-111 equivalent). No silent fallback.
|
|
- Evidence: Rust unit test result
|
|
- SDD-116 matrix row satisfied: none directly (matrix records `achieved_input_preset` per device)
|
|
|
|
**SWE4-UV-049**: Verify sharing-mode fallback Exclusive→Shared is observable.
|
|
|
|
- Source SDD: SDD-111, SDD-112 (sharing mode field)
|
|
- Source SRS: SRS-214
|
|
- Source SAD: SAD-077
|
|
- Verification method: Rust unit test with a fake Oboe builder return path
|
|
- Pass criteria: When the fake builder accepts `SharingMode::Exclusive`, `achieved_sharing_mode()` returns `Exclusive` and no retry occurs. When the fake builder rejects `Exclusive` (returns the documented Oboe error path for exclusive denial), the unit retries with `Shared`, and `achieved_sharing_mode()` returns `Shared`. The original request (`Exclusive`) is still recorded for diagnostics.
|
|
- Evidence: Rust unit test result
|
|
- SDD-116 matrix row satisfied: none directly (matrix records `achieved_sharing_mode` per device)
|
|
|
|
**SWE4-UV-050**: Verify hardware effects per-effect success/failure logic with software-AEC fallback.
|
|
|
|
- Source SDD: SDD-113 (per-effect construction + software fallback signal)
|
|
- Source SRS: SRS-212
|
|
- Source SAD: SAD-077, SAD-081
|
|
- Verification method: Rust unit test with a mocked JNI surface (`new_object`-style indirection) representing `AcousticEchoCanceler.create`, `NoiseSuppressor.create`, `AutomaticGainControl.create`
|
|
- Pass criteria: For each of AEC, NS, AGC: (a) success path — mock returns a non-null `GlobalRef`, effect is recorded as engaged, `setEnabled(true)` is invoked once; (b) failure path — mock returns null OR throws, the unit records the per-effect failure, does NOT abort the other two, and signals the engine to engage the software equivalent (per SDD-113 item 5 — for AEC failure the engine's software AEC must be flagged on). Order of effect construction does not affect outcome (no cross-effect coupling). `release()` is called on every engaged `GlobalRef` exactly once when the unit is torn down.
|
|
- Evidence: Rust unit test result
|
|
- SDD-116 matrix row satisfied: per-device AEC/NS/AGC availability column
|
|
|
|
**SWE4-UV-051**: Verify performance-mode achieved recording feeds SRS-210 latency tier classification.
|
|
|
|
- Source SDD: SDD-111 (`achieved_performance_mode`), SDD-112 (mode field)
|
|
- Source SRS: SRS-210
|
|
- Source SAD: SAD-077
|
|
- Verification method: Rust unit test
|
|
- Pass criteria: When the fake builder grants `PERFORMANCE_MODE_LOW_LATENCY`, `achieved_performance_mode()` returns `LowLatency` and the SRS-210 tier classifier (the unit-level pure function that maps achieved mode → latency target) returns the 150 ms tier. When the fake builder grants `PERFORMANCE_MODE_NONE` or `POWER_SAVING`, the classifier returns the 250 ms tier. The classifier is a pure function reachable from the engine without a device.
|
|
- Evidence: Rust unit test result
|
|
- SDD-116 matrix row satisfied: per-device `achieved_performance_mode` column
|
|
|
|
**SWE4-UV-052**: Verify output stream usage and content type are set correctly.
|
|
|
|
- Source SDD: SDD-112 (output config fields)
|
|
- Source SRS: SRS-213
|
|
- Source SAD: SAD-077
|
|
- Verification method: Rust unit test inspecting the builder calls captured by a mock Oboe builder
|
|
- Pass criteria: The output stream-construction path invokes `setUsage(VoiceCommunication)` and `setContentType(Speech)` exactly once on the builder before `openStream`. No other usage / content-type combination is reachable from the production path (the test asserts there is no code path that constructs the output stream with `Media` / `Music` defaults). `achieved_output_usage()` returns `VoiceCommunication` and `achieved_output_content_type()` returns `Speech` on a successful open.
|
|
- Evidence: Rust unit test result
|
|
- SDD-116 matrix row satisfied: per-device `achieved_output_usage` / `achieved_output_content_type` column
|
|
|
|
| SDD Range | SWE.4 Coverage |
|
|
|---|---|
|
|
| SDD-111 | SWE4-UV-047, SWE4-UV-048, SWE4-UV-049, SWE4-UV-051 |
|
|
| SDD-112 | SWE4-UV-047, SWE4-UV-048, SWE4-UV-049, SWE4-UV-051, SWE4-UV-052 |
|
|
| SDD-113 | SWE4-UV-050 |
|
|
| SDD-115 | (lifecycle sequencing — see SWE.5 integration items) |
|
|
| SDD-116 | (device matrix — see SWE.6 + android-p0-acceptance TC-14..TC-18) |
|
|
|
|
|
|
## Baseline Candidate 0.9.4 Update
|
|
|
|
| Version | Date | Description |
|
|
|---|---|---|
|
|
| 0.9.4 | 2026-05-18 | Added Android P0 unit-verification items SWE4-UV-040 through SWE4-UV-046 covering SDD-028 (expanded back-intent branches), SDD-073 (refreshed build config + AAB), SDD-105 (JNI bootstrap), SDD-106 (permission state machine + transmit clamp), SDD-107 (foreground service lifecycle), SDD-108 (audio mode controller refcount + restore), SDD-110 (PTT capability pin). |
|
|
| 0.9.5 | 2026-05-18 | Added Android voice audio backend unit-verification items SWE4-UV-047 through SWE4-UV-052 covering SDD-111 (trait surface), SDD-112 (config requested vs achieved), SDD-113 (per-effect hardware engagement + software fallback) and feeding SRS-210/211/213/214 unit-level classification. |
|
|
| 0.9.14 | 2026-05-18 | Wave 3 reviewer follow-up: allocated real SWE.4 IDs for two test sets that had been cited under provisional `SWE4-UV-NNN` placeholders. SWE4-UV-053..055 anchor the three `TransmitModeSelector` permission-state clamp tests in `crates/chanora_audio/src/transmit_selector.rs` (commit 635d160 was cited under the "SWE4-UV-026 family" without real anchors). SWE4-UV-056..057 anchor the two missing `DiagnosticExport::with_android_audio` rendering tests in `crates/chanora_diagnostics/src/lib.rs` (commit aea50a1 introduced the field/builder/`to_text` branch but the unit-test pair was queued for the commit-8 amend). Closes the Wave 3 traceability gap; downstream test cites in commits 4 and 8 are amended to reference these IDs. |
|
|
|
|
## 12. Android Permission Clamp + Diagnostics Android-Audio Unit Verification Addendum (Wave 3 — v0.9.14)
|
|
|
|
**Background.** Wave 3 reviewer audit flagged two newly-landed test groups whose source comments cited verification IDs as `SWE4-UV-NNN` placeholders rather than real allocated anchors:
|
|
|
|
1. Three `TransmitModeSelector` permission-state tests at `crates/chanora_audio/src/transmit_selector.rs:343-435` (introduced by commit 635d160). The reviewer noted at `transmit_selector.rs:343` that these tests cite "SWE4-UV-026 family" without real IDs.
|
|
2. Two missing unit tests for the new `chanora_diagnostics` Android-audio surface (`android_audio: Option<String>` field, `with_android_audio` builder, `[audio.android]` `to_text` branch) introduced by commit aea50a1; queued for the commit-8 amend.
|
|
|
|
This addendum allocates the five required anchors. SWE4-UV-052 was the prior high-water mark; SWE4-UV-053..057 are the next free contiguous range.
|
|
|
|
**SWE4-UV-053**: Verify `TransmitModeSelector` clamps transmit to `false` when `permission_state == Denied` (or `PermanentlyDenied`/`Unknown`) regardless of PTT, channel, or transmit-mode state.
|
|
|
|
- Source SDD: SDD-106 §6
|
|
- Source SRS: SRS-209 (fail-safe listen-only default)
|
|
- Verification method: Rust unit test
|
|
- Test code path: `crates/chanora_audio/src/transmit_selector.rs::tests::permission_state_denied_clamps_transmit_to_false` (lines 348-384)
|
|
- Pass criteria: With `TransmitMode::Ptt`, `in_channel = true`, `ptt_held = true` and the default `Granted` permission state the gate evaluates `true`. Publishing `PermissionGate::Denied` flips the gate to `false`. `PermanentlyDenied` and `Unknown` likewise clamp `false`. The clamp wins over `TransmitMode::Continuous`.
|
|
- Evidence: `cargo test -p chanora_audio` result
|
|
- Notes: Establishes the fail-safe semantics: cold-launch `Unknown` is listen-only per SRS-209.
|
|
|
|
**SWE4-UV-054**: Verify `TransmitModeSelector` releases the permission clamp on transition back to `Granted` and resumes normal PTT-driven evaluation.
|
|
|
|
- Source SDD: SDD-106 §6
|
|
- Source SRS: SRS-209
|
|
- Verification method: Rust unit test
|
|
- Test code path: `crates/chanora_audio/src/transmit_selector.rs::tests::permission_state_granted_releases_clamp` (lines 389-409)
|
|
- Pass criteria: After `Denied` clamps the gate to `false`, transitioning to `PermissionGate::Granted` (with PTT held + in channel) restores the gate to `true` on the next state tick. Releasing the PTT key then drops the gate per normal PTT semantics — the clamp is no longer in effect.
|
|
- Evidence: `cargo test -p chanora_audio` result
|
|
- Notes: Pairs with SWE4-UV-053; together they cover the clamp on/off edges.
|
|
|
|
**SWE4-UV-055**: Verify `TransmitModeSelector` ignores `PermissionState` events for non-`RECORD_AUDIO` permissions (contract: bridge filters before reaching the selector).
|
|
|
|
- Source SDD: SDD-106 §5
|
|
- Verification method: Rust unit test (contract pin)
|
|
- Test code path: `crates/chanora_audio/src/transmit_selector.rs::tests::permission_state_for_other_permission_does_not_clamp` (lines 418-435)
|
|
- Pass criteria: The selector exposes no setter for non-`RECORD_AUDIO` permissions. With `TransmitMode::Continuous` + `in_channel = true` and no call to `set_permission_state`, the selector remains in its `Granted` default and the gate evaluates `true`. Demonstrates the contract that unrelated permission events (e.g. `POST_NOTIFICATIONS`) cannot reach this code path.
|
|
- Evidence: `cargo test -p chanora_audio` result
|
|
- Notes: This is a negative/contract test; the JNI bridge is responsible for filtering by permission name before invoking `set_permission_state`.
|
|
|
|
**SWE4-UV-056**: Verify `DiagnosticExport::with_android_audio(Some(yaml))` renders the `[audio.android]` section between `[metadata]` and `[recent logs]` in `to_text()`.
|
|
|
|
- Source SDD: SDD-116 item 3 (diagnostics matrix surface), SDD-112 item 10 / SDD-113 item 7 (producing crate)
|
|
- Verification method: Rust unit test
|
|
- Test code path: `crates/chanora_diagnostics/src/lib.rs::tests::android_audio_renders_between_metadata_and_logs` (to be added by commit-8 amend)
|
|
- Pass criteria: Building a `DiagnosticExport::from_sink(...)` and chaining `.with_android_audio(Some("perf: low_latency\n".into()))` produces a `to_text()` output where the substring `[audio.android]` appears (a) after the `[metadata]` header, (b) before the `[recent logs]` header, and (c) is immediately followed by the supplied YAML fragment verbatim. The YAML fragment is not re-redacted by the diagnostics bundle (SDD-090 places sanitisation in the producing crate).
|
|
- Evidence: `cargo test -p chanora_diagnostics` result
|
|
- Notes: Section ordering is part of the SDD-116 matrix contract; downstream tooling parses by header.
|
|
|
|
**SWE4-UV-057**: Verify `DiagnosticExport` with default `android_audio = None` omits the `[audio.android]` header entirely (negative test).
|
|
|
|
- Source SDD: SDD-116 item 3 (negative case — non-Android or pre-session)
|
|
- Verification method: Rust unit test
|
|
- Test code path: `crates/chanora_diagnostics/src/lib.rs::tests::android_audio_absent_omits_section` (to be added by commit-8 amend)
|
|
- Pass criteria: A `DiagnosticExport::from_sink(...)` constructed without `.with_android_audio(...)` (i.e. `android_audio == None`) produces a `to_text()` output that does **not** contain the substring `[audio.android]`. The `[metadata]` and `[recent logs]` sections remain present in order. Calling `.with_android_audio(None)` explicitly is equivalent (idempotent omission).
|
|
- Evidence: `cargo test -p chanora_diagnostics` result
|
|
- Notes: Pairs with SWE4-UV-056; together they cover the conditional-render branch in `DiagnosticExport::to_text`.
|
|
|
|
| SDD Range | SWE.4 Coverage |
|
|
|---|---|
|
|
| SDD-106 §5 | SWE4-UV-055 |
|
|
| SDD-106 §6 | SWE4-UV-053, SWE4-UV-054 |
|
|
| SDD-116 item 3 | SWE4-UV-056, SWE4-UV-057 |
|