--- name: simulator-audio-e2e description: Build and run repeatable react-native-nitro-sound recorder/player regression tests on an iOS Simulator or Android emulator, with explicit virtual-device selection, microphone permission, Maestro evidence, native log inspection, and cleanup. Use after dependency, Nitro, TypeScript, Swift, Kotlin, generated-binding, or audio state-machine changes when a physical device is not required. --- # Simulator Audio E2E Verify real native recording and playback on virtual devices without touching a connected physical phone. Treat builds, UI automation, callback state, and log inspection as separate evidence. ## Safety Boundary - Require explicit permission in the current request before recording. State that `sound.example` records a short non-sensitive clip through the host or emulator microphone. A request to run audio E2E is sufficient permission. - Select a concrete iOS Simulator UDID or Android serial beginning with `emulator-`. Never allow an implicit destination when physical devices are connected. - Do not upload, transcribe, or retain the recording. Keep only screenshots, JUnit output, and redacted logs needed to diagnose the run. - Do not claim Bluetooth, interruptions, backgrounding, audio focus, route changes, or audible fidelity from this lane; those require targeted tests and can require a physical device. ## Preflight 1. Read `AGENTS.md`, `.claude/commands/e2e-tests.md`, the changed source, and `references/flow-contract.md`. 2. Preserve `git status --short --branch`; never clean unrelated work. 3. Run `scripts/preflight.sh` and select one available virtual destination. 4. Run `yarn install --immutable`, `yarn prepare`, `yarn typecheck`, `yarn lint`, and `yarn test --runInBand`. 5. Confirm `sound.example` declares microphone permission and no Metro process conflict exists on port 8081. ## Build And Install For iOS, boot the selected Simulator and build the Debug app for that exact UDID. Install the produced `.app` with `xcrun simctl install`. For Android, start the selected AVD, wait for boot completion, and build/install Debug with `ANDROID_SERIAL` set to the selected emulator serial. Start Metro from the repository root with `yarn start --reset-cache`. Keep its session and save errors separately from native device logs. Grant microphone permission to `sound.example` on the selected virtual device before the flow. ## Run The Runtime Contract Run the repository flow through the guarded helper: ```bash .codex/skills/simulator-audio-e2e/scripts/run-maestro.sh ios .codex/skills/simulator-audio-e2e/scripts/run-maestro.sh android ``` The flow must prove both direct and hook APIs can: 1. Start recording and emit increasing record time. 2. Pause and resume the recorder without a crash or duplicate instance. 3. Stop and expose a playable path. 4. Start, pause, resume, and stop playback with matching UI state. 5. Complete with no visible error alert. Do not weaken selectors or remove state assertions to make a failed flow pass. Fix the product or explain a platform limitation. ## Inspect Native Evidence After Maestro, inspect simulator logs for the current app process only: - iOS: `xcrun simctl spawn log show` with a short time bound and a `sound.example` predicate. - Android: `adb -s logcat --pid=$(adb -s shell pidof sound.example)` captured around the run. Fail the runtime lane for uncaught exceptions, native crashes, rejected promises, MediaRecorder/AVAudio errors, or leaked-resource warnings attributable to the tested flow. Ignore unrelated host and OS noise with an explanation. ## Report And Cleanup Report `BUILD PASS/FAIL` and `RUNTIME PASS/FAIL/BLOCKED` per platform. Include the exact UDID/serial, OS/API level, RN and Nitro versions, flow path, callback states observed, JUnit result, and relevant redacted log findings. List every untested device-only row. Terminate only Metro/emulators started by this run. Leave user-owned devices and processes intact. Use the guarded runner's mandatory cleanup and verify that no recording remains in the selected app container or `e2e/artifacts/`. Report `RUNTIME BLOCKED` if cleanup fails or cannot be confirmed. JUnit, screenshots, debug output, and redacted logs under `e2e/artifacts/` remain disposable and ignored by Git.