Problem
Starting a routine local automation session often requires an agent to list devices, infer a target,
then repeat platform/device selectors on open. The explicit path is predictable, but it adds tool
calls and decision points even when exactly one healthy local target is available or the user already
named an unambiguous platform.
The goal is to reduce this bootstrap ceremony without making target choice implicit in ambiguous or
concurrent environments.
Desired outcome
Design one deterministic device-selection policy shared by CLI, Node, MCP, and daemon dispatch so a
routine open can select the only sensible local target while ambiguous selection still fails with a
bounded, actionable candidate list.
Examples of the intended experience:
- One booted iOS simulator and an iOS app target:
open <app> --platform ios uses it.
- One available Android emulator and no active Android target: the command may boot/select it if the
command contract explicitly permits that lifecycle transition.
- Multiple eligible devices: fail before app mutation and return ranked candidates plus the exact
selectors needed to retry.
- An existing healthy session: preserve current session ownership and device binding; never silently
migrate the session to a different device.
- Physical devices, remote providers, simulator-set overrides, macOS desktop, TV, web, and concurrent
worktrees keep their current isolation/ownership guarantees.
Constraints and source-of-truth seams
- Start from the device/session vocabulary in
CONTEXT.md and accepted decisions in
docs/adr/README.md.
- Selection and support checks must remain derived from the command descriptor registry and
src/core/capabilities.ts; do not create a new command-name or capability allowlist.
- Keep simulator-set scoping iOS-specific so it cannot hide the host macOS desktop target.
- Respect daemon lease/device ownership and
DEVICE_IN_USE; convenience must not bypass a live owner
or make two worktrees select the same device.
- Prefer explicit device/UDID/serial and an existing session binding over inference.
- Provider/cloud selection must stay explicit unless a provider already guarantees a single leased
target. Do not turn local convenience into remote allocation.
- Any fallback/default must be represented as a named policy with typed reason codes and diagnostics,
not error-message sniffing.
- Keep CLI flags and MCP/Node structured inputs aligned if public selection inputs change; follow
docs/agents/cli-flags.md.
Investigation / design questions
- Inventory every current selection path (
open, sessionless inventory/state commands, existing
session reuse, provider targets, default-device helpers) and identify where their precedence rules
differ.
- Define an ordered candidate policy. A starting hypothesis is: explicit selector -> existing session
binding -> exactly one already-booted compatible local target -> exactly one compatible local target
whose lifecycle may be prepared -> typed ambiguity/no-candidate result.
- Decide whether app identity can contribute to target selection (for example, exactly one device has
the app installed) without making selection expensive or creating success-path parity differences.
- Decide whether selection should be an
open behavior only or a reusable resolver for every
sessionless command that permits a default device.
- Specify the result metadata agents need: selected-by reason, candidate count, whether boot occurred,
and retry selectors. Keep it response-level; do not add bytes per snapshot node.
- Prototype ambiguous and concurrent cases before changing defaults. Measure tool-call reduction and
wrong-target rate, not only happy-path latency.
Verification
- Unit tests pin candidate precedence and typed reason codes, including explicit selector dominance,
existing session reuse, one booted target, one bootable target, no target, and multiple targets.
- Contract/integration coverage proves the same outcome through CLI, Node, and MCP projections.
- A planted pre-change failure demonstrates that the new single-target case was not already passing
through another fallback.
- iOS tests cover simulator-set scoping and physical-device coexistence; Android tests cover emulator
versus physical serial selection. Add TV/macOS/web/provider cases only where the shared resolver can
actually fire.
- Two concurrent worktrees/daemons targeting the same inventory cannot both acquire the device; the
loser receives DEVICE_IN_USE with the owning session and recovery hint.
- Ambiguity performs no app/device mutation and returns a bounded deterministic candidate list.
- Existing explicit command lines remain behaviorally unchanged.
- Update versioned CLI help, MCP/Node metadata, user docs, and a help-conformance scenario if command
planning guidance changes.
Acceptance criteria
- A documented deterministic resolver owns selection precedence across applicable surfaces.
- The routine exactly-one-compatible-local-target path needs no preliminary
devices call.
- Ambiguous, remote, and concurrent cases remain explicit and safe.
- Selection reason and retry guidance are structured and test-covered.
- No parallel hand-maintained device-selection allowlist is introduced.
Problem
Starting a routine local automation session often requires an agent to list devices, infer a target,
then repeat platform/device selectors on
open. The explicit path is predictable, but it adds toolcalls and decision points even when exactly one healthy local target is available or the user already
named an unambiguous platform.
The goal is to reduce this bootstrap ceremony without making target choice implicit in ambiguous or
concurrent environments.
Desired outcome
Design one deterministic device-selection policy shared by CLI, Node, MCP, and daemon dispatch so a
routine
opencan select the only sensible local target while ambiguous selection still fails with abounded, actionable candidate list.
Examples of the intended experience:
open <app> --platform iosuses it.command contract explicitly permits that lifecycle transition.
selectors needed to retry.
migrate the session to a different device.
worktrees keep their current isolation/ownership guarantees.
Constraints and source-of-truth seams
CONTEXT.mdand accepted decisions indocs/adr/README.md.src/core/capabilities.ts; do not create a new command-name or capability allowlist.DEVICE_IN_USE; convenience must not bypass a live owneror make two worktrees select the same device.
target. Do not turn local convenience into remote allocation.
not error-message sniffing.
docs/agents/cli-flags.md.Investigation / design questions
open, sessionless inventory/state commands, existingsession reuse, provider targets, default-device helpers) and identify where their precedence rules
differ.
binding -> exactly one already-booted compatible local target -> exactly one compatible local target
whose lifecycle may be prepared -> typed ambiguity/no-candidate result.
the app installed) without making selection expensive or creating success-path parity differences.
openbehavior only or a reusable resolver for everysessionless command that permits a default device.
and retry selectors. Keep it response-level; do not add bytes per snapshot node.
wrong-target rate, not only happy-path latency.
Verification
existing session reuse, one booted target, one bootable target, no target, and multiple targets.
through another fallback.
versus physical serial selection. Add TV/macOS/web/provider cases only where the shared resolver can
actually fire.
loser receives
DEVICE_IN_USEwith the owning session and recovery hint.planning guidance changes.
Acceptance criteria
devicescall.