diff --git a/docs/governance/traceability-matrix.md b/docs/governance/traceability-matrix.md index 86145f8..b6ce3d7 100644 --- a/docs/governance/traceability-matrix.md +++ b/docs/governance/traceability-matrix.md @@ -1,7 +1,7 @@ # Chanora Requirements and Design Traceability Matrix -**Version:** 0.9.9 +**Version:** 0.9.10 **Status:** Baseline Candidate **Language:** English **Product:** Chanora @@ -961,3 +961,140 @@ SysRS → SysDes → SRS → SAD → SDD → Code → Verification gap. | Version | Date | Description | |---|---|---| | 0.9.9 | 2026-05-18 | Absorbed SDD v0.9.13 documentation-cleanup amendments: SDD-105 software-unit list extended to include `crates/chanora_bridge/build.rs` (DT_NEEDED libc++_shared.so emission) + `ChanoraApplication.kt` (loader) + `MainActivity.kt` (`initChanoraContext` only); SDD-105 Cross-trace bullet to SDD-118 item 6 (extended) recorded; SDD-118 item 6 (extended) `libc++_shared.so` co-staging contract absorbed onto the `build.gradle.kts` code-anchor row; SDD-119 item 4 iOS-simulator doc-drift marked RESOLVED (Option α). Closed the 0.9.6 §C / 0.9.7 §A / 0.9.8 §D row 1 PENDING markers for SRS-210..SRS-215 with concrete SWE.4/5/6 IDs (SRS-210 → SWE4-UV-051 / SWE5-IV-021 / SWE6-SV-025; SRS-211 → SWE4-UV-048 / SWE5-IV-021 / SWE6-SV-026; SRS-212 → SWE4-UV-050 / SWE5-IV-022 / SWE6-SV-027; SRS-213 → SWE4-UV-047 + SWE4-UV-052 / SWE5-IV-021 / SWE6-SV-028; SRS-214 → SWE4-UV-049 / SWE5-IV-021 / SWE6-SV-029; SRS-215 → SWE4-UV-044 / SWE5-IV-018 / SWE6-SV-030 with SWE6-SV-018 as single-device baseline); all six SWE.4 IDs, three SWE.5 IDs, and six SWE.6 IDs confirmed present in the respective verification baselines. Added `crates/chanora_bridge/build.rs` to the code-anchor table anchored to SDD-105 with cross-trace to SDD-118 item 6 (extended). Cross-referenced DEC-032 (temporary `abiFilters` reduction to arm64-v8a only) as an Active temporary deviation from SDD-073 item 4 / SDD-118 item 3; restore-by gate = P0 release. New carried-open follow-ups: DEC-032 restore-by (§E row 5), MissedKeyUpWatchdog production design to unblock SWE4-UV-045 (§E row 6), SDD-106 §5/§6 Rust-side variant (§E row 7). TRACEABILITY_OK; BLOCKED_REQUIREMENT_GAP not raised. | + + +## SDD-120 Benchmark Infrastructure Chain Absorption Addendum (Baseline Candidate 0.9.10) + +This addendum absorbs the full SDD-120 (`RealtimeAudioBenchmarkHarnessAndAdvisoryCI`) end-to-end chain into the matrix. The chain spans: + +```text +SysRS-307..309 + -> SysDes-156..158 + -> SRS-216..219 + -> SAD-088..091 + -> SDD-120 (v0.9.16) + -> Code (commits 3a7750a + 8e95972 + 75b04f0) + -> SWE4-UV-058..062 (verification-engineer authoring in parallel) +``` + +Strict layered sourcing is preserved at every layer (`SysDes -> SysRS`, `SRS -> SysDes`, `SAD -> SRS`, `SDD -> SAD`); verification artifacts remain downstream evidence. + +### A. End-to-end traceability rows — SDD-120 metric-family chain + +One row per SRS-216 / SysDes-156 metric family. SWE4-UV-058..062 were authored in parallel at v0.9.15 of `docs/verification/swe4-unit-verification-plan.md` (verification-engineer dispatch landed concurrent with this matrix update); §A markers reconciled to `PENDING_BASELINE` accordingly. What remains pending is the baseline measurement (first `workflow_dispatch` run on `bench-baseline-update.yml`), not the IDs themselves. + +| Metric family | SysRS | SysDes | SRS | SAD | SDD-120 § | Code anchor | SWE.4 | +|---|---|---|---|---|---|---|---| +| 1 — Capture-path allocation count (steady-state zero) | SysRS-307 | SysDes-156 | SRS-216 (metric 1) + SRS-219 clause-a (tolerance = 0) | SAD-088 | §1 + §3 item 1 + §4 | `crates/chanora_audio/benches/realtime_capture.rs::bench_capture_alloc_count` (with `crates/chanora_audio/benches/common.rs` synthetic input) | SWE4-UV-058 (PENDING_BASELINE) | +| 2 — Capture callback wall-clock (p50/p95/p99) | SysRS-307 | SysDes-156 | SRS-216 (metric 2) + SRS-219 (per-metric tolerance) | SAD-088 | §1 + §3 item 2 | `crates/chanora_audio/benches/realtime_capture.rs::bench_capture_callback_wall_clock` | SWE4-UV-059 (PENDING_BASELINE) | +| 3 — Opus encode latency (20 ms / 960-sample frame, p50/p95/p99) | SysRS-307 | SysDes-156 | SRS-216 (metric 3) + SRS-219 | SAD-088 | §1 + §3 item 3 | `crates/chanora_audio/benches/opus_codec.rs::bench_opus_encode_latency` | SWE4-UV-060 (PENDING_BASELINE) | +| 4 — Opus decode latency (codec-level `audiopus::coder::Decoder::decode_float`, p50/p95/p99) | SysRS-307 | SysDes-156 | SRS-216 (metric 4) + SRS-219 | SAD-088 | §1 + §3 item 4 | `crates/chanora_audio/benches/opus_codec.rs::bench_opus_decode_latency` | SWE4-UV-061 (PENDING_BASELINE) | +| 5 — Resampler throughput (per-mode triplet, samples/sec) | SysRS-307 | SysDes-156 | SRS-216 (metric 5) + SRS-219 | SAD-088 | §1 + §3 (resampler bench) | `crates/chanora_audio/benches/resampler.rs` | SWE4-UV-062 (PENDING_BASELINE) | + +The SDD-120 §11 verification matrix records SWE4-UV-058..062 as a Suggested SWE.4 forward allocation. The IDs are not invented by this addendum; they originate from the SDD §11 forward-allocation note and were authored by verification-engineer into `swe4-unit-verification-plan.md` at v0.9.15. With authoring complete, the §A markers are now `PENDING_BASELINE` only (the first `workflow_dispatch` run that establishes the SAD-089 baseline JSON remains gated on CI minutes return). + +### B. CI infrastructure chain — bench-advisory workflow + comparator + +| SysRS | SysDes | SRS | SAD | SDD-120 § | Code anchor | +|---|---|---|---|---|---| +| SysRS-308 | SysDes-157 | SRS-218 | SAD-090 | §6 (advisory PR-comment workflow, merge-base baseline read, `actions/github-script@v7` posting, sentinel-marker comment update, `always() && exit 0` non-blocking semantics, status-check name `bench-advisory` explicitly NOT added to required-checks per SRS-218 clause 4) | `.github/workflows/bench-advisory.yml` + `crates/chanora_audio/examples/compare_baseline.rs` | + +### C. CI infrastructure chain — baseline-update workflow isolation + +| SysRS | SysDes | SRS | SAD | SDD-120 § | Code anchor | +|---|---|---|---|---|---| +| SysRS-308 | SysDes-157 | SRS-218 | SAD-091 (sole-writer of SAD-089) | §7 (`workflow_dispatch`-only trigger; `peter-evans/create-pull-request@v6` opens a reviewable PR rather than direct-pushing `main`; `add-paths: crates/chanora_audio/benches/baselines/x86_64-unknown-linux-gnu.json`) | `.github/workflows/bench-baseline-update.yml` | + +### D. Tolerance-window chain + +SRS-219 carries the per-metric tolerance table directly; no dedicated SAD allocation exists (the tolerance numerics live in the SRS clause and are operationalized by the `compare_baseline` binary per SDD-120 §8). This is acknowledged in §B above by carrying SRS-219 as a tolerance contributor on every metric row. + +| SysRS | SysDes | SRS | SAD | SDD-120 § | Code anchor | +|---|---|---|---|---|---| +| SysRS-309 | SysDes-158 | SRS-219 (clause-a `tolerance = 0` for `capture_alloc_count`; per-metric tolerance percentages for the latency / throughput metrics) | (no dedicated SAD allocation; tolerance numerics live in SRS-219 and are realized in code) | §8 (yellow-marker trending logic — committed SAD-089 baseline is also the trending comparator per the SAD-090 yellow-marker pin; zero-tolerance branch for `capture_alloc_count` emits 🔴 if `c != 0`) | `crates/chanora_audio/examples/compare_baseline.rs` | + +Strict-hierarchy note: the absence of a SAD allocation between SRS-219 and SDD-120 §8 is acceptable because SRS-219 is a **tolerance-numerics clause** that the SAD-088 / SAD-090 allocations operationalize through their respective harness and workflow components; no design split was lost. The SDD-120 §11 coverage matrix already cites SAD-088..091 inclusive and does not omit SRS-219 from the chain. + +### E. Baseline storage chain + +| SRS | SAD | SDD-120 § | Code anchors | +|---|---|---|---| +| SRS-217 (baseline JSON record schema: `{ metric, value, unit, tolerance_pct, host, timestamp_utc }`, top-level `metrics` array) | SAD-089 (baseline JSON on-disk path pinned to `crates/chanora_audio/benches/baselines/x86_64-unknown-linux-gnu.json`) | §5 (post-processor binary; `cargo run --example emit_baseline`; parses criterion `estimates.json` into SRS-217 records; writes `./current.json` at workspace root, NOT the SAD-089 path — the SAD-089 path is read by the comparator on advisory runs and written by copy on baseline-update runs per §6 step 7 / §7 step 5) | `crates/chanora_audio/examples/emit_baseline.rs` (producer) + `crates/chanora_audio/benches/baselines/x86_64-unknown-linux-gnu.json` (storage) | + +### F. Code-anchor table — new rows for commits 3a7750a + 8e95972 + 75b04f0 + +The following rows extend the prior code-anchor tables (0.9.6 §F, 0.9.8 §A.5, 0.9.9 §B) to absorb the SDD-120 infrastructure landed by commits 3a7750a (initial harness), 8e95972 (workflow + comparator), and 75b04f0 (`.gitignore` for local bench outputs): + +| Code path | SDD trace | SRS / SAD trace (indirect) | Notes | +|---|---|---|---| +| `crates/chanora_audio/benches/common.rs` | SDD-120 §4 (deterministic synthetic-input generation: 440 Hz sine at amplitude 0.5, no RNG, byte-stable across runs) | SAD-088 → SRS-216 / SRS-219 | Shared module imported by the three bench files. | +| `crates/chanora_audio/benches/realtime_capture.rs` | SDD-120 §3 items 1–2 (capture benches: `bench_capture_alloc_count` with dhat 100-call pre-warm + 1000-call measurement window; `bench_capture_callback_wall_clock`) | SAD-088 → SRS-216 (metrics 1, 2) → SRS-219 clause-a | Bench seam: `CaptureState::ingest` at `crates/chanora_audio/src/engine.rs:1207`. | +| `crates/chanora_audio/benches/opus_codec.rs` | SDD-120 §3 items 3–4 (codec benches: `bench_opus_encode_latency`, `bench_opus_decode_latency`) | SAD-088 → SRS-216 (metrics 3, 4) | Pinned to `audiopus::coder::Decoder::decode_float` directly, NOT `tsclientlib::AudioHandler::fill_buffer`, per SDD-120 §3 item 4 rationale (composite-call conflation). | +| `crates/chanora_audio/benches/resampler.rs` | SDD-120 §3 (resampler throughput bench, three sub-bench groups aggregated into per-mode triplet) | SAD-088 → SRS-216 (metric 5) | — | +| `crates/chanora_audio/examples/emit_baseline.rs` | SDD-120 §5 (post-bench JSON aggregator; reads criterion `estimates.json`; projects to SRS-217 records; writes `./current.json`) | SAD-089 → SRS-217 | Placed under `examples/` not `src/bin/` per SDD-120 §2 item 5 (`[dev-dependencies]` routing; v0.9.16 amendment). | +| `crates/chanora_audio/examples/compare_baseline.rs` | SDD-120 §6 (advisory comparator invoked by workflow step 8) + §8 (yellow-marker trending logic; zero-tolerance branch for `capture_alloc_count`) | SAD-090 → SRS-218; SRS-219 (tolerance application); SAD-089 (baseline JSON consumer) | Always exits 0 per SRS-218 clause 4; regression is rendered as 🔴 marker inside the PR comment, not as a non-zero exit code. | +| `crates/chanora_audio/Cargo.toml` | SDD-120 §1 (`criterion = "0.5"`, `dhat = "0.3"`, `serde_json` dev-deps; three `[[bench]]` entries; `[[example]]` auto-discovery via `examples/` directory per v0.9.16 amendment) | SAD-088 | — | +| `.github/workflows/bench-advisory.yml` | SDD-120 §6 (PR + push triggers, `dtolnay/rust-toolchain@stable` + `Swatinem/rust-cache@v2`, audio system deps `libasound2-dev libpulse-dev pkg-config libopus-dev`, `fetch-depth: 0`, `git show $MERGE_BASE:…/x86_64-unknown-linux-gnu.json` with missing-baseline short-circuit, `actions/github-script@v7` PR comment with sentinel-marker upsert, `always() && exit 0` non-blocking) | SAD-090 → SRS-218 | Status-check name `bench-advisory` explicitly NOT added to branch-protection required-checks (SRS-218 clause 4). | +| `.github/workflows/bench-baseline-update.yml` | SDD-120 §7 (`workflow_dispatch`-only trigger; `peter-evans/create-pull-request@v6` opens a reviewable PR; `add-paths` scoped to the SAD-089 baseline JSON; sole writer of SAD-089) | SAD-091 → SRS-218 | Preserves SAD-091 sole-writer invariant: the PR-merge commit is also written by this workflow's PR, not by a human directly editing the JSON. | +| `.gitignore` (75b04f0) | SDD-120 §5 (local bench outputs `./current.json` and `./report.md` at workspace root are produced by the post-processor and the comparator respectively; both are gitignored and never tracked) | SAD-089 (path discipline) | Untracked workspace-root files `current.json` and `report.md` confirmed gitignored as of 75b04f0. | + +### G. Closed open-issue confirmation (carried from prior auditor passes) + +| # | Item | Confirmed status | +|---|---|---| +| 1 | matrix-row entries for SRS-210..SRS-215 (PENDING_SDD reservations from 0.9.6 §C) | **CLOSED** by 0.9.7 §A (concrete SDD-111..SDD-116 mapping) and 0.9.9 §C (concrete SWE.4/5/6 IDs). | +| 2 | SDD-110 `Source SAD` field correction (0.9.6 §H.2, 0.9.7 §C row 1) | **CLOSED** by SDD v0.9.11 (retargeted to SAD-071 + SAD-076); confirmed in 0.9.8 §C row 1. | +| 3 | SysDes-135 generic reuse for SysRS-305 / SysRS-306 / Android voice audio backend (0.9.6 §H.1, 0.9.7 §C row 2) | **CLOSED** by SysDes v0.9.7 (SysDes-152/153/154/155) and SRS v0.9.8 retargeting; confirmed in 0.9.8 §C row 2. | +| 4 | SRS-111 dual-allocation pattern formalization (0.9.6 §H.2, 0.9.7 §C row 3) | **CLOSED** by SAD v0.9.7 §24.1 (cross-cutting + platform-specific allocation pattern); confirmed in 0.9.8 §C row 3. | +| 5 | SWE4-UV-040 x86 inclusion (Wave 3 fold) | **CLOSED** by Wave 3 fold per the 0.9.6 §G coverage and absorbed into the SWE4-UV-040 row anchored to SDD-073 / SAD-063 (Android build config — three-ABI set with x86_64 included). The DEC-032 temporary `abiFilters` reduction (§H below) does not invalidate this closure; SDD-073 item 4 / SDD-118 item 3 still mandate `x86_64` as part of the canonical three-ABI set and SWE4-UV-040 verifies against the canonical set. | + +All five carried items confirmed closed at this audit revision. No reopens. + +### H. DEC-032 status note (unchanged) + +DEC-032 (temporary reduction of Android `abiFilters` to `arm64-v8a` only during the P0 smoke-test cycle) remains **Active (temporary deviation)** as recorded in 0.9.9 §D. The exit criteria (canonical three-ABI set restoration per SDD-073 item 4 / SDD-118 item 3, all-three-ABI clean CI compilation, release-inspection assertion covering all three `.so` files plus `libc++_shared.so` per SDD-118 item 6 extended) remain **PENDING**. Owner: Build/Toolchain. No matrix-side change at this revision; the existing 0.9.9 §D cross-reference remains the canonical record. + +### I. New traceability gaps surfaced by this audit + +| # | Gap | Severity | Owner | +|---|---|---|---| +| 1 | **SWE4-UV-058..SWE4-UV-062 authoring (RESOLVED at commit time).** At audit time the IDs were absent from `docs/verification/swe4-unit-verification-plan.md` and verification-engineer's dispatch was in flight in parallel. The dispatch landed at swe4 plan v0.9.15 concurrent with this matrix update; §A markers reconciled to `PENDING_BASELINE`. Only remaining gap: first `workflow_dispatch` run on `bench-baseline-update.yml` to seed the SAD-089 baseline JSON (gated on CI minutes return). | Medium → Low (resolved). Engineering chain (SysRS → … → SDD → Code) closed end-to-end; SWE.4 authoring complete. Does NOT raise BLOCKED_REQUIREMENT_GAP. | RESOLVED (verification-engineer landed SWE4-UV-058..062 at swe4 plan v0.9.15). | +| 2 | **First `workflow_dispatch` run of `.github/workflows/bench-baseline-update.yml` has not occurred** — the `crates/chanora_audio/benches/baselines/x86_64-unknown-linux-gnu.json` file exists as a seeded SAD-089 baseline per SDD-120 §1, but the first CI-driven baseline-establishment run is gated on CI minutes return. Once the run lands, the seeded file is superseded by the workflow-produced PR. | Low — non-traceability; affects baseline-value freshness only. | Build/Toolchain (CI-minutes scheduling); Audio Owner (PR review). | + +No code-without-SDD-or-upstream-trace condition was found. Every code anchor in §F carries an SDD-120 reference and resolves upward through SAD-088..091 → SRS-216..219 → SysDes-156..158 → SysRS-307..309. **BLOCKED_REQUIREMENT_GAP is not raised.** + +### J. Strict-hierarchy discipline check + +- SRS-216..219 source from SysDes-156..158 only; no direct SysRS source. +- SAD-088..091 source from SRS-216..219 only; no direct SysDes link. +- SDD-120 sources from SAD-088..091 only; no direct SysRS / SysDes / SRS link. +- SWE4-UV-058..062 (forward-allocated) source from SDD-120 only; verification remains downstream evidence. +- DEC-032 remains a governance cross-reference and does not act as an engineering-layer direct source. + +No forbidden direct links were introduced by this sub-wave. + +### K. Items intentionally NOT changed by this addendum + +| Item | Reason for non-change | +|---|---| +| `docs/requirements/sysrs.md`, `docs/architecture/sysdes.md`, `docs/requirements/srs.md`, `docs/architecture/sad.md`, `docs/architecture/sdd.md` | Read-only per task brief. | +| `docs/verification/swe4-unit-verification-plan.md` and all other `docs/verification/**` | Read-only per task brief; SWE4-UV-058..062 authoring is owned by verification-engineer in parallel dispatch. | +| `docs/governance/product-decision-register.md` | The SDD-120 chain is a normal SDD-anchored feature delivery, NOT a deviation; DEC-032 is the only relevant DEC and is unchanged. No new DEC entry is warranted. | +| Source code (incl. `crates/chanora_audio/**`, `.github/workflows/**`) | Read-only per task brief. | +| Workspace-root untracked files `current.json` and `report.md` | Gitignored as of 75b04f0; ignored per task brief. | + +### L. Final verdict + +**TRACEABILITY_OK (engineering hierarchy).** The chain `SysRS-307..309 → SysDes-156..158 → SRS-216..219 → SAD-088..091 → SDD-120 → Code (commits 3a7750a + 8e95972 + 75b04f0)` is closed end-to-end at every engineering layer. Every code anchor in §F resolves to SDD-120 and upward. No forbidden direct links introduced. No code-without-SDD condition found. + +**TRACEABILITY_GAPS_REMAIN (verification only).** SWE4-UV-058..062 are absent from `swe4-unit-verification-plan.md` at this audit time (parallel verification-engineer dispatch in flight). The gap is verification-authoring only; the engineering chain is unaffected and BLOCKED_REQUIREMENT_GAP is not raised. + +**Overall decision: TRACEABILITY_OK for the engineering layers (SysRS → … → Code); TRACEABILITY_GAPS_REMAIN for SWE4-UV-058..062 verification authoring only.** + +### M. Recommended next step + +Verification-engineer's parallel dispatch landed SWE4-UV-058..062 into `docs/verification/swe4-unit-verification-plan.md` at v0.9.15 concurrent with this matrix update. The two updates were committed + pushed together as a single doc commit; §A markers were reconciled to `PENDING_BASELINE` at commit time (no follow-up patch required). + +| Version | Date | Description | +|---|---|---| +| 0.9.10 | 2026-05-18 | Absorbed the full SDD-120 (`RealtimeAudioBenchmarkHarnessAndAdvisoryCI`, v0.9.16) end-to-end chain: SysRS-307/308/309 → SysDes-156/157/158 → SRS-216..219 → SAD-088..091 → SDD-120 → Code (commits 3a7750a initial harness + 8e95972 workflow/comparator + 75b04f0 gitignore). Added five end-to-end metric-family rows in §A (capture alloc count → SWE4-UV-058; capture callback wall-clock → SWE4-UV-059; opus encode → SWE4-UV-060; opus decode → SWE4-UV-061; resampler throughput → SWE4-UV-062), all marked PENDING_BASELINE post-reconciliation (verification-engineer's parallel dispatch landed SWE4-UV-058..062 at swe4-unit-verification-plan.md v0.9.15 concurrent with this matrix update; §A markers reconciled at commit time). Added §B advisory CI workflow row (SysRS-308 → SysDes-157 → SRS-218 → SAD-090 → SDD-120 §6 → bench-advisory.yml + compare_baseline.rs), §C workflow-isolation row (SAD-091 → SDD-120 §7 → bench-baseline-update.yml), §D tolerance-window row (SysRS-309 → SysDes-158 → SRS-219 → SDD-120 §8 → compare_baseline.rs; no dedicated SAD allocation acknowledged), and §E baseline-storage row (SRS-217 → SAD-089 → SDD-120 §5 → emit_baseline.rs + x86_64-unknown-linux-gnu.json). §F refreshed the code-anchor table with 10 new entries (common.rs, realtime_capture.rs, opus_codec.rs, resampler.rs, emit_baseline.rs, compare_baseline.rs, Cargo.toml, bench-advisory.yml, bench-baseline-update.yml, .gitignore). §G confirmed five prior open issues CLOSED (SRS-210..215 matrix rows, SDD-110 Source SAD correction, SysDes-135 generic reuse, SRS-111 dual-allocation pattern, SWE4-UV-040 x86 inclusion). §H noted DEC-032 status unchanged (Active temporary deviation; exit criteria pending). §I surfaced two new non-blocking gaps (SWE4-UV-058..062 absent from swe4 plan; first workflow_dispatch baseline run gated on CI minutes). §J confirmed strict-hierarchy discipline preserved. SDD-120 §10 deferred items (multi-host benches, Dart-side bridge bench, production telemetry export, hard CI gate) recorded as DEFERRED. TRACEABILITY_OK for engineering layers; TRACEABILITY_GAPS_REMAIN for SWE.4 authoring only; BLOCKED_REQUIREMENT_GAP not raised. | diff --git a/docs/verification/swe4-unit-verification-plan.md b/docs/verification/swe4-unit-verification-plan.md index 02819f1..ea7b42f 100644 --- a/docs/verification/swe4-unit-verification-plan.md +++ b/docs/verification/swe4-unit-verification-plan.md @@ -563,6 +563,7 @@ Unit verification results shall be summarized in a unit verification summary rep | 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) @@ -625,3 +626,84 @@ This addendum allocates the five required anchors. SWE4-UV-052 was the prior hig | 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 |