Files
chanora/docs/governance/issue-history-analysis.md
T
Edison Jwa 3b13a7edb4 docs: comprehensive codebase analysis and reference documentation
Add full codebase analysis report, issue history, test environment
requirements, external research (TeaSpeak/ReSpeak/YaTQA), and offline
protocol references (ReSpeak ts3protocol, TeaSpeak, YaTQA). Add master
TODO list with 88 items across 11 categories. Add missing LICENSE files.

Branch: docs/codebase-analysis-v2
2026-06-11 09:23:10 +09:00

5.9 KiB

Issue History Analysis

Date: 2026-06-11
Scope: All git history, PRs, and issue patterns


1. Issue Categories

iOS Audio (15+ issues) — Most Problematic Area

Commit Issue Root Cause Fix
#42 (OPEN) AVAudioSession not activated before connect Auto-join spawns VPIO before session in playAndRecord mode Activate session BEFORE rust.connect
#41 iOS Debug builds blocked Debug.xcconfig missing -u flags; verify script checked wrong Mach-O Mirror Release xcconfig; check correct dylib
#38 Audio session dead after "already in channel" Server response 0x0302 treated as failure Keep session active on already-in-channel
#33 App kills other apps' audio while idle Held .playAndRecord from launch Idle baseline now .ambient; escalate during calls
#28 False underrun counters when muted peak_i16 == 0 check didn't gate on muted state Gate underrun on !muted
#26 Silero exports stripped in Xcode Archive ld -dead_strip removed unreferenced symbols -exported_symbol whitelist in xcconfigs
#10 Voice join stuck at "Connecting" Audio startup blocking connect critical path Move audio startup off connect path

Pattern: iOS AVAudioSession has 7+ interacting configuration dimensions. Each fix reveals the next layer.

Realtime Thread Safety (5+ issues)

Commit Issue Root Cause Fix
#20 Android audio output stutter Mutex contention in audio callback Oboe config tuning + lock-free callback
#27 macOS audio event queue Lock contention in render path Lock-free ArrayQueue pattern
engine.rs:39 ~39 unwrap() calls on Mutex Poisoned mutex will panic engine Need try_lock() or parking_lot::Mutex

Pattern: Realtime audio callbacks must NEVER use Mutex::lock() — always try_lock() with silence fallback.

Build Toolchain (4+ issues)

Commit Issue Root Cause Fix
#41 iOS Debug builds fail Debug.xcconfig diverged from Release Mirror Release settings in Debug
#26 Silero exports stripped ld -dead_strip + install-time strip -exported_symbol whitelist + STRIP_STYLE = non-global
#37 MSVC CRT mismatch cmake linking wrong CRT cmake-msvc-release-crt.cmd

Pattern: Always verify with xcodebuild archive, not just flutter build.

Protocol Issues (3+ issues)

Commit Issue Root Cause Fix
#16 Speaking state incorrect for non-self clients Client profiles not refreshed before mapping Refresh non-self profiles
#16 Server-query clients missing Missing protocol DTO fields Add ping deviation through full stack
#5 UI crashes on unexpected state transitions Missing null/mounted guards Guard deferred side effects

Pattern: Every protocol command should surface errors to UI — fire-and-forget hides failures.


2. PR Development Patterns

PR Summary (42 total, 34 merged, 8 closed)

Type Count Merged
Features 14 10
Bug fixes 12 12
Refactoring 4 3
Documentation 1 1
Build/Chore 4 4
Performance 1 1
Dependency 1 0
Closed (superseded) 5 0

Most Active Areas

Area PR Count Notes
iOS Audio 10+ Most recurring issues
macOS Audio 5 Lock-free architecture
Voice/VAD 6 CoreML, ONNX, WebRTC
Flutter UI 8 Event-driven, responsive
Protocol/State 5 State reducers, events

Quality Patterns

  1. Self-review via "Oracle" agent — catches real issues pre-merge
  2. Local CI mirroring — GitHub Actions billing broken
  3. PR stacking — need better branch management workflow
  4. Follow-up fix pattern — PRs stay focused

3. Test Cases for Known Issues

iOS Audio Session Lifecycle

// Test: Session activates before connect
test('voice_join activates AVAudioSession before starting voice', () async {
  // Verify session state transitions: ambient → playAndRecord → ambient
});

// Test: Already-in-channel response keeps session active
test('voice_join keeps session active on already-in-channel response', () async {
  // Mock server response code 0x0302
  // Verify session remains in playAndRecord state
});

// Test: Idle app doesn't kill other audio
test('app uses ambient mode when not in voice channel', () async {
  // Verify session mode is .ambient + .mixWithOthers when idle
});

Realtime Thread Safety

// Test: Audio callback doesn't panic on poisoned mutex
#[test]
fn audio_callback_survives_poisoned_mutex() {
    // Verify try_lock fallback produces silence, not panic
}

Protocol Error Surfacing

// Test: Server errors surface to UI
test('server error messages are forwarded as UI events', () async {
  // Mock protocol error
  // Verify UI receives error event
});

Build Verification

# Test: iOS Debug build succeeds
xcodebuild -workspace ios/Runner.xcworkspace -scheme Runner -configuration Debug build

# Test: iOS Archive build preserves Silero exports
xcodebuild archive -workspace ios/Runner.xcworkspace -scheme Runner
# Verify: nm -g archive.xcarchive/Products/Applications/Chanora.app/Chanora | grep silero

4. Root Cause Patterns

Pattern Frequency Prevention
iOS AVAudioSession lifecycle 8+ PRs Document state machine, add integration tests
Mutex on realtime threads 5+ issues Use try_lock() or parking_lot::Mutex
Xcode Archive vs build divergence 4+ issues Always test with xcodebuild archive
Silent protocol failures 3+ issues Surface all errors to UI
Platform-specific build quirks 5+ issues CI on all target platforms

Generated by git history analysis agents on 2026-06-11