## Why On the macOS native real-device setup (`docs/MACOS_IPHONE_SETUP.md`), a device only reports `idle`/online to the Cloud Control Plane if `DeviceManager.connect()` (`device/manager.py:68-108`) can actually establish an Appium session — but the Host Agent process (`apps/device-host-agent/host_agent/app.py`) never starts Appium itself; the operator must run `appium --address 127.0.0.1 --port 4723` in a separate terminal before starting `device-host-agent`, and separately run the local Runtime API (`uvicorn api.rest:create_app --factory ...`) if they want to inspect device/task state during local debugging. Forgetting (or losing) either process is invisible from the Host Agent's own output: heartbeats keep succeeding, so the Host looks "connected," while the device silently stays `offline` and every assigned task stays queued forever with no error. This was diagnosed live from exactly that symptom. Having the Host Agent supervise these known local dependencies for the single-machine dev/real-device workflow removes an easy-to-miss manual step and makes the failure visible instead of silent. ## What Changes - `HostAgentApplication` gains an optional local dependency supervisor that, when enabled, starts and monitors two external processes alongside the existing heartbeat/claim loop: - **Appium server** (`appium --address --port `), whose reachability already gates real device `connect()` calls. - **Local Runtime API** (`uvicorn api.rest:create_app --factory --host --port `), used for local inspection/debugging of device and task state. - Before spawning either process, the supervisor probes the configured address: if something is already listening and answers the expected health check, it adopts the existing instance (log-only) instead of spawning a duplicate or rebinding the port. It only spawns a subprocess when the port is free. - Crash handling: if a supervised subprocess it spawned exits unexpectedly, the supervisor restarts it with capped exponential backoff and a maximum retry count per run; it does not touch a process it did not spawn (an adopted, externally-managed instance is never restarted or killed by the Host Agent). - New `HostAgentConfig` fields to control this, all opt-in and disabled by default (see design.md for the specific default-off rationale): enable/disable the supervisor as a whole, enable/disable each of the two dependencies independently, and host/port for each (defaulting to the existing documented conventions — Appium `127.0.0.1:4723`, Runtime `127.0.0.1:8000`). - Documentation update to `docs/MACOS_IPHONE_SETUP.md` describing the new opt-in supervised mode as an alternative to the existing manual multi-terminal flow (the manual flow remains fully supported and is still what's documented as the default path). - Explicitly out of scope: no change to WDA's own lifecycle (Appium continues to own WDA session management entirely unchanged), no Docker Compose changes (`compose.yaml`/`compose.deploy.yaml` are unaffected — this is a native-process-only capability), no change to the outbound cloud protocol. ## Capabilities ### New Capabilities - `host-agent-dependency-supervisor`: optional, opt-in local process supervision inside the Host Agent for the Appium server and the local Runtime API — port/adoption probing, spawn, health-checked readiness, and rate-limited crash-restart, scoped to the macOS native single-machine real-device workflow. ### Modified Capabilities (none — `host-agent-protocol` outbound behavior is unchanged; `driver-registry`/`device-pool` behavior for how a `Driver.connect()` reaches Appium is unchanged, this change only affects whether Appium happens to already be running when that connect attempt occurs) ## Impact - Affected code: `apps/device-host-agent/host_agent/` (new supervisor module, `app.py` wiring to start/stop it alongside the heartbeat/claim loop, `config.py` new fields), `apps/device-host-agent/pyproject.toml` (no new runtime dependency expected — spawning uses stdlib `subprocess`; Runtime API is already invoked via its existing `uvicorn`/`api.rest` entry point). - Not affected: `cloud.*`, `apps/cloud-api`, `compose.yaml`, `compose.deploy.yaml`, `driver/wda_driver.py` / `driver/android_driver.py` connection logic, WDA's own session lifecycle (still fully owned by Appium). - Operational impact: opt-in only — a Host Agent with the supervisor disabled (the default) behaves exactly as it does today. When enabled, the Host Agent's own process lifecycle now indirectly affects two more local processes, which changes what "the Host Agent crashed" or "the Host Agent's log" means for local troubleshooting (see design.md for how adoption-vs-spawn is surfaced in logs to keep this legible).