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
package/README.md CHANGED
@@ -44,13 +44,34 @@ Stim builds or restores the app, installs it, launches it, and checks launch
44
44
  readiness. Plain output streams progress and reports the complete result. Use
45
45
  `--json` when a script needs structured data.
46
46
 
47
+ For native Xcode simulator builds, declared repeatable SwiftPM macOS builds,
48
+ and React Native/Expo iOS Simulator or Android development builds, a local and configured-provider miss can
49
+ reuse an exact completed artifact from an enabled paired build worker. Reuse
50
+ checks the full source, toolchain, SDK, architecture and target cache key and
51
+ verifies the downloaded archive. It needs no compilation slot. An explicit
52
+ local build and remote build mode off skip peer lookup. React Native archives
53
+ match the native fingerprint, build choices and compatible toolchain verified
54
+ around compilation; they remain reusable after the worker changes checkouts.
55
+ Release and physical device builds keep their existing cache paths. See `stim guide settings` for placement.
56
+ SwiftPM peer reuse requires `macos.artifactInputs` and a capable worker. Its
57
+ receipt verifies actual worker source and rechecks worker-private files,
58
+ environment and Swift/Xcode/SDK identity. Private values are not transferred;
59
+ worker identities are separate from local cache keys. Compiler overrides
60
+ (`SWIFT_EXEC` and `SWIFT_EXEC_MANIFEST`) are resolved and versioned separately.
61
+ Overrides and custom toolchain launchers
62
+ require the worker checkout to revalidate their selection. See `stim guide macos`.
63
+
47
64
  ## Native Android build workers
48
65
 
49
66
  Native Gradle apps can use an approved build worker after declaring that
50
67
  Git-visible source and exact additional ignored files are sufficient. See
51
- `stim guide lifecycle native-android` for `android.offloadInputs`, generated
52
- output ownership, and supported input boundaries. Stim does not invent an artifact-cache key for
53
- arbitrary Gradle inputs; Gradle keeps its own incremental and task caches.
68
+ `stim guide lifecycle native-android` for `android.offloadInputs`, generated output ownership,
69
+ and supported input boundaries. Workers remain uncached. Local builds can opt
70
+ into APK caching through a separate complete `android.artifactInputs` declaration.
71
+ A configured cache provider with a `files` capability can share the verified APK
72
+ and its receipt between machines. Private input files and environment values
73
+ stay local; the declaration never authorizes their transfer. Gradle
74
+ keeps its own incremental and task caches in both cases.
54
75
 
55
76
  ## Programmatic API
56
77
 
@@ -80,26 +101,138 @@ already running server. `run` builds, installs and launches.
80
101
  `build({ platform: 'ios' })` returns a retained simulator app without starting
81
102
  a device or runtime; Android returns an APK and macOS returns an app bundle.
82
103
  Build-only preserves existing sessions and uses the same cache and build locks.
104
+ Successful builds include `result.facts.links.workspace`, an HTTPS workspace link
105
+ agents can share with an already-paired phone or Desktop, including when the
106
+ build machine has no Desktop app installed.
83
107
  Each result is a separate copy kept in the workspace until `stim worktree remove`.
84
108
  Run results preserve the CLI's launch evidence, including `'bundling'` and
85
109
  `'unverified'` results.
86
110
 
87
- Each operation uses a separate bundled worker so its home, cancellation and
88
- process state cannot change the importing process. The CLI and workers call
111
+ `reload({ platform?: 'ios' | 'android' | 'web', signal? })` requests a JavaScript
112
+ reload in a live app or reloads the owned Chrome page, returning the flat
113
+ `stim reload --json` facts. Select a platform when more than one is live.
114
+ Dispatch does not prove completion; verify the expected UI and inspect logs.
115
+ A Metro broadcast can reach other connected clients. Reload uses a 60 second
116
+ execution budget and 35 second cleanup budget, with the report timeout and
117
+ cleanup refusals described below. Cancellation stops pending work but cannot
118
+ retract a request already sent. Reload never retries automatically.
119
+
120
+ `warmWorktree({ signal?, beforeWarm? })` copies missing ignored state from the
121
+ source checkout into the client's linked worktree in process, returning
122
+ `{ exitCode: 0 | 1 }`. It preserves existing entries and tracked files, shares
123
+ the source's read claim, and takes an exclusive claim on the target while copying.
124
+ `beforeWarm(workspace)` admits each canonical workspace in the resolved warming
125
+ scope before registration or copying; throwing refuses warming. Progress uses
126
+ `onProgress`. Cancellation drains the copy child before removing its partial
127
+ entry or releasing claims. Unverifiable cleanup retains the claims and reports
128
+ `STIM_CLAIM_UNAVAILABLE` with recovery paths. Warming has a 90 minute execution
129
+ budget and a 35 second cleanup budget. Source refresh remains available through
130
+ `stim worktree warm --refresh`; this API does not refresh or install dependencies.
131
+
132
+ `removeWorktree({ target?, force?, signal? })` uses the CLI's removal checks and
133
+ cleanup in process. The target defaults to `projectRoot`; relative paths resolve
134
+ against it. It returns `{ removed, exitCode }` without changing `process.exitCode`.
135
+ Source checkout environment cleanup can succeed with `removed: false` and
136
+ `exitCode: 0`; a linked worktree deleted before a branch-cleanup failure returns
137
+ `removed: true` and `exitCode: 1`. `force` means CLI `--force`, including discarding
138
+ unsaved work. It uses the 60 second execution and 35 second cleanup budgets below.
139
+ Cancellation stops pending actions and drains owned cleanup; completed deletions
140
+ remain applied.
141
+
142
+ `setSetting(key, text, { scope?, signal? })` and `unsetSetting(key, { scope?, signal? })`
143
+ share the CLI's validation and return its JSON write result, including masked
144
+ sensitive values. Values use CLI text syntax, including JSON for arrays and
145
+ objects. Config lock waits and device-pool probes are asynchronous. Cancellation
146
+ prevents a pending write; a committed write finishes its recording cleanup
147
+ before settling. Recording changes serialize through cleanup within the home.
148
+
149
+ Native lifecycle operations run in the importing process. Custom Expo
150
+ `buildCacheProvider` modules are not supported. Use EAS or a Stim cache provider.
151
+
152
+ `settings()` and `stats()`
153
+ read the `stim settings --json` and `stim stats --json` payloads. All
154
+ use the client's own home and leave the caller's cwd, environment,
155
+ output, signal handlers and exit listeners as they were. The API and CLI call
89
156
  the same native lifecycle operations. Progress is silent unless `onProgress`
90
157
  is provided; its `message` is an output chunk. Operations accept `signal`.
91
- Cancellation waits for the worker to exit, and does not replace `stop()`.
158
+ Cancellation drains the operation's owned work, and does not replace `stop()`.
92
159
  Call cleanup with a fresh signal after cancellation or partial failure.
160
+ Cancelling `stop()` while it waits for another native operation ends that wait.
161
+ Once teardown starts, it finishes cleanup before rejecting with `STIM_CANCELLED`;
162
+ its config, workspace-state, and lease lock waits are asynchronous.
163
+
164
+ `plan({ platform: 'ios' | 'android' | 'macos', signal? })` predicts the next
165
+ configured native build, as the CLI's `--plan --json` reports it, without building
166
+ or launching. iOS and Android also accept `slot`; build and device selectors
167
+ come from the project's settings. Plans use the report execution and cleanup
168
+ budgets below. Fingerprinting uses the existing cancellable report helper;
169
+ native probes and cache downloads finish cleanup before the report settles.
170
+ Cache providers must settle after cancellation. If cleanup cannot finish within
171
+ 35 seconds, the plan refuses with `STIM_CLAIM_UNAVAILABLE` and retains the download
172
+ directory; it does not delete files a broken provider may still be writing.
173
+
174
+ `doctor({ platform?, record? })` and `gc({ cache?, olderThan?, worktrees? })` read their CLI
175
+ JSON reports with a 60 second execution budget and optional `signal`. Doctor
176
+ never repairs; its `stim.runningPath` is null. By default it does not record a
177
+ check. Pass `record: true` to register the supported iOS/Android project and record
178
+ its checked platforms after the report and owned cleanup succeed. Recording waits
179
+ asynchronously for the config lock, honors `signal`, and rejects unavailable state.
180
+ GC never
181
+ deletes or shuts down idle devices. Reads can refresh their own usage caches
182
+ and existing pending remote approvals. An explicit `home` or `STIM_HOME` keeps
183
+ the CLI's scoped-home restrictions. Expiry rejects with `STIM_REPORT_TIMEOUT`
184
+ after owned cleanup; a caller abort rejects with
185
+ `STIM_CANCELLED`. Throwing from report progress also cancels the read.
186
+ If child identity cannot be verified after a one-second retry budget, cleanup
187
+ refuses with `STIM_CLAIM_UNAVAILABLE` instead of a cancellation or timeout
188
+ error. Child cleanup errors name the launcher PID; unverifiable processes and descendants
189
+ are left untouched. On POSIX, a launcher that exited before identity capture can only
190
+ finish successfully once its process group is proven gone.
191
+ After a termination request, cleanup waits at most one second for a child to
192
+ close. Overall cleanup has a 35 second budget, including temporary-worktree
193
+ removal; unfinished cleanup returns `STIM_CLAIM_UNAVAILABLE` and leaves
194
+ unresolved resources in place. Credential refresh waits asynchronously and
195
+ checks cancellation before writing.
196
+ On Windows, report probes require the built-in Windows PowerShell for process-tree containment.
93
197
 
94
198
  `home` and `buildCache` accept absolute paths. Omit them to use normal Stim
95
199
  settings. A cache used by concurrent writers needs the same coordinating Stim
96
200
  home; do not point independent homes at a concurrently writable artifact cache.
201
+ `start({ remote?, resetCache?, waitSeconds?, signal?, beforeStart? })` starts or
202
+ reuses the managed dev server and returns flat start facts.
203
+ The optional admission callback receives the resolved app before startup effects.
204
+ Cancellation accounts for newly spawned processes before returning; a verified
205
+ supervisor handed off to its workspace can remain running. Unconfirmed cleanup
206
+ reports `STIM_CLAIM_UNAVAILABLE` with the retained ownership claims' recovery remedy.
207
+
97
208
  Ownership checks and cache locks remain active. `stop()` acts on this workspace,
98
209
  including resources from earlier runs, so use a dedicated workspace in CI.
99
210
 
100
211
  Stim failures are `StimError` instances with `code`, `message`, `remedy`, and
101
- `details`. An exception thrown by `onProgress` cancels the worker and is
102
- propagated unchanged.
212
+ `details`. An exception thrown by `onProgress` stops further progress and is
213
+ propagated unchanged: `start()`, `build()` or `run()` is cancelled, and
214
+ `stop()` or read finishes its work first.
215
+ `logs({ tail, sources, minLevel, slot, since, grep, errorsOnly })` reads the same
216
+ merged records as `stim logs --json`, including crash capture and agent actions.
217
+ Pass `tail` to bound the returned records. `followLogs(options, onRecord)` emits
218
+ that backfill and new records, then returns a stop function; aborting its signal
219
+ also stops it. An optional third callback receives initial records instead of
220
+ `onRecord`; its promise is awaited before the next batch. With that callback and
221
+ no `tail`, timeline batches hold at most 500 records. Agent attribution still
222
+ retains its matching records during backfill. These reads run in process and yield between log chunks.
223
+ Local follow uses filesystem hints with a ten-second repair scan. While a
224
+ directory watch is unavailable, it retries and scans every 500 ms; Expo error
225
+ context uses a timer only while pending. Local agent actions use filesystem
226
+ notifications for state and claim changes, with the same repair timing. Active hosted log
227
+ queries retain their pull cadence.
228
+ Attachment schedules one 500 ms recovery scan. A moved directory on Windows can
229
+ require the ten-second repair scan.
230
+ Hosted targets join and leave the follow stream from local state notifications;
231
+ missed notifications are reconciled about every 10 seconds. Active hosts still
232
+ serve bounded log queries.
233
+ Tail selection bounds matching timeline and agent records; agent attribution
234
+ still reads each retained session generation to establish device ownership.
235
+
103
236
  `diagnostics()` returns the workspace log directory and up to 200 local records,
104
237
  even if no run has succeeded. It does not fetch remote logs or capture new crashes.
105
238
  See [the API reference](https://stim.appandflow.com/docs/programmatic-api) or
@@ -0,0 +1,171 @@
1
+ import { r as WorkspaceProcessCleanupError } from "./exec-DEoAhcze.mjs";
2
+ import { I as waitForSharedBuild } from "./activity-CMLmzp7o.mjs";
3
+ import { rmSync } from "node:fs";
4
+ //#region src/engine/artifact-lifecycle.ts
5
+ async function runArtifactLifecycle(phases) {
6
+ try {
7
+ const resolved = await phases.resolve();
8
+ if (resolved.kind === "ready") return resolved.artifact;
9
+ const cached = resolved.kind === "cached" ? resolved.artifact : await phases.claim?.() ?? null;
10
+ if (cached !== null) {
11
+ const reused = await phases.reuse(cached);
12
+ if (reused !== null) return reused;
13
+ }
14
+ const { build } = phases;
15
+ const placement = await build.placement?.select() ?? null;
16
+ if (placement === null) await build.admit();
17
+ const preparation = await build.prepare();
18
+ const late = await build.revalidate(preparation);
19
+ if (late !== null) return late.ready;
20
+ if (build.placement && placement !== null) {
21
+ const offloaded = await build.placement.acquire(placement, preparation);
22
+ if (offloaded !== null) return offloaded.ready;
23
+ await build.admit();
24
+ }
25
+ const artifact = await build.compile(placement, preparation);
26
+ if (await build.validate(preparation) === "cacheable") await build.store(artifact);
27
+ return build.finish ? await build.finish(artifact) : artifact;
28
+ } finally {
29
+ phases.release();
30
+ }
31
+ }
32
+ //#endregion
33
+ //#region src/engine/cleanup-scope.ts
34
+ function drain(pending, report) {
35
+ const kept = [];
36
+ for (const cleanup of pending.toReversed()) try {
37
+ cleanup();
38
+ } catch (error) {
39
+ kept.unshift(cleanup);
40
+ report(error);
41
+ }
42
+ return kept;
43
+ }
44
+ function createCleanupScope(report) {
45
+ let pending = [];
46
+ return {
47
+ defer: (cleanup) => {
48
+ pending.push(cleanup);
49
+ return () => {
50
+ pending = pending.filter((entry) => entry !== cleanup);
51
+ };
52
+ },
53
+ transfer: () => {
54
+ let handed = pending;
55
+ pending = [];
56
+ return () => {
57
+ handed = drain(handed, report);
58
+ };
59
+ },
60
+ release: () => {
61
+ pending = drain(pending, report);
62
+ }
63
+ };
64
+ }
65
+ //#endregion
66
+ //#region src/engine/acquire-artifact.ts
67
+ function unresolvedCleanup(error) {
68
+ return error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error;
69
+ }
70
+ /** Waits for upload readers; unresolved child cleanup refuses deletion of their temporary inputs. */
71
+ async function settleArtifactUploads(...uploads) {
72
+ const unresolved = (await Promise.allSettled(uploads)).find((result) => result.status === "rejected" && unresolvedCleanup(result.reason));
73
+ if (unresolved?.status === "rejected") throw unresolved.reason;
74
+ }
75
+ async function acquireArtifact(adapter, { root, logFile, deps }) {
76
+ const owned = createCleanupScope((error) => adapter.temporaryReleaseFailed(error));
77
+ let closeOffload = null;
78
+ let buildLock = null;
79
+ let buildSlot = null;
80
+ const releaseLock = () => {
81
+ if (!buildLock) return;
82
+ const held = buildLock;
83
+ buildLock = null;
84
+ try {
85
+ deps.releaseBuildLock(held);
86
+ } catch (error) {
87
+ adapter.releaseFailed(`the build lock at ${held.path}`, error);
88
+ }
89
+ };
90
+ const releaseSlot = () => {
91
+ if (!buildSlot) return;
92
+ const held = buildSlot;
93
+ buildSlot = null;
94
+ try {
95
+ deps.releaseBuildSlot(held);
96
+ } catch (error) {
97
+ adapter.releaseFailed("the build slot", error);
98
+ }
99
+ };
100
+ const run = {
101
+ own: (directory) => owned.defer(() => rmSync(directory, {
102
+ recursive: true,
103
+ force: true
104
+ })),
105
+ openOffload: (close) => {
106
+ closeOffload = close;
107
+ },
108
+ claimSharedBuild: async (options) => {
109
+ const shared = await waitForSharedBuild({
110
+ ...options,
111
+ platform: adapter.platform,
112
+ root,
113
+ logFile,
114
+ command: adapter.command,
115
+ acquire: deps.acquireBuildLock,
116
+ wait: deps.waitForBuild,
117
+ now: deps.now
118
+ });
119
+ if (!shared.refusal) buildLock = shared.lock;
120
+ return shared;
121
+ },
122
+ takeBuildSlot: async (options) => {
123
+ buildSlot = await deps.acquireBuildSlot({
124
+ ...options,
125
+ root,
126
+ logFile
127
+ });
128
+ return buildSlot;
129
+ }
130
+ };
131
+ try {
132
+ return {
133
+ ok: true,
134
+ artifact: await runArtifactLifecycle({
135
+ ...adapter.lifecycle(run),
136
+ release: () => {
137
+ const close = closeOffload;
138
+ closeOffload = null;
139
+ try {
140
+ close?.();
141
+ } finally {
142
+ releaseLock();
143
+ releaseSlot();
144
+ }
145
+ }
146
+ }),
147
+ release: owned.transfer()
148
+ };
149
+ } catch (error) {
150
+ try {
151
+ await adapter.settleFailed?.();
152
+ } catch (cleanupError) {
153
+ if (unresolvedCleanup(cleanupError)) owned.transfer();
154
+ throw cleanupError;
155
+ }
156
+ if (unresolvedCleanup(error)) {
157
+ owned.transfer();
158
+ throw error;
159
+ }
160
+ const failure = adapter.refuse(error);
161
+ if (failure === null) throw error;
162
+ return {
163
+ ok: false,
164
+ failure
165
+ };
166
+ } finally {
167
+ owned.release();
168
+ }
169
+ }
170
+ //#endregion
171
+ export { settleArtifactUploads as n, acquireArtifact as t };