stim 1.23.1 → 1.25.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 (174) hide show
  1. package/README.md +3 -2
  2. package/dist/{acquire-artifact-BzYRDgaP.mjs → acquire-artifact-zA4S7RHE.mjs} +2 -2
  3. package/dist/{act-vxiMwdf5.mjs → act-BbHS3oV8.mjs} +41 -26
  4. package/dist/{activity-BpWUPgUm.mjs → activity-BpjwrQXU.mjs} +6 -6
  5. package/dist/{agent-device-usage-output-CUlLsbRt.mjs → agent-device-usage-output-Bnkerfod.mjs} +5 -5
  6. package/dist/{android-DtfRGLcc.mjs → android-BGwuK3Mc.mjs} +75 -50
  7. package/dist/{android-CLi6DSiS.mjs → android-CNZgRC-4.mjs} +5 -5
  8. package/dist/{android-C7sVmyI9.mjs → android-Cjcj8MCw.mjs} +140 -46
  9. package/dist/{android-cas-ngferVq2.mjs → android-cas-BVqh2Zep.mjs} +3 -3
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/{android-project-DVWyCbWU.d.mts → android-project-CTYaETc0.d.mts} +6 -2
  12. package/dist/{android-DR5lZ2Az.mjs → android-saBeB4lr.mjs} +13 -3
  13. package/dist/api.d.mts +22 -5
  14. package/dist/api.mjs +32 -31
  15. package/dist/{artifact-Xvgibgzq.mjs → artifact-Co8zixVx.mjs} +19 -17
  16. package/dist/{artifact-DBI3DALs.mjs → artifact-DN8JNwqS.mjs} +18 -17
  17. package/dist/{artifact-platform-CXcmX_j3.mjs → artifact-platform-CMRc0M_r.mjs} +3 -3
  18. package/dist/{browser-web-BJN9ZHxB.mjs → browser-web-CCgZsHmI.mjs} +16 -17
  19. package/dist/{budget-3ivAK99e.mjs → budget-HyShrIpL.mjs} +149 -47
  20. package/dist/{build-Dv9s8Fz-.mjs → build-CAiw8Ezm.mjs} +33 -29
  21. package/dist/{build-cache-Dv7RN200.mjs → build-cache-CKCzxzxA.mjs} +172 -21
  22. package/dist/{build-plan-BmbdHQbr.mjs → build-plan-zCuHGlA8.mjs} +8 -7
  23. package/dist/{cache-manifest-DSeQjt-Q.mjs → cache-manifest-BPXRONJz.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{ccache-CH2EWGPB.mjs → ccache-h1FKhZeg.mjs} +6 -6
  26. package/dist/{cdp-3fwICjzi.mjs → cdp-BG3FJCCx.mjs} +1 -1
  27. package/dist/{chrome-Bbw689-6.mjs → chrome-BvV8ssI3.mjs} +1 -1
  28. package/dist/{cli-BkK6Wr5i.mjs → cli-C4w607Pz.mjs} +20 -20
  29. package/dist/cli.mjs +1 -1
  30. package/dist/{client-B4MMzfo_.mjs → client-BQsmyp_-.mjs} +274 -39
  31. package/dist/collector-run.mjs +6 -6
  32. package/dist/{command-output-YKGWivpG.mjs → command-output-BBvS1H6v.mjs} +3 -2
  33. package/dist/{config-DlrsduwG.mjs → config-BZhXY15H.mjs} +3 -3
  34. package/dist/{created-devices-x9rN6bhs.mjs → created-devices-D2Aca-xu.mjs} +6 -2
  35. package/dist/{dependency-state-1I9KZT1Y.mjs → dependency-state-BwNCYG5Q.mjs} +2 -2
  36. package/dist/{detached-entry-BwNEtIrP.mjs → detached-entry-KmieOKgN.mjs} +1 -1
  37. package/dist/{dev-client-BFxiDpkf.mjs → dev-client-CHoXXZeg.mjs} +3 -3
  38. package/dist/{device-CiNYxqp6.mjs → device-B9FqTBYW.mjs} +81 -54
  39. package/dist/{device-B7ljwccX.mjs → device-F5-4z9ef.mjs} +16 -16
  40. package/dist/{device-capacity-DH0QsZYZ.mjs → device-capacity-ZYaRALv5.mjs} +20 -16
  41. package/dist/device-host-worker.mjs +17 -17
  42. package/dist/{device-ios-CbVDtDIy.mjs → device-ios-DkHBrmvH.mjs} +32 -50
  43. package/dist/{device-lease-run-DXPSwdbb.mjs → device-lease-run-ogEeJ62K.mjs} +6 -6
  44. package/dist/{device-pool-B4iOXIrD.mjs → device-pool-BIg8MU8l.mjs} +3 -3
  45. package/dist/{doctor-DRu-8ld6.mjs → doctor-A_Nr_fDe.mjs} +1 -1
  46. package/dist/{doctor-HUC1igzw.mjs → doctor-Bm8TVpGn.mjs} +37 -31
  47. package/dist/{doctor-fingerprint-DZLoYFVb.mjs → doctor-fingerprint-zlujA1Gs.mjs} +1 -1
  48. package/dist/doctor-fingerprint.mjs +1 -1
  49. package/dist/{doctor-C6t4Maue.mjs → doctor-k3P3PizH.mjs} +14 -14
  50. package/dist/{doctor-watchman-iGBpC6KM.mjs → doctor-watchman-BovI1y3-.mjs} +5 -5
  51. package/dist/{eas-build-DMWSSvxq.mjs → eas-build-CyDKNTBP.mjs} +4 -4
  52. package/dist/{eas-fallback-vKlrqxgE.mjs → eas-fallback-gaZi-dJL.mjs} +16 -15
  53. package/dist/{eas-session-ledger-BQF9Yyy9.mjs → eas-session-ledger-BMCA1gdO.mjs} +12 -8
  54. package/dist/{error-diagnostics-DYsjJIHz.mjs → error-diagnostics-B1Mj_-7h.mjs} +17 -42
  55. package/dist/{errors-ccaPc4ox.mjs → errors-DHm_U5gv.mjs} +2 -1
  56. package/dist/{exec-DEoAhcze.mjs → exec-VFRpu1iA.mjs} +116 -28
  57. package/dist/{gc-BW8E1uSC.mjs → gc-B9jcnmIk.mjs} +205 -28
  58. package/dist/{gc-dDE4QPVu.mjs → gc-eaz403W6.mjs} +2 -2
  59. package/dist/{guide-DYYEO3Wz.mjs → guide-DR0K0xW9.mjs} +328 -89
  60. package/dist/{hosted-android-xcfgCgSF.mjs → hosted-android-Bvb2-ZxD.mjs} +4 -4
  61. package/dist/{hosted-client-Bt-tndxV.mjs → hosted-client-rsRqysJc.mjs} +4 -4
  62. package/dist/{hosted-ios-y19jCYFF.mjs → hosted-ios-RtVcJH3u.mjs} +1 -1
  63. package/dist/{hosted-logs-DzJKzKlj.mjs → hosted-logs-CWKGYWNX.mjs} +11 -6
  64. package/dist/{hosted-macos-BJusKvqL.mjs → hosted-macos-d0pv9Tth.mjs} +7 -7
  65. package/dist/{hosted-native-BmQC6U_x.mjs → hosted-native-BxTizGU2.mjs} +58 -11
  66. package/dist/{idle-shutdown-CJmUOV5x.mjs → idle-shutdown-BIyfl0Zj.mjs} +10 -10
  67. package/dist/{ios-hcBpnEGk.mjs → ios-BQzvJlzw.mjs} +122 -17
  68. package/dist/{ios-CWjqfSm_.mjs → ios-BRVM8b0P.mjs} +81 -49
  69. package/dist/{ios-DTOYZGMJ.mjs → ios-Dvt97HgQ.mjs} +8 -8
  70. package/dist/{ios-xtlRHaeB.mjs → ios-ENC4sRPA.mjs} +1 -1
  71. package/dist/{ios-device-BXZ0c7Kb.mjs → ios-device-B6HK951C.mjs} +1 -1
  72. package/dist/{ios-device-DFGuwF4U.mjs → ios-device-CKSvk0bu.mjs} +3 -3
  73. package/dist/{ios-project-CSZYI1iu.mjs → ios-project-DCUDo06I.mjs} +5 -5
  74. package/dist/{ios-signing-BtAffm0A.mjs → ios-signing-4c_qXvQm.mjs} +2 -2
  75. package/dist/{ios-state-Dtw5K2aI.mjs → ios-state-CT9nV5SP.mjs} +15 -7
  76. package/dist/{js-swap-BSBHldmm.mjs → js-swap-Z9HbC4cj.mjs} +7 -6
  77. package/dist/{launch-D-zq8SHG.mjs → launch-D0lPvFFu.mjs} +49 -30
  78. package/dist/{launch-CP2wDCVd.mjs → launch-DscF1QfM.mjs} +52 -50
  79. package/dist/{logs-pNvA2hHK.mjs → logs-BsIRre8x.mjs} +16 -9
  80. package/dist/{logs-By5aw3g9.mjs → logs-Crs9y34Z.mjs} +8 -6
  81. package/dist/{macos-CPMahOC2.mjs → macos-CcUlJPMu.mjs} +1 -1
  82. package/dist/{macos-C67FZ2ft.mjs → macos-D477nfzH.mjs} +49 -42
  83. package/dist/macos-run.mjs +1 -1
  84. package/dist/maintenance-run.mjs +7 -7
  85. package/dist/{metro-DiXtA3Ty.mjs → metro-1pJgCX4U.mjs} +4 -4
  86. package/dist/{metro-gateway-CKZqKqx7.mjs → metro-gateway-Bp9gJQAN.mjs} +3 -4
  87. package/dist/{named-ports-DkEzOfzO.mjs → named-ports-BVbn8SvC.mjs} +3 -3
  88. package/dist/{native-android-_MWSs3PP.mjs → native-android-BvMizJn1.mjs} +17 -17
  89. package/dist/{native-gradle-artifact-inputs-DHFnmrVf.mjs → native-gradle-artifact-inputs-BJscK4vN.mjs} +5 -5
  90. package/dist/{native-run-Dv88i0aU.mjs → native-run-D5OJsGwA.mjs} +6 -6
  91. package/dist/{native-runtime-DBRfY_PN.mjs → native-runtime-B9w_Qyz3.mjs} +10 -9
  92. package/dist/{native-source-Y0yLhFyQ.mjs → native-source-D-4Dh4JU.mjs} +7 -4
  93. package/dist/{native-xcode-inputs-CqViUh3r.mjs → native-xcode-inputs-Cv4l-obn.mjs} +2 -2
  94. package/dist/{native-xcode-ios-vFgqL_yS.mjs → native-xcode-ios-DGrg90hE.mjs} +21 -20
  95. package/dist/offload-worker.d.mts +12 -4
  96. package/dist/offload-worker.mjs +78 -43
  97. package/dist/{operation-exec-BW0em61G.mjs → operation-exec-CUZifp6Z.mjs} +2 -25
  98. package/dist/{ownership-C5fo5Edb.mjs → ownership-jxxz-19m.mjs} +3 -3
  99. package/dist/{page-DBL2PiUU.mjs → page-CzEA_-5_.mjs} +2 -3
  100. package/dist/phone-reverses-CYb7RRAx.mjs +57 -0
  101. package/dist/{placement-log-BnGgJRRZ.mjs → placement-log-DjOXJRIH.mjs} +1 -1
  102. package/dist/{plan-placement-cr0fEU7b.mjs → plan-placement-BqKgKHCi.mjs} +3 -3
  103. package/dist/{ports-DpXjKkSV.mjs → ports-DtS1Amb0.mjs} +3 -3
  104. package/dist/{prebuild-BligW0QS.mjs → prebuild-JUaqOLpc.mjs} +14 -9
  105. package/dist/{project-DhCtQWWU.mjs → project-BiC68mIp.mjs} +21 -17
  106. package/dist/{pull-request-W1IuLXDt.mjs → pull-request-CbNlkFok.mjs} +2 -2
  107. package/dist/pull-requests.mjs +1 -1
  108. package/dist/{react-native-android-ZlhQfhvq.mjs → react-native-android-DRYqoJc4.mjs} +76 -32
  109. package/dist/{react-native-build-CelbTO_y.mjs → react-native-build-CwZB-agu.mjs} +23 -20
  110. package/dist/{react-native-doctor-LTIaP7lv.mjs → react-native-doctor-BCrytK7h.mjs} +10 -9
  111. package/dist/{react-native-ios-C5W0SA6f.mjs → react-native-ios-Cr1buNFo.mjs} +41 -24
  112. package/dist/{recordings-CQmfzAh7.mjs → recordings-BaoQ0t-J.mjs} +1 -1
  113. package/dist/{registration-BcRgF6Ox.mjs → registration-CN6nlhcD.mjs} +1 -1
  114. package/dist/{reload-QcwnYLYV.mjs → reload-Beftw2X3.mjs} +1 -1
  115. package/dist/{reload-COJWTbae.mjs → reload-FbSgMF8x.mjs} +144 -42
  116. package/dist/{remote-DR8qUERM.mjs → remote-BuZj6AyU.mjs} +16 -7
  117. package/dist/{result-utnBea7x.mjs → result-CR2vk2cj.mjs} +41 -18
  118. package/dist/{run-DidHghD1.mjs → run-BtzE09Dl.mjs} +2 -2
  119. package/dist/{selection-DSMbWEX2.mjs → selection-D5cxEl3t.mjs} +13 -7
  120. package/dist/{server-bare-CafzuyFB.mjs → server-bare-CH9X0RLn.mjs} +56 -4
  121. package/dist/{server-command-B9o92sLM.mjs → server-command-CaBbDNU2.mjs} +5 -5
  122. package/dist/server-expo-C16Zf2k7.mjs +2 -0
  123. package/dist/{server-expo-BXrWxNYh.mjs → server-expo-Ck8EIidM.mjs} +14 -9
  124. package/dist/{settings-C7O8A6ZI.mjs → settings-B5tCoq9N.mjs} +132 -39
  125. package/dist/{settings-PfJx8uK1.mjs → settings-DzH9mGQZ.mjs} +1 -1
  126. package/dist/{settings-write-Chuy7Cte.mjs → settings-write-n0zwfohx.mjs} +7 -7
  127. package/dist/settings.schema.json +51 -0
  128. package/dist/{simslim-BNckWpXi.mjs → simslim-BjxszUAb.mjs} +22 -7
  129. package/dist/{slot-launch-B7AuoWJv.mjs → slot-launch-QeuJMlnJ.mjs} +6 -6
  130. package/dist/{stage-C4u17aES.mjs → stage-D8xlRU2D.mjs} +2 -3
  131. package/dist/{start-BL_BsiWt.mjs → start-C1JLjkNw.mjs} +1 -1
  132. package/dist/{start-CU8mCPC7.mjs → start-YMpNwLhh.mjs} +75 -35
  133. package/dist/{state--smjFSTL.mjs → state-DMRNP7-4.mjs} +4 -4
  134. package/dist/{state-08I3hw3_.mjs → state-DPaM3u5K.mjs} +2 -2
  135. package/dist/{stats-CO6sK0Nh.mjs → stats-CP7STzZw.mjs} +5 -5
  136. package/dist/{stats-report-BzaPrRm6.mjs → stats-report-n2U5plhk.mjs} +1 -1
  137. package/dist/{status-_WPHzVft.mjs → status-CRLiJ-O_.mjs} +24 -24
  138. package/dist/{status-BRROykC8.mjs → status-Fect2w9R.mjs} +1 -1
  139. package/dist/{status-CrJutl6-.mjs → status-cNw6i0_t.mjs} +1 -1
  140. package/dist/{status-watch-BHFasOZN.mjs → status-watch-Bc2J4TZn.mjs} +5 -5
  141. package/dist/status-worker.mjs +1 -1
  142. package/dist/stim-clonefile.c +18 -0
  143. package/dist/{stim-desktop-D5OGpYZM.mjs → stim-desktop-DS0mzR8U.mjs} +2 -2
  144. package/dist/{stop-iuFHjUST.mjs → stop-Br7LKxBE.mjs} +2 -2
  145. package/dist/{stop-CR5689oB.mjs → stop-COP6PQqw.mjs} +5 -5
  146. package/dist/{stop-BJ06ipTZ.mjs → stop-Db9Kh-UA.mjs} +109 -56
  147. package/dist/supervisor-run.mjs +17 -17
  148. package/dist/{support-CbXPbUMJ.mjs → support-Cxj9CmII.mjs} +6 -6
  149. package/dist/{support-TWuQlHQo.mjs → support-qKcbgmI5.mjs} +14 -11
  150. package/dist/{swiftpm-artifact-inputs-DFcGsXDP.mjs → swiftpm-artifact-inputs-iY9fsmOc.mjs} +4 -4
  151. package/dist/{swiftpm-macos-DbwGCpZg.mjs → swiftpm-macos-Bp_sn9P4.mjs} +15 -14
  152. package/dist/{toolchain-XkA2PfJZ.mjs → toolchain-DB1aeqxO.mjs} +1 -1
  153. package/dist/{toolchain-B9hCFCQw.mjs → toolchain-VzLJzZ7O.mjs} +69 -37
  154. package/dist/trigger-BLsHgAGR.mjs +2 -0
  155. package/dist/{trigger-Cbyc41d_.mjs → trigger-CBMe2YLH.mjs} +2 -2
  156. package/dist/{warm-progress-CA3TgT3-.mjs → warm-progress-BV3ZPmcY.mjs} +6 -6
  157. package/dist/{web-DRF_oFXk.mjs → web-B4Yjyt1G.mjs} +12 -10
  158. package/dist/web-DS4UDWvf.mjs +2 -0
  159. package/dist/web-run.mjs +8 -9
  160. package/dist/windows-report.mjs +12 -1
  161. package/dist/windows-report.ps1 +1 -1
  162. package/dist/{workspace-state-U08dEzhG.mjs → workspace-state-CPSp3mav.mjs} +11 -4
  163. package/dist/{workspaces-e41xsjKr.mjs → workspaces-C9w4aeXF.mjs} +36 -32
  164. package/dist/{worktree-B4Nj3EGS.mjs → worktree-CclFIe1Z.mjs} +324 -99
  165. package/dist/{worktree-BEwxVwKF.mjs → worktree-Ct9Gk3KL.mjs} +1 -1
  166. package/dist/{xcode-Rq744mBF.mjs → xcode-CiIIDnuD.mjs} +42 -28
  167. package/package.json +7 -7
  168. package/shim/bundle-response.cjs +53 -1
  169. package/shim/bundle-response.d.cts +1 -1
  170. package/shim/expo-metro-config.cjs +23 -1
  171. package/dist/native-gradle-inputs-Dnh84Zbd.mjs +0 -211
  172. package/dist/server-expo-Ddr8cG_c.mjs +0 -2
  173. package/dist/trigger-yb_nFzPF.mjs +0 -2
  174. package/dist/web-kDE9Myoy.mjs +0 -2
@@ -1,27 +1,26 @@
1
- import { _ as reportSignal, b as debugLog, m as operationState, t as getExecutor } from "./exec-DEoAhcze.mjs";
2
- import { Q as openAuthenticated, _ as loadConfig$1, it as sayHello, rt as resolveEndpoint } from "./config-DlrsduwG.mjs";
3
- import { f as throwIfCancelled, o as git, s as gitAsync } from "./operation-exec-BW0em61G.mjs";
1
+ import { C as reportSignal, E as debugLog, b as operationState, c as throwIfCancelled, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
+ import { Q as openAuthenticated, _ as loadConfig$1, it as sayHello, rt as resolveEndpoint } from "./config-BZhXY15H.mjs";
3
+ import { o as git, s as gitAsync } from "./operation-exec-CUZifp6Z.mjs";
4
4
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
5
- import { X as emptyCaches, br as discoverCaches, nt as planCacheEmptying } from "./budget-3ivAK99e.mjs";
5
+ import { Cr as discoverCaches, Q as emptyCaches, it as planCacheEmptying } from "./budget-HyShrIpL.mjs";
6
6
  import { t as canonicalPath } from "./paths-BsJMoPP2.mjs";
7
- import { d as runCancellationSignal } from "./native-run-Dv88i0aU.mjs";
8
- import { n as CCACHE_UNAVAILABLE, t as CCACHE_NOT_RUN } from "./ccache-CH2EWGPB.mjs";
9
- import { n as COMPILATION_CACHE_UNAVAILABLE, t as COMPILATION_CACHE_NOT_RUN } from "./xcode-Rq744mBF.mjs";
7
+ import { d as runCancellationSignal } from "./native-run-D5OJsGwA.mjs";
8
+ import { n as CCACHE_UNAVAILABLE, t as CCACHE_NOT_RUN } from "./ccache-h1FKhZeg.mjs";
9
+ import { n as COMPILATION_CACHE_UNAVAILABLE, t as COMPILATION_CACHE_NOT_RUN } from "./xcode-CiIIDnuD.mjs";
10
10
  import { t as resolveMaintenanceSettings } from "./settings-Djl-mpjX.mjs";
11
- import { a as iosToolchainAsync, d as toolchainMismatches, f as workerToolchain, g as readRubyVersion } from "./toolchain-B9hCFCQw.mjs";
12
- import { l as pairedMachines, r as namedBuildMachine, t as OffloadRefusal } from "./selection-DSMbWEX2.mjs";
13
- import { r as manifestDigest } from "./native-inputs-TRTTTRxt.mjs";
14
- import { a as sourceManifest, i as nativeTransferManifest, n as gitVisiblePaths, t as checkNativeTransferMembership } from "./native-source-Y0yLhFyQ.mjs";
15
- import { a as nativeGradleTransfer } from "./native-gradle-inputs-Dnh84Zbd.mjs";
11
+ import { a as iosToolchainAsync, d as toolchainMismatches, f as workerToolchain, g as readRubyVersion } from "./toolchain-VzLJzZ7O.mjs";
12
+ import { i as namedBuildMachine, t as OffloadRefusal, u as pairedMachines } from "./selection-D5cxEl3t.mjs";
13
+ import { n as fingerprintNativeInputs, r as manifestDigest } from "./native-inputs-TRTTTRxt.mjs";
14
+ import { a as sourceManifest, i as nativeTransferManifest, n as gitVisiblePaths, r as nativeFileDigest, t as checkNativeTransferMembership } from "./native-source-D-4Dh4JU.mjs";
16
15
  import { createHash, webcrypto } from "node:crypto";
17
16
  import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
18
17
  import { isDeepStrictEqual } from "node:util";
19
- import { basename, dirname, isAbsolute, join, relative, sep } from "node:path";
20
- import { LOG_ROTATE_BYTES, ambientContext, reactNativeArtifactIdentity, reactNativeArtifactQuery, rotatedLogPath, swiftpmArtifactQuery, withDirLock } from "@stim-cli/core";
18
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
19
+ import { LOG_ROTATE_BYTES, ambientContext, dependencyLockfile, reactNativeArtifactIdentity, reactNativeArtifactQuery, rotatedLogPath, swiftpmArtifactQuery, withDirLock } from "@stim-cli/core";
21
20
  import { MAINTENANCE_LOG_NAME, OFFLOAD_MODES, automaticMachineEnabled, isJsonObject, maintenanceDir, maintenanceNdjsonFile, requireAutomaticMachine, runId, saturation, workspaceLogsDir } from "@stim-cli/core/state";
22
21
  import { WebSocket } from "ws";
23
22
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
24
- import { readFile, readlink } from "node:fs/promises";
23
+ import { access, lstat, readFile, readlink, realpath } from "node:fs/promises";
25
24
  //#region src/maintenance/log.ts
26
25
  function maintenanceLogger(settings, pass, trigger) {
27
26
  const file = maintenanceNdjsonFile();
@@ -158,6 +157,210 @@ function reportRemoteFailure(context, event, fields) {
158
157
  } catch {}
159
158
  }
160
159
  //#endregion
160
+ //#region src/integrations/native-gradle-inputs.ts
161
+ function containedPath(path) {
162
+ return typeof path === "string" && path.length > 0 && !path.includes("\\") && !path.includes(":") && !path.includes("\0") && !path.split("/").some((part) => !part || part === "." || part === ".." || part.toLowerCase() === ".git");
163
+ }
164
+ function gradleOffloadInputs(value) {
165
+ const input = value;
166
+ if (!input || typeof input !== "object" || input.complete !== true || Object.keys(input).some((key) => ![
167
+ "complete",
168
+ "ignored",
169
+ "outputs"
170
+ ].includes(key)) || !Array.isArray(input.ignored) || !input.ignored.every(containedPath) || !Array.isArray(input.outputs) || !input.outputs.every(containedPath)) throw new Error("Native Gradle offload requires android.offloadInputs with complete: true, ignored: [exact repository-relative files], and outputs: [generated repository-relative directories].");
171
+ const ignored = [...new Set(input.ignored)].toSorted();
172
+ const outputs = [...new Set(input.outputs)].toSorted();
173
+ if (ignored.some((path) => path.split("/").at(-1) === "local.properties")) throw new Error("local.properties is machine-local; remove it from android.offloadInputs.ignored.");
174
+ if (outputs.some((path) => path.split("/").some((part) => part === ".gradle" || part === ".kotlin"))) throw new Error("Gradle project state is worker-owned and cannot be declared as a generated output.");
175
+ for (const output of outputs) if (outputs.some((other) => other !== output && output.startsWith(`${other}/`))) throw new Error(`Generated output ${output} is nested inside another output declaration.`);
176
+ return {
177
+ complete: true,
178
+ ignored,
179
+ outputs
180
+ };
181
+ }
182
+ const below = (path, directory) => path === directory || path.startsWith(`${directory}/`);
183
+ function gradleStateDirectories(project) {
184
+ return [".gradle", ".kotlin"].map((name) => project ? `${project}/${name}` : name);
185
+ }
186
+ async function statIfPresent(path) {
187
+ try {
188
+ return await lstat(path);
189
+ } catch (error) {
190
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return null;
191
+ throw error;
192
+ }
193
+ }
194
+ async function requireRealParents(repository, path, signal) {
195
+ const parts = path.split("/");
196
+ for (let index = 1; index < parts.length; index++) {
197
+ signal?.throwIfAborted();
198
+ const stat = await statIfPresent(join(repository, ...parts.slice(0, index)));
199
+ if (stat && !stat.isDirectory()) throw new Error(`Native input ${path} has a non-directory parent.`);
200
+ }
201
+ }
202
+ async function nativeGradleTransfer(root, value, signal) {
203
+ return nativeGradleInventory(root, value, [], signal, true);
204
+ }
205
+ async function nativeGradleLocalSourceDigest(root, value, localFiles, signal) {
206
+ const { project, digest } = await nativeGradleInventory(root, value, localFiles, signal, false);
207
+ return createHash("sha256").update(JSON.stringify({
208
+ project,
209
+ digest
210
+ })).digest("hex");
211
+ }
212
+ async function nativeGradleInventory(root, value, localFiles, signal, transfer) {
213
+ signal?.throwIfAborted();
214
+ const declaration = gradleOffloadInputs(value);
215
+ const repository = await realpath(await gitAsync(root, ["rev-parse", "--show-toplevel"], { signal }));
216
+ const realRoot = await realpath(root);
217
+ const project = relative(repository, realRoot).split(sep).join("/");
218
+ const local = localFiles.map((path) => resolve(realRoot, relative(root, path)));
219
+ if (project && !containedPath(project)) throw new Error("The native Gradle project leaves its repository.");
220
+ if (transfer && (await statIfPresent(join(repository, project, "buildSrc")))?.isDirectory()) throw new Error("Native Gradle offload does not support buildSrc: AGP does not report its build directories, so the worker cannot keep them.");
221
+ const state = gradleStateDirectories(project);
222
+ const files = new Map((await sourceManifest(repository, true, signal)).map((file) => [file.path, file]));
223
+ for (const path of declaration.ignored) {
224
+ await requireRealParents(repository, path, signal);
225
+ const absolute = join(repository, path);
226
+ const stat = await lstat(absolute);
227
+ if (!stat.isFile() && !stat.isSymbolicLink()) throw new Error(`Ignored native input ${path} must be an exact file or link, not a directory.`);
228
+ if (stat.isSymbolicLink()) {
229
+ const content = Buffer.from(await readlink(absolute));
230
+ files.set(path, {
231
+ path,
232
+ kind: "link",
233
+ size: content.length,
234
+ sha256: createHash("sha256").update(content).digest("hex")
235
+ });
236
+ } else files.set(path, {
237
+ path,
238
+ kind: stat.mode & 73 ? "exec" : "file",
239
+ ...await nativeFileDigest(absolute, signal)
240
+ });
241
+ }
242
+ for (const file of files.values()) {
243
+ if (local.includes(resolve(repository, file.path))) {
244
+ files.delete(file.path);
245
+ continue;
246
+ }
247
+ if (!containedPath(file.path)) throw new Error(`Native input ${file.path} is not a contained relative path.`);
248
+ await requireRealParents(repository, file.path, signal);
249
+ if (state.some((path) => below(file.path, path))) throw new Error("Gradle project state cannot be transferred as source.");
250
+ if (declaration.outputs.some((output) => below(file.path, output) || below(output, file.path))) throw new Error(`Native input ${file.path} overlaps a declared generated output.`);
251
+ if (file.path.split("/").at(-1) === "local.properties") {
252
+ if (file.kind === "link") throw new Error(`Native input ${file.path} is a machine-local properties link.`);
253
+ if ((await readFile(join(repository, file.path), {
254
+ encoding: "utf8",
255
+ signal
256
+ })).split(/\r?\n/).some((line) => line.trim() && !/^\s*[#!]/.test(line) && !/^\s*sdk\.dir\s*[:=].*[^\\]$/.test(line))) throw new Error(`Native input ${file.path} contains unsupported machine-local properties.`);
257
+ files.delete(file.path);
258
+ continue;
259
+ }
260
+ }
261
+ for (const file of files.values()) if (file.kind === "link") {
262
+ const absolute = join(repository, file.path);
263
+ const target = await readlink(absolute);
264
+ const resolved = await realpath(resolve(dirname(absolute), target));
265
+ const destination = relative(repository, resolved).split(sep).join("/");
266
+ if (isAbsolute(target) || !containedPath(destination) || !files.has(destination)) throw new Error(`Native input ${file.path} links to a target outside the declared source inventory.`);
267
+ }
268
+ for (const output of declaration.outputs) {
269
+ await requireRealParents(repository, output, signal);
270
+ const stat = await statIfPresent(join(repository, output));
271
+ if (stat && !stat.isDirectory()) throw new Error(`Generated output ${output} is not a real directory.`);
272
+ if (state.some((path) => below(output, path) || below(path, output))) throw new Error(`Generated output ${output} overlaps Gradle project state.`);
273
+ }
274
+ const empty = createHash("sha256").update("").digest("hex");
275
+ for (const path of files.keys()) {
276
+ const parts = path.split("/");
277
+ for (let index = 1; index < parts.length; index++) {
278
+ const directory = parts.slice(0, index).join("/");
279
+ files.set(directory, {
280
+ path: directory,
281
+ kind: "directory",
282
+ size: 0,
283
+ sha256: empty
284
+ });
285
+ }
286
+ }
287
+ const selected = [...files.values()].toSorted((a, b) => a.path.localeCompare(b.path));
288
+ return {
289
+ repository,
290
+ project,
291
+ declaration,
292
+ files: selected,
293
+ digest: manifestDigest(selected)
294
+ };
295
+ }
296
+ async function canonicalParent(path) {
297
+ const missing = [];
298
+ while (!await access(path).then(() => true, () => false) && dirname(path) !== path) {
299
+ missing.unshift(basename(path));
300
+ path = dirname(path);
301
+ }
302
+ return join(await realpath(path), ...missing);
303
+ }
304
+ async function nativeGradleOutputs(repository, declaration, reported, signal) {
305
+ signal?.throwIfAborted();
306
+ if (!Array.isArray(reported) || !reported.every((path) => typeof path === "string" && isAbsolute(path))) throw new Error("AGP did not report the configured native Gradle build directories.");
307
+ const real = await realpath(repository);
308
+ const reportedPaths = /* @__PURE__ */ new Set();
309
+ for (const absolute of reported) {
310
+ const resolved = resolve(absolute);
311
+ const canonical = join(await canonicalParent(dirname(resolved)), basename(resolved));
312
+ const path = relative(real, canonical).split(sep).join("/");
313
+ if (!containedPath(path)) throw new Error("A Gradle build directory leaves the transferred repository.");
314
+ await requireRealParents(repository, path, signal);
315
+ const stat = await statIfPresent(join(repository, path));
316
+ if (stat && !stat.isDirectory()) throw new Error(`Gradle build directory ${path} is not a real directory.`);
317
+ reportedPaths.add(path);
318
+ }
319
+ for (const output of declaration.outputs) if (!reportedPaths.has(output)) throw new Error(`Declared output ${output} was not reported by AGP.`);
320
+ for (const path of reportedPaths) if ((await statIfPresent(join(repository, path)))?.isDirectory() && !declaration.outputs.some((output) => below(path, output))) throw new Error(`Gradle build directory ${path} is not declared; add it to android.offloadInputs.outputs.`);
321
+ const outputs = [];
322
+ for (const path of declaration.outputs) {
323
+ signal?.throwIfAborted();
324
+ if ((await statIfPresent(join(repository, path)))?.isDirectory()) outputs.push(path);
325
+ }
326
+ return outputs;
327
+ }
328
+ function validateGradleManifest(project, declaration, files) {
329
+ gradleOffloadInputs(declaration);
330
+ if (project && !containedPath(project)) throw new Error("The native Gradle project leaves its repository.");
331
+ const excluded = [...declaration.outputs, ...gradleStateDirectories(project)];
332
+ for (const file of files) if (!containedPath(file.path) || excluded.some((path) => below(file.path, path) || file.kind !== "directory" && below(path, file.path))) throw new Error(`Native source ${file.path} overlaps worker outputs or leaves the repository.`);
333
+ for (const path of declaration.ignored) if (!files.some((file) => file.path === path && file.kind !== "directory")) throw new Error(`Declared ignored input ${path} is missing from the transfer.`);
334
+ }
335
+ async function verifyGradleTransfer(repository, project, declaration, files, digest, signal) {
336
+ signal?.throwIfAborted();
337
+ validateGradleManifest(project, declaration, files);
338
+ const excluded = [...declaration.outputs, ...gradleStateDirectories(project)];
339
+ for (const path of excluded) {
340
+ await requireRealParents(repository, path, signal);
341
+ const stat = await statIfPresent(join(repository, path));
342
+ if (stat && !stat.isDirectory()) throw new Error(`Worker output ${path} is not a real directory.`);
343
+ }
344
+ const markers = excluded.flatMap((path) => path.split("/").slice(0, -1).map((_, index) => join(repository, ...path.split("/").slice(0, index + 1))));
345
+ const snapshot = await fingerprintNativeInputs([{
346
+ name: "repository",
347
+ path: repository
348
+ }], {
349
+ excluded: [join(repository, ".git"), ...excluded.map((path) => join(repository, path))],
350
+ ignoredDirectoryMarkers: markers.filter((path) => !files.some((file) => join(repository, file.path) === path)),
351
+ parameters: null,
352
+ signal
353
+ });
354
+ const known = new Set(files.map((file) => file.path));
355
+ for (const entry of snapshot.entries) {
356
+ if (!entry.path.startsWith("repository/") || entry.path.includes("/@target")) continue;
357
+ const parts = entry.path.slice(11).split("/");
358
+ const index = parts.findIndex((_, depth) => !known.has(parts.slice(0, depth + 1).join("/")));
359
+ if (index >= 0 && (index < parts.length - 1 || entry.kind === "directory")) throw new Error(`Native Gradle directory ${parts.slice(0, index + 1).join("/")} is outside the source transfer and not a declared output reported by AGP; such directories, for example, included builds or externalNativeBuild staging, are not supported for remote builds.`);
360
+ }
361
+ return manifestDigest(await nativeTransferManifest(repository, snapshot, files, signal)) === digest;
362
+ }
363
+ //#endregion
161
364
  //#region src/offload/react-native-artifact.ts
162
365
  function reactNativeBuildQuery(build, fingerprint, project, toolchain) {
163
366
  if (build.native) return null;
@@ -176,17 +379,18 @@ function reactNativeBuildQuery(build, fingerprint, project, toolchain) {
176
379
  } } : { android: build.android }
177
380
  });
178
381
  }
179
- async function reactNativeArtifactToolchain(platform, root) {
382
+ async function reactNativeArtifactToolchain(platform, root, iosDirectory) {
180
383
  if (platform === "ios") {
181
- const tools = await iosToolchainAsync(root);
384
+ const tools = await iosToolchainAsync(root, iosDirectory);
182
385
  return tools.stimBuild && tools.xcode && tools.simulatorSdk && tools.cocoapods ? {
183
386
  ...tools,
184
387
  os: process.platform
185
388
  } : null;
186
389
  }
187
- const { stimBuild, os, arch, jdk, androidSdk } = workerToolchain(null, "gradle");
188
- return stimBuild && jdk && androidSdk ? {
390
+ const { stimBuild, compat, os, arch, jdk, androidSdk } = workerToolchain(null, "gradle");
391
+ return stimBuild && compat !== void 0 && jdk && androidSdk ? {
189
392
  stimBuild,
393
+ compat,
190
394
  os,
191
395
  arch,
192
396
  jdk,
@@ -697,16 +901,13 @@ function repoIdentity(projectRoot) {
697
901
  function repositoryIdentity(projectRoot, repoRoot, common) {
698
902
  const digest = createHash("sha256").update(common).digest("hex").slice(0, 12);
699
903
  const name = (basename(dirname(common)) || "repo").replace(/[^A-Za-z0-9._-]/g, "_").replace(/^[^A-Za-z0-9]+/, "");
700
- const lock = [
701
- "pnpm-lock.yaml",
702
- "yarn.lock",
703
- "package-lock.json"
704
- ].find((file) => existsSync(join(repoRoot, file)));
904
+ const project = relative(repoRoot, realpathSync(projectRoot));
905
+ const lock = dependencyLockfile(repoRoot, project);
705
906
  return {
706
907
  repoRoot,
707
- project: relative(repoRoot, realpathSync(projectRoot)),
908
+ project,
708
909
  repo: `${name.slice(0, 60) || "repo"}-${digest}`,
709
- lockfile: lock ? createHash("sha256").update(readFileSync(join(repoRoot, lock))).digest("hex") : null
910
+ lockfile: lock ? createHash("sha256").update(readFileSync(join(repoRoot, lock.dir, lock.file))).digest("hex") : null
710
911
  };
711
912
  }
712
913
  function dependencySelection(identity, target) {
@@ -770,8 +971,8 @@ async function probeMachine(credential, identity, { connectMs = CONNECT_TIMEOUT_
770
971
  ...identity.dependencies && connection.supports("build-dependency-cache") ? { dependencies: identity.dependencies } : {},
771
972
  ...native ? { native } : identity.rubyVersion ? { rubyVersion: identity.rubyVersion } : {},
772
973
  ...native === "xcode" && identity.artifact && connection.supports("build-artifact-cache") ? { artifact: identity.artifact } : {},
773
- ...identity.swiftpmArtifact && connection.supports("swiftpm-peer-cache") ? { swiftpmArtifact: identity.swiftpmArtifact } : {},
774
- ...identity.reactNativeArtifact && connection.supports("react-native-peer-cache") ? { reactNativeArtifact: identity.reactNativeArtifact } : {},
974
+ ...identity.swiftpmArtifact && queriesPeerCache(connection, "swiftpm-peer-cache") ? { swiftpmArtifact: identity.swiftpmArtifact } : {},
975
+ ...identity.reactNativeArtifact && queriesPeerCache(connection, "react-native-peer-cache") ? { reactNativeArtifact: identity.reactNativeArtifact } : {},
775
976
  ...native === "gradle" && identity.gradleArtifact && connection.supports("native-gradle-peer-cache") ? { gradleArtifact: identity.gradleArtifact } : {}
776
977
  }, offerMs);
777
978
  const failure = replyError(reply);
@@ -793,7 +994,7 @@ async function probeMachine(credential, identity, { connectMs = CONNECT_TIMEOUT_
793
994
  return {
794
995
  credential,
795
996
  connection,
796
- offer: identity.swiftpmArtifact && !connection.supports("swiftpm-peer-cache") || identity.reactNativeArtifact && !connection.supports("react-native-peer-cache") || native === "gradle" && (!identity.gradleArtifact || !connection.supports("native-gradle-peer-cache")) ? {
997
+ offer: identity.swiftpmArtifact && !queriesPeerCache(connection, "swiftpm-peer-cache") || identity.reactNativeArtifact && !queriesPeerCache(connection, "react-native-peer-cache") || native === "gradle" && (!identity.gradleArtifact || !connection.supports("native-gradle-peer-cache")) ? {
797
998
  ...offer,
798
999
  artifact: null
799
1000
  } : offer
@@ -822,7 +1023,7 @@ async function chooseBuildMachine({ projectRoot, target, mode, here, note, machi
822
1023
  const swiftpmQuery = swiftpmArtifact?.artifactInputs ? swiftpmArtifactQuery({
823
1024
  project: identity.project,
824
1025
  sourceDigest: manifestDigest(await sourceManifest(identity.repoRoot, true, runCancellationSignal(ambientContext()) ?? ambientContext()?.signal)),
825
- stimBuild: target.local.stimBuild,
1026
+ compat: target.local.compat,
826
1027
  inputs: swiftpmArtifact.artifactInputs,
827
1028
  build: {
828
1029
  product: swiftpmArtifact.product,
@@ -885,6 +1086,13 @@ async function chooseBuildMachine({ projectRoot, target, mode, here, note, machi
885
1086
  ...swiftpmQuery ? { swiftpmArtifact: swiftpmQuery } : {}
886
1087
  };
887
1088
  }
1089
+ function startCompat(choice) {
1090
+ return choice.connection.supports("build-compat") ? { compat: choice.target.local.compat } : {};
1091
+ }
1092
+ /** Peer artifact queries carry `compat`, which a stim-server without `build-compat` refuses. */
1093
+ function queriesPeerCache(connection, feature) {
1094
+ return connection.supports(feature) && connection.supports("build-compat");
1095
+ }
888
1096
  function macosBuildParameters(request, peerCache) {
889
1097
  return {
890
1098
  ...request.cacheArtifact === true && peerCache ? { cacheArtifact: true } : {},
@@ -920,13 +1128,13 @@ async function peerArtifact(choice, request, fingerprint) {
920
1128
  assetCatalog: request.assetCatalog ?? null
921
1129
  }
922
1130
  }))) throw new Error("The SwiftPM artifact query does not match the build request.");
923
- if (!choice.connection.supports("swiftpm-peer-cache") || manifestDigest(await sourceManifest(choice.identity.repoRoot, true, runCancellationSignal(ambientContext()) ?? ambientContext()?.signal)) !== swiftpm.sourceDigest) return null;
1131
+ if (!queriesPeerCache(choice.connection, "swiftpm-peer-cache") || manifestDigest(await sourceManifest(choice.identity.repoRoot, true, runCancellationSignal(ambientContext()) ?? ambientContext()?.signal)) !== swiftpm.sourceDigest) return null;
924
1132
  return matchingArtifact(choice.offer, "swiftpm");
925
1133
  }
926
1134
  const reactNative = choice.reactNativeArtifact;
927
1135
  if (reactNative) {
928
1136
  if (typeof fingerprint !== "string" || !isDeepStrictEqual(reactNative, reactNativeBuildQuery(request, fingerprint, choice.identity.project, choice.target.local))) throw new Error("The React Native artifact query does not match the build request.");
929
- return choice.connection.supports("react-native-peer-cache") ? matchingArtifact(choice.offer, `react-native-${reactNative.platform}`) : null;
1137
+ return queriesPeerCache(choice.connection, "react-native-peer-cache") ? matchingArtifact(choice.offer, `react-native-${reactNative.platform}`) : null;
930
1138
  }
931
1139
  const query = choice.gradleArtifact;
932
1140
  if (query) {
@@ -998,10 +1206,15 @@ async function resumeJob(credential, job, abandoned, signal, native) {
998
1206
  return `no connection to it within ${RESUME_WINDOW_MS / 6e4} min (${last})`;
999
1207
  }
1000
1208
  /** Mirrors the checkout on the machine: the manifest in pages, then every blob it lacks. */
1001
- async function syncSource(connection, identity, onEnter, native, signal) {
1209
+ async function syncSource(connection, identity, onEnter, native, signal, ignored = []) {
1002
1210
  onEnter("sync");
1003
1211
  const syncStarted = Date.now();
1004
- const manifest = native && "declaration" in native ? (await nativeGradleTransfer(join(identity.repoRoot, identity.project), native.declaration, signal)).files : native ? await nativeTransferManifest(identity.repoRoot, native, await sourceManifest(identity.repoRoot, false, signal), signal) : await sourceManifest(identity.repoRoot, false, signal);
1212
+ const ignoredPaths = [];
1213
+ for (const path of ignored) {
1214
+ const inRepo = relative(identity.repoRoot, join(await realpath(dirname(path)), basename(path)));
1215
+ if (inRepo && !isAbsolute(inRepo) && inRepo !== ".." && !inRepo.startsWith(`..${sep}`)) ignoredPaths.push(inRepo.split(sep).join("/"));
1216
+ }
1217
+ const manifest = native && "declaration" in native ? (await nativeGradleTransfer(join(identity.repoRoot, identity.project), native.declaration, signal)).files : native ? await nativeTransferManifest(identity.repoRoot, native, await sourceManifest(identity.repoRoot, false, signal), signal) : await sourceManifest(identity.repoRoot, false, signal, ignoredPaths);
1005
1218
  if (native && "declaration" in native && manifestDigest(manifest) !== native.digest) return { failure: "The native Gradle source changed before upload." };
1006
1219
  const bySha = new Map(manifest.map((file) => [file.sha256, file]));
1007
1220
  const missing = [];
@@ -1132,6 +1345,21 @@ async function fetchArtifact({ connection, method, params, artifact, request, st
1132
1345
  declared
1133
1346
  };
1134
1347
  }
1348
+ function fingerprintSourcesParam(inputs, connection) {
1349
+ if (!inputs || !connection.supports("fingerprint-sources")) return {};
1350
+ return { fingerprintSources: inputs.sources.map((source) => ({
1351
+ id: source.type === "contents" ? source.id : source.filePath,
1352
+ hash: source.hash
1353
+ })) };
1354
+ }
1355
+ function fingerprintIgnoredParam(inputs, connection) {
1356
+ if (!inputs?.ignoredPaths?.length || !connection.supports("fingerprint-ignored")) return {};
1357
+ return { fingerprintIgnored: [...inputs.ignoredPaths] };
1358
+ }
1359
+ function fingerprintTrackedParam(inputs, connection) {
1360
+ if (!inputs?.trackedPaths?.length || !connection.supports("fingerprint-tracked")) return {};
1361
+ return { fingerprintTracked: [...inputs.trackedPaths] };
1362
+ }
1135
1363
  function keepCorruptCacheMessage(failed, result) {
1136
1364
  return result.code === "STIM_COMPILATION_CACHE_CORRUPT" ? {
1137
1365
  ...failed,
@@ -1262,6 +1490,8 @@ async function offloadBuild(input) {
1262
1490
  let syncMs = 0;
1263
1491
  let uploadedBytes = 0;
1264
1492
  let workerStarted = 0;
1493
+ let fingerprintInputs;
1494
+ const readFingerprintInputs = () => fingerprintInputs ??= !native && request.platform !== "macos" && input.fingerprintInputs ? input.fingerprintInputs() : Promise.resolve(null);
1265
1495
  const moveOn = (why) => {
1266
1496
  const next = choice.runnersUp.shift();
1267
1497
  if (!next) return false;
@@ -1293,7 +1523,8 @@ async function offloadBuild(input) {
1293
1523
  break;
1294
1524
  }
1295
1525
  if (choice.cacheOnly) return fail("The exact artifact is no longer available.");
1296
- const synced = await syncSource(choice.connection, identity, onEnter, nativeTransferInput(native), signal);
1526
+ const inputs = await readFingerprintInputs();
1527
+ const synced = await syncSource(choice.connection, identity, onEnter, nativeTransferInput(native), signal, inputs?.ignored);
1297
1528
  checkCancelled();
1298
1529
  if ("failure" in synced) {
1299
1530
  if (moveOn(synced.failure)) continue;
@@ -1312,6 +1543,9 @@ async function offloadBuild(input) {
1312
1543
  project: identity.project,
1313
1544
  platform: request.platform,
1314
1545
  fingerprint: request.platform === "macos" ? synced.digest : expectedFingerprint,
1546
+ ...fingerprintSourcesParam(inputs, choice.connection),
1547
+ ...fingerprintIgnoredParam(inputs, choice.connection),
1548
+ ...fingerprintTrackedParam(inputs, choice.connection),
1315
1549
  ...native ? { native: {
1316
1550
  provider: native.provider,
1317
1551
  sourceDigest: synced.digest,
@@ -1324,18 +1558,19 @@ async function offloadBuild(input) {
1324
1558
  ...choice.connection.supports("native-gradle-artifact-cache") ? { cache: native.cache } : {}
1325
1559
  }
1326
1560
  } } : {},
1327
- ...request.platform === "macos" ? macosBuildParameters(request, choice.connection.supports("swiftpm-peer-cache")) : {
1561
+ ...request.platform === "macos" ? macosBuildParameters(request, queriesPeerCache(choice.connection, "swiftpm-peer-cache")) : {
1328
1562
  configuration: request.platform === "ios" ? request.configuration : null,
1329
1563
  scheme: request.platform === "ios" ? request.scheme : null,
1330
1564
  iosProjectPath: request.platform === "ios" ? request.iosProjectPath ?? null : null,
1331
1565
  runtime: request.platform === "ios" ? request.runtime : null,
1332
1566
  packageName: packageName(join(identity.repoRoot, identity.project)),
1333
1567
  isExpo: request.isExpo,
1334
- ...!native && request.cacheArtifact === true && choice.connection.supports("react-native-peer-cache") ? { cacheArtifact: true } : {},
1568
+ ...!native && request.cacheArtifact === true && queriesPeerCache(choice.connection, "react-native-peer-cache") ? { cacheArtifact: true } : {},
1335
1569
  optimizations: request.platform === "ios" && isJsonObject(request.optimizations) ? request.optimizations : null,
1336
1570
  ...request.platform === "android" ? { android: request.android } : {}
1337
1571
  },
1338
- stimBuild: choice.target.local.stimBuild
1572
+ stimBuild: choice.target.local.stimBuild,
1573
+ ...startCompat(choice)
1339
1574
  });
1340
1575
  checkCancelled();
1341
1576
  if ("result" in reply) {
@@ -1574,4 +1809,4 @@ function offloadCheck(projectRoot, targets) {
1574
1809
  };
1575
1810
  }
1576
1811
  //#endregion
1577
- export { clearCorruptCompilationCache as _, nativeTransferRefusal as a, offloadPlacement as c, simulatorRuntime as d, reactNativeArtifactReceipt as f, COMPILATION_CACHE_CORRUPT as g, setRemoteLogSink as h, closeOffload as i, placementLoad as l, reactNativeBuildQuery as m, buildPlacementCandidates as n, offloadBuild as o, reactNativeArtifactToolchain as p, chooseBuildMachine as r, offloadCheck as s, BuildConnection as t, remotePhaseText as u, maintenanceLogger as v };
1812
+ export { COMPILATION_CACHE_CORRUPT as C, setRemoteLogSink as S, maintenanceLogger as T, nativeGradleLocalSourceDigest as _, nativeTransferRefusal as a, validateGradleManifest as b, offloadPlacement as c, simulatorRuntime as d, reactNativeArtifactReceipt as f, gradleStateDirectories as g, gradleOffloadInputs as h, closeOffload as i, placementLoad as l, reactNativeBuildQuery as m, buildPlacementCandidates as n, offloadBuild as o, reactNativeArtifactToolchain as p, chooseBuildMachine as r, offloadCheck as s, BuildConnection as t, remotePhaseText as u, nativeGradleOutputs as v, clearCorruptCompilationCache as w, verifyGradleTransfer as x, nativeGradleTransfer as y };
@@ -1,12 +1,12 @@
1
- import { g as process_identity_exports } from "./exec-DEoAhcze.mjs";
1
+ import { S as process_identity_exports } from "./exec-VFRpu1iA.mjs";
2
2
  import { m as workspaceLogsDir } from "./paths-DQtTgsBf.mjs";
3
- import { V as deviceSlotKey, q as validateDeviceSlot } from "./config-DlrsduwG.mjs";
3
+ import { V as deviceSlotKey, q as validateDeviceSlot } from "./config-BZhXY15H.mjs";
4
4
  import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
5
+ import { c as watchAppPid, i as parseLogcatLine, o as startAndroidLogcat, s as waitForAppPid, t as androidClockOffset } from "./android-saBeB4lr.mjs";
5
6
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
6
- import { a as startIosDeviceConsole, i as parseDeviceConsoleLine } from "./ios-device-BXZ0c7Kb.mjs";
7
- import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-C5fo5Edb.mjs";
8
- import { a as waitForAppPid, i as startAndroidLogcat, n as parseLogcatLine, o as watchAppPid, t as androidClockOffset } from "./android-DR5lZ2Az.mjs";
9
- import { n as parseLogStreamLine, r as startIosLogStream, t as appNameFromBundleId } from "./ios-xtlRHaeB.mjs";
7
+ import { a as startIosDeviceConsole, i as parseDeviceConsoleLine } from "./ios-device-B6HK951C.mjs";
8
+ import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-jxxz-19m.mjs";
9
+ import { n as parseLogStreamLine, r as startIosLogStream, t as appNameFromBundleId } from "./ios-ENC4sRPA.mjs";
10
10
  import { existsSync } from "node:fs";
11
11
  import { isAbsolute, join, resolve } from "node:path";
12
12
  import { LOG_ROTATE_BYTES } from "@stim-cli/core";
@@ -1,8 +1,9 @@
1
1
  import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
2
- import { t as NO_PROJECT_REFUSAL } from "./project-DhCtQWWU.mjs";
2
+ import { t as NO_PROJECT_REFUSAL } from "./project-BiC68mIp.mjs";
3
3
  import { quotedPath as quotedPath$1 } from "@stim-cli/core";
4
4
  import chalk from "chalk";
5
5
  //#region src/diagnostics/launch-error-preview.ts
6
+ const MAX_FRAME_LINE_LENGTH = 2048;
6
7
  function framePriority(frame, root) {
7
8
  const normalized = frame.replaceAll("\\", "/");
8
9
  if (/^\s*at (?:android\.|java\.|com\.android\.|dalvik\.)/.test(normalized)) return 2;
@@ -145,7 +146,7 @@ function launchErrorPreview(records, root, { full = false } = {}) {
145
146
  if (header) {
146
147
  flush();
147
148
  kind = /^component/i.test(header[1]) ? "Component" : "Error";
148
- } else if (/^\s*at\s+\S/.test(line) || /^\s*\S[^\n]*@\S+:\d+:\d+\s*$/.test(line) || /^\s+\S[^\n]*\([^()]+:\d+:\d+\)\s*$/.test(line)) {
149
+ } else if (line.length <= MAX_FRAME_LINE_LENGTH && (/^\s*at\s+\S/.test(line) || /^\s*\S[^\n]*@\S+:\d+:\d+\s*$/.test(line) || /^\s+\S[^\n]*\([^()]+:\d+:\d+\)\s*$/.test(line))) {
149
150
  if (!full && /\(https?:\/\/[^\s)]*$/.test(line)) return;
150
151
  frames.push(line);
151
152
  } else if (line.trim()) {
@@ -1,5 +1,5 @@
1
- import { _ as reportSignal, g as process_identity_exports, r as WorkspaceProcessCleanupError, t as getExecutor, x as ownership_claim_exports, y as trackReportResource } from "./exec-DEoAhcze.mjs";
2
- import { t as runOperationFile } from "./operation-exec-BW0em61G.mjs";
1
+ import { C as reportSignal, D as ownership_claim_exports, S as process_identity_exports, T as trackReportResource, l as WorkspaceProcessCleanupError, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
+ import { t as runOperationFile } from "./operation-exec-CUZifp6Z.mjs";
3
3
  import { join } from "node:path";
4
4
  import { ambientEnv, configDir, ensurePrivateDir } from "@stim-cli/core";
5
5
  import { allMetroPorts, cannotHost, clientIdentity, configCorruptRepair, endpoint, findEnclosingWorktreeRoot, findPeer as findPeer$1, getConcurrencyLimits, getConfigPath, getConfigPath as getConfigPath$1, getProject, getProjectSettings, getRepoSettings, isJsonObject, isPathPrefix, loadConfig, loadConfig as loadConfig$1, machineEndpoint, parseMachine, parseMachine as parseMachine$1, validateAutomaticPool, withConfigLock, withConfigLock as withConfigLock$1, withConfigLockAsync, withConfigLockAsync as withConfigLockAsync$1 } from "@stim-cli/core/state";
@@ -783,7 +783,7 @@ function releaseAndroidConsolePort(projectPath, consolePort, slot = "default") {
783
783
  });
784
784
  }
785
785
  function recordIosSchemeApprovals(projectPath, deviceUdid, schemeApprovals, slot = "default") {
786
- withConfigLock(() => {
786
+ return withConfigLockAsync(() => {
787
787
  const cfg = loadConfig();
788
788
  const ios = deviceSlotPlatforms(cfg?.projects?.[projectPath], slot)?.ios;
789
789
  if (!cfg || !ios?.owned || ios.deviceUdid !== deviceUdid) return;
@@ -1,5 +1,5 @@
1
1
  import { v as withDirLock$1, y as withDirLockAsync$1 } from "./paths-DQtTgsBf.mjs";
2
- import { d as getConfigDir } from "./config-DlrsduwG.mjs";
2
+ import { d as getConfigDir } from "./config-BZhXY15H.mjs";
3
3
  import { renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { ensurePrivateDir } from "@stim-cli/core";
5
5
  import { createdDevicesFile, createdDevicesLock, readCreatedDevices, readCreatedDevices as readCreatedDevices$1 } from "@stim-cli/core/state";
@@ -34,6 +34,10 @@ function recordCreatedDevice(platform, id) {
34
34
  function forgetCreatedDevice(platform, id) {
35
35
  update(platform, (entries) => entries.delete(id));
36
36
  }
37
+ /** Waits asynchronously for the ledger lock, then records the device. */
38
+ function recordCreatedDeviceAsync(platform, id) {
39
+ return withDirLockAsync$1(createdDevicesLock(), () => recordCreatedDevice(platform, id), { ensureParent: () => ensurePrivateDir(getConfigDir()) });
40
+ }
37
41
  /** Waits asynchronously for the ledger lock, then atomically forgets the device. The synchronous transaction decides whether to commit the removal; cancellation stops admission. */
38
42
  function forgetCreatedDeviceAsync(platform, id, signal, transaction = (forget) => {
39
43
  forget();
@@ -45,4 +49,4 @@ function forgetCreatedDeviceAsync(platform, id, signal, transaction = (forget) =
45
49
  });
46
50
  }
47
51
  //#endregion
48
- export { recordCreatedDevice as i, forgetCreatedDeviceAsync as n, readCreatedDevices$1 as r, forgetCreatedDevice as t };
52
+ export { recordCreatedDeviceAsync as a, recordCreatedDevice as i, forgetCreatedDeviceAsync as n, readCreatedDevices$1 as r, forgetCreatedDevice as t };
@@ -1,5 +1,5 @@
1
- import { t as getExecutor } from "./exec-DEoAhcze.mjs";
2
- import { Mt as repoRoot } from "./settings-C7O8A6ZI.mjs";
1
+ import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
+ import { Nt as repoRoot } from "./settings-B5tCoq9N.mjs";
3
3
  import { existsSync } from "node:fs";
4
4
  import { dirname, join, relative } from "node:path";
5
5
  //#region src/dependency-state.ts
@@ -1,4 +1,4 @@
1
- import { t as getExecutor } from "./exec-DEoAhcze.mjs";
1
+ import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
2
  import { openSync } from "node:fs";
3
3
  //#region src/detached-entry.ts
4
4
  const LOG_FILE_FLAG = "--log-file";
@@ -1,5 +1,5 @@
1
- import { C as resolvePackageJson, b as isPackageResolvable } from "./project-DhCtQWWU.mjs";
2
- import { An as readBundleSchemes, kn as pickDevClientScheme } from "./budget-3ivAK99e.mjs";
1
+ import { C as resolvePackageJson, b as isPackageResolvable } from "./project-BiC68mIp.mjs";
2
+ import { Mn as pickDevClientScheme, Nn as readBundleSchemes } from "./budget-HyShrIpL.mjs";
3
3
  import { dirname, join } from "node:path";
4
4
  import { isJsonObject, readJsonObject } from "@stim-cli/core/state";
5
5
  //#region src/commands/dev-client.ts
@@ -40,4 +40,4 @@ function installedDevLauncherVersion(root) {
40
40
  return typeof version === "string" ? version : null;
41
41
  }
42
42
  //#endregion
43
- export { devClientTakesDevMenuParams as n, devClientScheme as t };
43
+ export { devClientTakesDevMenuParams as n, hasDevClient as r, devClientScheme as t };