Repository navigation
feat(boot): let an unscoped boot pick the newest of several shut-down devices - #4042
Conversation
Device selection ranked an Apple device as a tablet only when its name matched /\bipad\b/. A renamed iPad simulator therefore tied with every iPhone and turned an otherwise resolvable request into AMBIGUOUS_MATCH. Discovery already stamps appleOs from the device type, so rank by it and keep the name regex only for records that predate the discriminant.
…down devices A boot that names no device fails with AMBIGUOUS_MATCH whenever several equally preferred devices match. That covers every stock Xcode install, which ships more than one iPhone simulator on one runtime, so a test runner cannot boot "an iPhone" without listing devices and choosing one itself. The refusal is deliberate (callstack#1880): a quietly chosen device answers successfully about the wrong device. `boot --pick newest` (SDK: `devices.boot({ pick: 'newest' })`) is an explicit opt-in, so the caller has said any match will do. It decides only when every equally preferred match is shut down: nothing runs on them yet to be misread, and once one boots, booted-over-offline resolves later unscoped commands to it. It picks a mobile target over a TV, then the newest OS version, then the name. It never picks between booted devices or provider devices, and other commands keep refusing. Boot responses now carry the same `selection` evidence as open, with the new reason `newest-bootable-local`, and the CLI line names the pick.
|
@KrzysztofMoch is attempting to deploy a commit to the Callstack Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
1 issue found across 28 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/commands/management/device.ts">
<violation number="1" location="src/commands/management/device.ts:64">
P3: `selection` is advertised only as an unconstrained object, so MCP/schema consumers cannot discover or validate the new selection fields. Describe its four contract fields while retaining additive properties.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
There was a problem hiding this comment.
🟡 Changes recommended
The cold-pick guard can create ambiguous simulator matches by treating a booting device as shut down, and existing local sessions can incorrectly report that no boot occurred after a successful boot.
2 open issues
What changed in this PR
Adds an explicit boot --pick newest opt-in for ambiguous, shut-down local devices while preserving the default refusal to choose silently.
Changes:
- Wires the boot-only policy through CLI, SDK, daemon resolution, and request claims.
- Reports selection evidence in boot responses and CLI output, with documentation and regression tests.
- Uses
appleOsto keep renamed iPads ranked below iPhones.
| File | Description |
|---|---|
| website/docs/docs/commands.md | Documents the opt-in and its limits. |
| website/docs/docs/client-api.md | Adds SDK usage and selection evidence. |
| src/commands/management/output.ts | Names explicit picks in CLI output. |
| src/commands/management/output.test.ts | Tests picked and ordinary boot output. |
| src/commands/management/device.ts | Adds boot input metadata and response schema. |
| src/commands/command-flags.ts | Forwards the pick option. |
| src/client/client-normalizers.ts | Recognizes the new selection reason. |
| src/cli/parser/__tests__/args-parse-session.test.ts | Tests boot-only flag acceptance. |
| scripts/integration-progress-model.ts | Records local-only flag coverage ownership. |
| packages/session-journal/src/session-event-action.ts | Adds the pick enum to safe boot flags. |
| packages/kernel/src/device.ts | Implements cold-pick ordering and iPad classification. |
| packages/kernel/src/device.test.ts | Tests renamed and legacy iPad ranking. |
| packages/device-selection/src/dispatch-resolve.ts | Passes the policy through inventory resolution. |
| packages/device-selection/src/device-selection-resolver.ts | Applies local picks and emits selection evidence. |
| packages/device-selection/src/__tests__/dispatch-resolve.test.ts | Tests policy propagation for iOS and Android. |
| packages/device-selection/src/__tests__/device-selection-resolver.test.ts | Tests ordering and refusal conditions. |
| packages/daemon/src/sessions/handlers/session-device-status-response.ts | Includes selection metadata in boot responses. |
| packages/daemon/src/sessions/handlers/session-boot.ts | Boots the selected target and reports evidence. |
| packages/daemon/src/sessions/handlers/__tests__/session-device-status-response.test.ts | Updates response-shape assertions. |
| packages/daemon/src/sessions/handlers/__tests__/session-boot.test.ts | Tests policy forwarding, evidence, and hints. |
| packages/daemon/src/server/request-execution-scope.ts | Uses boot selection when resolving device claims. |
| packages/daemon/src/resources/session-device-resolution.ts | Adds boot-specific selection and ambiguity hints. |
| packages/contracts/src/request-envelope.ts | Adds the execution option type. |
| packages/contracts/src/device.ts | Adds boot-result selection metadata. |
| packages/contracts/src/client-device-view.ts | Exposes the SDK boot policy. |
| packages/contracts/src/client-app.ts | Declares the new selection reason. |
| packages/contracts/src/cli-flags.ts | Types the CLI pick flag. |
| packages/command-registry/src/flag-definitions-target.ts | Registers --pick and its help text. |
Review effort: Balanced
The --pick hint was appended to every ambiguous boot, including provider and booted ties that the opt-in cannot settle. Boot now passes a typed intent to the selection resolver, which knows the inventory source and whether a shut-down tie exists, and adds the hint only there. Also document that device ranking (phone over iPad) applies before the pick, align the --pick usage text with the field description, and describe the selection fields in the boot output schema.
There was a problem hiding this comment.
All reported issues were addressed across 9 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
|
The code looks good at 167663c, and I found nothing that needs a change. The only failing check is Vercel, and it looks unrelated: the fork deploy waits for a Callstack member to authorize it, so no build ran. I did not run the live check myself. I accepted the run summary in the PR body because the reported states match the code. I checked the kernel and boot-handler tests by reading them, not by running them without their fixes. Not blocking, and you can take or leave these: the name tie-break in packages/kernel/src/device.ts#L757 is alphabetical, so on a stock Xcode 26 set |
Review follow-ups: with equal OS versions the name tie-break is alphabetical, so iPhone 16e sorts before iPhone 17; say so wherever the order is documented. The ambiguity hint also names the Node/MCP spelling, and markSelectionBootOccurred gains an overload so boot needs no fallback.
|
[claude-opus-5-5] responding on behalf of Krzysztof Thanks, @thymikee. All three suggestions are in d3af7a8:
|
There was a problem hiding this comment.
All reported issues were addressed across 5 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
View guided diff | Re-trigger cubic

Summary
boot --platform iosfails withAMBIGUOUS_MATCHon any Mac with several iPhone simulators, which includes every stock Xcode install. Closes #4041.boot --pick newestis an explicit opt-in. It decides only when every equally preferred local match is shut down: mobile over TV, then the newest OS version, then the name. Booted ties, provider devices and other commands still refuse, so #1880's guarantee holds. Aselectionrecord (reasonnewest-bootable-local) and the CLI output report the pick, and an ambiguousbootnow suggests the opt-in.A second commit ranks iPads by
appleOsrather than by name, so a renamed iPad no longer ties with iPhones. 28 files changed.Validation
check:affected --run --head daf6f912d(66 checks): everything passes except 3 timing tests (daemon-client, Android fill) under load. Those pass 64/64 when run alone, andmainshows the same daemon-client errors on this host. 9 unreached checks (docs, wire-compat, flags) pass when run directly.167663c5a: lint, typecheck, focused tests (device-selection, boot handler, commands, MCP), and the mcp-metadata, command-docs, docs, wire-compat and progress-model gates all pass.bootrefuses;--pick newestboots iPhone 17;main144bd59 and passes here.Changes made by Claude Opus 5.5 running in Claude Code (T3 Code).