stim 1.20.2 → 1.21.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 (217) hide show
  1. package/README.md +88 -8
  2. package/dist/acquire-artifact-CD4lbiWE.mjs +153 -0
  3. package/dist/act-DHAw2A2S.mjs +2667 -0
  4. package/dist/activity-BzVfHSrY.mjs +1376 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-zh1vhbLp.mjs} +21 -65
  6. package/dist/{android-HqP1_vB_.mjs → android-BEJ8Jpl7.mjs} +2 -2
  7. package/dist/{android-DCKZrNvV.mjs → android-BLgbNqox.mjs} +128 -78
  8. package/dist/{android-Dlzxshgp.mjs → android-CV_GCELZ.mjs} +5 -5
  9. package/dist/{android-Mz_Inn3w.mjs → android-DUYkNF4u.mjs} +184 -102
  10. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-Ct5b1xCK.mjs} +7 -6
  11. package/dist/android-cas-compiler.mjs +2 -2
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/api.d.mts +740 -8
  14. package/dist/api.mjs +585 -1
  15. package/dist/{artifact-HSwkIWEQ.mjs → artifact-B8T3S5gi.mjs} +223 -201
  16. package/dist/{artifact-D3czlUvT.mjs → artifact-DAuZ-FNU.mjs} +158 -148
  17. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-QQzVjz3O.mjs} +26 -24
  18. package/dist/budget-Bs6SxxzO.mjs +9154 -0
  19. package/dist/{build-DYDbfkk5.mjs → build-CoPzQRNw.mjs} +144 -96
  20. package/dist/build-cache-DmyR9Zzc.mjs +602 -0
  21. package/dist/build-plan-CaFskB7_.mjs +188 -0
  22. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DkkqguoK.mjs} +2 -2
  23. package/dist/cache-manifest.mjs +1 -1
  24. package/dist/{ccache-zdKiYQ3E.mjs → ccache-BJRZ9pG3.mjs} +10 -9
  25. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-CWmIUMbw.mjs} +18 -5
  26. package/dist/{chrome-BnzZMqsR.mjs → chrome-B6tfCta1.mjs} +7 -4
  27. package/dist/{cli-CLP3diBm.mjs → cli-0DYf8QhQ.mjs} +20 -20
  28. package/dist/cli.mjs +1 -1
  29. package/dist/client-B7QVOlCr.d.mts +253 -0
  30. package/dist/client-UXD70ZbM.mjs +1406 -0
  31. package/dist/collector-run.d.mts +4 -40
  32. package/dist/collector-run.mjs +9 -8
  33. package/dist/{command-output-BTy8hZ0F.mjs → command-output-B1UrjZHL.mjs} +1 -1
  34. package/dist/config-CYcBF478.mjs +949 -0
  35. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-CqeBlrEn.mjs} +3 -3
  36. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-BbKQW83h.mjs} +20 -5
  37. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-DFRyG1_o.mjs} +1 -1
  38. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-UOeESKm6.mjs} +2 -2
  39. package/dist/device-DCxH7_By.mjs +1068 -0
  40. package/dist/{device-BECOiufl.mjs → device-ExJq8Ei7.mjs} +35 -35
  41. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-CMlqEcvw.mjs} +43 -13
  42. package/dist/device-host-worker.mjs +65 -61
  43. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DRUeKaFV.mjs} +48 -45
  44. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-C8raGFoP.mjs} +14 -26
  45. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-DMRpVX9a.mjs} +5 -5
  46. package/dist/doctor-BLHCYxzi.mjs +2 -0
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-DTvaDOda.mjs} +281 -317
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-Dhqebm0q.mjs} +183 -91
  49. package/dist/doctor-fingerprint.mjs +19 -0
  50. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-Cv1F10Kj.mjs} +40 -21
  51. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-BomfRnFT.mjs} +53 -20
  52. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-DJwZpy0c.mjs} +26 -208
  53. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-op6A54yi.mjs} +229 -11
  54. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-Bf0rZvG9.mjs} +172 -82
  55. package/dist/exec-H20xSg2T.d.mts +65 -0
  56. package/dist/exec-_UbtCQcG.mjs +750 -0
  57. package/dist/gc-C-WwL0yi.mjs +3 -0
  58. package/dist/{gc-qWOMdnER.mjs → gc-_-dCXdyL.mjs} +584 -796
  59. package/dist/git-C3iTsJaZ.mjs +73 -0
  60. package/dist/{guide-G9cAbVAc.mjs → guide-Yqwt2bd6.mjs} +941 -269
  61. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-Bw-honsd.mjs} +8 -6
  62. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DB_gBPfY.mjs} +34 -19
  63. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CUvOf4Vr.mjs} +1 -1
  64. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-DL_P5AdN.mjs} +77 -43
  65. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-QI141yKk.mjs} +21 -17
  66. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-Ksyjgzq-.mjs} +30 -21
  67. package/dist/idle-BVeRGroT.d.mts +24 -0
  68. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DaKmZi0z.mjs} +11 -10
  69. package/dist/{ios-BwVCF7oA.mjs → ios-CQ68hG9s.mjs} +8 -8
  70. package/dist/{ios-RkW4pnQf.mjs → ios-CpByZy12.mjs} +140 -80
  71. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-CXGP1bsD.mjs} +1 -1
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device-CwFMehUS.mjs} +51 -26
  73. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-WuwwBdvW.mjs} +13 -13
  74. package/dist/{ios-nOLJGVdy.mjs → ios-qNJt4dFm.mjs} +1 -1
  75. package/dist/ios-signing-DTTIChGs.mjs +489 -0
  76. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-DvFX-K_l.mjs} +1 -1
  77. package/dist/{ios-Ce7bc7br.mjs → ios-ubFsBzwq.mjs} +129 -86
  78. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Cc1dttps.mjs} +53 -26
  79. package/dist/{launch-F4sOqAhB.mjs → launch-CD1yVc7U.mjs} +91 -90
  80. package/dist/{launch-C3qJ6Agb.mjs → launch-Zq2mOSDy.mjs} +82 -541
  81. package/dist/logs-BS00Anxf.mjs +352 -0
  82. package/dist/logs-CMm05HxN.mjs +255 -0
  83. package/dist/{macos-D7uDvO-z.mjs → macos-B65--pPd.mjs} +1 -1
  84. package/dist/{macos-Ch5VJmcS.mjs → macos-C-0qJ6zq.mjs} +225 -212
  85. package/dist/macos-run.mjs +1 -1
  86. package/dist/maintenance-run.mjs +122 -247
  87. package/dist/{metro-DnCEjCxs.mjs → metro-DEXpIhHC.mjs} +67 -12
  88. package/dist/{metro-gateway-CX9Xlkq2.mjs → metro-gateway-BMJNlj3E.mjs} +20 -12
  89. package/dist/{named-ports-4WopRPg-.mjs → named-ports-BWTzt6mu.mjs} +8 -63
  90. package/dist/native-android-JACyjTZs.mjs +844 -0
  91. package/dist/{native-gradle-inputs-BsLRrl7u.mjs → native-gradle-inputs-Bep9JcSF.mjs} +128 -140
  92. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  93. package/dist/native-run-DY_RLx3C.mjs +277 -0
  94. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-Dg1Q7tfF.mjs} +9 -8
  95. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-CB2iQeWq.mjs} +27 -18
  96. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-CXX39F7o.mjs} +96 -47
  97. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  98. package/dist/offload-worker.d.mts +1 -46
  99. package/dist/offload-worker.mjs +197 -66
  100. package/dist/{ownership-DCtw_2IA.mjs → ownership-DEmM5vhh.mjs} +3 -3
  101. package/dist/{page-DRHy329N.mjs → page-CPaHeYqj.mjs} +7 -4
  102. package/dist/paths-BsJMoPP2.mjs +12 -0
  103. package/dist/paths-DQtTgsBf.mjs +42 -0
  104. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BqGbTa61.mjs} +5 -5
  105. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-Bwj-IjY1.mjs} +6 -6
  106. package/dist/{ports-DdSUicVo.mjs → ports-D-MmCTdv.mjs} +3 -3
  107. package/dist/prebuild-uD_ipCxF.mjs +449 -0
  108. package/dist/{project-_phNIJfs.mjs → project-BZNjmW_8.mjs} +65 -37
  109. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-Lfetn8Kr.mjs} +2 -2
  110. package/dist/pull-request-zjCSAryH.d.mts +120 -0
  111. package/dist/pull-requests.d.mts +1 -119
  112. package/dist/pull-requests.mjs +1 -1
  113. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-DuzH0cn3.mjs} +74 -48
  114. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-rhk4smwQ.mjs} +292 -15
  115. package/dist/react-native-doctor-CQpuIMso.mjs +234 -0
  116. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-Bhq1rJeV.mjs} +46 -28
  117. package/dist/{recordings-D0d5aQt0.mjs → recordings-DYteQSu4.mjs} +12 -9
  118. package/dist/{reload-C8JhxjSh.mjs → reload-CmTRFJaX.mjs} +93 -47
  119. package/dist/reload-DzjSl5P_.mjs +2 -0
  120. package/dist/{remote-BiR6aYjy.mjs → remote-ByYkXdGD.mjs} +15 -10
  121. package/dist/result-DNiS-tTP.mjs +434 -0
  122. package/dist/{run-BtPgpKks.mjs → run-D23HmJMs.mjs} +4 -5
  123. package/dist/selection-CSl9i5qU.mjs +619 -0
  124. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CxTrvDg8.mjs} +3 -4
  125. package/dist/{server-command-CTtCkmcQ.mjs → server-command-CtzloH3v.mjs} +14 -7
  126. package/dist/server-expo-C-90EhcG.mjs +2 -0
  127. package/dist/{server-expo-DsguMGUF.mjs → server-expo-DT_F_uVI.mjs} +50 -9
  128. package/dist/{settings-B717odTD.mjs → settings-CsJDEXgK.mjs} +234 -24
  129. package/dist/{settings-vk3mJGSm.d.mts → settings-DkdmlelE.d.mts} +6 -4
  130. package/dist/settings-T1gtc3bf.mjs +114 -0
  131. package/dist/settings-write-HyVZ8eQ8.mjs +359 -0
  132. package/dist/settings.schema.json +163 -16
  133. package/dist/{simslim-CCr3rE-A.mjs → simslim-Cgk17SXV.mjs} +14 -12
  134. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-DF8VfT64.mjs} +15 -20
  135. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  136. package/dist/stage-BIS0ydsV.mjs +183 -0
  137. package/dist/{start-BWqzODpb.mjs → start-7lpH7hmN.mjs} +63 -44
  138. package/dist/{start-TXeMmmO2.mjs → start-RChynRDp.mjs} +1 -1
  139. package/dist/{state-D1Icyjlu.mjs → state-C4ZtUisW.mjs} +40 -13
  140. package/dist/{state-CG_OFoaA.mjs → state-XMziexv2.mjs} +3 -2
  141. package/dist/{stats-BoY5sEPU.mjs → stats-53T7OTb9.mjs} +7 -13
  142. package/dist/stats-report-BFfMpWWF.mjs +16 -0
  143. package/dist/{status-WgFbkRzj.mjs → status-BL7jVyAB.mjs} +535 -447
  144. package/dist/status-CSi6tlRq.mjs +2 -0
  145. package/dist/{status-BTA7kKiQ.mjs → status-DqEUSSxs.mjs} +6 -4
  146. package/dist/{status-watch-C23ILtf9.mjs → status-watch-GDCfqpTE.mjs} +187 -22
  147. package/dist/status-worker.d.mts +1 -0
  148. package/dist/status-worker.mjs +19 -0
  149. package/dist/stim-desktop-C12we7lz.mjs +112 -0
  150. package/dist/{stop-DR6VoDIk.mjs → stop-Bk_1qiV6.mjs} +2 -2
  151. package/dist/{stop-BNmBMi1F.mjs → stop-CPzlM1L-.mjs} +138 -98
  152. package/dist/{stop-DPEhunlw.mjs → stop-D7h6jAXQ.mjs} +11 -10
  153. package/dist/supervisor-run.d.mts +8 -17
  154. package/dist/supervisor-run.mjs +63 -27
  155. package/dist/{support-DMTqj3Hm.mjs → support-67vraa1Q.mjs} +18 -11
  156. package/dist/{support-CwjbFs9H.mjs → support-Dlu37g6H.mjs} +12 -12
  157. package/dist/{swiftpm-macos-DRNVJWlb.mjs → swiftpm-macos-p8WZbxKU.mjs} +35 -24
  158. package/dist/toolchain-DhKwp9iI.mjs +2 -0
  159. package/dist/toolchain-Hp9sCpK4.mjs +873 -0
  160. package/dist/{trigger-CigAYjeL.mjs → trigger-BAahxUPq.mjs} +20 -5
  161. package/dist/trigger-Bf3uDcpv.mjs +2 -0
  162. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-BHX5r0Ei.mjs} +250 -156
  163. package/dist/{web-BDBMxDpx.mjs → web-CJmIj6AI.mjs} +18 -13
  164. package/dist/web-DknQETPs.mjs +2 -0
  165. package/dist/web-run.mjs +11 -12
  166. package/dist/windows-report.d.mts +1 -0
  167. package/dist/windows-report.mjs +18 -0
  168. package/dist/windows-report.ps1 +43 -0
  169. package/dist/workspace-process-lock-1_1OoVW5.mjs +57 -0
  170. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-Cjuigeeu.mjs} +62 -58
  171. package/dist/{workspaces-C36s2jb9.mjs → workspaces-BccMFmGQ.mjs} +1188 -1079
  172. package/dist/worktree-CK2MpJW5.mjs +2 -0
  173. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-DQ6Zi2Mv.mjs} +304 -53
  174. package/dist/xcode-Zlx3qjEs.mjs +896 -0
  175. package/package.json +7 -5
  176. package/shim/android-optimizations.gradle +7 -5
  177. package/dist/activity-BSV745Kz.mjs +0 -629
  178. package/dist/api-qvOzWyfO.mjs +0 -154
  179. package/dist/api-run.mjs +0 -294
  180. package/dist/app-install-BIKtMfPq.mjs +0 -896
  181. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  182. package/dist/budget-f7516Zk0.mjs +0 -4106
  183. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  184. package/dist/cancellation-C_22VQTH.mjs +0 -24
  185. package/dist/client-qQAaXSUs.mjs +0 -1771
  186. package/dist/config-BYDxlMY3.mjs +0 -562
  187. package/dist/device-DuiPJQSn.mjs +0 -290
  188. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  189. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  190. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  191. package/dist/exec-DqKo9GKJ.mjs +0 -268
  192. package/dist/git-DDfFzkMm.mjs +0 -45
  193. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  194. package/dist/logs-BGrEUaEs.mjs +0 -383
  195. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  196. package/dist/native-android-D5qc3-_v.mjs +0 -226
  197. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  198. package/dist/plan-C4TjdPsR.mjs +0 -260
  199. package/dist/prebuild-DYbucPXy.mjs +0 -212
  200. package/dist/preview-78a9kR_-.mjs +0 -1011
  201. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  202. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  203. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  204. package/dist/result-CaJg5Iat.mjs +0 -186
  205. package/dist/server-expo-Bigriskl.mjs +0 -2
  206. package/dist/settings-BORNaaCO.mjs +0 -402
  207. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  208. package/dist/stage-KNTQopqv.mjs +0 -157
  209. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  210. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  211. package/dist/toolchain-BFkAcstd.mjs +0 -2
  212. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  213. package/dist/trigger-9_USgmxz.mjs +0 -2
  214. package/dist/web-Dq-i3wzJ.mjs +0 -2
  215. package/dist/worktree-DpLdCHga.mjs +0 -2
  216. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  217. package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
@@ -1,34 +1,36 @@
1
- import { _ as loadConfig$1, s as configCorruptRepair, u as getConcurrencyLimits } from "./config-BYDxlMY3.mjs";
2
- import { t as getExecutor } from "./exec-DqKo9GKJ.mjs";
3
- import { r as gitQuiet, t as git } from "./git-DDfFzkMm.mjs";
4
- import { B as remoteAndroidSetting, Ct as locallyKnownUpstream, D as mergeSettingsLayers, Dt as repoRoot, Ft as makeTemporaryDirectory, G as resolveIosProjectDir, H as remoteIosSetting, I as projectSettingsContext, Lt as temporaryRoot, Pt as filesystemDevice, Q as settingShapeErrors, St as listWorktrees, T as iosSimSlimProfileSetting, U as resolveAndroidLayout, X as settingOrigin, a as SETTING_SHAPE_REMEDY, et as settingsLayers, ht as gitCommonDir, i as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, kt as resolveSourceCheckout, m as defaultAndroidLayout, nt as unknownSettingKeys, pt as dirtyFingerprintFiles, q as resolveSettings, r as PATH_SETTINGS, rt as webSettings } from "./settings-B717odTD.mjs";
5
- import { C as diffFingerprintSources, D as fingerprintProject, h as listBuildLocks } from "./device-lease-BX1sJQ2E.mjs";
6
- import { b as workspaceDerivedData, m as sharedBuildCache } from "./workspace-state-DJt_MMvf.mjs";
7
- import { d as quotedPath, u as plural } from "./command-output-BTy8hZ0F.mjs";
8
- import { S as resolvePackageJson, _ as detectIsExpo, g as appProjectProblem, y as isPackageResolvable } from "./project-_phNIJfs.mjs";
9
- import { D as hostSystemImageArch, at as POOL_SETTING_REMEDY, dt as parkedMaxSetting, o as androidHome } from "./android-Mz_Inn3w.mjs";
10
- import { I as listBuildSlots } from "./workspaces-C36s2jb9.mjs";
11
- import { l as realIo } from "./tailnet-Dh-qiYzG.mjs";
12
- import { p as resolveOptimizations, u as compilerCacheFallbackMessage } from "./errors-DzkMYh8Q.mjs";
13
- import { f as resolveEasCliBin, i as checkEasAuth$1, l as ownerFromConfig, u as providerFromConfig } from "./remote-cache-OyOyVIS3.mjs";
14
- import { M as hostMemoryPressureAdvice, P as readHostMemoryPressure } from "./ios-RkW4pnQf.mjs";
15
- import { i as projectCmakeLauncher } from "./ccache-zdKiYQ3E.mjs";
16
- import { r as androidSdkRefusal } from "./gradle-DSrXb6lG.mjs";
17
- import { L as podInstallCommand } from "./toolchain-DxSsNssu.mjs";
18
- import { i as countLiveOwnedDevices } from "./device-capacity-CBUAcRyQ.mjs";
19
- import { d as androidPathRoomRemedy, i as ccacheEnabled, l as androidPathRoom, t as apkOutputsDir, u as androidPathRoomMessage } from "./react-native-build-CtCccJtb.mjs";
20
- import { r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-Bl-cLJBk.mjs";
21
- import { g as easCliUpgradeRemedy, h as easCliSupport, m as MIN_EAS_CLI_SIMULATOR_VERSION, s as readInstalledEasCliVersion } from "./device-remote-xRT0Vmo9.mjs";
22
- import { t as MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION } from "./eas-build-JyfqyHfC.mjs";
23
- import { n as simslimIsOnPath } from "./simslim-CCr3rE-A.mjs";
24
- import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-DG0p31-y.mjs";
25
- import { a as findChrome, t as CHROME_INSTALL_REMEDY } from "./chrome-BnzZMqsR.mjs";
1
+ import { g as trackReportResource, m as reportSignal, t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
+ import { i as sharedBuildCache, u as workspaceDerivedData } from "./paths-DQtTgsBf.mjs";
3
+ import { _ as loadConfig$1, rt as realIo, s as configCorruptRepair, u as getConcurrencyLimits } from "./config-CYcBF478.mjs";
4
+ import { d as quotedPath, u as plural } from "./command-output-B1UrjZHL.mjs";
5
+ import { r as readWorkspaceState$1 } from "./workspace-state-Cjuigeeu.mjs";
6
+ import { D as mergeSettingsLayers, Ft as repoRoot, I as projectSettingsContext, It as repoRootAsync, Jt as filesystemDevice, K as resolveIosProjectDir, Q as settingOrigin, T as iosSimSlimProfileSetting, U as remoteIosSetting, V as remoteAndroidSetting, W as resolveAndroidLayout, Y as resolveSettings, Yt as makeTemporaryDirectory, Zt as temporaryRoot, a as SETTING_SHAPE_REMEDY, at as webSettings, et as settingShapeErrors, ht as dirtyFingerprintFiles, i as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, it as unknownSettingKeys, jt as locallyKnownUpstreamAsync, kt as listWorktreesAsync, m as defaultAndroidLayout, nt as settingsLayers, r as PATH_SETTINGS, tt as settingValueAt, yt as gitCommonDirAsync, zt as resolveSourceCheckoutAsync } from "./settings-CsJDEXgK.mjs";
7
+ import { i as gitQuietAsync, t as git } from "./git-C3iTsJaZ.mjs";
8
+ import { C as resolvePackageJson, _ as appProjectProblem, b as isPackageResolvable, v as detectIsExpo } from "./project-BZNjmW_8.mjs";
9
+ import { Bn as checkEasAuth$1, Gn as providerFromConfig, Ht as readInstalledEasCliVersionAsync, Wn as ownerFromConfig, er as MIN_EAS_CLI_SIMULATOR_VERSION, nr as easCliUpgradeRemedy, qn as resolveEasCliBin, tr as easCliSupport } from "./budget-Bs6SxxzO.mjs";
10
+ import { I as listBuildSlots } from "./workspaces-BccMFmGQ.mjs";
11
+ import { N as listBuildLocks } from "./activity-BzVfHSrY.mjs";
12
+ import { a as diffFingerprintSources, l as fingerprintProject } from "./build-cache-DmyR9Zzc.mjs";
13
+ import { O as hostSystemImageArch, ht as parkedMaxSetting, lt as POOL_SETTING_REMEDY, o as androidHome } from "./android-DUYkNF4u.mjs";
14
+ import { F as readHostMemoryPressureAsync, M as hostMemoryPressureAdvice } from "./ios-CpByZy12.mjs";
15
+ import { p as resolveOptimizations, u as compilerCacheFallbackMessage } from "./errors-ccaPc4ox.mjs";
16
+ import { i as projectCmakeLauncher } from "./ccache-BJRZ9pG3.mjs";
17
+ import { x as podInstallCommand } from "./xcode-Zlx3qjEs.mjs";
18
+ import { h as androidPathRoomRemedy, i as ccacheEnabled, l as androidSdkRefusal, m as androidPathRoomMessage, p as androidPathRoom, t as apkOutputsDir } from "./react-native-build-rhk4smwQ.mjs";
19
+ import { a as countLiveOwnedDevicesAsync, i as countLiveOwnedDevices } from "./device-capacity-CMlqEcvw.mjs";
20
+ import { i as probeSigningIdentities } from "./ios-signing-DTTIChGs.mjs";
21
+ import { a as findChrome, t as CHROME_INSTALL_REMEDY } from "./chrome-B6tfCta1.mjs";
22
+ import { i as installedNpmTreeIsValidAsync, n as hasInstalledDependencies, t as dependencyState } from "./dependency-state-BbKQW83h.mjs";
23
+ import { n as simslimIsOnPath } from "./simslim-Cgk17SXV.mjs";
24
+ import { t as MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION } from "./eas-build-BomfRnFT.mjs";
25
+ import { r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-Ct5b1xCK.mjs";
26
26
  import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
27
27
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
28
+ import { LAST_BUILD_KEYS, isJsonObject, readBuildHistory, readJsonObject, readStats, settingDefinition } from "@stim-cli/core/state";
28
29
  import { basename as basename$1, dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
29
- import { isJsonObject, readJsonObject, readStats, settingDefinition } from "@stim-cli/core/state";
30
- import { existsSync as existsSync$1, lstatSync as lstatSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, rmSync as rmSync$1 } from "fs";
30
+ import { fileURLToPath } from "node:url";
31
+ import { existsSync as existsSync$1, lstatSync as lstatSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1 } from "fs";
31
32
  import * as expoFingerprint from "@expo/fingerprint";
33
+ import { rm } from "fs/promises";
32
34
  import { createRequire } from "module";
33
35
  //#region src/diagnostics/doctor-config.ts
34
36
  function readMachineSettings(context) {
@@ -139,26 +141,44 @@ function missingPath(value, projectRoot, exists, trim = false) {
139
141
  }
140
142
  //#endregion
141
143
  //#region src/diagnostics/doctor-storage.ts
144
+ const temporaryFix = "Unset STIM_TMPDIR / machine tempDir to select same-volume staging automatically, or point the override at a writable directory on the relevant volume outside Git working trees.";
145
+ function crossFilesystem(operation, paths, fix, device) {
146
+ if (new Set(paths.map(device)).size < 2) return null;
147
+ return {
148
+ level: "cost",
149
+ title: `${operation} crosses filesystems`,
150
+ detail: `${paths.join(" -> ")}. These copies cannot share file blocks across volumes and can consume the full artifact size in space and I/O. cp -c can silently perform a full copy without an error.`,
151
+ fix
152
+ };
153
+ }
154
+ function storageFailure(error) {
155
+ return {
156
+ level: "cost",
157
+ title: "Could not resolve temporary storage",
158
+ detail: String(error.message),
159
+ fix: temporaryFix
160
+ };
161
+ }
162
+ async function checkWorktreeStorageLayout({ root, repoRoot, options }, { device = filesystemDevice } = {}) {
163
+ if (options.machineSettings?.corrupt) return [];
164
+ try {
165
+ const target = repoRoot ?? root;
166
+ const source = await resolveSourceCheckoutAsync(target);
167
+ const finding = crossFilesystem("Worktree copy", ["path" in source ? source.path : target, target], "Keep the source checkout and linked worktree on the same volume to share file blocks when warming.", device);
168
+ return finding ? [finding] : [];
169
+ } catch (error) {
170
+ return [storageFailure(error)];
171
+ }
172
+ }
142
173
  function checkStorageLayout(projectRoot, { platform, iosProjectPath = "ios", androidLayout = defaultAndroidLayout(projectRoot), host = process.platform, device = filesystemDevice, stagingRoot = temporaryRoot, scope } = {}) {
143
174
  const findings = [];
144
- const temporaryFix = "Unset STIM_TMPDIR / machine tempDir to select same-volume staging automatically, or point the override at a writable directory on the relevant volume outside Git working trees.";
145
175
  const check = (operation, paths, fix) => {
146
- if (new Set(paths.map(device)).size < 2) return;
147
- findings.push({
148
- level: "cost",
149
- title: `${operation} crosses filesystems`,
150
- detail: `${paths.join(" -> ")}. These copies cannot share file blocks across volumes and can consume the full artifact size in space and I/O. cp -c can silently perform a full copy without an error.`,
151
- fix
152
- });
176
+ const finding = crossFilesystem(operation, paths, fix, device);
177
+ if (finding) findings.push(finding);
153
178
  };
154
179
  try {
155
180
  const cache = sharedBuildCache();
156
- if (scope !== "native") {
157
- const target = repoRoot(projectRoot) ?? projectRoot;
158
- const source = resolveSourceCheckout(target);
159
- check("Worktree copy", ["path" in source ? source.path : target, target], "Keep the source checkout and linked worktree on the same volume to share file blocks when warming.");
160
- check("Cached app/APK staging", [cache, stagingRoot(join(cache, "artifact.app"))], temporaryFix);
161
- }
181
+ if (scope !== "native") check("Cached app/APK staging", [cache, stagingRoot(join(cache, "artifact.app"))], temporaryFix);
162
182
  const cacheFix = "Place STIM_BUILD_CACHE / machine caches.buildCache on the build-output volume, or accept the full-copy cost of keeping the cache on a separate volume.";
163
183
  const localIos = platform === "ios" || platform !== "android" && existsSync(join(projectRoot, iosProjectPath));
164
184
  if (scope !== "shared" && localIos && host === "darwin") {
@@ -168,150 +188,22 @@ function checkStorageLayout(projectRoot, { platform, iosProjectPath = "ios", and
168
188
  }
169
189
  if (scope !== "shared" && (platform === "android" || platform !== "ios" && existsSync(androidLayout.gradleRoot))) check("Android build-cache storage", [apkOutputsDir(androidLayout), cache], cacheFix);
170
190
  } catch (error) {
171
- findings.push({
172
- level: "cost",
173
- title: "Could not resolve temporary storage",
174
- detail: String(error.message),
175
- fix: temporaryFix
176
- });
191
+ findings.push(storageFailure(error));
177
192
  }
178
193
  return findings;
179
194
  }
180
195
  //#endregion
181
- //#region src/diagnostics/doctor-ios-architectures.ts
182
- const COMPILED_PRODUCTS = /* @__PURE__ */ new Set([
183
- "com.apple.product-type.application",
184
- "com.apple.product-type.application.on-demand-install-capable",
185
- "com.apple.product-type.app-extension",
186
- "com.apple.product-type.framework",
187
- "com.apple.product-type.library.static",
188
- "com.apple.product-type.library.dynamic"
189
- ]);
190
- function architectureList(value) {
191
- if (typeof value !== "string" || /[^\w\s-]/.test(value)) return null;
192
- return [...new Set(value.split(/\s+/).filter(Boolean))];
193
- }
194
- function parseIosDebugArchitectures(output) {
195
- const report = {
196
- affected: [],
197
- unknown: false
198
- };
199
- let data;
200
- try {
201
- data = JSON.parse(output);
202
- } catch {
203
- return {
204
- ...report,
205
- unknown: true
206
- };
207
- }
208
- if (!Array.isArray(data) || data.length === 0) return {
209
- ...report,
210
- unknown: true
211
- };
212
- let inspected = false;
213
- for (const entry of data) {
214
- if (!entry || typeof entry !== "object" || entry.error || !entry.buildSettings) {
215
- report.unknown = true;
216
- continue;
217
- }
218
- const settings = entry.buildSettings;
219
- if (settings.CONFIGURATION !== "Debug" || settings.PLATFORM_NAME !== "iphonesimulator") {
220
- report.unknown = true;
221
- continue;
222
- }
223
- if (!settings.PRODUCT_TYPE) continue;
224
- if (settings.PRODUCT_TYPE === "com.apple.product-type.bundle") {
225
- inspected = true;
226
- continue;
227
- }
228
- if (!COMPILED_PRODUCTS.has(settings.PRODUCT_TYPE)) {
229
- report.unknown = true;
230
- continue;
231
- }
232
- inspected = true;
233
- if (settings.ONLY_ACTIVE_ARCH === "YES") continue;
234
- const archs = architectureList(settings.ARCHS);
235
- const valid = settings.VALID_ARCHS === void 0 ? archs : architectureList(settings.VALID_ARCHS);
236
- const excluded = architectureList(settings.EXCLUDED_ARCHS ?? "");
237
- if (settings.ONLY_ACTIVE_ARCH !== "NO" || !archs?.length || !valid || !excluded || typeof entry.target !== "string") {
238
- report.unknown = true;
239
- continue;
240
- }
241
- const architectures = archs.filter((arch) => valid.includes(arch) && !excluded.includes(arch));
242
- if (architectures.length > 1) report.affected.push({
243
- target: entry.target,
244
- architectures
245
- });
246
- }
247
- return {
248
- ...report,
249
- unknown: report.unknown || !inspected
250
- };
251
- }
252
- function inspectIosDebugArchitectures(projectRoot, iosProjectPath = "ios") {
253
- const iosRoot = join(projectRoot, iosProjectPath);
254
- if (!existsSync(iosRoot)) return [];
255
- const findings = [];
256
- const unknown = [];
257
- let projects;
258
- try {
259
- projects = readdirSync(iosRoot).filter((name) => name.endsWith(".xcodeproj")).toSorted().map((name) => join(iosRoot, name));
260
- } catch {
261
- projects = [];
262
- }
263
- if (!projects.length) unknown.push("app project");
264
- const pods = join(iosRoot, "Pods", "Pods.xcodeproj");
265
- if (existsSync(pods)) projects.push(pods);
266
- else if (existsSync(join(iosRoot, "Podfile"))) unknown.push("Pods project (not generated)");
267
- const deadline = Date.now() + 6e4;
268
- for (const project of projects) {
269
- const label = relative(projectRoot, project);
270
- const timeoutMs = Math.min(3e4, deadline - Date.now());
271
- if (timeoutMs <= 0) {
272
- unknown.push(label);
273
- continue;
274
- }
275
- try {
276
- const report = parseIosDebugArchitectures(getExecutor().runFile("xcodebuild", [
277
- "-project",
278
- project,
279
- "-alltargets",
280
- "-configuration",
281
- "Debug",
282
- "-sdk",
283
- "iphonesimulator",
284
- "-showBuildSettings",
285
- "-json",
286
- "-disableAutomaticPackageResolution",
287
- "-skipPackageUpdates"
288
- ], {
289
- cwd: iosRoot,
290
- timeoutMs
291
- }));
292
- if (report.unknown) unknown.push(label);
293
- if (report.affected.length) {
294
- const targets = report.affected.slice(0, 5).map(({ target, architectures }) => `${target} (${architectures.join(", ")})`).join("; ");
295
- findings.push({
296
- code: "ios-debug-architectures",
297
- level: "cost",
298
- title: "iOS Debug targets build multiple simulator architectures",
299
- detail: `${label}: ${report.affected.length} Debug target(s) resolve ONLY_ACTIVE_ARCH=NO with multiple architectures after exclusions: ${targets}${report.affected.length > 5 ? `; plus ${report.affected.length - 5} more` : ""}. This can compile extra native code when targeting one simulator.`,
300
- fix: "Review the Debug ONLY_ACTIVE_ARCH override in the project, xcconfig, or Podfile post_install helpers. Prefer YES for local Debug simulator builds where appropriate; preserve intentional Release and distribution settings. Regenerate Pods through the project workflow after changing a helper, then rerun stim doctor --platform ios. Doctor --fix does not change architecture settings."
301
- });
302
- }
303
- } catch {
304
- unknown.push(label);
305
- }
306
- }
307
- if (unknown.length) findings.push({
308
- code: "ios-debug-architectures-unknown",
309
- level: "note",
310
- title: "iOS Debug architecture settings could not be fully inspected",
311
- detail: `Effective Debug simulator settings are unavailable for ${unknown.join(", ")}. Architecture policy is not verified for those targets. Metadata inspection has a 60-second total budget.`,
312
- fix: "Ensure Xcode can read the generated app and Pods projects, then rerun stim doctor --platform ios. Doctor does not evaluate Podfiles or install Pods to inspect architecture settings."
196
+ //#region src/doctor-fingerprint.ts
197
+ async function readDoctorFingerprint(operation, request) {
198
+ const output = await getExecutor().runFileAsync(process.execPath, [fileURLToPath(new URL("../dist/doctor-fingerprint.mjs", import.meta.url))], {
199
+ cwd: operation.cwd,
200
+ env: Object.fromEntries(Object.entries(operation.env).filter((entry) => entry[1] !== void 0)),
201
+ input: JSON.stringify(request),
202
+ timeoutMs: 6e4,
203
+ killSignal: "SIGKILL",
204
+ signal: operation.signal
313
205
  });
314
- return findings;
206
+ return JSON.parse(output);
315
207
  }
316
208
  //#endregion
317
209
  //#region src/diagnostics/doctor-cxx.ts
@@ -341,7 +233,7 @@ function moduleRoots(root, layout) {
341
233
  function cacheFiles(base, depth = 0) {
342
234
  const files = [];
343
235
  for (const name of children(base)) {
344
- if (depth === 0 && /^stim-[a-f0-9]{16}$/.test(name)) continue;
236
+ if (depth === 0 && /^(?:stim-[a-f0-9]{16}|[a-f0-9]{4})$/.test(name)) continue;
345
237
  const path = join(base, name);
346
238
  const entry = lstatSync(path);
347
239
  if (entry.isSymbolicLink()) continue;
@@ -451,6 +343,23 @@ function finding(level, title, detail, fix) {
451
343
  fix
452
344
  };
453
345
  }
346
+ const isDeviceCacheKey = (key) => typeof key === "string" && /-device(?:-|$)/.test(key);
347
+ /** Whether this workspace has run, or is set up for, `ios --device`: a device build in its history or an iOS signing or LAN setting. */
348
+ function deviceWorkflowPlausible(state, settings) {
349
+ const last = state?.[LAST_BUILD_KEYS.ios];
350
+ if (last && typeof last === "object" && "cacheKey" in last && isDeviceCacheKey(last.cacheKey)) return true;
351
+ if ((readBuildHistory(state).ios ?? []).some((entry) => isDeviceCacheKey(entry.cacheKey))) return true;
352
+ return [
353
+ "ios.signingIdentity",
354
+ "ios.signingIdentitySha1",
355
+ "ios.lanHost"
356
+ ].some((key) => settingValueAt(settings, key) !== void 0);
357
+ }
358
+ function checkDeviceSigning(identities) {
359
+ if (identities === null) return finding("note", "Could not list code signing identities", "`security find-identity -v -p codesigning` failed, so doctor cannot tell whether `stim ios --device` can sign a build for a phone.", "Run `security find-identity -v -p codesigning` to see the error; a locked login keychain is the usual cause (`security unlock-keychain`).");
360
+ if (identities.length > 0) return null;
361
+ return finding("note", "No code signing identity for iOS device builds", "`security find-identity -v -p codesigning` lists no identity on this Mac, so `stim ios --device` cannot sign a build for a phone. Simulator runs are unaffected.", "With the phone connected, run `stim device provision ios`: it lists the Apple Developer account changes (register the phone, create or refresh its Development profile, create an Apple Development certificate) and asks before making them; an agent runs it only with your go-ahead. Or sign in under Xcode > Settings > Accounts and build once from Xcode to the phone.");
362
+ }
454
363
  function checkOffloadCandidate(placements, machines, peers, now) {
455
364
  if (machines.length || !peers.some((peer) => isJsonObject(peer) && peer.OS === "macOS" && peer.Online === true)) return null;
456
365
  const cold = placements.filter((placement) => {
@@ -462,27 +371,27 @@ function checkOffloadCandidate(placements, machines, peers, now) {
462
371
  if (average <= 18e4) return null;
463
372
  return {
464
373
  code: "offload-candidate",
465
- ...finding("note", "Builds could run on another Mac", `Cold builds averaged ~${Math.round(average / 6e4)} min over ${cold.length} builds this week.`, "In Stim Desktop, open Settings > Remote Macs > Add.")
374
+ ...finding("note", "Builds could run on another machine", `Cold builds averaged ~${Math.round(average / 6e4)} min over ${cold.length} builds this week.`, "In Stim Desktop, open Settings > Remote Machines > Add.")
466
375
  };
467
376
  }
468
- function readOffloadCandidate(tailnetStatus, now, host) {
377
+ async function readOffloadCandidate(tailnetStatus, now, host) {
469
378
  if (host !== "darwin") return null;
470
379
  try {
471
380
  const entries = loadConfig$1()?.remote?.machines;
472
381
  const machines = Array.isArray(entries) ? entries.filter((entry) => typeof entry === "string") : [];
473
382
  const placements = readStats().record?.placements ?? [];
474
383
  if (machines.length || placements.length < 3) return null;
475
- const status = tailnetStatus();
384
+ const status = await tailnetStatus();
476
385
  return checkOffloadCandidate(placements, machines, isJsonObject(status) && isJsonObject(status.Peer) ? Object.values(status.Peer) : [], now);
477
386
  } catch {
478
387
  return null;
479
388
  }
480
389
  }
481
- function mainCheckoutProjectRoot(projectRoot) {
482
- const currentRepoRoot = repoRoot(projectRoot);
390
+ async function mainCheckoutProjectRoot(projectRoot) {
391
+ const currentRepoRoot = await repoRootAsync(projectRoot);
483
392
  if (!currentRepoRoot) return projectRoot;
484
393
  try {
485
- const source = resolveSourceCheckout(currentRepoRoot);
394
+ const source = await resolveSourceCheckoutAsync(currentRepoRoot);
486
395
  if ("refusal" in source) return projectRoot;
487
396
  const projectRel = relative$1(currentRepoRoot, realpathSync$1(projectRoot));
488
397
  if (projectRel.startsWith("..")) return projectRoot;
@@ -491,15 +400,15 @@ function mainCheckoutProjectRoot(projectRoot) {
491
400
  return projectRoot;
492
401
  }
493
402
  }
494
- function brokenPodLinks(podsRoot) {
403
+ async function brokenPodLinks(podsRoot) {
495
404
  try {
496
- return getExecutor().runFile("find", [
405
+ return (await getExecutor().runFileAsync("find", [
497
406
  "-L",
498
407
  podsRoot,
499
408
  "-type",
500
409
  "l",
501
410
  "-print"
502
- ], { timeoutMs: 1e4 }).split("\n").map((line) => line.trim()).filter(Boolean);
411
+ ], { timeoutMs: 1e4 })).split("\n").map((line) => line.trim()).filter(Boolean);
503
412
  } catch {
504
413
  return [];
505
414
  }
@@ -514,90 +423,90 @@ function hasIosWarmOutput(root, iosRoot) {
514
423
  return false;
515
424
  }
516
425
  }
517
- function hasLinkedWorktree(projectRoot) {
518
- const root = repoRoot(projectRoot);
426
+ async function hasLinkedWorktree(projectRoot) {
427
+ const root = await repoRootAsync(projectRoot);
519
428
  if (!root) return false;
520
- return listWorktrees(root).filter((entry) => !entry.prunable && !entry.bare).length > 1;
429
+ return (await listWorktreesAsync(root)).filter((entry) => !entry.prunable && !entry.bare).length > 1;
521
430
  }
522
- function headBranch(root) {
523
- const ref = gitQuiet(root, [
431
+ async function headBranch(root) {
432
+ const ref = (await gitQuietAsync(root, [
524
433
  "symbolic-ref",
525
434
  "--quiet",
526
435
  "HEAD"
527
- ])?.trim();
436
+ ]))?.trim();
528
437
  return ref?.startsWith("refs/heads/") ? ref.slice(11) : null;
529
438
  }
530
- function mainOperation(root) {
531
- const gitDir = gitQuiet(root, [
439
+ async function mainOperation(root) {
440
+ const gitDir = (await gitQuietAsync(root, [
532
441
  "rev-parse",
533
442
  "--path-format=absolute",
534
443
  "--git-dir"
535
- ])?.trim();
444
+ ]))?.trim();
536
445
  if (!gitDir) return null;
537
446
  if (existsSync$1(join$1(gitDir, "rebase-merge")) || existsSync$1(join$1(gitDir, "rebase-apply"))) return "rebase";
538
447
  return existsSync$1(join$1(gitDir, "MERGE_HEAD")) ? "merge" : null;
539
448
  }
540
- function dirtyTrackedPaths(root) {
541
- return (gitQuiet(root, [
449
+ async function dirtyTrackedPaths(root) {
450
+ return (await gitQuietAsync(root, [
542
451
  "diff",
543
452
  "--name-only",
544
453
  "HEAD"
545
454
  ]) ?? "").split("\n").map((line) => line.trim()).filter(Boolean);
546
455
  }
547
- function resolveDefaultBranch(root) {
456
+ async function resolveDefaultBranch(root) {
548
457
  const worktree = resolveSettings({
549
- gitCommonDir: gitCommonDir(root),
550
- repoRoot: repoRoot(root) ?? root
458
+ gitCommonDir: await gitCommonDirAsync(root),
459
+ repoRoot: await repoRootAsync(root) ?? root
551
460
  }).worktree;
552
461
  const configured = worktree && typeof worktree === "object" && !Array.isArray(worktree) ? worktree.defaultBranch : void 0;
553
462
  if (typeof configured === "string" && configured.trim()) return configured.trim();
554
- const head = gitQuiet(root, [
463
+ const head = (await gitQuietAsync(root, [
555
464
  "symbolic-ref",
556
465
  "--short",
557
466
  "refs/remotes/origin/HEAD"
558
- ])?.trim();
467
+ ]))?.trim();
559
468
  if (!head) return null;
560
469
  const cut = head.indexOf("/");
561
470
  return cut > 0 ? head.slice(cut + 1) : head;
562
471
  }
563
- function seedFindings(mainRoot, upstream) {
472
+ async function seedFindings(mainRoot, upstream) {
564
473
  const findings = [];
565
- const root = repoRoot(mainRoot);
474
+ const root = await repoRootAsync(mainRoot);
566
475
  const quotedRoot = quotedPath(root ?? mainRoot);
567
476
  if (upstream && upstream.behind > 0 && upstream.ahead === 0) findings.push(finding("note", `The source checkout is ${plural(upstream.behind, "commit")} behind ${upstream.name}`, "The count uses the locally known upstream ref. A fetch can reveal additional commits. A later rebase or merge can change native inputs and invalidate work done from the older base.", `Run \`stim worktree warm --refresh\` from a linked worktree to fetch and fast-forward the source checkout, or \`git -C ${quotedRoot} fetch --prune\` and inspect the branch yourself.`));
568
477
  if (root === null) return findings;
569
- const operation = mainOperation(root);
478
+ const operation = await mainOperation(root);
570
479
  if (operation) {
571
480
  findings.push(finding("note", `The source checkout has a ${operation} in progress`, "`stim worktree warm --refresh` refuses a source checkout it cannot move, and the branch stays where the interrupted operation left it.", `Finish it, or run \`git -C ${quotedRoot} ${operation} --abort\`.`));
572
481
  return findings;
573
482
  }
574
- const dirty = dirtyTrackedPaths(root);
483
+ const dirty = await dirtyTrackedPaths(root);
575
484
  if (dirty.length) findings.push(finding("note", `The source checkout has ${plural(dirty.length, "uncommitted tracked change")}`, `\`stim worktree warm --refresh\` refuses a source checkout it cannot move, so the seed stays where it is until this is cleared. First: ${dirty[0]}.`, `Commit them, or run \`git -C ${quotedRoot} stash push -u -m warm-refresh\`.`));
576
- const branch = headBranch(root);
485
+ const branch = await headBranch(root);
577
486
  if (branch === null) {
578
487
  findings.push(finding("note", "The source checkout has a detached HEAD", "`stim worktree warm --refresh` refuses: there is no branch to fast-forward.", `Run \`git -C ${quotedRoot} checkout <branch>\`.`));
579
488
  return findings;
580
489
  }
581
490
  if (upstream && upstream.ahead > 0 && upstream.behind > 0) findings.push(finding("note", `The source checkout has diverged from ${upstream.name}`, `${branch} is ${upstream.ahead} ahead of and ${upstream.behind} behind ${upstream.name}, so it cannot fast-forward. \`stim worktree warm --refresh\` refuses rather than merging or resetting.`, `Rebase or merge ${branch} onto ${upstream.name} yourself.`));
582
- const defaultBranch = resolveDefaultBranch(root);
491
+ const defaultBranch = await resolveDefaultBranch(root);
583
492
  if (defaultBranch !== null && defaultBranch !== branch) findings.push(finding("note", `The source checkout is on ${branch}, not the default branch ${defaultBranch}`, `Every worktree warmed from here carries ${branch}'s dependencies. \`stim worktree warm --refresh\` warns and continues; it never switches a branch under another checkout.`, `Run \`git -C ${quotedRoot} checkout ${defaultBranch}\`.`));
584
493
  return findings;
585
494
  }
586
- function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, upstream = void 0, linkedWorktrees = void 0, platform, localIos = platform !== "android", iosProjectPath = "ios", androidLayout = defaultAndroidLayout(projectRoot) } = {}) {
587
- const mainRoot = mainCheckoutProjectRoot(projectRoot);
495
+ async function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, upstream = void 0, linkedWorktrees = void 0, platform, localIos = platform !== "android", iosProjectPath = "ios", androidLayout = defaultAndroidLayout(projectRoot) } = {}) {
496
+ const mainRoot = await mainCheckoutProjectRoot(projectRoot);
588
497
  const mainAndroid = {
589
498
  ...androidLayout,
590
499
  gradleRoot: join$1(mainRoot, relative$1(projectRoot, androidLayout.gradleRoot)),
591
500
  moduleDir: join$1(mainRoot, relative$1(projectRoot, androidLayout.moduleDir))
592
501
  };
593
502
  const findings = [];
594
- const dependencies = dependencyState(mainRoot);
503
+ const dependencies = dependencyState(mainRoot, await repoRootAsync(mainRoot) ?? mainRoot);
595
504
  if (dependencies) {
596
505
  const installed = hasInstalledDependencies(dependencies.root, dependencies.installed);
597
506
  const installCommand = `cd ${quotedPath(dependencies.root)} && ${dependencies.command}`;
598
507
  if (!installed) findings.push(finding("cost", "The source checkout has no installed dependencies", `A worktree cannot carry dependencies from ${dependencies.root}, so its first build must install them from scratch.`, `Run \`${installCommand}\` before creating native worktrees, or let \`stim worktree warm --refresh\` run it from a linked worktree.`));
599
508
  else if (dependencies.lock === "package-lock.json") {
600
- if ((npmTreeValid === void 0 ? installedNpmTreeIsValid(dependencies.root) : npmTreeValid) === false) findings.push(finding("cost", "The source checkout dependency tree is stale", `npm reports that ${dependencies.root}/node_modules does not match the project dependency graph. Copying it makes each worktree start from the same invalid state.`, `Run \`${installCommand}\` before creating native worktrees, or let \`stim worktree warm --refresh\` run it from a linked worktree.`));
509
+ if ((npmTreeValid === void 0 ? await installedNpmTreeIsValidAsync(dependencies.root) : npmTreeValid) === false) findings.push(finding("cost", "The source checkout dependency tree is stale", `npm reports that ${dependencies.root}/node_modules does not match the project dependency graph. Copying it makes each worktree start from the same invalid state.`, `Run \`${installCommand}\` before creating native worktrees, or let \`stim worktree warm --refresh\` run it from a linked worktree.`));
601
510
  }
602
511
  }
603
512
  const iosRoot = join$1(mainRoot, iosProjectPath);
@@ -616,7 +525,7 @@ function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, ups
616
525
  const podCommand = `cd ${quotedPath(iosRoot)} && ${podInstallCommand(mainRoot)}`;
617
526
  findings.push(finding("cost", `The source checkout CocoaPods state is ${podsState}`, `ios/Pods cannot be reused safely because its Manifest.lock ${podsState === "missing" ? "is absent" : "does not match ios/Podfile.lock"}.`, `Run \`${podCommand}\` before creating native worktrees, or let \`stim worktree warm --refresh\` run it from a linked worktree.`));
618
527
  }
619
- const broken = brokenPods === void 0 && existsSync$1(podsRoot) ? brokenPodLinks(podsRoot) : brokenPods || [];
528
+ const broken = brokenPods === void 0 && existsSync$1(podsRoot) ? await brokenPodLinks(podsRoot) : brokenPods || [];
620
529
  if (broken.length) {
621
530
  const podCommand = `cd ${quotedPath(iosRoot)} && ${podInstallCommand(mainRoot, "--clean-install")}`;
622
531
  findings.push(finding("cost", "The source checkout CocoaPods state has broken links", `${broken.length} symlink${broken.length === 1 ? "" : "s"} under ios/Pods point to missing files. Worktrees copy these broken links and can fail during compilation. First: ${broken[0]}.`, `Run \`${podCommand}\` before creating native worktrees.`));
@@ -624,7 +533,7 @@ function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, ups
624
533
  }
625
534
  const coldPlatforms = [localIos && existsSync$1(iosRoot) && !hasIosWarmOutput(mainRoot, iosRoot) ? "iOS" : null, platform !== "ios" && hasAndroidProject(mainAndroid) && !existsSync$1(join$1(mainAndroid.gradleRoot, "build")) && !existsSync$1(join$1(mainAndroid.moduleDir, "build")) ? "Android" : null].filter((coldPlatform) => coldPlatform !== null);
626
535
  if (coldPlatforms.length) findings.push(finding("note", `The source checkout has no ${coldPlatforms.join(" or ")} warm build output`, "The shared Stim artifact or compilation cache can still be warm. Building the source checkout once gives later native worktrees the strongest warm starting point.", `When more native worktrees are expected, run \`stim start\`, \`stim ${coldPlatforms[0] === "iOS" ? "ios" : "android"}\`, and \`stim stop\` from ${mainRoot}.`));
627
- if (linkedWorktrees === void 0 ? hasLinkedWorktree(projectRoot) : linkedWorktrees) findings.push(...seedFindings(mainRoot, upstream === void 0 ? locallyKnownUpstream(mainRoot) : upstream));
536
+ if (linkedWorktrees === void 0 ? await hasLinkedWorktree(projectRoot) : linkedWorktrees) findings.push(...await seedFindings(mainRoot, upstream === void 0 ? await locallyKnownUpstreamAsync(mainRoot) : upstream));
628
537
  return findings;
629
538
  }
630
539
  function checkMetroCache(metroConfigSource) {
@@ -723,9 +632,12 @@ function checkConcurrency({ maxBuilds = 0, maxDevices = 0, liveDevices = 0, acti
723
632
  if (!maxBuilds && !maxDevices) return null;
724
633
  return finding("note", "Concurrency limits are set", `${`maxBuilds ${maxBuilds || "unlimited"}, maxDevices ${maxDevices || "unlimited"}`}. Right now ${typeof liveDevices === "number" ? `${liveDevices} Stim device(s) are booted` : `the number of booted Stim devices is unknown (${liveDevices.unknown})`} and ${activeBuilds} build slot(s) are in use on this machine. At the device cap a new \`stim ios\`/\`android\` waits in FIFO order for 600s (--wait changes it; --no-wait refuses with STIM_AT_CAPACITY); at the build cap a compile waits for a free slot.`, null);
725
634
  }
726
- function easCliOutsideRepository(projectRoot) {
635
+ async function easCliOutsideRepository(projectRoot, operation) {
727
636
  const found = (String(getExecutor().findExecutable("eas") ?? "").split("\n")[0] ?? "").trim();
728
- const root = found ? repoRoot(projectRoot) : null;
637
+ const root = found ? operation ? await repoRootAsync(projectRoot, {
638
+ env: operation.env,
639
+ signal: operation.signal
640
+ }) : repoRoot(projectRoot) : null;
729
641
  if (!found || !root) return null;
730
642
  try {
731
643
  const repository = realpathSync$1(root);
@@ -743,18 +655,19 @@ function easCliOutsideRepository(projectRoot) {
743
655
  return null;
744
656
  }
745
657
  }
746
- function readProjectEasCliVersion(projectRoot) {
658
+ async function readProjectEasCliVersion(projectRoot, operation) {
747
659
  const packageJson = resolvePackageJson(projectRoot, "eas-cli");
748
660
  if (packageJson) {
749
661
  const version = readJsonObject(packageJson)?.version;
750
662
  return typeof version === "string" ? `eas-cli/${version}` : null;
751
663
  }
752
- const onPath = easCliOutsideRepository(projectRoot);
753
- return onPath ? readInstalledEasCliVersion(onPath, projectRoot) : null;
664
+ const onPath = await easCliOutsideRepository(projectRoot, operation);
665
+ return onPath ? readInstalledEasCliVersionAsync(onPath, projectRoot) : null;
754
666
  }
755
- function doctorEasAuth({ projectRoot, owner }) {
756
- const file = easCliOutsideRepository(projectRoot);
667
+ async function doctorEasAuth({ projectRoot, owner, operation }) {
668
+ const file = await easCliOutsideRepository(projectRoot, operation);
757
669
  if (file) return checkEasAuth$1({
670
+ context: operation,
758
671
  projectRoot,
759
672
  owner,
760
673
  resolveBin: () => ({
@@ -764,6 +677,7 @@ function doctorEasAuth({ projectRoot, owner }) {
764
677
  });
765
678
  const unchecked = resolveEasCliBin(projectRoot);
766
679
  if (!unchecked) return checkEasAuth$1({
680
+ context: operation,
767
681
  projectRoot,
768
682
  owner,
769
683
  resolveBin: () => null
@@ -793,13 +707,16 @@ function checkEasBuildDownload({ easJson = false, remoteEas = false, easCliResol
793
707
  if (easCli.supported) return null;
794
708
  return finding("cost", easCli.version ? `eas-cli ${easCli.version} cannot download EAS builds for --eas-profile` : "The eas-cli version could not be read for --eas-profile", `\`stim ios --eas-profile\` and \`stim android --eas-profile\` download a finished EAS development build with \`eas build:download --build-id\`, which needs eas-cli ${MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION} or later. Older versions refuse with STIM_EAS_UNAVAILABLE before any download.`, `${easCliUpgradeRemedy(MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION)}.`);
795
709
  }
796
- function projectEasBuildDownloadFinding(projectRoot, remoteBackends, lookupEasCli) {
710
+ async function projectEasBuildDownloadFinding(projectRoot, remoteBackends, lookupEasCli, operation) {
797
711
  const easJson = existsSync$1(join$1(projectRoot, "eas.json"));
712
+ const remoteEas = remoteBackends.includes("eas");
713
+ const easCliResolvable = easJson && (lookupEasCli ? lookupEasCli() : Boolean(resolveEasCliBin(projectRoot)));
714
+ const version = easJson && !remoteEas && easCliResolvable ? await readProjectEasCliVersion(projectRoot, operation) : null;
798
715
  return checkEasBuildDownload({
799
716
  easJson,
800
- remoteEas: remoteBackends.includes("eas"),
801
- easCliResolvable: easJson && (lookupEasCli ? lookupEasCli() : Boolean(resolveEasCliBin(projectRoot))),
802
- readEasCliVersion: () => readProjectEasCliVersion(projectRoot)
717
+ remoteEas,
718
+ easCliResolvable,
719
+ readEasCliVersion: () => version
803
720
  });
804
721
  }
805
722
  function checkSimSlim({ configured = false, profileError = null, onPath = false } = {}) {
@@ -830,8 +747,8 @@ function configuredRemoteBackends(projectSettings, platform) {
830
747
  const androidTarget = remoteAndroidSetting(projectSettings);
831
748
  return [.../* @__PURE__ */ new Set([...platform !== "android" ? [iosTarget?.kind === "backend" ? iosTarget.backend : null] : [], ...platform !== "ios" ? [androidTarget?.kind === "backend" ? androidTarget.backend : null] : []])].filter((backend) => backend !== null);
832
749
  }
833
- function runDoctor(projectRoot, options = {}, inspectors = []) {
834
- const { concurrency = getConcurrencyLimits, liveDevices = null, activeBuilds = null, lookupSimSlim = null, memoryPressure = readHostMemoryPressure, lookupChrome, platform, host = process.platform, platforms = ["ios", "android"], machineSettings = readMachineSettings(projectSettingsContext(projectRoot)) } = options;
750
+ async function runDoctor(projectRoot, options = {}, inspectors = []) {
751
+ const { concurrency = getConcurrencyLimits, liveDevices = null, activeBuilds = null, lookupSimSlim = null, lookupSigningIdentities = () => probeSigningIdentities({ env: options.operation?.env ?? process.env }), memoryPressure = readHostMemoryPressureAsync, lookupChrome, platform, host = process.platform, platforms = ["ios", "android"], machineSettings = readMachineSettings(projectSettingsContext(projectRoot)) } = options;
835
752
  const localIos = platforms.includes("ios") && platform !== "android" && host === "darwin";
836
753
  const projectSettings = machineSettings.settings;
837
754
  const context = {
@@ -851,14 +768,15 @@ function runDoctor(projectRoot, options = {}, inspectors = []) {
851
768
  if (limits && (limits.maxBuilds || limits.maxDevices)) concurrencyFinding = checkConcurrency({
852
769
  maxBuilds: limits.maxBuilds,
853
770
  maxDevices: limits.maxDevices,
854
- liveDevices: liveDevices ? liveDevices() : countLiveOwnedDevices(),
771
+ liveDevices: liveDevices ? liveDevices() : options.operation ? await countLiveOwnedDevicesAsync(options.operation) : countLiveOwnedDevices(),
855
772
  activeBuilds: activeBuilds ? activeBuilds() : countActiveBuilds()
856
773
  });
857
774
  const settingShapeFindings = settingShapeErrors(projectSettings).map((error) => finding("cost", "A setting has the wrong type", error, SETTING_SHAPE_REMEDY));
858
775
  let optimizations = null;
859
776
  try {
860
777
  optimizations = resolveAndroidCompilerCache({
861
- optimizations: resolveOptimizations(projectSettings),
778
+ optimizations: resolveOptimizations(projectSettings, options.operation?.env ?? options.remoteEnv ?? process.env),
779
+ env: options.operation?.env ?? options.remoteEnv ?? process.env,
862
780
  use: readAndroidCasToolchain
863
781
  }).optimizations;
864
782
  } catch {}
@@ -880,36 +798,40 @@ function runDoctor(projectRoot, options = {}, inspectors = []) {
880
798
  profileError: simslimProfileError,
881
799
  onPath: simslimProfile ? lookupSimSlim ? lookupSimSlim() : simslimIsOnPath() : false
882
800
  });
883
- const memoryAdvice = localIos && !remoteIosSetting(projectSettings) ? hostMemoryPressureAdvice(memoryPressure()) : null;
801
+ const memoryAdvice = localIos && !remoteIosSetting(projectSettings) ? hostMemoryPressureAdvice(await memoryPressure()) : null;
802
+ const shared = [
803
+ ...checkStorageLayout(projectRoot, {
804
+ platform,
805
+ host,
806
+ scope: "shared"
807
+ }),
808
+ checkChrome({
809
+ usesWeb: () => !platform && webSettings(projectSettings).url !== null,
810
+ chrome: lookupChrome
811
+ }),
812
+ concurrencyFinding,
813
+ memoryAdvice ? finding("cost", "Host memory pressure can stall the iOS simulator", memoryAdvice, "Free host memory, then retry. Run `stim guide lifecycle simslim` for the optional memory reduction setup.") : null,
814
+ simslimFinding,
815
+ localIos && deviceWorkflowPlausible(readWorkspaceState$1(projectRoot), projectSettings) ? checkDeviceSigning(await lookupSigningIdentities()) : null,
816
+ ...settingShapeFindings,
817
+ ...checkMachineSettings({
818
+ settings: projectSettings,
819
+ layers: machineSettings.layers,
820
+ projectRoot,
821
+ optimizations,
822
+ env: options.operation?.env ?? options.remoteEnv ?? process.env,
823
+ reportedElsewhere: simslimProfileError ? ["ios.simslimProfile"] : []
824
+ })
825
+ ].filter((f) => Boolean(f));
826
+ const inspected = await Promise.all(inspectors.map((inspect) => inspect(context)));
884
827
  return {
885
- findings: [...[
886
- ...checkStorageLayout(projectRoot, {
887
- platform,
888
- host,
889
- scope: "shared"
890
- }),
891
- checkChrome({
892
- usesWeb: () => !platform && webSettings(projectSettings).url !== null,
893
- chrome: lookupChrome
894
- }),
895
- concurrencyFinding,
896
- memoryAdvice ? finding("cost", "Host memory pressure can stall the iOS simulator", memoryAdvice, "Free host memory, then retry. Run `stim guide lifecycle simslim` for the optional memory reduction setup.") : null,
897
- simslimFinding,
898
- ...settingShapeFindings,
899
- ...checkMachineSettings({
900
- settings: projectSettings,
901
- layers: machineSettings.layers,
902
- projectRoot,
903
- optimizations,
904
- reportedElsewhere: simslimProfileError ? ["ios.simslimProfile"] : []
905
- })
906
- ].filter((f) => Boolean(f)), ...inspectors.flatMap((inspect) => inspect(context))],
828
+ findings: [...shared, ...inspected.flat()],
907
829
  context
908
830
  };
909
831
  }
910
- function reactNativeDoctorFindings({ root: projectRoot, settings: projectSettings, optimizations, options, repoRoot: repositoryRoot }) {
832
+ async function reactNativeDoctorFindings({ root: projectRoot, settings: projectSettings, optimizations, options, repoRoot: repositoryRoot }) {
911
833
  const androidLayout = resolveAndroidLayout(projectSettings, projectRoot, repositoryRoot ?? projectRoot);
912
- const { readFile = readFileSync$1, xcodeMajor = null, easAuth = doctorEasAuth, remoteEnv = process.env, lookupAgentDevice = null, lookupEasCli = null, lookupCcache = null, tailnetStatus = realIo.status, now = Date.now, platform, host = process.platform } = options;
834
+ const { readFile = readFileSync$1, xcodeMajor = null, easAuth = doctorEasAuth, remoteEnv = options.operation?.env ?? process.env, lookupAgentDevice = null, lookupEasCli = null, lookupCcache = null, tailnetStatus = realIo.status, now = Date.now, platform, host = process.platform } = options;
913
835
  const localIos = platform !== "android" && host === "darwin";
914
836
  const read = (rel) => {
915
837
  const p = join$1(projectRoot, rel);
@@ -940,34 +862,29 @@ function reactNativeDoctorFindings({ root: projectRoot, settings: projectSetting
940
862
  const easFinding = remoteBuildCache && provider === "eas" ? checkEasAuth({
941
863
  provider,
942
864
  owner,
943
- auth: easAuth({
865
+ auth: await easAuth({
944
866
  projectRoot,
945
- owner
867
+ owner,
868
+ operation: options.operation
946
869
  })
947
870
  }) : null;
948
871
  const remoteBackends = configuredRemoteBackends(projectSettings, platform);
949
872
  const daemonInEnv = Boolean(remoteEnv.AGENT_DEVICE_DAEMON_BASE_URL?.trim() && remoteEnv.AGENT_DEVICE_DAEMON_AUTH_TOKEN?.trim());
950
873
  const agentDeviceOnPath = remoteBackends.length ? lookupAgentDevice ? lookupAgentDevice() : agentDeviceIsOnPath() : false;
951
874
  const easCliResolvable = remoteBackends.includes("eas") ? lookupEasCli ? lookupEasCli() : Boolean(resolveEasCliBin(projectRoot)) : false;
875
+ const remoteVersion = agentDeviceOnPath && easCliResolvable && remoteBackends.includes("eas") ? await readProjectEasCliVersion(projectRoot, options.operation) : null;
952
876
  const remoteFindings = remoteBackends.map((backend) => checkRemoteDevice({
953
877
  configured: backend,
954
878
  daemonInEnv,
955
879
  agentDeviceOnPath,
956
880
  easCliResolvable,
957
- readEasCliVersion: () => readProjectEasCliVersion(projectRoot)
881
+ readEasCliVersion: () => remoteVersion
958
882
  })).filter((remoteFinding) => remoteFinding !== null);
959
- const easBuildDownloadFinding = projectEasBuildDownloadFinding(projectRoot, remoteBackends, lookupEasCli);
883
+ const easBuildDownloadFinding = await projectEasBuildDownloadFinding(projectRoot, remoteBackends, lookupEasCli, options.operation);
960
884
  return [
961
885
  checkAppProject(projectRoot),
962
886
  checkIosHost(platform, host),
963
887
  checkXcodeEnvLineEndings(projectRoot, platform, host),
964
- ...checkMainCheckout(projectRoot, {
965
- platform,
966
- localIos,
967
- iosProjectPath: iosProject.relative,
968
- androidLayout
969
- }),
970
- ...localIos ? inspectIosDebugArchitectures(mainCheckoutProjectRoot(projectRoot), iosProject.relative) : [],
971
888
  ...checkStorageLayout(projectRoot, {
972
889
  platform,
973
890
  host,
@@ -988,7 +905,7 @@ function reactNativeDoctorFindings({ root: projectRoot, settings: projectSetting
988
905
  remoteBuildCache ? checkBuildCacheProvider(appConfig, sdkMajor, isExpo, dynamicConfig) : null,
989
906
  easFinding,
990
907
  easBuildDownloadFinding,
991
- readOffloadCandidate(tailnetStatus, now(), host),
908
+ await readOffloadCandidate(tailnetStatus, now(), host),
992
909
  ...remoteFindings
993
910
  ].filter((value) => Boolean(value));
994
911
  }
@@ -1110,8 +1027,8 @@ function listDirectory(dir) {
1110
1027
  return [];
1111
1028
  }
1112
1029
  }
1113
- function hasLinkedPackageWithGit(projectRoot) {
1114
- const root = repoRoot(projectRoot) ?? projectRoot;
1030
+ async function hasLinkedPackageWithGit(projectRoot) {
1031
+ const root = await repoRootAsync(projectRoot) ?? projectRoot;
1115
1032
  for (let dir = projectRoot;; dir = dirname$1(dir)) {
1116
1033
  if (linkedPackageWithGitIn(join$1(dir, "node_modules"))) return true;
1117
1034
  if (dir === root || dirname$1(dir) === dir || relative$1(root, dirname$1(dir)).startsWith("..")) return false;
@@ -1137,14 +1054,18 @@ function linkedPackageWithGitIn(nodeModules) {
1137
1054
  * packages can be hoisted, so the gate looks at every node_modules from the
1138
1055
  * app up to the repository root.
1139
1056
  */
1140
- async function detectLinkedLibraryGitMetadata(projectRoot, { createFingerprint = expoFingerprint.createFingerprintAsync, platform } = {}) {
1141
- const mainRoot = mainCheckoutProjectRoot(projectRoot);
1142
- if (!hasLinkedPackageWithGit(mainRoot)) return null;
1057
+ async function detectLinkedLibraryGitMetadata(projectRoot, { createFingerprint = expoFingerprint.createFingerprintAsync, platform, operation } = {}) {
1058
+ const mainRoot = await mainCheckoutProjectRoot(projectRoot);
1059
+ if (!await hasLinkedPackageWithGit(mainRoot)) return null;
1143
1060
  const skipped = fingerprintConfigSkipped(mainRoot);
1144
1061
  if (skipped) return skipped;
1145
1062
  let sources;
1146
1063
  try {
1147
- sources = (await fingerprintProject(mainRoot, {
1064
+ sources = (operation && createFingerprint === expoFingerprint.createFingerprintAsync ? await readDoctorFingerprint(operation, {
1065
+ root: mainRoot,
1066
+ platform,
1067
+ debug: true
1068
+ }) : await fingerprintProject(mainRoot, {
1148
1069
  platform,
1149
1070
  createFingerprint,
1150
1071
  debug: true
@@ -1164,8 +1085,14 @@ async function detectLinkedLibraryGitMetadata(projectRoot, { createFingerprint =
1164
1085
  code: "linked-library-git-metadata"
1165
1086
  };
1166
1087
  }
1167
- async function detectFingerprintParity(projectRoot, { createFingerprint = expoFingerprint.createFingerprintAsync, differ = expoFingerprint.diffFingerprints, dirtyFiles = dirtyFingerprintFiles, platform: selectedPlatform, iosProjectPath = "ios" } = {}) {
1168
- if (gitQuiet(projectRoot, ["rev-parse", "--git-dir"]) == null) return null;
1088
+ async function appPathInRepository(projectRoot) {
1089
+ const top = await repoRootAsync(projectRoot);
1090
+ if (!top) return "";
1091
+ const path = relative$1(realpathSync$1.native(top), realpathSync$1.native(projectRoot));
1092
+ return path.startsWith("..") ? "" : path;
1093
+ }
1094
+ async function detectFingerprintParity(projectRoot, { createFingerprint = expoFingerprint.createFingerprintAsync, differ = expoFingerprint.diffFingerprints, dirtyFiles = dirtyFingerprintFiles, platform: selectedPlatform, iosProjectPath = "ios", operation } = {}) {
1095
+ if (await gitQuietAsync(projectRoot, ["rev-parse", "--git-dir"]) == null) return null;
1169
1096
  if (hasInstalledDependencies(projectRoot)) return null;
1170
1097
  const skipped = fingerprintConfigSkipped(projectRoot);
1171
1098
  if (skipped) return skipped;
@@ -1183,37 +1110,44 @@ async function detectFingerprintParity(projectRoot, { createFingerprint = expoFi
1183
1110
  return null;
1184
1111
  }
1185
1112
  const worktree = join$1(base, "head");
1186
- if (gitQuiet(projectRoot, [
1187
- "-c",
1188
- `core.hooksPath=${join$1(base, "hooks")}`,
1189
- "worktree",
1190
- "add",
1191
- "--detach",
1192
- worktree,
1193
- "HEAD"
1194
- ], {
1195
- write: true,
1196
- timeoutMs: 6e4
1197
- }) == null) {
1198
- rmSync$1(base, {
1199
- recursive: true,
1200
- force: true
1201
- });
1202
- return null;
1203
- }
1113
+ let released;
1114
+ let rejected;
1115
+ const cleanup = new Promise((done, reject) => {
1116
+ released = done;
1117
+ rejected = reject;
1118
+ });
1119
+ const release = () => released();
1120
+ let added = false;
1121
+ trackReportResource(operation, cleanup, () => cleanup);
1204
1122
  try {
1205
- const headSkipped = fingerprintConfigSkipped(worktree) ?? coldFingerprintRunsProjectCode(worktree, platform);
1123
+ added = await gitQuietAsync(projectRoot, [
1124
+ "-c",
1125
+ `core.hooksPath=${join$1(base, "hooks")}`,
1126
+ "worktree",
1127
+ "add",
1128
+ "--detach",
1129
+ worktree,
1130
+ "HEAD"
1131
+ ], {
1132
+ write: true,
1133
+ timeoutMs: 6e4
1134
+ }) !== null;
1135
+ if (!added) return null;
1136
+ const headApp = join$1(worktree, await appPathInRepository(projectRoot));
1137
+ const headSkipped = fingerprintConfigSkipped(headApp) ?? coldFingerprintRunsProjectCode(headApp, platform);
1206
1138
  if (headSkipped) return headSkipped;
1207
- const project = await fingerprintProject(projectRoot, {
1139
+ const inspect = (root) => operation && createFingerprint === expoFingerprint.createFingerprintAsync ? readDoctorFingerprint(operation, {
1140
+ root,
1208
1141
  platform,
1209
1142
  iosProjectPath,
1210
- createFingerprint: coldFingerprint
1211
- });
1212
- const clean = await fingerprintProject(worktree, {
1143
+ cold: true
1144
+ }) : fingerprintProject(root, {
1213
1145
  platform,
1214
1146
  iosProjectPath,
1215
1147
  createFingerprint: coldFingerprint
1216
1148
  });
1149
+ const project = await inspect(projectRoot);
1150
+ const clean = await inspect(headApp);
1217
1151
  if (!project || !clean) return null;
1218
1152
  if (project.hash === clean.hash) return null;
1219
1153
  const changed = diffFingerprintSources({
@@ -1226,26 +1160,56 @@ async function detectFingerprintParity(projectRoot, { createFingerprint = expoFi
1226
1160
  projectHash: project.hash,
1227
1161
  worktreeHash: clean.hash,
1228
1162
  changed,
1229
- dirtyFiles: dirtyFiles(projectRoot)
1163
+ dirtyFiles: await dirtyFiles(projectRoot)
1230
1164
  });
1231
1165
  } catch {
1232
1166
  return null;
1233
1167
  } finally {
1234
- gitQuiet(projectRoot, [
1235
- "worktree",
1236
- "remove",
1237
- "--force",
1238
- worktree
1239
- ], {
1240
- write: true,
1241
- timeoutMs: 3e4
1242
- });
1243
- rmSync$1(base, {
1244
- recursive: true,
1245
- force: true
1246
- });
1247
- gitQuiet(projectRoot, ["worktree", "prune"], { write: true });
1168
+ await finishCleanup();
1169
+ }
1170
+ async function finishCleanup() {
1171
+ try {
1172
+ const options = {
1173
+ timeoutMs: 3e4,
1174
+ ...operation ? { signal: AbortSignal.timeout(3e4) } : {}
1175
+ };
1176
+ const target = join$1(realpathSync$1.native(base), "head");
1177
+ if (added || operation) await gitQuietAsync(projectRoot, [
1178
+ "worktree",
1179
+ "remove",
1180
+ "--force",
1181
+ "--force",
1182
+ worktree
1183
+ ], {
1184
+ write: true,
1185
+ ...options
1186
+ });
1187
+ if (operation) {
1188
+ const registered = await gitQuietAsync(projectRoot, [
1189
+ "worktree",
1190
+ "list",
1191
+ "--porcelain",
1192
+ "-z"
1193
+ ], options);
1194
+ if (registered === null || registered.split("\0").some((line) => line.startsWith("worktree ") && relative$1(target, line.slice(9)) === "")) throw new Error("The temporary worktree is still registered or its registration cannot be read.");
1195
+ }
1196
+ await rm(base, {
1197
+ recursive: true,
1198
+ force: true
1199
+ });
1200
+ if (added && !operation) await gitQuietAsync(projectRoot, ["worktree", "prune"], { write: true });
1201
+ } catch (error) {
1202
+ if (!operation) throw error;
1203
+ const refusal = Object.assign(new Error(`Cannot finish cleanup for temporary worktree ${worktree}.`, { cause: error }), {
1204
+ code: "STIM_CLAIM_UNAVAILABLE",
1205
+ reportCleanup: true
1206
+ });
1207
+ if (reportSignal(operation)) rejected(refusal);
1208
+ throw refusal;
1209
+ } finally {
1210
+ release();
1211
+ }
1248
1212
  }
1249
1213
  }
1250
1214
  //#endregion
1251
- export { repairCxxLauncherState as a, runDoctor as i, detectLinkedLibraryGitMetadata as n, readMachineSettings as o, reactNativeDoctorFindings as r, detectFingerprintParity as t };
1215
+ export { reactNativeDoctorFindings as a, checkWorktreeStorageLayout as c, mainCheckoutProjectRoot as i, readMachineSettings as l, detectFingerprintParity as n, runDoctor as o, detectLinkedLibraryGitMetadata as r, repairCxxLauncherState as s, checkMainCheckout as t };