Date: 2026-06-13 · Reviewers: Product Management, Business Analysis, Machine Learning, Real-Time Systems (C++), Security & Privacy · Participants: Audio DSP Engineering (knowledge base), QA Strategy, UX Guidelines, Design System
Input: PRD v0.3, requirements v0.6, backlog v2.1, architecture v0.3, prior-art.md, all delivered documentation.
Net verdict: Documentation set is SUBSTANTIALLY MATURE and INTERNALLY ALIGNED. The settled spine (control/data-plane, RT-safety rules, fidelity anchor, BRIR-first spatialization, typed-macro NL, ERB masking subset, per-stem re-sum discipline, MLX-primary separation, 4-phase roadmap) has survived full-team review with no material contradictions. However, three HIGH-CONFIDENCE blocker gaps remain that must be resolved before engineering starts: (1) ML artifact-gate signal entirely unspecified; (2) Hearing-data-at-rest hardening regressed to hand-wavy; (3) Lock-free param-bus wire protocol has no concrete type/memory-order contract. Additionally, 7 SHOULD-FIX gaps (mostly traceability and numeric specification) and ~20 POLISH items (minor clarifications, missing acceptance criteria, numeric bounds). No showstoppers; three must-fixes are resolvable in < 2 weeks.
"Documentation is largely coherent with moderate alignment drift — primarily version-update lag in PRD §0 LD table vs. architecture amendments, plus 3 orphaned Personas/goals and 2 uncovered backlog enabler spikes. No critical blockers; all high-severity gaps are traceability/pointer issues, not functional contradictions. Safe to proceed to Phase 0 engineering with the listed refinements."
"The documentation set is substantially mature and internally aligned; the settled spine is respected throughout. However, four testability/measurability gaps directly threaten acceptance-test authoring, two architectural mechanisms lack requirement anchors, and three OQs listed as open are actually already decided in architecture.md — creating stale noise that could mislead sprint planning."
"v0.3 is substantially improved from v0.2 — all five expert-panel items landed in some form — but three underspecification issues remain build-blocking in the separation pipeline, and one dangerous overclaim survived in both prior-art.md and requirements.md."
"The control-plane/data-plane spine and the RT-rules list are sound, but five implementation-blocking gaps remain — particularly in the lock-free param-bus wire protocol, IR hot-swap mechanics, and sample-rate/device-switch handling — that would force a builder to make consequential synchronization decisions not covered by the spec."
"C9's tap-as-capability landed cleanly and the LLM/cloud-allowlist intent is well-captured in prose, but the spec is not yet build-safe — the two named hardening items (hearing-data-at-rest, model-weight integrity) regressed to hand-wavy, the safety/security clamps live only as adjectives with no normative bounds, and there is no enforced 'stems-only-from-local-files' invariant — all must-fix before development."
| ID | Severity | Panel | Title | Fix | Phase Gate |
|---|---|---|---|---|---|
| BLK-1 | 🔴 Blocker | ML | Artifact-gate signal ENTIRELY UNSPECIFIED — no concrete metric, no threshold | Promote one concrete proxy signal into architecture §6 (e.g., "inter-stem energy leakage in 2–5 kHz + transient-smear index, thresholded before clamping Reimagine ceiling"). Move 6s→4s→mix fallback ladder + per-track ceiling clamp mapping from review-v0.2 into FR-STEM-05. Even if thresholds are marked "to be calibrated in SPIKE-SEP-QUALITY," the signal shape must be normative. | Phase 1 start |
| BLK-2 | 🔴 Blocker | CPP | Lock-free param-bus wire protocol UNDERDEFINED — no concrete type, width, or memory-order contract | Specify the concrete synchronization idiom by name — e.g., "triple-buffer with std::atomic<uint8_t> slot index, release-store on publish, acquire-load on consume; RT thread copies full DSPSnapshot struct by value before use; struct must be trivially copyable and fit in one cache line." Specify which memory order is required (e.g., memory_order_acquire/release). |
Phase 0 start |
| BLK-3 | 🔴 Blocker | SEC | Hearing-data-at-rest REGRESSED to hand-wavy — v0.2 P1 fix (FileVault + Keychain/Data-Protection + crypto-shred, never cloud-synced guarantee) did NOT land | Mandate Data-Protection class (key in Keychain/Secure Enclave, FileVault-at-rest assumed), crypto-shred on profile delete, explicit "never written to any iCloud/cloud-sync container" rule, resolve the backup-exclusion-vs-data-loss trade-off explicitly. Update NFR-PRIV-03 and FR-HEAR-02 with concrete mechanism names. | Phase 0 start |
| BLK-4 | 🔴 Blocker | ML | Demucs weights license OVERCLAIM in prior-art.md & requirements.md DEP-14 — still says "MIT (incl. weights)" | Change both DEP-14 and prior-art.md §4 to: "code MIT; weights NC-trained — auto-downloaded on first run, not redistributed." One-line edit in each document. This is a latent legal/compliance trap. | Pre-Phase 0 |
| BLK-5 | 🔴 Blocker | CPP | IR hot-swap (double-buffer + crossfade) mentioned in review-v0.2 but NOT in v0.3 architecture spec | Write concrete object-lifetime section: pre-allocate N=2 convolver slots at init; publish the "active slot" index atomically; the old slot is returned to the non-RT plane via SPSC retire queue; non-RT plane reloads it with new IR and re-publishes. Specify crossfade duration (~20 ms) and policy for overlapping requests. | Phase 1 start |
| BLK-6 | 🔴 Blocker | BA | FR-TONAL-03 acceptance criterion is UNTESTABLE — specifies "fraction of the equal-loudness contour difference" but never defines what fraction | Lock the fraction (e.g., "50% of ISO 226 contour difference between 83 dB SPL reference and actual playback SPL, ±cap of +12 dB"). Make SPL calibration step explicit precondition. Update band-level numbers to reflect fractional calculation. Confirm the fraction with OQ-15c resolution or as a separate founder decision. | Phase 1 start |
| BLK-7 | 🔴 Blocker | BA | FR-SPAT-01 acceptance criterion relies on undefined "statistically significant rate" ABX test with NO statistical design | Replace vague ABX clause with concrete criterion, e.g., "In a within-subjects ABX test with ≥10 listeners, ≥10 trials each, BRIR mode scores correct identification at p < 0.05 (binomial test); or equivalently, a subjective rating improvement of ≥1 point on a 5-point externalisation scale." | Phase 1 start |
| BLK-8 | 🔴 Blocker | SEC | "Hearing-safety limits" and protective clamps are ADJECTIVES, not numbers — no normative bounds anywhere | State concrete per-band gain bounds, an absolute output-SPL/true-peak ceiling that the clamp enforces post-interpretation. Make the clamp a hard FR (not prose). Verify the numeric bounds with the audio-engineering team. | Phase 0 start |
| BLK-9 | 🔴 Blocker | SEC | No integrity/signature/pinning on the FIRST-RUN model-weight download | Pin the download to a known URL + verify a hard-coded SHA-256 (ideally code-signed manifest) before load; fail closed on mismatch; document the trusted host. Add to ADR-007. | Phase 1.5 start |
| BLK-10 | 🔴 Blocker | BA | OQ-15b and OQ-15c are founder-decision blockers with no engineering path yet, but not gated in Phase 0/1 sprint plan | Promote SPIKE-OQ15BC to a mandatory Phase 1 pre-sprint gate in the epic ordering table, with a stated deadline ("must be completed before Phase 1 Sprint 1 planning"). The Open Items table already flags it "High — before profile-delta storage design," which is correct; the sprint ordering must echo that urgency. | Phase 1 start |
-
[PM-1] Persona naming inconsistent across documents (PRD A/B/C vs. backlog generic "developer"). Impact: stories reference personas inconsistently, making persona→requirement traceability unmappable. Fix: Audit all story "As a [actor]" clauses, replace generic with "Ramith/Marcus/Tom/system" per persona matrix.
-
[ML-2] MLX-vs-Core-ML path decision has no buildable decision criteria. Specify: "MLX is used unconditionally; Core ML conversion is attempted only as a pre-release optimization if MLX runtime is unavailable on target OS; fallback to mix-only (no separation) is the safe default." Add measured sec/track per hardware tier to SPIKE-SEP-QUALITY.
-
[ML-3] NL validation harness specified as an intent but has no structure. Add one paragraph describing: (a) the JSON schema that every NL interpreter output must satisfy; (b) the monotonicity smoke-test (~10 descriptor pairs that must pass before shipping); (c) reference to SPIKE-NL-VALIDATION for full calibration.
-
[CPP-3] Sample-rate change and device-switch mid-stream handling is unspecified. Specify the quiesce contract: "on device change, the AU host (non-RT) calls
kernel.prepareForReset(), which atomically setsrenderingEnabledflag to false; the render block returns silence; non-RT side reconstructs filters at new SR, publishes snapshot, re-enables rendering." -
[CPP-4] Seqlock/ring-buffer upward meter path lacks defined producer/consumer role assignment and overflow policy. State explicitly: "RT thread is sole producer; if ring is full, RT thread discards frame (non-blocking drop); UI timer reads without blocking."
-
[BA-2] FR-TONAL-05 (adaptive multi-band dynamics) maps to no architecture mechanism name. Architecture §9 says "no program DRC by default; if any, prefer dynamic EQ." FR-TONAL-05 permits the compressor in loud ambient conditions but there is no ADR or architecture section describing the dynamic-EQ vs. multiband-compressor implementation path. Add a design section for conditional dynamics.
-
[CPP-5] Audio Workgroup fan-out model for per-stem parallelism is unnamed. Name the primitive: "
os_workgroup_parallel_twithos_workgroup_parallel_start/finish; worker threads pre-created, permanently joined, signaled via atomic store +os_sync_wait_on_addresswith deadline." -
[CPP-6] Bit-exact intensity-0 bypass insertion point and SRC interaction not specified. Specify the bypass as a hard wire in render block: "if
bypassActive,memcpy(output, input, byteCount)and return; assert no SRC in chain at intensity 0." -
[CPP-7] Swift/C++ interop boundary ownership and RT-path calling convention not documented. Specify: facade is plain C header (extern "C"); ownership held by Swift AU class via
std::unique_ptrmanaged on main thread; render block receives raw (non-owning) pointer captured atallocateRenderResourcestime. -
[ML-4] NL context field-allowlist described but not enumerated. Add positive enumeration: "context MAY contain: (1) current typed macro state (numeric only); (2) active profile EQ curve (numeric); (3) Reimagine intensity (0–100); (4) device category (headphones/speakers only, not device name); (5) submitted phrase text. Context MUST NOT contain: audio, hearing profile, track identity, artist/album, listening history, user identifiers."
-
[ML-5] "~seconds/track" separation time estimate unanchored and misleading. Replace with "estimated 10–60 seconds per track depending on hardware tier and track length (to be measured in SPIKE-SEP-QUALITY); UI must show progress and allow cancellation."
-
[ML-6] Stem count per hardware tier and QualityProfile scaling unspecified. Add provisional table: "Floor (M1 Pro/AC): up to 6 stems; M1 Pro/battery or thermal-throttled: reduce to 4 stems; fallback: 2 stems before dropping to mix-only."
-
[ML-7] Reimagine knob dead-band above 0% lacks specified width. Add spec: "The dead-band spans 0–X% (exact value from user test; provisional: 5%); within this range, original mix only is rendered; stem engine activates and crossfade begins at dead-band exit."
-
[ML-8] LRU stem cache has no specified size bound. Add default bound: "LRU cache default ceiling: 4 GB (user-configurable); at ceiling, evict least-recently-played tracks first."
-
[BA-3] ADR-004 status inconsistent (Accepted vs. Proposed vs. contingent). Pick one status uniformly: "Accepted (dormant — no current RT ML workload; reserved for future use if needed)."
-
[BA-4] NFR-QUAL-02 references "MacBook Pro M3" in acceptance criterion but floor hardware is M1 Pro (LD-18). Replace "MacBook Pro M3" with "the target hardware floor (Apple-Silicon Pro-class, M1 Pro, ≥16 GB, per LD-18)."
-
[BA-5] The "imperceptible-as-motion" Phase-0 KPI gate has no acceptance criterion or verification method. Add explicit NFR or FR-ADAPT sub-criterion: e.g., "In a forced-choice listening test, fewer than 20% of listeners can identify which of two 60-second passages has adaptive parameter changes active (vs. static reference)."
-
[SEC-4] Prompt-injection via track metadata / file contents is an unaddressed threat. Classify all file-derived metadata as untrusted; never place in interpreter prompt, or sanitize+escape it.
-
[SEC-5] "Stems-only-from-local-files" is stated as intent, not enforced code invariant. Elevate to named invariant with enforcement point (separation pipeline accepts only local-file-handle source type) + test asserting tap path cannot reach separator.
-
[SEC-6] Info.plist usage-description key + min-OS still unverified. Verify exact key + min-OS in
<CoreAudio/AudioHardwareTapping.h>and record it; confirm whether tap and mic are distinct TCC services. -
[SEC-7] No update-channel / app-distribution integrity spec. State distribution/update channel; if Sparkle, require EdDSA-signed appcast; if App-Store-only, state and drop the HAL-plug-in-installer path.
-
[SEC-8] Cloud-context allowlist contradictory across docs and not enumerated. Define one canonical allowlist FR enumerating exactly what cloud
contextmay contain. -
[SEC-9] Crash-log / diagnostic leakage of user text and metadata not addressed. Add NL text + file paths/metadata to diagnostic-redaction list; gate any crash SDK on scrubbing.
-
[SEC-10] Tapped-audio "never persists" lacks transient-buffer/scratch boundary. State tap path uses only ephemeral RAM buffers, no disk/cache/temp, and excludes tapped mix from pre-analysis/transparency caches.
-
[PM-2] KPI target for Phase 1 NL "phrase success rate" (>75%) not defined operationally. Operationalize as "75% of submitted phrases that reach a confirmation card are not undone within 60 s of confirmation."
-
[PM-3] "Perceptual-domain decisions" constraint not explicitly mapped to Arbiter design. Add explicit AC to US-PERC-01: "Arbiter's masking-relief contribution computed using ERB/Bark excitation-pattern subset model per LD-12, not raw dB magnitude curve."
-
[PM-4] Phase 1.5 SPIKE-PERF-BUDGET gates the phase but is not listed in critical-path "Definition of Ready". Add note at top of Phase 1.5 in backlog.
-
[PM-5] Hearing profile "non-medical positioning" rule (LD-7) but no acceptance criterion in backlog story US-HEAR-01. Add explicit AC: "All UI copy...uses term 'listening preference', explicitly disclaims medical device status."
-
[PM-6] Reimagine knob intensity→parameter mapping curve (OQ-21) deferred but PRD hardcodes "default sits low-to-lower-mid" without numeric. Add SPIKE-REIMAGINE-MAP to backlog with concrete acceptance.
-
[PM-7] Adaptivity Signal → Decision Matrix (requirements §5) NLT row lacks "governing principle clamp" detail. Expand "Direction / Rule" column to spell out the subordination rule.
-
[PM-8] Backlog is missing explicit spikes for three open decisions (OQ-11, OQ-16, OQ-17) that block feature shipping. Create SPIKE-NLT-ARCH, SPIKE-IPREVIEW, SPIKE-LIBBS2B with each containing AC, effort estimate, and phase-gate status.
-
[PM-9] Auditing trail for LD-18 (hardware floor) impact on risk register is incomplete. Add footnote to PRD §7 Risk R-1 and R-2: "Likelihood further reduced by LD-18 (M1 Pro floor, sole-occupancy): adaptive cadence can be conservative given large compute/memory headroom."
-
[PM-10] No explicit "gates" defined between phases in backlog or PRD roadmap. Add "Phase Gates" section in backlog header defining go/no-go criteria and dependencies.
-
[BA-6] FR-ADAPT-04 (ambient sensing) and OQ-03 are in unresolved conflict. In FR-ADAPT-04, mark timing values as "provisional — subject to SPIKE-AMBNOISE output" inline.
-
[BA-7] NFR-REL-01 crash-free rate ≥99.5% has no verification method. Add parenthetical verification method: "Measured via crash-reporting SDK selected by SPIKE-TELEMETRY; a 'session' is defined as continuous app invocation from launch to quit."
-
[BA-8] FR-NLT-09 protective reduction specifies ≥−6 dB but the discomfort keyword list is never defined. Add informative normative minimum list to FR-NLT-09.
-
[BA-9] NFR-ACC-03 (Dynamic Type) has no acceptance criterion while every other NFR-ACC does. Add minimal Given/When/Then for text-size legibility test.
-
Locked decisions spine (LD-1…LD-19) are consistently threaded through all three docs. PRD §0, requirements §0, architecture §0 all cross-reference the amendments. The v0.3 → v0.6 alignment is explicit in change notes. This spine is rock-solid.
-
Stem object engine (LD-15 / FR-STEM / US-STEM-*) is coherent end-to-end. Phase 1.5 scope, acceptance, dependencies, and risks are well-defined. The re-sum mixbus (ADR-011, v0.3 amendment) is clearly traced through to US-STEM-02.
-
Conversational Tuning (FR-NLT / US-NLT-*) is fully specified at the behavioral level, even though the mechanism (OQ-11) is deferred. All phrase types map to a unified DSP action-space per LD-8. The requirements §3.9.1 phrase-mapping table is comprehensive and the backlog stories implement each row. This is production-ready despite the mechanism being TBD.
-
Privacy posture (NFR-PRIV, hearing-profile storage, mic on-demand, telemetry opt-in) is consistent across all docs. The tap-path high-consent framing (TCC + purple indicator + auto-exclude comms apps) is correctly reflected in requirements FR-SYS-07/08 and backlog US-SYSW-TAP.
-
OQ-11 deferral discipline is well-executed. All FR-NLT-* requirements are specified at the behavioral/interface level (input → output) with the mechanism explicitly excluded. The SPIKE-NLT-ARCH output specification is complete enough to unblock behavioral story authoring.
-
Reimagine intensity-0 bit-faithful anchor is thoroughly specified and consistently cross-referenced: FR-REIMAGINE-02, NFR-QUAL-03, US-RMG-01, architecture §5. This is the fidelity contract and the anchor is tight.
-
Patent/IP risk management for FR-TONAL-04 (CON-11, OQ-16, SPIKE-IPREVIEW) is handled correctly: engineering is unblocked with the mono-sum design, the release gate is explicit, the legal task is scoped, and the requirement text names the specific patent numbers. This is a model for how to manage IP risk without blocking velocity.
-
Tap consent model (C9 core) — high-consent framing, purple indicator, auto-exclude comms apps, explicit pre-prompt, graceful denial→fallback, and the "never persisted/never feeds stems" rule are all present and consistent across §13, FR-SYS-07/08, and Journey 2.6.
-
On-device-first NL posture — rules-floor → on-device-LLM-primary → cloud-opt-in-only, with monotonicity validation mandated; the privacy default (no cloud unless opted in) is correct.
-
Control-plane/data-plane spine (off-RT Realizer→RT kernel, lock-free param bus, intensity-0 bit-exact bypass, no program DRC by default, BRIR-first + exemptions, typed-macro NL, ERB masking subset, per-stem re-sum discipline, MLX-primary separation + weights download-on-first-run, 4-phase roadmap) has survived two expert-panel passes with no structural contradictions. It is the correct architecture and is ready to implement.
- BLK-4 (License): Fix DEP-14 and prior-art.md to remove "MIT (incl. weights)" overclaim.
- BLK-2 (Param-bus wire protocol): Write the concrete synchronization spec in architecture §14.
- BLK-8 (Hearing-safety bounds): Work with audio-engineering team to define numeric clamps.
- BLK-3 (Hearing-data-at-rest): Write concrete mechanism names into NFR-PRIV-03 and FR-HEAR-02.
- BLK-1 (Artifact-gate signal): Promote concrete proxy signal into architecture §6; move fallback ladder into FR-STEM-05.
- BLK-5 (IR hot-swap): Write object-lifetime section for hot-swap mechanics.
- BLK-6 (Loudness compensation fraction): Lock the fraction with audio-engineering team.
- BLK-7 (ABX test statistical design): Define the protocol (sample size, threshold, population).
- CPP-3: Specify sample-rate/device-switch quiesce contract.
- SEC-5: Define stems-only-from-local-files as enforced code invariant.
- All PM/BA SHOULD-FIX traceability items: Update personas, phase gates, OQ-15bc gating, SPIKE shortlist.
- BLK-10 (OQ-15bc): Promote SPIKE-OQ15BC to mandatory Phase 1 pre-sprint gate.
- All ML SHOULD-FIX items (MLX/Core ML decision tree, NL validation harness structure, stem count tiers, NL context allowlist).
- All CPP POLISH items (Workgroup primitive naming, Swift/C++ interop boundary, QualityProfile scaling policy).
- UX & Design System reviews (cross-check with ux-guidelines.md and design-system.md).
- BLK-9 (Model-weight download integrity): Implement SHA-256 pinning and fail-closed verification.
- All remaining POLISH items (accept as tech-debt for post-Phase-0 refinement).
- All OQ resolutions that are not pre-conditions (e.g., OQ-21 on Reimagine mapping curve, OQ-22 on masking SPIKE output).
-
For Engineering Team: Use the Blocker and Should-Fix sections as a checklist. Each item names the exact section/FR to update and the fix required. Work through blockers in the order listed; should-fixes before Phase kickoff.
-
For Product / Architecture: The Polish section and the "Solid Spine" section are for context and confidence. The solid spine should be protected as the invariant structure; the polish items can be batch-updated over time.
-
For QA/Testing: Read the new test-and-qa-strategy.md document. It defines the signal-correctness test catalog, RT-safety verification, and phase gates. Use this to author test plans and acceptance criteria.
-
For UX/Design: Read the new ux-guidelines.md and design-system.md documents. They define the interaction standards and visual tokens that the implementation must satisfy.
-
For Next Review Round: This review-v0.3.md will be superseded once the blocker and should-fix items are resolved. Plan a v0.4 review round after fixes are merged, focusing on the updated requirement/architecture consistency and the design-system implementation plan.