stim 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +3 -1
  2. package/dist/{android-Da-G_o3n.mjs → android-BRgBYzU0.mjs} +7 -7
  3. package/dist/{app-install-DJg7bVv-.mjs → app-install-BDbsSgCl.mjs} +1 -1
  4. package/dist/cli.mjs +11 -11
  5. package/dist/{dev-client-DDUkWgJL.mjs → dev-client-BmT-ioFI.mjs} +2 -2
  6. package/dist/{device-CLeDp-KH.mjs → device-BUoZyMoR.mjs} +18 -11
  7. package/dist/{device-CBSaC6BU.mjs → device-RdujjHLB.mjs} +2 -2
  8. package/dist/{device-pool-DNSHL5z8.mjs → device-pool-BxRwdufO.mjs} +1 -1
  9. package/dist/{device-remote-BprxZp-m.mjs → device-remote-ByN8P6CB.mjs} +23 -16
  10. package/dist/{doctor-CTAx9gMu.mjs → doctor-BMt156qe.mjs} +3 -3
  11. package/dist/{gc-CX0KRfLG.mjs → gc-v2YcoJvm.mjs} +4 -4
  12. package/dist/{guide-CPmAG9me.mjs → guide-BTAlD1_y.mjs} +30 -4
  13. package/dist/{ios-BRXYSxSc.mjs → ios-BP04pY5f.mjs} +34 -11
  14. package/dist/{ios-lEJ5pKsq.mjs → ios-BcCiI4TS.mjs} +41 -8
  15. package/dist/{ios-device-CDbvn5H2.mjs → ios-device-CauFJiYx.mjs} +1 -1
  16. package/dist/{ownership-D5vkdm8H.mjs → ownership-wolE-0Do.mjs} +3 -8
  17. package/dist/public-http-probe-CyMDrQ3c.mjs +61 -0
  18. package/dist/{reclaim-D614jI6_.mjs → reclaim-KJ-0uWEF.mjs} +3 -3
  19. package/dist/{reload-ChW46VDb.mjs → reload-BdypPbjM.mjs} +3 -3
  20. package/dist/{slot-launch-DbLvyrup.mjs → slot-launch-ZUUe0TQP.mjs} +1 -1
  21. package/dist/{start-TTVILlUi.mjs → start-CmxtOKjU.mjs} +1 -1
  22. package/dist/{status-DUNy_HZs.mjs → status-DdkLki47.mjs} +4 -4
  23. package/dist/{stop-CnUpnFT5.mjs → stop-B1kOpYei.mjs} +2 -2
  24. package/dist/{stop-ZrfODZ51.mjs → stop-C8JW6kKp.mjs} +3 -3
  25. package/dist/{teardown-5J5UXz2P.mjs → teardown-BJqEzPo_.mjs} +1 -1
  26. package/dist/{worktree-BfE4lzHK.mjs → worktree-CFLA-6MX.mjs} +3 -3
  27. package/package.json +5 -5
package/README.md CHANGED
@@ -26,7 +26,9 @@ Node 22.12.0 or later is required.
26
26
 
27
27
  Machine defaults in `~/.stim/config.json` can enable or disable native artifact
28
28
  caching, remote caches, Metro sharing, iOS compiler caching and prefix mapping,
29
- and Android ccache/CAS, PCH, Gradle caching, and target ABI narrowing. Optional
29
+ and Android ccache/CAS, PCH, Gradle caching, and target ABI narrowing. The
30
+ top-level `iosSimulatorApp` setting selects Xcode's viewer or an installed
31
+ Siniulator.
30
32
  `.stim.json` runtime overrides apply per app, beside its `package.json`; monorepo
31
33
  apps do not inherit the repository-root file. Worktree-copy rules stay at the
32
34
  repository root. Run `stim guide settings` for the
@@ -13,18 +13,18 @@ import { B as waitForBoot, E as memoizeEmulatorProbe, F as resetAdoptedAvd, I as
13
13
  import { _ as launchErrorPreview, c as launchErrorReport, g as stepTimer, h as stepClock, i as formatDuration, l as phaseLine, n as appReadinessMessage, p as shortHash } from "./command-output-B3ycpsYv.mjs";
14
14
  import { C as untrackedNativeFiles, D as readAssetManifest, E as compareAssetManifests, S as untrackedMissLine, T as captureAssetManifest, _ as providerUploadOutcome, b as storeBuild, c as buildCacheKey, d as filesystemBuildCapability, f as fingerprintDiffRecord, g as providerDownloadPath, h as prepareProviderDownloadDir, i as releaseBuildLock, l as describeFingerprintMiss, m as fingerprintProject, n as acquireBuildLock, o as takeoverLine, p as fingerprintDiffSuffix, s as waitForBuild, t as WAIT_CEILING_MS, v as refingerprintAfterMutation, w as assetDiffReason, x as storedAssetManifest, y as resolveBuild } from "./build-lock-CgtsB6TV.mjs";
15
15
  import { t as cleanLine } from "./server-expo-BVAA1OqJ.mjs";
16
- import { C as resolveRemote, S as resolveEasCliBin, _ as exitAfterFlush, f as RESOLVE_TIMEOUT_MS, g as easAuthNote, h as checkEasAuth, l as parkedMaxSetting, m as cacheLevel, p as UPLOAD_TIMEOUT_MS, v as isEasAuthFailureText, w as uploadRemote, y as loadProjectProvider } from "./teardown-5J5UXz2P.mjs";
17
- import { c as ensureWorkspaceStorageSafely, d as launchOutcomeRecord, f as noMetroMessage, g as warmMetro, i as detectEntryFile, m as resolveMetroWithRetry, n as pickDevClientScheme, o as needsPrebuild, p as noMetroRemedy, s as runPrebuild, t as devClientScheme, u as isPhysicalDeviceRequest, v as isEasBuildFailure, y as resolveEasDevelopmentBuild } from "./dev-client-DDUkWgJL.mjs";
16
+ import { C as resolveRemote, S as resolveEasCliBin, _ as exitAfterFlush, f as RESOLVE_TIMEOUT_MS, g as easAuthNote, h as checkEasAuth, l as parkedMaxSetting, m as cacheLevel, p as UPLOAD_TIMEOUT_MS, v as isEasAuthFailureText, w as uploadRemote, y as loadProjectProvider } from "./teardown-BJqEzPo_.mjs";
17
+ import { c as ensureWorkspaceStorageSafely, d as launchOutcomeRecord, f as noMetroMessage, g as warmMetro, i as detectEntryFile, m as resolveMetroWithRetry, n as pickDevClientScheme, o as needsPrebuild, p as noMetroRemedy, s as runPrebuild, t as devClientScheme, u as isPhysicalDeviceRequest, v as isEasBuildFailure, y as resolveEasDevelopmentBuild } from "./dev-client-BmT-ioFI.mjs";
18
18
  import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BYfZz_S-.mjs";
19
- import { D as verifyAndroidReleaseLaunch, E as unverifiedLaunchLines, O as verifyLaunch, S as launchAndroidReleaseApp, _ as installConflictKind, c as RELEASE_VERIFY_WAIT_MS, d as androidDevClientUrl, g as installAndroidApp, h as deviceShellArg, i as LAUNCH_BUNDLING, l as VERIFY_TIMEOUT_MS, n as DEFAULT_METRO_PORT, o as LAUNCH_FATAL, s as LAUNCH_UNVERIFIED, t as ADB_INSTALL_TIMEOUT_MS, u as androidAppProcess, x as launchAndroidApp } from "./app-install-DJg7bVv-.mjs";
20
- import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-DNSHL5z8.mjs";
19
+ import { D as verifyAndroidReleaseLaunch, E as unverifiedLaunchLines, O as verifyLaunch, S as launchAndroidReleaseApp, _ as installConflictKind, c as RELEASE_VERIFY_WAIT_MS, d as androidDevClientUrl, g as installAndroidApp, h as deviceShellArg, i as LAUNCH_BUNDLING, l as VERIFY_TIMEOUT_MS, n as DEFAULT_METRO_PORT, o as LAUNCH_FATAL, s as LAUNCH_UNVERIFIED, t as ADB_INSTALL_TIMEOUT_MS, u as androidAppProcess, x as launchAndroidApp } from "./app-install-BDbsSgCl.mjs";
20
+ import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-BxRwdufO.mjs";
21
21
  import { r as releaseBuildSlot, t as acquireBuildSlot } from "./build-slots-C-oAHRT1.mjs";
22
22
  import { a as statsProjectKey, i as recordRunStats, n as readRunEstimates, t as createRunRecorder } from "./stats-BYcZ6n1h.mjs";
23
- import { i as ensureOwnedDevice, l as AvdBootError, o as unknownAndroidSystemImageRefusal, r as ensureBooted, t as checkDeviceCapacity, u as AvdRecoveryError } from "./device-CLeDp-KH.mjs";
24
- import { a as ensureMetroReachable, b as ownedSessionName, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, s as remoteAndroidDeps } from "./device-remote-BprxZp-m.mjs";
23
+ import { i as ensureOwnedDevice, l as AvdBootError, o as unknownAndroidSystemImageRefusal, r as ensureBooted, t as checkDeviceCapacity, u as AvdRecoveryError } from "./device-BUoZyMoR.mjs";
24
+ import { a as ensureMetroReachable, b as ownedSessionName, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, s as remoteAndroidDeps } from "./device-remote-ByN8P6CB.mjs";
25
25
  import { a as buildAndroid, c as CCACHE_NOT_RUN, f as resolveCcache, l as CCACHE_UNAVAILABLE, n as resolveAndroidCas, o as productFlavorRefusal, p as formatDiagnostic, r as resolveAndroidCompilerCache, s as readProductFlavors, u as ccacheActivityLine } from "./android-cas-SWIjzeuL.mjs";
26
26
  import { d as startBuildHeartbeat, f as tailLines, n as HEARTBEAT_INTERVAL_MS } from "./xcode-B6YaWeg0.mjs";
27
- import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-DbLvyrup.mjs";
27
+ import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-ZUUe0TQP.mjs";
28
28
  import { t as spawnEntry } from "./spawn-entry-nCE6m770.mjs";
29
29
  import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-D1Kaf-eT.mjs";
30
30
  import { constants, copyFileSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync } from "node:fs";
@@ -2,7 +2,7 @@ import { t as getExecutor } from "./exec-B29XNuhP.mjs";
2
2
  import { o as parseNdjsonText } from "./ndjson-BZwI1NBv.mjs";
3
3
  import { t as DEV_MENU_LAUNCH_ARGS } from "./ios-device-CFXA46ez.mjs";
4
4
  import { s as isAppLaunchError } from "./command-output-B3ycpsYv.mjs";
5
- import { l as iosSimulatorFailureAdvice, p as listUserApps, w as uninstallIosApp } from "./ios-lEJ5pKsq.mjs";
5
+ import { l as iosSimulatorFailureAdvice, p as listUserApps, w as uninstallIosApp } from "./ios-BcCiI4TS.mjs";
6
6
  import { closeSync, lstatSync, openSync, readFileSync, readSync, readdirSync } from "node:fs";
7
7
  import { createHash } from "node:crypto";
8
8
  import { isAbsolute, join } from "node:path";
package/dist/cli.mjs CHANGED
@@ -3,20 +3,20 @@ import { readFileSync } from "node:fs";
3
3
  import { Command } from "commander";
4
4
  //#region bin/cli.ts
5
5
  const commands = /* @__PURE__ */ new Map([
6
- ["doctor", () => import("./doctor-CTAx9gMu.mjs")],
7
- ["worktree", () => import("./worktree-BfE4lzHK.mjs")],
8
- ["start", () => import("./start-TTVILlUi.mjs")],
6
+ ["doctor", () => import("./doctor-BMt156qe.mjs")],
7
+ ["worktree", () => import("./worktree-CFLA-6MX.mjs")],
8
+ ["start", () => import("./start-CmxtOKjU.mjs")],
9
9
  ["ports", () => import("./ports-BIbJaKNW.mjs")],
10
- ["stop", () => import("./stop-CnUpnFT5.mjs")],
11
- ["ios", () => import("./ios-BRXYSxSc.mjs")],
12
- ["android", () => import("./android-Da-G_o3n.mjs")],
13
- ["reload", () => import("./reload-ChW46VDb.mjs")],
14
- ["device", () => import("./device-CBSaC6BU.mjs")],
10
+ ["stop", () => import("./stop-B1kOpYei.mjs")],
11
+ ["ios", () => import("./ios-BP04pY5f.mjs")],
12
+ ["android", () => import("./android-BRgBYzU0.mjs")],
13
+ ["reload", () => import("./reload-BdypPbjM.mjs")],
14
+ ["device", () => import("./device-RdujjHLB.mjs")],
15
15
  ["logs", () => import("./logs-CakdBTtm.mjs")],
16
- ["status", () => import("./status-DUNy_HZs.mjs")],
16
+ ["status", () => import("./status-DdkLki47.mjs")],
17
17
  ["stats", () => import("./stats-CLg5RuDS.mjs")],
18
- ["gc", () => import("./gc-CX0KRfLG.mjs")],
19
- ["guide", () => import("./guide-CPmAG9me.mjs")]
18
+ ["gc", () => import("./gc-v2YcoJvm.mjs")],
19
+ ["guide", () => import("./guide-BTAlD1_y.mjs")]
20
20
  ]);
21
21
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
22
22
  const program = new Command();
@@ -7,8 +7,8 @@ import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./proc
7
7
  import { t as NOT_OURS_FOREIGN_CWD } from "./metro-C7bcJ0uo.mjs";
8
8
  import { i as releaseBuildLock, n as acquireBuildLock } from "./build-lock-CgtsB6TV.mjs";
9
9
  import { i as expoBinRefusal, r as expoBinPath, t as cleanLine } from "./server-expo-BVAA1OqJ.mjs";
10
- import { S as resolveEasCliBin } from "./teardown-5J5UXz2P.mjs";
11
- import { i as LAUNCH_BUNDLING, s as LAUNCH_UNVERIFIED } from "./app-install-DJg7bVv-.mjs";
10
+ import { S as resolveEasCliBin } from "./teardown-BJqEzPo_.mjs";
11
+ import { i as LAUNCH_BUNDLING, s as LAUNCH_UNVERIFIED } from "./app-install-BDbsSgCl.mjs";
12
12
  import { d as startBuildHeartbeat, f as tailLines, n as HEARTBEAT_INTERVAL_MS } from "./xcode-B6YaWeg0.mjs";
13
13
  import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
14
14
  import { createHash } from "node:crypto";
@@ -7,9 +7,9 @@ import { i as pidExists } from "./metro-C7bcJ0uo.mjs";
7
7
  import { l as androidDataPartitionSizeGbSetting, o as androidAvdConfigSetting, v as iosSimSlimProfileSetting } from "./settings-BXXorVM2.mjs";
8
8
  import { A as ownedAvdName, B as waitForBoot, C as listAvds, D as nextConsolePort, I as resolveOwnedAvdSerial, N as pickDefaultSystemImage, S as listAdbDevices, b as getAvdNameForSerial, c as assertOwnedAvdStopped, f as bootAndroidEmulator, j as ownedAvdSystemImage, k as ownedAvdMatchesConfiguration, m as createOwnedAvd, p as configureNewOwnedAvd, u as avdPoolConfiguration, w as listInstalledSystemImages } from "./android-DWssqHQ8.mjs";
9
9
  import { l as phaseLine } from "./command-output-B3ycpsYv.mjs";
10
- import { c as isLegacyDeletionClaim, d as selectParked, i as teardownParkedIosSim, l as parkedMaxSetting, o as adoptParked, r as teardownParkedAvd, s as dropParked, t as teardownOwnedAvd, u as readParked } from "./teardown-5J5UXz2P.mjs";
10
+ import { c as isLegacyDeletionClaim, d as selectParked, i as teardownParkedIosSim, l as parkedMaxSetting, o as adoptParked, r as teardownParkedAvd, s as dropParked, t as teardownOwnedAvd, u as readParked } from "./teardown-BJqEzPo_.mjs";
11
11
  import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BYfZz_S-.mjs";
12
- import { E as readHostMemoryPressure, T as hostMemoryPressureAdvice, _ as renameIosSim, b as resolveIosCreation, c as iosRuntimeMatches, d as listIosDeviceTypes, g as parseRuntimeVersion, i as createOwnedIosSim, l as iosSimulatorFailureAdvice, m as ownedSimName, n as bootIosSim, u as listAllIosSims, v as resetIosKeychain, x as resolveOwnedIosSim, y as resetIosPrivacy } from "./ios-lEJ5pKsq.mjs";
12
+ import { D as hostMemoryPressureAdvice, O as readHostMemoryPressure, T as configuredIosSimulatorViewer, _ as renameIosSim, b as resolveIosCreation, c as iosRuntimeMatches, d as listIosDeviceTypes, g as parseRuntimeVersion, i as createOwnedIosSim, l as iosSimulatorFailureAdvice, m as ownedSimName, n as bootIosSim, u as listAllIosSims, v as resetIosKeychain, x as resolveOwnedIosSim, y as resetIosPrivacy } from "./ios-BcCiI4TS.mjs";
13
13
  import { randomUUID } from "node:crypto";
14
14
  import { join } from "node:path";
15
15
  import { claimRemoveCommand, clearClaimChild, markClaimChildPending, processGroupAlive, releaseClaim, setClaimChild } from "@stim-cli/core/ownership-claim";
@@ -313,11 +313,12 @@ async function prepareOwnedAvd({ projectPath, slot, label, previousAvdName, syst
313
313
  //#region src/engine/device.ts
314
314
  const ANDROID_FRESH_BOOT_TIMEOUT_MS = process.platform === "win32" ? 12e5 : 12e4;
315
315
  const ANDROID_BOOT_TIMEOUT_MS = process.platform === "win32" ? 12e5 : 24e4;
316
- function startIosBoot(udid, configure, label, out) {
316
+ function startIosBoot(udid, configure, label, out, simulatorApp) {
317
317
  const done = (async () => {
318
318
  await bootIosSim(udid, {
319
319
  label,
320
- out
320
+ out,
321
+ simulatorApp
321
322
  });
322
323
  await configure();
323
324
  })();
@@ -405,7 +406,7 @@ async function ensureOwnedIosDevice({ record, projectPath, slot, settingsRoot, l
405
406
  out(chalk.dim(phaseLine("device", `booting ${name} (${sim.udid})`)));
406
407
  return {
407
408
  ...updated,
408
- booting: startIosBoot(sim.udid, configure, name, out),
409
+ booting: startIosBoot(sim.udid, configure, name, out, flags.simulatorApp),
409
410
  ...facts
410
411
  };
411
412
  }
@@ -454,7 +455,7 @@ async function ensureOwnedIosDevice({ record, projectPath, slot, settingsRoot, l
454
455
  out,
455
456
  reconcileIosSimulator
456
457
  });
457
- }, adopted.deviceName, out);
458
+ }, adopted.deviceName, out, flags.simulatorApp);
458
459
  return {
459
460
  ...adopted,
460
461
  booting,
@@ -487,7 +488,7 @@ async function ensureOwnedIosDevice({ record, projectPath, slot, settingsRoot, l
487
488
  profile: simslimProfile,
488
489
  out,
489
490
  reconcileIosSimulator
490
- }), created.name, out);
491
+ }), created.name, out, flags.simulatorApp);
491
492
  return {
492
493
  ...newRecord,
493
494
  created: true,
@@ -969,9 +970,10 @@ function unknownAndroidSystemImageRefusal(requested, images) {
969
970
  };
970
971
  }
971
972
  const BOOT_POLL_MS = 500;
972
- async function ensureBooted({ platform, device, timeoutMs, pollMs = BOOT_POLL_MS, out = () => {}, logFile = null, alive = pidExists } = {}) {
973
+ async function ensureBooted({ platform, device, simulatorApp, timeoutMs, pollMs = BOOT_POLL_MS, out = () => {}, logFile = null, alive = pidExists } = {}) {
973
974
  if (platform === "ios") return ensureIosBooted({
974
975
  device,
976
+ simulatorApp,
975
977
  timeoutMs: timeoutMs ?? 6e5,
976
978
  pollMs,
977
979
  out
@@ -988,7 +990,7 @@ async function ensureBooted({ platform, device, timeoutMs, pollMs = BOOT_POLL_MS
988
990
  reason: `Unknown platform "${platform}".`
989
991
  };
990
992
  }
991
- async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
993
+ async function ensureIosBooted({ device, simulatorApp, timeoutMs, pollMs, out }) {
992
994
  const udid = device?.deviceUdid;
993
995
  if (!udid) return {
994
996
  failed: true,
@@ -1044,14 +1046,19 @@ async function ensureIosBooted({ device, timeoutMs, pollMs, out }) {
1044
1046
  reason: `Simulator ${udid} is now named "${resolved.notOwned}" and is not Stim-owned; refusing to boot it.`
1045
1047
  };
1046
1048
  const sim = resolved.sim;
1047
- if (sim.state === "Booted") return ready();
1049
+ if (sim.state === "Booted") {
1050
+ const result = ready();
1051
+ if (result.ok && simulatorApp !== void 0) configuredIosSimulatorViewer(simulatorApp).open(udid);
1052
+ return result;
1053
+ }
1048
1054
  out(chalk.dim(phaseLine("device", `booting ${sim.name} (${udid})`)));
1049
1055
  const bootDeadline = Date.now() + timeoutMs;
1050
1056
  try {
1051
1057
  await bootIosSim(udid, {
1052
1058
  timeoutMs,
1053
1059
  label: sim.name,
1054
- out
1060
+ out,
1061
+ simulatorApp
1055
1062
  });
1056
1063
  } catch (e) {
1057
1064
  return {
@@ -3,8 +3,8 @@ import { a as findProjectRoot } from "./project-DDZWf_16.mjs";
3
3
  import { E as memoizeEmulatorProbe, L as resolvePhysicalDevice, M as physicalDeviceModel, P as probeEmulatorSerial, S as listAdbDevices, a as androidPoolNoCandidatesRefusal, i as androidPoolCandidates } from "./android-DWssqHQ8.mjs";
4
4
  import { r as clockTime } from "./command-output-B3ycpsYv.mjs";
5
5
  import { f as takeLease, l as releaseWorkspaceLeases, n as fileLeaseIo, o as parseLeaseDuration } from "./device-lease-Ffz_M5t0.mjs";
6
- import { d as waitForDevice, s as parseDeviceWait, t as selectFromPool } from "./device-pool-DNSHL5z8.mjs";
7
- import { c as listIosDevices, o as iosPoolCandidates, s as iosPoolNoCandidatesRefusal, u as resolveIosPhysicalDevice } from "./ios-device-CDbvn5H2.mjs";
6
+ import { d as waitForDevice, s as parseDeviceWait, t as selectFromPool } from "./device-pool-BxRwdufO.mjs";
7
+ import { c as listIosDevices, o as iosPoolCandidates, s as iosPoolNoCandidatesRefusal, u as resolveIosPhysicalDevice } from "./ios-device-CauFJiYx.mjs";
8
8
  import chalk from "chalk";
9
9
  //#region src/commands/device.ts
10
10
  const DEFAULT_FOR = "5m";
@@ -1,6 +1,6 @@
1
1
  import { F as deviceSlotKey } from "./config-B7iyKWkL.mjs";
2
2
  import { a as formatElapsed, r as clockTime } from "./command-output-B3ycpsYv.mjs";
3
- import { A as APP_READINESS_TIMEOUT_MS, l as VERIFY_TIMEOUT_MS } from "./app-install-DJg7bVv-.mjs";
3
+ import { A as APP_READINESS_TIMEOUT_MS, l as VERIFY_TIMEOUT_MS } from "./app-install-BDbsSgCl.mjs";
4
4
  import { a as parseLease, c as releaseRunLease, d as selectPoolDevice, f as takeLease, n as fileLeaseIo, r as leaseIsExpired, s as raiseLease, t as deviceLeasePath } from "./device-lease-Ffz_M5t0.mjs";
5
5
  //#region src/engine/device-lease-run.ts
6
6
  const LEASE_STEP_FLOOR_MS = 6e4;
@@ -5,8 +5,9 @@ import { a as clearRemoteSession, l as readRemoteSession, s as readMetroTunnel }
5
5
  import { i as pidExists } from "./metro-C7bcJ0uo.mjs";
6
6
  import { z as planMetroReach } from "./settings-BXXorVM2.mjs";
7
7
  import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BYfZz_S-.mjs";
8
- import { T as readMetroRecords, a as LAUNCH_ERROR, b as isBundleProof, p as devClientDeepLink, r as INSTALL_ERROR } from "./app-install-DJg7bVv-.mjs";
9
- import { S as sanitizeDeviceLabel } from "./ios-lEJ5pKsq.mjs";
8
+ import { T as readMetroRecords, a as LAUNCH_ERROR, b as isBundleProof, p as devClientDeepLink, r as INSTALL_ERROR } from "./app-install-BDbsSgCl.mjs";
9
+ import { S as sanitizeDeviceLabel } from "./ios-BcCiI4TS.mjs";
10
+ import { t as probePublicHttp } from "./public-http-probe-CyMDrQ3c.mjs";
10
11
  import { existsSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
11
12
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
12
13
  import { homedir } from "node:os";
@@ -18,31 +19,37 @@ function probeBundleUrl(origin, platform, entryPoint = "index") {
18
19
  const entry = entryPoint.replace(/^\/+/, "").replace(/\.(?:[cm]?[jt]sx?)$/, "");
19
20
  return `${origin.replace(/\/+$/, "")}/${entry}.bundle?platform=${platform}&dev=true`;
20
21
  }
21
- const defaultProbe = async (url, signal) => {
22
- try {
23
- return (await fetch(url, {
24
- signal,
25
- redirect: "follow"
26
- })).status;
27
- } catch {
28
- return null;
29
- }
30
- };
31
- async function gateMetroOrigin({ origin, metroPort, platform, entryPoint = "index", readRecords, isProof, probe = defaultProbe, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), timeoutMs = GATE_TIMEOUT_MS }) {
22
+ async function gateMetroOrigin({ origin, metroPort, platform, entryPoint = "index", readRecords, isProof, probe = probePublicHttp, now = Date.now, sleep = (ms) => new Promise((r) => setTimeout(r, ms)), timeoutMs = GATE_TIMEOUT_MS }) {
32
23
  const since = now();
33
24
  const controller = new AbortController();
34
- const request = probe(probeBundleUrl(origin, platform, entryPoint), controller.signal);
35
- request.catch(() => {});
25
+ const bundleUrl = probeBundleUrl(origin, platform, entryPoint);
26
+ let status = null;
27
+ let pending = false;
28
+ let request = Promise.resolve();
29
+ const startProbe = () => {
30
+ pending = true;
31
+ request = (async () => {
32
+ try {
33
+ status = await probe(bundleUrl, controller.signal);
34
+ } catch {
35
+ status = null;
36
+ } finally {
37
+ pending = false;
38
+ }
39
+ })();
40
+ };
41
+ startProbe();
36
42
  try {
37
43
  const deadline = now() + timeoutMs;
38
44
  while (now() < deadline) {
39
45
  for (const record of readRecords()) if (isProof(record, since)) return { ok: true };
46
+ if (!pending && status === null) startProbe();
40
47
  await sleep(POLL_MS);
41
48
  }
42
49
  } finally {
43
50
  controller.abort();
44
51
  }
45
- const status = await request.catch(() => null);
52
+ await request;
46
53
  return {
47
54
  failed: true,
48
55
  code: REMOTE_METRO_WRONG,
@@ -7,10 +7,10 @@ import { A as resolveSettings, E as remoteAndroidSetting, I as unknownSettingKey
7
7
  import { S as listAdbDevices, x as hostSystemImageArch } from "./android-DWssqHQ8.mjs";
8
8
  import { d as quotedPath, l as phaseLine, u as plural } from "./command-output-B3ycpsYv.mjs";
9
9
  import { m as fingerprintProject, r as listBuildLocks, u as diffFingerprintSources } from "./build-lock-CgtsB6TV.mjs";
10
- import { S as resolveEasCliBin, a as POOL_SETTING_REMEDY, b as ownerFromConfig, h as checkEasAuth$1, l as parkedMaxSetting, x as providerFromConfig } from "./teardown-5J5UXz2P.mjs";
11
- import { E as readHostMemoryPressure, T as hostMemoryPressureAdvice, u as listAllIosSims } from "./ios-lEJ5pKsq.mjs";
10
+ import { S as resolveEasCliBin, a as POOL_SETTING_REMEDY, b as ownerFromConfig, h as checkEasAuth$1, l as parkedMaxSetting, x as providerFromConfig } from "./teardown-BJqEzPo_.mjs";
11
+ import { D as hostMemoryPressureAdvice, O as readHostMemoryPressure, u as listAllIosSims } from "./ios-BcCiI4TS.mjs";
12
12
  import { n as listBuildSlots } from "./build-slots-C-oAHRT1.mjs";
13
- import { a as liveOwnedDeviceCount, d as simslimIsOnPath } from "./device-CLeDp-KH.mjs";
13
+ import { a as liveOwnedDeviceCount, d as simslimIsOnPath } from "./device-BUoZyMoR.mjs";
14
14
  import { d as projectCmakeLauncher, g as androidPathRoomRemedy, h as androidPathRoomMessage, i as apkOutputsDir, m as androidPathRoom, r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-SWIjzeuL.mjs";
15
15
  import { h as podInstallCommand, i as ccacheEnabled, o as detectXcodeMajor } from "./xcode-B6YaWeg0.mjs";
16
16
  import { i as inspectStimVersions, n as recordDoctorRun, r as compareStimVersions } from "./guide-status-Craq9z0t.mjs";
@@ -8,12 +8,12 @@ import { A as resolveSettings, N as settingShapeErrors, a as SETTING_SHAPE_REMED
8
8
  import { C as listAvds, O as ownedAvdDirectory, T as listOrphanedAvdDirectories } from "./android-DWssqHQ8.mjs";
9
9
  import { m as shortUdid, o as formatLongDuration, u as plural } from "./command-output-B3ycpsYv.mjs";
10
10
  import { r as listBuildLocks } from "./build-lock-CgtsB6TV.mjs";
11
- import { S as resolveEasCliBin, a as POOL_SETTING_REMEDY, i as teardownParkedIosSim, l as parkedMaxSetting, n as teardownOwnedIosSim, r as teardownParkedAvd, s as dropParked, t as teardownOwnedAvd, u as readParked } from "./teardown-5J5UXz2P.mjs";
12
- import { d as listIosDeviceTypes, g as parseRuntimeVersion, u as listAllIosSims } from "./ios-lEJ5pKsq.mjs";
11
+ import { S as resolveEasCliBin, a as POOL_SETTING_REMEDY, i as teardownParkedIosSim, l as parkedMaxSetting, n as teardownOwnedIosSim, r as teardownParkedAvd, s as dropParked, t as teardownOwnedAvd, u as readParked } from "./teardown-BJqEzPo_.mjs";
12
+ import { d as listIosDeviceTypes, g as parseRuntimeVersion, u as listAllIosSims } from "./ios-BcCiI4TS.mjs";
13
13
  import { i as listLeaseFiles, r as leaseIsExpired, u as removeExpiredLease } from "./device-lease-Ffz_M5t0.mjs";
14
14
  import { n as listBuildSlots } from "./build-slots-C-oAHRT1.mjs";
15
- import { C as verifyStoppedSession, S as stopSessionArgs, _ as inspectSessionForTeardown, d as withEasProjectLock, f as easMachineStateRoot, g as getSessionArgs, h as findOrphanedOwnedSessions, m as removeEasSessionClaim, p as readEasSessionLedger, u as withRemoteSessionLock, v as isDefinitiveMissingSessionError, x as parseSessionListPage, y as listOwnedSessionsArgs } from "./device-remote-BprxZp-m.mjs";
16
- import { n as reclaimProject, t as describeDereferenced } from "./reclaim-D614jI6_.mjs";
15
+ import { C as verifyStoppedSession, S as stopSessionArgs, _ as inspectSessionForTeardown, d as withEasProjectLock, f as easMachineStateRoot, g as getSessionArgs, h as findOrphanedOwnedSessions, m as removeEasSessionClaim, p as readEasSessionLedger, u as withRemoteSessionLock, v as isDefinitiveMissingSessionError, x as parseSessionListPage, y as listOwnedSessionsArgs } from "./device-remote-ByN8P6CB.mjs";
16
+ import { n as reclaimProject, t as describeDereferenced } from "./reclaim-KJ-0uWEF.mjs";
17
17
  import { InvalidArgumentError } from "commander";
18
18
  import { existsSync, readFileSync, readdirSync, realpathSync, rmSync, statSync } from "fs";
19
19
  import { homedir, tmpdir } from "os";
@@ -3402,7 +3402,7 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
3402
3402
  summary: "every flag per command, Android variants and flavors, the per-run simulator model, runtime and system image",
3403
3403
  body: () => `THE OPTION SURFACE, IN FULL
3404
3404
  start --json --wait <seconds> --remote --reset-cache
3405
- ios --slot <name> --json --no-metro-check --no-build-cache --scheme <name> --configuration <name> --device-type <name> --runtime <version> --device [udid] --wait <seconds> --no-wait --remote <proxy|eas>
3405
+ ios --slot <name> --json --no-metro-check --no-build-cache --scheme <name> --configuration <name> --device-type <name> --runtime <version> --simulator-app <xcode|siniulator> --device [udid] --wait <seconds> --no-wait --remote <proxy|eas>
3406
3406
  android --slot <name> --json --no-metro-check --no-build-cache --variant <name> --system-image <id> --device [serial] --wait <seconds> --no-wait --remote <proxy|eas>
3407
3407
  reload [ios|android] --json
3408
3408
  device lock <ios|android> [id] --slot <name> --for <duration> --wait <seconds> --json;
@@ -3949,9 +3949,15 @@ HOST MEMORY PRESSURE AND STALLED SIMULATORS
3949
3949
  simulator launch operations. Simulator discovery waits up to 30 seconds,
3950
3950
  boot (including the initial boot request) up to 10 minutes, and app installation
3951
3951
  up to 5 minutes. Process termination confirmation can take another 10 seconds;
3952
- a final boot-state query can take 30 seconds. Opening the Simulator app after
3953
- boot is best-effort and takes at most 5 seconds. A timeout is not proof of an
3954
- app crash or OOM.
3952
+ a final boot-state query can take 30 seconds. After boot, Stim opens the owned
3953
+ simulator in the selected Xcode's Device Hub on Xcode 27, or Simulator on
3954
+ older Xcode. Top-level iosSimulatorApp in the machine config can select
3955
+ Siniulator instead; see guide settings. Override it for one local run with
3956
+ \`stim ios --simulator-app siniulator\` or \`--simulator-app xcode\`. This also
3957
+ opens an already running owned simulator without rebooting it or saving the
3958
+ preference. The flag refuses physical and remote targets, including ios.remote.
3959
+ Opening the window is best-effort
3960
+ and takes at most 10 seconds. A timeout is not proof of an app crash or OOM.
3955
3961
  During boot, Stim reports elapsed time, the simulator name, last boot output,
3956
3962
  current pressure and the highest observed pressure roughly every 15 seconds.
3957
3963
  Failure diagnostics retain the highest pressure and unavailable sample count;
@@ -4534,6 +4540,26 @@ Unset, 0, or any non-positive value means NO enforcement -- the default, where
4534
4540
  Stim limits nothing. See \`guide lifecycle concurrency\` for what each cap
4535
4541
  does.
4536
4542
 
4543
+ THE IOS SIMULATOR APP IS MACHINE-LEVEL
4544
+ Top-level \`iosSimulatorApp\` in ~/.stim/config.json selects the macOS app that
4545
+ displays Stim's owned local iOS simulator after boot. It is not a project
4546
+ setting. Unset or \`"xcode"\` opens the selected Xcode's Device Hub on Xcode 27,
4547
+ or Simulator on older Xcode. To use an installed Siniulator instead:
4548
+
4549
+ { "iosSimulatorApp": "siniulator" }
4550
+
4551
+ Override the preference for one local launch with
4552
+ \`stim ios --simulator-app siniulator\` or \`stim ios --simulator-app xcode\`.
4553
+ The flag also opens an already running owned simulator without rebooting it.
4554
+ It leaves the saved preference unchanged and refuses physical or remote targets.
4555
+
4556
+ Stim still creates and boots its owned simulator. An invalid value refuses
4557
+ before boot. Opening a window remains best-effort, so install Siniulator before
4558
+ selecting it. By default, closing a Siniulator device window shuts down that
4559
+ simulator. Enable "Leave simulator running after window is closed" in Siniulator
4560
+ Settings if Stim should keep it running. See \`guide lifecycle simslim\` for
4561
+ window behavior.
4562
+
4537
4563
  THE DEVICE POOL BOUNDS ARE MACHINE-LEVEL TOO
4538
4564
  \`pool.iosParkedMax\` caps how many parked simulators \`worktree remove\` may
4539
4565
  leave behind for a later workspace to adopt. It is machine-level for the same
@@ -10,21 +10,21 @@ import { n as verifyCollectorOwnership } from "./ownership-Cp52QAK1.mjs";
10
10
  import { A as resolveSettings, B as artifactCachePolicy, D as remoteDeviceSettingError, F as tunnelModeSetting, H as optimizationBuildProfile, I as unknownSettingKeys, N as settingShapeErrors, O as remoteIosSetting, R as detectProviders, T as publicUrlSetting, U as resolveOptimizations, _ as iosSigningIdentitySha1SettingError, a as SETTING_SHAPE_REMEDY, d as cacheProviderSettingError, f as iosLanHostSetting, g as iosSigningIdentitySha1Setting, h as iosSigningIdentitySettingError, k as resolveCacheProviderConfig, m as iosSigningIdentitySetting, p as iosLanHostSettingError, r as REMOTE_DEVICE_BACKENDS, x as metroWarmupUrlSetting } from "./settings-BXXorVM2.mjs";
11
11
  import { _ as launchErrorPreview, c as launchErrorReport, g as stepTimer, h as stepClock, i as formatDuration, l as phaseLine, m as shortUdid, n as appReadinessMessage, p as shortHash } from "./command-output-B3ycpsYv.mjs";
12
12
  import { C as untrackedNativeFiles, S as untrackedMissLine, _ as providerUploadOutcome, b as storeBuild, c as buildCacheKey, d as filesystemBuildCapability, f as fingerprintDiffRecord, g as providerDownloadPath, h as prepareProviderDownloadDir, i as releaseBuildLock, l as describeFingerprintMiss, m as fingerprintProject, n as acquireBuildLock, o as takeoverLine, p as fingerprintDiffSuffix, s as waitForBuild, t as WAIT_CEILING_MS, v as refingerprintAfterMutation, y as resolveBuild } from "./build-lock-CgtsB6TV.mjs";
13
- import { C as resolveRemote, S as resolveEasCliBin, _ as exitAfterFlush, a as POOL_SETTING_REMEDY, f as RESOLVE_TIMEOUT_MS, g as easAuthNote, h as checkEasAuth, l as parkedMaxSetting, m as cacheLevel, p as UPLOAD_TIMEOUT_MS, v as isEasAuthFailureText, w as uploadRemote, y as loadProjectProvider } from "./teardown-5J5UXz2P.mjs";
14
- import { _ as easDeviceBuildRemedy, a as swapJsBundle, c as ensureWorkspaceStorageSafely, d as launchOutcomeRecord, f as noMetroMessage, g as warmMetro, h as sleep, l as gateShouldRetry, m as resolveMetroWithRetry, n as pickDevClientScheme, o as needsPrebuild, p as noMetroRemedy, r as schemesFromInfoPlist, s as runPrebuild, t as devClientScheme, u as isPhysicalDeviceRequest, v as isEasBuildFailure, y as resolveEasDevelopmentBuild } from "./dev-client-DDUkWgJL.mjs";
13
+ import { C as resolveRemote, S as resolveEasCliBin, _ as exitAfterFlush, a as POOL_SETTING_REMEDY, f as RESOLVE_TIMEOUT_MS, g as easAuthNote, h as checkEasAuth, l as parkedMaxSetting, m as cacheLevel, p as UPLOAD_TIMEOUT_MS, v as isEasAuthFailureText, w as uploadRemote, y as loadProjectProvider } from "./teardown-BJqEzPo_.mjs";
14
+ import { _ as easDeviceBuildRemedy, a as swapJsBundle, c as ensureWorkspaceStorageSafely, d as launchOutcomeRecord, f as noMetroMessage, g as warmMetro, h as sleep, l as gateShouldRetry, m as resolveMetroWithRetry, n as pickDevClientScheme, o as needsPrebuild, p as noMetroRemedy, r as schemesFromInfoPlist, s as runPrebuild, t as devClientScheme, u as isPhysicalDeviceRequest, v as isEasBuildFailure, y as resolveEasDevelopmentBuild } from "./dev-client-BmT-ioFI.mjs";
15
15
  import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BYfZz_S-.mjs";
16
- import { C as launchIosApp, E as unverifiedLaunchLines, O as verifyLaunch, T as readMetroRecords, b as isBundleProof, c as RELEASE_VERIFY_WAIT_MS, f as clearOtherUserApps, i as LAUNCH_BUNDLING, k as verifyReleaseLaunch, m as devClientUrl, n as DEFAULT_METRO_PORT, o as LAUNCH_FATAL, s as LAUNCH_UNVERIFIED, v as installIosApp, w as readCollectorRecords, y as iosAppProcess } from "./app-install-DJg7bVv-.mjs";
17
- import { f as listIosRuntimes } from "./ios-lEJ5pKsq.mjs";
18
- import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-DNSHL5z8.mjs";
16
+ import { C as launchIosApp, E as unverifiedLaunchLines, O as verifyLaunch, T as readMetroRecords, b as isBundleProof, c as RELEASE_VERIFY_WAIT_MS, f as clearOtherUserApps, i as LAUNCH_BUNDLING, k as verifyReleaseLaunch, m as devClientUrl, n as DEFAULT_METRO_PORT, o as LAUNCH_FATAL, s as LAUNCH_UNVERIFIED, v as installIosApp, w as readCollectorRecords, y as iosAppProcess } from "./app-install-BDbsSgCl.mjs";
17
+ import { E as parseIosSimulatorApp, f as listIosRuntimes } from "./ios-BcCiI4TS.mjs";
18
+ import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-BxRwdufO.mjs";
19
19
  import { r as releaseBuildSlot, t as acquireBuildSlot } from "./build-slots-C-oAHRT1.mjs";
20
20
  import { a as statsProjectKey, i as recordRunStats, n as readRunEstimates, t as createRunRecorder } from "./stats-BYcZ6n1h.mjs";
21
- import { c as unknownIosRuntimeRefusal, i as ensureOwnedDevice, n as clearIosAdoptionPending, r as ensureBooted, s as unknownIosDeviceTypeRefusal, t as checkDeviceCapacity } from "./device-CLeDp-KH.mjs";
22
- import { a as ensureMetroReachable, b as ownedSessionName, c as remoteIosDeps, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, r as bundleEntryPoint, w as gateMetroOrigin } from "./device-remote-BprxZp-m.mjs";
21
+ import { c as unknownIosRuntimeRefusal, i as ensureOwnedDevice, n as clearIosAdoptionPending, r as ensureBooted, s as unknownIosDeviceTypeRefusal, t as checkDeviceCapacity } from "./device-BUoZyMoR.mjs";
22
+ import { a as ensureMetroReachable, b as ownedSessionName, c as remoteIosDeps, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, r as bundleEntryPoint, w as gateMetroOrigin } from "./device-remote-ByN8P6CB.mjs";
23
23
  import { a as compilationCacheActivityLine, c as readBundleExecutable, l as readBundleId, p as describeDiagnostic, r as buildIos, s as discoverXcodeProject, t as COMPILATION_CACHE_NOT_RUN, u as resolveScheme } from "./xcode-B6YaWeg0.mjs";
24
- import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-DbLvyrup.mjs";
24
+ import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-ZUUe0TQP.mjs";
25
25
  import { t as spawnEntry } from "./spawn-entry-nCE6m770.mjs";
26
26
  import { a as printNativeCrashReport, n as IOS_CRASH_REPORT_RETRY, o as simulatorConsolePaths, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-D1Kaf-eT.mjs";
27
- import { a as iosDeviceProcess, c as listIosDevices, d as verifyIosDeviceReleaseLaunch, i as installIosDeviceApp, l as localNetworkPending, n as LAUNCH_PROBE_TIMEOUT_MS, o as iosPoolCandidates, r as awaitIosDeviceLaunch, s as iosPoolNoCandidatesRefusal, t as DEVICECTL_INSTALL_TIMEOUT_MS, u as resolveIosPhysicalDevice } from "./ios-device-CDbvn5H2.mjs";
27
+ import { a as iosDeviceProcess, c as listIosDevices, d as verifyIosDeviceReleaseLaunch, i as installIosDeviceApp, l as localNetworkPending, n as LAUNCH_PROBE_TIMEOUT_MS, o as iosPoolCandidates, r as awaitIosDeviceLaunch, s as iosPoolNoCandidatesRefusal, t as DEVICECTL_INSTALL_TIMEOUT_MS, u as resolveIosPhysicalDevice } from "./ios-device-CauFJiYx.mjs";
28
28
  import { a as runPodInstall, n as podsAreStale, r as readPodState } from "./deps-oCXVNEqQ.mjs";
29
29
  import { existsSync, mkdirSync, mkdtempSync, openSync, rmSync, writeFileSync } from "node:fs";
30
30
  import { InvalidArgumentError } from "commander";
@@ -143,6 +143,24 @@ function resolveDeviceType(flag, settings) {
143
143
  function resolveRuntime(flag, settings) {
144
144
  return (typeof flag === "string" && flag.trim() !== "" ? flag.trim() : null) || iosStringSetting(settings, "runtime");
145
145
  }
146
+ function resolveSimulatorAppFlag(flag, physical, remoteBackend) {
147
+ if (flag === void 0) return {};
148
+ let simulatorApp;
149
+ try {
150
+ simulatorApp = parseIosSimulatorApp(flag, "--simulator-app");
151
+ } catch (error) {
152
+ return { refusal: {
153
+ code: "STIM_BAD_ARG",
154
+ message: error.message
155
+ } };
156
+ }
157
+ if (physical || remoteBackend) return { refusal: {
158
+ code: "STIM_BAD_ARG",
159
+ message: "--simulator-app only applies to a local owned iOS simulator.",
160
+ remedy: "Drop --simulator-app when using a physical or remote device."
161
+ } };
162
+ return { simulatorApp };
163
+ }
146
164
  function deviceModelRefusal({ slot, deviceTypeFlag, runtimeFlag, deviceType, runtime, physical, remoteBackend, listRuntimes }) {
147
165
  if (slot && slot !== "default" && remoteBackend) return {
148
166
  code: "STIM_BAD_ARG",
@@ -2239,7 +2257,7 @@ function iosCommand(program) {
2239
2257
  registerIos(program);
2240
2258
  }
2241
2259
  function registerIos(program, deps = {}) {
2242
- program.command("ios").description("Build (or restore from the fingerprint cache), install and launch this workspace's app on its owned simulator, wired to the reserved Metro port. Requires a running dev server (`stim start`).").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", validateDeviceSlot).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--scheme <name>", "Shared Xcode app scheme to build; overrides automatic scheme selection, not the app URL scheme").option("--no-metro-check", "Skip the \"is this workspace's dev server running?\" gate and build anyway").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--configuration <name>", "Xcode configuration to build (e.g. Release). A non-Debug configuration embeds the JS bundle and skips Metro entirely. Overrides the ios.configuration setting. Default: Debug").option("--device-type <name>", "Simulator model to create this workspace's owned sim as, exactly as `xcrun simctl list devicetypes` names it (e.g. \"iPad Pro 13-inch (M4)\"). Overrides the ios.deviceType setting for this invocation. A model no installed runtime can create refuses with STIM_BAD_ARG and prints the models they do offer.").option("--runtime <version>", "Simulator runtime to create this workspace's owned sim on, as a version (\"18.5\") or a runtime's full name (\"iOS 18.5\"); nothing else matches. Overrides the ios.runtime setting for this invocation. An unknown version refuses with STIM_BAD_ARG and prints the installed runtimes.").option("--device [udid]", "Build the iphoneos slice for a connected iPhone, install it, and launch it, instead of using this workspace's owned simulator. With no UDID, the first connected device this workspace can lease is used. In Debug the app is wired to this workspace's Metro over the LAN. Stim never creates, boots, or deletes a physical device.").option("--remote <backend>", "Install and launch on a remote device with proxy or EAS. Builds are local unless --eas-profile selects an existing EAS build.", (value) => {
2260
+ program.command("ios").description("Build (or restore from the fingerprint cache), install and launch this workspace's app on its owned simulator, wired to the reserved Metro port. Requires a running dev server (`stim start`).").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", validateDeviceSlot).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--scheme <name>", "Shared Xcode app scheme to build; overrides automatic scheme selection, not the app URL scheme").option("--no-metro-check", "Skip the \"is this workspace's dev server running?\" gate and build anyway").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--configuration <name>", "Xcode configuration to build (e.g. Release). A non-Debug configuration embeds the JS bundle and skips Metro entirely. Overrides the ios.configuration setting. Default: Debug").option("--device-type <name>", "Simulator model to create this workspace's owned sim as, exactly as `xcrun simctl list devicetypes` names it (e.g. \"iPad Pro 13-inch (M4)\"). Overrides the ios.deviceType setting for this invocation. A model no installed runtime can create refuses with STIM_BAD_ARG and prints the models they do offer.").option("--runtime <version>", "Simulator runtime to create this workspace's owned sim on, as a version (\"18.5\") or a runtime's full name (\"iOS 18.5\"); nothing else matches. Overrides the ios.runtime setting for this invocation. An unknown version refuses with STIM_BAD_ARG and prints the installed runtimes.").option("--simulator-app <app>", "Open the owned simulator in xcode or siniulator for this run, overriding the machine iosSimulatorApp setting. Also opens an already running simulator; local simulators only.").option("--device [udid]", "Build the iphoneos slice for a connected iPhone, install it, and launch it, instead of using this workspace's owned simulator. With no UDID, the first connected device this workspace can lease is used. In Debug the app is wired to this workspace's Metro over the LAN. Stim never creates, boots, or deletes a physical device.").option("--remote <backend>", "Install and launch on a remote device with proxy or EAS. Builds are local unless --eas-profile selects an existing EAS build.", (value) => {
2243
2261
  if (REMOTE_DEVICE_BACKENDS.includes(value)) return value;
2244
2262
  throw new InvalidArgumentError(`expected one of: ${REMOTE_DEVICE_BACKENDS.join(", ")}`);
2245
2263
  }).option("--wait <seconds>", "How long to wait for another workspace to release the phone it leases, before refusing with STIM_DEVICE_BUSY (default 60, 0 refuses at once). Only with --device.").option("--no-wait", "Install on a phone another workspace leases instead of waiting: this run takes no lease and, when both workspaces build the same app id, the install terminates the holder's running app. Only with --device.").action(async (opts) => {
@@ -2522,6 +2540,9 @@ async function runIos(opts = {}, overrides = {}) {
2522
2540
  const schemeRefusal = explicitSchemeRefusal(root, buildScheme, isExpo, d);
2523
2541
  if (schemeRefusal) return fail(schemeRefusal);
2524
2542
  const remoteBackend = physical ? null : opts.remote ?? remoteIosSetting(settings);
2543
+ const viewer = resolveSimulatorAppFlag(opts.simulatorApp, physical, remoteBackend);
2544
+ if ("refusal" in viewer) return fail(viewer.refusal);
2545
+ const { simulatorApp } = viewer;
2525
2546
  const modelRefusal = deviceModelRefusal({
2526
2547
  slot,
2527
2548
  deviceTypeFlag: opts.deviceType,
@@ -2648,7 +2669,8 @@ async function runIos(opts = {}, overrides = {}) {
2648
2669
  settings,
2649
2670
  flags: {
2650
2671
  deviceType,
2651
- runtime
2672
+ runtime,
2673
+ simulatorApp
2652
2674
  },
2653
2675
  note,
2654
2676
  out: note
@@ -2778,6 +2800,7 @@ async function runIos(opts = {}, overrides = {}) {
2778
2800
  }) : Promise.resolve(d.ensureBooted({
2779
2801
  platform: "ios",
2780
2802
  device,
2803
+ simulatorApp,
2781
2804
  out: note
2782
2805
  })).catch((e) => ({
2783
2806
  ok: false,
@@ -1,7 +1,8 @@
1
1
  import { t as getExecutor } from "./exec-B29XNuhP.mjs";
2
+ import { g as loadConfig } from "./config-B7iyKWkL.mjs";
2
3
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Dl5uKE03.mjs";
3
- import { mkdtempSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
4
- import { join } from "node:path";
4
+ import { existsSync, mkdtempSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
5
+ import { dirname, join, resolve } from "node:path";
5
6
  import { tmpdir } from "node:os";
6
7
  //#region src/host-memory.ts
7
8
  function readHostMemoryPressure(exec = getExecutor(), platform = process.platform) {
@@ -22,6 +23,40 @@ function hostMemoryPressureAdvice(pressure) {
22
23
  return `macOS reports ${pressure} host memory pressure. Simulator processes can stall even when the device is Booted. Free memory before retrying: use \`stim stop\` only in workspaces you own, and ask before closing other apps or devices. For parallel iOS work, consider a reviewed SimSlim profile (\`stim guide lifecycle simslim\`). This observation does not establish an OOM crash.`;
23
24
  }
24
25
  //#endregion
26
+ //#region src/devices/ios-simulator-viewer.ts
27
+ const OPEN_OPTIONS = {
28
+ timeoutMs: 5e3,
29
+ killSignal: "SIGKILL"
30
+ };
31
+ function parseIosSimulatorApp(value, source = "iosSimulatorApp in machine config") {
32
+ if (value === void 0 || value === "xcode") return "xcode";
33
+ if (value === "siniulator") return "siniulator";
34
+ const error = /* @__PURE__ */ new Error(`Invalid ${source}. Use "xcode" or "siniulator".`);
35
+ Object.assign(error, { code: "STIM_BAD_ARG" });
36
+ throw error;
37
+ }
38
+ function configuredIosSimulatorViewer(override) {
39
+ const app = override ?? parseIosSimulatorApp(loadConfig()?.iosSimulatorApp);
40
+ const exec = getExecutor();
41
+ if (app === "siniulator") return { open: (udid) => {
42
+ exec.runFileQuiet("open", [
43
+ "-a",
44
+ "Siniulator",
45
+ `siniulator://open?udid=${udid}`
46
+ ], OPEN_OPTIONS);
47
+ } };
48
+ return { open: (udid) => {
49
+ const simctlPath = exec.runFileQuiet("xcrun", ["--find", "simctl"], OPEN_OPTIONS);
50
+ const deviceHubApp = simctlPath ? resolve(dirname(simctlPath), "..", "..", "..", "Applications", "DeviceHub.app") : null;
51
+ const args = deviceHubApp && existsSync(deviceHubApp) ? [
52
+ "-a",
53
+ deviceHubApp,
54
+ `devices://device/open?id=${udid}`
55
+ ] : ["-a", "Simulator"];
56
+ exec.runFileQuiet("open", args, OPEN_OPTIONS);
57
+ } };
58
+ }
59
+ //#endregion
25
60
  //#region src/devices/ios.ts
26
61
  function parseSimctlList(jsonOutput, { includeUnavailable = false } = {}) {
27
62
  const parsed = JSON.parse(jsonOutput);
@@ -138,8 +173,9 @@ async function awaitBootCommand(args, attemptMs, onLine) {
138
173
  const detail = lines.length ? `: ${lines.join(" | ")}` : "";
139
174
  throw new Error(`${command} failed with exit code ${result.code ?? "unknown"}${detail}`);
140
175
  }
141
- async function bootIosSim(udid, { timeoutMs = IOS_BOOT_TIMEOUT_MS, attemptMs = BOOTSTATUS_ATTEMPT_MS, label = udid, out = () => {} } = {}) {
176
+ async function bootIosSim(udid, { timeoutMs = IOS_BOOT_TIMEOUT_MS, attemptMs = BOOTSTATUS_ATTEMPT_MS, simulatorApp, label = udid, out = () => {} } = {}) {
142
177
  const exec = getExecutor();
178
+ const viewer = configuredIosSimulatorViewer(simulatorApp);
143
179
  const started = Date.now();
144
180
  const deadline = started + timeoutMs;
145
181
  let worst = null;
@@ -213,10 +249,7 @@ async function bootIosSim(udid, { timeoutMs = IOS_BOOT_TIMEOUT_MS, attemptMs = B
213
249
  } finally {
214
250
  clearInterval(monitor);
215
251
  }
216
- exec.runFileQuiet("open", ["-a", "Simulator"], {
217
- timeoutMs: 5e3,
218
- killSignal: "SIGKILL"
219
- });
252
+ viewer.open(udid);
220
253
  }
221
254
  function shutdownIosSim(udid) {
222
255
  getExecutor().runQuiet(`xcrun simctl shutdown ${udid}`);
@@ -486,4 +519,4 @@ function listIosRuntimes() {
486
519
  }));
487
520
  }
488
521
  //#endregion
489
- export { shutdownIosSim as C, readHostMemoryPressure as E, sanitizeDeviceLabel as S, hostMemoryPressureAdvice as T, renameIosSim as _, deleteIosSim as a, resolveIosCreation as b, iosRuntimeMatches as c, listIosDeviceTypes as d, listIosRuntimes as f, parseRuntimeVersion as g, parkedSimName as h, createOwnedIosSim as i, iosSimulatorFailureAdvice as l, ownedSimName as m, bootIosSim as n, deleteParkedIosSim as o, listUserApps as p, clearAppDataContainer as r, findAppDataContainer as s, IOS_BOOT_TIMEOUT_MS as t, listAllIosSims as u, resetIosKeychain as v, uninstallIosApp as w, resolveOwnedIosSim as x, resetIosPrivacy as y };
522
+ export { shutdownIosSim as C, hostMemoryPressureAdvice as D, parseIosSimulatorApp as E, readHostMemoryPressure as O, sanitizeDeviceLabel as S, configuredIosSimulatorViewer as T, renameIosSim as _, deleteIosSim as a, resolveIosCreation as b, iosRuntimeMatches as c, listIosDeviceTypes as d, listIosRuntimes as f, parseRuntimeVersion as g, parkedSimName as h, createOwnedIosSim as i, iosSimulatorFailureAdvice as l, ownedSimName as m, bootIosSim as n, deleteParkedIosSim as o, listUserApps as p, clearAppDataContainer as r, findAppDataContainer as s, IOS_BOOT_TIMEOUT_MS as t, listAllIosSims as u, resetIosKeychain as v, uninstallIosApp as w, resolveOwnedIosSim as x, resetIosPrivacy as y };
@@ -1,5 +1,5 @@
1
1
  import { t as getExecutor } from "./exec-B29XNuhP.mjs";
2
- import { r as INSTALL_ERROR } from "./app-install-DJg7bVv-.mjs";
2
+ import { r as INSTALL_ERROR } from "./app-install-BDbsSgCl.mjs";
3
3
  import { mkdtempSync, readFileSync, rmSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
@@ -3,6 +3,7 @@ import { u as getConfigDir, w as process_identity_exports } from "./config-B7iyK
3
3
  import { t as createLineReader } from "./process-output-Dl5uKE03.mjs";
4
4
  import { i as pidExists, o as signalProcessTree } from "./metro-C7bcJ0uo.mjs";
5
5
  import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BYfZz_S-.mjs";
6
+ import { t as probePublicHttp } from "./public-http-probe-CyMDrQ3c.mjs";
6
7
  import { closeSync, mkdirSync, openSync, readFileSync, unlinkSync } from "node:fs";
7
8
  import { createHash, randomUUID } from "node:crypto";
8
9
  import { basename, join, resolve, sep } from "node:path";
@@ -86,14 +87,8 @@ function managedRemoteWorktreeLockRoot(worktreeRoot) {
86
87
  return join(getConfigDir(), "process-locks", "worktrees", key);
87
88
  }
88
89
  async function defaultProbeReachable(url, signal) {
89
- try {
90
- return (await fetch(url, {
91
- signal,
92
- redirect: "follow"
93
- })).status > 0;
94
- } catch {
95
- return false;
96
- }
90
+ const status = await probePublicHttp(url, signal);
91
+ return status !== null && status > 0;
97
92
  }
98
93
  function waitForUrl(child, parseLine, timeoutMs) {
99
94
  return new Promise((resolve) => {
@@ -0,0 +1,61 @@
1
+ import { resolve4 } from "node:dns/promises";
2
+ import { request } from "node:https";
3
+ //#region src/engine/public-http-probe.ts
4
+ const DNS_TIMEOUT_MS = 5e3;
5
+ async function resolveAddresses(hostname, signal) {
6
+ if (signal.aborted) throw signal.reason;
7
+ let timer;
8
+ let onAbort;
9
+ const unavailable = new Promise((_resolve, reject) => {
10
+ onAbort = () => reject(signal.reason);
11
+ signal.addEventListener("abort", onAbort, { once: true });
12
+ if (signal.aborted) onAbort();
13
+ else timer = setTimeout(() => reject(/* @__PURE__ */ new Error("DNS lookup timed out")), DNS_TIMEOUT_MS);
14
+ });
15
+ try {
16
+ return await Promise.race([resolve4(hostname), unavailable]);
17
+ } finally {
18
+ clearTimeout(timer);
19
+ if (onAbort) signal.removeEventListener("abort", onAbort);
20
+ }
21
+ }
22
+ async function probePublicHttp(url, signal) {
23
+ try {
24
+ return (await fetch(url, {
25
+ signal,
26
+ redirect: "follow"
27
+ })).status;
28
+ } catch (error) {
29
+ const cause = error?.cause;
30
+ if (cause?.code !== "ENOTFOUND" && cause?.code !== "EAI_AGAIN") return null;
31
+ }
32
+ const hostname = new URL(url).hostname;
33
+ if (!hostname.endsWith(".trycloudflare.com")) return null;
34
+ let addresses;
35
+ try {
36
+ addresses = await resolveAddresses(hostname, signal);
37
+ } catch {
38
+ return null;
39
+ }
40
+ const firstAddress = addresses[0];
41
+ if (!firstAddress) return null;
42
+ return new Promise((resolve) => {
43
+ const request$1 = request(url, {
44
+ signal,
45
+ lookup: (_hostname, options, callback) => {
46
+ if (options.all) callback(null, addresses.map((address) => ({
47
+ address,
48
+ family: 4
49
+ })));
50
+ else callback(null, firstAddress, 4);
51
+ }
52
+ }, (response) => {
53
+ response.resume();
54
+ resolve(response.statusCode ?? null);
55
+ });
56
+ request$1.on("error", () => resolve(null));
57
+ request$1.end();
58
+ });
59
+ }
60
+ //#endregion
61
+ export { probePublicHttp as t };
@@ -3,11 +3,11 @@ import { h as workspaceDir, r as readWorkspaceState } from "./workspace-state-BT
3
3
  import { a as clearRemoteSession, i as clearManagedMetroTunnel, s as readMetroTunnel, u as readRemoteSessionId } from "./state-DZobzxLW.mjs";
4
4
  import { a as resolveProjectMetro, i as pidExists, n as killMetroTree } from "./metro-C7bcJ0uo.mjs";
5
5
  import { n as verifyCollectorOwnership } from "./ownership-Cp52QAK1.mjs";
6
- import { S as resolveEasCliBin, l as parkedMaxSetting, n as teardownOwnedIosSim, t as teardownOwnedAvd } from "./teardown-5J5UXz2P.mjs";
6
+ import { S as resolveEasCliBin, l as parkedMaxSetting, n as teardownOwnedIosSim, t as teardownOwnedAvd } from "./teardown-BJqEzPo_.mjs";
7
7
  import { l as releaseWorkspaceLeases } from "./device-lease-Ffz_M5t0.mjs";
8
- import { i as endRecordedSession } from "./device-remote-BprxZp-m.mjs";
8
+ import { i as endRecordedSession } from "./device-remote-ByN8P6CB.mjs";
9
9
  import { t as clearNamedPorts } from "./named-ports-DzMOlmaX.mjs";
10
- import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-D5vkdm8H.mjs";
10
+ import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-wolE-0Do.mjs";
11
11
  import { existsSync, rmSync } from "node:fs";
12
12
  //#region src/devices/reclaim.ts
13
13
  async function reapCollectors(root, { verify = verifyCollectorOwnership, collectors }) {
@@ -4,9 +4,9 @@ import { d as readWorkspaceLaunches } from "./state-DZobzxLW.mjs";
4
4
  import { a as resolveProjectMetro } from "./metro-C7bcJ0uo.mjs";
5
5
  import { I as resolveOwnedAvdSerial } from "./android-DWssqHQ8.mjs";
6
6
  import { l as phaseLine } from "./command-output-B3ycpsYv.mjs";
7
- import { u as androidAppProcess, y as iosAppProcess } from "./app-install-DJg7bVv-.mjs";
8
- import { x as resolveOwnedIosSim } from "./ios-lEJ5pKsq.mjs";
9
- import { n as nativeRunCommand } from "./slot-launch-DbLvyrup.mjs";
7
+ import { u as androidAppProcess, y as iosAppProcess } from "./app-install-BDbsSgCl.mjs";
8
+ import { x as resolveOwnedIosSim } from "./ios-BcCiI4TS.mjs";
9
+ import { n as nativeRunCommand } from "./slot-launch-ZUUe0TQP.mjs";
10
10
  import chalk from "chalk";
11
11
  import { WebSocket } from "ws";
12
12
  //#region src/engine/reload.ts
@@ -1,6 +1,6 @@
1
1
  import { f as getProject } from "./config-B7iyKWkL.mjs";
2
2
  import { r as readWorkspaceState } from "./workspace-state-BT5E3SA2.mjs";
3
- import { h as deviceShellArg } from "./app-install-DJg7bVv-.mjs";
3
+ import { h as deviceShellArg } from "./app-install-BDbsSgCl.mjs";
4
4
  import { n as fileLeaseIo } from "./device-lease-Ffz_M5t0.mjs";
5
5
  //#region src/engine/slot-launch.ts
6
6
  function launchSlotScope(root, slot = "default") {
@@ -12,7 +12,7 @@ import { g as stepTimer, l as phaseLine } from "./command-output-B3ycpsYv.mjs";
12
12
  import { n as workspaceProcessLockError, t as withWorkspaceProcessLock } from "./workspace-process-lock-BYfZz_S-.mjs";
13
13
  import { t as spawnEntry } from "./spawn-entry-nCE6m770.mjs";
14
14
  import { c as queryLogs } from "./logs-query-BGL-Pl12.mjs";
15
- import { a as withManagedRemoteWorktreeLock, i as terminateChild, n as startTunnelSequence, r as stopTunnel, s as withManagedTunnelLock, t as resolveSupervisorTarget } from "./ownership-D5vkdm8H.mjs";
15
+ import { a as withManagedRemoteWorktreeLock, i as terminateChild, n as startTunnelSequence, r as stopTunnel, s as withManagedTunnelLock, t as resolveSupervisorTarget } from "./ownership-wolE-0Do.mjs";
16
16
  import { appendFileSync, mkdirSync, openSync, readFileSync } from "node:fs";
17
17
  import { dirname } from "node:path";
18
18
  import { EventEmitter } from "node:events";
@@ -6,12 +6,12 @@ import { a as findProjectRoot, c as projectShortcut } from "./project-DDZWf_16.m
6
6
  import { a as resolveProjectMetro, s as isMetroRunning } from "./metro-C7bcJ0uo.mjs";
7
7
  import { I as resolveOwnedAvdSerial } from "./android-DWssqHQ8.mjs";
8
8
  import { a as formatElapsed, r as clockTime, u as plural } from "./command-output-B3ycpsYv.mjs";
9
- import { a as POOL_SETTING_REMEDY, l as parkedMaxSetting, u as readParked } from "./teardown-5J5UXz2P.mjs";
10
- import { u as listAllIosSims } from "./ios-lEJ5pKsq.mjs";
9
+ import { a as POOL_SETTING_REMEDY, l as parkedMaxSetting, u as readParked } from "./teardown-BJqEzPo_.mjs";
10
+ import { u as listAllIosSims } from "./ios-BcCiI4TS.mjs";
11
11
  import { i as listLeaseFiles } from "./device-lease-Ffz_M5t0.mjs";
12
12
  import { c as queryLogs } from "./logs-query-BGL-Pl12.mjs";
13
- import { t as resolveSupervisorTarget } from "./ownership-D5vkdm8H.mjs";
14
- import { i as readSupervisorState } from "./stop-ZrfODZ51.mjs";
13
+ import { t as resolveSupervisorTarget } from "./ownership-wolE-0Do.mjs";
14
+ import { i as readSupervisorState } from "./stop-C8JW6kKp.mjs";
15
15
  import { existsSync } from "fs";
16
16
  import { totalmem } from "os";
17
17
  import chalk from "chalk";
@@ -1,3 +1,3 @@
1
- import { t as resolveSupervisorTarget } from "./ownership-D5vkdm8H.mjs";
2
- import { a as resolveCollectorTargets, i as readSupervisorState, n as clearSupervisorState, o as runStop, r as readCollectorState, s as stopCommand, t as clearCollectorState } from "./stop-ZrfODZ51.mjs";
1
+ import { t as resolveSupervisorTarget } from "./ownership-wolE-0Do.mjs";
2
+ import { a as resolveCollectorTargets, i as readSupervisorState, n as clearSupervisorState, o as runStop, r as readCollectorState, s as stopCommand, t as clearCollectorState } from "./stop-C8JW6kKp.mjs";
3
3
  export { clearCollectorState, clearSupervisorState, stopCommand as default, readCollectorState, readSupervisorState, resolveCollectorTargets, resolveSupervisorTarget, runStop };
@@ -5,11 +5,11 @@ import { a as clearRemoteSession, i as clearManagedMetroTunnel, l as readRemoteS
5
5
  import { a as resolveProjectMetro, i as pidExists, n as killMetroTree, o as signalProcessTree } from "./metro-C7bcJ0uo.mjs";
6
6
  import { n as verifyCollectorOwnership } from "./ownership-Cp52QAK1.mjs";
7
7
  import { f as releasedLeaseFact, l as phaseLine, u as plural } from "./command-output-B3ycpsYv.mjs";
8
- import { S as resolveEasCliBin, n as teardownOwnedIosSim, t as teardownOwnedAvd } from "./teardown-5J5UXz2P.mjs";
8
+ import { S as resolveEasCliBin, n as teardownOwnedIosSim, t as teardownOwnedAvd } from "./teardown-BJqEzPo_.mjs";
9
9
  import { t as withWorkspaceProcessLock } from "./workspace-process-lock-BYfZz_S-.mjs";
10
10
  import { l as releaseWorkspaceLeases } from "./device-lease-Ffz_M5t0.mjs";
11
- import { i as endRecordedSession } from "./device-remote-BprxZp-m.mjs";
12
- import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-D5vkdm8H.mjs";
11
+ import { i as endRecordedSession } from "./device-remote-ByN8P6CB.mjs";
12
+ import { r as stopTunnel, t as resolveSupervisorTarget } from "./ownership-wolE-0Do.mjs";
13
13
  import chalk from "chalk";
14
14
  //#region src/commands/stop.ts
15
15
  const DEFAULT_WAIT_MS = 1e4;
@@ -7,7 +7,7 @@ import { n as stripAnsi } from "./process-output-Dl5uKE03.mjs";
7
7
  import { I as resolveOwnedAvdSerial, O as ownedAvdDirectory, R as shutdownAndroidEmulator, T as listOrphanedAvdDirectories, c as assertOwnedAvdStopped, d as avdStorageRoots, h as deleteAvd, j as ownedAvdSystemImage, k as ownedAvdMatchesConfiguration, l as avdPathExists, z as waitForAndroidEmulatorShutdown } from "./android-DWssqHQ8.mjs";
8
8
  import { l as phaseLine } from "./command-output-B3ycpsYv.mjs";
9
9
  import { n as expoBinFromPackage, r as expoBinPath, s as findBinUpward } from "./server-expo-BVAA1OqJ.mjs";
10
- import { C as shutdownIosSim, _ as renameIosSim, a as deleteIosSim, d as listIosDeviceTypes, g as parseRuntimeVersion, h as parkedSimName, o as deleteParkedIosSim, r as clearAppDataContainer, s as findAppDataContainer, x as resolveOwnedIosSim } from "./ios-lEJ5pKsq.mjs";
10
+ import { C as shutdownIosSim, _ as renameIosSim, a as deleteIosSim, d as listIosDeviceTypes, g as parseRuntimeVersion, h as parkedSimName, o as deleteParkedIosSim, r as clearAppDataContainer, s as findAppDataContainer, x as resolveOwnedIosSim } from "./ios-BcCiI4TS.mjs";
11
11
  import { createRequire } from "node:module";
12
12
  import { existsSync, lstatSync, readFileSync, renameSync, rmSync } from "node:fs";
13
13
  import { randomUUID } from "node:crypto";
@@ -5,11 +5,11 @@ import { a as findProjectRoot } from "./project-DDZWf_16.mjs";
5
5
  import { l as readRemoteSession, s as readMetroTunnel } from "./state-DZobzxLW.mjs";
6
6
  import { A as resolveSettings, I as unknownSettingKeys, N as settingShapeErrors, a as SETTING_SHAPE_REMEDY } from "./settings-BXXorVM2.mjs";
7
7
  import { a as formatElapsed, f as releasedLeaseFact, i as formatDuration, l as phaseLine, m as shortUdid, u as plural } from "./command-output-B3ycpsYv.mjs";
8
- import { a as POOL_SETTING_REMEDY, l as parkedMaxSetting } from "./teardown-5J5UXz2P.mjs";
8
+ import { a as POOL_SETTING_REMEDY, l as parkedMaxSetting } from "./teardown-BJqEzPo_.mjs";
9
9
  import { h as podInstallCommand, n as HEARTBEAT_INTERVAL_MS } from "./xcode-B6YaWeg0.mjs";
10
10
  import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-D0M7oKA7.mjs";
11
- import { c as withManagedTunnelRemovalLock, o as withManagedRemoteWorktreeRemovalLock } from "./ownership-D5vkdm8H.mjs";
12
- import { n as reclaimProject } from "./reclaim-D614jI6_.mjs";
11
+ import { c as withManagedTunnelRemovalLock, o as withManagedRemoteWorktreeRemovalLock } from "./ownership-wolE-0Do.mjs";
12
+ import { n as reclaimProject } from "./reclaim-KJ-0uWEF.mjs";
13
13
  import { a as runPodInstall, i as runCaptured, n as podsAreStale, r as readPodState, t as DEPS_ERROR } from "./deps-oCXVNEqQ.mjs";
14
14
  import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
15
15
  import { createHash, randomUUID } from "node:crypto";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stim",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Stim: fast, isolated React Native environments for coding agents",
5
5
  "keywords": [
6
6
  "agent",
@@ -42,9 +42,9 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@expo/fingerprint": "^0.20.10",
45
- "@stim-cli/cache": "^1.7.0",
46
- "@stim-cli/core": "^1.7.0",
47
- "@stim-cli/metro": "^1.7.0",
45
+ "@stim-cli/cache": "^1.8.0",
46
+ "@stim-cli/core": "^1.8.0",
47
+ "@stim-cli/metro": "^1.8.0",
48
48
  "chalk": "^6.0.0",
49
49
  "commander": "^15.0.0",
50
50
  "cross-spawn": "^7.0.6",
@@ -52,7 +52,7 @@
52
52
  "ws": "^8.21.3"
53
53
  },
54
54
  "devDependencies": {
55
- "@stim-cli/expo-build-cache": "1.7.0",
55
+ "@stim-cli/expo-build-cache": "1.8.0",
56
56
  "@types/cross-spawn": "^6.0.6",
57
57
  "@types/which": "^3.0.4",
58
58
  "@types/ws": "^8.18.1",