stim 1.25.0 → 1.26.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 (158) hide show
  1. package/README.md +1 -1
  2. package/dist/{acquire-artifact-zA4S7RHE.mjs → acquire-artifact-DVsvSwf7.mjs} +1 -1
  3. package/dist/{act-BbHS3oV8.mjs → act-C-BqJEpu.mjs} +157 -35
  4. package/dist/{activity-BpjwrQXU.mjs → activity-Lnb_EoRY.mjs} +4 -5
  5. package/dist/{agent-device-usage-output-Bnkerfod.mjs → agent-device-usage-output-DbXy5tg8.mjs} +4 -4
  6. package/dist/{android-saBeB4lr.mjs → android-B5P81yI-.mjs} +1 -1
  7. package/dist/{android-CNZgRC-4.mjs → android-CSbLRD53.mjs} +5 -5
  8. package/dist/{android-BGwuK3Mc.mjs → android-CiNQw3kq.mjs} +73 -49
  9. package/dist/{android-Cjcj8MCw.mjs → android-DTAcRwBC.mjs} +81 -34
  10. package/dist/{android-cas-BVqh2Zep.mjs → android-cas-BTVhZ0Qs.mjs} +4 -4
  11. package/dist/{android-project-CTYaETc0.d.mts → android-project-DUGMbq28.d.mts} +55 -1
  12. package/dist/api.d.mts +8 -5
  13. package/dist/api.mjs +27 -27
  14. package/dist/apk-signed-tail-B46U9hXc.mjs +142 -0
  15. package/dist/{artifact-Co8zixVx.mjs → artifact-BxREhAaV.mjs} +23 -18
  16. package/dist/{artifact-DN8JNwqS.mjs → artifact-CsAP6AGK.mjs} +35 -20
  17. package/dist/{attempt-DW-mQqM7.mjs → attempt-ClyJlZPT.mjs} +4 -2
  18. package/dist/{browser-web-CCgZsHmI.mjs → browser-web-rYPyqhTf.mjs} +11 -12
  19. package/dist/{budget-HyShrIpL.mjs → budget-k2mZGvvk.mjs} +196 -33
  20. package/dist/{build-CAiw8Ezm.mjs → build-DPhApsjV.mjs} +26 -23
  21. package/dist/{build-cache-CKCzxzxA.mjs → build-cache-DrXNCy3T.mjs} +103 -21
  22. package/dist/{build-plan-zCuHGlA8.mjs → build-plan-DrMMdayj.mjs} +5 -5
  23. package/dist/{cache-manifest-BPXRONJz.mjs → cache-manifest-BEZ9Bpl1.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{ccache-h1FKhZeg.mjs → ccache-Bx5TbxwG.mjs} +6 -6
  26. package/dist/{cli-C4w607Pz.mjs → cli-BBKFGOFl.mjs} +19 -19
  27. package/dist/cli.mjs +1 -1
  28. package/dist/{client-BQsmyp_-.mjs → client-D9CaRks-.mjs} +36 -61
  29. package/dist/collector-run.mjs +4 -4
  30. package/dist/{command-output-BBvS1H6v.mjs → command-output-BF5AR2dL.mjs} +1 -1
  31. package/dist/{config-BZhXY15H.mjs → config-BktkY_zC.mjs} +321 -15
  32. package/dist/{launch-DscF1QfM.mjs → dependencies-Dw6wfQdv.mjs} +258 -255
  33. package/dist/{dependency-state-BwNCYG5Q.mjs → dependency-state-DFB41vfr.mjs} +1 -1
  34. package/dist/{dev-client-CHoXXZeg.mjs → dev-client-DXR_tPVY.mjs} +2 -2
  35. package/dist/{device-B9FqTBYW.mjs → device-BK-zwyd_.mjs} +13 -13
  36. package/dist/{device-F5-4z9ef.mjs → device-BcYeHSFu.mjs} +14 -14
  37. package/dist/{device-capacity-ZYaRALv5.mjs → device-capacity-DCSvUF0l.mjs} +10 -17
  38. package/dist/device-host-worker.mjs +11 -13
  39. package/dist/{device-ios-DkHBrmvH.mjs → device-ios-BLGfXQeK.mjs} +49 -17
  40. package/dist/{device-lease-run-ogEeJ62K.mjs → device-lease-run-BmvIl7bI.mjs} +4 -4
  41. package/dist/{device-pool-BIg8MU8l.mjs → device-pool-Dluix4H3.mjs} +3 -3
  42. package/dist/{doctor-k3P3PizH.mjs → doctor-Bhg1ii70.mjs} +14 -14
  43. package/dist/{doctor-A_Nr_fDe.mjs → doctor-Cp-BhzTS.mjs} +1 -1
  44. package/dist/{doctor-Bm8TVpGn.mjs → doctor-OnwP94ne.mjs} +72 -23
  45. package/dist/{doctor-fingerprint-zlujA1Gs.mjs → doctor-fingerprint-D3a04Mhu.mjs} +8 -2
  46. package/dist/doctor-fingerprint.mjs +1 -1
  47. package/dist/{doctor-watchman-BovI1y3-.mjs → doctor-watchman-BStK05nt.mjs} +4 -4
  48. package/dist/{eas-build-CyDKNTBP.mjs → eas-build-Dsj93iM9.mjs} +2 -2
  49. package/dist/{eas-fallback-gaZi-dJL.mjs → eas-fallback-FwkeqqGi.mjs} +10 -10
  50. package/dist/{eas-session-ledger-BMCA1gdO.mjs → eas-session-ledger-B5vygTiD.mjs} +5 -5
  51. package/dist/{error-diagnostics-B1Mj_-7h.mjs → error-diagnostics-BOOm9Db7.mjs} +8 -8
  52. package/dist/{gc-eaz403W6.mjs → gc-C_79zvz4.mjs} +2 -2
  53. package/dist/{gc-B9jcnmIk.mjs → gc-ldgr-hXU.mjs} +74 -43
  54. package/dist/{guide-DR0K0xW9.mjs → guide-D7K0X6KG.mjs} +272 -52
  55. package/dist/{hosted-android-Bvb2-ZxD.mjs → hosted-android-Bk54ej6n.mjs} +3 -3
  56. package/dist/{hosted-client-rsRqysJc.mjs → hosted-client-fHO8yqzc.mjs} +5 -5
  57. package/dist/{hosted-ios-RtVcJH3u.mjs → hosted-ios-D55QhYaD.mjs} +1 -1
  58. package/dist/{hosted-logs-CWKGYWNX.mjs → hosted-logs-BfbmDM4M.mjs} +17 -11
  59. package/dist/hosted-logs-sync-B0pvmOk-.mjs +195 -0
  60. package/dist/{hosted-macos-d0pv9Tth.mjs → hosted-macos-CPl0OZ9h.mjs} +5 -5
  61. package/dist/{hosted-native-BxTizGU2.mjs → hosted-native-CpDB3-PO.mjs} +6 -7
  62. package/dist/{idle-shutdown-BIyfl0Zj.mjs → idle-shutdown-FfxL1KdG.mjs} +22 -9
  63. package/dist/{ios-Dvt97HgQ.mjs → ios-B7-lToDu.mjs} +8 -8
  64. package/dist/{ios-BQzvJlzw.mjs → ios-WxpDJ5T1.mjs} +72 -5
  65. package/dist/{ios-device-CKSvk0bu.mjs → ios-device-CsyryvpT.mjs} +1 -1
  66. package/dist/{ios-BRVM8b0P.mjs → ios-ftxdQbJS.mjs} +74 -46
  67. package/dist/{ios-project-DCUDo06I.mjs → ios-project-Ty5pHl9O.mjs} +6 -6
  68. package/dist/{ios-state-CT9nV5SP.mjs → ios-state-Cw7-WQf2.mjs} +1 -1
  69. package/dist/{js-swap-Z9HbC4cj.mjs → js-swap-BMhXYVDS.mjs} +4 -4
  70. package/dist/{launch-D0lPvFFu.mjs → launch-DOp8RjDz.mjs} +31 -26
  71. package/dist/{logs-BsIRre8x.mjs → logs-dQDki6Tt.mjs} +9 -173
  72. package/dist/{logs-Crs9y34Z.mjs → logs-s1dRIG1E.mjs} +85 -36
  73. package/dist/{macos-CcUlJPMu.mjs → macos-B0VEV3Gf.mjs} +1 -1
  74. package/dist/{macos-D477nfzH.mjs → macos-DBBPNnIA.mjs} +18 -19
  75. package/dist/macos-run.mjs +1 -1
  76. package/dist/maintenance-run.mjs +28 -11
  77. package/dist/{metro-1pJgCX4U.mjs → metro-CjC10t6E.mjs} +2 -2
  78. package/dist/{metro-gateway-Bp9gJQAN.mjs → metro-gateway-B6_PgD0L.mjs} +2 -3
  79. package/dist/{named-ports-BVbn8SvC.mjs → named-ports-BG0j1X4g.mjs} +2 -2
  80. package/dist/{native-android-BvMizJn1.mjs → native-android-CL2NGiik.mjs} +17 -17
  81. package/dist/{native-gradle-artifact-inputs-BJscK4vN.mjs → native-gradle-artifact-inputs-btSUulme.mjs} +3 -3
  82. package/dist/{native-run-D5OJsGwA.mjs → native-run-BfIDFKLH.mjs} +2 -3
  83. package/dist/{native-runtime-B9w_Qyz3.mjs → native-runtime-Dq3RBcON.mjs} +6 -7
  84. package/dist/{native-xcode-inputs-Cv4l-obn.mjs → native-xcode-inputs-BW7H8JGu.mjs} +2 -2
  85. package/dist/{native-xcode-ios-DGrg90hE.mjs → native-xcode-ios-CBXJAxfC.mjs} +15 -16
  86. package/dist/offload-worker.d.mts +3 -1
  87. package/dist/offload-worker.mjs +31 -21
  88. package/dist/{ownership-jxxz-19m.mjs → ownership-BjYvMNX_.mjs} +2 -2
  89. package/dist/{phone-reverses-CYb7RRAx.mjs → phone-reverses-lmj6kcPm.mjs} +3 -3
  90. package/dist/{placement-log-DjOXJRIH.mjs → placement-log-DIFPQAXp.mjs} +1 -1
  91. package/dist/{plan-placement-BqKgKHCi.mjs → plan-placement-IiiSQhtz.mjs} +3 -3
  92. package/dist/{ports-DtS1Amb0.mjs → ports-C2_w1Z0Z.mjs} +3 -3
  93. package/dist/prebuild-gmouvmJZ.mjs +1247 -0
  94. package/dist/{project-BiC68mIp.mjs → project-BUu6Is4k.mjs} +15 -16
  95. package/dist/{react-native-android-DRYqoJc4.mjs → react-native-android-Cgg99REN.mjs} +47 -33
  96. package/dist/{react-native-build-CwZB-agu.mjs → react-native-build-oNwqF5Wb.mjs} +7 -7
  97. package/dist/{react-native-doctor-BCrytK7h.mjs → react-native-doctor-BhA3KUte.mjs} +49 -8
  98. package/dist/{react-native-ios-Cr1buNFo.mjs → react-native-ios-B-nf4rjN.mjs} +37 -23
  99. package/dist/{recordings-BaoQ0t-J.mjs → recordings-BldzVKq0.mjs} +1 -1
  100. package/dist/{reload-Beftw2X3.mjs → reload-C9OduiNc.mjs} +1 -1
  101. package/dist/{reload-FbSgMF8x.mjs → reload-CCR7KC_l.mjs} +14 -14
  102. package/dist/{remote-BuZj6AyU.mjs → remote-C8S7FlPF.mjs} +7 -7
  103. package/dist/{result-CR2vk2cj.mjs → result-7F5hEwQJ.mjs} +16 -16
  104. package/dist/{run-BtzE09Dl.mjs → run-BqB0v3pt.mjs} +1 -1
  105. package/dist/{selection-D5cxEl3t.mjs → selection-BNPBZ6T5.mjs} +155 -42
  106. package/dist/{server-bare-CH9X0RLn.mjs → server-bare-A75rDIdD.mjs} +1 -1
  107. package/dist/{server-command-CaBbDNU2.mjs → server-command-CssKFOD7.mjs} +4 -4
  108. package/dist/{server-expo-Ck8EIidM.mjs → server-expo-eQfOdydb.mjs} +2 -2
  109. package/dist/server-expo-wvcj5tiZ.mjs +2 -0
  110. package/dist/{settings-B5tCoq9N.mjs → settings-CosW5X-S.mjs} +1 -1
  111. package/dist/{settings-DzH9mGQZ.mjs → settings-OaGQF-ri.mjs} +1 -1
  112. package/dist/{settings-write-n0zwfohx.mjs → settings-write-QjYfSrjF.mjs} +5 -5
  113. package/dist/settings.schema.json +33 -6
  114. package/dist/{simslim-BjxszUAb.mjs → simslim-Bax1qcxu.mjs} +3 -2
  115. package/dist/{slot-launch-QeuJMlnJ.mjs → slot-launch-CYCEhfBY.mjs} +6 -6
  116. package/dist/{stage-D8xlRU2D.mjs → stage-jKQ7CP_B.mjs} +1 -1
  117. package/dist/{start-C1JLjkNw.mjs → start-C_wefNKB.mjs} +1 -1
  118. package/dist/{start-YMpNwLhh.mjs → start-_BdJ32cZ.mjs} +9 -10
  119. package/dist/{state-DMRNP7-4.mjs → state-C1i2nMOP.mjs} +2 -3
  120. package/dist/{state-DPaM3u5K.mjs → state-C4OdpOTF.mjs} +1 -2
  121. package/dist/{stats-CP7STzZw.mjs → stats-tEpEEH-u.mjs} +4 -4
  122. package/dist/{status-cNw6i0_t.mjs → status-B9M7x4CZ.mjs} +1 -1
  123. package/dist/{status-Fect2w9R.mjs → status-CRXz-Gtj.mjs} +1 -1
  124. package/dist/{status-CRLiJ-O_.mjs → status-DQrqodLj.mjs} +22 -23
  125. package/dist/{status-watch-Bc2J4TZn.mjs → status-watch-B5wDIH_o.mjs} +4 -4
  126. package/dist/status-worker.mjs +1 -1
  127. package/dist/{stim-desktop-DS0mzR8U.mjs → stim-desktop-6Dqp-gjX.mjs} +1 -1
  128. package/dist/{stop-Br7LKxBE.mjs → stop-CmdNhGlC.mjs} +2 -2
  129. package/dist/{stop-Db9Kh-UA.mjs → stop-DRqQVqDJ.mjs} +21 -19
  130. package/dist/{stop-COP6PQqw.mjs → stop-ySNQHXMG.mjs} +4 -5
  131. package/dist/supervisor-run.d.mts +1 -0
  132. package/dist/supervisor-run.mjs +14 -15
  133. package/dist/{support-Cxj9CmII.mjs → support-BGSCBoib.mjs} +4 -4
  134. package/dist/{support-qKcbgmI5.mjs → support-CVOCp0Ft.mjs} +9 -9
  135. package/dist/{swiftpm-artifact-inputs-iY9fsmOc.mjs → swiftpm-artifact-inputs-CfUzt_0Z.mjs} +1 -1
  136. package/dist/{swiftpm-macos-Bp_sn9P4.mjs → swiftpm-macos-x6HPpl_2.mjs} +9 -9
  137. package/dist/toolchain-DoavrvIA.mjs +2 -0
  138. package/dist/toolchain-J4J8MrAr.mjs +2107 -0
  139. package/dist/trigger-DzJu208Q.mjs +2 -0
  140. package/dist/{trigger-CBMe2YLH.mjs → trigger-KVaWWNyn.mjs} +1 -1
  141. package/dist/{warm-progress-BV3ZPmcY.mjs → warm-progress-DvhTX_eu.mjs} +3 -4
  142. package/dist/web-BFLueSh-.mjs +2 -0
  143. package/dist/{web-B4Yjyt1G.mjs → web-Bihbf7-u.mjs} +8 -9
  144. package/dist/web-run.mjs +4 -4
  145. package/dist/{workspace-state-CPSp3mav.mjs → workspace-state-pUg3_RRA.mjs} +45 -7
  146. package/dist/{workspaces-C9w4aeXF.mjs → workspaces-g2lhdBXF.mjs} +17 -17
  147. package/dist/{worktree-CclFIe1Z.mjs → worktree-BKuklFh_.mjs} +34 -31
  148. package/dist/{worktree-Ct9Gk3KL.mjs → worktree-Bm4cb-nU.mjs} +1 -1
  149. package/package.json +8 -8
  150. package/dist/created-devices-D2Aca-xu.mjs +0 -52
  151. package/dist/paths-DQtTgsBf.mjs +0 -42
  152. package/dist/prebuild-JUaqOLpc.mjs +0 -501
  153. package/dist/server-expo-C16Zf2k7.mjs +0 -2
  154. package/dist/toolchain-DB1aeqxO.mjs +0 -2
  155. package/dist/toolchain-VzLJzZ7O.mjs +0 -908
  156. package/dist/trigger-BLsHgAGR.mjs +0 -2
  157. package/dist/web-DS4UDWvf.mjs +0 -2
  158. package/dist/xcode-CiIIDnuD.mjs +0 -910
@@ -1,13 +1,14 @@
1
1
  import { c as throwIfCancelled, t as getExecutor, x as withDrainingCancellation } from "./exec-VFRpu1iA.mjs";
2
- import { i as sharedBuildCache } from "./paths-DQtTgsBf.mjs";
2
+ import { y as sharedBuildCache } from "./workspace-state-pUg3_RRA.mjs";
3
3
  import { a as killOnAbort, c as gitQuiet, o as git, r as childEnvironment, s as gitAsync } from "./operation-exec-CUZifp6Z.mjs";
4
- import { m as defaultAndroidLayout } from "./settings-B5tCoq9N.mjs";
5
- import { r as register } from "./cache-manifest-BPXRONJz.mjs";
4
+ import { m as defaultAndroidLayout } from "./settings-CosW5X-S.mjs";
5
+ import { r as register } from "./cache-manifest-BEZ9Bpl1.mjs";
6
+ import { r as writeSignedTail, t as computeSignedTail } from "./apk-signed-tail-B46U9hXc.mjs";
6
7
  import { createHash } from "node:crypto";
7
8
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
8
9
  import { join } from "node:path";
9
10
  import { artifactIn, buildCacheKey, resolveArtifact, storeArtifactAsync } from "@stim-cli/core";
10
- import { isAbsolute as isAbsolute$1, join as join$1, posix as posix$1, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
11
+ import { basename as basename$1, isAbsolute as isAbsolute$1, join as join$1, posix as posix$1, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
11
12
  import { existsSync as existsSync$1, lstatSync as lstatSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, rmSync as rmSync$1, statSync as statSync$1 } from "fs";
12
13
  import { readdir, writeFile } from "node:fs/promises";
13
14
  import { isDeepStrictEqual } from "util";
@@ -293,6 +294,58 @@ function androidProjectFingerprintOptions(projectRoot, layout, exists = existsSy
293
294
  ].map((dir) => `${moduleRel}/${dir}/**/*`)
294
295
  };
295
296
  }
297
+ const LOCKFILES = [
298
+ "pnpm-lock.yaml",
299
+ "yarn.lock",
300
+ "package-lock.json",
301
+ "bun.lock",
302
+ "bun.lockb"
303
+ ];
304
+ /**
305
+ * The patches of a monorepo's install root, which @expo/fingerprint does not see: its patch sourcer reads only the
306
+ * app's own `patches/`, and its default preset hashes an installed package by name and version, so a patch applied
307
+ * from the workspace root would leave the key unchanged.
308
+ */
309
+ function workspacePatchSources(projectRoot) {
310
+ let dir = resolve$1(projectRoot);
311
+ for (;;) {
312
+ if (LOCKFILES.some((name) => existsSync$1(join$1(dir, name)))) break;
313
+ const parent = resolve$1(dir, "..");
314
+ if (parent === dir || existsSync$1(join$1(dir, ".git"))) return [];
315
+ dir = parent;
316
+ }
317
+ const sources = ["patches", ".yarn/patches"].filter((name) => (name === "patches" ? dir !== resolve$1(projectRoot) : true) && existsSync$1(join$1(dir, name))).map((name) => ({
318
+ type: "dir",
319
+ filePath: relative$1(projectRoot, join$1(dir, name)).split(sep$1).join("/"),
320
+ reasons: ["workspacePatches"]
321
+ }));
322
+ const patched = pnpmPatchedDependencies(join$1(dir, "pnpm-lock.yaml"));
323
+ if (patched) sources.push({
324
+ type: "contents",
325
+ id: "pnpmPatchedDependencies",
326
+ contents: patched,
327
+ reasons: ["workspacePatches"]
328
+ });
329
+ return sources;
330
+ }
331
+ /** The lockfile's `patchedDependencies` block, which pnpm rewrites with each patch's hash wherever the patch lives. */
332
+ function pnpmPatchedDependencies(lockfile) {
333
+ let text;
334
+ try {
335
+ text = readFileSync$1(lockfile, "utf8");
336
+ } catch {
337
+ return null;
338
+ }
339
+ const lines = text.split(/\r?\n/);
340
+ const start = lines.indexOf("patchedDependencies:");
341
+ if (start === -1) return null;
342
+ const block = [];
343
+ for (const line of lines.slice(start + 1)) {
344
+ if (line && !/^\s/.test(line)) break;
345
+ if (line.trim()) block.push(line.trim());
346
+ }
347
+ return block.length ? block.join("\n") : null;
348
+ }
296
349
  /**
297
350
  * The bundle output and, with `ios.projectPath` '.', the top-level entries that git ignores here for an iOS
298
351
  * fingerprint, as the paths a build worker needs to ignore the same ones: it has no .git/info/exclude or global
@@ -319,7 +372,12 @@ async function fingerprintOptions(projectRoot, { platform, iosProjectPath = "ios
319
372
  const ignoredAtAppRoot = (names) => new Set([...ignoredHere(names)].filter((name) => !trackedPaths.includes(name)));
320
373
  const platforms = platform && FINGERPRINT_PLATFORMS.has(platform) ? { platforms: [platform] } : void 0;
321
374
  const ios = platform === "ios" ? iosProjectFingerprintOptions(projectRoot, iosProjectPath, { ignored: (_, names) => ignoredAtAppRoot(names) }) : androidLayout?.custom ? androidProjectFingerprintOptions(projectRoot, androidLayout) : {};
322
- if (ios.extraSources) ios.extraSources = [...(await loadConfigAsync(projectRoot, true))?.extraSources ?? [], ...ios.extraSources];
375
+ const patches = workspacePatchSources(projectRoot);
376
+ if (ios.extraSources || patches.length) ios.extraSources = [
377
+ ...(await loadConfigAsync(projectRoot, true))?.extraSources ?? [],
378
+ ...ios.extraSources ?? [],
379
+ ...patches
380
+ ];
323
381
  const bundleOutput = platform === "android" ? [] : [...ignoredHere(Object.keys(BUNDLE_OUTPUT_IGNORES), true)].map((path) => BUNDLE_OUTPUT_IGNORES[path]);
324
382
  return {
325
383
  ...platforms,
@@ -345,14 +403,13 @@ async function fingerprintProject(projectRoot, { createFingerprint = expoFingerp
345
403
  sources: Array.isArray(result?.sources) ? result.sources : []
346
404
  };
347
405
  }
348
- /** The env files @expo/env loads for the config, in the mode @expo/fingerprint's config loader sets. */
406
+ /** The env files @expo/env loads for the config: @expo/fingerprint 0.21 evaluates it in development mode. */
349
407
  function expoEnvFiles(env = {}) {
350
408
  if (/^(1|true)$/i.test(env.EXPO_NO_DOTENV ?? "")) return [];
351
- const mode = env.NODE_ENV || "development";
352
409
  return [
353
- `.env.${mode}.local`,
354
- ...mode === "test" ? [] : [".env.local"],
355
- `.env.${mode}`,
410
+ ".env.development.local",
411
+ ".env.local",
412
+ ".env.development",
356
413
  ".env"
357
414
  ];
358
415
  }
@@ -457,6 +514,17 @@ async function storeBuild(platform, key, buildPath, rootOrOptions = {}) {
457
514
  }),
458
515
  overwrite: Boolean(options.overwrite),
459
516
  writeMetadata: async (staging) => {
517
+ if (platform === "android" && buildPath.endsWith(".apk")) try {
518
+ const tail = await computeSignedTail(join$1(staging, basename$1(buildPath)), (file, args) => getExecutor().runFileAsync(file, args, {
519
+ timeoutMs: 12e4,
520
+ ...env ? childEnvironment(env) : {},
521
+ onSpawn: killOnAbort(signal),
522
+ declareFor: options.context
523
+ }));
524
+ if (tail) await writeSignedTail(staging, tail);
525
+ } catch {
526
+ throwIfCancelled(signal, "build cache copy");
527
+ }
460
528
  if (Array.isArray(options.sources)) try {
461
529
  await writeFile(join$1(staging, SOURCES_FILE), JSON.stringify(options.sources.map(withoutContents)));
462
530
  } catch {}
@@ -588,6 +656,28 @@ function diffItemChange(item) {
588
656
  reasons: sourceReasons(source)
589
657
  };
590
658
  }
659
+ /** The installed package a source path lies in: the name after its last `node_modules/`. */
660
+ function packageIn(path) {
661
+ return [...path.matchAll(/(?:^|\/)node_modules\/((?:@[^/]+\/)?[^/]+)/g)].at(-1)?.[1] ?? null;
662
+ }
663
+ /** A package that moved, such as a version bump of a pnpm store directory, is one change rather than a removal and an addition. */
664
+ function mergeMovedPackages(changes) {
665
+ const added = /* @__PURE__ */ new Map();
666
+ for (const change of changes) {
667
+ const pkg = change.change === "added" ? packageIn(change.name) : null;
668
+ if (pkg && !added.has(pkg)) added.set(pkg, change);
669
+ }
670
+ const moved = /* @__PURE__ */ new Set();
671
+ const kept = changes.filter((change) => {
672
+ const pkg = change.change === "removed" ? packageIn(change.name) : null;
673
+ const counterpart = pkg ? added.get(pkg) : void 0;
674
+ if (!counterpart || moved.has(counterpart)) return true;
675
+ moved.add(counterpart);
676
+ return false;
677
+ });
678
+ for (const change of moved) change.change = "changed";
679
+ return kept;
680
+ }
591
681
  function compareSourceLists(previous, current) {
592
682
  const previousByName = /* @__PURE__ */ new Map();
593
683
  for (const source of previous) {
@@ -621,7 +711,7 @@ function compareSourceLists(previous, current) {
621
711
  change: "removed",
622
712
  reasons: before.reasons
623
713
  });
624
- return changes;
714
+ return mergeMovedPackages(changes);
625
715
  }
626
716
  function diffFingerprintSources({ previous, previousHash = null, current, differ = null }) {
627
717
  if (typeof differ === "function") try {
@@ -633,16 +723,8 @@ function diffFingerprintSources({ previous, previousHash = null, current, differ
633
723
  hash: current.hash
634
724
  });
635
725
  if (Array.isArray(items)) {
636
- const changes = [];
637
726
  const seen = /* @__PURE__ */ new Set();
638
- for (const item of items) {
639
- const change = diffItemChange(item);
640
- if (change !== null && !seen.has(change.name)) {
641
- seen.add(change.name);
642
- changes.push(change);
643
- }
644
- }
645
- return changes;
727
+ return mergeMovedPackages(items.map(diffItemChange).filter((change) => change !== null)).filter((change) => !seen.has(change.name) && Boolean(seen.add(change.name)));
646
728
  }
647
729
  } catch {}
648
730
  return compareSourceLists(previous, current.sources);
@@ -750,4 +832,4 @@ function fingerprintDiffRecord({ changed, previousHash, hash }) {
750
832
  };
751
833
  }
752
834
  //#endregion
753
- export { readAssetManifest as A, storedSources as C, assetDiffReason as D, untrackedNativeFiles as E, captureAssetManifest as O, storedAssetManifest as S, untrackedMissLine as T, providerUploadOutcome as _, configInputsChanged as a, storeBuild as b, expoConfigContents as c, fingerprintProject as d, gitignoredFingerprintInputs as f, providerDownloadPath as g, prepareProviderDownloadDir as h, compareSourceLists as i, compareAssetManifests as k, filesystemBuildCapability as l, inputsChangedDuringBuild as m, buildCacheKey as n, diffFingerprintSources as o, ignoredFingerprintPaths as p, changedDuringBuildLine as r, entryDir as s, artifactIn as t, fingerprintDiffRecord as u, refingerprintAfterMutation as v, trackedFingerprintPaths as w, storedAppId as x, resolveBuild as y };
835
+ export { assetDiffReason as A, storeBuild as C, trackedFingerprintPaths as D, storedSources as E, compareAssetManifests as M, readAssetManifest as N, untrackedMissLine as O, resolveBuild as S, storedAssetManifest as T, packageIn as _, configInputsChanged as a, providerUploadOutcome as b, expoConfigContents as c, fingerprintDiffRecord as d, fingerprintOptions as f, inputsChangedDuringBuild as g, ignoredFingerprintPaths as h, compareSourceLists as i, captureAssetManifest as j, untrackedNativeFiles as k, expoEnvFiles as l, gitignoredFingerprintInputs as m, buildCacheKey as n, diffFingerprintSources as o, fingerprintProject as p, changedDuringBuildLine as r, entryDir as s, artifactIn as t, filesystemBuildCapability as u, prepareProviderDownloadDir as v, storedAppId as w, refingerprintAfterMutation as x, providerDownloadPath as y };
@@ -1,9 +1,9 @@
1
1
  import { T as trackReportResource } from "./exec-VFRpu1iA.mjs";
2
- import { i as formatDuration, l as phaseLine, m as shortHash, u as plural } from "./command-output-BBvS1H6v.mjs";
3
- import { Gt as removeTemporaryEntryAsync, Ut as makeTemporaryDirectory } from "./settings-B5tCoq9N.mjs";
4
- import { L as estimateBuild, Wn as easAuthNote, q as readStats } from "./budget-HyShrIpL.mjs";
5
- import { s as entryDir, t as artifactIn } from "./build-cache-CKCzxzxA.mjs";
6
- import { l as predictBuildMiss, o as staleNativeDirRefusal } from "./prebuild-JUaqOLpc.mjs";
2
+ import { i as formatDuration, l as phaseLine, m as shortHash, u as plural } from "./command-output-BF5AR2dL.mjs";
3
+ import { Gt as removeTemporaryEntryAsync, Ut as makeTemporaryDirectory } from "./settings-CosW5X-S.mjs";
4
+ import { Jn as easAuthNote, V as estimateBuild, Z as readStats } from "./budget-k2mZGvvk.mjs";
5
+ import { s as entryDir, t as artifactIn } from "./build-cache-DrXNCy3T.mjs";
6
+ import { l as predictBuildMiss, o as staleNativeDirRefusal } from "./prebuild-gmouvmJZ.mjs";
7
7
  import chalk from "chalk";
8
8
  import { PROVIDER_LOAD_TIMEOUT_ENV, PROVIDER_LOAD_TIMEOUT_MS, buildResolveTimeoutMs, resolveTieredBuild, timeoutFromEnv } from "@stim-cli/cache";
9
9
  //#region src/commands/build-plan.ts
@@ -1,4 +1,4 @@
1
- import { d as getConfigDir } from "./config-BZhXY15H.mjs";
1
+ import { d as getConfigDir } from "./config-BktkY_zC.mjs";
2
2
  import { cacheDirRefusal, readCacheManifest, updateCacheManifest } from "@stim-cli/core";
3
3
  import { join, resolve } from "path";
4
4
  import { existsSync } from "fs";
@@ -1,2 +1,2 @@
1
- import { a as unregister, i as registeredCaches, n as readManifest, r as register, t as manifestPath } from "./cache-manifest-BPXRONJz.mjs";
1
+ import { a as unregister, i as registeredCaches, n as readManifest, r as register, t as manifestPath } from "./cache-manifest-BEZ9Bpl1.mjs";
2
2
  export { manifestPath, readManifest, register, registeredCaches, unregister };
@@ -1,10 +1,10 @@
1
1
  import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { a as sharedCcache, m as workspaceLogsDir } from "./paths-DQtTgsBf.mjs";
3
- import { _ as loadConfig } from "./config-BZhXY15H.mjs";
4
- import { l as phaseLine } from "./command-output-BBvS1H6v.mjs";
5
- import { m as defaultAndroidLayout } from "./settings-B5tCoq9N.mjs";
6
- import { r as register } from "./cache-manifest-BPXRONJz.mjs";
7
- import { o as machineNumber } from "./budget-HyShrIpL.mjs";
2
+ import { b as sharedCcache, k as workspaceLogsDir } from "./workspace-state-pUg3_RRA.mjs";
3
+ import { _ as loadConfig } from "./config-BktkY_zC.mjs";
4
+ import { l as phaseLine } from "./command-output-BF5AR2dL.mjs";
5
+ import { m as defaultAndroidLayout } from "./settings-CosW5X-S.mjs";
6
+ import { r as register } from "./cache-manifest-BEZ9Bpl1.mjs";
7
+ import { o as machineNumber } from "./budget-k2mZGvvk.mjs";
8
8
  import { readFileSync, realpathSync } from "node:fs";
9
9
  import { isAbsolute, join, relative } from "node:path";
10
10
  import chalk from "chalk";
@@ -1,27 +1,27 @@
1
1
  import { E as debugLog } from "./exec-VFRpu1iA.mjs";
2
- import { y as refuseRelativeStimPaths } from "./config-BZhXY15H.mjs";
2
+ import { y as refuseRelativeStimPaths } from "./config-BktkY_zC.mjs";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { runId } from "@stim-cli/core/state";
5
5
  import { Command } from "commander";
6
6
  //#region bin/cli.ts
7
7
  const commands = /* @__PURE__ */ new Map([
8
- ["doctor", () => import("./doctor-A_Nr_fDe.mjs")],
9
- ["worktree", () => import("./worktree-Ct9Gk3KL.mjs")],
10
- ["start", () => import("./start-C1JLjkNw.mjs")],
11
- ["ports", () => import("./ports-DtS1Amb0.mjs")],
12
- ["stop", () => import("./stop-Br7LKxBE.mjs")],
13
- ["ios", () => import("./ios-Dvt97HgQ.mjs")],
14
- ["android", () => import("./android-CNZgRC-4.mjs")],
15
- ["web", () => import("./web-DS4UDWvf.mjs")],
16
- ["macos", () => import("./macos-CcUlJPMu.mjs")],
17
- ["reload", () => import("./reload-Beftw2X3.mjs")],
18
- ["device", () => import("./device-F5-4z9ef.mjs")],
19
- ["logs", () => import("./logs-Crs9y34Z.mjs")],
20
- ["settings", () => import("./settings-DzH9mGQZ.mjs")],
21
- ["status", () => import("./status-cNw6i0_t.mjs")],
22
- ["stats", () => import("./stats-CP7STzZw.mjs")],
23
- ["gc", () => import("./gc-eaz403W6.mjs")],
24
- ["guide", () => import("./guide-DR0K0xW9.mjs")]
8
+ ["doctor", () => import("./doctor-Cp-BhzTS.mjs")],
9
+ ["worktree", () => import("./worktree-Bm4cb-nU.mjs")],
10
+ ["start", () => import("./start-C_wefNKB.mjs")],
11
+ ["ports", () => import("./ports-C2_w1Z0Z.mjs")],
12
+ ["stop", () => import("./stop-CmdNhGlC.mjs")],
13
+ ["ios", () => import("./ios-B7-lToDu.mjs")],
14
+ ["android", () => import("./android-CSbLRD53.mjs")],
15
+ ["web", () => import("./web-BFLueSh-.mjs")],
16
+ ["macos", () => import("./macos-B0VEV3Gf.mjs")],
17
+ ["reload", () => import("./reload-C9OduiNc.mjs")],
18
+ ["device", () => import("./device-BcYeHSFu.mjs")],
19
+ ["logs", () => import("./logs-s1dRIG1E.mjs")],
20
+ ["settings", () => import("./settings-OaGQF-ri.mjs")],
21
+ ["status", () => import("./status-B9M7x4CZ.mjs")],
22
+ ["stats", () => import("./stats-tEpEEH-u.mjs")],
23
+ ["gc", () => import("./gc-C_79zvz4.mjs")],
24
+ ["guide", () => import("./guide-D7K0X6KG.mjs")]
25
25
  ]);
26
26
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
27
27
  const program = new Command();
@@ -52,7 +52,7 @@ try {
52
52
  }));
53
53
  }
54
54
  try {
55
- const { triggerMaintenance } = await import("./trigger-BLsHgAGR.mjs");
55
+ const { triggerMaintenance } = await import("./trigger-DzJu208Q.mjs");
56
56
  triggerMaintenance(action.name());
57
57
  } catch {}
58
58
  });
package/dist/cli.mjs CHANGED
@@ -4,6 +4,6 @@ const encode = (version) => version.split(".", 3).reduce((sum, part) => sum * 1e
4
4
  if (encode(process.versions.node) < encode("22.12.0")) {
5
5
  process.stderr.write(`STIM_NODE_UNSUPPORTED: Stim needs Node 22.12.0 or later; this is Node ${process.versions.node} at ${process.execPath}. To run Stim where a project pins an older Node, see https://stim.appandflow.com/docs/requirements#older-node-pins\n`);
6
6
  process.exitCode = 1;
7
- } else import("./cli-C4w607Pz.mjs");
7
+ } else import("./cli-BBKFGOFl.mjs");
8
8
  //#endregion
9
9
  export {};
@@ -1,69 +1,24 @@
1
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";
2
+ import { _ as loadConfig$1, at as resolveEndpoint, et as openAuthenticated, ot as sayHello } from "./config-BktkY_zC.mjs";
3
3
  import { o as git, s as gitAsync } from "./operation-exec-CUZifp6Z.mjs";
4
- import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
5
- import { Cr as discoverCaches, Q as emptyCaches, it as planCacheEmptying } from "./budget-HyShrIpL.mjs";
4
+ import { Dr as discoverCaches, E as maintenanceLogger, ct as planCacheEmptying, nt as emptyCaches } from "./budget-k2mZGvvk.mjs";
6
5
  import { t as canonicalPath } from "./paths-BsJMoPP2.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";
6
+ import { d as runCancellationSignal } from "./native-run-BfIDFKLH.mjs";
10
7
  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-VzLJzZ7O.mjs";
12
- import { i as namedBuildMachine, t as OffloadRefusal, u as pairedMachines } from "./selection-D5cxEl3t.mjs";
8
+ import { n as CCACHE_UNAVAILABLE, t as CCACHE_NOT_RUN } from "./ccache-Bx5TbxwG.mjs";
9
+ import { A as COMPILATION_CACHE_UNAVAILABLE, E as readRubyVersion, a as cocoapodsDifference, k as COMPILATION_CACHE_NOT_RUN, s as iosToolchainAsync, v as toolchainMismatches, x as workerToolchain, y as toolchainNotes } from "./toolchain-J4J8MrAr.mjs";
10
+ import { f as pairedMachines, i as namedBuildMachine, t as OffloadRefusal, u as workerFailureReason } from "./selection-BNPBZ6T5.mjs";
13
11
  import { n as fingerprintNativeInputs, r as manifestDigest } from "./native-inputs-TRTTTRxt.mjs";
14
12
  import { a as sourceManifest, i as nativeTransferManifest, n as gitVisiblePaths, r as nativeFileDigest, t as checkNativeTransferMembership } from "./native-source-D-4Dh4JU.mjs";
15
13
  import { createHash, webcrypto } from "node:crypto";
16
- import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
14
+ import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, rmSync, writeSync } from "node:fs";
17
15
  import { isDeepStrictEqual } from "node:util";
18
16
  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";
20
- import { MAINTENANCE_LOG_NAME, OFFLOAD_MODES, automaticMachineEnabled, isJsonObject, maintenanceDir, maintenanceNdjsonFile, requireAutomaticMachine, runId, saturation, workspaceLogsDir } from "@stim-cli/core/state";
17
+ import { ambientContext, dependencyLockfile, reactNativeArtifactIdentity, reactNativeArtifactQuery, swiftpmArtifactQuery } from "@stim-cli/core";
18
+ import { OFFLOAD_MODES, automaticMachineEnabled, isJsonObject, maintenanceDir, requireAutomaticMachine, runId, saturation } from "@stim-cli/core/state";
21
19
  import { WebSocket } from "ws";
22
20
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
23
21
  import { access, lstat, readFile, readlink, realpath } from "node:fs/promises";
24
- //#region src/maintenance/log.ts
25
- function maintenanceLogger(settings, pass, trigger) {
26
- const file = maintenanceNdjsonFile();
27
- const rotated = rotatedLogPath(file);
28
- withDirLock(`${file}.lock`, () => {
29
- try {
30
- if (Date.now() - statSync(rotated).mtimeMs > settings.logRetentionDays * 864e5) unlinkSync(rotated);
31
- } catch {}
32
- });
33
- const writer = createNdjsonWriter(file, { maxBytes: settings.logMaxMb * 1024 ** 2 });
34
- return {
35
- write(event, level, msg, fields = {}) {
36
- if (level === "debug" && !settings.logChecks) return null;
37
- const record = {
38
- ...fields,
39
- ts: Date.now(),
40
- src: "maintenance",
41
- level,
42
- msg,
43
- event,
44
- pass,
45
- trigger,
46
- mode: settings.mode === "on" ? "on" : "report"
47
- };
48
- if (!writer.write(record)) throw writer.lastError ?? /* @__PURE__ */ new Error(`Could not append ${file}`);
49
- if (typeof fields.workspace === "string" && [
50
- "maintenance_action",
51
- "maintenance_failure",
52
- "maintenance_skip"
53
- ].includes(event)) {
54
- const workspace = createNdjsonWriter(join(workspaceLogsDir(fields.workspace), MAINTENANCE_LOG_NAME), { maxBytes: LOG_ROTATE_BYTES });
55
- try {
56
- if (!workspace.write(record)) throw workspace.lastError ?? /* @__PURE__ */ new Error("Could not append workspace maintenance log");
57
- } finally {
58
- workspace.close();
59
- }
60
- }
61
- return record;
62
- },
63
- close: () => writer.close()
64
- };
65
- }
66
- //#endregion
67
22
  //#region src/cache/compilation-cache-corruption.ts
68
23
  const COMPILATION_CACHE_CORRUPT = "STIM_COMPILATION_CACHE_CORRUPT";
69
24
  async function emptyCompilationCache(dir) {
@@ -541,8 +496,10 @@ function matchingArtifact(offer, identity) {
541
496
  }
542
497
  const gb = (bytes) => (bytes / 1024 ** 3).toFixed(1);
543
498
  /** Every reason a machine's offer cannot take this build, in either mode; empty when it can. */
544
- function offerProblems(offer, target) {
499
+ function offerProblems(offer, target, named = false) {
545
500
  const problems = toolchainMismatches(target, offer.toolchain);
501
+ const pods = !named && target.platform === "ios" && !problems.some(({ code }) => code === "platform") ? cocoapodsDifference(target, offer.toolchain) : null;
502
+ if (pods) problems.push(pods);
546
503
  const capacity = offer.capacity;
547
504
  const { running, max, diskFreeBytes, minDiskFreeBytes, declined } = capacity;
548
505
  if (diskFreeBytes !== null && diskFreeBytes < minDiskFreeBytes) problems.push({
@@ -602,7 +559,7 @@ function pickOffer({ mode, here, offers, target, localEnabled = true, selected =
602
559
  return;
603
560
  }
604
561
  if (cacheOnly) return skip(machine, "artifact-miss", "no matching completed artifact");
605
- const problems = offerProblems(offer, target);
562
+ const problems = offerProblems(offer, target, namedBuildMachine(selected));
606
563
  if (problems.length) return skip(machine, problemCode(problems[0]), problems.map((problem) => problem.reason).join("; "), problems.map((problem) => problem.code));
607
564
  const load = offer.capacity.loadPerCore;
608
565
  if (selected === "auto" && localEnabled && mode === "auto" && !slotsFull) {
@@ -615,10 +572,11 @@ function pickOffer({ mode, here, offers, target, localEnabled = true, selected =
615
572
  score,
616
573
  load: typeof load === "number" ? load : Number.POSITIVE_INFINITY
617
574
  });
575
+ const notes = toolchainNotes(target, offer.toolchain).map((each) => each.reason);
618
576
  candidates.push({
619
577
  machine,
620
578
  code: "accepted",
621
- msg: typeof load === "number" ? `can take the build (load ${load}/core there)` : "can take the build"
579
+ msg: [typeof load === "number" ? `can take the build (load ${load}/core there)` : "can take the build", ...notes].join("; ")
622
580
  });
623
581
  });
624
582
  ranked.sort((a, b) => b.score - a.score || a.load - b.load);
@@ -1086,6 +1044,10 @@ async function chooseBuildMachine({ projectRoot, target, mode, here, note, machi
1086
1044
  ...swiftpmQuery ? { swiftpmArtifact: swiftpmQuery } : {}
1087
1045
  };
1088
1046
  }
1047
+ function startJdk(choice) {
1048
+ const { target, connection } = choice;
1049
+ return target.platform === "android" && target.local.jdk && connection.supports("build-jdk") ? { jdk: target.local.jdk } : {};
1050
+ }
1089
1051
  function startCompat(choice) {
1090
1052
  return choice.connection.supports("build-compat") ? { compat: choice.target.local.compat } : {};
1091
1053
  }
@@ -1570,7 +1532,8 @@ async function offloadBuild(input) {
1570
1532
  ...request.platform === "android" ? { android: request.android } : {}
1571
1533
  },
1572
1534
  stimBuild: choice.target.local.stimBuild,
1573
- ...startCompat(choice)
1535
+ ...startCompat(choice),
1536
+ ...startJdk(choice)
1574
1537
  });
1575
1538
  checkCancelled();
1576
1539
  if ("result" in reply) {
@@ -1594,7 +1557,7 @@ async function offloadBuild(input) {
1594
1557
  const { connection, machine } = choice;
1595
1558
  connection.onProgress(null);
1596
1559
  const workerMs = cacheHit ? 0 : Date.now() - workerStarted;
1597
- if (result.ok !== true) return keepCorruptCacheMessage(fail(`${String(result.code ?? "failed")}: ${String(result.message ?? "")}`), result);
1560
+ if (result.ok !== true) return keepCorruptCacheMessage(fail(workerFailureReason(result.code, result.message)), result);
1598
1561
  if (!cacheHit && native && (result.sourceDigest !== sourceDigest || result.fingerprint !== expectedFingerprint)) return fail("The worker returned a different native source or artifact identity.");
1599
1562
  if (native?.provider === "gradle" && !ANDROID_PACKAGE.test(String(result.androidPackage ?? ""))) return fail("The worker returned no verified native APK package.");
1600
1563
  const artifact = result.artifact;
@@ -1745,6 +1708,16 @@ function machineProblems(offer, targets) {
1745
1708
  }
1746
1709
  return problems;
1747
1710
  }
1711
+ /** What a build on a machine that would take it does beyond the match, for each of `targets`, labeled like `machineProblems`. */
1712
+ function machineNotes(offer, targets) {
1713
+ const notes = [];
1714
+ if (machineProblems(offer, targets).length) return notes;
1715
+ for (const target of targets) for (const note of toolchainNotes(target, offer.toolchain)) notes.push(targets.length > 1 ? {
1716
+ ...note,
1717
+ reason: `${PLATFORM_LABEL[target.platform]}: ${note.reason}`
1718
+ } : note);
1719
+ return notes;
1720
+ }
1748
1721
  const DOCTOR_CONNECT_MS = 5e3;
1749
1722
  const DOCTOR_OFFER_MS = 8e3;
1750
1723
  const PLATFORM_LABEL = {
@@ -1802,11 +1775,13 @@ function offloadCheck(projectRoot, targets) {
1802
1775
  };
1803
1776
  probe.connection.close();
1804
1777
  resolved ??= targets();
1778
+ const judged = await resolved;
1805
1779
  return {
1806
1780
  capacity: probe.offer.capacity,
1807
- problems: machineProblems(probe.offer, await resolved)
1781
+ problems: machineProblems(probe.offer, judged),
1782
+ notes: machineNotes(probe.offer, judged)
1808
1783
  };
1809
1784
  };
1810
1785
  }
1811
1786
  //#endregion
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 };
1787
+ export { COMPILATION_CACHE_CORRUPT as C, setRemoteLogSink as S, 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,11 +1,11 @@
1
1
  import { S as process_identity_exports } from "./exec-VFRpu1iA.mjs";
2
- import { m as workspaceLogsDir } from "./paths-DQtTgsBf.mjs";
3
- import { V as deviceSlotKey, q as validateDeviceSlot } from "./config-BZhXY15H.mjs";
2
+ import { k as workspaceLogsDir } from "./workspace-state-pUg3_RRA.mjs";
3
+ import { V as deviceSlotKey, q as validateDeviceSlot } from "./config-BktkY_zC.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
+ import { c as watchAppPid, i as parseLogcatLine, o as startAndroidLogcat, s as waitForAppPid, t as androidClockOffset } from "./android-B5P81yI-.mjs";
6
6
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
7
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";
8
+ import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-BjYvMNX_.mjs";
9
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";
@@ -1,5 +1,5 @@
1
1
  import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
2
- import { t as NO_PROJECT_REFUSAL } from "./project-BiC68mIp.mjs";
2
+ import { t as NO_PROJECT_REFUSAL } from "./project-BUu6Is4k.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