.cursor/skills/platform-parity-audit/SKILL.md
Audit iOS port parity against the Android app. Compares ViewModels, Views, Settings, and Navigation at the code level, verifies features from docs/videos/ TOML project files, and optionally captures side-by-side screenshots. Use when the user asks to compare iOS vs Android, check iOS parity, find missing iOS features, audit the port, or mentions feature gaps.
npx skillsauth add baijum/ukulele-companion platform-parity-auditInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Systematically compare the iOS port against the Android reference implementation to identify missing features, partial implementations, and behavioral differences. The audit has three layers that can be run independently.
Compare source files between platforms to find functional gaps. This is the fastest layer and should always be run first.
List all Android UI files and ViewModels:
ls app/src/main/java/com/baijum/ukufretboard/ui/*.kt
ls app/src/main/java/com/baijum/ukufretboard/viewmodel/*.kt
List all iOS View and ViewModel files:
ls iosApp/UkuleleCompanion/Views/*.swift
ls iosApp/UkuleleCompanion/ViewModels/*.swift
Build a feature matrix by matching each Android screen to its iOS equivalent. Use the mapping table below as a starting reference:
| Category | Android Screen (ui/) | iOS Screen (Views/) | |----------|---------------------|---------------------| | Play | FretboardScreen.kt (Explorer) | ExplorerView.swift | | Play | TunerTab.kt | TunerView.swift | | Play | PitchMonitorTab.kt | PitchMonitorView.swift | | Play | MetronomeTab.kt | MetronomeView.swift | | Play | ChordLibraryTab.kt | ChordLibraryView.swift | | Play | FavoritesTab.kt | FavoritesView.swift | | Create | SongbookTab.kt | SongbookView.swift | | Create | MelodyNotepadView.kt | MelodyNotepadView.swift | | Create | StrumPatternsTab.kt | StrumPatternsView.swift | | Create | ProgressionsTab.kt | ProgressionsView.swift | | Learn | TheoryLessonsView.kt | TheoryLessonsView.swift | | Learn | TheoryQuizView.kt | TheoryQuizView.swift | | Learn | IntervalTrainerView.kt | IntervalTrainerView.swift | | Learn | NoteQuizView.kt | NoteQuizView.swift | | Learn | ChordEarTrainingView.kt | ChordEarTrainingView.swift | | Learn | ScalePracticeView.kt | ScalePracticeView.swift | | Learn | LearningProgressView.kt | LearningProgressView.swift | | Learn | DailyChallengeView.kt | DailyChallengeView.swift | | Learn | PracticeRoutineView.kt | PracticeRoutineView.swift | | Learn | ChordTransitionView.kt | ChordTransitionsView.swift | | Learn | PlayAlongView.kt | PlayAlongView.swift | | Learn | AchievementsView.kt | AchievementsView.swift | | Reference | CapoGuideView.kt | CapoGuideView.swift | | Reference | CircleOfFifthsView.kt | CircleOfFifthsView.swift | | Reference | ChordSubstitutionsView.kt | ChordSubstitutionsView.swift | | Reference | ScaleChordView.kt | ScaleChordsView.swift | | Reference | FretboardNoteMapView.kt | FretboardNoteMapView.swift | | Reference | GlossaryView.kt | GlossaryView.swift | | Other | SettingsSheet.kt | SettingsView.swift | | Other | HelpView.kt | HelpView.swift | | Other | OnboardingScreen.kt | OnboardingView.swift |
For each ViewModel pair, compare the Android StateFlow/MutableState properties against iOS @Published properties. Look for:
Example comparison approach:
# Extract Android ViewModel public API
rg "val |var |fun " app/src/main/java/com/baijum/ukufretboard/viewmodel/FretboardViewModel.kt | head -40
# Extract iOS ViewModel public API
rg "@Published|func " iosApp/UkuleleCompanion/ViewModels/FretboardViewModel.swift | head -40
Compare all settings keys between platforms:
# Android settings
rg "putBoolean\|putString\|putInt\|putFloat\|getBoolean\|getString\|getInt\|getFloat" app/src/main/java/com/baijum/ukufretboard/data/
# iOS settings
rg "UserDefaults\|@AppStorage\|defaults\." iosApp/UkuleleCompanion/ViewModels/SettingsViewModel.swift
For each matched screen pair, read both files and compare:
Create a markdown table in docs/ios-parity-report.md with columns:
| Feature | Android File | iOS File | Status | Notes | |---------|-------------|----------|--------|-------|
Status values:
The docs/videos/ directory contains TOML project files that document detailed feature scenarios. Use these as checklists.
ls docs/videos/*/android.toml
For each android.toml, read the [[scene]] entries. Each scene has:
name — what the scene demonstratesnarration — description of the feature behaviorrecording_notes — step-by-step interaction instructionsFor each scene, search the iOS codebase for the described feature:
# Example: verify chord detection exists in iOS
rg "detect\|chord.*result\|ChordResult" iosApp/UkuleleCompanion/Views/ExplorerView.swift
Mark each scene as:
The TOML files cover Play and Create features only. For Learn and Reference screens, manually verify by reading the iOS view files and comparing against the Android equivalents.
Capture side-by-side screenshots to catch visual/layout differences.
mkdir -p docs/parity-screenshots/{android,ios}
ADB=~/Library/Android/sdk/platform-tools/adb
# Launch app
$ADB shell am start -n com.baijum.ukufretboard/.MainActivity
sleep 3
# For each screen: navigate, wait, capture
# Example: Explorer
$ADB exec-out screencap -p > docs/parity-screenshots/android/explorer.png
# Example: Chord Library (via drawer)
$ADB shell input tap 80 200 # hamburger menu
sleep 1
$ADB shell uiautomator dump /sdcard/ui.xml 2>/dev/null
$ADB shell cat /sdcard/ui.xml | tr '>' '\n' | grep 'text="Chords"'
# Tap found coordinates
$ADB shell input tap <x> <y>
sleep 2
$ADB exec-out screencap -p > docs/parity-screenshots/android/chord-library.png
# Get booted simulator UUID
SIM_UUID=$(xcrun simctl list devices booted -j | python3 -c "import sys,json; devs=json.load(sys.stdin)['devices']; print([d['udid'] for ds in devs.values() for d in ds if d['state']=='Booted'][0])")
# Launch app
xcrun simctl launch $SIM_UUID com.baijum.ukufretboard.ios
sleep 3
# Capture each screen (navigate via UI or deep links if available)
xcrun simctl io $SIM_UUID screenshot docs/parity-screenshots/ios/explorer.png
iOS navigation automation is limited compared to ADB. For screens requiring navigation:
xcrun simctl status bar overrides for consistent appearanceReview the paired screenshots (android/<name>.png vs ios/<name>.png) visually or present them side-by-side. Look for:
Use consistent names matching the feature:
explorer.png, tuner.png, metronome.png, chord-library.pngsettings.png, onboarding.png{feature}-{subscreen}.png for sub-screens (e.g., progressions-practice.png)Generate docs/ios-parity-report.md containing:
| Task | Command |
|------|---------|
| List Android UI files | ls app/src/main/java/com/baijum/ukufretboard/ui/*.kt |
| List iOS View files | ls iosApp/UkuleleCompanion/Views/*.swift |
| List Android ViewModels | ls app/src/main/java/com/baijum/ukufretboard/viewmodel/*.kt |
| List iOS ViewModels | ls iosApp/UkuleleCompanion/ViewModels/*.swift |
| Compare ViewModel API | rg "val \|var \|fun " <android.kt> vs rg "@Published\|func " <ios.swift> |
| List TOML projects | ls docs/videos/*/android.toml |
| Android screenshot | adb exec-out screencap -p > file.png |
| iOS screenshot | xcrun simctl io <UUID> screenshot file.png |
TunerViewModel is defined inline in Views/TunerView.swift, not in ViewModels/. Check both directories.shared/src/commonMain/ are available to both platforms. When a feature appears "missing" from iOS, check if the shared module provides it.uiautomator and input tap, iOS simulator automation is limited to xcrun simctl which has no UI element discovery. For full automation, use XCUITest or navigate manually.tools
Record scene video clips for a TOML video project. Reads the android.toml or ios.toml to get the scene list and min_clip_duration, navigates to each screen via ADB (Android) or simctl (iOS), and records individual clips. Use when the user says /record-clips and provides a TOML path.
tools
Upload a release AAB to Google Play Store using the Gradle Play Publisher plugin. Use when the user asks to upload to Play Store, publish to Google Play, deploy to internal testing, promote a release, or mentions Play Console.
development
Promote a release from Google Play internal testing to a closed testing track (Alpha or App Hive Testing). Use when the user asks to promote a release, move to closed testing, push to alpha, push to App Hive Testing, or mentions track promotion.
development
Promote a release to Google Play open testing or production tracks. Supports full rollout and staged rollout to production. Use when the user asks to promote to open testing, beta, go to production, release to all users, staged rollout, or increase rollout percentage.