feat(proxy): lease by device spec — --os, --image-tag honoured or refused by the backend
Draft
V3
9h ago+1253+1253+0123456789012345678901234567890123456789-58-58-01234567890123456789
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.
| Flag | Key on agent_device.lease.allocate | Echo on data.lease.device |
|---|---|---|
--os <version|range> | osVersion (opaque string) | model, osVersion (exact) |
--image-tag <tag> | imageTag | imageTag? |
Rules:
- The CLI sends the keys only on a by-spec allocate.
devices.listis 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 isUNSUPPORTED_OPERATIONwithreason: 'device-spec-unsupported'andkeys, 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 withCONNECTION_DEVICE_CONFLICT. connect proxystores the keys as defaults. The keys are visible in MCP and the SDK.open --jsonprintslease.device.- Docs:
remote-proxy.md,help remote, and an amendment to ADR 0007.--physicalis 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.
connectforms other thanproxyaccept 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 --osthen fails withCONNECTION_DEVICE_CONFLICT.