stim 1.20.2 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +88 -8
  2. package/dist/acquire-artifact-CD4lbiWE.mjs +153 -0
  3. package/dist/act-DHAw2A2S.mjs +2667 -0
  4. package/dist/activity-BzVfHSrY.mjs +1376 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-zh1vhbLp.mjs} +21 -65
  6. package/dist/{android-HqP1_vB_.mjs → android-BEJ8Jpl7.mjs} +2 -2
  7. package/dist/{android-DCKZrNvV.mjs → android-BLgbNqox.mjs} +128 -78
  8. package/dist/{android-Dlzxshgp.mjs → android-CV_GCELZ.mjs} +5 -5
  9. package/dist/{android-Mz_Inn3w.mjs → android-DUYkNF4u.mjs} +184 -102
  10. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-Ct5b1xCK.mjs} +7 -6
  11. package/dist/android-cas-compiler.mjs +2 -2
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/api.d.mts +740 -8
  14. package/dist/api.mjs +585 -1
  15. package/dist/{artifact-HSwkIWEQ.mjs → artifact-B8T3S5gi.mjs} +223 -201
  16. package/dist/{artifact-D3czlUvT.mjs → artifact-DAuZ-FNU.mjs} +158 -148
  17. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-QQzVjz3O.mjs} +26 -24
  18. package/dist/budget-Bs6SxxzO.mjs +9154 -0
  19. package/dist/{build-DYDbfkk5.mjs → build-CoPzQRNw.mjs} +144 -96
  20. package/dist/build-cache-DmyR9Zzc.mjs +602 -0
  21. package/dist/build-plan-CaFskB7_.mjs +188 -0
  22. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DkkqguoK.mjs} +2 -2
  23. package/dist/cache-manifest.mjs +1 -1
  24. package/dist/{ccache-zdKiYQ3E.mjs → ccache-BJRZ9pG3.mjs} +10 -9
  25. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-CWmIUMbw.mjs} +18 -5
  26. package/dist/{chrome-BnzZMqsR.mjs → chrome-B6tfCta1.mjs} +7 -4
  27. package/dist/{cli-CLP3diBm.mjs → cli-0DYf8QhQ.mjs} +20 -20
  28. package/dist/cli.mjs +1 -1
  29. package/dist/client-B7QVOlCr.d.mts +253 -0
  30. package/dist/client-UXD70ZbM.mjs +1406 -0
  31. package/dist/collector-run.d.mts +4 -40
  32. package/dist/collector-run.mjs +9 -8
  33. package/dist/{command-output-BTy8hZ0F.mjs → command-output-B1UrjZHL.mjs} +1 -1
  34. package/dist/config-CYcBF478.mjs +949 -0
  35. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-CqeBlrEn.mjs} +3 -3
  36. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-BbKQW83h.mjs} +20 -5
  37. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-DFRyG1_o.mjs} +1 -1
  38. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-UOeESKm6.mjs} +2 -2
  39. package/dist/device-DCxH7_By.mjs +1068 -0
  40. package/dist/{device-BECOiufl.mjs → device-ExJq8Ei7.mjs} +35 -35
  41. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-CMlqEcvw.mjs} +43 -13
  42. package/dist/device-host-worker.mjs +65 -61
  43. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DRUeKaFV.mjs} +48 -45
  44. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-C8raGFoP.mjs} +14 -26
  45. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-DMRpVX9a.mjs} +5 -5
  46. package/dist/doctor-BLHCYxzi.mjs +2 -0
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-DTvaDOda.mjs} +281 -317
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-Dhqebm0q.mjs} +183 -91
  49. package/dist/doctor-fingerprint.mjs +19 -0
  50. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-Cv1F10Kj.mjs} +40 -21
  51. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-BomfRnFT.mjs} +53 -20
  52. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-DJwZpy0c.mjs} +26 -208
  53. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-op6A54yi.mjs} +229 -11
  54. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-Bf0rZvG9.mjs} +172 -82
  55. package/dist/exec-H20xSg2T.d.mts +65 -0
  56. package/dist/exec-_UbtCQcG.mjs +750 -0
  57. package/dist/gc-C-WwL0yi.mjs +3 -0
  58. package/dist/{gc-qWOMdnER.mjs → gc-_-dCXdyL.mjs} +584 -796
  59. package/dist/git-C3iTsJaZ.mjs +73 -0
  60. package/dist/{guide-G9cAbVAc.mjs → guide-Yqwt2bd6.mjs} +941 -269
  61. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-Bw-honsd.mjs} +8 -6
  62. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DB_gBPfY.mjs} +34 -19
  63. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CUvOf4Vr.mjs} +1 -1
  64. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-DL_P5AdN.mjs} +77 -43
  65. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-QI141yKk.mjs} +21 -17
  66. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-Ksyjgzq-.mjs} +30 -21
  67. package/dist/idle-BVeRGroT.d.mts +24 -0
  68. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DaKmZi0z.mjs} +11 -10
  69. package/dist/{ios-BwVCF7oA.mjs → ios-CQ68hG9s.mjs} +8 -8
  70. package/dist/{ios-RkW4pnQf.mjs → ios-CpByZy12.mjs} +140 -80
  71. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-CXGP1bsD.mjs} +1 -1
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device-CwFMehUS.mjs} +51 -26
  73. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-WuwwBdvW.mjs} +13 -13
  74. package/dist/{ios-nOLJGVdy.mjs → ios-qNJt4dFm.mjs} +1 -1
  75. package/dist/ios-signing-DTTIChGs.mjs +489 -0
  76. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-DvFX-K_l.mjs} +1 -1
  77. package/dist/{ios-Ce7bc7br.mjs → ios-ubFsBzwq.mjs} +129 -86
  78. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Cc1dttps.mjs} +53 -26
  79. package/dist/{launch-F4sOqAhB.mjs → launch-CD1yVc7U.mjs} +91 -90
  80. package/dist/{launch-C3qJ6Agb.mjs → launch-Zq2mOSDy.mjs} +82 -541
  81. package/dist/logs-BS00Anxf.mjs +352 -0
  82. package/dist/logs-CMm05HxN.mjs +255 -0
  83. package/dist/{macos-D7uDvO-z.mjs → macos-B65--pPd.mjs} +1 -1
  84. package/dist/{macos-Ch5VJmcS.mjs → macos-C-0qJ6zq.mjs} +225 -212
  85. package/dist/macos-run.mjs +1 -1
  86. package/dist/maintenance-run.mjs +122 -247
  87. package/dist/{metro-DnCEjCxs.mjs → metro-DEXpIhHC.mjs} +67 -12
  88. package/dist/{metro-gateway-CX9Xlkq2.mjs → metro-gateway-BMJNlj3E.mjs} +20 -12
  89. package/dist/{named-ports-4WopRPg-.mjs → named-ports-BWTzt6mu.mjs} +8 -63
  90. package/dist/native-android-JACyjTZs.mjs +844 -0
  91. package/dist/{native-gradle-inputs-BsLRrl7u.mjs → native-gradle-inputs-Bep9JcSF.mjs} +128 -140
  92. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  93. package/dist/native-run-DY_RLx3C.mjs +277 -0
  94. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-Dg1Q7tfF.mjs} +9 -8
  95. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-CB2iQeWq.mjs} +27 -18
  96. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-CXX39F7o.mjs} +96 -47
  97. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  98. package/dist/offload-worker.d.mts +1 -46
  99. package/dist/offload-worker.mjs +197 -66
  100. package/dist/{ownership-DCtw_2IA.mjs → ownership-DEmM5vhh.mjs} +3 -3
  101. package/dist/{page-DRHy329N.mjs → page-CPaHeYqj.mjs} +7 -4
  102. package/dist/paths-BsJMoPP2.mjs +12 -0
  103. package/dist/paths-DQtTgsBf.mjs +42 -0
  104. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BqGbTa61.mjs} +5 -5
  105. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-Bwj-IjY1.mjs} +6 -6
  106. package/dist/{ports-DdSUicVo.mjs → ports-D-MmCTdv.mjs} +3 -3
  107. package/dist/prebuild-uD_ipCxF.mjs +449 -0
  108. package/dist/{project-_phNIJfs.mjs → project-BZNjmW_8.mjs} +65 -37
  109. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-Lfetn8Kr.mjs} +2 -2
  110. package/dist/pull-request-zjCSAryH.d.mts +120 -0
  111. package/dist/pull-requests.d.mts +1 -119
  112. package/dist/pull-requests.mjs +1 -1
  113. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-DuzH0cn3.mjs} +74 -48
  114. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-rhk4smwQ.mjs} +292 -15
  115. package/dist/react-native-doctor-CQpuIMso.mjs +234 -0
  116. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-Bhq1rJeV.mjs} +46 -28
  117. package/dist/{recordings-D0d5aQt0.mjs → recordings-DYteQSu4.mjs} +12 -9
  118. package/dist/{reload-C8JhxjSh.mjs → reload-CmTRFJaX.mjs} +93 -47
  119. package/dist/reload-DzjSl5P_.mjs +2 -0
  120. package/dist/{remote-BiR6aYjy.mjs → remote-ByYkXdGD.mjs} +15 -10
  121. package/dist/result-DNiS-tTP.mjs +434 -0
  122. package/dist/{run-BtPgpKks.mjs → run-D23HmJMs.mjs} +4 -5
  123. package/dist/selection-CSl9i5qU.mjs +619 -0
  124. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CxTrvDg8.mjs} +3 -4
  125. package/dist/{server-command-CTtCkmcQ.mjs → server-command-CtzloH3v.mjs} +14 -7
  126. package/dist/server-expo-C-90EhcG.mjs +2 -0
  127. package/dist/{server-expo-DsguMGUF.mjs → server-expo-DT_F_uVI.mjs} +50 -9
  128. package/dist/{settings-B717odTD.mjs → settings-CsJDEXgK.mjs} +234 -24
  129. package/dist/{settings-vk3mJGSm.d.mts → settings-DkdmlelE.d.mts} +6 -4
  130. package/dist/settings-T1gtc3bf.mjs +114 -0
  131. package/dist/settings-write-HyVZ8eQ8.mjs +359 -0
  132. package/dist/settings.schema.json +163 -16
  133. package/dist/{simslim-CCr3rE-A.mjs → simslim-Cgk17SXV.mjs} +14 -12
  134. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-DF8VfT64.mjs} +15 -20
  135. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  136. package/dist/stage-BIS0ydsV.mjs +183 -0
  137. package/dist/{start-BWqzODpb.mjs → start-7lpH7hmN.mjs} +63 -44
  138. package/dist/{start-TXeMmmO2.mjs → start-RChynRDp.mjs} +1 -1
  139. package/dist/{state-D1Icyjlu.mjs → state-C4ZtUisW.mjs} +40 -13
  140. package/dist/{state-CG_OFoaA.mjs → state-XMziexv2.mjs} +3 -2
  141. package/dist/{stats-BoY5sEPU.mjs → stats-53T7OTb9.mjs} +7 -13
  142. package/dist/stats-report-BFfMpWWF.mjs +16 -0
  143. package/dist/{status-WgFbkRzj.mjs → status-BL7jVyAB.mjs} +535 -447
  144. package/dist/status-CSi6tlRq.mjs +2 -0
  145. package/dist/{status-BTA7kKiQ.mjs → status-DqEUSSxs.mjs} +6 -4
  146. package/dist/{status-watch-C23ILtf9.mjs → status-watch-GDCfqpTE.mjs} +187 -22
  147. package/dist/status-worker.d.mts +1 -0
  148. package/dist/status-worker.mjs +19 -0
  149. package/dist/stim-desktop-C12we7lz.mjs +112 -0
  150. package/dist/{stop-DR6VoDIk.mjs → stop-Bk_1qiV6.mjs} +2 -2
  151. package/dist/{stop-BNmBMi1F.mjs → stop-CPzlM1L-.mjs} +138 -98
  152. package/dist/{stop-DPEhunlw.mjs → stop-D7h6jAXQ.mjs} +11 -10
  153. package/dist/supervisor-run.d.mts +8 -17
  154. package/dist/supervisor-run.mjs +63 -27
  155. package/dist/{support-DMTqj3Hm.mjs → support-67vraa1Q.mjs} +18 -11
  156. package/dist/{support-CwjbFs9H.mjs → support-Dlu37g6H.mjs} +12 -12
  157. package/dist/{swiftpm-macos-DRNVJWlb.mjs → swiftpm-macos-p8WZbxKU.mjs} +35 -24
  158. package/dist/toolchain-DhKwp9iI.mjs +2 -0
  159. package/dist/toolchain-Hp9sCpK4.mjs +873 -0
  160. package/dist/{trigger-CigAYjeL.mjs → trigger-BAahxUPq.mjs} +20 -5
  161. package/dist/trigger-Bf3uDcpv.mjs +2 -0
  162. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-BHX5r0Ei.mjs} +250 -156
  163. package/dist/{web-BDBMxDpx.mjs → web-CJmIj6AI.mjs} +18 -13
  164. package/dist/web-DknQETPs.mjs +2 -0
  165. package/dist/web-run.mjs +11 -12
  166. package/dist/windows-report.d.mts +1 -0
  167. package/dist/windows-report.mjs +18 -0
  168. package/dist/windows-report.ps1 +43 -0
  169. package/dist/workspace-process-lock-1_1OoVW5.mjs +57 -0
  170. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-Cjuigeeu.mjs} +62 -58
  171. package/dist/{workspaces-C36s2jb9.mjs → workspaces-BccMFmGQ.mjs} +1188 -1079
  172. package/dist/worktree-CK2MpJW5.mjs +2 -0
  173. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-DQ6Zi2Mv.mjs} +304 -53
  174. package/dist/xcode-Zlx3qjEs.mjs +896 -0
  175. package/package.json +7 -5
  176. package/shim/android-optimizations.gradle +7 -5
  177. package/dist/activity-BSV745Kz.mjs +0 -629
  178. package/dist/api-qvOzWyfO.mjs +0 -154
  179. package/dist/api-run.mjs +0 -294
  180. package/dist/app-install-BIKtMfPq.mjs +0 -896
  181. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  182. package/dist/budget-f7516Zk0.mjs +0 -4106
  183. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  184. package/dist/cancellation-C_22VQTH.mjs +0 -24
  185. package/dist/client-qQAaXSUs.mjs +0 -1771
  186. package/dist/config-BYDxlMY3.mjs +0 -562
  187. package/dist/device-DuiPJQSn.mjs +0 -290
  188. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  189. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  190. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  191. package/dist/exec-DqKo9GKJ.mjs +0 -268
  192. package/dist/git-DDfFzkMm.mjs +0 -45
  193. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  194. package/dist/logs-BGrEUaEs.mjs +0 -383
  195. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  196. package/dist/native-android-D5qc3-_v.mjs +0 -226
  197. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  198. package/dist/plan-C4TjdPsR.mjs +0 -260
  199. package/dist/prebuild-DYbucPXy.mjs +0 -212
  200. package/dist/preview-78a9kR_-.mjs +0 -1011
  201. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  202. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  203. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  204. package/dist/result-CaJg5Iat.mjs +0 -186
  205. package/dist/server-expo-Bigriskl.mjs +0 -2
  206. package/dist/settings-BORNaaCO.mjs +0 -402
  207. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  208. package/dist/stage-KNTQopqv.mjs +0 -157
  209. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  210. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  211. package/dist/toolchain-BFkAcstd.mjs +0 -2
  212. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  213. package/dist/trigger-9_USgmxz.mjs +0 -2
  214. package/dist/web-Dq-i3wzJ.mjs +0 -2
  215. package/dist/worktree-DpLdCHga.mjs +0 -2
  216. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  217. package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
package/README.md CHANGED
@@ -44,13 +44,24 @@ 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, a local and configured-provider miss can
48
+ reuse an exact completed artifact from an enabled paired build worker. Reuse
49
+ checks the full source, toolchain, SDK, architecture and target cache key and
50
+ verifies the downloaded archive. It needs no compilation slot. An explicit
51
+ local build and remote build mode off skip peer lookup; other project types
52
+ keep their existing cache paths. See `stim guide settings` for placement.
53
+
47
54
  ## Native Android build workers
48
55
 
49
56
  Native Gradle apps can use an approved build worker after declaring that
50
57
  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.
58
+ `stim guide lifecycle native-android` for `android.offloadInputs`, generated output ownership,
59
+ and supported input boundaries. Workers remain uncached. Local builds can opt
60
+ into APK caching through a separate complete `android.artifactInputs` declaration.
61
+ A configured cache provider with a `files` capability can share the verified APK
62
+ and its receipt between machines. Private input files and environment values
63
+ stay local; the declaration never authorizes their transfer. Gradle
64
+ keeps its own incremental and task caches in both cases.
54
65
 
55
66
  ## Programmatic API
56
67
 
@@ -80,16 +91,64 @@ already running server. `run` builds, installs and launches.
80
91
  `build({ platform: 'ios' })` returns a retained simulator app without starting
81
92
  a device or runtime; Android returns an APK and macOS returns an app bundle.
82
93
  Build-only preserves existing sessions and uses the same cache and build locks.
94
+ Successful builds include `result.facts.links.workspace`, an HTTPS workspace link
95
+ agents can share with an already-paired phone or Desktop, including when the
96
+ build machine has no Desktop app installed.
83
97
  Each result is a separate copy kept in the workspace until `stim worktree remove`.
84
98
  Run results preserve the CLI's launch evidence, including `'bundling'` and
85
99
  `'unverified'` results.
86
100
 
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
101
+ `reload({ platform?: 'ios' | 'android' | 'web', signal? })` requests a JavaScript
102
+ reload in a live app or reloads the owned Chrome page, returning the flat
103
+ `stim reload --json` facts. Select a platform when more than one is live.
104
+ Dispatch does not prove completion; verify the expected UI and inspect logs.
105
+ A Metro broadcast can reach other connected clients. Reload uses a 60 second
106
+ execution budget and 35 second cleanup budget, with the report timeout and
107
+ cleanup refusals described below. Cancellation stops pending work but cannot
108
+ retract a request already sent. Reload never retries automatically.
109
+
110
+ `setSetting(key, text, { scope?, signal? })` and `unsetSetting(key, { scope?, signal? })`
111
+ share the CLI's validation and return its JSON write result, including masked
112
+ sensitive values. Values use CLI text syntax, including JSON for arrays and
113
+ objects. Config lock waits and device-pool probes are asynchronous. Cancellation
114
+ prevents a pending write; a committed write finishes its recording cleanup
115
+ before settling. Recording changes serialize through cleanup within the home.
116
+
117
+ All operations run in the importing process. `settings()` and `stats()`
118
+ read the `stim settings --json` and `stim stats --json` payloads. All
119
+ use the client's own home and leave the caller's cwd, environment,
120
+ output, signal handlers and exit listeners as they were. The API and CLI call
89
121
  the same native lifecycle operations. Progress is silent unless `onProgress`
90
122
  is provided; its `message` is an output chunk. Operations accept `signal`.
91
- Cancellation waits for the worker to exit, and does not replace `stop()`.
123
+ Cancellation drains the operation's owned work, and does not replace `stop()`.
92
124
  Call cleanup with a fresh signal after cancellation or partial failure.
125
+ Cancelling `stop()` while it waits for another native operation ends that wait.
126
+ Once teardown starts, it finishes cleanup before rejecting with `STIM_CANCELLED`;
127
+ its config, workspace-state, and lease lock waits are asynchronous.
128
+
129
+ `doctor({ platform?, record? })` and `gc({ cache?, olderThan?, worktrees? })` read their CLI
130
+ JSON reports with a 60 second execution budget and optional `signal`. Doctor
131
+ never repairs; its `stim.runningPath` is null. By default it does not record a
132
+ check. Pass `record: true` to register the supported iOS/Android project and record
133
+ its checked platforms after the report and owned cleanup succeed. Recording waits
134
+ asynchronously for the config lock, honors `signal`, and rejects unavailable state.
135
+ GC never
136
+ deletes or shuts down idle devices. Reads can refresh their own usage caches
137
+ and existing pending remote approvals. An explicit `home` or `STIM_HOME` keeps
138
+ the CLI's scoped-home restrictions. Expiry rejects with `STIM_REPORT_TIMEOUT`
139
+ after owned cleanup; a caller abort rejects with
140
+ `STIM_CANCELLED`. Throwing from report progress also cancels the read.
141
+ If child identity cannot be verified after a one-second retry budget, cleanup
142
+ refuses with `STIM_CLAIM_UNAVAILABLE` instead of a cancellation or timeout
143
+ error. Child cleanup errors name the launcher PID; unverifiable processes and descendants
144
+ are left untouched. On POSIX, a launcher that exited before identity capture can only
145
+ finish successfully once its process group is proven gone.
146
+ After a termination request, cleanup waits at most one second for a child to
147
+ close. Overall cleanup has a 35 second budget, including temporary-worktree
148
+ removal; unfinished cleanup returns `STIM_CLAIM_UNAVAILABLE` and leaves
149
+ unresolved resources in place. Credential refresh waits asynchronously and
150
+ checks cancellation before writing.
151
+ On Windows, report probes require the built-in Windows PowerShell for process-tree containment.
93
152
 
94
153
  `home` and `buildCache` accept absolute paths. Omit them to use normal Stim
95
154
  settings. A cache used by concurrent writers needs the same coordinating Stim
@@ -98,8 +157,29 @@ Ownership checks and cache locks remain active. `stop()` acts on this workspace,
98
157
  including resources from earlier runs, so use a dedicated workspace in CI.
99
158
 
100
159
  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.
160
+ `details`. An exception thrown by `onProgress` stops further progress and is
161
+ propagated unchanged: `build()` or `run()` is cancelled, and
162
+ `stop()` or read finishes its work first.
163
+ `logs({ tail, sources, minLevel, slot, since, grep, errorsOnly })` reads the same
164
+ merged records as `stim logs --json`, including crash capture and agent actions.
165
+ Pass `tail` to bound the returned records. `followLogs(options, onRecord)` emits
166
+ that backfill and new records, then returns a stop function; aborting its signal
167
+ also stops it. An optional third callback receives initial records instead of
168
+ `onRecord`; its promise is awaited before the next batch. With that callback and
169
+ no `tail`, timeline batches hold at most 500 records. Agent attribution still
170
+ retains its matching records during backfill. These reads run in process and yield between log chunks.
171
+ Local follow uses filesystem hints with a ten-second repair scan. While a
172
+ directory watch is unavailable, it retries and scans every 500 ms; Expo error
173
+ context uses a timer only while pending. Agent-action and active hosted log
174
+ sampling are unchanged.
175
+ Attachment schedules one 500 ms recovery scan. A moved directory on Windows can
176
+ require the ten-second repair scan.
177
+ Hosted targets join and leave the follow stream from local state notifications;
178
+ missed notifications are reconciled about every 10 seconds. Active hosts still
179
+ serve bounded log queries.
180
+ Tail selection bounds matching timeline and agent records; agent attribution
181
+ still reads each retained session generation to establish device ownership.
182
+
103
183
  `diagnostics()` returns the workspace log directory and up to 200 local records,
104
184
  even if no run has succeeded. It does not fetch remote logs or capture new crashes.
105
185
  See [the API reference](https://stim.appandflow.com/docs/programmatic-api) or
@@ -0,0 +1,153 @@
1
+ import { I as waitForSharedBuild } from "./activity-BzVfHSrY.mjs";
2
+ import { rmSync } from "node:fs";
3
+ //#region src/engine/artifact-lifecycle.ts
4
+ async function runArtifactLifecycle(phases) {
5
+ try {
6
+ const resolved = await phases.resolve();
7
+ if (resolved.kind === "ready") return resolved.artifact;
8
+ const cached = resolved.kind === "cached" ? resolved.artifact : await phases.claim?.() ?? null;
9
+ if (cached !== null) {
10
+ const reused = await phases.reuse(cached);
11
+ if (reused !== null) return reused;
12
+ }
13
+ const { build } = phases;
14
+ const placement = await build.placement?.select() ?? null;
15
+ if (placement === null) await build.admit();
16
+ const preparation = await build.prepare();
17
+ const late = await build.revalidate(preparation);
18
+ if (late !== null) return late.ready;
19
+ if (build.placement && placement !== null) {
20
+ const offloaded = await build.placement.acquire(placement, preparation);
21
+ if (offloaded !== null) return offloaded.ready;
22
+ await build.admit();
23
+ }
24
+ const artifact = await build.compile(placement, preparation);
25
+ if (await build.validate(preparation) === "cacheable") await build.store(artifact);
26
+ return build.finish ? await build.finish(artifact) : artifact;
27
+ } finally {
28
+ phases.release();
29
+ }
30
+ }
31
+ //#endregion
32
+ //#region src/engine/cleanup-scope.ts
33
+ function drain(pending, report) {
34
+ const kept = [];
35
+ for (const cleanup of pending.toReversed()) try {
36
+ cleanup();
37
+ } catch (error) {
38
+ kept.unshift(cleanup);
39
+ report(error);
40
+ }
41
+ return kept;
42
+ }
43
+ function createCleanupScope(report) {
44
+ let pending = [];
45
+ return {
46
+ defer: (cleanup) => {
47
+ pending.push(cleanup);
48
+ return () => {
49
+ pending = pending.filter((entry) => entry !== cleanup);
50
+ };
51
+ },
52
+ transfer: () => {
53
+ let handed = pending;
54
+ pending = [];
55
+ return () => {
56
+ handed = drain(handed, report);
57
+ };
58
+ },
59
+ release: () => {
60
+ pending = drain(pending, report);
61
+ }
62
+ };
63
+ }
64
+ //#endregion
65
+ //#region src/engine/acquire-artifact.ts
66
+ async function acquireArtifact(adapter, { root, logFile, deps }) {
67
+ const owned = createCleanupScope((error) => adapter.temporaryReleaseFailed(error));
68
+ let closeOffload = null;
69
+ let buildLock = null;
70
+ let buildSlot = null;
71
+ const releaseLock = () => {
72
+ if (!buildLock) return;
73
+ const held = buildLock;
74
+ buildLock = null;
75
+ try {
76
+ deps.releaseBuildLock(held);
77
+ } catch (error) {
78
+ adapter.releaseFailed(`the build lock at ${held.path}`, error);
79
+ }
80
+ };
81
+ const releaseSlot = () => {
82
+ if (!buildSlot) return;
83
+ const held = buildSlot;
84
+ buildSlot = null;
85
+ try {
86
+ deps.releaseBuildSlot(held);
87
+ } catch (error) {
88
+ adapter.releaseFailed("the build slot", error);
89
+ }
90
+ };
91
+ const run = {
92
+ own: (directory) => owned.defer(() => rmSync(directory, {
93
+ recursive: true,
94
+ force: true
95
+ })),
96
+ openOffload: (close) => {
97
+ closeOffload = close;
98
+ },
99
+ claimSharedBuild: async (options) => {
100
+ const shared = await waitForSharedBuild({
101
+ ...options,
102
+ platform: adapter.platform,
103
+ root,
104
+ logFile,
105
+ command: adapter.command,
106
+ acquire: deps.acquireBuildLock,
107
+ wait: deps.waitForBuild,
108
+ now: deps.now
109
+ });
110
+ if (!shared.refusal) buildLock = shared.lock;
111
+ return shared;
112
+ },
113
+ takeBuildSlot: async (options) => {
114
+ buildSlot = await deps.acquireBuildSlot({
115
+ ...options,
116
+ root,
117
+ logFile
118
+ });
119
+ return buildSlot;
120
+ }
121
+ };
122
+ try {
123
+ return {
124
+ ok: true,
125
+ artifact: await runArtifactLifecycle({
126
+ ...adapter.lifecycle(run),
127
+ release: () => {
128
+ const close = closeOffload;
129
+ closeOffload = null;
130
+ try {
131
+ close?.();
132
+ } finally {
133
+ releaseLock();
134
+ releaseSlot();
135
+ }
136
+ }
137
+ }),
138
+ release: owned.transfer()
139
+ };
140
+ } catch (error) {
141
+ await adapter.settleFailed?.();
142
+ const failure = adapter.refuse(error);
143
+ if (failure === null) throw error;
144
+ return {
145
+ ok: false,
146
+ failure
147
+ };
148
+ } finally {
149
+ owned.release();
150
+ }
151
+ }
152
+ //#endregion
153
+ export { acquireArtifact as t };