feat(proxy): allocate by device spec and bind the device the lease names

Merged
V3
8h ago
+780-96

Summary

In proxy mode the CLI picked a device from the daemon's device list before allocating, so open failed when no device existed yet or when several matched. A service that boots devices on allocate could not choose one.

Now, without --udid/--serial, open/install send --platform, --target, --device (and the simulator-set/allowlist scoping) with lease_allocate and no deviceKey. The proxy daemon picks the device with the same resolveDevice rules and names it in the reply (data.device); the CLI binds that device and its deviceKey. A later open on a live lease reuses the leased device. A daemon that names no device: the CLI releases that lease and falls back to the local pick. Exact --udid/--serial and local mode are unchanged. Additive; no protocol version bump.

agent-device open MyApp --platform ios --device "iPhone 17"   # through connect proxy

15 files (one doc paragraph, one façade pin in chore(gates)).

Validation

Tested SHA e38bc9ef4. pnpm check:affected --run: all runnable checks passed (466 files, 3604 tests).

Live run on head 4dc358dfba (main merged through 562e798d1b). The built CLI ran through connect proxy to a local agent-device proxy daemon with a private simulator set. A fresh open --platform ios --device "PR3487 Alpha" bound deviceKey ios:mobile:1136B6B3-…4901, and the next screenshot ran on that UDID. On the same lease, open --device "PR3487 Bravo" and open --ios-simulator-device-set <empty set> were refused with INVALID_ARGS / CONNECTION_DEVICE_CONFLICT. No command ran on Alpha (only a devices inventory request).

  • New unit tests (daemon pick by name/target, no pick for exact key/no spec/non-proxy; CLI by-spec, renew, older-daemon fallback, exact udid; client reply parsing; HTTP projection) fail without the change.
  • Built CLI → built proxy → local daemon, private simulator set: open --platform ios --device "AD Spec Phone" bound the reply's device (deviceKey ios:mobile:<udid>), screenshot ran on it, and the daemon logged no devices call. Raw RPC allocate by spec returned data.device. Old paths (proxy --udid, local --device) still pass.