stim 1.20.2 → 1.22.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 (231) hide show
  1. package/README.md +141 -8
  2. package/dist/acquire-artifact-Co2k4f7O.mjs +171 -0
  3. package/dist/act-DsuqEkiM.mjs +2801 -0
  4. package/dist/activity-CMLmzp7o.mjs +1397 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-DUFaTMdd.mjs} +23 -67
  6. package/dist/{android-DCKZrNvV.mjs → android-ByRMUoiJ.mjs} +157 -93
  7. package/dist/{android-Mz_Inn3w.mjs → android-C7sVmyI9.mjs} +299 -116
  8. package/dist/{android-Dlzxshgp.mjs → android-DGkNqa_c.mjs} +5 -5
  9. package/dist/{android-HqP1_vB_.mjs → android-DR5lZ2Az.mjs} +2 -2
  10. package/dist/android-cas-compiler.mjs +2 -2
  11. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-ngferVq2.mjs} +7 -6
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/android-project-DVWyCbWU.d.mts +391 -0
  14. package/dist/api.d.mts +810 -64
  15. package/dist/api.mjs +782 -1
  16. package/dist/{artifact-HSwkIWEQ.mjs → artifact-8EY8SAPw.mjs} +240 -213
  17. package/dist/{artifact-D3czlUvT.mjs → artifact-DJPy518Y.mjs} +203 -164
  18. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  19. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-Bcv99PBM.mjs} +194 -64
  20. package/dist/budget-Cvwn54qV.mjs +9285 -0
  21. package/dist/{build-DYDbfkk5.mjs → build-CabC3G23.mjs} +153 -98
  22. package/dist/build-cache-Dv7RN200.mjs +602 -0
  23. package/dist/build-plan-DUC8Ka9y.mjs +248 -0
  24. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DSeQjt-Q.mjs} +2 -2
  25. package/dist/cache-manifest.mjs +1 -1
  26. package/dist/{ccache-zdKiYQ3E.mjs → ccache-Btwc36-I.mjs} +10 -9
  27. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-3fwICjzi.mjs} +18 -5
  28. package/dist/{chrome-BnzZMqsR.mjs → chrome-Bbw689-6.mjs} +7 -4
  29. package/dist/{cli-CLP3diBm.mjs → cli-CHZa9Lvk.mjs} +20 -20
  30. package/dist/cli.mjs +1 -1
  31. package/dist/client-OyRoEuSr.mjs +1577 -0
  32. package/dist/collector-run.d.mts +4 -40
  33. package/dist/collector-run.mjs +9 -8
  34. package/dist/{command-output-BTy8hZ0F.mjs → command-output-gwpm28fu.mjs} +1 -1
  35. package/dist/config-DlrsduwG.mjs +955 -0
  36. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-x9rN6bhs.mjs} +14 -4
  37. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-1I9KZT1Y.mjs} +20 -5
  38. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
  39. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-BSDR5h3F.mjs} +2 -2
  40. package/dist/{device-BECOiufl.mjs → device-B-L3Fbxy.mjs} +91 -34
  41. package/dist/device-DklWZLqb.mjs +1068 -0
  42. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-DK5_EwRS.mjs} +42 -13
  43. package/dist/device-host-worker.mjs +76 -79
  44. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DoB6KFCO.mjs} +77 -51
  45. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-xJPQ_QQG.mjs} +14 -26
  46. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-BMkdsefq.mjs} +5 -5
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-Bo7BXLux.mjs} +271 -320
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-D5_EzwfA.mjs} +186 -91
  49. package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
  50. package/dist/doctor-fingerprint.mjs +19 -0
  51. package/dist/doctor-thjWAV0z.mjs +2 -0
  52. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-N2wDotwQ.mjs} +40 -21
  53. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-CwknaQYj.mjs} +53 -20
  54. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-CSgAulr5.mjs} +41 -214
  55. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-DlY_serQ.mjs} +230 -11
  56. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-DBWO2rxE.mjs} +172 -82
  57. package/dist/exec-DEoAhcze.mjs +858 -0
  58. package/dist/exec-DnYc4HGH.d.mts +78 -0
  59. package/dist/{gc-qWOMdnER.mjs → gc-CXxN-4SE.mjs} +1091 -1029
  60. package/dist/gc-DnNDQyaP.mjs +3 -0
  61. package/dist/{guide-G9cAbVAc.mjs → guide-Br0LEfKy.mjs} +1165 -297
  62. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-B-9f-jkd.mjs} +10 -8
  63. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DZAPrcro.mjs} +34 -19
  64. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
  65. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-FIRx9X2f.mjs} +77 -43
  66. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-_awYSpfv.mjs} +35 -22
  67. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-BdzE668-.mjs} +49 -27
  68. package/dist/idle-C4cZ757K.d.mts +24 -0
  69. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DDg3SdvY.mjs} +11 -10
  70. package/dist/ios-CDvlmUs7.d.mts +24 -0
  71. package/dist/{ios-BwVCF7oA.mjs → ios-Ds1clbIt.mjs} +8 -8
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device--h_-8ENa.mjs} +51 -26
  73. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  74. package/dist/{ios-RkW4pnQf.mjs → ios-hcBpnEGk.mjs} +200 -93
  75. package/dist/{ios-Ce7bc7br.mjs → ios-pm4nL6By.mjs} +160 -108
  76. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-CZhKODF3.mjs} +13 -13
  77. package/dist/ios-signing-BtAffm0A.mjs +489 -0
  78. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  79. package/dist/{ios-nOLJGVdy.mjs → ios-xtlRHaeB.mjs} +1 -1
  80. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Bwhh4S7V.mjs} +30 -25
  81. package/dist/{launch-C3qJ6Agb.mjs → launch-BjxemNpK.mjs} +85 -543
  82. package/dist/{launch-F4sOqAhB.mjs → launch-CCzXlc8r.mjs} +91 -90
  83. package/dist/logs-BfwwadsZ.mjs +479 -0
  84. package/dist/logs-jTS_lHSo.mjs +248 -0
  85. package/dist/{macos-D7uDvO-z.mjs → macos-DVlSSyUg.mjs} +1 -1
  86. package/dist/macos-NfV2D7dO.mjs +694 -0
  87. package/dist/macos-run.mjs +1 -1
  88. package/dist/maintenance-run.mjs +123 -248
  89. package/dist/{metro-DnCEjCxs.mjs → metro-DiXtA3Ty.mjs} +107 -30
  90. package/dist/metro-gateway-CKZqKqx7.mjs +209 -0
  91. package/dist/{named-ports-4WopRPg-.mjs → named-ports-DkEzOfzO.mjs} +42 -90
  92. package/dist/native-android-CqgnOgsT.mjs +645 -0
  93. package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
  94. package/dist/native-gradle-inputs-Dnh84Zbd.mjs +211 -0
  95. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  96. package/dist/native-run-NwUuxbkg.mjs +276 -0
  97. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-B7KIafpM.mjs} +11 -9
  98. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  99. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-D_VOfFL7.mjs} +26 -18
  100. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-BYDOHWLN.mjs} +104 -60
  101. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  102. package/dist/offload-worker.d.mts +59 -41
  103. package/dist/offload-worker.mjs +478 -115
  104. package/dist/operation-exec-BW0em61G.mjs +171 -0
  105. package/dist/{ownership-DCtw_2IA.mjs → ownership-C5fo5Edb.mjs} +3 -3
  106. package/dist/{page-DRHy329N.mjs → page-DBL2PiUU.mjs} +12 -5
  107. package/dist/paths-BsJMoPP2.mjs +12 -0
  108. package/dist/paths-DQtTgsBf.mjs +42 -0
  109. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BnGgJRRZ.mjs} +5 -5
  110. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-DIsMtN-d.mjs} +15 -11
  111. package/dist/{ports-DdSUicVo.mjs → ports-Cy1RkmuQ.mjs} +3 -3
  112. package/dist/prebuild-D4JoEAEs.mjs +484 -0
  113. package/dist/{project-_phNIJfs.mjs → project-wM_XFTvE.mjs} +65 -37
  114. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-W1IuLXDt.mjs} +102 -20
  115. package/dist/pull-request-eODyIqZF.d.mts +124 -0
  116. package/dist/pull-requests.d.mts +2 -120
  117. package/dist/pull-requests.mjs +2 -2
  118. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-6OZ7MSM7.mjs} +121 -72
  119. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-Dvd8hC21.mjs} +292 -15
  120. package/dist/react-native-doctor-DsoSF1Y9.mjs +234 -0
  121. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-4u1Rn-GR.mjs} +71 -39
  122. package/dist/{recordings-D0d5aQt0.mjs → recordings-CQmfzAh7.mjs} +12 -9
  123. package/dist/registration-BcRgF6Ox.mjs +51 -0
  124. package/dist/{reload-C8JhxjSh.mjs → reload-BzkYabB-.mjs} +94 -47
  125. package/dist/reload-D7AVlb8N.mjs +2 -0
  126. package/dist/{remote-BiR6aYjy.mjs → remote-DjGDmlTZ.mjs} +26 -18
  127. package/dist/result-D2Ykz_iD.mjs +435 -0
  128. package/dist/{run-BtPgpKks.mjs → run-DidHghD1.mjs} +5 -5
  129. package/dist/selection-DSMbWEX2.mjs +620 -0
  130. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CafzuyFB.mjs} +3 -4
  131. package/dist/{server-command-CTtCkmcQ.mjs → server-command-C6QjeupS.mjs} +14 -7
  132. package/dist/{server-expo-DsguMGUF.mjs → server-expo-CrjB29pq.mjs} +54 -11
  133. package/dist/server-expo-D58c9L0M.mjs +2 -0
  134. package/dist/{settings-B717odTD.mjs → settings-C7O8A6ZI.mjs} +309 -119
  135. package/dist/settings-DpR-1Wnn.mjs +114 -0
  136. package/dist/settings-write-CzD60rOD.mjs +360 -0
  137. package/dist/settings.schema.json +176 -16
  138. package/dist/{simslim-CCr3rE-A.mjs → simslim-BNckWpXi.mjs} +14 -12
  139. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-CbfmNgM6.mjs} +15 -20
  140. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  141. package/dist/stage-Bps5oius.mjs +200 -0
  142. package/dist/{start-TXeMmmO2.mjs → start-Br-oxqMD.mjs} +1 -1
  143. package/dist/start-EojN4WFz.mjs +1364 -0
  144. package/dist/{state-D1Icyjlu.mjs → state--smjFSTL.mjs} +55 -13
  145. package/dist/{state-CG_OFoaA.mjs → state-08I3hw3_.mjs} +3 -2
  146. package/dist/{stats-BoY5sEPU.mjs → stats-D3GerlFW.mjs} +7 -13
  147. package/dist/stats-report-BzaPrRm6.mjs +16 -0
  148. package/dist/{status-BTA7kKiQ.mjs → status-BRROykC8.mjs} +7 -5
  149. package/dist/status-EvrK72L2.mjs +2 -0
  150. package/dist/{status-WgFbkRzj.mjs → status-WBDajew2.mjs} +554 -452
  151. package/dist/{status-watch-C23ILtf9.mjs → status-watch-Bg_u-pwR.mjs} +222 -25
  152. package/dist/status-worker.d.mts +1 -0
  153. package/dist/status-worker.mjs +19 -0
  154. package/dist/stim-desktop-D5OGpYZM.mjs +112 -0
  155. package/dist/{stop-DR6VoDIk.mjs → stop-DTZ9uTw3.mjs} +2 -2
  156. package/dist/{stop-DPEhunlw.mjs → stop-Dky10AEJ.mjs} +33 -23
  157. package/dist/{stop-BNmBMi1F.mjs → stop-Mv6W9FAk.mjs} +137 -98
  158. package/dist/supervisor-run.d.mts +8 -17
  159. package/dist/supervisor-run.mjs +56 -28
  160. package/dist/{support-CwjbFs9H.mjs → support-CNioewsd.mjs} +14 -14
  161. package/dist/{support-DMTqj3Hm.mjs → support-yUiOjnVY.mjs} +20 -13
  162. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  163. package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
  164. package/dist/toolchain-BY8X8HXx.mjs +2 -0
  165. package/dist/toolchain-DpJMHq0n.mjs +876 -0
  166. package/dist/{trigger-CigAYjeL.mjs → trigger-Cbyc41d_.mjs} +21 -6
  167. package/dist/trigger-yb_nFzPF.mjs +2 -0
  168. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-CA3TgT3-.mjs} +263 -156
  169. package/dist/web-CZ07gd77.mjs +2 -0
  170. package/dist/{web-BDBMxDpx.mjs → web-DKx6yoFA.mjs} +20 -14
  171. package/dist/web-run.mjs +13 -12
  172. package/dist/windows-report.d.mts +1 -0
  173. package/dist/windows-report.mjs +18 -0
  174. package/dist/windows-report.ps1 +43 -0
  175. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-U08dEzhG.mjs} +62 -58
  176. package/dist/{workspaces-C36s2jb9.mjs → workspaces-CpANmBlq.mjs} +1723 -1286
  177. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-CHecZ4Oq.mjs} +1097 -547
  178. package/dist/worktree-ZqZVjD9K.mjs +2 -0
  179. package/dist/xcode-BXn9-xYx.mjs +896 -0
  180. package/package.json +7 -5
  181. package/shim/android-audio/Main.java +24 -0
  182. package/shim/android-audio/README.md +17 -0
  183. package/shim/android-audio.jar +0 -0
  184. package/shim/android-optimizations.gradle +7 -5
  185. package/dist/activity-BSV745Kz.mjs +0 -629
  186. package/dist/api-qvOzWyfO.mjs +0 -154
  187. package/dist/api-run.mjs +0 -294
  188. package/dist/app-install-BIKtMfPq.mjs +0 -896
  189. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  190. package/dist/budget-f7516Zk0.mjs +0 -4106
  191. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  192. package/dist/cancellation-C_22VQTH.mjs +0 -24
  193. package/dist/client-qQAaXSUs.mjs +0 -1771
  194. package/dist/config-BYDxlMY3.mjs +0 -562
  195. package/dist/device-DuiPJQSn.mjs +0 -290
  196. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  197. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  198. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  199. package/dist/exec-DqKo9GKJ.mjs +0 -268
  200. package/dist/git-DDfFzkMm.mjs +0 -45
  201. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  202. package/dist/logs-BGrEUaEs.mjs +0 -383
  203. package/dist/macos-Ch5VJmcS.mjs +0 -584
  204. package/dist/metro-gateway-CX9Xlkq2.mjs +0 -103
  205. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  206. package/dist/native-android-D5qc3-_v.mjs +0 -226
  207. package/dist/native-gradle-inputs-BsLRrl7u.mjs +0 -349
  208. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  209. package/dist/plan-C4TjdPsR.mjs +0 -260
  210. package/dist/prebuild-DYbucPXy.mjs +0 -212
  211. package/dist/preview-78a9kR_-.mjs +0 -1011
  212. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  213. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  214. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  215. package/dist/result-CaJg5Iat.mjs +0 -186
  216. package/dist/server-expo-Bigriskl.mjs +0 -2
  217. package/dist/settings-BORNaaCO.mjs +0 -402
  218. package/dist/settings-vk3mJGSm.d.mts +0 -13
  219. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  220. package/dist/stage-KNTQopqv.mjs +0 -157
  221. package/dist/start-BWqzODpb.mjs +0 -1116
  222. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  223. package/dist/swiftpm-macos-DRNVJWlb.mjs +0 -119
  224. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  225. package/dist/toolchain-BFkAcstd.mjs +0 -2
  226. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  227. package/dist/trigger-9_USgmxz.mjs +0 -2
  228. package/dist/web-Dq-i3wzJ.mjs +0 -2
  229. package/dist/worktree-DpLdCHga.mjs +0 -2
  230. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  231. 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 { _ as reportSignal, t as getExecutor, y as trackReportResource } from "./exec-DEoAhcze.mjs";
2
+ import { i as sharedBuildCache, u as workspaceDerivedData } from "./paths-DQtTgsBf.mjs";
3
+ import { _ as loadConfig$1, nt as realIo, s as configCorruptRepair, u as getConcurrencyLimits } from "./config-DlrsduwG.mjs";
4
+ import { d as quotedPath, u as plural } from "./command-output-gwpm28fu.mjs";
5
+ import { l as gitQuietAsync, o as git } from "./operation-exec-BW0em61G.mjs";
6
+ import { r as readWorkspaceState$1 } from "./workspace-state-U08dEzhG.mjs";
7
+ import { D as mergeSettingsLayers, Et as listWorktreesAsync, Gt as temporaryRoot, Ht as makeTemporaryDirectory, I as projectSettingsContext, It as resolveSourceCheckoutAsync, K as resolveIosProjectDir, Mt as repoRoot, Nt as repoRootAsync, Ot as locallyKnownUpstreamAsync, Q as settingOrigin, T as iosSimSlimProfileSetting, U as remoteIosSetting, V as remoteAndroidSetting, Vt as filesystemDevice, W as resolveAndroidLayout, Y as resolveSettings, a as SETTING_SHAPE_REMEDY, at as webSettings, et as settingShapeErrors, ht as dirtyFingerprintFiles, i as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, it as unknownSettingKeys, m as defaultAndroidLayout, nt as settingsLayers, r as PATH_SETTINGS, tt as settingValueAt, vt as gitCommonDirAsync } from "./settings-C7O8A6ZI.mjs";
8
+ import { C as resolvePackageJson, _ as appProjectProblem, b as isPackageResolvable, v as detectIsExpo } from "./project-wM_XFTvE.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-Cvwn54qV.mjs";
10
+ import { L as listBuildSlots } from "./workspaces-CpANmBlq.mjs";
11
+ import { N as listBuildLocks } from "./activity-CMLmzp7o.mjs";
12
+ import { a as diffFingerprintSources, l as fingerprintProject } from "./build-cache-Dv7RN200.mjs";
13
+ import { _t as parkedMaxSetting, dt as POOL_SETTING_REMEDY, k as hostSystemImageArch, o as androidHome } from "./android-C7sVmyI9.mjs";
14
+ import { F as readHostMemoryPressureAsync, M as hostMemoryPressureAdvice } from "./ios-hcBpnEGk.mjs";
15
+ import { p as resolveOptimizations, u as compilerCacheFallbackMessage } from "./errors-ccaPc4ox.mjs";
16
+ import { i as projectCmakeLauncher } from "./ccache-Btwc36-I.mjs";
17
+ import { x as podInstallCommand } from "./xcode-BXn9-xYx.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-Dvd8hC21.mjs";
19
+ import { a as countLiveOwnedDevicesAsync, i as countLiveOwnedDevices } from "./device-capacity-DK5_EwRS.mjs";
20
+ import { t as readDoctorFingerprint } from "./doctor-fingerprint-DZLoYFVb.mjs";
21
+ import { i as probeSigningIdentities } from "./ios-signing-BtAffm0A.mjs";
22
+ import { a as findChrome, t as CHROME_INSTALL_REMEDY } from "./chrome-Bbw689-6.mjs";
23
+ import { i as installedNpmTreeIsValidAsync, n as hasInstalledDependencies, t as dependencyState } from "./dependency-state-1I9KZT1Y.mjs";
24
+ import { n as simslimIsOnPath } from "./simslim-BNckWpXi.mjs";
25
+ import { t as MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION } from "./eas-build-CwknaQYj.mjs";
26
+ import { r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-ngferVq2.mjs";
26
27
  import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
27
28
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
29
+ import { LAST_BUILD_KEYS, isJsonObject, readBuildHistory, readJsonObject, readStats, settingDefinition } from "@stim-cli/core/state";
28
30
  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";
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,149 +188,8 @@ 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
- });
177
- }
178
- return findings;
179
- }
180
- //#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
- }
191
+ findings.push(storageFailure(error));
306
192
  }
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."
313
- });
314
193
  return findings;
315
194
  }
316
195
  //#endregion
@@ -341,7 +220,7 @@ function moduleRoots(root, layout) {
341
220
  function cacheFiles(base, depth = 0) {
342
221
  const files = [];
343
222
  for (const name of children(base)) {
344
- if (depth === 0 && /^stim-[a-f0-9]{16}$/.test(name)) continue;
223
+ if (depth === 0 && /^(?:stim-[a-f0-9]{16}|[a-f0-9]{4})$/.test(name)) continue;
345
224
  const path = join(base, name);
346
225
  const entry = lstatSync(path);
347
226
  if (entry.isSymbolicLink()) continue;
@@ -451,6 +330,23 @@ function finding(level, title, detail, fix) {
451
330
  fix
452
331
  };
453
332
  }
333
+ const isDeviceCacheKey = (key) => typeof key === "string" && /-device(?:-|$)/.test(key);
334
+ /** 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. */
335
+ function deviceWorkflowPlausible(state, settings) {
336
+ const last = state?.[LAST_BUILD_KEYS.ios];
337
+ if (last && typeof last === "object" && "cacheKey" in last && isDeviceCacheKey(last.cacheKey)) return true;
338
+ if ((readBuildHistory(state).ios ?? []).some((entry) => isDeviceCacheKey(entry.cacheKey))) return true;
339
+ return [
340
+ "ios.signingIdentity",
341
+ "ios.signingIdentitySha1",
342
+ "ios.lanHost"
343
+ ].some((key) => settingValueAt(settings, key) !== void 0);
344
+ }
345
+ function checkDeviceSigning(identities) {
346
+ 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`).");
347
+ if (identities.length > 0) return null;
348
+ 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.");
349
+ }
454
350
  function checkOffloadCandidate(placements, machines, peers, now) {
455
351
  if (machines.length || !peers.some((peer) => isJsonObject(peer) && peer.OS === "macOS" && peer.Online === true)) return null;
456
352
  const cold = placements.filter((placement) => {
@@ -462,27 +358,27 @@ function checkOffloadCandidate(placements, machines, peers, now) {
462
358
  if (average <= 18e4) return null;
463
359
  return {
464
360
  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.")
361
+ ...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
362
  };
467
363
  }
468
- function readOffloadCandidate(tailnetStatus, now, host) {
364
+ async function readOffloadCandidate(tailnetStatus, now, host) {
469
365
  if (host !== "darwin") return null;
470
366
  try {
471
367
  const entries = loadConfig$1()?.remote?.machines;
472
368
  const machines = Array.isArray(entries) ? entries.filter((entry) => typeof entry === "string") : [];
473
369
  const placements = readStats().record?.placements ?? [];
474
370
  if (machines.length || placements.length < 3) return null;
475
- const status = tailnetStatus();
371
+ const status = await tailnetStatus();
476
372
  return checkOffloadCandidate(placements, machines, isJsonObject(status) && isJsonObject(status.Peer) ? Object.values(status.Peer) : [], now);
477
373
  } catch {
478
374
  return null;
479
375
  }
480
376
  }
481
- function mainCheckoutProjectRoot(projectRoot) {
482
- const currentRepoRoot = repoRoot(projectRoot);
377
+ async function mainCheckoutProjectRoot(projectRoot) {
378
+ const currentRepoRoot = await repoRootAsync(projectRoot);
483
379
  if (!currentRepoRoot) return projectRoot;
484
380
  try {
485
- const source = resolveSourceCheckout(currentRepoRoot);
381
+ const source = await resolveSourceCheckoutAsync(currentRepoRoot);
486
382
  if ("refusal" in source) return projectRoot;
487
383
  const projectRel = relative$1(currentRepoRoot, realpathSync$1(projectRoot));
488
384
  if (projectRel.startsWith("..")) return projectRoot;
@@ -491,15 +387,15 @@ function mainCheckoutProjectRoot(projectRoot) {
491
387
  return projectRoot;
492
388
  }
493
389
  }
494
- function brokenPodLinks(podsRoot) {
390
+ async function brokenPodLinks(podsRoot) {
495
391
  try {
496
- return getExecutor().runFile("find", [
392
+ return (await getExecutor().runFileAsync("find", [
497
393
  "-L",
498
394
  podsRoot,
499
395
  "-type",
500
396
  "l",
501
397
  "-print"
502
- ], { timeoutMs: 1e4 }).split("\n").map((line) => line.trim()).filter(Boolean);
398
+ ], { timeoutMs: 1e4 })).split("\n").map((line) => line.trim()).filter(Boolean);
503
399
  } catch {
504
400
  return [];
505
401
  }
@@ -514,90 +410,90 @@ function hasIosWarmOutput(root, iosRoot) {
514
410
  return false;
515
411
  }
516
412
  }
517
- function hasLinkedWorktree(projectRoot) {
518
- const root = repoRoot(projectRoot);
413
+ async function hasLinkedWorktree(projectRoot) {
414
+ const root = await repoRootAsync(projectRoot);
519
415
  if (!root) return false;
520
- return listWorktrees(root).filter((entry) => !entry.prunable && !entry.bare).length > 1;
416
+ return (await listWorktreesAsync(root)).filter((entry) => !entry.prunable && !entry.bare).length > 1;
521
417
  }
522
- function headBranch(root) {
523
- const ref = gitQuiet(root, [
418
+ async function headBranch(root) {
419
+ const ref = (await gitQuietAsync(root, [
524
420
  "symbolic-ref",
525
421
  "--quiet",
526
422
  "HEAD"
527
- ])?.trim();
423
+ ]))?.trim();
528
424
  return ref?.startsWith("refs/heads/") ? ref.slice(11) : null;
529
425
  }
530
- function mainOperation(root) {
531
- const gitDir = gitQuiet(root, [
426
+ async function mainOperation(root) {
427
+ const gitDir = (await gitQuietAsync(root, [
532
428
  "rev-parse",
533
429
  "--path-format=absolute",
534
430
  "--git-dir"
535
- ])?.trim();
431
+ ]))?.trim();
536
432
  if (!gitDir) return null;
537
433
  if (existsSync$1(join$1(gitDir, "rebase-merge")) || existsSync$1(join$1(gitDir, "rebase-apply"))) return "rebase";
538
434
  return existsSync$1(join$1(gitDir, "MERGE_HEAD")) ? "merge" : null;
539
435
  }
540
- function dirtyTrackedPaths(root) {
541
- return (gitQuiet(root, [
436
+ async function dirtyTrackedPaths(root) {
437
+ return (await gitQuietAsync(root, [
542
438
  "diff",
543
439
  "--name-only",
544
440
  "HEAD"
545
441
  ]) ?? "").split("\n").map((line) => line.trim()).filter(Boolean);
546
442
  }
547
- function resolveDefaultBranch(root) {
443
+ async function resolveDefaultBranch(root) {
548
444
  const worktree = resolveSettings({
549
- gitCommonDir: gitCommonDir(root),
550
- repoRoot: repoRoot(root) ?? root
445
+ gitCommonDir: await gitCommonDirAsync(root),
446
+ repoRoot: await repoRootAsync(root) ?? root
551
447
  }).worktree;
552
448
  const configured = worktree && typeof worktree === "object" && !Array.isArray(worktree) ? worktree.defaultBranch : void 0;
553
449
  if (typeof configured === "string" && configured.trim()) return configured.trim();
554
- const head = gitQuiet(root, [
450
+ const head = (await gitQuietAsync(root, [
555
451
  "symbolic-ref",
556
452
  "--short",
557
453
  "refs/remotes/origin/HEAD"
558
- ])?.trim();
454
+ ]))?.trim();
559
455
  if (!head) return null;
560
456
  const cut = head.indexOf("/");
561
457
  return cut > 0 ? head.slice(cut + 1) : head;
562
458
  }
563
- function seedFindings(mainRoot, upstream) {
459
+ async function seedFindings(mainRoot, upstream) {
564
460
  const findings = [];
565
- const root = repoRoot(mainRoot);
461
+ const root = await repoRootAsync(mainRoot);
566
462
  const quotedRoot = quotedPath(root ?? mainRoot);
567
463
  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
464
  if (root === null) return findings;
569
- const operation = mainOperation(root);
465
+ const operation = await mainOperation(root);
570
466
  if (operation) {
571
467
  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
468
  return findings;
573
469
  }
574
- const dirty = dirtyTrackedPaths(root);
470
+ const dirty = await dirtyTrackedPaths(root);
575
471
  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);
472
+ const branch = await headBranch(root);
577
473
  if (branch === null) {
578
474
  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
475
  return findings;
580
476
  }
581
477
  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);
478
+ const defaultBranch = await resolveDefaultBranch(root);
583
479
  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
480
  return findings;
585
481
  }
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);
482
+ async function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, upstream = void 0, linkedWorktrees = void 0, platform, localIos = platform !== "android", iosProjectPath = "ios", androidLayout = defaultAndroidLayout(projectRoot) } = {}) {
483
+ const mainRoot = await mainCheckoutProjectRoot(projectRoot);
588
484
  const mainAndroid = {
589
485
  ...androidLayout,
590
486
  gradleRoot: join$1(mainRoot, relative$1(projectRoot, androidLayout.gradleRoot)),
591
487
  moduleDir: join$1(mainRoot, relative$1(projectRoot, androidLayout.moduleDir))
592
488
  };
593
489
  const findings = [];
594
- const dependencies = dependencyState(mainRoot);
490
+ const dependencies = dependencyState(mainRoot, await repoRootAsync(mainRoot) ?? mainRoot);
595
491
  if (dependencies) {
596
492
  const installed = hasInstalledDependencies(dependencies.root, dependencies.installed);
597
493
  const installCommand = `cd ${quotedPath(dependencies.root)} && ${dependencies.command}`;
598
494
  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
495
  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.`));
496
+ 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
497
  }
602
498
  }
603
499
  const iosRoot = join$1(mainRoot, iosProjectPath);
@@ -616,7 +512,7 @@ function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, ups
616
512
  const podCommand = `cd ${quotedPath(iosRoot)} && ${podInstallCommand(mainRoot)}`;
617
513
  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
514
  }
619
- const broken = brokenPods === void 0 && existsSync$1(podsRoot) ? brokenPodLinks(podsRoot) : brokenPods || [];
515
+ const broken = brokenPods === void 0 && existsSync$1(podsRoot) ? await brokenPodLinks(podsRoot) : brokenPods || [];
620
516
  if (broken.length) {
621
517
  const podCommand = `cd ${quotedPath(iosRoot)} && ${podInstallCommand(mainRoot, "--clean-install")}`;
622
518
  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 +520,7 @@ function checkMainCheckout(projectRoot, { npmTreeValid, brokenPods = void 0, ups
624
520
  }
625
521
  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
522
  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));
523
+ if (linkedWorktrees === void 0 ? await hasLinkedWorktree(projectRoot) : linkedWorktrees) findings.push(...await seedFindings(mainRoot, upstream === void 0 ? await locallyKnownUpstreamAsync(mainRoot) : upstream));
628
524
  return findings;
629
525
  }
630
526
  function checkMetroCache(metroConfigSource) {
@@ -723,9 +619,12 @@ function checkConcurrency({ maxBuilds = 0, maxDevices = 0, liveDevices = 0, acti
723
619
  if (!maxBuilds && !maxDevices) return null;
724
620
  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
621
  }
726
- function easCliOutsideRepository(projectRoot) {
622
+ async function easCliOutsideRepository(projectRoot, operation) {
727
623
  const found = (String(getExecutor().findExecutable("eas") ?? "").split("\n")[0] ?? "").trim();
728
- const root = found ? repoRoot(projectRoot) : null;
624
+ const root = found ? operation ? await repoRootAsync(projectRoot, {
625
+ env: operation.env,
626
+ signal: operation.signal
627
+ }) : repoRoot(projectRoot) : null;
729
628
  if (!found || !root) return null;
730
629
  try {
731
630
  const repository = realpathSync$1(root);
@@ -743,18 +642,19 @@ function easCliOutsideRepository(projectRoot) {
743
642
  return null;
744
643
  }
745
644
  }
746
- function readProjectEasCliVersion(projectRoot) {
645
+ async function readProjectEasCliVersion(projectRoot, operation) {
747
646
  const packageJson = resolvePackageJson(projectRoot, "eas-cli");
748
647
  if (packageJson) {
749
648
  const version = readJsonObject(packageJson)?.version;
750
649
  return typeof version === "string" ? `eas-cli/${version}` : null;
751
650
  }
752
- const onPath = easCliOutsideRepository(projectRoot);
753
- return onPath ? readInstalledEasCliVersion(onPath, projectRoot) : null;
651
+ const onPath = await easCliOutsideRepository(projectRoot, operation);
652
+ return onPath ? readInstalledEasCliVersionAsync(onPath, projectRoot) : null;
754
653
  }
755
- function doctorEasAuth({ projectRoot, owner }) {
756
- const file = easCliOutsideRepository(projectRoot);
654
+ async function doctorEasAuth({ projectRoot, owner, operation }) {
655
+ const file = await easCliOutsideRepository(projectRoot, operation);
757
656
  if (file) return checkEasAuth$1({
657
+ context: operation,
758
658
  projectRoot,
759
659
  owner,
760
660
  resolveBin: () => ({
@@ -764,6 +664,7 @@ function doctorEasAuth({ projectRoot, owner }) {
764
664
  });
765
665
  const unchecked = resolveEasCliBin(projectRoot);
766
666
  if (!unchecked) return checkEasAuth$1({
667
+ context: operation,
767
668
  projectRoot,
768
669
  owner,
769
670
  resolveBin: () => null
@@ -793,13 +694,16 @@ function checkEasBuildDownload({ easJson = false, remoteEas = false, easCliResol
793
694
  if (easCli.supported) return null;
794
695
  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
696
  }
796
- function projectEasBuildDownloadFinding(projectRoot, remoteBackends, lookupEasCli) {
697
+ async function projectEasBuildDownloadFinding(projectRoot, remoteBackends, lookupEasCli, operation) {
797
698
  const easJson = existsSync$1(join$1(projectRoot, "eas.json"));
699
+ const remoteEas = remoteBackends.includes("eas");
700
+ const easCliResolvable = easJson && (lookupEasCli ? lookupEasCli() : Boolean(resolveEasCliBin(projectRoot)));
701
+ const version = easJson && !remoteEas && easCliResolvable ? await readProjectEasCliVersion(projectRoot, operation) : null;
798
702
  return checkEasBuildDownload({
799
703
  easJson,
800
- remoteEas: remoteBackends.includes("eas"),
801
- easCliResolvable: easJson && (lookupEasCli ? lookupEasCli() : Boolean(resolveEasCliBin(projectRoot))),
802
- readEasCliVersion: () => readProjectEasCliVersion(projectRoot)
704
+ remoteEas,
705
+ easCliResolvable,
706
+ readEasCliVersion: () => version
803
707
  });
804
708
  }
805
709
  function checkSimSlim({ configured = false, profileError = null, onPath = false } = {}) {
@@ -830,8 +734,8 @@ function configuredRemoteBackends(projectSettings, platform) {
830
734
  const androidTarget = remoteAndroidSetting(projectSettings);
831
735
  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
736
  }
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;
737
+ async function runDoctor(projectRoot, options = {}, inspectors = []) {
738
+ 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
739
  const localIos = platforms.includes("ios") && platform !== "android" && host === "darwin";
836
740
  const projectSettings = machineSettings.settings;
837
741
  const context = {
@@ -851,14 +755,15 @@ function runDoctor(projectRoot, options = {}, inspectors = []) {
851
755
  if (limits && (limits.maxBuilds || limits.maxDevices)) concurrencyFinding = checkConcurrency({
852
756
  maxBuilds: limits.maxBuilds,
853
757
  maxDevices: limits.maxDevices,
854
- liveDevices: liveDevices ? liveDevices() : countLiveOwnedDevices(),
758
+ liveDevices: liveDevices ? liveDevices() : options.operation ? await countLiveOwnedDevicesAsync(options.operation) : countLiveOwnedDevices(),
855
759
  activeBuilds: activeBuilds ? activeBuilds() : countActiveBuilds()
856
760
  });
857
761
  const settingShapeFindings = settingShapeErrors(projectSettings).map((error) => finding("cost", "A setting has the wrong type", error, SETTING_SHAPE_REMEDY));
858
762
  let optimizations = null;
859
763
  try {
860
764
  optimizations = resolveAndroidCompilerCache({
861
- optimizations: resolveOptimizations(projectSettings),
765
+ optimizations: resolveOptimizations(projectSettings, options.operation?.env ?? options.remoteEnv ?? process.env),
766
+ env: options.operation?.env ?? options.remoteEnv ?? process.env,
862
767
  use: readAndroidCasToolchain
863
768
  }).optimizations;
864
769
  } catch {}
@@ -880,36 +785,40 @@ function runDoctor(projectRoot, options = {}, inspectors = []) {
880
785
  profileError: simslimProfileError,
881
786
  onPath: simslimProfile ? lookupSimSlim ? lookupSimSlim() : simslimIsOnPath() : false
882
787
  });
883
- const memoryAdvice = localIos && !remoteIosSetting(projectSettings) ? hostMemoryPressureAdvice(memoryPressure()) : null;
788
+ const memoryAdvice = localIos && !remoteIosSetting(projectSettings) ? hostMemoryPressureAdvice(await memoryPressure()) : null;
789
+ const shared = [
790
+ ...checkStorageLayout(projectRoot, {
791
+ platform,
792
+ host,
793
+ scope: "shared"
794
+ }),
795
+ checkChrome({
796
+ usesWeb: () => !platform && webSettings(projectSettings).url !== null,
797
+ chrome: lookupChrome
798
+ }),
799
+ concurrencyFinding,
800
+ 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,
801
+ simslimFinding,
802
+ localIos && deviceWorkflowPlausible(readWorkspaceState$1(projectRoot), projectSettings) ? checkDeviceSigning(await lookupSigningIdentities()) : null,
803
+ ...settingShapeFindings,
804
+ ...checkMachineSettings({
805
+ settings: projectSettings,
806
+ layers: machineSettings.layers,
807
+ projectRoot,
808
+ optimizations,
809
+ env: options.operation?.env ?? options.remoteEnv ?? process.env,
810
+ reportedElsewhere: simslimProfileError ? ["ios.simslimProfile"] : []
811
+ })
812
+ ].filter((f) => Boolean(f));
813
+ const inspected = await Promise.all(inspectors.map((inspect) => inspect(context)));
884
814
  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))],
815
+ findings: [...shared, ...inspected.flat()],
907
816
  context
908
817
  };
909
818
  }
910
- function reactNativeDoctorFindings({ root: projectRoot, settings: projectSettings, optimizations, options, repoRoot: repositoryRoot }) {
819
+ async function reactNativeDoctorFindings({ root: projectRoot, settings: projectSettings, optimizations, options, repoRoot: repositoryRoot }) {
911
820
  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;
821
+ 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
822
  const localIos = platform !== "android" && host === "darwin";
914
823
  const read = (rel) => {
915
824
  const p = join$1(projectRoot, rel);
@@ -940,34 +849,29 @@ function reactNativeDoctorFindings({ root: projectRoot, settings: projectSetting
940
849
  const easFinding = remoteBuildCache && provider === "eas" ? checkEasAuth({
941
850
  provider,
942
851
  owner,
943
- auth: easAuth({
852
+ auth: await easAuth({
944
853
  projectRoot,
945
- owner
854
+ owner,
855
+ operation: options.operation
946
856
  })
947
857
  }) : null;
948
858
  const remoteBackends = configuredRemoteBackends(projectSettings, platform);
949
859
  const daemonInEnv = Boolean(remoteEnv.AGENT_DEVICE_DAEMON_BASE_URL?.trim() && remoteEnv.AGENT_DEVICE_DAEMON_AUTH_TOKEN?.trim());
950
860
  const agentDeviceOnPath = remoteBackends.length ? lookupAgentDevice ? lookupAgentDevice() : agentDeviceIsOnPath() : false;
951
861
  const easCliResolvable = remoteBackends.includes("eas") ? lookupEasCli ? lookupEasCli() : Boolean(resolveEasCliBin(projectRoot)) : false;
862
+ const remoteVersion = agentDeviceOnPath && easCliResolvable && remoteBackends.includes("eas") ? await readProjectEasCliVersion(projectRoot, options.operation) : null;
952
863
  const remoteFindings = remoteBackends.map((backend) => checkRemoteDevice({
953
864
  configured: backend,
954
865
  daemonInEnv,
955
866
  agentDeviceOnPath,
956
867
  easCliResolvable,
957
- readEasCliVersion: () => readProjectEasCliVersion(projectRoot)
868
+ readEasCliVersion: () => remoteVersion
958
869
  })).filter((remoteFinding) => remoteFinding !== null);
959
- const easBuildDownloadFinding = projectEasBuildDownloadFinding(projectRoot, remoteBackends, lookupEasCli);
870
+ const easBuildDownloadFinding = await projectEasBuildDownloadFinding(projectRoot, remoteBackends, lookupEasCli, options.operation);
960
871
  return [
961
872
  checkAppProject(projectRoot),
962
873
  checkIosHost(platform, host),
963
874
  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
875
  ...checkStorageLayout(projectRoot, {
972
876
  platform,
973
877
  host,
@@ -988,7 +892,7 @@ function reactNativeDoctorFindings({ root: projectRoot, settings: projectSetting
988
892
  remoteBuildCache ? checkBuildCacheProvider(appConfig, sdkMajor, isExpo, dynamicConfig) : null,
989
893
  easFinding,
990
894
  easBuildDownloadFinding,
991
- readOffloadCandidate(tailnetStatus, now(), host),
895
+ await readOffloadCandidate(tailnetStatus, now(), host),
992
896
  ...remoteFindings
993
897
  ].filter((value) => Boolean(value));
994
898
  }
@@ -1110,8 +1014,8 @@ function listDirectory(dir) {
1110
1014
  return [];
1111
1015
  }
1112
1016
  }
1113
- function hasLinkedPackageWithGit(projectRoot) {
1114
- const root = repoRoot(projectRoot) ?? projectRoot;
1017
+ async function hasLinkedPackageWithGit(projectRoot) {
1018
+ const root = await repoRootAsync(projectRoot) ?? projectRoot;
1115
1019
  for (let dir = projectRoot;; dir = dirname$1(dir)) {
1116
1020
  if (linkedPackageWithGitIn(join$1(dir, "node_modules"))) return true;
1117
1021
  if (dir === root || dirname$1(dir) === dir || relative$1(root, dirname$1(dir)).startsWith("..")) return false;
@@ -1137,14 +1041,18 @@ function linkedPackageWithGitIn(nodeModules) {
1137
1041
  * packages can be hoisted, so the gate looks at every node_modules from the
1138
1042
  * app up to the repository root.
1139
1043
  */
1140
- async function detectLinkedLibraryGitMetadata(projectRoot, { createFingerprint = expoFingerprint.createFingerprintAsync, platform } = {}) {
1141
- const mainRoot = mainCheckoutProjectRoot(projectRoot);
1142
- if (!hasLinkedPackageWithGit(mainRoot)) return null;
1044
+ async function detectLinkedLibraryGitMetadata(projectRoot, { createFingerprint = expoFingerprint.createFingerprintAsync, platform, operation } = {}) {
1045
+ const mainRoot = await mainCheckoutProjectRoot(projectRoot);
1046
+ if (!await hasLinkedPackageWithGit(mainRoot)) return null;
1143
1047
  const skipped = fingerprintConfigSkipped(mainRoot);
1144
1048
  if (skipped) return skipped;
1145
1049
  let sources;
1146
1050
  try {
1147
- sources = (await fingerprintProject(mainRoot, {
1051
+ sources = (operation && createFingerprint === expoFingerprint.createFingerprintAsync ? await readDoctorFingerprint(operation, {
1052
+ root: mainRoot,
1053
+ platform,
1054
+ debug: true
1055
+ }) : await fingerprintProject(mainRoot, {
1148
1056
  platform,
1149
1057
  createFingerprint,
1150
1058
  debug: true
@@ -1164,8 +1072,14 @@ async function detectLinkedLibraryGitMetadata(projectRoot, { createFingerprint =
1164
1072
  code: "linked-library-git-metadata"
1165
1073
  };
1166
1074
  }
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;
1075
+ async function appPathInRepository(projectRoot) {
1076
+ const top = await repoRootAsync(projectRoot);
1077
+ if (!top) return "";
1078
+ const path = relative$1(realpathSync$1.native(top), realpathSync$1.native(projectRoot));
1079
+ return path.startsWith("..") ? "" : path;
1080
+ }
1081
+ async function detectFingerprintParity(projectRoot, { createFingerprint = expoFingerprint.createFingerprintAsync, differ = expoFingerprint.diffFingerprints, dirtyFiles = dirtyFingerprintFiles, platform: selectedPlatform, iosProjectPath = "ios", operation } = {}) {
1082
+ if (await gitQuietAsync(projectRoot, ["rev-parse", "--git-dir"]) == null) return null;
1169
1083
  if (hasInstalledDependencies(projectRoot)) return null;
1170
1084
  const skipped = fingerprintConfigSkipped(projectRoot);
1171
1085
  if (skipped) return skipped;
@@ -1183,37 +1097,44 @@ async function detectFingerprintParity(projectRoot, { createFingerprint = expoFi
1183
1097
  return null;
1184
1098
  }
1185
1099
  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
- }
1100
+ let released;
1101
+ let rejected;
1102
+ const cleanup = new Promise((done, reject) => {
1103
+ released = done;
1104
+ rejected = reject;
1105
+ });
1106
+ const release = () => released();
1107
+ let added = false;
1108
+ trackReportResource(operation, cleanup, () => cleanup);
1204
1109
  try {
1205
- const headSkipped = fingerprintConfigSkipped(worktree) ?? coldFingerprintRunsProjectCode(worktree, platform);
1110
+ added = await gitQuietAsync(projectRoot, [
1111
+ "-c",
1112
+ `core.hooksPath=${join$1(base, "hooks")}`,
1113
+ "worktree",
1114
+ "add",
1115
+ "--detach",
1116
+ worktree,
1117
+ "HEAD"
1118
+ ], {
1119
+ write: true,
1120
+ timeoutMs: 6e4
1121
+ }) !== null;
1122
+ if (!added) return null;
1123
+ const headApp = join$1(worktree, await appPathInRepository(projectRoot));
1124
+ const headSkipped = fingerprintConfigSkipped(headApp) ?? coldFingerprintRunsProjectCode(headApp, platform);
1206
1125
  if (headSkipped) return headSkipped;
1207
- const project = await fingerprintProject(projectRoot, {
1126
+ const inspect = (root) => operation && createFingerprint === expoFingerprint.createFingerprintAsync ? readDoctorFingerprint(operation, {
1127
+ root,
1208
1128
  platform,
1209
1129
  iosProjectPath,
1210
- createFingerprint: coldFingerprint
1211
- });
1212
- const clean = await fingerprintProject(worktree, {
1130
+ cold: true
1131
+ }) : fingerprintProject(root, {
1213
1132
  platform,
1214
1133
  iosProjectPath,
1215
1134
  createFingerprint: coldFingerprint
1216
1135
  });
1136
+ const project = await inspect(projectRoot);
1137
+ const clean = await inspect(headApp);
1217
1138
  if (!project || !clean) return null;
1218
1139
  if (project.hash === clean.hash) return null;
1219
1140
  const changed = diffFingerprintSources({
@@ -1226,26 +1147,56 @@ async function detectFingerprintParity(projectRoot, { createFingerprint = expoFi
1226
1147
  projectHash: project.hash,
1227
1148
  worktreeHash: clean.hash,
1228
1149
  changed,
1229
- dirtyFiles: dirtyFiles(projectRoot)
1150
+ dirtyFiles: await dirtyFiles(projectRoot)
1230
1151
  });
1231
1152
  } catch {
1232
1153
  return null;
1233
1154
  } 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 });
1155
+ await finishCleanup();
1156
+ }
1157
+ async function finishCleanup() {
1158
+ try {
1159
+ const options = {
1160
+ timeoutMs: 3e4,
1161
+ ...operation ? { signal: AbortSignal.timeout(3e4) } : {}
1162
+ };
1163
+ const target = join$1(realpathSync$1.native(base), "head");
1164
+ if (added || operation) await gitQuietAsync(projectRoot, [
1165
+ "worktree",
1166
+ "remove",
1167
+ "--force",
1168
+ "--force",
1169
+ worktree
1170
+ ], {
1171
+ write: true,
1172
+ ...options
1173
+ });
1174
+ if (operation) {
1175
+ const registered = await gitQuietAsync(projectRoot, [
1176
+ "worktree",
1177
+ "list",
1178
+ "--porcelain",
1179
+ "-z"
1180
+ ], options);
1181
+ 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.");
1182
+ }
1183
+ await rm(base, {
1184
+ recursive: true,
1185
+ force: true
1186
+ });
1187
+ if (added && !operation) await gitQuietAsync(projectRoot, ["worktree", "prune"], { write: true });
1188
+ } catch (error) {
1189
+ if (!operation) throw error;
1190
+ const refusal = Object.assign(new Error(`Cannot finish cleanup for temporary worktree ${worktree}.`, { cause: error }), {
1191
+ code: "STIM_CLAIM_UNAVAILABLE",
1192
+ reportCleanup: true
1193
+ });
1194
+ if (reportSignal(operation)) rejected(refusal);
1195
+ throw refusal;
1196
+ } finally {
1197
+ release();
1198
+ }
1248
1199
  }
1249
1200
  }
1250
1201
  //#endregion
1251
- export { repairCxxLauncherState as a, runDoctor as i, detectLinkedLibraryGitMetadata as n, readMachineSettings as o, reactNativeDoctorFindings as r, detectFingerprintParity as t };
1202
+ 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 };