stim 1.19.0 → 1.20.1

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 (172) hide show
  1. package/README.md +20 -3
  2. package/dist/{activity-BSw0x84R.mjs → activity-BaMpUQ4-.mjs} +3 -3
  3. package/dist/{agent-device-usage-output-Bjxu_VmX.mjs → agent-device-usage-output-VPaOgGaF.mjs} +7 -7
  4. package/dist/android-CLbBJ2ve.mjs +1258 -0
  5. package/dist/{android-DE5g_5gv.mjs → android-CZh6ElG5.mjs} +2 -2
  6. package/dist/{android-BdQC6zs1.mjs → android-DE8-JfGW.mjs} +105 -47
  7. package/dist/{android-cas-C87geAg-.mjs → android-cas-BFpS84v2.mjs} +9 -5
  8. package/dist/android-cas-compiler.mjs +1 -1
  9. package/dist/android-eXfIjKJr.mjs +6 -0
  10. package/dist/api-run.mjs +159 -8
  11. package/dist/{api-DIf_s86s.mjs → api-zuX3ynYN.mjs} +5 -1
  12. package/dist/api.d.mts +98 -4
  13. package/dist/api.mjs +1 -1
  14. package/dist/{app-install-CFI4ptUL.mjs → app-install-Cg9YJy3x.mjs} +9 -8
  15. package/dist/artifact-Ctb2jpw6.mjs +807 -0
  16. package/dist/artifact-DXk_Fle_.mjs +772 -0
  17. package/dist/artifact-lifecycle-DzPpBYvK.mjs +30 -0
  18. package/dist/{browser-web-CDhqQxhv.mjs → browser-web-xQWC2RWl.mjs} +19 -19
  19. package/dist/{budget-Dz-kyXLv.mjs → budget-RFbwFpG5.mjs} +3101 -3062
  20. package/dist/build-COBA1tBc.mjs +462 -0
  21. package/dist/{build-facts-B87vo-Im.d.mts → build-facts-DcLv2HSd.d.mts} +1 -32
  22. package/dist/build-plan-CRjAA6Qi.mjs +553 -0
  23. package/dist/{cache-manifest-DiwKSyv9.mjs → cache-manifest-qA3dT2x2.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{manifest-CX0d1IkZ.mjs → ccache-CtbqWxIC.mjs} +13 -19
  26. package/dist/{chrome-BTUOo8p2.mjs → chrome-Dp2lMLBe.mjs} +1 -1
  27. package/dist/{cli-C9Zvgbdc.mjs → cli-sGqlPu1n.mjs} +20 -20
  28. package/dist/cli.mjs +1 -1
  29. package/dist/{client-CuUo8Nvg.mjs → client-zqjFd79D.mjs} +89 -307
  30. package/dist/collector-run.d.mts +4 -0
  31. package/dist/collector-run.mjs +7 -7
  32. package/dist/{command-output-Bt8ygHE7.mjs → command-output-CPDq_90S.mjs} +2 -2
  33. package/dist/{config-DC5jEtd1.mjs → config-D0LhTY3S.mjs} +8 -12
  34. package/dist/{created-devices-D0s26Hx5.mjs → created-devices-CXBMtoj5.mjs} +7 -6
  35. package/dist/{dependency-state-DKaS1OM9.mjs → dependency-state-B2m8eqsS.mjs} +2 -2
  36. package/dist/{detached-entry-pB_IPfV4.mjs → detached-entry-BXq4fIl-.mjs} +1 -1
  37. package/dist/{dev-client-CDY_zAmD.mjs → dev-client-BqYjMIaC.mjs} +2 -2
  38. package/dist/{device-BHw0WlHl.mjs → device-BgNj-qVj.mjs} +8 -8
  39. package/dist/device-D4DqjSZZ.mjs +727 -0
  40. package/dist/{device-capacity-BoN1jQkO.mjs → device-capacity-DrwHwR97.mjs} +13 -14
  41. package/dist/device-host-worker.mjs +38 -18
  42. package/dist/device-ios-DE8KJd3b.mjs +413 -0
  43. package/dist/{device-lease-Cu7PtQpZ.mjs → device-lease-C309csaB.mjs} +138 -24
  44. package/dist/{device-lease-run-D38SnZtt.mjs → device-lease-run-Baelt3nc.mjs} +4 -4
  45. package/dist/{device-pool-CP4rAsHx.mjs → device-pool-DtK9S6AD.mjs} +3 -3
  46. package/dist/{device-remote-B5GiUifk.mjs → device-remote-DjsNw8DD.mjs} +17 -68
  47. package/dist/doctor-DiP9HsIP.mjs +515 -0
  48. package/dist/{doctor-PRJH94v6.mjs → doctor-Dunu3Nv1.mjs} +333 -744
  49. package/dist/{doctor-watchman-wZhyTdp4.mjs → doctor-watchman-XJzT8tK-.mjs} +15 -13
  50. package/dist/{simslim-D9LkJxIO.mjs → eas-build-0gadvrca.mjs} +6 -152
  51. package/dist/{stim-installations-DbmUjsLv.mjs → eas-session-ledger-DJDeL4Uq.mjs} +57 -4
  52. package/dist/{error-diagnostics--v5HGOU0.mjs → error-diagnostics-BhQtoLrZ.mjs} +17 -12
  53. package/dist/errors-DzkMYh8Q.mjs +205 -0
  54. package/dist/{exec-i8GDPwq9.mjs → exec-B81Qodjn.mjs} +40 -10
  55. package/dist/{gc-CyHMcKcn.mjs → gc-D5cz5G0k.mjs} +22 -21
  56. package/dist/{device-ios-B2ruohE-.mjs → gradle-CZZo1TSA.mjs} +21 -650
  57. package/dist/{guide-dRaQJJk9.mjs → guide-DakjcoUt.mjs} +503 -251
  58. package/dist/{hosted-android-Bs7fytj7.mjs → hosted-android-C-D8Dj0_.mjs} +5 -5
  59. package/dist/{hosted-client-C5G4h_OJ.mjs → hosted-client--hNFgixu.mjs} +9 -3
  60. package/dist/{hosted-ios-Bik035eL.mjs → hosted-ios-Chx9XQyI.mjs} +3 -3
  61. package/dist/{hosted-logs-CI9Az9a4.mjs → hosted-logs-Bkz0Hxzh.mjs} +8 -8
  62. package/dist/{hosted-macos-DABm3ScO.mjs → hosted-macos-ckTjN-0V.mjs} +7 -6
  63. package/dist/{hosted-native-DbV2aUVw.mjs → hosted-native-3KXZ5-qn.mjs} +17 -14
  64. package/dist/{idle-shutdown-DYiMBn34.mjs → idle-shutdown-DhAUyf5s.mjs} +7 -7
  65. package/dist/{ios-DYUr9LGc.mjs → ios-BDBN-xpf.mjs} +8 -7
  66. package/dist/ios-CQ8bHQXB.mjs +1112 -0
  67. package/dist/{ios-DCrkgXEM.mjs → ios-VGvNdsv2.mjs} +1 -1
  68. package/dist/{ios-device-CrW8aMb5.mjs → ios-device-B1B14xND.mjs} +1 -1
  69. package/dist/{ios-device-CJ_ZOGky.mjs → ios-device-BWHKGaJq.mjs} +3 -3
  70. package/dist/{ios-BWbHFZVz.mjs → ios-o896T9PE.mjs} +195 -35
  71. package/dist/ios-project-BeOXKPt2.mjs +197 -0
  72. package/dist/{ios-state-By0XuLTQ.mjs → ios-state-BsXMwo5y.mjs} +1 -1
  73. package/dist/js-swap-Z_mSuRrx.mjs +432 -0
  74. package/dist/{react-native-ios-CSpIxexZ.mjs → launch-BootbMk4.mjs} +59 -612
  75. package/dist/launch-V1zqiOYn.mjs +745 -0
  76. package/dist/{launch-verify-DCveSE6d.mjs → launch-verify-Dl78EVgR.mjs} +26 -7
  77. package/dist/{logs-Bao1HOMy.mjs → logs-Bh4eqCCc.mjs} +11 -11
  78. package/dist/{macos-ciyBdTY5.mjs → macos-D7irBW3A.mjs} +42 -50
  79. package/dist/macos-kivF8qKz.mjs +2 -0
  80. package/dist/macos-run.mjs +1 -1
  81. package/dist/maintenance-run.mjs +13 -10
  82. package/dist/{metro-DI2AjPF_.mjs → metro-_ZIE3Axg.mjs} +18 -5
  83. package/dist/{metro-gateway-BxpJLIwh.mjs → metro-gateway-BzlQZQmU.mjs} +2 -2
  84. package/dist/miss-reason-SuTptY-I.mjs +238 -0
  85. package/dist/{named-ports-B4iWH4E-.mjs → named-ports-O1TIl7tx.mjs} +3 -3
  86. package/dist/native-android-D94RlJ-X.mjs +226 -0
  87. package/dist/native-gradle-inputs-BQnIdAlL.mjs +356 -0
  88. package/dist/{native-runtime-BGxsbfny.mjs → native-runtime-D024BAvm.mjs} +9 -8
  89. package/dist/native-xcode-inputs-UElfGs59.mjs +306 -0
  90. package/dist/native-xcode-ios-CjS-nDVY.mjs +434 -0
  91. package/dist/{ndjson-LGZAMsqa.mjs → ndjson-GOnbyvso.mjs} +6 -6
  92. package/dist/offload-worker.d.mts +41 -7
  93. package/dist/offload-worker.mjs +409 -74
  94. package/dist/{ownership-EB0ySdGK.mjs → ownership-BrjepDiv.mjs} +2 -2
  95. package/dist/{placement-log-Dxe34rJm.mjs → placement-log-BItXET1x.mjs} +1 -1
  96. package/dist/plan-Jwu_vr-F.mjs +260 -0
  97. package/dist/plan-placement-B466UYMU.mjs +73 -0
  98. package/dist/{ports-ByPc0_97.mjs → ports-BFRL6JTj.mjs} +3 -3
  99. package/dist/{prebuild-BKJ3wJI1.mjs → prebuild-DB_zLOLc.mjs} +4 -4
  100. package/dist/{preview-BbSottmO.mjs → preview-BRLFRhTz.mjs} +50 -32
  101. package/dist/project-DX8fXyw_.mjs +1131 -0
  102. package/dist/project-plan-BPwbLwQu.mjs +10 -0
  103. package/dist/{pull-request-IHNdMnG8.mjs → pull-request-vOhLNmIb.mjs} +1 -1
  104. package/dist/pull-requests.mjs +1 -1
  105. package/dist/react-native-android-CuXM3QS8.mjs +921 -0
  106. package/dist/react-native-build-JUF31S8U.mjs +239 -0
  107. package/dist/react-native-doctor-BQHqiXaQ.mjs +78 -0
  108. package/dist/react-native-ios-DtVO4qf2.mjs +595 -0
  109. package/dist/{recordings-Bv8McZN4.mjs → recordings-Bk-VivUV.mjs} +1 -1
  110. package/dist/{reload-rAPdqeRR.mjs → reload-D9V7D8gP.mjs} +17 -13
  111. package/dist/remote-CZiTijxG.mjs +192 -0
  112. package/dist/{remote-cache-N3hAEaAL.mjs → remote-cache-fxcl5C-L.mjs} +5 -5
  113. package/dist/result-BrfgXtdO.mjs +186 -0
  114. package/dist/{run-lAkle1-c.mjs → run-ClC8UVB5.mjs} +3 -3
  115. package/dist/{server-bare-CkIjnegq.mjs → server-bare-dWjAarki.mjs} +5 -5
  116. package/dist/server-command-DnJYLnr4.mjs +69 -0
  117. package/dist/{server-expo-n3tUi3Em.mjs → server-expo-CUuzP9Mp.mjs} +107 -82
  118. package/dist/server-expo-Dvkd7JcF.mjs +2 -0
  119. package/dist/{settings-CxgngUZk.mjs → settings-Bbztm4oV.mjs} +179 -129
  120. package/dist/{settings-2am7TSxp.mjs → settings-BuKMOANA.mjs} +6 -6
  121. package/dist/{state-lKh8shBp.d.mts → settings-vk3mJGSm.d.mts} +4 -2
  122. package/dist/settings.schema.json +84 -0
  123. package/dist/simslim-ChMfe8rg.mjs +149 -0
  124. package/dist/{slot-launch-HV_KtPIw.mjs → slot-launch-CeCRr6MK.mjs} +6 -6
  125. package/dist/{stage-BgaZJVZY.mjs → stage-BNKKdDNc.mjs} +6 -3
  126. package/dist/{start-DtxthMfI.mjs → start-CRkG-mZ7.mjs} +97 -68
  127. package/dist/start-mh6bS27z.mjs +2 -0
  128. package/dist/{state-Tp4uImDS.mjs → state-BUpAmt2r.mjs} +1 -1
  129. package/dist/{state-D2KtnALG.mjs → state-lqxdOH_g.mjs} +32 -12
  130. package/dist/{stats-8EJ5ivFT.mjs → stats-CaB1MxMi.mjs} +5 -5
  131. package/dist/{status-BEeL6IKz.mjs → status-BDGHwkCs.mjs} +3 -1
  132. package/dist/{status-BOyp0CUl.mjs → status-C7vzkInu.mjs} +81 -293
  133. package/dist/status-watch-ZaVqRdtW.mjs +296 -0
  134. package/dist/{stim-desktop-C65jk_q2.mjs → stim-desktop-8GQX2OV8.mjs} +1 -1
  135. package/dist/{stop-zDlknFoz.mjs → stop-BO80KJoT.mjs} +21 -20
  136. package/dist/{stop-DRipAg-e.mjs → stop-BU7JaFCg.mjs} +2 -2
  137. package/dist/{stop-D0UIpZuh.mjs → stop-Cftw_sXJ.mjs} +5 -5
  138. package/dist/supervisor-run.d.mts +7 -2
  139. package/dist/supervisor-run.mjs +32 -20
  140. package/dist/{support-DsNaFg6D.mjs → support-Ca6PZbpr.mjs} +17 -7
  141. package/dist/{support-CNqYkV0y.mjs → support-Co0wk8Cv.mjs} +61 -8
  142. package/dist/{swiftpm-macos-aJzPAj1t.mjs → swiftpm-macos-siFSkmCO.mjs} +5 -5
  143. package/dist/tailnet-D7-tE_ug.mjs +265 -0
  144. package/dist/toolchain-B12psPA2.mjs +2 -0
  145. package/dist/{toolchain-C3xSoyUl.mjs → toolchain-SqehyPLw.mjs} +206 -53
  146. package/dist/{trigger-CAhmG-4s.mjs → trigger-C0MWBi8O.mjs} +2 -2
  147. package/dist/trigger-SHLOWJ4O.mjs +2 -0
  148. package/dist/{warm-progress-pFLB2e6P.mjs → warm-progress-5FAXkXIg.mjs} +6 -6
  149. package/dist/{watchman-BL1IdOtq.mjs → watchman-CqmaGcIb.mjs} +6 -6
  150. package/dist/{web-DbbrPUn0.mjs → web-BTjzE8mc.mjs} +9 -13
  151. package/dist/web-CHN5gh34.mjs +2 -0
  152. package/dist/web-run.mjs +10 -10
  153. package/dist/{workspace-state-CR9X86xJ.mjs → workspace-state-CvgTFe-h.mjs} +36 -36
  154. package/dist/{workspaces-Djb2gfi9.mjs → workspaces-C4kqIOlx.mjs} +1260 -1258
  155. package/dist/worktree-Cgnm6vZt.mjs +2 -0
  156. package/dist/{worktree-BL4M1rhB.mjs → worktree-DtRsh6go.mjs} +86 -50
  157. package/package.json +6 -5
  158. package/shim/native-android.gradle +101 -0
  159. package/dist/android-BXc6BmEi.mjs +0 -3732
  160. package/dist/android-BvV1gGdN.mjs +0 -4
  161. package/dist/ios-ITYno9rO.mjs +0 -2241
  162. package/dist/macos-nIOATJmR.mjs +0 -2
  163. package/dist/metro-store-BAHFcJm6.mjs +0 -106
  164. package/dist/miss-reason-CjQCOKqq.mjs +0 -1743
  165. package/dist/plan-placement-BVY59qa8.mjs +0 -290
  166. package/dist/project-B5eQ1USs.mjs +0 -612
  167. package/dist/react-native-ios-BMh2i25I.mjs +0 -2
  168. package/dist/server-expo-DGsdUGX2.mjs +0 -2
  169. package/dist/start-D8NbxNBb.mjs +0 -2
  170. package/dist/trigger-CoalsMTV.mjs +0 -2
  171. package/dist/web-DFpFeZu5.mjs +0 -2
  172. package/dist/worktree-DV-A0LNL.mjs +0 -2
@@ -1,14 +1,23 @@
1
- import { t as getExecutor } from "./exec-i8GDPwq9.mjs";
1
+ import { t as getExecutor } from "./exec-B81Qodjn.mjs";
2
+ import { O as writeConfigSetting } from "./config-D0LhTY3S.mjs";
3
+ import { d as androidLayoutSetting, y as iosProjectDirSetting } from "./settings-Bbztm4oV.mjs";
4
+ import { D as fingerprintProject, M as refingerprintAfterMutation } from "./device-lease-C309csaB.mjs";
5
+ import { w as workspaceLogsDir, x as workspaceDir } from "./workspace-state-CvgTFe-h.mjs";
2
6
  import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
3
- import { D as fingerprintProject, M as refingerprintAfterMutation } from "./device-lease-Cu7PtQpZ.mjs";
4
- import { r as CCACHE_UNAVAILABLE, s as resolveCcache, t as manifestDigest } from "./manifest-CX0d1IkZ.mjs";
5
- import { c as podsAreStale, f as runPodInstall, l as readPodState, o as workerToolchain } from "./toolchain-C3xSoyUl.mjs";
6
- import { m as assembleTaskFor, o as buildAndroid, s as buildIos, u as gradlewPath } from "./device-ios-B2ruohE-.mjs";
7
- import { n as recordPrebuild, r as runPrebuild, t as planPrebuild } from "./prebuild-BKJ3wJI1.mjs";
8
- import { d as podAction } from "./support-CNqYkV0y.mjs";
9
- import { r as stageBundle, t as resolveBundleExtras } from "./stage-BgaZJVZY.mjs";
10
- import { t as logLines } from "./run-lAkle1-c.mjs";
11
- import { chmodSync, constants, copyFileSync, cpSync, createReadStream, existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
7
+ import { d as projectRegistry, h as selectNativeXcodeProject } from "./project-DX8fXyw_.mjs";
8
+ import { o as parseNdjsonText } from "./ndjson-GOnbyvso.mjs";
9
+ import { n as CCACHE_UNAVAILABLE, o as resolveCcache } from "./ccache-CtbqWxIC.mjs";
10
+ import { i as assembleTaskFor } from "./gradle-CZZo1TSA.mjs";
11
+ import { f as podsAreStale, g as runPodInstall, p as readPodState, u as workerToolchain } from "./toolchain-SqehyPLw.mjs";
12
+ import { a as validateGradleManifest, d as verifyNativeTransfer, m as manifestDigest, n as gradleStateDirectories, o as verifyGradleTransfer, r as nativeGradleOutputs, t as gradleOffloadInputs } from "./native-gradle-inputs-BQnIdAlL.mjs";
13
+ import { n as buildAndroid, o as gradlewPath, r as buildIos } from "./react-native-build-JUF31S8U.mjs";
14
+ import { n as buildAndroidOperation, t as buildIosOperation } from "./build-COBA1tBc.mjs";
15
+ import { n as recordPrebuild, r as runPrebuild, t as planPrebuild } from "./prebuild-DB_zLOLc.mjs";
16
+ import { f as podAction } from "./support-Co0wk8Cv.mjs";
17
+ import { r as stageBundle, t as resolveBundleExtras } from "./stage-BNKKdDNc.mjs";
18
+ import { t as logLines } from "./run-ClC8UVB5.mjs";
19
+ import { r as nativeXcodeMetadataDirectories } from "./native-xcode-inputs-UElfGs59.mjs";
20
+ import { chmodSync, constants, copyFileSync, cpSync, createReadStream, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
12
21
  import { basename, dirname, join } from "node:path";
13
22
  import { createHash } from "node:crypto";
14
23
  //#region src/offload/worker.ts
@@ -80,12 +89,6 @@ function ensureParents(root, path) {
80
89
  mkdirSync(current);
81
90
  }
82
91
  }
83
- /**
84
- * Makes `src` hold exactly the manifest's files: a file the manifest names is rewritten unless this process
85
- * wrote that same content there and nothing touched it since; a file that git would list as untracked and not
86
- * ignored, and that the manifest does not name, is deleted, as is one the previous manifest named. Ignored
87
- * files (dependencies, generated native projects) stay, and the fingerprint check covers them.
88
- */
89
92
  function materialize(job, src) {
90
93
  const recordFile = join(job.area, "mirror.json");
91
94
  let previous = {};
@@ -107,10 +110,52 @@ function materialize(job, src) {
107
110
  "/dev/null"
108
111
  ], { timeoutMs: 3e4 });
109
112
  }
113
+ getExecutor().runFile("git", [
114
+ "-C",
115
+ src,
116
+ "read-tree",
117
+ "--empty"
118
+ ], { timeoutMs: 3e4 });
119
+ let retained = [];
120
+ if (job.native) {
121
+ if (job.native.provider === "gradle") {
122
+ const declaration = gradleOffloadInputs(job.native.inputs);
123
+ validateGradleManifest(job.project, declaration, job.manifest);
124
+ let receipt = {};
125
+ try {
126
+ receipt = JSON.parse(readFileSync(join(job.area, "gradle-outputs.json"), "utf8"));
127
+ } catch {}
128
+ const allowed = [...declaration.outputs, ...gradleStateDirectories(job.project)];
129
+ if (receipt.project === job.project && Array.isArray(receipt.directories)) retained = allowed.filter((path) => receipt.directories.includes(path));
130
+ retained = nativeGradleOutputs(src, {
131
+ complete: true,
132
+ ignored: [],
133
+ outputs: retained
134
+ }, retained.map((path) => join(src, path)));
135
+ }
136
+ const keep = new Set(job.manifest.flatMap((entry) => {
137
+ const parts = entry.path.split("/");
138
+ return parts.map((_, index) => parts.slice(0, index + 1).join("/"));
139
+ }));
140
+ const removeUnknown = (directory, prefix) => {
141
+ for (const name of readdirSync(directory)) {
142
+ if (!prefix && name === ".git") continue;
143
+ const path = prefix ? `${prefix}/${name}` : name;
144
+ const absolute = join(directory, name);
145
+ if (retained.includes(path)) continue;
146
+ if (!keep.has(path) && !retained.some((output) => output.startsWith(`${path}/`))) rmSync(absolute, {
147
+ recursive: true,
148
+ force: true
149
+ });
150
+ else if (lstatSync(absolute).isDirectory()) removeUnknown(absolute, path);
151
+ }
152
+ };
153
+ removeUnknown(src, "");
154
+ }
110
155
  const next = {};
111
156
  const wanted = /* @__PURE__ */ new Set();
112
157
  let written = 0;
113
- for (const entry of job.manifest) {
158
+ for (const entry of job.manifest.toSorted((a, b) => a.path.split("/").length - b.path.split("/").length)) {
114
159
  wanted.add(entry.path);
115
160
  const target = join(src, entry.path);
116
161
  const known = previous[entry.path];
@@ -118,7 +163,16 @@ function materialize(job, src) {
118
163
  try {
119
164
  stat = lstatSync(target);
120
165
  } catch {}
121
- if (known && stat && known.sha256 === entry.sha256 && known.kind === entry.kind && stat.mtimeMs === known.mtimeMs && stat.size === known.size) {
166
+ if (entry.kind === "directory" && stat?.isDirectory()) {
167
+ next[entry.path] = {
168
+ sha256: entry.sha256,
169
+ kind: entry.kind,
170
+ mtimeMs: stat.mtimeMs,
171
+ size: stat.size
172
+ };
173
+ continue;
174
+ }
175
+ if (known && stat && (!job.native || (entry.kind === "link" ? stat.isSymbolicLink() : stat.isFile()) && createHash("sha256").update(entry.kind === "link" ? readlinkSync(target) : readFileSync(target)).digest("hex") === entry.sha256 && (entry.kind === "link" || (stat.mode & 73) === (entry.kind === "exec" ? 73 : 0))) && known.sha256 === entry.sha256 && known.kind === entry.kind && stat.mtimeMs === known.mtimeMs && stat.size === known.size) {
122
176
  next[entry.path] = known;
123
177
  continue;
124
178
  }
@@ -128,7 +182,8 @@ function materialize(job, src) {
128
182
  force: true
129
183
  });
130
184
  const blob = blobPath(job.blobs, entry.sha256);
131
- if (entry.kind === "link") symlinkSync(readFileSync(blob, "utf8"), target);
185
+ if (entry.kind === "directory") mkdirSync(target);
186
+ else if (entry.kind === "link") symlinkSync(readFileSync(blob, "utf8"), target);
132
187
  else {
133
188
  copyFileSync(blob, target, constants.COPYFILE_FICLONE);
134
189
  chmodSync(target, entry.kind === "exec" ? 493 : 420);
@@ -142,7 +197,22 @@ function materialize(job, src) {
142
197
  };
143
198
  written += 1;
144
199
  }
145
- const untracked = getExecutor().runFile("git", [
200
+ if (job.native) {
201
+ const indexed = job.manifest.filter((entry) => entry.kind !== "directory").map((entry) => `${entry.path}\0`);
202
+ if (indexed.length) getExecutor().runFile("git", [
203
+ "-C",
204
+ src,
205
+ "update-index",
206
+ "--add",
207
+ "--info-only",
208
+ "-z",
209
+ "--stdin"
210
+ ], {
211
+ input: indexed.join(""),
212
+ timeoutMs: 12e4
213
+ });
214
+ }
215
+ const untracked = job.native ? [] : getExecutor().runFile("git", [
146
216
  "-C",
147
217
  src,
148
218
  "ls-files",
@@ -155,9 +225,12 @@ function materialize(job, src) {
155
225
  }).split("\0").filter(Boolean);
156
226
  let removed = 0;
157
227
  for (const path of /* @__PURE__ */ new Set([...untracked, ...Object.keys(previous)])) {
158
- if (wanted.has(path) || !realParents(src, path)) continue;
228
+ if (wanted.has(path) || retained.some((output) => output === path || output.startsWith(`${path}/`)) || !realParents(src, path)) continue;
159
229
  try {
160
- rmSync(join(src, path), { force: true });
230
+ rmSync(join(src, path), {
231
+ force: true,
232
+ ...job.native ? { recursive: true } : {}
233
+ });
161
234
  removed += 1;
162
235
  } catch {}
163
236
  }
@@ -288,9 +361,62 @@ async function build(job) {
288
361
  note("sync", `${job.manifest.length} files, ${mirrored.written} written, ${mirrored.removed} removed`);
289
362
  let fingerprint;
290
363
  let compiled;
291
- if (job.platform === "macos") {
364
+ if (job.native?.provider === "gradle") {
365
+ if (job.platform !== "android" || job.expectedFingerprint !== null) return failed("unsupported-provider", "Native Gradle needs an Android request with no reusable artifact identity.");
366
+ const selected = projectRegistry.selectAndroid(root);
367
+ if ("problem" in selected || selected.id !== "native-android") return failed("provider-mismatch", "The transferred project did not select the native Android integration.");
368
+ if (!verifyGradleTransfer(src, job.project, job.native.inputs, job.manifest, job.native.sourceDigest)) return failed("source-mismatch", "The materialized native inputs do not match the source transfer.");
369
+ compiled = await compileNativeAndroid(job, root, log, time);
370
+ if (!compiled.ok) return failed(compiled.code, compiled.message);
371
+ try {
372
+ const model = JSON.parse(readFileSync(join(workspaceDir(root), "gradle-build", `native-apk-${encodeURIComponent(job.android?.variant ?? "debug")}.json`), "utf8"));
373
+ const outputs = nativeGradleOutputs(src, job.native.inputs, model.buildDirectories);
374
+ if (!verifyGradleTransfer(src, job.project, job.native.inputs, job.manifest, job.native.sourceDigest)) throw new Error("The native source changed while the worker compiled it.");
375
+ const directories = [...outputs, ...gradleStateDirectories(job.project).filter((path) => lstatSync(join(src, path), { throwIfNoEntry: false })?.isDirectory())];
376
+ const receipt = join(job.area, "gradle-outputs.json");
377
+ const tmp = `${receipt}.${process.pid}.tmp`;
378
+ writeFileSync(tmp, JSON.stringify({
379
+ project: job.project,
380
+ directories
381
+ }));
382
+ renameSync(tmp, receipt);
383
+ } catch (error) {
384
+ if (compiled.temporary) rmSync(compiled.temporary, {
385
+ recursive: true,
386
+ force: true
387
+ });
388
+ return failed("source-moved", error.message);
389
+ }
390
+ fingerprint = null;
391
+ } else if (job.native) {
392
+ if (job.platform !== "ios" || job.native.provider !== "xcode") return failed("unsupported-provider", "The worker does not implement this native provider.");
393
+ const selected = projectRegistry.selectIos(root);
394
+ if ("problem" in selected || selected.id !== "native-xcode") return failed("provider-mismatch", "The transferred project did not select the native Xcode integration.");
395
+ let metadataDirectories;
396
+ try {
397
+ metadataDirectories = nativeXcodeMetadataDirectories(selectNativeXcodeProject(root, job.scheme ?? void 0, job.configuration ?? void 0));
398
+ if (!verifyNativeTransfer(src, job.manifest, job.native.sourceDigest, metadataDirectories)) return failed("source-mismatch", "The materialized native inputs do not match the source transfer.");
399
+ } catch (error) {
400
+ return failed("source-mismatch", error.message);
401
+ }
402
+ const native = job.native;
403
+ const refused = await time("fingerprintMs", () => nativeIdentityRefusal(job, native, root, () => selected.load({})));
404
+ if (refused) return failed("identity-mismatch", refused);
405
+ compiled = await compileNativeIos(job, root, log, time);
406
+ if (!compiled.ok) return failed(compiled.code, compiled.message);
407
+ try {
408
+ if (!verifyNativeTransfer(src, job.manifest, job.native.sourceDigest, metadataDirectories)) throw new Error("The native source changed while the worker compiled it.");
409
+ } catch (error) {
410
+ if (compiled.temporary) rmSync(compiled.temporary, {
411
+ recursive: true,
412
+ force: true
413
+ });
414
+ return failed("source-moved", error.message);
415
+ }
416
+ fingerprint = job.expectedFingerprint;
417
+ } else if (job.platform === "macos") {
292
418
  fingerprint = await time("fingerprintMs", () => manifestDigest(job.manifest));
293
- if (fingerprint !== job.expectedFingerprint) return failed("fingerprint-mismatch", `the manifest there fingerprints ${fingerprint.slice(0, 12)}, here ${job.expectedFingerprint.slice(0, 12)}`);
419
+ if (fingerprint !== job.expectedFingerprint) return failed("fingerprint-mismatch", `the manifest there fingerprints ${fingerprint.slice(0, 12)}, here ${job.expectedFingerprint?.slice(0, 12)}`);
294
420
  compiled = await compileMacos(job, root, log, time);
295
421
  if (!compiled.ok) return failed(compiled.code, compiled.message);
296
422
  } else {
@@ -300,7 +426,26 @@ async function build(job) {
300
426
  return failed("deps-failed", error.message);
301
427
  }
302
428
  const platform = job.platform;
303
- const initial = await time("fingerprintMs", () => fingerprintProject(root, { platform }));
429
+ let iosProject;
430
+ try {
431
+ iosProject = iosProjectDirSetting({ ios: { projectPath: job.iosProjectPath ?? void 0 } }, root);
432
+ } catch (error) {
433
+ return failed("bad-request", error.message);
434
+ }
435
+ let androidLayout;
436
+ try {
437
+ androidLayout = androidLayoutSetting({ android: {
438
+ gradleRoot: job.android?.gradleRoot ?? void 0,
439
+ module: job.android?.module ?? void 0
440
+ } }, root, realSrc);
441
+ } catch (error) {
442
+ return failed("bad-request", error.message);
443
+ }
444
+ const initial = await time("fingerprintMs", () => fingerprintProject(root, {
445
+ platform,
446
+ iosProjectPath: iosProject.relative,
447
+ androidLayout
448
+ }));
304
449
  if (!initial) return failed("no-fingerprint", "The remote Mac could not fingerprint the project.");
305
450
  const plan = planPrebuild(root, platform, {
306
451
  isExpo: job.isExpo,
@@ -317,11 +462,14 @@ async function build(job) {
317
462
  mutations.push("prebuild");
318
463
  }
319
464
  if (platform === "ios") {
320
- const podState = readPodState(root);
321
- const pods = podAction(podState, podsAreStale(podState.lockText, podState.manifestText));
465
+ const podState = readPodState(root, iosProject.dir);
466
+ const pods = podAction(podState, podsAreStale(podState.lockText, podState.manifestText, podState.dir));
322
467
  if (pods.install) {
323
468
  note("pods", `${pods.reason ?? "Pods are stale"} -> pod install`);
324
- const result = await time("podsMs", () => runPodInstall(root, log, { onHeartbeat: (line) => note("pods", line) }));
469
+ const result = await time("podsMs", () => runPodInstall(root, log, {
470
+ directory: iosProject.dir,
471
+ onHeartbeat: (line) => note("pods", line)
472
+ }));
325
473
  if (result?.failed) return failed("pods-failed", result.reason ?? "pod install failed.");
326
474
  mutations.push("pods");
327
475
  }
@@ -331,57 +479,240 @@ async function build(job) {
331
479
  const after = await time("fingerprintMs", () => refingerprintAfterMutation({
332
480
  projectRoot: root,
333
481
  platform,
334
- previousHash: initial.hash
482
+ previousHash: initial.hash,
483
+ iosProjectPath: iosProject.relative,
484
+ androidLayout
335
485
  }));
336
486
  if (!after) return failed("no-fingerprint", `No fingerprint after ${mutations.join(", ")}.`);
337
487
  fingerprint = after.hash;
338
488
  if (mutations.includes("prebuild")) recordPrebuild(root, platform, after.hash);
339
489
  }
340
- if (fingerprint !== job.expectedFingerprint) return failed("fingerprint-mismatch", `the checkout there fingerprints ${fingerprint.slice(0, 12)}, here ${job.expectedFingerprint.slice(0, 12)}`);
341
- compiled = platform === "android" ? await compileAndroid(job, root, log, time) : await compileIos(job, root, log, time);
490
+ if (fingerprint !== job.expectedFingerprint) return failed("fingerprint-mismatch", `the checkout there fingerprints ${fingerprint.slice(0, 12)}, here ${job.expectedFingerprint?.slice(0, 12)}`);
491
+ compiled = platform === "android" ? await compileAndroid(job, root, log, time, androidLayout) : await compileIos(job, root, log, time);
342
492
  if (!compiled.ok) return failed(compiled.code, compiled.message);
493
+ const builtFingerprint = fingerprint;
343
494
  const settled = await time("fingerprintMs", () => refingerprintAfterMutation({
344
495
  projectRoot: root,
345
496
  platform,
346
- previousHash: fingerprint
497
+ previousHash: builtFingerprint,
498
+ iosProjectPath: iosProject.relative,
499
+ androidLayout
347
500
  }));
348
501
  if (!settled || settled.moved) return failed("fingerprint-moved", "The inputs changed during the build there.");
349
502
  }
350
- const out = join(job.area, "out", job.job);
351
- if (job.platform !== "macos") rmSync(out, {
352
- recursive: true,
353
- force: true
354
- });
355
- mkdirSync(out, { recursive: true });
356
- const archive = join(out, "app.tgz");
357
- const name = basename(compiled.path);
358
- if (job.platform === "ios" || job.platform === "android") cpSync(compiled.path, join(out, name), {
359
- recursive: true,
360
- verbatimSymlinks: true,
361
- mode: constants.COPYFILE_FICLONE
362
- });
363
- await time("packageMs", () => getExecutor().runFileAsync("tar", [
364
- "-czf",
365
- archive,
366
- "--options",
367
- "gzip:compression-level=1",
368
- "-C",
369
- dirname(compiled.path),
370
- name
371
- ], { timeoutMs: 6e5 }));
372
- const sha256 = await time("packageMs", () => sha256Of(archive));
373
- return {
374
- ok: true,
375
- artifact: {
376
- path: archive,
377
- name,
378
- size: statSync(archive).size,
379
- sha256
380
- },
381
- fingerprint,
382
- compilationCache: compiled.cache,
383
- timings
503
+ try {
504
+ const out = join(job.area, "out", job.job);
505
+ if (job.platform !== "macos") rmSync(out, {
506
+ recursive: true,
507
+ force: true
508
+ });
509
+ mkdirSync(out, { recursive: true });
510
+ const archive = join(out, "app.tgz");
511
+ const name = basename(compiled.path);
512
+ if (job.platform === "ios" || job.platform === "android") cpSync(compiled.path, join(out, name), {
513
+ recursive: true,
514
+ verbatimSymlinks: true,
515
+ mode: constants.COPYFILE_FICLONE
516
+ });
517
+ await time("packageMs", () => getExecutor().runFileAsync("tar", [
518
+ "-czf",
519
+ archive,
520
+ "--options",
521
+ "gzip:compression-level=1",
522
+ "-C",
523
+ dirname(compiled.path),
524
+ name
525
+ ], { timeoutMs: 6e5 }));
526
+ const sha256 = await time("packageMs", () => sha256Of(archive));
527
+ return {
528
+ ok: true,
529
+ artifact: {
530
+ path: archive,
531
+ name,
532
+ size: statSync(archive).size,
533
+ sha256
534
+ },
535
+ fingerprint,
536
+ ...compiled.androidPackage ? { androidPackage: compiled.androidPackage } : {},
537
+ ...job.native ? { sourceDigest: job.native.sourceDigest } : {},
538
+ compilationCache: compiled.cache,
539
+ timings
540
+ };
541
+ } finally {
542
+ if (compiled.temporary) rmSync(compiled.temporary, {
543
+ recursive: true,
544
+ force: true
545
+ });
546
+ }
547
+ }
548
+ function isRecord(value) {
549
+ return typeof value === "object" && value !== null && !Array.isArray(value);
550
+ }
551
+ function differingParameters(here, there, path) {
552
+ if (JSON.stringify(here) === JSON.stringify(there)) return [];
553
+ if (!isRecord(here) || !isRecord(there)) return [path];
554
+ return [.../* @__PURE__ */ new Set([...Object.keys(here), ...Object.keys(there)])].toSorted().flatMap((key) => differingParameters(here[key], there[key], `${path}.${key}`));
555
+ }
556
+ function unused() {
557
+ throw new Error("The native identity check does not prepare or compile.");
558
+ }
559
+ async function nativeIdentityRefusal(job, native, root, load) {
560
+ if (!job.optimizations) return "The native Xcode build has no compiler options.";
561
+ try {
562
+ const recipe = (await load()).artifact({
563
+ root,
564
+ logFile: join(job.area, "build.ndjson"),
565
+ configuration: job.configuration,
566
+ ...job.scheme ? { buildScheme: job.scheme } : {},
567
+ target: {
568
+ udid: null,
569
+ destination: "generic/platform=iOS Simulator",
570
+ sdk: "iphonesimulator",
571
+ arch: native.arch,
572
+ keyArch: native.arch,
573
+ offloadRuntime: () => job.runtime,
574
+ offloadRefusal: null
575
+ },
576
+ device: null,
577
+ optimizations: job.optimizations,
578
+ cache: {
579
+ read: true,
580
+ write: true,
581
+ remote: false
582
+ },
583
+ phase: unused,
584
+ note: unused,
585
+ logWriter: unused,
586
+ estimates: unused,
587
+ step: unused,
588
+ setPodsMs: unused
589
+ });
590
+ const identity = await recipe.identity();
591
+ if ("cacheIneligible" in identity) return `This Mac cannot key the native build: ${identity.cacheIneligible}`;
592
+ if (identity.key === native.cacheKey) return null;
593
+ const here = recipe.offload?.request(job.runtime ?? "").native?.snapshot.parameters;
594
+ const differing = differingParameters(native.parameters, here, "parameters");
595
+ return differing.length ? `This Mac keys the native build differently in ${differing.join(", ")}.` : "This Mac keys the native build differently from the same parameters.";
596
+ } catch (error) {
597
+ return `This Mac cannot key the native build: ${error.message}`;
598
+ }
599
+ }
600
+ async function compileNativeIos(job, root, log, time) {
601
+ if (job.native?.provider !== "xcode" || !job.optimizations) return {
602
+ ok: false,
603
+ code: "bad-request",
604
+ message: "The native Xcode build has no compiler options."
605
+ };
606
+ const native = job.native;
607
+ for (const key of [
608
+ "compilationCache",
609
+ "swiftCompilationCache",
610
+ "prefixMapping"
611
+ ]) {
612
+ const value = job.optimizations[key];
613
+ writeConfigSetting({
614
+ scope: "workspace",
615
+ projectPath: root
616
+ }, `optimizations.ios.${key}`, value ?? void 0);
617
+ }
618
+ note("build", `native Xcode ${job.configuration ?? "Debug"}`);
619
+ const logFile = join(workspaceLogsDir(root), "build-ios.ndjson");
620
+ try {
621
+ rmSync(logFile, { force: true });
622
+ const built = await time("buildMs", () => buildIosOperation(root, {
623
+ scheme: job.scheme ?? void 0,
624
+ configuration: job.configuration ?? void 0,
625
+ arch: native.arch ?? "all",
626
+ remoteBuild: "local"
627
+ }));
628
+ if (built.cacheKey !== native.cacheKey || built.cacheSkipped) {
629
+ rmSync(dirname(built.appPath), {
630
+ recursive: true,
631
+ force: true
632
+ });
633
+ return {
634
+ ok: false,
635
+ code: "fingerprint-mismatch",
636
+ message: "The worker resolved a different native artifact identity."
637
+ };
638
+ }
639
+ return {
640
+ ok: true,
641
+ path: built.appPath,
642
+ cache: built.compilationCache,
643
+ temporary: dirname(built.appPath)
644
+ };
645
+ } catch (error) {
646
+ return {
647
+ ok: false,
648
+ code: "native-build-failed",
649
+ message: error.message
650
+ };
651
+ } finally {
652
+ if (existsSync(logFile)) for (const record of parseNdjsonText(readFileSync(logFile, "utf8"))) log.write(record);
653
+ }
654
+ }
655
+ async function compileNativeAndroid(job, root, log, time) {
656
+ const options = job.android;
657
+ if (!options) return {
658
+ ok: false,
659
+ code: "bad-request",
660
+ message: "The native Gradle job has no build options."
384
661
  };
662
+ for (const key of [
663
+ "compilerCache",
664
+ "pch",
665
+ "gradleBuildCache"
666
+ ]) writeConfigSetting({
667
+ scope: "workspace",
668
+ projectPath: root
669
+ }, `optimizations.android.${key}`, options[key]);
670
+ const idleMs = job.gradleDaemonIdleMs ?? 0;
671
+ limitDaemonIdle(idleMs > 0 ? idleMs : 6e4);
672
+ const gradlew = join(root, process.platform === "win32" ? "gradlew.bat" : "gradlew");
673
+ const stop = () => {
674
+ stopGradleDaemons(gradlew, 4e3);
675
+ process.exit(143);
676
+ };
677
+ process.once("SIGTERM", stop);
678
+ const logFile = join(workspaceLogsDir(root), "build-android.ndjson");
679
+ note("build", `native Gradle ${options.variant ?? "debug"}`);
680
+ try {
681
+ rmSync(logFile, { force: true });
682
+ const built = await time("buildMs", () => buildAndroidOperation(root, {
683
+ variant: options.variant ?? void 0,
684
+ abi: options.abi ?? "all",
685
+ remoteBuild: "local"
686
+ }));
687
+ if (built.cacheKey !== null || !built.cacheSkipped || !built.androidPackage) {
688
+ rmSync(dirname(built.apkPath), {
689
+ recursive: true,
690
+ force: true
691
+ });
692
+ return {
693
+ ok: false,
694
+ code: "unexpected-cache-identity",
695
+ message: "The native Gradle worker returned an unsupported artifact identity or package."
696
+ };
697
+ }
698
+ return {
699
+ ok: true,
700
+ path: built.apkPath,
701
+ temporary: dirname(built.apkPath),
702
+ cache: built.ccache,
703
+ androidPackage: built.androidPackage
704
+ };
705
+ } catch (error) {
706
+ return {
707
+ ok: false,
708
+ code: "native-build-failed",
709
+ message: error.message
710
+ };
711
+ } finally {
712
+ process.off("SIGTERM", stop);
713
+ if (idleMs <= 0) stopGradleDaemons(gradlew, 6e4);
714
+ if (existsSync(logFile)) for (const record of parseNdjsonText(readFileSync(logFile, "utf8"))) log.write(record);
715
+ }
385
716
  }
386
717
  async function compileMacos(job, root, log, time) {
387
718
  const options = job.macos;
@@ -479,6 +810,7 @@ async function compileIos(job, root, log, time) {
479
810
  note("build", `xcodebuild for ${runtime}`);
480
811
  const built = await time("buildMs", () => buildIos({
481
812
  root,
813
+ iosDir: iosProjectDirSetting({ ios: { projectPath: job.iosProjectPath ?? void 0 } }, root).dir,
482
814
  destination: target,
483
815
  logWriter: log,
484
816
  ...job.scheme ? { scheme: job.scheme } : {},
@@ -505,8 +837,7 @@ async function compileIos(job, root, log, time) {
505
837
  * Stops the Gradle daemons of this client's Gradle home. A daemon calls setsid, so it leaves the build's
506
838
  * process group and would outlive the job and its claim.
507
839
  */
508
- function stopGradleDaemons(root, timeoutMs) {
509
- const gradlew = gradlewPath(root);
840
+ function stopGradleDaemons(gradlew, timeoutMs) {
510
841
  if (!existsSync(gradlew)) return;
511
842
  getExecutor().runFileQuiet(gradlew, ["--stop"], {
512
843
  cwd: dirname(gradlew),
@@ -528,7 +859,7 @@ function limitDaemonIdle(idleMs) {
528
859
  mkdirSync(home, { recursive: true });
529
860
  writeFileSync(file, wanted);
530
861
  }
531
- async function compileAndroid(job, root, log, time) {
862
+ async function compileAndroid(job, root, log, time, layout) {
532
863
  const options = job.android;
533
864
  if (!options) return {
534
865
  ok: false,
@@ -540,23 +871,25 @@ async function compileAndroid(job, root, log, time) {
540
871
  limitDaemonIdle(keepDaemon ? idleMs : 6e4);
541
872
  const onNote = (line) => note("build", line);
542
873
  const stop = () => {
543
- stopGradleDaemons(root, 4e3);
874
+ stopGradleDaemons(gradlewPath(layout), 4e3);
544
875
  process.exit(143);
545
876
  };
546
877
  process.once("SIGTERM", stop);
547
- note("build", `gradle ${assembleTaskFor(options.variant)} for ${options.abi ?? "every ABI"}`);
878
+ note("build", `gradle ${layout.custom ? `${layout.module}:` : ""}${assembleTaskFor(options.variant)} for ${options.abi ?? "every ABI"}`);
548
879
  try {
549
880
  const built = await time("buildMs", () => buildAndroid({
550
881
  root,
551
882
  logWriter: log,
552
883
  variant: options.variant,
553
- abi: options.abi
884
+ abi: options.abi,
885
+ layout
554
886
  }, {
555
887
  buildCache: options.gradleBuildCache,
556
888
  pch: options.pch,
557
889
  compilerCacheDisabled: options.compilerCache === "none",
558
890
  ccache: options.compilerCache === "ccache" ? resolveCcache({
559
891
  root,
892
+ layout,
560
893
  onNote
561
894
  }) : null,
562
895
  onHeartbeat: onNote,
@@ -577,12 +910,14 @@ async function compileAndroid(job, root, log, time) {
577
910
  };
578
911
  } finally {
579
912
  process.off("SIGTERM", stop);
580
- if (!keepDaemon) stopGradleDaemons(root, 6e4);
913
+ if (!keepDaemon) stopGradleDaemons(gradlewPath(layout), 6e4);
581
914
  }
582
915
  }
583
916
  async function main() {
584
917
  const mode = process.argv[2];
585
918
  if (mode === "offer") return emit(workerToolchain(process.argv[3] ?? null));
919
+ if (mode === "offer-native-xcode") return emit(workerToolchain(null, "xcode"));
920
+ if (mode === "offer-native-gradle") return emit(workerToolchain(null, "gradle"));
586
921
  if (mode === "build") {
587
922
  const chunks = [];
588
923
  for await (const chunk of process.stdin) chunks.push(chunk);
@@ -591,7 +926,7 @@ async function main() {
591
926
  ...await build(JSON.parse(Buffer.concat(chunks).toString("utf8")))
592
927
  });
593
928
  }
594
- process.stderr.write("usage: offload-worker offer | build < job.json\n");
929
+ process.stderr.write("usage: offload-worker offer | offer-native-xcode | offer-native-gradle | build < job.json\n");
595
930
  process.exitCode = 2;
596
931
  }
597
932
  main().catch((error) => {
@@ -1,6 +1,6 @@
1
1
  import { t as process_identity_exports } from "./process-identity-Biv3arCO.mjs";
2
- import { c as writeWorkspaceState, o as withWorkspaceStateLock, r as readWorkspaceState } from "./workspace-state-CR9X86xJ.mjs";
3
- import { s as pidExists } from "./metro-DI2AjPF_.mjs";
2
+ import { c as writeWorkspaceState, o as withWorkspaceStateLock, r as readWorkspaceState } from "./workspace-state-CvgTFe-h.mjs";
3
+ import { s as pidExists } from "./metro-_ZIE3Axg.mjs";
4
4
  import { realpathSync } from "node:fs";
5
5
  //#region src/collector/state.ts
6
6
  function collectorRoot(root) {
@@ -1,4 +1,4 @@
1
- import { T as buildPlacementSettings } from "./client-CuUo8Nvg.mjs";
1
+ import { m as buildPlacementSettings } from "./client-zqjFd79D.mjs";
2
2
  //#region src/placement-log.ts
3
3
  /** `machine` is `local` when the run stays on this Mac. */
4
4
  function placementRecord(input) {