stim 1.21.0 → 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 (184) hide show
  1. package/README.md +60 -7
  2. package/dist/{acquire-artifact-CD4lbiWE.mjs → acquire-artifact-Co2k4f7O.mjs} +21 -3
  3. package/dist/{act-DHAw2A2S.mjs → act-DsuqEkiM.mjs} +298 -164
  4. package/dist/{activity-BzVfHSrY.mjs → activity-CMLmzp7o.mjs} +33 -12
  5. package/dist/{agent-device-usage-output-zh1vhbLp.mjs → agent-device-usage-output-DUFaTMdd.mjs} +7 -7
  6. package/dist/{android-BLgbNqox.mjs → android-ByRMUoiJ.mjs} +66 -52
  7. package/dist/{android-DUYkNF4u.mjs → android-C7sVmyI9.mjs} +160 -59
  8. package/dist/{android-CV_GCELZ.mjs → android-DGkNqa_c.mjs} +5 -5
  9. package/dist/{android-BEJ8Jpl7.mjs → android-DR5lZ2Az.mjs} +2 -2
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/{android-cas-Ct5b1xCK.mjs → android-cas-ngferVq2.mjs} +3 -3
  12. package/dist/{client-B7QVOlCr.d.mts → android-project-DVWyCbWU.d.mts} +145 -7
  13. package/dist/api.d.mts +132 -118
  14. package/dist/api.mjs +239 -42
  15. package/dist/{artifact-B8T3S5gi.mjs → artifact-8EY8SAPw.mjs} +40 -35
  16. package/dist/{artifact-DAuZ-FNU.mjs → artifact-DJPy518Y.mjs} +69 -40
  17. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  18. package/dist/{browser-web-QQzVjz3O.mjs → browser-web-Bcv99PBM.mjs} +187 -59
  19. package/dist/{budget-Bs6SxxzO.mjs → budget-Cvwn54qV.mjs} +830 -699
  20. package/dist/{build-CoPzQRNw.mjs → build-CabC3G23.mjs} +34 -27
  21. package/dist/{build-cache-DmyR9Zzc.mjs → build-cache-Dv7RN200.mjs} +4 -4
  22. package/dist/{build-plan-CaFskB7_.mjs → build-plan-DUC8Ka9y.mjs} +74 -14
  23. package/dist/{cache-manifest-DkkqguoK.mjs → cache-manifest-DSeQjt-Q.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{ccache-BJRZ9pG3.mjs → ccache-Btwc36-I.mjs} +6 -6
  26. package/dist/{cdp-CWmIUMbw.mjs → cdp-3fwICjzi.mjs} +1 -1
  27. package/dist/{chrome-B6tfCta1.mjs → chrome-Bbw689-6.mjs} +1 -1
  28. package/dist/{cli-0DYf8QhQ.mjs → cli-CHZa9Lvk.mjs} +20 -20
  29. package/dist/cli.mjs +1 -1
  30. package/dist/{client-UXD70ZbM.mjs → client-OyRoEuSr.mjs} +218 -47
  31. package/dist/collector-run.d.mts +1 -1
  32. package/dist/collector-run.mjs +6 -6
  33. package/dist/{command-output-B1UrjZHL.mjs → command-output-gwpm28fu.mjs} +1 -1
  34. package/dist/{config-CYcBF478.mjs → config-DlrsduwG.mjs} +17 -11
  35. package/dist/{created-devices-CqeBlrEn.mjs → created-devices-x9rN6bhs.mjs} +13 -3
  36. package/dist/{dependency-state-BbKQW83h.mjs → dependency-state-1I9KZT1Y.mjs} +2 -2
  37. package/dist/{detached-entry-DFRyG1_o.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
  38. package/dist/{dev-client-UOeESKm6.mjs → dev-client-BSDR5h3F.mjs} +2 -2
  39. package/dist/{device-ExJq8Ei7.mjs → device-B-L3Fbxy.mjs} +71 -14
  40. package/dist/{device-DCxH7_By.mjs → device-DklWZLqb.mjs} +16 -16
  41. package/dist/{device-capacity-CMlqEcvw.mjs → device-capacity-DK5_EwRS.mjs} +9 -10
  42. package/dist/device-host-worker.mjs +25 -32
  43. package/dist/{device-ios-DRUeKaFV.mjs → device-ios-DoB6KFCO.mjs} +39 -16
  44. package/dist/{device-lease-run-C8raGFoP.mjs → device-lease-run-xJPQ_QQG.mjs} +5 -5
  45. package/dist/{device-pool-DMRpVX9a.mjs → device-pool-BMkdsefq.mjs} +3 -3
  46. package/dist/{doctor-DTvaDOda.mjs → doctor-Bo7BXLux.mjs} +24 -37
  47. package/dist/{doctor-Dhqebm0q.mjs → doctor-D5_EzwfA.mjs} +19 -16
  48. package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
  49. package/dist/doctor-fingerprint.mjs +1 -1
  50. package/dist/{doctor-BLHCYxzi.mjs → doctor-thjWAV0z.mjs} +1 -1
  51. package/dist/{doctor-watchman-Cv1F10Kj.mjs → doctor-watchman-N2wDotwQ.mjs} +5 -5
  52. package/dist/{eas-build-BomfRnFT.mjs → eas-build-CwknaQYj.mjs} +4 -4
  53. package/dist/{eas-fallback-DJwZpy0c.mjs → eas-fallback-CSgAulr5.mjs} +27 -18
  54. package/dist/{eas-session-ledger-op6A54yi.mjs → eas-session-ledger-DlY_serQ.mjs} +8 -7
  55. package/dist/{error-diagnostics-Bf0rZvG9.mjs → error-diagnostics-DBWO2rxE.mjs} +10 -10
  56. package/dist/{exec-_UbtCQcG.mjs → exec-DEoAhcze.mjs} +155 -47
  57. package/dist/{exec-H20xSg2T.d.mts → exec-DnYc4HGH.d.mts} +17 -4
  58. package/dist/{gc-_-dCXdyL.mjs → gc-CXxN-4SE.mjs} +587 -313
  59. package/dist/gc-DnNDQyaP.mjs +3 -0
  60. package/dist/{guide-Yqwt2bd6.mjs → guide-Br0LEfKy.mjs} +239 -43
  61. package/dist/{hosted-android-Bw-honsd.mjs → hosted-android-B-9f-jkd.mjs} +6 -6
  62. package/dist/{hosted-client-DB_gBPfY.mjs → hosted-client-DZAPrcro.mjs} +4 -4
  63. package/dist/{hosted-ios-CUvOf4Vr.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
  64. package/dist/{hosted-logs-DL_P5AdN.mjs → hosted-logs-FIRx9X2f.mjs} +5 -5
  65. package/dist/{hosted-macos-QI141yKk.mjs → hosted-macos-_awYSpfv.mjs} +21 -12
  66. package/dist/{hosted-native-Ksyjgzq-.mjs → hosted-native-BdzE668-.mjs} +27 -14
  67. package/dist/{idle-BVeRGroT.d.mts → idle-C4cZ757K.d.mts} +3 -3
  68. package/dist/{idle-shutdown-DaKmZi0z.mjs → idle-shutdown-DDg3SdvY.mjs} +7 -7
  69. package/dist/ios-CDvlmUs7.d.mts +24 -0
  70. package/dist/{ios-CQ68hG9s.mjs → ios-Ds1clbIt.mjs} +8 -8
  71. package/dist/{ios-device-CwFMehUS.mjs → ios-device--h_-8ENa.mjs} +3 -3
  72. package/dist/{ios-device-CXGP1bsD.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  73. package/dist/{ios-CpByZy12.mjs → ios-hcBpnEGk.mjs} +81 -34
  74. package/dist/{ios-ubFsBzwq.mjs → ios-pm4nL6By.mjs} +59 -50
  75. package/dist/{ios-project-WuwwBdvW.mjs → ios-project-CZhKODF3.mjs} +5 -5
  76. package/dist/{ios-signing-DTTIChGs.mjs → ios-signing-BtAffm0A.mjs} +2 -2
  77. package/dist/{ios-state-DvFX-K_l.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  78. package/dist/{ios-qNJt4dFm.mjs → ios-xtlRHaeB.mjs} +1 -1
  79. package/dist/{js-swap-Cc1dttps.mjs → js-swap-Bwhh4S7V.mjs} +7 -29
  80. package/dist/{launch-Zq2mOSDy.mjs → launch-BjxemNpK.mjs} +40 -39
  81. package/dist/{launch-CD1yVc7U.mjs → launch-CCzXlc8r.mjs} +16 -16
  82. package/dist/{logs-BS00Anxf.mjs → logs-BfwwadsZ.mjs} +151 -24
  83. package/dist/{logs-CMm05HxN.mjs → logs-jTS_lHSo.mjs} +10 -17
  84. package/dist/{macos-B65--pPd.mjs → macos-DVlSSyUg.mjs} +1 -1
  85. package/dist/{macos-C-0qJ6zq.mjs → macos-NfV2D7dO.mjs} +143 -46
  86. package/dist/macos-run.mjs +1 -1
  87. package/dist/maintenance-run.mjs +8 -8
  88. package/dist/{metro-DEXpIhHC.mjs → metro-DiXtA3Ty.mjs} +59 -37
  89. package/dist/{metro-gateway-BMJNlj3E.mjs → metro-gateway-CKZqKqx7.mjs} +120 -22
  90. package/dist/{named-ports-BWTzt6mu.mjs → named-ports-DkEzOfzO.mjs} +40 -33
  91. package/dist/{native-android-JACyjTZs.mjs → native-android-CqgnOgsT.mjs} +43 -242
  92. package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
  93. package/dist/{native-gradle-inputs-Bep9JcSF.mjs → native-gradle-inputs-Dnh84Zbd.mjs} +3 -129
  94. package/dist/{native-run-DY_RLx3C.mjs → native-run-NwUuxbkg.mjs} +4 -5
  95. package/dist/{native-runtime-Dg1Q7tfF.mjs → native-runtime-B7KIafpM.mjs} +8 -7
  96. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  97. package/dist/{native-xcode-inputs-CB2iQeWq.mjs → native-xcode-inputs-D_VOfFL7.mjs} +2 -3
  98. package/dist/{native-xcode-ios-CXX39F7o.mjs → native-xcode-ios-BYDOHWLN.mjs} +27 -32
  99. package/dist/offload-worker.d.mts +65 -2
  100. package/dist/offload-worker.mjs +305 -73
  101. package/dist/operation-exec-BW0em61G.mjs +171 -0
  102. package/dist/{ownership-DEmM5vhh.mjs → ownership-C5fo5Edb.mjs} +3 -3
  103. package/dist/{page-CPaHeYqj.mjs → page-DBL2PiUU.mjs} +8 -4
  104. package/dist/{placement-log-BqGbTa61.mjs → placement-log-BnGgJRRZ.mjs} +1 -1
  105. package/dist/{plan-placement-Bwj-IjY1.mjs → plan-placement-DIsMtN-d.mjs} +12 -8
  106. package/dist/{ports-D-MmCTdv.mjs → ports-Cy1RkmuQ.mjs} +3 -3
  107. package/dist/{prebuild-uD_ipCxF.mjs → prebuild-D4JoEAEs.mjs} +49 -14
  108. package/dist/{project-BZNjmW_8.mjs → project-wM_XFTvE.mjs} +16 -16
  109. package/dist/{pull-request-Lfetn8Kr.mjs → pull-request-W1IuLXDt.mjs} +102 -20
  110. package/dist/{pull-request-zjCSAryH.d.mts → pull-request-eODyIqZF.d.mts} +6 -2
  111. package/dist/pull-requests.d.mts +2 -2
  112. package/dist/pull-requests.mjs +2 -2
  113. package/dist/{react-native-android-DuzH0cn3.mjs → react-native-android-6OZ7MSM7.mjs} +71 -48
  114. package/dist/{react-native-build-rhk4smwQ.mjs → react-native-build-Dvd8hC21.mjs} +8 -8
  115. package/dist/{react-native-doctor-CQpuIMso.mjs → react-native-doctor-DsoSF1Y9.mjs} +7 -7
  116. package/dist/{react-native-ios-Bhq1rJeV.mjs → react-native-ios-4u1Rn-GR.mjs} +40 -26
  117. package/dist/{recordings-DYteQSu4.mjs → recordings-CQmfzAh7.mjs} +1 -1
  118. package/dist/registration-BcRgF6Ox.mjs +51 -0
  119. package/dist/{reload-CmTRFJaX.mjs → reload-BzkYabB-.mjs} +16 -15
  120. package/dist/{reload-DzjSl5P_.mjs → reload-D7AVlb8N.mjs} +1 -1
  121. package/dist/{remote-ByYkXdGD.mjs → remote-DjGDmlTZ.mjs} +18 -15
  122. package/dist/{result-DNiS-tTP.mjs → result-D2Ykz_iD.mjs} +24 -23
  123. package/dist/{run-D23HmJMs.mjs → run-DidHghD1.mjs} +3 -2
  124. package/dist/{selection-CSl9i5qU.mjs → selection-DSMbWEX2.mjs} +6 -5
  125. package/dist/{server-bare-CxTrvDg8.mjs → server-bare-CafzuyFB.mjs} +2 -2
  126. package/dist/{server-command-CtzloH3v.mjs → server-command-C6QjeupS.mjs} +5 -5
  127. package/dist/{server-expo-DT_F_uVI.mjs → server-expo-CrjB29pq.mjs} +7 -5
  128. package/dist/server-expo-D58c9L0M.mjs +2 -0
  129. package/dist/{settings-CsJDEXgK.mjs → settings-C7O8A6ZI.mjs} +223 -243
  130. package/dist/{settings-T1gtc3bf.mjs → settings-DpR-1Wnn.mjs} +1 -1
  131. package/dist/{settings-write-HyVZ8eQ8.mjs → settings-write-CzD60rOD.mjs} +7 -6
  132. package/dist/settings.schema.json +13 -0
  133. package/dist/{simslim-Cgk17SXV.mjs → simslim-BNckWpXi.mjs} +2 -2
  134. package/dist/{slot-launch-DF8VfT64.mjs → slot-launch-CbfmNgM6.mjs} +6 -6
  135. package/dist/{stage-BIS0ydsV.mjs → stage-Bps5oius.mjs} +21 -4
  136. package/dist/{start-RChynRDp.mjs → start-Br-oxqMD.mjs} +1 -1
  137. package/dist/{start-7lpH7hmN.mjs → start-EojN4WFz.mjs} +622 -393
  138. package/dist/{state-C4ZtUisW.mjs → state--smjFSTL.mjs} +22 -7
  139. package/dist/{state-XMziexv2.mjs → state-08I3hw3_.mjs} +2 -2
  140. package/dist/{stats-53T7OTb9.mjs → stats-D3GerlFW.mjs} +5 -5
  141. package/dist/{stats-report-BFfMpWWF.mjs → stats-report-BzaPrRm6.mjs} +1 -1
  142. package/dist/{status-DqEUSSxs.mjs → status-BRROykC8.mjs} +2 -2
  143. package/dist/{status-CSi6tlRq.mjs → status-EvrK72L2.mjs} +1 -1
  144. package/dist/{status-BL7jVyAB.mjs → status-WBDajew2.mjs} +43 -29
  145. package/dist/{status-watch-GDCfqpTE.mjs → status-watch-Bg_u-pwR.mjs} +48 -16
  146. package/dist/status-worker.mjs +1 -1
  147. package/dist/{stim-desktop-C12we7lz.mjs → stim-desktop-D5OGpYZM.mjs} +2 -2
  148. package/dist/{stop-Bk_1qiV6.mjs → stop-DTZ9uTw3.mjs} +2 -2
  149. package/dist/{stop-D7h6jAXQ.mjs → stop-Dky10AEJ.mjs} +31 -22
  150. package/dist/{stop-CPzlM1L-.mjs → stop-Mv6W9FAk.mjs} +15 -16
  151. package/dist/supervisor-run.d.mts +3 -3
  152. package/dist/supervisor-run.mjs +28 -36
  153. package/dist/{support-Dlu37g6H.mjs → support-CNioewsd.mjs} +10 -10
  154. package/dist/{support-67vraa1Q.mjs → support-yUiOjnVY.mjs} +8 -8
  155. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  156. package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
  157. package/dist/toolchain-BY8X8HXx.mjs +2 -0
  158. package/dist/{toolchain-Hp9sCpK4.mjs → toolchain-DpJMHq0n.mjs} +9 -6
  159. package/dist/{trigger-BAahxUPq.mjs → trigger-Cbyc41d_.mjs} +3 -3
  160. package/dist/trigger-yb_nFzPF.mjs +2 -0
  161. package/dist/{warm-progress-BHX5r0Ei.mjs → warm-progress-CA3TgT3-.mjs} +29 -16
  162. package/dist/web-CZ07gd77.mjs +2 -0
  163. package/dist/{web-CJmIj6AI.mjs → web-DKx6yoFA.mjs} +11 -10
  164. package/dist/web-run.mjs +11 -9
  165. package/dist/windows-report.mjs +1 -1
  166. package/dist/{workspace-state-Cjuigeeu.mjs → workspace-state-U08dEzhG.mjs} +3 -3
  167. package/dist/{workspaces-BccMFmGQ.mjs → workspaces-CpANmBlq.mjs} +594 -266
  168. package/dist/{worktree-DQ6Zi2Mv.mjs → worktree-CHecZ4Oq.mjs} +850 -551
  169. package/dist/worktree-ZqZVjD9K.mjs +2 -0
  170. package/dist/{xcode-Zlx3qjEs.mjs → xcode-BXn9-xYx.mjs} +5 -5
  171. package/package.json +7 -7
  172. package/shim/android-audio/Main.java +24 -0
  173. package/shim/android-audio/README.md +17 -0
  174. package/shim/android-audio.jar +0 -0
  175. package/dist/gc-C-WwL0yi.mjs +0 -3
  176. package/dist/git-C3iTsJaZ.mjs +0 -73
  177. package/dist/server-expo-C-90EhcG.mjs +0 -2
  178. package/dist/settings-DkdmlelE.d.mts +0 -15
  179. package/dist/swiftpm-macos-p8WZbxKU.mjs +0 -130
  180. package/dist/toolchain-DhKwp9iI.mjs +0 -2
  181. package/dist/trigger-Bf3uDcpv.mjs +0 -2
  182. package/dist/web-DknQETPs.mjs +0 -2
  183. package/dist/workspace-process-lock-1_1OoVW5.mjs +0 -57
  184. package/dist/worktree-CK2MpJW5.mjs +0 -2
@@ -0,0 +1,3 @@
1
+ import { Ct as describeParkedSims, Dt as findOrphanedDevices, Ot as findStaleDeviceRecords, it as selectCaches, kt as findStaleProjectDevices, wt as describeUnverifiableDevices, xt as deleteParkedSims } from "./budget-Cvwn54qV.mjs";
2
+ import { a as runGc, i as readGcReport, n as executeGc, o as withGcMaintenanceClaim, r as gcCommand, s as formatGcReport, t as collectGcReport } from "./gc-CXxN-4SE.mjs";
3
+ export { collectGcReport, gcCommand as default, deleteParkedSims, describeParkedSims, describeUnverifiableDevices, executeGc, findOrphanedDevices, findStaleDeviceRecords, findStaleProjectDevices, formatGcReport, readGcReport, runGc, selectCaches, withGcMaintenanceClaim };
@@ -1,8 +1,8 @@
1
- import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-CsJDEXgK.mjs";
2
- import { i as findProjectRoot$1 } from "./project-BZNjmW_8.mjs";
3
- import { h as RECENT_LAUNCH_MS } from "./eas-session-ledger-op6A54yi.mjs";
4
- import { o as guideStatus, t as WATCHMAN_NESTED_WORKTREES } from "./doctor-watchman-Cv1F10Kj.mjs";
5
- import "./status-watch-GDCfqpTE.mjs";
1
+ import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-C7O8A6ZI.mjs";
2
+ import { i as findProjectRoot$1 } from "./project-wM_XFTvE.mjs";
3
+ import { h as RECENT_LAUNCH_MS } from "./eas-session-ledger-DlY_serQ.mjs";
4
+ import { o as guideStatus, t as WATCHMAN_NESTED_WORKTREES } from "./doctor-watchman-N2wDotwQ.mjs";
5
+ import "./status-watch-Bg_u-pwR.mjs";
6
6
  import { SETTINGS, SETTINGS_SCHEMA_URL, TUTORIAL_VERSION } from "@stim-cli/core/state";
7
7
  import chalk from "chalk";
8
8
  //#region src/guide/agent.ts
@@ -418,7 +418,7 @@ FULL TOPIC LIST
418
418
  //#endregion
419
419
  //#region src/guide/api.ts
420
420
  var api_default = {
421
- summary: "Typed lifecycle API: createStim, build, run, reload, stop, diagnostics, doctor, GC reports, settings, stats, logs, and cancellation",
421
+ summary: "Typed lifecycle API: createStim, build, run, reload, stop, warmWorktree, removeWorktree, diagnostics, doctor, GC, settings, stats, logs, and cancellation",
422
422
  body: () => `PROGRAMMATIC API
423
423
 
424
424
  Install stim as a project dependency: npm install --save-dev stim.
@@ -445,6 +445,8 @@ STIM_HOME from env, else the default home. All operations run in the calling
445
445
  process against the client's home and project and call the same lifecycle
446
446
  operations as the CLI. None parses CLI arguments or changes the caller's
447
447
  cwd/environment.
448
+ Custom Expo buildCacheProvider modules are not supported. Use EAS or a Stim
449
+ cache provider.
448
450
 
449
451
  settings() returns the stim settings --json payload: every setting with its
450
452
  effective value, origin and per-layer values. An invalid environment override
@@ -461,6 +463,15 @@ Later registry changes do not redirect the write or its returned setting.
461
463
  Pending writes cancel. After commit, recording deletion finishes before the
462
464
  promise settles, including when cancellation arrives during cleanup.
463
465
 
466
+ plan({ platform, slot?, signal? }) returns the configured ios/android/macos next-build
467
+ report, matching --plan --json, without building, launching or taking a device.
468
+ slot applies to ios/android. A predicted build refusal stays in the report;
469
+ a failure to produce a report rejects with StimError. Fingerprinting uses the
470
+ existing cancellable report helper. Native probes and cache downloads drain
471
+ before the report settles. Plans use the report budgets below. Providers must settle on abort;
472
+ cleanup exceeding 35 seconds refuses with STIM_CLAIM_UNAVAILABLE and retains
473
+ the download directory rather than deleting files a provider may still write.
474
+
464
475
  doctor({ platform? }) and gc({ cache?, olderThan?, worktrees? }) read reports in
465
476
  process with a 60 second execution budget. They accept signal and attempt
466
477
  owned cleanup before rejecting. Deadline expiry rejects with
@@ -478,6 +489,57 @@ resources in place. Credential refresh waits asynchronously and checks
478
489
  cancellation before writing.
479
490
  On Windows, report probes require the built-in Windows PowerShell for process-tree containment.
480
491
 
492
+ requestMachineAccess({ ticket?, signal? }) requests build and device-host access
493
+ from configured remote machines without granting capabilities or repairing project
494
+ state. It returns the iOS doctor report and records the completed project check
495
+ after owned cleanup. A supplied ticket encodes 32 random bytes; omitting it
496
+ generates or reuses a pending ticket instead of inheriting the process environment.
497
+ A person approves each capability on the worker. Execution has a 120 second
498
+ budget and cleanup uses the report's 35 second budget. Desktop requests access
499
+ only through its matching-home bundled server's private desktop-machine-access
500
+ subscription; cancellation waits for cleanup and reconnect never repeats it.
501
+
502
+ warmWorktree({ signal?, beforeWarm? }) copies missing ignored state from the source
503
+ checkout into the client's linked worktree in process. It returns { exitCode },
504
+ 0 or 1, without changing process.exitCode. Existing entries and tracked paths
505
+ remain untouched. Copies share a source read claim and hold an exclusive target
506
+ claim. beforeWarm(workspace) admits each canonical workspace in the resolved
507
+ warming scope before registration or copying; throwing refuses warming.
508
+ Progress uses onProgress. Cancellation drains the copy child before removing
509
+ its partial entry or releasing claims. Unknown cleanup retains those claims
510
+ and returns STIM_CLAIM_UNAVAILABLE with exact recovery paths. The execution
511
+ budget is 90 minutes; cleanup still has the 35 second budget above. The API
512
+ does not refresh the source or install dependencies; use CLI worktree warm
513
+ --refresh for that.
514
+
515
+ removeWorktree({ target?, force?, signal?, beforeRemove? }) runs the CLI's worktree removal
516
+ safety checks and cleanup in process. target defaults to projectRoot; relative
517
+ paths resolve against it. It returns { removed, exitCode } without changing
518
+ process.exitCode. removed is true once a linked Git worktree is deleted, even
519
+ if later branch cleanup fails. Source checkout environment cleanup can succeed
520
+ with removed: false and exitCode: 0. force has the same destructive meaning as
521
+ CLI --force. Cancellation stops pending work and waits for owned cleanup;
522
+ completed actions remain applied. It uses the report budgets above.
523
+ beforeRemove(workspace) runs for every canonical workspace in the resolved
524
+ cleanup scope before effects, including registered descendants and pending
525
+ branch cleanup. Throwing refuses the operation.
526
+
527
+ gc() stays read-only. collectGarbage({ cache?, olderThan?, worktrees?, delete?,
528
+ idleMs?, signal? }) runs the same GC selections and actions as the CLI, including
529
+ an unscoped sweep. It returns { report, exitCode }; exitCode is 0 or 1 and does
530
+ not change process.exitCode. delete: true enables deletion. idleMs reclaims
531
+ owned devices idle for that many milliseconds, including without delete.
532
+ The existing CLI rules for cache selection, workspace safety and scoped homes apply.
533
+
534
+ A deletion or idle sweep takes this home's exclusive maintenance claim;
535
+ concurrent maintenance rejects with STIM_CLAIM_REFUSED and names the held claim.
536
+ Execution and cleanup use the report budgets above. Cancellation stops pending
537
+ lock waits and further actions; completed actions remain applied. An archive
538
+ whose history has started moving finishes publication before cancellation.
539
+ Unresolved owned cleanup rejects with STIM_CLAIM_UNAVAILABLE and retains its
540
+ actual ownership claims for recovery. Progress uses onProgress; GC does not
541
+ replace the caller's console methods.
542
+
481
543
  doctor returns the doctor --json findings and metadata, with runningPath null
482
544
  because the caller imports the library rather than executing a Stim CLI. It
483
545
  never repairs the project. By default it does not record a check; record: true
@@ -510,11 +572,20 @@ Expo context uses a settle timer only while an error is pending. The separate
510
572
  agent-action cursor and active hosted log queries keep their current sampling.
511
573
 
512
574
  run takes platform plus its options:
513
- ios: configuration, scheme, deviceType, runtime
575
+ ios: configuration, scheme, deviceType, runtime, simulatorApp
514
576
  android: variant, systemImage, deviceProfile
515
- macos: remoteBuild
577
+ macos: remoteBuild, remote
516
578
  web: headed (default false)
517
- iOS and Android also accept slot, metroCheck, buildCache, and remoteBuild.
579
+ iOS and Android also accept slot, metroCheck, buildCache, remoteBuild, remote,
580
+ device, wait and easProfile. device: true auto-selects a physical device; a
581
+ string pins its UDID or serial. wait takes seconds as a string, such as '30'.
582
+ wait: false refuses a full owned-device slot immediately; on a physical device
583
+ it bypasses another workspace's lease and can replace its running app, as CLI
584
+ --no-wait does. easProfile downloads an existing compatible development build;
585
+ it never starts an EAS build. iOS simulatorApp selects the simulator viewer.
586
+ remote selects the launch host using the CLI's existing placement and approval
587
+ rules; remoteBuild independently selects where compilation runs. macOS requires
588
+ a named hosting Mac; auto, eas and proxy are not supported there.
518
589
  All methods accept signal. run builds, installs and launches.
519
590
  Web requires a running server, just like stim web.
520
591
 
@@ -543,12 +614,33 @@ writes its own build-artifact-<platform>.ndjson. No distribution archive or web
543
614
  pipeline is inferred. Use @stim-cli/ci's buildCI to export a portable artifact and
544
615
  diagnostics for your CI provider.
545
616
 
617
+ Unresolved native Metro cleanup keeps error.details.cause.retainedClaimRoots and
618
+ STIM_CLAIM_UNAVAILABLE even after cancellation. Web cancellation stops pending
619
+ browser-lock and verification waits. A new browser launch is accounted for and
620
+ stopped before cancellation finishes, or refuses with retained ownership when
621
+ cleanup cannot be confirmed.
622
+
546
623
  run returns { platform, facts }. iOS facts include udid; Android includes
547
624
  serial; both include bundleId, appPath, metroPort, cacheHit and launched.
548
625
  macOS facts include bundle, bundleId, executable, pid, build and launched.
626
+ A hosted macOS result has a null local pid and preserves true or 'unverified'
627
+ from the host's launch evidence.
549
628
  Web facts contain the owned browser's existing launch and page facts.
550
629
  Do not interpret 'bundling' or 'unverified' as proven application readiness.
551
630
 
631
+ start({ remote?, resetCache?, waitSeconds?, signal?, beforeStart? }) starts or
632
+ reuses the managed dev server, using the same settings and ownership rules as
633
+ stim start. remote requests the configured public URL or tunnel. resetCache
634
+ restarts the server with a cleared transform cache. waitSeconds is a positive
635
+ whole number, defaulting to 60. The flat result is port, supervisorPid, mode,
636
+ logsDir, agentDevice and alreadyRunning.
637
+ beforeStart(workspace) runs once with the resolved app before usage recording
638
+ or effects; throwing refuses startup. Cancellation stops pending probes and lock
639
+ waits, then accounts for new children before returning. A verified supervisor
640
+ handed off to the workspace may remain running. Unconfirmed cleanup refuses with
641
+ STIM_CLAIM_UNAVAILABLE, taking precedence over cancellation or callback failure;
642
+ follow its remedy before retrying. Startup never retries automatically.
643
+
552
644
  reload({ platform?, signal?, beforeReload? }) requests a JavaScript reload in
553
645
  the live iOS/Android app or reloads the owned Chrome page. It returns the flat
554
646
  stim reload --json facts: platform, deviceId, deviceName, appId, metroPort,
@@ -561,8 +653,11 @@ usage recording or dispatch; throwing refuses the action. Reload uses the
561
653
  STIM_REPORT_TIMEOUT and STIM_CLAIM_UNAVAILABLE. Cancellation stops pending
562
654
  probes and dispatch, but cannot retract a reload already sent. It never retries.
563
655
 
564
- stop({ slot? }) returns { ok, outcomes, summary }. It acts on the workspace,
565
- including resources from earlier runs. Use a dedicated workspace in CI.
656
+ stop({ slot?, beforeStop? }) returns { ok, outcomes, summary }. It acts on the
657
+ workspace, including resources from earlier runs. Use a dedicated workspace in CI.
658
+ beforeStop(workspace) runs once with the resolved workspace before teardown;
659
+ throwing refuses the operation.
660
+ From a child directory, start and stop resolve the enclosing supported app.
566
661
  Cancellation drains the operation's owned work, a read kills its child
567
662
  processes, and both reject with STIM_CANCELLED. Cancelling stop while it waits
568
663
  for another native operation ends that wait. Once teardown starts, stop finishes
@@ -3045,6 +3140,8 @@ it retries and scans every 500 ms, with one recovery scan 500 ms after attachmen
3045
3140
  On Windows a moved log directory can require the ten-second repair scan.
3046
3141
  Expo context settling uses a timer only
3047
3142
  while an error is pending; otherwise idle files are not repeatedly scanned.
3143
+ Local agent actions also follow their state and claim directories, coalescing file
3144
+ changes instead of re-reading every 500 ms while idle.
3048
3145
  While following, hosted targets join and leave from local state notifications.
3049
3146
  Missed notifications are reconciled about every 10 seconds. Active hosts still
3050
3147
  serve bounded log queries.
@@ -4623,7 +4720,8 @@ captured" (in metro.ndjson, bare RN)
4623
4720
  a changed pin while this workspace's dev server runs or its supervisor
4624
4721
  cannot be verified,
4625
4722
  \`--device\` with an empty
4626
- serial or UDID, \`--device\` together with \`--remote\`, \`ios --runtime\`
4723
+ serial or UDID, \`--device\` together with \`--remote\` other than
4724
+ \`local\`, \`ios --runtime\`
4627
4725
  on an eas/proxy run (\`--remote\` or ios.remote; that backend picks the
4628
4726
  iOS version), \`ios --device-type\` on the proxy backend or with an
4629
4727
  eas-cli older than 22.2.0 on the eas backend, \`android --system-image\` or
@@ -4693,15 +4791,17 @@ captured" (in metro.ndjson, bare RN)
4693
4791
  STIM_WORKTREE_REMOVAL_IN_PROGRESS instead.`
4694
4792
  },
4695
4793
  STIM_REPORT_TIMEOUT: {
4696
- summary: "An in-process doctor or GC report exceeded its execution budget",
4794
+ summary: "An in-process report or lifecycle operation exceeded its execution budget",
4697
4795
  body: () => `STIM_REPORT_TIMEOUT
4698
4796
 
4699
- The doctor() or gc() API read exceeded its 60 second execution budget. Stim
4700
- attempts only that report's cleanup before rejecting, with a 35 second cleanup
4701
- budget. Unfinished cleanup returns STIM_CLAIM_UNAVAILABLE instead.
4797
+ An API operation exceeded its execution budget: 90 minutes for warmWorktree(),
4798
+ 60 seconds for doctor(), gc(), collectGarbage(), reload(), plan() and removeWorktree().
4799
+ Stim attempts only that operation's cleanup before rejecting, with a 35 second
4800
+ cleanup budget. Unfinished cleanup returns STIM_CLAIM_UNAVAILABLE instead.
4702
4801
  Other clients are unaffected. Retry after the machine is less busy, or narrow
4703
- the report with doctor({ platform }) or gc({ cache }). No GC deletion or idle
4704
- shutdown occurs through these report methods.
4802
+ the report with doctor({ platform }) or gc({ cache }). doctor() and gc() remain
4803
+ read-only. collectGarbage() can mutate resources; completed actions remain applied.
4804
+ Inspect what remains with gc() before retrying a mutation.
4705
4805
  `
4706
4806
  },
4707
4807
  STIM_CANCELLED: {
@@ -5222,6 +5322,16 @@ with eas or proxy starts it the way \`stim start --remote\` does. A named
5222
5322
  hosting Mac keeps Metro local through a private bridge; see hosted-ios. Step 2 remains useful to warm
5223
5323
  Metro while other work happens.
5224
5324
 
5325
+ Each time Stim boots an owned local simulator or emulator, it mutes it: iOS
5326
+ simulators to volume zero through Xcode's devicectl, and Android 15 and later
5327
+ emulators to media volume zero. A device that is already running keeps its
5328
+ volume. Turn sound on for one device with Sound (iOS) or Media sound
5329
+ (Android) in its Stim Desktop options; the choice lasts until that device next
5330
+ boots. Android 14 and older images have no shell command that can set media
5331
+ volume, so startup warns, as it does whenever a mute is not confirmed. Host
5332
+ volume, Android alarm and ringtone volumes, hosted devices and physical
5333
+ devices are unchanged.
5334
+
5225
5335
  Repeat step 3 whenever a NATIVE input changes. A JS-only edit needs nothing --
5226
5336
  that is what Fast Refresh over the running dev server is for. \`stim reload\` is
5227
5337
  not part of the normal workflow. It is the explicit recovery path when Fast
@@ -5385,7 +5495,7 @@ WAITING FOR A CHANGE
5385
5495
  repositories, the exit of a recorded supervisor, Metro, build, browser or
5386
5496
  macOS app process (checked every 2 seconds), adb device arrivals and
5387
5497
  departures, and simulator boots, shutdowns, creations and deletions (from
5388
- CoreSimulator's device set, with a simctl check every 30 seconds), and
5498
+ CoreSimulator's device set and metadata files, with a simctl check every 30 seconds), and
5389
5499
  recomputes every 30 seconds as a fallback. A log append updates the log-derived facts
5390
5500
  within about a second; device activity follows at most every 5 seconds. The
5391
5501
  first line does not wait for git: worktree git summaries can be null in it,
@@ -5522,8 +5632,17 @@ homes. External inputs, directory links, submodules and custom local.properties
5522
5632
  refuse; an SDK-only local.properties stays local. Only declared directories
5523
5633
  reported by AGP and previously produced by this worker remain warm, along with
5524
5634
  worker project .gradle/.kotlin state. Undeclared bytes are removed. Gradle owns
5525
- incremental, task-cache and configuration-cache reuse; transfer digests never
5526
- become reusable APK cache keys. Older hosts refuse before source upload.
5635
+ incremental, task-cache and configuration-cache reuse. A transferred
5636
+ android.artifactInputs declaration also lets the worker reuse verified APKs under
5637
+ its own complete inputs: worker toolchain, signing files and environment values,
5638
+ not the caller's. The returned fingerprint remains null; transfer digests never
5639
+ become reusable APK cache keys. Workers with native-gradle-peer-cache can offer a
5640
+ completed APK for declared source and resolved variant, ABI and build options,
5641
+ rechecking current private inputs against the saved receipt at offer and fetch.
5642
+ A hit skips source upload and compilation even while that worker is busy or
5643
+ this machine has room. A miss follows normal placement; older Gradle workers
5644
+ still build normally. Off mode, explicit local builds and disabled remote cache
5645
+ reads skip peer lookup. Hosts without native-gradle-build refuse before upload.
5527
5646
 
5528
5647
  outputs must list every build directory of this build's projects that the build
5529
5648
  creates: the root build directory and each module's, library modules included.
@@ -5598,9 +5717,10 @@ android.remote = auto places automatically; see hosted-ios for the shared
5598
5717
  policy. No flag or setting runs on this machine.
5599
5718
 
5600
5719
  A named Mac is strict: refusal, unreachable, declined or failed preparation
5601
- returns STIM_HOSTING_REFUSED without fallback. --device, a different recorded
5602
- machine, a running local owned emulator in the slot, and --no-metro-check for
5603
- hosted Metro development apps refuse STIM_BAD_ARG. Run stim stop before switching placement.
5720
+ returns STIM_HOSTING_REFUSED without fallback. --device with --remote
5721
+ <machine>, a different recorded machine, a running local owned emulator in
5722
+ the slot, and --no-metro-check for hosted Metro development apps refuse
5723
+ STIM_BAD_ARG. Run stim stop before switching placement.
5604
5724
  Unreadable android.host blocks only its slot; restore its recorded machine and
5605
5725
  session from the host before stopping that slot.
5606
5726
 
@@ -5792,7 +5912,8 @@ A reserve refusal after a successful offer can race with another run. It fails
5792
5912
  with STIM_HOSTING_REFUSED naming the host and asking to retry. Stim does not
5793
5913
  try the next host or local placement after the build has targeted that host's
5794
5914
  architecture, and never falls back once a hosted session exists. A named machine remains strict. --device
5795
- cannot combine with auto. eas/proxy and macOS placement are unchanged.
5915
+ cannot combine with --remote auto, and a --device run ignores ios.remote and
5916
+ android.remote. eas/proxy and macOS placement are unchanged.
5796
5917
  --simulator-app is honoured locally with auto and ignored with a note on a host.
5797
5918
  Placement measures budgets without reclaiming; only a new local run reclaims.
5798
5919
  Android --remote <machine> uses an owned emulator on that Mac; see hosted-android.
@@ -6776,8 +6897,8 @@ THE BUILD CACHE HAS THREE LEVELS
6776
6897
  @stim-cli/cache contract (see \`guide settings\`). Consulted only when
6777
6898
  level one misses, and its hit is stored into level one before install.
6778
6899
  The same contract serves the Metro transform cache.
6779
- 3. On an EXPO project only, the provider the project ALREADY configured for
6780
- Expo (\`expo.buildCacheProvider\` -- "eas", or a module of its own).
6900
+ 3. On an EXPO project only, EAS when the project configures it through
6901
+ Expo (\`expo.buildCacheProvider\` -- "eas").
6781
6902
  Consulted only when levels one and two miss, bounded so a slow or expired
6782
6903
  remote cannot stall the loop, and a hit is copied into level one on the
6783
6904
  way past so the next workspace on this machine gets it for free. After a
@@ -7288,6 +7409,8 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
7288
7409
  install requires an exclusive claim. It releases shared before waiting for
7289
7410
  exclusive, then checks the checkout again before fetching or writing. Every
7290
7411
  copy holds shared, so no copy reads a node_modules a refresh is rewriting.
7412
+ Each copy also holds an exclusive claim on its target, so concurrent warms
7413
+ into the same linked worktree wait instead of racing destination checks.
7291
7414
  The lock is keyed on the repository root, so
7292
7415
  two apps of one monorepo share it. It is the same ownership claim the build
7293
7416
  locks take: the holder's process IDENTITY decides, so a holder that dies frees
@@ -7369,8 +7492,9 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
7369
7492
  filled in. Warm does not copy tracked changes, switch branches, or build,
7370
7493
  and it installs dependencies only under \`--refresh\`, in the source checkout. stdout stays empty; stderr reports copied, kept,
7371
7494
  and failed entry counts. A copy failure exits 1 and reports incomplete;
7372
- files copied before a failure remain. Inspect the named failed entry
7373
- before retrying: a partially copied directory will be kept on the retry.
7495
+ completed entries remain. After its child drains, warm removes its own
7496
+ failed partial entry so a retry can copy it again. Unverifiable child cleanup
7497
+ leaves that entry and its ownership claims in place with recovery instructions.
7374
7498
  A completed copy is not proof that dependencies match this branch. Follow
7375
7499
  any lockfile remedies before building, and install missing dependencies
7376
7500
  with the project's package manager when the source has none to copy.
@@ -7459,7 +7583,8 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
7459
7583
  body: () => ` \`android --device [serial]\` installs and launches on a physical device
7460
7584
  connected to this machine instead of this workspace's owned emulator. With
7461
7585
  no serial it takes the first device it can lease (\`guide lifecycle lease\`).
7462
- It cannot be combined with --remote.
7586
+ It ignores android.remote and cannot be combined with --remote other than
7587
+ --remote local.
7463
7588
 
7464
7589
  A \`--device\` run LEASES the device from just after the build until it
7465
7590
  exits, so a second workspace cannot install over it mid-run
@@ -7475,7 +7600,8 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
7475
7600
  \`android --device\` selects a connected phone: with no UDID it takes the
7476
7601
  first device it can lease (\`guide lifecycle lease\`), and an iPhone
7477
7602
  that is unpaired or has Developer Mode off is refused with the fix. It
7478
- cannot be combined with --remote, and it never creates, boots, or deletes
7603
+ ignores ios.remote, cannot be combined with --remote other than --remote
7604
+ local, and never creates, boots, or deletes
7479
7605
  hardware -- there is no capacity check, no simulator creation, no boot wait,
7480
7606
  and no owned-device registry entry. Like
7481
7607
  \`android --device\`, it leases the phone for the run
@@ -8643,6 +8769,12 @@ run drops the dead config ENTRIES those projects left behind and frees their
8643
8769
  Metro ports. \`stim gc --json\` prints the same report as one payload
8644
8770
  (\`guide facts gc\`); show the user its sections before \`gc --delete\`.
8645
8771
 
8772
+ Ctrl-C stops pending GC actions and drains verified owned children before exiting
8773
+ 130. Completed actions remain applied. Unverifiable child cleanup keeps its
8774
+ ownership claims and prints STIM_CLAIM_UNAVAILABLE with a recovery remedy.
8775
+ With --json, cancellation prints one STIM_CANCELLED payload, or the cleanup
8776
+ refusal when cleanup cannot be verified.
8777
+
8646
8778
  REMOTE EAS SESSIONS
8647
8779
  Plain \`stim gc\` is a dry run. \`gc --delete\` can stop active stim-* EAS
8648
8780
  sessions after workspace state is missing. The stop needs verified
@@ -9103,7 +9235,8 @@ KEYS STIM READS
9103
9235
  remote.machines, with the same meaning as --remote.
9104
9236
  "auto" places on an approved Mac when this machine is full or
9105
9237
  busy. Unset runs here; "local" runs here even when a
9106
- lower layer says otherwise. See lifecycle hosted-ios.
9238
+ lower layer says otherwise. A --device run ignores
9239
+ it. See lifecycle hosted-ios.
9107
9240
  ios.projectPath directory under the app holding a bare React Native
9108
9241
  app's Xcode project and Podfile; default "ios". "."
9109
9242
  is the app directory itself (RNTester's layout).
@@ -9294,7 +9427,7 @@ ${ANDROID_AVD_CONFIG_HELP.map((line) => ` ${line}`).joi
9294
9427
  build. outputs names generated directories reported
9295
9428
  by AGP; recorded outputs can survive worker sync.
9296
9429
  Omitted optional inputs can change build results.
9297
- Worker APKs remain uncached. See
9430
+ Worker APK caching also requires artifactInputs. See
9298
9431
  \`stim guide lifecycle native-android\` for input,
9299
9432
  privacy and worker requirements.
9300
9433
  android.keystore the keystore a RE-PACKED release APK is signed with,
@@ -9321,7 +9454,8 @@ ${ANDROID_AVD_CONFIG_HELP.map((line) => ` ${line}`).joi
9321
9454
  remote.machines; "auto" places on an approved Mac when
9322
9455
  this machine is full or busy. Unset runs here; "local"
9323
9456
  runs here even when a lower layer says otherwise.
9324
- See lifecycle hosted-android.
9457
+ A --device run ignores it. See lifecycle
9458
+ hosted-android.
9325
9459
  remote.easFallback true lets "auto" (ios.remote, android.remote or
9326
9460
  --remote auto) run the simulator or emulator on a
9327
9461
  billed EAS Simulator when this machine is at its
@@ -9436,6 +9570,8 @@ ${ANDROID_AVD_CONFIG_HELP.map((line) => ` ${line}`).joi
9436
9570
  Debug by stim macos
9437
9571
  macos.infoPlist development Info.plist relative to Package.swift,
9438
9572
  without shared URL schemes or an update feed
9573
+ macos.artifactInputs complete pinned, repeatable inputs producing a relocatable
9574
+ app for completed build caching. See stim guide macos.
9439
9575
  macos.arguments string array passed directly to the executable;
9440
9576
  see stim guide macos for the prototype's limits
9441
9577
  macos.assetCatalog optional .xcassets directory relative to Package.swift,
@@ -9899,6 +10035,12 @@ emulator debug build or a stim macos SwiftPM Debug build compiles:
9899
10035
  force on a remote machine whenever one accepts it
9900
10036
  off here when local remains enabled in the automatic build pool
9901
10037
 
10038
+ For React Native and Expo, among machines that can take a new build, a matching dependency installation
10039
+ ranks before load. The worker checks the requested project, lockfile and install
10040
+ arguments, and verifies that its modules and install marker remain present.
10041
+ Older workers' dependency hints and mere checkout or build-folder presence do
10042
+ not influence this ranking. Exact completed-artifact hits still come first.
10043
+
9902
10044
  Load per core is the 5-minute load average divided by the CPU count; a machine's
9903
10045
  native builds are its Stim runs in prebuild, pods or compile on that machine, not
9904
10046
  the ones it offloaded.
@@ -9913,7 +10055,8 @@ Debug builds can use a separate --remote-build, targeting the hosting Mac's
9913
10055
  architecture and runtime.
9914
10056
  macOS uses matching Xcode and macOS SDK, with a per-client SwiftPM dependency
9915
10057
  cache on the worker. It skips JavaScript dependencies, prebuild and pods; see
9916
- stim guide macos. macOS artifacts are not cached.
10058
+ stim guide macos. Completed caching requires macos.artifactInputs and a locally
10059
+ verified compile; remote output is not published under an unverified client key.
9917
10060
  An offloaded iOS/Android build first runs prebuild (and \`pod install\` for iOS) here,
9918
10061
  then asks every paired machine what it can build. It takes one whose Stim
9919
10062
  build matches this Mac and, for iOS and macOS, CPU matches the target simulator, with enough disk, that does not decline,
@@ -9926,7 +10069,17 @@ includes source, Xcode, SDK, architecture and target options. A hit skips sync
9926
10069
  and compilation even while the worker is busy or this machine has room. Missing or
9927
10070
  corrupt archives follow normal placement. Off mode and an explicit local build
9928
10071
  do not query peer caches. Older workers continue normal placement. This peer
9929
- lookup covers native Xcode worker artifacts, not compiler or dependency caches.
10072
+ lookup also covers declared native Gradle worker APKs when the worker supports
10073
+ native-gradle-peer-cache. It rechecks current private inputs against the saved
10074
+ receipt at offer and fetch for the requested source, resolved variant, ABI and
10075
+ build options. Caller fingerprints stay null; worker keys stay worker-scoped.
10076
+ React Native and Expo development builds also query enabled paired workers
10077
+ with react-native-peer-cache after local and configured-provider misses. Their
10078
+ post-mutation fingerprint, native build choices and compatible toolchain must
10079
+ match. Completed archives survive worker checkout changes or removal; hits
10080
+ need no source upload or build slot. Disabled remote artifact reads skip this
10081
+ lookup. Release and physical-device builds keep their existing paths.
10082
+ SwiftPM, compiler and dependency caches use their existing paths.
9930
10083
  For iOS the machine's Xcode and simulator SDK must match, and it needs an
9931
10084
  iPhone simulator on the target runtime. Its project-selected CocoaPods must match too, unless
9932
10085
  the app's Gemfile.lock pins CocoaPods: both machines then run that version through
@@ -10135,6 +10288,8 @@ The example shows the defaults. Full setting names and behavior:
10135
10288
  Install @stim-cli/cache-s3 and select it through cache.provider for S3-compatible storage,
10136
10289
  including Cloudflare R2, or configure another provider through Expo.
10137
10290
  Stim does not run a hosted cache service; credentials use the AWS SDK chain.
10291
+ S3 file uploads retry connection resets up to three PUT attempts, reopening
10292
+ the completed file each time. Cancellation also stops the retry delays.
10138
10293
  optimizations.releaseBundleSwap
10139
10294
  false always builds Release from source, including the current JS;
10140
10295
  it never installs an old embedded bundle. Fresh artifacts can still store.
@@ -10598,24 +10753,65 @@ changing focus: it sets STIM_BACKGROUND_LAUNCH=1 in the app's environment, which
10598
10753
  Stim Desktop honors, including for reopen events from open -g. An app that
10599
10754
  activates itself at launch or on reopen still takes focus.
10600
10755
  Hosted launches (macos --remote) do not set it.
10601
- macOS artifacts are not cached. This prototype has no --slot or reload command.
10756
+ This prototype has no --slot or reload command.
10757
+ Completed app caching is opt-in with macos.artifactInputs:
10758
+
10759
+ { "macos": { "artifactInputs": { "complete": true,
10760
+ "ignored": [], "outputs": [], "localFiles": [], "environment": [] } } }
10761
+
10762
+ complete declares pinned, repeatable build inputs and an app that runs after its
10763
+ original checkout and scratch directory are gone. Do not enable it for mutable
10764
+ dependencies, build-time network data, undeclared environment or local inputs,
10765
+ or code that needs its original absolute source paths (including #filePath).
10766
+ Stim hashes Git-visible repository source, Package.resolved even when ignored,
10767
+ the development plist, declared resources, Swift/Xcode/SDK identity and CPU
10768
+ architecture. ignored names exact Git-ignored repository-relative input files;
10769
+ outputs names generated repository-relative directories already ignored by Git.
10770
+ localFiles names exact additional private files, relative to the package or
10771
+ absolute; environment names additional build-time variables. Values and private
10772
+ file contents are hashed locally and are not included in the shared receipt.
10773
+ Symbolic links in source inventories are currently ineligible for caching.
10774
+ Without a valid declaration Stim compiles normally and keeps SwiftPM incremental
10775
+ reuse. optimizations.buildCache and optimizations.remoteBuildCache also apply.
10776
+ The completed bundle uses the ordinary shared build cache and an optional
10777
+ cache.provider's files capability, including S3. A hit avoids compiler slots and
10778
+ placement, then gets this workspace's identifier and name on a re-signed copy.
10779
+ Corrupt or incompatible entries fall back to compilation. Inputs changed during
10780
+ compilation prevent publication. Compiler and package scratch state is not shared.
10781
+ An enabled paired worker with swiftpm-peer-cache can retain a completed archive
10782
+ after verifying its actual source, private inputs and toolchain before and after
10783
+ compilation. After local/provider misses, an exact peer hit skips source upload
10784
+ and compiler admission, even while that worker is busy. Private values stay on
10785
+ the worker; its opaque identity is not used as this Mac's local cache key.
10786
+ Ignored bundle files must be declared in ignored or localFiles for peer reuse.
10787
+ The worker rechecks private inputs before offer and fetch; deleting its checkout
10788
+ does not discard an archive whose private inputs remain valid. Toolchain versions and command selection are
10789
+ checked from the package directory. After checkout removal, only verified direct
10790
+ Apple Swift, xcrun and xcodebuild selections can be reproduced; custom launchers
10791
+ require the checkout and otherwise miss safely. SWIFT_EXEC and SWIFT_EXEC_MANIFEST
10792
+ compiler overrides are resolved and versioned separately and require the checkout.
10793
+ The SDK selected by SDKROOT or SWIFTPM_SDKROOT_macosx is checked by real path and build version. Explicit local placement,
10794
+ remote build mode off, disabled pool members and remoteBuildCache
10795
+ false skip peer lookup. Older workers keep their normal compilation path.
10602
10796
  --plan validates the Swift Package directory, macos settings, development plist
10603
- and declared resources without building, signing, staging, stopping or launching
10797
+ and declared resources without building, signing, stopping or launching
10604
10798
  an app, writing workspace state or claiming a build slot. It does not execute
10605
10799
  Package.swift, so it cannot validate the executable product or package dependencies.
10606
10800
  --remote-build is respected, including named-machine setup refusals; no worker
10607
10801
  is contacted and live worker availability is unknown. --remote is launch-only
10608
10802
  and refuses with --plan. The JSON plan has platform "macos", product and
10609
- buildMachine; fingerprint, cacheKey, provider, prebuild, outcome and expectedMs
10610
- are null, cacheHit and cacheSkipped are false, and basis is 0. SwiftPM decides
10611
- incremental compile work when a build runs; the plan predicts no cache outcome
10612
- or duration. Desktop checks automatically while build details are visible,
10803
+ buildMachine. An eligible cache identity supplies fingerprint and cacheKey;
10804
+ cacheHit reports a verified local completed artifact, checked in a disposable
10805
+ temporary copy. Providers and workers are not contacted. cacheSkipped is true
10806
+ when artifact caching is disabled or ineligible. provider, prebuild, outcome
10807
+ and expectedMs remain null, and basis is 0. SwiftPM decides incremental compile
10808
+ work when a build runs; the plan predicts no duration. Desktop checks automatically while build details are visible,
10613
10809
  reusing a completed build or check for 60 seconds and skipping running builds.
10614
10810
  A failed build records its error and compiler output without launching an app.
10615
10811
  While it runs, stim status --json reports it as environments[].build with
10616
10812
  platform "macos": phase prepare, compile, install, then launch, and during
10617
10813
  compile detail.unit "steps" with SwiftPM's [done / total] counts (fetching and
10618
- planning are detail.step "configure"). It has no cache lookup, so outcome and
10814
+ planning are detail.step "configure"). outcome and
10619
10815
  plannedPhases are null; finished runs and their phase times are in
10620
10816
  environments[].builds.macos, where phases includes launch once the launch step finishes
10621
10817
  and compileSteps is SwiftPM's step total. An offloaded build reports the worker's
@@ -1,7 +1,7 @@
1
- import { en as throwIfCancelled } from "./settings-CsJDEXgK.mjs";
2
- import { c as call, l as connectHost } from "./hosted-client-DB_gBPfY.mjs";
3
- import { i as requestHostedMetro } from "./metro-gateway-BMJNlj3E.mjs";
4
- import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-Ksyjgzq-.mjs";
1
+ import { f as throwIfCancelled } from "./operation-exec-BW0em61G.mjs";
2
+ import { c as call, l as connectHost } from "./hosted-client-DZAPrcro.mjs";
3
+ import { i as requestHostedMetro } from "./metro-gateway-CKZqKqx7.mjs";
4
+ import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-BdzE668-.mjs";
5
5
  //#region src/device-host/hosted-android.ts
6
6
  async function prepareHostedAndroid(machine, selectors, recorded, mode) {
7
7
  return await prepareHostedNative(machine, selectors, recorded, "android", false, mode);
@@ -13,8 +13,8 @@ async function placeHostedAndroid(target, options) {
13
13
  reserved: (placement) => options.reserved(placement)
14
14
  });
15
15
  }
16
- async function stopHostedAndroid(root, slot) {
17
- await stopHostedNative(root, slot, "android");
16
+ async function stopHostedAndroid(root, slot, signal) {
17
+ await stopHostedNative(root, slot, signal, "android");
18
18
  }
19
19
  async function reopenHostedAndroidMetro(root, placement, clientMetroPort, signal) {
20
20
  const host = await connectHost(placement.machine, void 0, true, signal);
@@ -1,7 +1,7 @@
1
- import { it as resolveEndpoint } from "./config-CYcBF478.mjs";
2
- import { Qt as cancellableSleep, en as throwIfCancelled } from "./settings-CsJDEXgK.mjs";
3
- import { t as BuildConnection } from "./client-UXD70ZbM.mjs";
4
- import { u as configuredMachines } from "./selection-CSl9i5qU.mjs";
1
+ import { rt as resolveEndpoint } from "./config-DlrsduwG.mjs";
2
+ import { f as throwIfCancelled, u as cancellableSleep } from "./operation-exec-BW0em61G.mjs";
3
+ import { t as BuildConnection } from "./client-OyRoEuSr.mjs";
4
+ import { u as configuredMachines } from "./selection-DSMbWEX2.mjs";
5
5
  import { createHash } from "node:crypto";
6
6
  import { lstatSync, readFileSync, readdirSync, readlinkSync } from "node:fs";
7
7
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-Ksyjgzq-.mjs";
1
+ import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-BdzE668-.mjs";
2
2
  //#region src/device-host/hosted-ios.ts
3
3
  async function prepareHostedIos(machine, selectors, recorded, mode) {
4
4
  return await prepareHostedNative(machine, selectors, recorded, "ios", false, mode);
@@ -1,10 +1,10 @@
1
- import { t as getExecutor } from "./exec-_UbtCQcG.mjs";
1
+ import { t as getExecutor } from "./exec-DEoAhcze.mjs";
2
2
  import { d as workspaceDir, m as workspaceLogsDir$1 } from "./paths-DQtTgsBf.mjs";
3
- import { J as validateDeviceSlot, V as deviceSlotFileKey, tt as parseMachine$1 } from "./config-CYcBF478.mjs";
4
- import { l as phaseLine } from "./command-output-B1UrjZHL.mjs";
5
- import { n as macosDir } from "./state-XMziexv2.mjs";
3
+ import { B as deviceSlotFileKey, et as parseMachine$1, q as validateDeviceSlot } from "./config-DlrsduwG.mjs";
4
+ import { l as phaseLine } from "./command-output-gwpm28fu.mjs";
5
+ import { n as macosDir } from "./state-08I3hw3_.mjs";
6
6
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
7
- import { c as call } from "./hosted-client-DB_gBPfY.mjs";
7
+ import { c as call } from "./hosted-client-DZAPrcro.mjs";
8
8
  import { mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
9
9
  import { dirname, join } from "node:path";
10
10
  import { LOG_ROTATE_BYTES, ambientWrite, withDirLockAsync } from "@stim-cli/core";