# `MobDev.Bench.Preflight`
[🔗](https://github.com/genericjam/mob_dev/blob/master/lib/mob_dev/bench/preflight.ex#L1)

Pre-run checklist for the iOS battery bench.

Walks through the things that have to be right before locking the screen
and running for 30 minutes. Each check returns `:ok | {:error, message}`.

Goals:

- Catch the misconfigurations that would invalidate a run *before* the run
  starts (saves ~30 min of wasted bench time).
- Tell the user exactly what's wrong and how to fix it.
- Be testable — each check is a pure function returning a tagged result.

## Checks performed

1. **USB / hardware UDID** — at least one of: USB-connected device
   reachable via `idevice_id -l`, or a configured `:hw_udid`.
2. **App installed** — bundle id appears in `xcrun devicectl device info apps`.
3. **BEAM reachable** — Node.connect succeeds.
4. **RPC responsive** — `rpc.call(node, :erlang, :node, [])` returns within
   2 seconds. Distinguishes "BEAM up but suspended" from "fully alive".
5. **NIF version** — `mob_nif:battery_level/0` is exported. (Indicates the
   installed app build is recent enough.)
6. **Background NIF** — `mob_nif:background_keep_alive/0` is exported.
   Required for screen-off bench mode.

Each check is independent — failure in (3) doesn't skip (5); we run them
all and report a complete picture.

# `check_result`

```elixir
@type check_result() :: {:ok, String.t()} | {:error, String.t()}
```

Result for a single check.

# `all_ok?`

```elixir
@spec all_ok?([{atom(), check_result()}]) :: boolean()
```

Returns true if every result is `{:ok, _}`. Stricter overall check than
examining individual results — useful for deciding whether to abort.

# `pretty`

```elixir
@spec pretty([{atom(), check_result()}]) :: String.t()
```

Format the results as a multi-line string with ✓/✗ markers.

# `run`

```elixir
@spec run(keyword()) :: [{atom(), check_result()}]
```

Run all preflight checks and return a list of `{name, result}` tuples in
the order they were run.

Common options:
- `:platform` — `:ios` (default) or `:android` — selects platform-specific
  `hardware` and `app_installed` checks
- `:node` — node atom (required for BEAM checks)
- `:cookie` — cookie atom
- `:bundle_id` — app bundle id
- `:host` — IP/host for EPMD (default: derive from node)
- `:require_keep_alive` — boolean, default true (set false for screen-on bench)

iOS-specific:
- `:device_id` — devicectl identifier (CoreDevice UUID)
- `:hw_udid` — hardware UDID for USB checks

Android-specific:
- `:adb_serial` — ADB serial / IP:port for `adb` checks

---

*Consult [api-reference.md](api-reference.md) for complete listing*
