Files
chanora/docs/governance/codebase-analysis-2026-06-11.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

543 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Chanora Codebase Analysis Report
**Date:** 2026-06-11
**Branch:** `docs/codebase-analysis-v2`
**Scope:** Full codebase analysis — functions, tests, documentation, dead code, duplication, architecture, external research
---
## Table of Contents
1. [Executive Summary](#1-executive-summary)
2. [Function Inventory](#2-function-inventory)
3. [Test Coverage](#3-test-coverage)
4. [Documentation Coverage](#4-documentation-coverage)
5. [Dead Code Analysis](#5-dead-code-analysis)
6. [Useless/Redundant Code](#6-uselessredundant-code)
7. [Duplicated Code](#7-duplicated-code)
8. [Document Link Coverage](#8-document-link-coverage)
9. [Git History & Issue Patterns](#9-git-history--issue-patterns)
10. [PR Analysis](#10-pr-analysis)
11. [API Gap Analysis](#11-api-gap-analysis)
12. [Crate Architecture Analysis](#12-crate-architecture-analysis)
13. [Document Staleness Analysis](#13-document-staleness-analysis)
14. [Test Environment Requirements](#14-test-environment-requirements)
15. [External Research](#15-external-research)
16. [Recommendations](#16-recommendations)
---
## 1. Executive Summary
### Key Metrics
| Metric | Value |
|--------|-------|
| **Total Rust public functions** | ~428 |
| **Total Flutter/Dart functions** | ~586 |
| **Rust test count** | 359 |
| **Flutter test count** | 221 |
| **Total test count** | 580 |
| **Overall test coverage** | 75% of modules |
| **Documentation coverage (Rust)** | 30% of functions have doc comments |
| **Documentation coverage (Flutter)** | 58% of classes documented |
| **Dead code items** | ~20 (5 definitely dead, 11 likely dead, 4 conditionally dead) |
| **Duplicated code patterns** | 10 major patterns |
| **Broken doc links** | 6 (all from missing LICENSE files) |
| **Orphaned docs** | 14 files |
| **Stale documents** | 5/8 major docs need updates |
| **PRs analyzed** | 42 (34 merged, 8 closed) |
| **Issues documented in history** | 45 significant issues |
### Critical Findings
1. **iOS audio is the #1 problem area** — 15+ issues, AVAudioSession lifecycle is the most recurring root cause
2. **chanora_audio has 168 public functions but only 24% documented** — largest crate, most complex
3. **chanora_bridge has 0 tests** — the Flutter-Rust boundary is completely untested
4. **53 SysRS requirements (SysRS-258310) lack SysDes allocation** — breaks traceability
5. **Several features exist without requirements** — poke, file transfer, hard-mute, cache
6. **engine.rs is 3,244 lines** — monolithic, needs splitting
7. **main.dart is 2,910 lines** — monolithic, needs splitting
8. **~39 production `unwrap()` calls in engine.rs** — crash risk on poisoned mutex
---
## 2. Function Inventory
### Summary by Component
| Component | Type | Total `pub fn` | Documented | Coverage |
|---|---|---|---|---|
| **chanora_core** | Rust lib | 68 | 65 | 96% |
| **chanora_audio** | Rust crate | 168 | ~40 | 24% |
| **chanora_bridge** | Rust crate | 65 | ~10 | 15% |
| **chanora_protocol** | Rust crate | 35 | 33 | 94% |
| **chanora_state** | Rust crate | 16 | ~8 | 50% |
| **chanora_storage** | Rust crate | 20 | ~12 | 60% |
| **chanora_cache** | Rust crate | 7 | 7 | 100% |
| **chanora_resolver** | Rust crate | 15 | ~8 | 50% |
| **chanora_diagnostics** | Rust crate | 27 | ~15 | 50% |
| **chanora_prefetch** | Rust crate | 7 | 4 | 57% |
| **Flutter app** | Dart | ~586 | ~5 | <1% |
### Potentially Unused Functions
Functions defined but never called from outside their module:
| Crate | Function | File:Line |
|---|---|---|
| chanora_core | `ChanoraSession::protocol_events_snapshot()` | lib.rs:788 |
| chanora_audio | `AudioEngine::capture_active()` | engine.rs:1621 |
| chanora_audio | `AudioEngine::frames_sent()` | engine.rs:1626 |
| chanora_audio | `AudioEngine::frames_received()` | engine.rs:1631 |
| chanora_audio | `HpfProcessor::process_sample()` | dsp/hpf.rs:63 |
| chanora_audio | `CoreMlWorker::reset_state()` | apple_coreml.rs:140 |
| chanora_audio | `PttCapabilityLevel::is_global()` | ptt.rs:72 |
| chanora_bridge | `handle_media_services_reset_with_route()` | api.rs:696 |
| chanora_bridge | `handle_interruption_began()` | api.rs:703 |
| chanora_state | `ServerState::replace_from_snapshot()` | lib.rs:114 |
| chanora_state | `ServerState::channel_count()` | lib.rs:148 |
| chanora_state | `ServerState::client_count()` | lib.rs:153 |
| chanora_storage | `BookmarkStore::upsert_or_add()` | lib.rs:891 |
| chanora_resolver | `normalize_args()` | lib.rs:778 |
| chanora_resolver | `validate_args()` | lib.rs:785 |
---
## 3. Test Coverage
### Summary by Component
| Component | Source Modules | Modules w/ Tests | Coverage % | Test Count |
|---|---|---|---|---|
| **chanora_audio** | 43 | 35 | 81% | 221 |
| **chanora_bridge** | 5 | 0 | **0%** | 0 |
| **chanora_cache** | 1 | 1 | 100% | 7 |
| **chanora_diagnostics** | 1 | 1 | 100% | 19 |
| **chanora_prefetch** | 1 | 1 | 100% | 6 |
| **chanora_protocol** | 4 | 2 | 50% | 23 |
| **chanora_resolver** | 1 | 1 | 100% | 14 |
| **chanora_state** | 2 | 2 | 100% | 27 |
| **chanora_storage** | 1 | 1 | 100% | 15 |
| **chanora_core** | 5 | 4 | 80% | 27 |
| **Flutter (services)** | 24 | 22 | 92% | 124 |
| **Flutter (widgets)** | 25 | 14 | 56% | 97 |
| **TOTAL** | **113** | **85** | **75%** | **580** |
### Critical Untested Areas
| Component | Module | Risk |
|---|---|---|
| **chanora_bridge** | All 5 modules | **High** — FFI boundary, zero tests |
| **Flutter widgets** | `voice_bar`, `voice_settings`, `connect_widgets` | **High** — core UI |
| **chanora_protocol** | `dto` module | **Medium** — serialization bugs |
| **chanora_core** | `events` module | **Medium** — event system |
---
## 4. Documentation Coverage
### Doc Comment Coverage (Rust)
| Crate | Functions | With Doc Comments | Coverage |
|---|---|---|---|
| chanora_core | 68 | 65 | 96% |
| chanora_audio | 168 | ~40 | 24% |
| chanora_bridge | 65 | ~10 | 15% |
| chanora_protocol | 35 | 33 | 94% |
| chanora_cache | 7 | 7 | 100% |
| chanora_state | 16 | ~8 | 50% |
| chanora_storage | 20 | ~12 | 60% |
| chanora_resolver | 15 | ~8 | 50% |
| chanora_diagnostics | 27 | ~15 | 50% |
| chanora_prefetch | 7 | 4 | 57% |
### Missing README Files
| Directory | Status |
|---|---|
| crates/chanora_audio/ | **MISSING** |
| crates/chanora_bridge/ | **MISSING** |
| crates/chanora_cache/ | **MISSING** |
| crates/chanora_diagnostics/ | **MISSING** |
| crates/chanora_prefetch/ | **MISSING** |
| crates/chanora_protocol/ | **MISSING** |
| crates/chanora_state/ | **MISSING** |
| crates/chanora_storage/ | **MISSING** |
| core/chanora_core/ | **MISSING** |
Only `crates/chanora_resolver/README.md` exists.
---
## 5. Dead Code Analysis
### Definitely Dead (safe to remove)
| Item | File:Line | Evidence |
|------|-----------|----------|
| `AudioFrame10ms` struct | frame.rs:21 | Never referenced outside tests |
| `AudioFrame20ms` struct | frame.rs:28 | Never referenced outside tests |
| `AudioFrame10ms::dbfs()` | frame.rs:58 | Never called anywhere |
| `disable_failed_vad_backend()` | audio_processing.rs:216 | Only called in tests |
| `import 'package:share_plus/share_plus.dart'` | main.dart:55 | `Share` class never used |
### Likely Dead (no production callers)
| Item | File:Line |
|------|-----------|
| `AudioEngine::output_muted()` | engine.rs:1707 |
| `AudioEngine::output_gain()` | engine.rs:1720 |
| `AudioEngine::capture_active()` | engine.rs:1621 |
| `AudioEngine::transmit_gate()` | engine.rs:1614 |
| `AudioEngine::set_transmit_active()` | engine.rs:1601 |
| `AudioEngine::android_diagnostics()` | engine.rs:1694 |
| `TransmitModeSelector::gate()` | transmit_selector.rs:253 |
| `TransmitModeSelector::in_channel()` | transmit_selector.rs:198 |
| `TransmitModeSelector::ptt_held()` | transmit_selector.rs:226 |
| `ReleaseTailTimer::cancel()` | release_tail.rs:133 |
| `ReleaseTailTimer::arm()` | release_tail.rs:70 |
### `#[allow(dead_code)]` Annotated Items
| Item | Status |
|------|--------|
| `AudioCommand::RemoveClient` | TODO: "Wire to client disconnect path" |
| `android_render_ring` module | Conditionally dead (non-Android) |
| `audio_event_queue` module | Conditionally dead (non-Android) |
| `capture_accumulator` module | Conditionally dead (non-Android) |
---
## 6. Useless/Redundant Code
### TODO/FIXME/HACK Inventory (12 entries, 14 occurrences)
| File | Line | Content |
|------|------|---------|
| engine.rs | 2348 | TODO: realtime-audio callback concern |
| mobile_voice_backend.rs | 16 | TODO(SDD-117): back-fill IosVoiceUnit |
| audio_event_queue.rs | 27 | TODO: Wire to client disconnect path |
| audio_lifecycle_service.dart | 151,156 | TODO: macosDefaultDeviceChanged (×2) |
| poke_notification_service.dart | 33-168 | TODO(event-sounds) (×10) |
### Risky Code
| Risk | Location | Count |
|------|----------|-------|
| Production `unwrap()` | engine.rs | ~39 |
| `unsafe impl Send/Sync` | Various | 8 |
| `unimplemented!("")` in FRB | frb_generated.rs | 23 |
### Complexity Warnings
| File | Lines | Risk |
|------|-------|------|
| engine.rs | 3,244 | **High** — monolithic audio engine |
| main.dart | 2,910 | **High** — monolithic Flutter entry |
| adapter.rs | 2,504 | Medium |
| api.rs | 2,432 | Medium |
---
## 7. Duplicated Code
### Major Patterns
| # | Pattern | Files | Lines Saved | Priority |
|---|---------|-------|-------------|----------|
| 1 | AudioProcessingConfig 4× construction | 1 Dart | ~50 | High |
| 2 | Audio processing toggle UI duplication | 2 Dart | ~150 | High |
| 3 | `.map_err(format!)` boilerplate | 5 Rust | ~85 closures | Medium |
| 4 | PttCapability event construction | 1 Rust | ~15 | Medium |
| 5 | DnsFailed/ServerRejected error mirroring | 2 Rust | ~20 | Medium |
| 6 | Platform detection scatter | 6 Dart | ~35 checks | Medium |
| 7 | Host normalization `trim().to_lowercase()` | 3 Rust | ~5 sites | Low |
| 8 | `create_dir_all` pattern | 2 Rust | ~3 sites | Low |
| 9 | `Io(String)` error variant | 3 Rust | ~10 | Low |
| 10 | StateEvent ↔ Delta mirror | 1 Rust | ~5 | Low |
---
## 8. Document Link Coverage
| Metric | Value |
|--------|-------|
| Total links checked | 38 |
| Valid links | 32 |
| Broken links | 6 |
| Health rate | 84.2% |
| Orphaned docs | 14 / 65 (21.5%) |
### Broken Links
All 6 broken links stem from missing `LICENSE-APACHE` and `LICENSE-MIT` files at project root.
### Orphaned Documentation (14 files)
Mostly in `docs/superpowers/plans/` and `docs/superpowers/specs/` — not linked from any index document.
---
## 9. Git History & Issue Patterns
### Issue Categories (45 significant issues)
| Category | Count | Severity |
|----------|-------|----------|
| iOS audio (AVAudioSession/VPIO) | 15+ | Most problematic |
| Realtime thread safety (Mutex) | 5+ | Cross-platform |
| Build toolchain (Xcode Archive) | 4+ | CI-blocking |
| Platform-specific build | 5+ | Cross-compilation |
| Flutter framework bugs | 3+ | Workarounds needed |
| Protocol failures | 3+ | Silent failures |
### Key Patterns
1. **iOS AVAudioSession has 7+ interacting configuration dimensions** — each fix reveals the next layer
2. **Realtime audio callbacks must NEVER use `Mutex::lock()`** — always `try_lock()` with silence fallback
3. **Always verify with `xcodebuild archive`** — not just `flutter build`
4. **Every protocol command should surface errors to UI** — fire-and-forget hides failures
---
## 10. PR Analysis
### PR Summary (42 total)
| Type | Count | Merged |
|------|-------|--------|
| Features | 15 | 7 |
| Bug fixes | 15 | 12 |
| Refactoring | 4 | 3 |
| Documentation | 1 | 1 |
| Build/Chore | 4 | 4 |
| Performance | 1 | 1 |
### Most Active Areas
| Area | PR Count |
|------|----------|
| iOS Audio | 10+ |
| macOS Audio | 5 |
| Voice/VAD | 6 |
| Flutter UI | 8 |
| Protocol/State | 5 |
### Development Patterns
- **Self-review via "Oracle" agent** — effective quality gate
- **Local CI mirroring** — GitHub Actions billing broken
- **PR stacking complexity** — need better branch management
- **Follow-up fix pattern** — PRs stay focused
---
## 11. API Gap Analysis
### Requirements with NO or Minimal Implementation
| Requirement | ID | Status |
|---|---|---|
| UI settings persistence | SysRS-143, SRS-087 | **Missing** |
| Per-user mute persistence | SysRS-145, SRS-088 | **Missing** |
| Event replay tool | SysRS-171, SRS-098 | **Missing** |
| Audio loopback test tool | SysRS-073, SRS-083 | **Missing** | SRS-083 covers both loopback and processing test tools |
| Audio processing test tool | SysRS-074, SRS-083 | **Missing** | SRS-083 shared with SysRS-073 |
| Protocol probe tool | SysRS-128, SRS-123 | **Missing** |
| Notification permission | SysRS-166, SRS-109 | **Missing** |
| Recent server management | SysRS-141, SRS-085 | **Partial** |
| Per-user volume persistence | SysRS-144, SRS-088 | **Partial** |
| Input validation | SysRS-157, SRS-094 | **Partial** |
### Missing Bridge Functions
| Capability | Gap |
|---|---|
| `is_hard_muted()` | Missing read for hard-mute state |
| `get_output_gain()` | Missing gain read-back |
| `get_client_volume()` | Missing per-client volume read |
| `connection_state()` | UI must derive from events only |
| `reconnect()` | No manual trigger |
### Hardcoded Implementations
| Location | Issue |
|---|---|
| `adapter.rs:141` | `pick_client_version()` returns Windows version for ALL platforms |
| `api.rs:350-356` | `log_file_path()` Android returns `None` |
| `chanora_storage` | `keyring_load()` on Android returns `Ok(None)` always |
---
## 12. Crate Architecture Analysis
### Current Dependency Graph
```
chanora_bridge
└─ chanora_core
├─ chanora_audio ────── chanora_protocol ───── chanora_resolver
├─ chanora_state ────── chanora_protocol
├─ chanora_storage (standalone)
├─ chanora_cache (standalone)
├─ chanora_diagnostics (standalone)
└─ chanora_prefetch ── chanora_resolver
```
**No circular dependencies.** Max depth: 3 levels.
### Crate Size
| Crate | Source Lines | Files |
|-------|-------------|-------|
| **chanora_audio** | **18,895** | 26 |
| chanora_bridge | 7,579 | 5 |
| chanora_protocol | 3,372 | 4 |
| chanora_core | 2,716 | 5 |
| chanora_state | 1,870 | 2 |
| chanora_resolver | 1,434 | 1 |
| chanora_storage | 1,332 | 1 |
| chanora_diagnostics | 1,118 | 1 |
| chanora_cache | 359 | 1 |
| chanora_prefetch | 312 | 1 |
### chanora_audio Split Recommendation
**Option A — Extract platform backends (recommended):**
| New Crate | Contents | Lines |
|---|---|---|
| `chanora_audio` (core) | engine, frame types, transmit, VAD, DSP, PTT trait | ~8,000 |
| `chanora_audio_android` | android_voice_unit, render_ring, event_queue, Oboe | ~3,200 |
| `chanora_audio_apple` | ios_voice_unit, coreaudio-rs | ~1,400 |
| `chanora_audio_desktop` | cpal, sdl_output, Windows/Linux PTT | ~3,500 |
**Rationale:** Platform backends are 100% cfg-gated. Splitting removes heavy platform dependencies from core.
### Common Code Extraction
**Not justified at this time.** Patterns are too small for a `chanora_common` crate.
---
## 13. Document Staleness Analysis
### Freshness Scores
| Document | Score | Status |
|---|---|---|
| docs/sysrs.md | 8/10 | Mostly current |
| docs/srs.md | 7/10 | Missing newer requirements |
| docs/sysdes.md | 6/10 | Missing 53 SysRS allocations |
| docs/architecture/sdd.md | 5/10 | Missing many modules |
| docs/architecture/sad.md | 5/10 | Missing components |
| docs/verification/verification-master-plan.md | 6/10 | Stale evidence source |
| docs/governance/traceability-matrix.md | 5/10 | SRS ID mismatches |
| docs/implementation-status-2026-05-28.md | 3/10 | 14 days stale |
### Critical Staleness Issues
1. **53 SysRS requirements (SysRS-258310) lack SysDes allocation** — breaks traceability
2. **Multiple features without requirements** — poke, file transfer, hard-mute, cache
3. **SRS numbering mismatches** in traceability matrix
4. **Implementation status 14 days stale** — missing v0.3.0 features
---
## 14. Test Environment Requirements
### Current CI Coverage
| Platform | CI Status |
|----------|-----------|
| Ubuntu (Rust + Flutter) | ✅ Automated |
| macOS (iOS unsigned build) | ✅ Automated |
| Android | ❌ Not in CI |
| Windows | ❌ Not in CI |
| macOS (native) | ❌ Not in CI |
| Linux (non-Ubuntu) | ❌ Not in CI |
### Physical Devices Needed
| Device | Purpose | Est. Cost |
|---|---|---|
| iPhone 14+ | iOS audio, CoreML VAD | $600-800 |
| Android phone (arm64) | Android audio, Oboe | $200-400 |
| Windows PC | Windows PTT, audio | $500-800 |
| Linux PC | GNOME/Wayland, PipeWire | $500-800 |
| Audio peripherals | USB/BT headset testing | $100 |
| **Total** | | **$2,400-4,200** |
### Implementation Roadmap
| Phase | Timeline | Focus |
|-------|----------|-------|
| Foundation | Weeks 1-4 | Android/Windows/macOS CI builds |
| Device Integration | Weeks 5-8 | Physical devices, audio loopback |
| Full Automation | Weeks 9-12 | E2E tests, audio quality, Firebase |
---
## 15. External Research
### TeaSpeak
- **Status:** Effectively unmaintained since ~2022
- **Architecture:** Closed-source server, TypeScript web client, C++ music bot
- **Lesson for Chanora:** Open-source client + formal engineering process is the right approach
- **Market validation:** TeaSpeak's abandonment creates opportunity for Chanora
### ReSpeak
- **Status:** Active, 16 repositories, tsclientlib is the core library
- **Chanora dependency:** Uses `tsclientlib` (forked) for protocol implementation
- **Key repos:** `tsclientlib` (protocol), `tsdeclarations` (protocol spec), `quicklz` (compression)
- **Recommendation:** Continue using tsclientlib, consider upstreaming p256 fix
### yat.qa (YaTQA)
- **What it is:** Windows GUI tool for TeamSpeak 3 ServerQuery management (NOT a testing/QA site)
- **Relevance:** Low — management tool, not testing framework
- **Useful resources:** Unofficial ServerQuery docs, server error codes, permission IDs, anti-flood mechanics
---
## 16. Recommendations
### P0 — Critical (do immediately)
1. **Add `chanora_bridge` tests** — 0/5 modules tested, FFI boundary is highest risk
2. **Replace `Mutex::lock().unwrap()` in engine.rs** — ~39 calls, crash risk
3. **Update implementation-status document** — 14 days stale, primary evidence source
4. **Allocate SysRS-258310 in SysDes** — breaks traceability chain
5. **Fix traceability matrix SRS numbering** — IDs don't match actual SRS
### P1 — High Priority (next sprint)
6. **Add Android/Windows/macOS CI builds** — currently only Ubuntu
7. **Add missing bridge functions**`get_hard_mute()`, `get_connection_state()`, `reconnect()`
8. **Add README files to all 8 crates + core**
9. **Split engine.rs** (3,244 lines) into smaller modules
10. **Add requirements for implemented features** — poke, file transfer, hard-mute, cache
### P2 — Medium Priority
11. **Extract platform backends from chanora_audio** — compile-time benefit
12. **Add doc comments to chanora_audio** (24% → 80% target)
13. **Fix `pick_client_version()` hardcoded to Windows**
14. **Implement per-user volume/mute persistence**
15. **Add UI settings store**
### P3 — Low Priority
16. **Clean up dead code** (25+ items)
17. **Deduplicate code patterns** (10 major patterns)
18. **Fix broken doc links** (create LICENSE files)
19. **Link orphaned documentation**
20. **Add protocol probe tool**
---
*Generated by codebase analysis agents on 2026-06-11*