feat(proxy): lease by device spec — --os, --image-tag honoured or refused by the backend

Draft
V3
9h ago
+1253-58

Summary

open, install, reinstall and uninstall through connect proxy can now lease by OS version and Android image tag. A backend that cannot honour the spec refuses it rather than ignoring it. 38 files. Closes #3864.

FlagKey on agent_device.lease.allocateEcho on data.lease.device
--os <version|range>osVersion (opaque string)model, osVersion (exact)
--image-tag <tag>imageTagimageTag?

Rules:

  • The CLI sends the keys only on a by-spec allocate. devices.list is not called first.
  • A daemon refuses any request that names either key. This covers a local daemon and one behind agent-device proxy. The refusal is UNSUPPORTED_OPERATION with reason: 'device-spec-unsupported' and keys, and it happens before admission, so no lease is recorded.
  • If a lease comes back without lease.device, the CLI releases it and fails with the same reason.
  • A live lease serves a command only when every spec key the command names, and any --udid/--serial, matches it. Otherwise the command fails with CONNECTION_DEVICE_CONFLICT.
  • connect proxy stores the keys as defaults. The keys are visible in MCP and the SDK. open --json prints lease.device.
  • Docs: remote-proxy.md, help remote, and an amendment to ADR 0007. --physical is dropped, per the maintainer.
agent-device open MyApp --platform android --os 34 --image-tag google_apis_playstore

Validation

At 4f94d93e8, pnpm check:affected --run --head 4f94d93e8 passed with exactCommit=true; all 36 runnable checks passed. CI owns device lanes and coverage.

Review: three independent Opus rounds. All findings except the gaps below are fixed. The round-3 fixes were not reviewed again.

Assumption: a spec key that a command leaves out does not constrain a live lease. This follows the existing --device rule.
Assumption: env vars cannot set the keys; only flags and connect proxy can.

Known gaps:

  • MCP and the SDK never allocate a proxy lease, so through them the keys are always refused.
  • connect forms other than proxy accept the flags but do not store them, as with --device.
  • If a backend returns the run's existing lease without an echo, the CLI releases that lease.
  • If a spec lease expires and a non-allocating command re-allocates it by device, the new lease has no spec. A later open --os then fails with CONNECTION_DEVICE_CONFLICT.