---
description: Verify iOS/mobile code compiles, all files are in Xcode targets, and passes quality checks
---

# Mobile/Native Code Quality Workflow

> Pre-flight quality gate for MindLyst native (KMP) and LysnrAI iOS code.
> Run before any TestFlight release or after adding/renaming Swift/Kotlin files.

---

## Phase 1: MindLyst Native (Kotlin Multiplatform)

### Step 1.1 — Verify git clean

// turbo
```bash
cd $HOME/code/mygh/learning_multimodal_memory_agents && git diff --quiet && git diff --cached --quiet && echo "Clean" || echo "WARNING: uncommitted changes"
```

### Step 1.2 — KMP shared module compile

```bash
cd $HOME/code/mygh/learning_multimodal_memory_agents/mindlyst-native && ./gradlew :shared:compileKotlinIosSimulatorArm64
```

> This is the primary KMP verification step. If the shared module compiles for
> iOS Simulator, the core business logic is valid.

### Step 1.3 — Android compile (if SDK available)

```bash
cd $HOME/code/mygh/learning_multimodal_memory_agents/mindlyst-native && ./gradlew :shared:compileKotlinAndroid
```

> Requires `local.properties` with `sdk.dir`. Skip if Android SDK not configured.

### Step 1.4 — Web build check

// turbo
```bash
cd $HOME/code/mygh/learning_multimodal_memory_agents/mindlyst-native/web && npx next build 2>&1 | tail -10
```

---

## Phase 2: LysnrAI iOS

### Step 2.1 — Verify git clean

// turbo
```bash
cd $HOME/code/mygh/learning_voice_ai_agent && git diff --quiet && git diff --cached --quiet && echo "Clean" || echo "WARNING: uncommitted changes"
```

### Step 2.2 — Install CocoaPods

// turbo
```bash
cd $HOME/code/mygh/learning_voice_ai_agent/mobile_app/ios && pod install
```

### Step 2.3 — Build ALL iOS targets

Build both the main app AND the LysnrKeyboard extension.

```bash
cd $HOME/code/mygh/learning_voice_ai_agent && xcodebuild build \
  -workspace mobile_app/ios/LysnrAI.xcworkspace \
  -scheme LysnrAI \
  -configuration Debug \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
  CODE_SIGN_IDENTITY=- \
  CODE_SIGNING_ALLOWED=NO \
  2>&1 | tail -30
```

> **IMPORTANT:** Use `.xcworkspace` (NOT `.xcodeproj`) — CocoaPods requires the workspace.
> Building the LysnrAI scheme also compiles LysnrKeyboard as an embedded extension.

### Step 2.4 — Verify pbxproj ↔ filesystem consistency

// turbo
```bash
cd $HOME/code/mygh/learning_voice_ai_agent && \
echo "=== Checking LysnrKeyboard ===" && \
for f in mobile_app/ios/LysnrKeyboard/*.swift; do
  fname=$(basename "$f")
  if ! grep -q "$fname" mobile_app/ios/LysnrAI.xcodeproj/project.pbxproj; then
    echo "ERROR: $fname not in project.pbxproj" && exit 1
  fi
done && echo "OK: All keyboard .swift files in project" && \
echo "=== Checking LysnrAI main app ===" && \
missing=0 && \
for f in $(find mobile_app/ios/LysnrAI -name '*.swift' -not -path '*/Pods/*'); do
  fname=$(basename "$f")
  if ! grep -q "$fname" mobile_app/ios/LysnrAI.xcodeproj/project.pbxproj; then
    echo "WARNING: $fname may be missing from project.pbxproj"
    missing=$((missing + 1))
  fi
done && \
if [ "$missing" -eq 0 ]; then echo "OK: All main app .swift files in project"; \
else echo "$missing file(s) may be missing"; fi
```

### Step 2.5 — Check for common Swift issues

// turbo
```bash
cd $HOME/code/mygh/learning_voice_ai_agent && \
echo "=== Hardcoded secrets ===" && \
grep -rn --include='*.swift' -E '(AZURE_SPEECH_KEY|api_key|secret|password)\s*=' mobile_app/ios/ \
  | grep -v 'forKey:' | grep -v '//' | grep -v 'UserDefaults' | grep -v 'loadEnvValue' | grep -v 'Pods/' \
  || echo "None found" && \
echo "" && echo "=== print() in production ===" && \
count=$(grep -rn --include='*.swift' '^\s*print(' mobile_app/ios/LysnrKeyboard/ 2>/dev/null | wc -l) && \
echo "Keyboard extension: $count print() calls (should be 0)"
```

### Step 2.6 — Verify Info.plist + entitlements

// turbo
```bash
cd $HOME/code/mygh/learning_voice_ai_agent && \
for key in NSMicrophoneUsageDescription NSSpeechRecognitionUsageDescription NSExtensionPointIdentifier RequestsOpenAccess; do
  if grep -q "$key" mobile_app/ios/LysnrKeyboard/Info.plist; then echo "OK: $key"; else echo "ERROR: $key MISSING"; fi
done && \
if grep -q "com.apple.security.application-groups" mobile_app/ios/LysnrKeyboard/LysnrKeyboard.entitlements; then
  echo "OK: App Group entitlement"
else echo "ERROR: App Group entitlement MISSING"; fi
```

---

## Reference

### What This Catches

| Check | Prevents |
|-------|----------|
| KMP compile | Shared business logic errors |
| Build all iOS targets | Missing source files in Xcode project |
| pbxproj consistency | New .swift files on disk but not in target |
| Secret scan | Hardcoded API keys in Swift source |
| print() check | Debug logging in production keyboard extension |
| Info.plist check | Missing privacy descriptions → App Store rejection |
| Entitlements check | Missing App Group → keyboard can't share data |

### Key Files

| File | Purpose |
|------|---------|
| `mindlyst-native/shared/` | KMP shared business logic |
| `mindlyst-native/web/` | Next.js web dashboard |
| `../learning_voice_ai_agent/mobile_app/ios/LysnrAI.xcodeproj/project.pbxproj` | Xcode project config |
| `../learning_voice_ai_agent/mobile_app/ios/LysnrKeyboard/` | Keyboard extension sources |
| `../learning_voice_ai_agent/mobile_app/ios/Podfile` | CocoaPods deps |

### Troubleshooting

| Problem | Fix |
|---------|-----|
| KMP compile fails | Check `gradle/libs.versions.toml` for version conflicts |
| Xcode build fails | Use `.xcworkspace`, run `pod install` first |
| File missing from pbxproj | Add to PBXFileReference + PBXGroup + PBXBuildFile + PBXSourcesBuildPhase |
| Android SDK missing | Set `sdk.dir` in `local.properties` or skip Android steps |
| Simulator not found | Run `xcrun simctl list devices` to see available simulators |
