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
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
# 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
|
||||
|
||||
```dart
|
||||
// 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
|
||||
|
||||
```rust
|
||||
// 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
|
||||
|
||||
```dart
|
||||
// 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
|
||||
|
||||
```bash
|
||||
# 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*
|
||||
Reference in New Issue
Block a user