---
type: reference
title: "CAMDOM — Code Quality, Patterns & Technical Debt"
description: "Code review: quality metrics, naming conventions, structural patterns, error handling, code duplication, type safety, technical debt, commit analysis."
tags: [camdom, code-review, quality, technical-debt, patterns, post-mortem]
timestamp: "2026-07-20"
---

# CAMDOM — Code Quality, Patterns & Technical Debt

## Project Overview

| Metric | Value |
|--------|-------|
| **Total Commits** | 429 |
| **Date Range** | 2024-06-06 to 2025-11-16 (17 months) |
| **Contributors** | 6 (alefita: 142, GitHub Action: 116, alefita-p4b: 90, Mikael: 46, Alef Oliveira: 22, Victor: 8) |
| **Total Source Lines** | ~8,967 (TypeScript + Kotlin + Swift) |
| **TypeScript Strict Mode** | Enabled |
| **Test Coverage** | 0% — No test files exist |

---

## 1. Code Quality Metrics

### File Sizes (Largest to Smallest)

| Rank | File | Lines | Category |
|------|------|-------|----------|
| 1 | `modules/ble-manager/src/BleManager.ts` | **1,877** | BLE Logic (God Object) |
| 2 | `app/index.tsx` | **918** | Main UI Screen |
| 3 | `modules/ble-manager/android/.../BleManager.kt` | **753** | Android Native BLE |
| 4 | `modules/ble-manager/android/.../BlePeripheralManager.kt` | **452** | Android Peripheral |
| 5 | `modules/ble-manager/ios/BlePeripheralManager.swift` | **273** | iOS Peripheral |
| 6 | `utils/i18n.ts` | **247** | Internationalization |
| 7 | `app/onboarding.tsx` | **246** | Onboarding UI |
| 8 | `components/Menu/MenuList.tsx` | **237** | Menu Component |
| 9 | `utils/Animations.ts` | **164** | Animation Engine |
| 10 | `components/Menu/MenuTitle.tsx` | **159** | Menu Title |

**Critical Finding:** `BleManager.ts` at 1,877 lines is **25.9% of all TypeScript source code**. This is a textbook god object antipattern.

### TypeScript `any` Usage

| Type | Count | Location |
|------|-------|----------|
| Explicit `any` type annotations | 5 | `BleManager.ts:873,886,892` (event handler) |
| `as any` type casts | 3 | `BleManager.ts` (event casting) |
| **Total `any` violations** | **8** | All in `BleManager.ts` |

Lines with `any`:
- Line 873: `emit(name: EventNames, ...args: any[])`
- Line 885: `(event as any).value.data`
- Line 892: `(event as any).value`

### TODO/FIXME/HACK Markers

| File | Line | Marker | Content |
|------|------|--------|---------|
| `BleManager.kt` | 319 | `TODO` | timeout timer: if callback not called - disconnect, wait 120ms, close |
| `BleManager.kt` | 329 | `TODO` | bonding state |
| `BleManager.kt` | 344 | `TODO` | random error 133 - close and try reconnect |
| `BleManager.kt` | 391 | `WARN` | characteristic not found $CHAR_FOR_INDICATE_UUID |

**Analysis:** All TODOs are in the Android native layer, indicating incomplete BLE error recovery. The error 133 handler (line 344) is a known Android BLE issue that remains unimplemented.

### Commented-Out Code Blocks

| File | Lines | Count | Feature |
|------|-------|-------|---------|
| `BleManager.ts` | 587-589 | 3 | Debug logging for device scan |
| `BleManager.ts` | 1106-1113 | 8 | RSSI proximity sensor activation |
| `BleManager.ts` | 1198-1205 | 8 | RSSI proximity sensor activation (duplicate) |
| `BleManager.ts` | 1268-1275 | 8 | RSSI proximity sensor activation (duplicate) |
| `BleManager.ts` | 1463-1468 | 6 | Proximity notification UI |
| `BleManager.ts` | 1483-1491 | 9 | RSSI notification handler |
| `BleManager.ts` | 1799-1804 | 6 | Client RSSI packet sending |
| `BleManager.ts` | 1814-1849 | 36 | Server RSSI processing + alarm firing |
| `BleManager.ts` | 1868-1870 | 3 | RSSI timeout configuration |
| `Options.tsx` | 117-144 | 28 | Sign out + Delete account buttons |
| **Total** | | **~115** | |

**Critical Finding:** 109 lines of commented-out code in `BleManager.ts` alone. The RSSI proximity feature is **completely disabled** but remains as zombie code. The `Options.tsx` file has commented-out authentication features (sign out, delete account).

### Magic Numbers vs Named Constants

| Magic Number | Location | Context | Should Be |
|--------------|----------|---------|-----------|
| `125`, `124`, `126`, `249`, `251` | BleManager.ts:499-507 | Advertising value ranges | Named constants for iOS/Android ranges |
| `53` | BleManager.ts:909 | MTU request size | `const MTU_SIZE = 53` |
| `8` | BleManager.ts:438 | Session ID substring length | `const SESSION_ID_LENGTH = 8` |
| `7500` | BleManager.ts:768 | Scanning timeout ms | `const SCAN_TIMEOUT_MS = 7500` |
| `500` | BleManager.ts:1001 | Server disconnection poll interval | `const DISCONNECT_POLL_MS = 500` |
| `3500` | BleManager.ts:1114 | RSSI reader delay | `const RSSI_DELAY_MS = 3500` |
| `300` | BleManager.ts:981 | Connection sleep delay | `const CONNECTION_DELAY_MS = 300` |
| `15` | BleManager.ts:1803,1848 | RSSI tick rate | `const RSSI_TICK_MS = 15` |
| `5` | BleManager.ts:1859 | RSSI history buffer size | `const RSSI_BUFFER_SIZE = 5` |
| `10` | BleManager.ts:601 | iOS scan retry limit | `const IOS_SCAN_RETRY_LIMIT = 10` |
| `1800` | BleManager.ts:1514 | Ping pong timeout | `const PING_PONG_TIMEOUT_MS = 1800` |
| `600` | BleManager.ts:1523 | Disconnect acknowledgment delay | `const DISCONNECT_ACK_MS = 600` |
| `1500` | BleManager.ts:1296 | Client disconnect timeout | `const CLIENT_DISCONNECT_TIMEOUT_MS = 1500` |

**Result:** 13+ magic numbers identified. Zero named constants for timing/range values.

---

## 2. Naming Conventions Analysis

### TypeScript Conventions

| Pattern | Status | Examples |
|---------|--------|----------|
| camelCase functions | **PASS** | `startScanning()`, `stopAdvertising()`, `handlePacketFromServer()` |
| PascalCase components | **PASS** | `LateralMenu`, `Options`, `MenuList`, `MenuTitle` |
| PascalCase interfaces | **PASS** | `UISharedValues`, `EventBase`, `EventWithPayload` |
| SCREAMING_SNAKE constants | **PARTIAL** | `SERVICE_UUID`, `CHAR_FOR_READ_UUID` (BLE UUIDs only) |
| Boolean naming with `is/has` | **PASS** | `isScanning`, `isConnecting`, `isServer`, `hasConnectionError` |

**Issues Found:**
- `AvailablePositions` type at line 53: `"center" | "center" | "center"` — duplicate union members (likely a bug or dead code)
- `randomIntFromInterval` (line 491) — should be `getRandomInt` or `randomInt`
- `PacketToSoundsMapper` and `SoundsToPacketMapper` — inconsistent naming (one uses `To`, other uses `ToPacket`)

### Cross-Language Consistency (TS → Kotlin → Swift)

| Concept | TypeScript | Kotlin | Swift |
|---------|------------|--------|-------|
| BLE Manager | `BleManager` | `BleManager` | `BlePeripheralManager` |
| Service UUID | `SERVICE_UUID` | `SERVICE_UUID` | `SERVICE_UUID` |
| Characteristic UUID | `CHAR_FOR_READ_UUID` | `CHAR_FOR_READ_UUID` | `CHAR_FOR_INDICATE_UUID` |
| Broadcast packet | `broadcastPacket()` | `broadcastPacket()` | `broadcastPacket()` |
| Send to client | `sendPacketToClient()` | `sendPacketToClient()` | — |

**Finding:** Naming is largely consistent across languages. The iOS implementation uses `BlePeripheralManager` instead of `BleManager`, which is a minor inconsistency but semantically accurate (iOS focuses on peripheral role).

---

## 3. Structural Patterns

### The "God Object" Problem — BleManager.ts

`BleManager.ts` at 1,877 lines contains:

| Responsibility | Lines | Methods |
|----------------|-------|---------|
| BLE state management | ~200 | 15+ private state variables |
| Sound effects | ~80 | `bindSoundEffects()`, `playSound()` |
| Event listeners | ~230 | `bindListeners()` |
| Scanning logic | ~180 | `startScanning()`, `stopScanning()`, `configureScanTimeout()` |
| Connection management | ~150 | `registerClientCallbacks()`, `disconnectFromServer()` |
| Packet handling (server) | ~220 | `handlePacketFromClient()` |
| Packet handling (client) | ~200 | `handlePacketFromServer()` |
| UI interactions | ~180 | `onDisconnectPressStart()`, `onDisconnectPressFinish()`, `onStopAlarmPressStart()` |
| RSSI proximity (disabled) | ~80 | `configureClientRSSITimeout()`, `configureServerRSSITimeout()` |
| Storage initialization | ~10 | Constructor |

**Recommendation:** Split into:
1. `BleConnectionManager` — scanning, connecting, disconnecting
2. `BlePacketHandler` — packet parsing and routing
3. `BleSoundManager` — audio effects
4. `BleRssiMonitor` — proximity detection (currently disabled)
5. `BleStateManager` — SharedValue management

### Module Separation

```
modules/
├── ble-manager/           # BLE native module (Expo Module)
│   ├── src/               # TypeScript layer
│   │   ├── BleManager.ts  # 1,877 lines — GOD OBJECT
│   │   ├── Events.types.ts
│   │   ├── Utils.ts
│   │   └── BleManagerModule.ts
│   ├── android/           # Kotlin implementation
│   │   └── src/main/java/p4b/modules/blemanager/
│   │       ├── BleManager.kt (753 lines)
│   │       ├── BlePeripheralManager.kt (452 lines)
│   │       └── BleManagerModule.kt (56 lines)
│   └── ios/               # Swift implementation
│       ├── BlePeripheralManager.swift (273 lines)
│       └── BleManagerModule.swift (42 lines)
├── app/                   # UI screens
│   ├── index.tsx (918 lines)
│   └── onboarding.tsx (246 lines)
├── components/            # Reusable UI
│   ├── LateralMenu/       # 6 files
│   └── Menu/              # 7 files
├── hooks/                 # Custom React hooks
│   └── useLateralMenu.tsx
└── utils/                 # Utilities
    ├── Animations.ts      # Generator-based animation engine
    ├── i18n.ts
    └── requestPermissions.ts
```

**Issues:**
- No clear separation between UI and business logic
- `app/index.tsx` at 918 lines is also oversized
- No service layer or repository pattern
- BLE protocol logic mixed with UI state management

### File Naming Conventions

| Pattern | Status | Examples |
|---------|--------|----------|
| PascalCase components | **PASS** | `LateralMenu.tsx`, `Options.tsx`, `MenuList.tsx` |
| camelCase hooks | **PASS** | `useLateralMenu.tsx` |
| camelCase utilities | **PASS** | `Animations.ts`, `i18n.ts`, `requestPermissions.ts` |
| PascalCase classes | **PASS** | `BleManager.ts` |
| Consistent extensions | **PASS** | `.tsx` for components, `.ts` for logic |

---

## 4. Error Handling Audit

### Try/Catch Blocks in BleManager.ts

| Line | Context | Handling Quality |
|------|---------|------------------|
| 194-206 | `Audio.setAudioModeAsync()` | **POOR** — Sets `isAudioModeSet = false` but no user feedback |
| 511-521 | `startAdvertising()` | **POOR** — Silently retries permissions, no error propagation |
| 649-673 | `device.connect()` | **GOOD** — Logs error, updates UI state, sets `hasConnectionError` |
| 794-797 | `connectedDevice.cancelConnection()` | **POOR** — Empty catch: `//ignore` |
| 824-865 | `sendPacketToServer()` | **GOOD** — Logs error, disconnects, updates UI |
| 928-955 | `monitorCharacteristicForService()` | **POOR** — Updates UI but no error logging |

**Total catch blocks:** 6
**Empty/ignoring catch blocks:** 1 (`cancelConnection`)
**Silent failures:** 2 (`setAudioModeAsync`, `startAdvertising`)

### Missing Error Handling

| Location | Risk |
|----------|------|
| `bindSoundEffects()` (line 177) | No catch — if audio files fail to load, `isSoundsLoaded` stays false |
| `registerClientCallbacks()` (line 902) | No catch on `discoverAllServicesAndCharacteristics()` |
| `handlePacketFromServer()` (line 1327) | No validation of packet format before parsing |
| `handlePacketFromClient()` (line 1529) | No validation of `packet.data` format |
| `playSound()` (line 217) | No catch on `setVolume()` or `replayAsync()` |

### Error Propagation Pattern

```
Native Module Error
    ↓
TypeScript Event Emitter
    ↓
BleManager Event Handler
    ↓
SharedValue UI State Update
    ↓
React Component Re-render
    ↓
Snackbar.show() (optional)
```

**Issues:**
- Errors are swallowed in 33% of catch blocks
- No centralized error handling or error boundary
- User-facing errors only shown via Snackbar (no retry mechanism)
- No error codes or structured error objects

---

## 5. Code Duplication

### Lateral Menu Components (6 files)

| File | Lines | Animation Pattern |
|------|-------|-------------------|
| `LateralMenu.tsx` | 73 | `makeAnimation` + `stagger` + `timing` |
| `MenuIcon.tsx` | 79 | `makeAnimation` + `stagger` + `timing` |
| `CamdomLogo.tsx` | — | Same pattern |
| `UnlockYourPleasure.tsx` | — | Same pattern |
| `BuyAComdomLateralText.tsx` | 79 | Same pattern |
| `BillyBoyVerticalLogo.tsx` | — | Same pattern |

**Duplication:** Each component independently defines:
```typescript
const animation = makeAnimation(
  function* ({ isOpened, display, transition }) {
    "worklet";
    let to = 1;
    while (true) {
      yield* waitUntil(isOpened, !to);
      display.value = isOpened.value;
      yield* stagger(duration / 2, timing(transition, { to, duration }));
      to = to === 1 ? 0 : 1;
    }
  },
  { isOpened: false, display: false, transition: 0 }
);
```

**Recommendation:** Extract to `useMenuAnimation()` hook with configurable duration and stagger delay.

### State Reset Code in BleManager.ts

The following block appears **5 times** with minor variations (lines 317-333, 366-372, 529-534, 690-698, 1033-1044):

```typescript
this.allowedClientsToDisconnect = [];
this.askedDisconnectionDevices = [];
this.askedToStopAlarmClients = [];
this.rssiUpdatesFromClients = new Map<string, number[]>();
this.connectedDevice = undefined; // or this.connectedClients = []
this.lastDisconnectedDevice = undefined;
this.hasAnyoneRequestedToFireWhenDisconnect = false;
this.hasAnyoneHigherSensibility = undefined;
```

**Recommendation:** Extract to `resetConnectionState()` method.

### Disconnection Handler Duplication

`onDisconnectPressFinish()` (lines 1058-1146) and `onDisconnectLongPress()` (lines 1148-1225) share ~80% identical code for server-side disconnection handling. The only difference is the long press version sets `hasConnectionError = false`.

---

## 6. Type Safety

### TypeScript Strict Mode Status

**Enabled** in `tsconfig.json`:
```json
{
  "compilerOptions": {
    "strict": true
  }
}
```

### Interface vs Type Usage

| Pattern | Count | Location |
|---------|-------|----------|
| `interface` declarations | 4 | `Events.types.ts:1,3,7,14` |
| `type` declarations | 5 | `BleManager.ts:44,53,102` |
| Mixed usage | **YES** | Inconsistent |

**Issues:**
- `UISharedValues` uses `interface` (line 92)
- `AppConnectionState` uses `type` (line 44)
- No clear rule for when to use `interface` vs `type`

### SharedValue Type Safety

| SharedValue | Type | Line | Safety |
|-------------|------|------|--------|
| `isPeripheralServer` | `SharedValue<boolean>` | 93 | **SAFE** |
| `hasConnectionError` | `SharedValue<boolean>` | 94 | **SAFE** |
| `alarmButtonPosition` | `SharedValue<AvailablePositions>` | 95 | **SAFE** |
| `ballPosition` | `SharedValue<AvailablePositions>` | 96 | **SAFE** |
| `ballRadius` | `SharedValue<number>` | 97 | **SAFE** |
| `ballText` | `SharedValue<string[]>` | 98 | **SAFE** |
| `appState` | `SharedValue<AppConnectionState>` | 99 | **SAFE** |

**Finding:** SharedValue types are well-defined. However, `AvailablePositions` type (line 53) is suspicious:
```typescript
export type AvailablePositions = "center" | "center" | "center";
```
This appears to be a bug — likely should be `"left" | "center" | "right"`.

### Critical Type Bug

`AvailablePositions` at line 53:
```typescript
export type AvailablePositions = "center" | "center" | "center";
```
This type only allows `"center"` as a value. If the ball/alarm positions are supposed to move left/right, this type is broken. The animation code references `"left"` and `"right"` positions, but the type system would reject them.

---

## 7. Technical Debt Inventory

### Deprecated APIs

| API | Location | Replacement |
|-----|----------|-------------|
| `expo-modules-core` EventEmitter | BleManager.ts:3 | Modern Expo Module API |
| `react-native-ble-plx` BlePlxManager | BleManager.ts:21-26 | Consider Expo BLE native module |
| `btoa()` / `atob()` | BleManager.ts:831,937 | Use `TextEncoder`/`TextDecoder` |

### Workarounds & Hacks

| Issue | Location | Description |
|-------|----------|-------------|
| Platform-specific scan delay | BleManager.ts:716 | `Platform.OS === "ios" ? 400 : 0` — iOS needs 400ms delay before scanning |
| MTU negotiation | BleManager.ts:909 | Hardcoded `requestMTU(53)` — should negotiate |
| Session ID truncation | BleManager.ts:438 | `uuid.v4().substring(0, 8)` — arbitrary truncation |
| iOS scan retry logic | BleManager.ts:601-608 | Complex retry with `scanCountRetriesIos` counter |
| Volume manager workaround | BleManager.ts:235-238 | Forces volume to 1 before playing sounds |

### Commented-Out Features

| Feature | Lines | Status |
|---------|-------|--------|
| RSSI Proximity Detection | 1791-1871 | **DISABLED** — 80 lines of dead code |
| Proximity Notifications | 1106-1113, 1198-1205, 1268-1275 | **DISABLED** — Snackbar UI for proximity |
| RSSI Packet Sending | 1799-1804 | **DISABLED** — Client RSSI reporting |
| Sign Out / Delete Account | Options.tsx:117-144 | **DISABLED** — Authentication features |

### Zombie Variables (Allocated but Unused)

| Variable | Line | Purpose |
|----------|------|---------|
| `isAmIClientAllowedToDisconnectEdgeCase` | 116 | Complex disconnection state |
| `hasAnyoneHigherSensibility` | 142 | RSSI sensitivity (disabled feature) |
| `distanceAlarmFired` | 149 | Distance-based alarm (disabled feature) |
| `timeoutRssiReader` | 150 | RSSI reader timeout (disabled feature) |
| `pingPongTimeout` | 151 | Ping pong protocol timeout |

### Missing Tests

**Zero test files found.** No `.test.ts`, `.test.tsx`, `.spec.ts`, or `.spec.tsx` files exist in the entire codebase.

**Risk Areas Without Tests:**
- BLE packet parsing (custom protocol)
- State machine transitions
- Connection/disconnection logic
- RSSI threshold calculations (disabled but still in code)
- Sound effect loading and playback

---

## 8. Commit Quality Analysis

### Message Quality

| Category | Count | Percentage |
|----------|-------|------------|
| Semantic (feat/fix/chore) | ~120 | 28% |
| Descriptive | ~280 | 65% |
| WIP/Temporary | ~29 | 7% |

### WIP Commits Found

| Hash | Message |
|------|---------|
| `8db976f` | `wip` |
| `b19cdc4` | `final bitch - wip` |
| `8712884` | `wip: almost alive babe` |

### Time-of-Day Patterns

Based on commit timestamps, development peaks at:
- **Evening (17:00-19:00 BRT)** — Most commits
- **Night (21:00-02:00 BRT)** — Significant activity
- **Early Morning (03:00-06:00 BRT)** — Some commits present

### Fix-Heavy Periods

| Period | Pattern |
|--------|---------|
| Initial setup (Jun 2024) | Build configuration fixes |
| Nov 2025 | Final push with rapid fixes |

---

## 9. Architectural Strengths

### Generator-Based Animation Engine (`utils/Animations.ts`)

**Lines:** 164

This is an **elegant, production-quality animation system**:

```typescript
export function* timing(value: SharedValue<number>, rawConfig?: TimingConfig) {
  "worklet";
  const from = value.value;
  const { to, easing, duration } = { ...defaultTimingConfig, ...rawConfig };
  const start: number = yield;
  const end = start + duration;
  for (let current = start; current < end; ) {
    const progress = easing((current - start) / duration);
    const val = interpolate(progress, [0, 1], [from, to]);
    value.value = val;
    current += yield* timeSincePreviousFrame();
  }
  value.value = to;
}
```

**Strengths:**
- Leverages JavaScript generators for imperative-style async animations
- Composable via `parallel()` and `stagger()`
- Runs on UI thread via `"worklet"` directive
- Clean API: `yield* timing(value, { to: 1, duration: 300 })`

### Custom BLE Protocol

The packet protocol is purpose-built and efficient:
```
c:0:125        → Connection (role:client, advertisingValue:125)
s:a|session1   → Session answer (sessionId: session1)
d:r|s          → Disconnection request start
a:f|1|u        → Alarm fire (action:1, source:user)
sound:1|3      → Sound play (type:1, sound:alarm)
n:rssi|1|45|null → RSSI update (enabled:1, value:45, sense:null)
```

**Strengths:**
- Minimal overhead (ASCII-encoded, ~20 bytes typical)
- Bidirectional (server/client roles)
- Self-describing (colon-delimited type:content)
- Supports migration (device role switching)

### Skia Rendering

- GPU-accelerated rendering via `@shopify/react-native-skia`
- No bridge overhead for animations
- Custom font rendering with `Paragraph` API
- Shader-based effects (blur, image shaders)

### Privacy by Design

- **No network calls** except BLE (peer-to-peer)
- **No analytics** or telemetry
- **No data collection** — all state is local (MMKV)
- **No server dependency** — fully decentralized

---

## 10. Architectural Weaknesses

### BleManager as Monolith

**1,877 lines** handling:
- BLE scanning
- Connection management
- Packet parsing/routing
- Sound effects
- UI state synchronization
- RSSI monitoring (disabled)
- Storage initialization

**Impact:**
- Changes to one feature risk breaking others
- Difficult to test in isolation
- Merge conflicts likely in team development
- Cognitive load for new developers

### Shared State Sprawl

**11 SharedValues** managed by BleManager:
```typescript
interface UISharedValues {
  isPeripheralServer: SharedValue<boolean>;
  hasConnectionError: SharedValue<boolean>;
  alarmButtonPosition: SharedValue<AvailablePositions>;
  ballPosition: SharedValue<AvailablePositions>;
  ballRadius: SharedValue<number>;
  ballText: SharedValue<string[]>;
  appState: SharedValue<AppConnectionState>;
}
```

**Plus 15 private state variables:**
```typescript
private isServer?: boolean;
private isScanning = false;
private isConnecting = false;
private connectedDevice?: Device;
private connectedClients: string[] = [];
// ... 10 more
```

**Total state count:** 22 state variables in a single class.

### Missing Abstractions

| Pattern | Status | Impact |
|---------|--------|--------|
| Repository Pattern | **MISSING** | Direct MMKV access scattered across codebase |
| Service Layer | **MISSING** | Business logic mixed with UI |
| State Machine | **MISSING** | Connection states managed via if/else chains |
| Dependency Injection | **MISSING** | Singleton pattern (`const manager = new BleManager(...)`) |
| Event Bus | **PARTIAL** | Native EventEmitter used, but not centralized |

### No Tests

**Risk Assessment:**

| Component | Risk | Reason |
|-----------|------|--------|
| BLE Protocol | **CRITICAL** | Custom packet format, no validation |
| State Transitions | **HIGH** | Complex conditional logic |
| Connection Logic | **HIGH** | Race conditions possible |
| Sound Effects | **MEDIUM** | Platform-specific behavior |
| UI Animations | **LOW** | Visual feedback only |

### No CI/CD Quality Gates

No evidence of:
- Linting (ESLint)
- Type checking (`tsc --noEmit`)
- Test execution
- Code coverage
- Bundle size analysis
- Automated code review

---

## 11. Cross-Language Naming Inconsistencies

| Concept | TypeScript | Kotlin | Swift | Issue |
|---------|------------|--------|-------|-------|
| Main class | `BleManager` | `BleManager` | `BlePeripheralManager` | iOS naming differs |
| Read characteristic | `CHAR_FOR_READ_UUID` | `CHAR_FOR_READ_UUID` | — | iOS doesn't use read char |
| Indicate characteristic | `CHAR_FOR_INDICATE_UUID` | `CHAR_FOR_INDICATE_UUID` | `CHAR_FOR_INDICATE_UUID` | Consistent |
| Broadcast method | `broadcastPacket()` | `broadcastPacket()` | `broadcastPacket()` | Consistent |
| Send to client | `sendPacketToClient()` | `sendPacketToClient()` | — | iOS handles differently |

**Finding:** Naming is largely consistent. The iOS `BlePeripheralManager` name is semantically accurate (iOS BLE peripherals have different APIs than Android).

---

## 12. Protocol-Level Issues

### Packet Validation

No validation on incoming packets:

```typescript
// BleManager.ts:1327
private async handlePacketFromServer(packet: string) {
  const packetType = packet.split(":")[0];  // Could crash if no ":"
  const packetContent = packet.split(":")[1]; // Could be undefined
  // ...
}
```

**Risks:**
- Malformed packets could crash the app
- No bounds checking on array access
- No packet authentication

### Race Conditions

Multiple async operations without proper locking:

```typescript
// BleManager.ts:539-544
async startScanning() {
  this.isScanning = true;  // Set immediately
  // ... async operations ...
  // isScanning could be false before async completes
}
```

### Memory Leaks

Potential leaks in event listeners:

```typescript
// BleManager.ts:253
const subscriptions = [];
subscriptions.push(
  AppState.addEventListener("change", (state) => {
    // Closure captures `this`
  })
);
```

If `bindListeners()` is called multiple times, old subscriptions aren't cleaned up.

---

## 13. Recommendations

### Immediate (Quick Wins)

1. **Extract magic numbers** to named constants
2. **Fix `AvailablePositions` type** — should be `"left" | "center" | "right"`
3. **Remove commented-out code** — 115 lines of dead code
4. **Add error logging** to silent catch blocks
5. **Fix `cancelConnection` empty catch** — at minimum log the error

### Short-Term (1-2 weeks)

1. **Split `BleManager.ts`** into 4-5 focused modules
2. **Extract `resetConnectionState()`** method
3. **Add packet validation** in `handlePacketFromServer` and `handlePacketFromClient`
4. **Add ESLint** with strict rules
5. **Add TypeScript CI check** (`tsc --noEmit`)

### Medium-Term (1 month)

1. **Implement state machine** for connection states
2. **Add unit tests** for BLE protocol parsing
3. **Extract animation hooks** from lateral menu components
4. **Remove disabled RSSI feature** or implement properly
5. **Add integration tests** for BLE connection flow

### Long-Term (3 months)

1. **Add repository pattern** for storage access
2. **Implement dependency injection** for testability
3. **Add E2E tests** with Detox
4. **Set up CI/CD** with quality gates
5. **Consider architecture overhaul** — MVVM or Clean Architecture

---

## 14. Summary Scorecard

| Category | Score | Grade |
|----------|-------|-------|
| **Code Organization** | 4/10 | D |
| **Type Safety** | 6/10 | C |
| **Error Handling** | 4/10 | D |
| **Test Coverage** | 0/10 | F |
| **Documentation** | 2/10 | F |
| **Naming Conventions** | 7/10 | B- |
| **Code Duplication** | 3/10 | D |
| **Technical Debt** | 3/10 | D |
| **Architecture** | 4/10 | D |
| **Overall** | **3.6/10** | **D-** |

### Key Strengths
- Generator-based animation engine (elegant, composable)
- Custom BLE protocol (efficient, purpose-built)
- Privacy by design (no data collection)
- TypeScript strict mode enabled

### Key Weaknesses
- God object antipattern (BleManager: 1,877 lines)
- Zero test coverage
- 115 lines of commented-out code
- 13+ magic numbers
- 22 state variables in single class
- No CI/CD quality gates

---

## Appendix: File Line Counts

```
7281 total
1877 ./modules/ble-manager/src/BleManager.ts
 918 ./app/index.tsx
 753 ./modules/ble-manager/android/.../BleManager.kt
 452 ./modules/ble-manager/android/.../BlePeripheralManager.kt
 273 ./modules/ble-manager/ios/BlePeripheralManager.swift
 247 ./utils/i18n.ts
 246 ./app/onboarding.tsx
 237 ./components/Menu/MenuList.tsx
 164 ./utils/Animations.ts
 159 ./components/Menu/MenuTitle.tsx
 147 ./components/Menu/MenuContent/Pages/Options/Options.tsx
 128 ./components/NoisyBlurredBackground.tsx
 101 ./components/Menu/MenuContent/MenuContent.tsx
  99 ./hooks/useLateralMenu.tsx
  81 ./components/Menu/Menu.tsx
  79 ./components/LateralMenu/MenuIcon.tsx
  79 ./components/LateralMenu/BuyAComdomLateralText.tsx
  77 ./components/LateralMenu/styles.ts
  73 ./components/LateralMenu/LateralMenu.tsx
```

---

*This analysis reflects the codebase as of November 2025 (429 commits). The codebase demonstrates strong domain expertise in BLE protocol design and animation systems, but suffers from typical startup engineering tradeoffs: rapid iteration at the expense of maintainability. The generator-based animation engine is production-quality; the BLE manager needs architectural refactoring.*
