Skip to content

fix(simulator): Make simulator platform inference deterministic#472

Merged
cameroncooke merged 3 commits into
mainfrom
fix/simulator-platform-inference
Jul 11, 2026
Merged

fix(simulator): Make simulator platform inference deterministic#472
cameroncooke merged 3 commits into
mainfrom
fix/simulator-platform-inference

Conversation

@cameroncooke

Copy link
Copy Markdown
Collaborator

Simulator tools could build for the wrong platform. With an iPhone simulator selected via setup, simulator build produced platform=visionOS Simulator for an iOS app that also supports visionOS, failing with "Unable to find a device matching the provided destination specifier".

Root cause

When the selected simulator is unavailable (e.g. its runtime was removed by an Xcode upgrade, leaving a stale device record), platform inference found nothing in simctl list devices available and fell through to guessing from the scheme's SUPPORTED_PLATFORMS — which checked xrsimulator before iphonesimulator. For any multi-platform app the result was a coin toss, rigged toward visionOS.

Changes

  • Setup persists simulatorPlatform, derived from the selected simulator's runtime. Inference short-circuits on this cached, device-derived value — the session-defaults field existed but nothing ever wrote it.
  • The build-settings and default-iOS fallbacks are removed from inferPlatform. Guessing a destination from SUPPORTED_PLATFORMS is inherently non-deterministic for multi-platform apps; if no authoritative source resolves, tools now fail fast with a clear error pointing at setup.
  • The CLI hydrates the session store from project config (mirroring the MCP bootstrap) so the cached platform is visible to one-shot CLI invocations.
  • Setup's picker no longer offers unavailable simulators (dead device records whose runtime is uninstalled).
  • Xcode IDE sync invalidates the cached platform when it changes the simulator selector (bootstrap sync + state watcher), so a stale cache can't be applied to a different device.
  • build_run_sim shows the real platform name instead of downgrading to a generic "Simulator" when inference came from the cache.
  • Dead detectPlatformFromScheme removed — it carried the visionOS-over-iOS ordering bug and had no remaining callers.

The background defaults refresh keeps its name → id re-materialization: simulatorName remains the canonical, machine-portable selector for SCM-shared configs, and the refresh updates the machine-local UDID from it. This contract, and the deliberate asymmetry that one-shot CLI runs stay deterministic for CI (fail fast on a stale/foreign UDID rather than silently re-resolving), is now codified in code comments and schema descriptions.

Notes for review

  • inferPlatform now throws when it cannot resolve — build_run_sim converts that into a structured error via its existing prepare catch, while build_sim/test_sim surface it as a runtime tool error.
  • Snapshot fixtures are untouched; no fixture output changes under the recording environment.

Co-Authored-By: Claude noreply@anthropic.com

An iOS app that also supports visionOS could build for the wrong
platform: when the selected simulator was unavailable (e.g. its runtime
was removed by an Xcode upgrade), inference fell back to guessing from
SUPPORTED_PLATFORMS, which prefers xrsimulator over iphonesimulator.

- Persist simulatorPlatform during setup, derived from the selected
  simulator's runtime, so tools short-circuit on a cached authoritative
  value instead of guessing
- Remove the build-settings and default-iOS fallbacks from
  inferPlatform; throw a clear error when no source resolves
- Hydrate the CLI session store from project config so the cached
  platform is visible to one-shot CLI invocations
- Filter unavailable simulators out of the setup picker
- Invalidate the cached platform when Xcode sync changes the selector
- Keep name -> id re-materialization in the background refresh
  (simulatorName stays the canonical, machine-portable selector for
  SCM-shared configs) and skip it when nothing resolves
- Remove the now-dead detectPlatformFromScheme

Co-Authored-By: Claude <noreply@anthropic.com>
@pkg-pr-new

pkg-pr-new Bot commented Jul 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/xcodebuildmcp@472

commit: 4df2605

Codify two rules in AGENTS.md and CLAUDE.md:

- Never run the snapshot or smoke test suites without explicit user
  permission; they are expensive (~7 min, real xcodebuild/simctl
  processes) while the unit suite, typecheck, lint, and build remain
  free to run
- Structured errors (domain results with didError) are for domain
  errors only; system errors with the MCP server or CLI itself must
  surface as runtime tool errors

Co-Authored-By: Claude <noreply@anthropic.com>
Comment thread src/utils/simulator-defaults-refresh.ts
Comment thread src/cli/commands/setup.ts
- Clear the cached simulatorPlatform when the background refresh remaps
  the simulator id but the platform recompute fails, so a new id is
  never paired with the previous device's platform
- Report simulatorPlatform changes in the setup summary

Co-Authored-By: Claude <noreply@anthropic.com>

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4df2605. Configure here.

Comment thread src/cli/register-tool-commands.ts
@cameroncooke cameroncooke merged commit 1ec584f into main Jul 11, 2026
45 checks passed
@cameroncooke cameroncooke deleted the fix/simulator-platform-inference branch July 11, 2026 22:02
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.

1 participant