Skip to content

fix(ios): report devices CoreDevice cannot reach as not booted - #4210

Open
gronxb wants to merge 5 commits into
callstack:mainfrom
gronxb:fix/ios-unavailable-device-not-booted
Open

gronxb wants to merge 5 commits into
callstack:mainfrom
gronxb:fix/ios-unavailable-device-not-booted

Conversation

@gronxb

@gronxb gronxb commented Nov 4, 2026 •

Copy link
Copy Markdown

Summary

The devicectl inventory marked every paired device as booted. A paired iPhone that was unplugged and off the network was listed as booted: true, and boot succeeded on it. The app launch was the first command to fail, with CoreDeviceError 4016.

  • mapDevicectlAppleDevice lists an unavailable tunnel state as booted: false. Both call sites use isCoreDeviceReachable, which ignores case and non-string values.
  • ensureCoreDeviceReady refuses unavailable as not_ready with details.tunnelState. connected, disconnected (CoreDevice opens tunnels on demand), and an absent state still pass.
  • The physical-device help and installation.md describe this. The help sentence is on the existing "connected" line because cli-help.ts is at the 1,000-line limit.

6 files, no scope expansion. Moving off devicectl's deprecated connectionProperties is a separate change.

Fixes #4209

Validation

Base 035c2b6ca, head 73c49187d.

  • pnpm check:affected --run --head 73c49187d passed (exactCommit: true).
  • The new unit tests fail on base.
  • Live, on a paired iPhone whose tunnel state is unavailable, with agent-device-repro@ios-unavailable-device:
    • Base and 0.21.36: booted: true, boot succeeds, ./repro.sh exits 1.
    • Head: booted: false, boot fails with not_ready/unavailable, ./repro.sh exits 0. Booting a simulator still works.
  • CI owns the device lanes.
  • Risks:
    • The connected and disconnected paths are covered by unit tests only. No reachable device was available.

devicectl lists every paired device, and the inventory mapped each one as
booted, so a phone that was unplugged and off the network was listed as
booted and passed boot. The first command that failed was the app launch.

The devicectl mapping now reads connectionProperties.tunnelState and
reports an unavailable device as not booted, and CoreDevice readiness
refuses it as not_ready with a hint to connect it.

Fixes callstack#4209
The physical-device help and the installation page now say how devices
and readiness report a paired device that CoreDevice cannot reach.
@vercel

vercel Bot commented Nov 4, 2026

Copy link
Copy Markdown

@gronxb is attempting to deploy a commit to the Callstack Team on Vercel.

A member of the Team first needs to authorize it.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 6 files

Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.

View guided diff | Re-trigger cubic

The inventory mapping and the readiness check each compared the tunnel
state to 'unavailable', and only readiness lowercased it first. Both now
call isCoreDeviceUnreachable, which lives beside the readiness constants
so neither eager import closure grows.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

The inventory reads devicectl JSON without validating it at runtime, so
isCoreDeviceUnreachable lowercased whatever tunnelState held and would
throw on a non-string, breaking the whole device listing. It now returns
false for anything that is not a string.
isCoreDeviceReachable states the positive case, which is what booted
reports, so the inventory assigns it directly and readiness negates it.
@thymikee

thymikee commented Nov 4, 2026

Copy link
Copy Markdown
Member

At b814e92, the code looks good. Tunnel reachability is decided once, by the CoreDevice predicate in physical-device-constants.ts. Both the inventory mapping and the readiness check use it, so an unreachable paired iPhone now shows booted: false and boot fails with a typed not_ready reason. The base-vs-head live run with your repro script covers the change. If it is easy, pasting the head output of ./repro.sh here would make it auditable.

Not blocking, take or leave: the help sentence could say it applies to boot and to commands that check readiness, and a routed test that feeds an unavailable CoreDevice record through devices and boot would pin the user-facing output.

No GitHub Actions checks have run on this head yet; the only failing check is the Vercel deployment authorization. No conflicts are known.

@gronxb
gronxb force-pushed the fix/ios-unavailable-device-not-booted branch from fef0f60 to 73c4918 Compare November 4, 2026 05:42
@gronxb

gronxb commented Nov 4, 2026

Copy link
Copy Markdown
Author

Thanks! Head output of ./repro.sh at 73c4918, on a paired iPhone that is unplugged and off Wi-Fi:

agent-device: 0.21.37-dev
xcode: Xcode 27.2
device: 00008160-XXXXXXXXXXXXXXXX, devicectl tunnelState=unavailable

PASS  devices lists the unreachable device with booted: false
PASS  boot refuses the unreachable device as not_ready

The same script on 0.21.36 prints booted: true and boot succeeded, and exits 1. pnpm check:affected --run --head 73c49187d passed (exactCommit: true).

The only change since b814e92 is a rename: the classifier is now isCoreDeviceReachable, the positive case that booted reports. I left out the help wording and the routed test to keep this PR to the fix.

@gronxb

gronxb commented Nov 4, 2026

Copy link
Copy Markdown
Author

@cubic review

@cubic-dev-ai

cubic-dev-ai Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

@cubic review

@gronxb I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 7 files

View guided diff | Re-trigger cubic

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unreachable paired iOS device is listed as booted and passes boot

2 participants