Files
chanora/docs/verification/swe4-unit-verification-plan.md
T
EdisonJwa 92087d066a docs(verification,traceability): SWE4-UV-058..062 for SDD-120 benches + matrix absorption
Closes the SDD-120 §11 verification-engineer follow-up and refreshes the
traceability matrix to incorporate the full benchmark-infrastructure
chain landed in commits 3a7750a / 8e95972 / 75b04f0.

swe4-unit-verification-plan.md v0.9.14 → v0.9.15:
- SWE4-UV-058: bench_capture_alloc_count (SDD-120 §3; SRS-216 metric 1;
  SRS-219 clause a zero-tolerance).
- SWE4-UV-059: bench_capture_callback_wall_clock (metric 2; SRS-219 b
  +20% p95).
- SWE4-UV-060: bench_opus_encode_latency (metric 3; SRS-219 c +15% mean).
- SWE4-UV-061: bench_opus_decode_latency (metric 4; SRS-219 c +15% mean).
- SWE4-UV-062: bench_resampler_throughput (metric 5; SRS-219 d -10%
  samples/sec).
All five status PENDING_BASELINE until the first manual
bench-baseline-update.yml dispatch establishes baselines.

traceability-matrix.md v0.9.9 → v0.9.10:
- 9 new chain rows binding SysRS-307..309 → SysDes-156..158 →
  SRS-216..219 → SAD-088..091 → SDD-120 sections → code anchors →
  SWE4-UV-058..062.
- 10 new code-anchor rows for the benchmark files (benches/{common,
  realtime_capture,opus_codec,resampler}.rs + examples/{emit,compare}
  _baseline.rs + Cargo.toml + bench-advisory.yml +
  bench-baseline-update.yml + .gitignore).
- 5 §A markers reconciled to PENDING_BASELINE (the SWE.4 IDs are now
  authored; what remains pending is the baseline measurement).
- DEC-032 (abiFilters reduction) status unchanged; exit criteria
  pending.
- All 5 prior open issues from earlier wave audits confirmed closed.

Verdict: TRACEABILITY_OK (engineering chain closed end-to-end). Only
remaining gap: PENDING_BASELINE, gated on CI minutes return + manual
workflow_dispatch on bench-baseline-update.yml.
2026-05-18 14:15:04 +08:00

45 KiB
Raw Blame History

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.

SysRS -> SysDes -> SRS -> SAD -> SDD -> SWE.4 Unit Verification

Direct source rule:

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.
0.9.15 2026-05-18 Closed SDD-120 §11 verification-engineer follow-up: allocated SWE4-UV-058 through SWE4-UV-062 anchoring the five realtime-audio bench functions landed in commit 3a7750a (bench_capture_alloc_count and bench_capture_callback_wall_clock in crates/chanora_audio/benches/realtime_capture.rs; bench_opus_encode_latency and bench_opus_decode_latency in crates/chanora_audio/benches/opus_codec.rs; bench_resampler_throughput in crates/chanora_audio/benches/resampler.rs) and feeding the SRS-216 metric families under the SRS-219 per-metric tolerance windows. Status PENDING_BASELINE: pass/fail evaluation cannot proceed until the first bench-baseline-update.yml workflow_dispatch invocation lands the SAD-089 baseline JSON; once landed, the SDD-120 §6 bench-advisory.yml workflow plus examples/compare_baseline perform automated 🔴/🟡/🟢 evaluation against the merge-base baseline snapshot. Strict-layered sourcing preserved (SWE.4 -> SDD/SRS only); no SDD, SRS, SAD, SysDes, or SysRS edits performed.

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

13. Realtime-Audio Benchmark-Harness Unit Verification Addendum (SDD-120 §11 closure — v0.9.15)

Background. SDD-120 (RealtimeAudioBenchmarkHarnessAndAdvisoryCI, v0.9.16) §11 explicitly defers the SWE.4 allocation for the five bench functions it specifies in §3, noting: "Suggested SWE.4 forward allocation: SWE4-UV-058 through SWE4-UV-062 (verification-engineer follow-up; not authored by this SDD unit)." Commit 3a7750a landed the implementation across three bench files plus two examples/ post-processor binaries. This addendum closes the §11 follow-up by authoring the five anchors. SWE4-UV-057 was the prior high-water mark; SWE4-UV-058..062 are the next free contiguous range.

Status conventions. All five items are marked PENDING_BASELINE: pass/fail evaluation requires a committed SAD-089 baseline JSON for the active host triple (x86_64-unknown-linux-gnu), which is produced only by the SDD-120 §7 bench-baseline-update.yml workflow_dispatch workflow. Until that workflow has been dispatched at least once and its PR merged, the SDD-120 §6 bench-advisory.yml short-circuits on missing baseline (per SRS-218 clause 4 always-success) and these verification items cannot return 🟢/🟡/🔴. Automated comparison thereafter is performed by crates/chanora_audio/examples/compare_baseline.rs (invoked via cargo run --example compare_baseline) against the merge-base baseline per SRS-219.

SWE4-UV-058: Verify the realtime capture path performs zero heap allocations per callback after the warmup window.

  • Source SDD: SDD-120 §3 (bench function bench_capture_alloc_count with 100-callback warmup before the dhat measurement window); SDD-120 §8 (zero-tolerance metric collapses to 🔴/🟢 only — no 🟡 band).
  • Source SRS: SRS-216 metric 1 (heap allocation count per realtime callback after warmup); SRS-219 clause a (zero tolerance — "any non-zero allocation count on a PR is flagged 🔴").
  • Verification method: Criterion bench with dhat global allocator. Invocation: cargo bench --bench realtime_capture -- bench_capture_alloc_count.
  • Test code path: crates/chanora_audio/benches/realtime_capture.rs::bench_capture_alloc_count (line 27).
  • Pass criteria: After a 100-call CaptureState::ingest pre-warm (per SDD-120 §3), the dhat HeapStats.total_blocks delta across the subsequent 1000 CaptureState::ingest calls SHALL equal zero. Any non-zero count is a 🔴 regression per SRS-219 clause a (zero tolerance).
  • Acceptance evidence: dhat global-allocator HeapStats.total_blocks delta == 0 captured by the bench; criterion estimates.json projected into the SRS-217 baseline schema by examples/emit_baseline; advisory marker rendered by examples/compare_baseline against the merge-base baseline.
  • Cross-trace: SAD-088 (benchmark-instrumentation seam), SDD-094 (audio-engine lifecycle as the bench-seam container).
  • Status: PENDING_BASELINE (zero-tolerance metric — first baseline run establishes the binary 🟢/🔴 evaluation; subsequent runs gate on any non-zero allocation regardless of baseline value).

SWE4-UV-059: Verify the realtime capture callback wall-clock stays within the SRS-219 p95 tolerance.

  • Source SDD: SDD-120 §3 (bench function bench_capture_callback_wall_clock with criterion default warmup; measurement reports p50/p95/p99 as a fraction of the cpal stream period).
  • Source SRS: SRS-216 metric 2 (per-callback wall-clock at p50/p95/p99 as a fraction of cpal stream period); SRS-219 clause b ("per-callback wall-clock duration at p95 — tolerance is +20% relative to the baseline (p50 and p99 are advisory data only and do not drive the 🔴 marker)").
  • Verification method: Criterion timing bench. Invocation: cargo bench --bench realtime_capture -- bench_capture_callback_wall_clock.
  • Test code path: crates/chanora_audio/benches/realtime_capture.rs::bench_capture_callback_wall_clock (line 95).
  • Pass criteria: p95 wall-clock per callback SHALL stay within +20% of the baseline-at-merge-base per SRS-219 clause b. p50 and p99 are reported but advisory only (no tolerance gate; cannot drive 🔴). Automated 🟢/🟡/🔴 evaluation by examples/compare_baseline per SDD-120 §8 (🔴 if delta_pct > 20%, 🟡 if 10% < delta_pct ≤ 20%, 🟢 otherwise).
  • Acceptance evidence: criterion p95 estimate from target/criterion/.../estimates.json projected through examples/emit_baseline; advisory marker rendered by examples/compare_baseline.
  • Cross-trace: SAD-088, SDD-094.
  • Status: PENDING_BASELINE.

SWE4-UV-060: Verify Opus encode latency on a 960-sample / 20 ms frame stays within the SRS-219 mean tolerance.

  • Source SDD: SDD-120 §3 (bench function bench_opus_encode_latency exercising audiopus::coder::Encoder::encode_float directly, not through tsclientlib::AudioHandler, to isolate encode latency from higher-layer mix/jitter handling).
  • Source SRS: SRS-216 metric 3 (Opus encode latency on 960-sample/20 ms frame); SRS-219 clause c ("Opus encode latency on a 960-sample / 20 ms frame — tolerance is +15% relative to the baseline on the mean").
  • Verification method: Criterion timing bench. Invocation: cargo bench --bench opus_codec -- bench_opus_encode_latency.
  • Test code path: crates/chanora_audio/benches/opus_codec.rs::bench_opus_encode_latency (line 21).
  • Pass criteria: encoder.encode_float() mean latency on a 960-sample (20 ms @ 48 kHz mono) deterministic-sine frame SHALL stay within +15% of the baseline-at-merge-base per SRS-219 clause c. Automated 🟢/🟡/🔴 evaluation by examples/compare_baseline per SDD-120 §8 (🔴 if delta_pct > 15%, 🟡 if 7.5% < delta_pct ≤ 15%, 🟢 otherwise).
  • Acceptance evidence: criterion mean estimate from target/criterion/.../estimates.json projected through examples/emit_baseline; advisory marker rendered by examples/compare_baseline.
  • Cross-trace: SAD-088, SDD-094.
  • Status: PENDING_BASELINE.

SWE4-UV-061: Verify Opus decode latency on a 20 ms Opus frame stays within the SRS-219 mean tolerance.

  • Source SDD: SDD-120 §3 (bench function bench_opus_decode_latency exercising audiopus::coder::Decoder::decode_float directly, not tsclientlib::AudioHandler::fill_buffer; SDD-120 §3 pinned this explicitly because the AudioHandler path conflates Opus decode with jitter-buffer dequeue and PCM mix).
  • Source SRS: SRS-216 metric 4 (Opus decode latency on 960-sample/20 ms frame); SRS-219 clause c ("Opus decode latency on a 960-sample / 20 ms frame — tolerance is +15% relative to the baseline on the mean").
  • Verification method: Criterion timing bench. Invocation: cargo bench --bench opus_codec -- bench_opus_decode_latency.
  • Test code path: crates/chanora_audio/benches/opus_codec.rs::bench_opus_decode_latency (line 37).
  • Pass criteria: decoder.decode_float() mean latency on a single 20 ms (960-sample @ 48 kHz mono) Opus-encoded frame SHALL stay within +15% of the baseline-at-merge-base per SRS-219 clause c. Automated 🟢/🟡/🔴 evaluation by examples/compare_baseline per SDD-120 §8 (🔴 if delta_pct > 15%, 🟡 if 7.5% < delta_pct ≤ 15%, 🟢 otherwise).
  • Acceptance evidence: criterion mean estimate from target/criterion/.../estimates.json projected through examples/emit_baseline; advisory marker rendered by examples/compare_baseline.
  • Cross-trace: SAD-088, SDD-094.
  • Status: PENDING_BASELINE.

SWE4-UV-062: Verify resampler throughput on the three canonical rate pairs stays within the SRS-219 samples-per-second tolerance.

  • Source SDD: SDD-120 §3 (bench function bench_resampler_throughput structured as a criterion BenchmarkGroup with three sub-benches: 44.1 kHz → 48 kHz, 16 kHz → 48 kHz, and 48 kHz → 48 kHz passthrough).
  • Source SRS: SRS-216 metric 5 (resampler throughput on canonical rate pairs); SRS-219 clause d ("resampler throughput on the canonical rate pairs — tolerance is 10% relative to the baseline on samples-per-second (i.e. a throughput drop greater than 10% is flagged 🔴)").
  • Verification method: Criterion throughput bench. Invocation: cargo bench --bench resampler -- bench_resampler_throughput.
  • Test code path: crates/chanora_audio/benches/resampler.rs::bench_resampler_throughput (line 17).
  • Pass criteria: Each of the three sub-benches (44.1→48, 16→48, 48→48-passthrough) samples-per-second throughput SHALL stay no worse than 10% of the baseline-at-merge-base per SRS-219 clause d. A throughput drop greater than 10% on any of the three sub-benches is a 🔴 regression. Automated 🟢/🟡/🔴 evaluation by examples/compare_baseline per SDD-120 §8 (🔴 if delta_pct < 10%, 🟡 if 10% ≤ delta_pct < 5%, 🟢 otherwise; note the sign inversion versus latency metrics — for throughput, a decrease is the regression direction).
  • Acceptance evidence: criterion samples-per-second estimates from target/criterion/.../estimates.json for each of the three sub-benches projected through examples/emit_baseline; advisory marker rendered by examples/compare_baseline.
  • Cross-trace: SAD-088, SDD-094.
  • Status: PENDING_BASELINE.

13.1 SDD-120 Coverage Index

SDD Range SWE.4 Coverage Tolerance Source
SDD-120 §3 (bench bench_capture_alloc_count) SWE4-UV-058 SRS-219 clause a (zero-tolerance)
SDD-120 §3 (bench bench_capture_callback_wall_clock) SWE4-UV-059 SRS-219 clause b (+20% p95)
SDD-120 §3 (bench bench_opus_encode_latency) SWE4-UV-060 SRS-219 clause c (+15% mean)
SDD-120 §3 (bench bench_opus_decode_latency) SWE4-UV-061 SRS-219 clause c (+15% mean)
SDD-120 §3 (bench bench_resampler_throughput) SWE4-UV-062 SRS-219 clause d (10% samples/sec)

13.2 SWE4-UV-058..062 Status Index

SWE.4 ID Bench function Bench file Tolerance Status
SWE4-UV-058 bench_capture_alloc_count crates/chanora_audio/benches/realtime_capture.rs zero PENDING_BASELINE
SWE4-UV-059 bench_capture_callback_wall_clock crates/chanora_audio/benches/realtime_capture.rs +20% p95 PENDING_BASELINE
SWE4-UV-060 bench_opus_encode_latency crates/chanora_audio/benches/opus_codec.rs +15% mean PENDING_BASELINE
SWE4-UV-061 bench_opus_decode_latency crates/chanora_audio/benches/opus_codec.rs +15% mean PENDING_BASELINE
SWE4-UV-062 bench_resampler_throughput crates/chanora_audio/benches/resampler.rs 10% samples/sec PENDING_BASELINE