stim 1.26.0 → 1.28.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 (172) hide show
  1. package/dist/{acquire-artifact-DVsvSwf7.mjs → acquire-artifact-CKByBnTD.mjs} +2 -2
  2. package/dist/{act-C-BqJEpu.mjs → act-8iswyfRa.mjs} +319 -126
  3. package/dist/{activity-Lnb_EoRY.mjs → activity-DRMg4_mD.mjs} +6 -6
  4. package/dist/{agent-device-usage-output-DbXy5tg8.mjs → agent-device-usage-output-tE90fDdo.mjs} +5 -5
  5. package/dist/{android-CiNQw3kq.mjs → android-CHmSU4B4.mjs} +101 -45
  6. package/dist/{android-DTAcRwBC.mjs → android-CsPs-7Mg.mjs} +23 -18
  7. package/dist/{android-B5P81yI-.mjs → android-D577ApKG.mjs} +37 -15
  8. package/dist/{android-CSbLRD53.mjs → android-YWCbmkVK.mjs} +5 -5
  9. package/dist/{android-cas-BTVhZ0Qs.mjs → android-cas-_aDifWW0.mjs} +4 -4
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/api.d.mts +14 -4
  12. package/dist/api.mjs +39 -29
  13. package/dist/{apk-signed-tail-B46U9hXc.mjs → apk-signed-tail-CQbwM0qO.mjs} +2 -2
  14. package/dist/{artifact-CsAP6AGK.mjs → artifact-DYtHjxsn.mjs} +19 -24
  15. package/dist/{artifact-BxREhAaV.mjs → artifact-bFkfD3vf.mjs} +18 -23
  16. package/dist/{artifact-platform-CMRc0M_r.mjs → artifact-platform-BO2Uvk_A.mjs} +1 -1
  17. package/dist/auto-placement-BVqs8AJi.mjs +350 -0
  18. package/dist/{browser-web-rYPyqhTf.mjs → browser-web-BUaLcafY.mjs} +16 -16
  19. package/dist/{build-DPhApsjV.mjs → build-cQURy_KW.mjs} +35 -31
  20. package/dist/{build-cache-DrXNCy3T.mjs → build-cache-CZULpXVl.mjs} +43 -21
  21. package/dist/{build-plan-DrMMdayj.mjs → build-plan-CxoYfxsc.mjs} +7 -6
  22. package/dist/{cache-manifest-BEZ9Bpl1.mjs → cache-manifest-DEjqGGat.mjs} +1 -1
  23. package/dist/cache-manifest.mjs +1 -1
  24. package/dist/{budget-k2mZGvvk.mjs → ccache-Bm_A1xX9.mjs} +562 -1604
  25. package/dist/{cdp-BG3FJCCx.mjs → cdp-C3svvXiE.mjs} +1 -1
  26. package/dist/{chrome-BvV8ssI3.mjs → chrome-DyDWurWG.mjs} +1 -1
  27. package/dist/{cli-BBKFGOFl.mjs → cli-CpbaLDa7.mjs} +24 -23
  28. package/dist/cli.mjs +1 -1
  29. package/dist/{client-D9CaRks-.mjs → client-YxCer6ab.mjs} +84 -65
  30. package/dist/collector-run.d.mts +10 -9
  31. package/dist/collector-run.mjs +42 -27
  32. package/dist/{command-output-BF5AR2dL.mjs → command-output-C8R1KIvi.mjs} +1 -1
  33. package/dist/{config-BktkY_zC.mjs → config-Cn94Jc0g.mjs} +23 -4
  34. package/dist/{dependencies-Dw6wfQdv.mjs → dependencies-DKeMzwXY.mjs} +108 -60
  35. package/dist/{dependency-state-DFB41vfr.mjs → dependency-state-CojA2o0t.mjs} +14 -7
  36. package/dist/{detached-entry-KmieOKgN.mjs → detached-entry-BPlSaCwC.mjs} +1 -1
  37. package/dist/{dev-client-DXR_tPVY.mjs → dev-client-D-BW5uiq.mjs} +2 -2
  38. package/dist/{device-BK-zwyd_.mjs → device-CgXfbcz5.mjs} +25 -24
  39. package/dist/{device-capacity-DCSvUF0l.mjs → device-capacity-Cd8lMSn3.mjs} +175 -22
  40. package/dist/{device-BcYeHSFu.mjs → device-eeK95Lir.mjs} +16 -16
  41. package/dist/device-host-worker.mjs +22 -20
  42. package/dist/{device-ios-BLGfXQeK.mjs → device-ios-Cc9ulihb.mjs} +251 -23
  43. package/dist/{device-lease-run-BmvIl7bI.mjs → device-lease-run-Mtzp4THX.mjs} +5 -5
  44. package/dist/{device-pool-Dluix4H3.mjs → device-pool-eRz6DtCg.mjs} +3 -3
  45. package/dist/{doctor-Bhg1ii70.mjs → doctor-Bz_ouYAW.mjs} +28 -16
  46. package/dist/{doctor-Cp-BhzTS.mjs → doctor-C2QyhejJ.mjs} +1 -1
  47. package/dist/{doctor-fingerprint-D3a04Mhu.mjs → doctor-fingerprint-o7ZI9YLn.mjs} +1 -1
  48. package/dist/doctor-fingerprint.mjs +1 -1
  49. package/dist/{doctor-watchman-BStK05nt.mjs → doctor-watchman-BTW82PDC.mjs} +5 -5
  50. package/dist/{doctor-OnwP94ne.mjs → doctor-xf7ht-5n.mjs} +76 -32
  51. package/dist/{eas-build-Dsj93iM9.mjs → eas-build-Dm6q68QY.mjs} +4 -4
  52. package/dist/eas-fallback-DajNpxf-.mjs +87 -0
  53. package/dist/{eas-session-ledger-B5vygTiD.mjs → eas-session-ledger-CBFo_Uo1.mjs} +37 -8
  54. package/dist/{error-diagnostics-BOOm9Db7.mjs → error-diagnostics-D1QfyJzQ.mjs} +51 -25
  55. package/dist/{exec-VFRpu1iA.mjs → exec-aULwtNly.mjs} +57 -6
  56. package/dist/{gc-ldgr-hXU.mjs → gc-DM5oMm-J.mjs} +161 -45
  57. package/dist/{gc-C_79zvz4.mjs → gc-PLFwb0k4.mjs} +2 -2
  58. package/dist/{guide-D7K0X6KG.mjs → guide-C4I46XAk.mjs} +674 -213
  59. package/dist/{hosted-android-Bk54ej6n.mjs → hosted-android-DlaKLbW0.mjs} +6 -7
  60. package/dist/{hosted-client-fHO8yqzc.mjs → hosted-client-DDRm9hPJ.mjs} +51 -20
  61. package/dist/{hosted-logs-BfbmDM4M.mjs → hosted-logs-bSebOKbz.mjs} +8 -8
  62. package/dist/{hosted-logs-sync-B0pvmOk-.mjs → hosted-logs-sync-B0c53W_c.mjs} +5 -5
  63. package/dist/{hosted-macos-CPl0OZ9h.mjs → hosted-macos-B7-8Pv4H.mjs} +6 -6
  64. package/dist/{hosted-native-CpDB3-PO.mjs → hosted-native-CDe33CSr.mjs} +22 -18
  65. package/dist/{idle-shutdown-FfxL1KdG.mjs → idle-shutdown-CQ0QwU9J.mjs} +7 -8
  66. package/dist/{ios-WxpDJ5T1.mjs → ios-B1DYuOjh.mjs} +27 -11
  67. package/dist/{ios-B7-lToDu.mjs → ios-B1HvafEG.mjs} +8 -8
  68. package/dist/{ios-ENC4sRPA.mjs → ios-CsRVik64.mjs} +7 -1
  69. package/dist/{ios-device-CsyryvpT.mjs → ios-device-B4elVFKi.mjs} +3 -3
  70. package/dist/{ios-device-B6HK951C.mjs → ios-device-CiBA-er9.mjs} +1 -1
  71. package/dist/{ios-project-Ty5pHl9O.mjs → ios-project-CR4mZ7CH.mjs} +22 -9
  72. package/dist/{ios-signing-4c_qXvQm.mjs → ios-signing-BJzvDPfU.mjs} +2 -2
  73. package/dist/{ios-state-Cw7-WQf2.mjs → ios-state-BPHqMDdZ.mjs} +1 -1
  74. package/dist/{ios-ftxdQbJS.mjs → ios-tg4tp3q1.mjs} +94 -37
  75. package/dist/{js-swap-BMhXYVDS.mjs → js-swap-CVpSW1fn.mjs} +8 -7
  76. package/dist/{launch-DOp8RjDz.mjs → launch-DoySmhjz.mjs} +42 -38
  77. package/dist/lightened-DFAJgfIk.mjs +171 -0
  78. package/dist/{logs-s1dRIG1E.mjs → logs-BGsW7iPe.mjs} +46 -21
  79. package/dist/{logs-dQDki6Tt.mjs → logs-DI5ILkYB.mjs} +7 -7
  80. package/dist/{macos-DBBPNnIA.mjs → macos-Bo9st9Di.mjs} +73 -38
  81. package/dist/{macos-B0VEV3Gf.mjs → macos-C12RMJQF.mjs} +1 -1
  82. package/dist/macos-run.mjs +1 -1
  83. package/dist/maintenance-run.mjs +7 -7
  84. package/dist/{metro-CjC10t6E.mjs → metro-BnhXV2Mj.mjs} +4 -4
  85. package/dist/{metro-gateway-B6_PgD0L.mjs → metro-request-DXyKjVDF.mjs} +26 -47
  86. package/dist/{named-ports-BG0j1X4g.mjs → named-ports-Phoi2POD.mjs} +3 -3
  87. package/dist/{native-android-CL2NGiik.mjs → native-android-vxgtLD7w.mjs} +17 -18
  88. package/dist/{native-gradle-artifact-inputs-btSUulme.mjs → native-gradle-artifact-inputs-BN96IVw8.mjs} +5 -5
  89. package/dist/{native-runtime-Dq3RBcON.mjs → native-runtime-DG4Rodzj.mjs} +9 -8
  90. package/dist/{native-source-D-4Dh4JU.mjs → native-source-D1AzWiuP.mjs} +1 -1
  91. package/dist/{native-xcode-inputs-BW7H8JGu.mjs → native-xcode-inputs-BKarCoKg.mjs} +3 -3
  92. package/dist/{native-xcode-ios-CBXJAxfC.mjs → native-xcode-ios-8A-efGa5.mjs} +17 -17
  93. package/dist/{ndjson-CgE_o3Dl.mjs → ndjson-Dy2W4vRa.mjs} +2 -2
  94. package/dist/offload-worker.mjs +23 -24
  95. package/dist/{operation-exec-CUZifp6Z.mjs → operation-exec-Dp4FuIGR.mjs} +1 -1
  96. package/dist/{ownership-BjYvMNX_.mjs → ownership-DJCq48IJ.mjs} +3 -3
  97. package/dist/{page-CzEA_-5_.mjs → page-CQJlcj3x.mjs} +2 -2
  98. package/dist/{phone-reverses-lmj6kcPm.mjs → phone-reverses-BzTa8g1F.mjs} +18 -4
  99. package/dist/{placement-log-DIFPQAXp.mjs → placement-log-Cvhta5ib.mjs} +3 -3
  100. package/dist/{plan-placement-IiiSQhtz.mjs → plan-placement-WkZdccuN.mjs} +36 -10
  101. package/dist/{ports-C2_w1Z0Z.mjs → ports-UV4mJgyC.mjs} +3 -3
  102. package/dist/{prebuild-gmouvmJZ.mjs → prebuild-k8d_tqOq.mjs} +16 -17
  103. package/dist/{project-BUu6Is4k.mjs → project-Sui52ywT.mjs} +17 -17
  104. package/dist/{pull-request-CbNlkFok.mjs → pull-request-BzLmzAIQ.mjs} +2 -2
  105. package/dist/pull-requests.mjs +1 -1
  106. package/dist/{react-native-android-Cgg99REN.mjs → react-native-android-DANlGGQf.mjs} +32 -26
  107. package/dist/{react-native-build-oNwqF5Wb.mjs → react-native-build-jUHnIfZ9.mjs} +9 -9
  108. package/dist/{react-native-doctor-BhA3KUte.mjs → react-native-doctor-DCWRjS7K.mjs} +6 -6
  109. package/dist/{react-native-ios-B-nf4rjN.mjs → react-native-ios-BwMsFMXi.mjs} +23 -17
  110. package/dist/{recordings-BldzVKq0.mjs → recordings-iy0mkm7b.mjs} +1 -1
  111. package/dist/{registration-CN6nlhcD.mjs → registration-BwCe64PH.mjs} +1 -1
  112. package/dist/{reload-C9OduiNc.mjs → reload-Bj7QyuDy.mjs} +1 -1
  113. package/dist/{reload-CCR7KC_l.mjs → reload-c_uEyc_X.mjs} +16 -16
  114. package/dist/{remote-C8S7FlPF.mjs → remote-DFlpAqdV.mjs} +23 -10
  115. package/dist/{result-7F5hEwQJ.mjs → result-BIcXREyC.mjs} +32 -21
  116. package/dist/{run-BqB0v3pt.mjs → run-y2HwyNvg.mjs} +3 -3
  117. package/dist/{selection-BNPBZ6T5.mjs → selection-CXgM_VK_.mjs} +37 -29
  118. package/dist/{server-bare-A75rDIdD.mjs → server-bare-2N4vSRZG.mjs} +2 -2
  119. package/dist/{server-command-CssKFOD7.mjs → server-command-qneHPcRI.mjs} +6 -6
  120. package/dist/{server-expo-eQfOdydb.mjs → server-expo-Ccm9zB0o.mjs} +4 -4
  121. package/dist/server-expo-WulkyAwT.mjs +2 -0
  122. package/dist/{settings-CosW5X-S.mjs → settings-CY5JZlNN.mjs} +375 -62
  123. package/dist/{settings-OaGQF-ri.mjs → settings-Cfd_Q6ys.mjs} +24 -3
  124. package/dist/settings-payload-DwQiEMCn.mjs +257 -0
  125. package/dist/settings-write-CJpjkeAd.mjs +185 -0
  126. package/dist/settings.schema.json +51 -33
  127. package/dist/{simslim-Bax1qcxu.mjs → simslim-DCQwzoPy.mjs} +2 -2
  128. package/dist/{slot-launch-CYCEhfBY.mjs → slot-launch-BpmanOnk.mjs} +6 -6
  129. package/dist/{stage-jKQ7CP_B.mjs → stage-CmugrSG5.mjs} +2 -2
  130. package/dist/{start-C_wefNKB.mjs → start-CHH3zgIU.mjs} +1 -1
  131. package/dist/{start-_BdJ32cZ.mjs → start-DYLk6GXn.mjs} +27 -22
  132. package/dist/{state-C1i2nMOP.mjs → state-B2QJbDwz.mjs} +4 -4
  133. package/dist/{state-C4OdpOTF.mjs → state-BXC1Lfxw.mjs} +2 -2
  134. package/dist/{stats-tEpEEH-u.mjs → stats-DxKqhcGp.mjs} +5 -5
  135. package/dist/{stats-report-n2U5plhk.mjs → stats-report-B86Cv7Uc.mjs} +1 -1
  136. package/dist/{status-CRXz-Gtj.mjs → status-7ULDEJ1e.mjs} +1 -1
  137. package/dist/{status-DQrqodLj.mjs → status-BHCkOZga.mjs} +51 -28
  138. package/dist/{status-B9M7x4CZ.mjs → status-D_Ljc89p.mjs} +1 -1
  139. package/dist/{status-watch-B5wDIH_o.mjs → status-watch-BmsPqYSU.mjs} +18 -7
  140. package/dist/status-worker.mjs +1 -1
  141. package/dist/{stim-desktop-6Dqp-gjX.mjs → stim-desktop-CbWo21kb.mjs} +2 -2
  142. package/dist/{stop-DRqQVqDJ.mjs → stop-D-dGE9gh.mjs} +21 -20
  143. package/dist/{stop-ySNQHXMG.mjs → stop-DQvE-P76.mjs} +10 -6
  144. package/dist/{stop-CmdNhGlC.mjs → stop-b2pouxAO.mjs} +2 -2
  145. package/dist/supervisor-run.mjs +237 -63
  146. package/dist/{support-BGSCBoib.mjs → support-04IhBUTT.mjs} +6 -6
  147. package/dist/{support-CVOCp0Ft.mjs → support-BtlJKjyQ.mjs} +12 -11
  148. package/dist/{swiftpm-artifact-inputs-CfUzt_0Z.mjs → swiftpm-artifact-inputs-Cj2UpmPN.mjs} +4 -4
  149. package/dist/{swiftpm-macos-x6HPpl_2.mjs → swiftpm-macos-BhF2stxY.mjs} +11 -12
  150. package/dist/{toolchain-J4J8MrAr.mjs → toolchain-mLA_km-b.mjs} +321 -15
  151. package/dist/{toolchain-DoavrvIA.mjs → toolchain-qktiV8xc.mjs} +1 -1
  152. package/dist/{trigger-KVaWWNyn.mjs → trigger-DMou-X7j.mjs} +2 -2
  153. package/dist/trigger-qp2ji5wE.mjs +2 -0
  154. package/dist/{warm-progress-DvhTX_eu.mjs → warm-progress-B0Vpuvpl.mjs} +731 -727
  155. package/dist/{web-Bihbf7-u.mjs → web-BYmK0TjL.mjs} +9 -9
  156. package/dist/web-CrVLVQZY.mjs +2 -0
  157. package/dist/web-run.mjs +9 -9
  158. package/dist/windows-report.mjs +1 -1
  159. package/dist/{workspace-state-pUg3_RRA.mjs → workspace-state-kIZrdlSg.mjs} +3 -3
  160. package/dist/{workspaces-g2lhdBXF.mjs → workspaces-CmOcceDN.mjs} +1879 -74
  161. package/dist/{worktree-BKuklFh_.mjs → worktree-2dk5edza.mjs} +933 -534
  162. package/dist/worktree-nliAoHxB.mjs +2 -0
  163. package/package.json +7 -7
  164. package/dist/ccache-Bx5TbxwG.mjs +0 -143
  165. package/dist/eas-fallback-FwkeqqGi.mjs +0 -381
  166. package/dist/hosted-ios-D55QhYaD.mjs +0 -15
  167. package/dist/native-run-BfIDFKLH.mjs +0 -275
  168. package/dist/server-expo-wvcj5tiZ.mjs +0 -2
  169. package/dist/settings-write-QjYfSrjF.mjs +0 -360
  170. package/dist/trigger-DzJu208Q.mjs +0 -2
  171. package/dist/web-BFLueSh-.mjs +0 -2
  172. package/dist/worktree-Bm4cb-nU.mjs +0 -2
@@ -1,19 +1,161 @@
1
- import { D as ownership_claim_exports, o as cancellableSleep, t as getExecutor, u as withWorkspaceProcessLock } from "./exec-VFRpu1iA.mjs";
2
- import { D as workspaceId$1 } from "./workspace-state-pUg3_RRA.mjs";
3
- import { C as saveConfig, G as projectDeviceSlots, H as deviceSlotPlatforms, O as withConfigLockAsync$1, _ as loadConfig$1, a as clearDevice, d as getConfigDir, w as setDevice } from "./config-BktkY_zC.mjs";
4
- import { l as phaseLine } from "./command-output-BF5AR2dL.mjs";
5
- import { E as iosSimSlimProfileSetting, T as iosSimSlimDefaultSetting } from "./settings-CosW5X-S.mjs";
6
- import { mt as dropParked, pt as adoptParked, vt as parkedMaxSetting, xt as selectParked, yt as readParked } from "./android-DTAcRwBC.mjs";
7
- import { M as teardownParkedIosSim } from "./workspaces-g2lhdBXF.mjs";
8
- import { C as renameIosSim, D as resolveOwnedIosSim, E as resolveIosCreation, L as readHostMemoryPressure, M as configuredIosSimulatorViewer, P as hostMemoryPressureAdvice, S as readSpringBoardPid, T as resetIosPrivacy, _ as ownedSimName, a as createOwnedIosSim, d as listAllIosSims, f as listAllIosSimsAsync, h as listIosRuntimesAsync, j as waitForSpringBoard, n as bootIosSim, p as listIosDeviceTypesAsync, u as iosSimulatorFailureAdvice, w as resetIosKeychain, y as parseRuntimeVersion, z as reportMemoryCulprits } from "./ios-WxpDJ5T1.mjs";
9
- import { l as runtimeMismatch, m as withDeviceBootAdmission, n as DeviceAdmissionRefusal, o as deviceTypeMismatch } from "./device-capacity-DCSvUF0l.mjs";
1
+ import { D as ownership_claim_exports, o as cancellableSleep, t as getExecutor, u as withWorkspaceProcessLock } from "./exec-aULwtNly.mjs";
2
+ import { D as workspaceId$1, k as workspaceLogsDir$1 } from "./workspace-state-kIZrdlSg.mjs";
3
+ import { C as saveConfig, G as projectDeviceSlots, H as deviceSlotPlatforms, O as withConfigLockAsync$1, _ as loadConfig$1, a as clearDevice, d as getConfigDir, w as setDevice } from "./config-Cn94Jc0g.mjs";
4
+ import { l as phaseLine } from "./command-output-C8R1KIvi.mjs";
5
+ import { D as iosSimSlimProfileSetting, E as iosSimSlimDefaultSetting } from "./settings-CY5JZlNN.mjs";
6
+ import { mt as dropParked, pt as adoptParked, vt as parkedMaxSetting, xt as selectParked, yt as readParked } from "./android-CsPs-7Mg.mjs";
7
+ import { i as createNdjsonWriter } from "./ndjson-Dy2W4vRa.mjs";
8
+ import { _t as teardownParkedIosSim, ht as teardownOwnedIosSim } from "./workspaces-CmOcceDN.mjs";
9
+ import { A as springBoardRunning, B as reportMemoryCulprits, C as renameIosSim, D as resolveOwnedIosSim, E as resolveIosCreation, F as hostMemoryPressureAdvice, M as waitForSpringBoard, N as configuredIosSimulatorViewer, R as readHostMemoryPressure, S as readSpringBoardPid, T as resetIosPrivacy, _ as ownedSimName, a as createOwnedIosSim, d as listAllIosSims, f as listAllIosSimsAsync, h as listIosRuntimesAsync, n as bootIosSim, p as listIosDeviceTypesAsync, u as iosSimulatorFailureAdvice, w as resetIosKeychain, y as parseRuntimeVersion } from "./ios-B1DYuOjh.mjs";
10
+ import { c as deviceTypeMismatch, d as runtimeMismatch, g as withDeviceBootAdmission, n as DeviceAdmissionRefusal } from "./device-capacity-Cd8lMSn3.mjs";
10
11
  import { createHash } from "node:crypto";
11
12
  import { readFileSync } from "node:fs";
12
- import { ambientContext } from "@stim-cli/core";
13
+ import { homedir } from "node:os";
14
+ import { join } from "node:path";
15
+ import { LOG_ROTATE_BYTES, ambientContext } from "@stim-cli/core";
13
16
  import { isJsonObject } from "@stim-cli/core/state";
14
17
  import chalk from "chalk";
18
+ import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
19
+ //#region src/devices/springboard-crash-reports.ts
20
+ const REPORT_WINDOW_MS = 6e5;
21
+ const MAX_CANDIDATES = 100;
22
+ const MAX_STORED = 40;
23
+ const MAX_REPORT_BYTES = 1048576;
24
+ const MAX_COPIED_BYTES = 8388608;
25
+ function selectSpringBoardReports(entries, udid, sinceMs) {
26
+ const owner = `.${udid}`.toLowerCase();
27
+ return entries.flatMap(({ name, text }) => {
28
+ if (!/^SpringBoard-.+\.ips$/.test(name)) return [];
29
+ try {
30
+ const report = JSON.parse(text.slice(text.indexOf("\n") + 1));
31
+ if (!isJsonObject(report)) return [];
32
+ const { coalitionName, captureTime } = report;
33
+ const capturedAt = Date.parse(typeof captureTime === "string" ? captureTime : "");
34
+ return typeof coalitionName === "string" && coalitionName.toLowerCase().endsWith(owner) && capturedAt >= sinceMs ? [name] : [];
35
+ } catch {
36
+ return [];
37
+ }
38
+ });
39
+ }
40
+ /**
41
+ * Copies this simulator's recent SpringBoard crash reports from DiagnosticReports and its Retired folder into
42
+ * `destDir`, which keeps at most 40 of them. The source folders are only read; macOS deletes their reports after
43
+ * about two days. Returns the matching reports now in `destDir`, how many matched but did not fit its limits, and
44
+ * the message of a write that failed.
45
+ */
46
+ async function copySpringBoardCrashReports({ udid, destDir, now = Date.now(), home = homedir() }) {
47
+ const since = now - REPORT_WINDOW_MS;
48
+ const reportsDir = join(home, "Library/Logs/DiagnosticReports");
49
+ const candidates = /* @__PURE__ */ new Map();
50
+ for (const directory of [reportsDir, join(reportsDir, "Retired")]) {
51
+ let names;
52
+ try {
53
+ names = await readdir(directory);
54
+ } catch (error) {
55
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") continue;
56
+ throw error;
57
+ }
58
+ for (const name of names) {
59
+ if (!/^SpringBoard-.+\.ips$/.test(name) || candidates.has(name)) continue;
60
+ try {
61
+ const path = join(directory, name);
62
+ const { mtimeMs, size } = await stat(path);
63
+ if (mtimeMs >= since && size <= MAX_REPORT_BYTES) candidates.set(name, {
64
+ path,
65
+ mtimeMs
66
+ });
67
+ } catch {}
68
+ }
69
+ }
70
+ const newest = [...candidates].toSorted((a, b) => b[1].mtimeMs - a[1].mtimeMs).slice(0, MAX_CANDIDATES);
71
+ const entries = [];
72
+ for (const [name, { path }] of newest) try {
73
+ entries.push({
74
+ name,
75
+ text: await readFile(path, "utf8")
76
+ });
77
+ } catch {}
78
+ const matching = selectSpringBoardReports(entries, udid, since);
79
+ if (matching.length === 0) return {
80
+ files: [],
81
+ dropped: 0
82
+ };
83
+ await mkdir(destDir, {
84
+ recursive: true,
85
+ mode: 448
86
+ });
87
+ const present = new Set(await readdir(destDir));
88
+ let stored = [...present].filter((name) => /^SpringBoard-.+\.ips$/.test(name)).length;
89
+ let copiedBytes = 0;
90
+ const files = [];
91
+ for (const { name, text } of entries) {
92
+ if (!matching.includes(name)) continue;
93
+ if (present.has(name)) {
94
+ files.push(name);
95
+ continue;
96
+ }
97
+ const bytes = Buffer.byteLength(text);
98
+ if (stored >= MAX_STORED || copiedBytes + bytes > MAX_COPIED_BYTES) continue;
99
+ try {
100
+ await writeFile(join(destDir, name), text, {
101
+ flag: "wx",
102
+ mode: 384
103
+ });
104
+ } catch (error) {
105
+ if (error instanceof Error && "code" in error && error.code === "EEXIST") {
106
+ files.push(name);
107
+ continue;
108
+ }
109
+ await rm(join(destDir, name), { force: true }).catch(() => {});
110
+ return {
111
+ files,
112
+ dropped: 0,
113
+ failure: error instanceof Error ? error.message : String(error)
114
+ };
115
+ }
116
+ stored++;
117
+ copiedBytes += bytes;
118
+ files.push(name);
119
+ }
120
+ return {
121
+ files,
122
+ dropped: matching.length - files.length
123
+ };
124
+ }
125
+ //#endregion
126
+ //#region src/engine/ios-boot-log.ts
127
+ function iosBootRecorder(root, slot, udid) {
128
+ return (event, { level = "info", ...fields }) => {
129
+ try {
130
+ const writer = createNdjsonWriter(join(workspaceLogsDir$1(root), "device.ndjson"), { maxBytes: LOG_ROTATE_BYTES });
131
+ writer.write({
132
+ src: "device",
133
+ platform: "ios",
134
+ level,
135
+ event,
136
+ deviceId: udid,
137
+ ...slot && slot !== "default" ? { slot } : {},
138
+ ...fields
139
+ });
140
+ writer.close();
141
+ } catch {}
142
+ };
143
+ }
144
+ //#endregion
15
145
  //#region src/engine/device-ios.ts
16
- function startIosBoot(udid, configure, label, out, simulatorApp, root, deviceSlotWait) {
146
+ function recordBootPhase(record, udid, origin) {
147
+ return (event) => {
148
+ const pid = "pid" in event ? event.pid : void 0;
149
+ const boot = event.phase === "boot_requested" ? origin : void 0;
150
+ record("ios_boot", {
151
+ phase: event.phase,
152
+ ...pid === void 0 ? {} : { pid },
153
+ ...boot === void 0 ? {} : { boot },
154
+ msg: `ios boot ${udid}: ${event.phase}${pid === void 0 ? "" : ` pid ${pid}`}${boot === void 0 ? "" : ` (${boot})`}`
155
+ });
156
+ };
157
+ }
158
+ function startIosBoot(udid, configure, label, out, simulatorApp, root, slot, origin, deviceSlotWait) {
17
159
  const done = withDeviceBootAdmission({
18
160
  platform: "ios",
19
161
  key: udid
@@ -23,7 +165,8 @@ function startIosBoot(udid, configure, label, out, simulatorApp, root, deviceSlo
23
165
  label,
24
166
  out,
25
167
  simulatorApp,
26
- env: ambientContext()?.env
168
+ env: ambientContext()?.env,
169
+ onPhase: recordBootPhase(iosBootRecorder(root, slot, udid), udid, origin)
27
170
  });
28
171
  await configure();
29
172
  await muteBootedSimulator(udid, out);
@@ -120,7 +263,7 @@ async function ensureOwnedIosDevice({ record, projectPath, slot, settingsRoot, l
120
263
  };
121
264
  if (sim.state !== "Booted") return {
122
265
  ...updated,
123
- booting: startIosBoot(sim.udid, () => configure(true), name, out, flags.simulatorApp, projectPath, flags.deviceSlotWait),
266
+ booting: startIosBoot(sim.udid, () => configure(true), name, out, flags.simulatorApp, projectPath, slot, record.adoptionPending ? "adopted" : "existing", flags.deviceSlotWait),
124
267
  ...facts
125
268
  };
126
269
  const { record: configured, rebooted } = await configure(false);
@@ -172,7 +315,7 @@ async function ensureOwnedIosDevice({ record, projectPath, slot, settingsRoot, l
172
315
  out,
173
316
  reconcileIosSimulator
174
317
  });
175
- }, adopted.deviceName, out, flags.simulatorApp, projectPath, flags.deviceSlotWait);
318
+ }, adopted.deviceName, out, flags.simulatorApp, projectPath, slot, "adopted", flags.deviceSlotWait);
176
319
  return {
177
320
  ...adopted,
178
321
  booting,
@@ -207,7 +350,7 @@ async function ensureOwnedIosDevice({ record, projectPath, slot, settingsRoot, l
207
350
  freshBoot: true,
208
351
  out,
209
352
  reconcileIosSimulator
210
- }), created.name, out, flags.simulatorApp, projectPath, flags.deviceSlotWait);
353
+ }), created.name, out, flags.simulatorApp, projectPath, slot, "created", flags.deviceSlotWait);
211
354
  return {
212
355
  ...newRecord,
213
356
  created: true,
@@ -314,11 +457,15 @@ function simslimProfileIdentity(profile, slimByDefault) {
314
457
  if (profile) return `profile:${createHash("sha256").update(readFileSync(profile)).digest("hex")}`;
315
458
  return slimByDefault ? "default" : null;
316
459
  }
460
+ async function startedSpringBoardPid(udid) {
461
+ const springBoard = await waitForSpringBoard(udid, Date.now() + SPRINGBOARD_MUTE_WAIT_MS);
462
+ return springBoard.state === "started" ? springBoard.pid : null;
463
+ }
317
464
  async function configureOwnedIosSim({ record, projectPath, slot, profile, slimByDefault, freshBoot, out, reconcileIosSimulator }) {
318
465
  const identity = simslimProfileIdentity(profile, slimByDefault);
319
466
  const slimConfigured = identity !== null || Boolean(record.simslimManaged);
320
467
  const applied = record.simslimApplied;
321
- const springBoardBefore = slimConfigured && !freshBoot ? await readSpringBoardPid(record.deviceUdid) : null;
468
+ const springBoardBefore = slimConfigured ? await readSpringBoardPid(record.deviceUdid) : null;
322
469
  if (identity !== null && record.simslimManaged && !freshBoot && applied?.profile === identity && springBoardBefore !== null && springBoardBefore === applied.springBoardPid) {
323
470
  await withConfigLockAsync$1(() => setDevice(projectPath, "ios", { ...record }, slot));
324
471
  return {
@@ -350,32 +497,112 @@ async function configureOwnedIosSim({ record, projectPath, slot, profile, slimBy
350
497
  const updated = { ...record };
351
498
  if (result.managed) updated.simslimManaged = true;
352
499
  else delete updated.simslimManaged;
353
- const springBoardAfter = slimConfigured ? await readSpringBoardPid(record.deviceUdid) : null;
500
+ const springBoardAfter = slimConfigured ? await startedSpringBoardPid(record.deviceUdid) : null;
354
501
  if (result.managed && !result.notInstalled && identity !== null && springBoardAfter !== null) updated.simslimApplied = {
355
502
  profile: identity,
356
503
  springBoardPid: springBoardAfter
357
504
  };
358
505
  await withConfigLockAsync$1(() => setDevice(projectPath, "ios", updated, slot));
506
+ const rebooted = slimConfigured && springBoardAfter !== springBoardBefore;
507
+ if (rebooted && !result.notInstalled) iosBootRecorder(projectPath, slot, record.deviceUdid)("ios_boot", {
508
+ phase: "simslim_reboot",
509
+ pidBefore: springBoardBefore,
510
+ pidAfter: springBoardAfter,
511
+ msg: `ios boot ${record.deviceUdid}: simslim_reboot (SpringBoard pid ${springBoardBefore ?? "unknown"} to ${springBoardAfter ?? "unknown"})`
512
+ });
359
513
  return {
360
514
  record: updated,
361
- rebooted: slimConfigured && springBoardAfter !== springBoardBefore
515
+ rebooted
362
516
  };
363
517
  }
364
- async function ensureIosBooted({ device, projectPath, deviceSlotWait, simulatorApp, timeoutMs, pollMs, out }) {
518
+ const SPRINGBOARD_RESPAWN_POLLS = 20;
519
+ async function ensureIosBooted(args) {
520
+ const { springBoardDown, ...first } = await bootOwnedIosSim(args);
521
+ const { device, projectPath, out } = args;
522
+ const udid = device?.deviceUdid;
523
+ if (!springBoardDown || !device || !udid) return first;
524
+ out(chalk.yellow(phaseLine("device", `SpringBoard is not running on ${udid}; restarting the simulator once`)));
525
+ const record = iosBootRecorder(projectPath, args.slot, udid);
526
+ await preserveSpringBoardReports(record, udid, projectPath);
527
+ const stopped = await teardownOwnedIosSim(udid, { workspace: projectPath });
528
+ if (stopped.status !== "torn-down") return {
529
+ ...first,
530
+ reason: `${first.reason} The restart did not run: ${stopped.reason ?? stopped.status}.`
531
+ };
532
+ record("ios_boot", {
533
+ phase: "restart",
534
+ level: "warn",
535
+ msg: `ios boot ${udid}: restart (SpringBoard is not running after boot; restarting once)`
536
+ });
537
+ const { booted: _booted, booting: _booting, ...unbooted } = device;
538
+ const { springBoardDown: stillDown, ...second } = await bootOwnedIosSim({
539
+ ...args,
540
+ device: unbooted,
541
+ origin: "restart"
542
+ });
543
+ if (stillDown) await preserveSpringBoardReports(record, udid, projectPath);
544
+ return stillDown ? {
545
+ ...second,
546
+ reason: `${second.reason} Stim already restarted the simulator once, so it did not restart it again.`
547
+ } : second;
548
+ }
549
+ async function preserveSpringBoardReports(record, udid, root) {
550
+ const dir = workspaceLogsDir$1(root);
551
+ try {
552
+ const { files, dropped, failure } = await copySpringBoardCrashReports({
553
+ udid,
554
+ destDir: dir
555
+ });
556
+ const limit = dropped ? `; ${dropped} more matched but exceeded the copy limits` : "";
557
+ record("springboard_crash_reports", {
558
+ level: files.length || dropped || failure ? "warn" : "info",
559
+ files,
560
+ dropped,
561
+ ...failure ? { failure } : {},
562
+ dir,
563
+ msg: failure ? `could not copy a SpringBoard crash report for ${udid} (${files.length} copied before it): ${failure}` : files.length ? `copied ${files.length} SpringBoard crash report(s) for ${udid} to ${dir}: ${files.join(", ")}${limit}` : dropped ? `${dropped} SpringBoard crash report(s) for ${udid} matched but exceeded the copy limits` : `no SpringBoard crash report for ${udid} from the last 10 minutes`
564
+ });
565
+ } catch (error) {
566
+ record("springboard_crash_reports", {
567
+ level: "warn",
568
+ files: [],
569
+ dropped: 0,
570
+ failure: error instanceof Error ? error.message : String(error),
571
+ dir,
572
+ msg: `could not copy SpringBoard crash reports for ${udid}: ${error instanceof Error ? error.message : String(error)}`
573
+ });
574
+ }
575
+ }
576
+ async function bootOwnedIosSim({ device, projectPath, slot, origin, deviceSlotWait, simulatorApp, timeoutMs, pollMs, out }) {
365
577
  const udid = device?.deviceUdid;
366
578
  if (!udid) return {
367
579
  failed: true,
368
580
  reason: "No iOS simulator is recorded for this project."
369
581
  };
582
+ const onPhase = recordBootPhase(iosBootRecorder(projectPath, slot, udid), udid, origin ?? (device.adoptionPending ? "adopted" : "existing"));
583
+ const openViewer = async () => {
584
+ await configuredIosSimulatorViewer(simulatorApp, ambientContext()?.env).open(udid);
585
+ onPhase({ phase: "viewer_opened" });
586
+ };
370
587
  const ready = async () => {
371
588
  try {
372
- await getExecutor().runFileAsync("xcrun", [
589
+ const listSpringBoard = () => getExecutor().runFileAsync("xcrun", [
373
590
  "simctl",
374
591
  "spawn",
375
592
  udid,
376
593
  "launchctl",
377
594
  "list"
378
595
  ], { timeoutMs: 3e4 });
596
+ let listing = await listSpringBoard();
597
+ for (let poll = 0; !springBoardRunning(listing) && poll < SPRINGBOARD_RESPAWN_POLLS; poll++) {
598
+ await cancellableSleep(pollMs);
599
+ listing = await listSpringBoard();
600
+ }
601
+ if (!springBoardRunning(listing)) return {
602
+ failed: true,
603
+ springBoardDown: true,
604
+ reason: `Simulator ${udid} reports Booted, but SpringBoard (the system shell) is not running, so apps cannot launch. Run \`stim stop\`, then \`stim ios\` again. If it repeats, look for SpringBoard crash reports in ~/Library/Logs/DiagnosticReports.`
605
+ };
379
606
  return {
380
607
  ok: true,
381
608
  udid
@@ -398,7 +625,7 @@ async function ensureIosBooted({ device, projectPath, deviceSlotWait, simulatorA
398
625
  }
399
626
  const readiness = device?.booted === udid ? await ready() : null;
400
627
  if (readiness?.ok) {
401
- if (simulatorApp !== void 0) await configuredIosSimulatorViewer(simulatorApp, ambientContext()?.env).open(udid);
628
+ if (simulatorApp !== void 0) await openViewer();
402
629
  return readiness;
403
630
  }
404
631
  let resolved;
@@ -421,7 +648,7 @@ async function ensureIosBooted({ device, projectPath, deviceSlotWait, simulatorA
421
648
  const sim = resolved.sim;
422
649
  if (sim.state === "Booted") {
423
650
  const result = readiness ?? await ready();
424
- if (result.ok && simulatorApp !== void 0) await configuredIosSimulatorViewer(simulatorApp, ambientContext()?.env).open(udid);
651
+ if (result.ok && simulatorApp !== void 0) await openViewer();
425
652
  return result;
426
653
  }
427
654
  const bootDeadline = Date.now() + timeoutMs;
@@ -436,7 +663,8 @@ async function ensureIosBooted({ device, projectPath, deviceSlotWait, simulatorA
436
663
  label: sim.name,
437
664
  out,
438
665
  simulatorApp,
439
- env: ambientContext()?.env
666
+ env: ambientContext()?.env,
667
+ onPhase
440
668
  });
441
669
  await muteBootedSimulator(udid, out);
442
670
  }, {
@@ -1,8 +1,8 @@
1
- import { b as operationState } from "./exec-VFRpu1iA.mjs";
2
- import { V as deviceSlotKey } from "./config-BktkY_zC.mjs";
3
- import { a as formatElapsed, r as clockTime } from "./command-output-BF5AR2dL.mjs";
4
- import { nn as MANIFEST_VERIFY_TIMEOUT_MS, pn as APP_READINESS_TIMEOUT_MS } from "./budget-k2mZGvvk.mjs";
5
- import { E as releaseRunLease, S as parseLease, T as raiseLease, b as leaseIsExpired, j as takeLease, v as deviceLeasePath, y as fileLeaseIo } from "./activity-Lnb_EoRY.mjs";
1
+ import { b as operationState } from "./exec-aULwtNly.mjs";
2
+ import { V as deviceSlotKey } from "./config-Cn94Jc0g.mjs";
3
+ import { a as formatElapsed, r as clockTime } from "./command-output-C8R1KIvi.mjs";
4
+ import { Xt as APP_READINESS_TIMEOUT_MS, zt as MANIFEST_VERIFY_TIMEOUT_MS } from "./ccache-Bm_A1xX9.mjs";
5
+ import { E as releaseRunLease, S as parseLease, T as raiseLease, b as leaseIsExpired, j as takeLease, v as deviceLeasePath, y as fileLeaseIo } from "./activity-DRMg4_mD.mjs";
6
6
  //#region src/engine/device-lease-run.ts
7
7
  const LEASE_STEP_FLOOR_MS = 6e4;
8
8
  const DEBUG_VERIFY_STEP_MS = MANIFEST_VERIFY_TIMEOUT_MS + APP_READINESS_TIMEOUT_MS;
@@ -1,6 +1,6 @@
1
- import { V as deviceSlotKey } from "./config-BktkY_zC.mjs";
2
- import { A as selectPoolDevice, S as parseLease, b as leaseIsExpired, v as deviceLeasePath, y as fileLeaseIo } from "./activity-Lnb_EoRY.mjs";
3
- import { i as DEVICE_WAIT_POLL_MS, n as DEVICE_BUSY, o as leaseExpiryText } from "./device-lease-run-BmvIl7bI.mjs";
1
+ import { V as deviceSlotKey } from "./config-Cn94Jc0g.mjs";
2
+ import { A as selectPoolDevice, S as parseLease, b as leaseIsExpired, v as deviceLeasePath, y as fileLeaseIo } from "./activity-DRMg4_mD.mjs";
3
+ import { i as DEVICE_WAIT_POLL_MS, n as DEVICE_BUSY, o as leaseExpiryText } from "./device-lease-run-Mtzp4THX.mjs";
4
4
  //#region src/engine/device-pool.ts
5
5
  function heldPoolId(root, platform, now, io = fileLeaseIo, slot = "default") {
6
6
  const record = io.readHolder(root)[deviceSlotKey(platform, slot)];
@@ -1,17 +1,17 @@
1
- import { Z as doctorIo, _ as loadConfig$1, p as getProject } from "./config-BktkY_zC.mjs";
2
- import { f as refuseNoProject, l as phaseLine } from "./command-output-BF5AR2dL.mjs";
3
- import { Nt as repoRoot, R as projectSettingsContextAsync } from "./settings-CosW5X-S.mjs";
4
- import { f as projectRegistry, t as NO_PROJECT_REFUSAL } from "./project-BUu6Is4k.mjs";
5
- import { c as inspectStimVersions, s as compareStimVersions } from "./eas-session-ledger-B5vygTiD.mjs";
6
- import { a as inspectBudget, hr as inspectWatchmanMemory, n as budgetLine, yr as memorySweepIsScoped } from "./budget-k2mZGvvk.mjs";
7
- import { H as readMemoryCulpritsAsync, V as memoryCulpritFindings, f as listAllIosSimsAsync, h as listIosRuntimesAsync, l as iosRuntimeMatches, x as pickDefaultIosCreation } from "./ios-WxpDJ5T1.mjs";
8
- import { I as detectXcodeMajorAsync } from "./toolchain-J4J8MrAr.mjs";
9
- import { s as offloadCheck } from "./client-D9CaRks-.mjs";
10
- import { d as inspectBuildMachines, g as inspectDeviceHostMachines } from "./selection-BNPBZ6T5.mjs";
11
- import { r as maintenanceStatus, t as maintenanceLine } from "./status-CRXz-Gtj.mjs";
12
- import { a as writeIgnoreDirs, c as recordDoctorRun, i as watchedCheckouts, n as inspectNestedWorktrees, r as nestedWorktreeFinding } from "./doctor-watchman-BStK05nt.mjs";
13
- import { c as checkWorktreeStorageLayout, l as readMachineSettings, o as runDoctor } from "./doctor-OnwP94ne.mjs";
14
- import { h as resolveDeviceType, v as resolveRuntime } from "./support-CVOCp0Ft.mjs";
1
+ import { Q as doctorIo, _ as loadConfig$1, p as getProject } from "./config-Cn94Jc0g.mjs";
2
+ import { f as refuseNoProject, l as phaseLine } from "./command-output-C8R1KIvi.mjs";
3
+ import { Bt as repoRoot, z as projectSettingsContextAsync } from "./settings-CY5JZlNN.mjs";
4
+ import { f as projectRegistry, t as NO_PROJECT_REFUSAL } from "./project-Sui52ywT.mjs";
5
+ import { Qn as inspectWatchmanMemory, f as inspectBudget, l as budgetLine, nr as memorySweepIsScoped } from "./ccache-Bm_A1xX9.mjs";
6
+ import { c as inspectStimVersions, s as compareStimVersions } from "./eas-session-ledger-CBFo_Uo1.mjs";
7
+ import { I as detectXcodeMajorAsync } from "./toolchain-mLA_km-b.mjs";
8
+ import { H as memoryCulpritFindings, U as readMemoryCulpritsAsync, f as listAllIosSimsAsync, h as listIosRuntimesAsync, l as iosRuntimeMatches, x as pickDefaultIosCreation } from "./ios-B1DYuOjh.mjs";
9
+ import { s as offloadCheck } from "./client-YxCer6ab.mjs";
10
+ import { g as configuredMachines, p as inspectBuildMachines, v as inspectDeviceHostMachines } from "./selection-CXgM_VK_.mjs";
11
+ import { r as maintenanceStatus, t as maintenanceLine } from "./status-7ULDEJ1e.mjs";
12
+ import { a as writeIgnoreDirs, c as recordDoctorRun, i as watchedCheckouts, n as inspectNestedWorktrees, r as nestedWorktreeFinding } from "./doctor-watchman-BTW82PDC.mjs";
13
+ import { c as checkWorktreeStorageLayout, l as readMachineSettings, o as runDoctor } from "./doctor-xf7ht-5n.mjs";
14
+ import { h as resolveDeviceType, v as resolveRuntime } from "./support-BtlJKjyQ.mjs";
15
15
  import { isJsonObject, maintenanceNdjsonFile, readHostedAppMetadata, readHostedSessions } from "@stim-cli/core/state";
16
16
  import { dirname, join, sep } from "path";
17
17
  import chalk from "chalk";
@@ -419,6 +419,16 @@ async function prepareDoctor(root, platform, registry, operation) {
419
419
  doctors: await selected.load()
420
420
  };
421
421
  }
422
+ function withPriority(machines) {
423
+ const order = configuredMachines() ?? [];
424
+ return machines.map((each) => {
425
+ const at = order.indexOf(each.machine);
426
+ return at < 0 ? each : {
427
+ ...each,
428
+ priority: at + 1
429
+ };
430
+ });
431
+ }
422
432
  async function readDoctorReport(operation, platform, version, requestAccess = false) {
423
433
  const found = projectRegistry.findProjectRoot(operation.projectRoot);
424
434
  if (!found) throw Object.assign(new Error(NO_PROJECT_REFUSAL.message), NO_PROJECT_REFUSAL);
@@ -515,8 +525,8 @@ async function assembleDoctorReport(root, opts, version, prepared, inspectVersio
515
525
  ...maintenance,
516
526
  logPath: maintenanceNdjsonFile()
517
527
  },
518
- remoteMachines: remoteMachines.machines,
519
- deviceHosts: deviceHostMachines.machines,
528
+ remoteMachines: withPriority(remoteMachines.machines),
529
+ deviceHosts: withPriority(deviceHostMachines.machines),
520
530
  toolchain,
521
531
  findings
522
532
  };
@@ -568,7 +578,9 @@ function doctorCommand(program, version, inspectVersions = inspectStimVersions,
568
578
  const report = await assembleDoctorReport(root, opts, version, prepared, inspectVersions, host);
569
579
  const { findings, stim, toolchain, maintenance } = report;
570
580
  const budget = { report: report.budget };
581
+ const order = (configuredMachines() ?? []).map((machine, at) => `${at + 1} ${machine}`);
571
582
  const maintenanceLines = [
583
+ ...order.length ? [phaseLine("placement order", `${order.join(", ")} (first with room and load under its limit)`)] : [],
572
584
  phaseLine("maintenance.mode", maintenance.mode),
573
585
  phaseLine("maintenance log", maintenanceNdjsonFile()),
574
586
  phaseLine("last pass", maintenanceLine(maintenance, false) ?? "no pass has run yet")
@@ -1,2 +1,2 @@
1
- import { a as readDoctorReport, i as parseDoctorPlatform, n as doctorCommand, o as shadowedStimFinding, r as doctorSuccessLines, s as toolchainReport, t as applySandboxFix } from "./doctor-Bhg1ii70.mjs";
1
+ import { a as readDoctorReport, i as parseDoctorPlatform, n as doctorCommand, o as shadowedStimFinding, r as doctorSuccessLines, s as toolchainReport, t as applySandboxFix } from "./doctor-Bz_ouYAW.mjs";
2
2
  export { applySandboxFix, doctorCommand as default, doctorSuccessLines, parseDoctorPlatform, readDoctorReport, shadowedStimFinding, toolchainReport };
@@ -1,4 +1,4 @@
1
- import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
1
+ import { t as getExecutor } from "./exec-aULwtNly.mjs";
2
2
  import { setPriority } from "node:os";
3
3
  import { fileURLToPath } from "node:url";
4
4
  //#region src/doctor-fingerprint.ts
@@ -1,4 +1,4 @@
1
- import { p as fingerprintProject } from "./build-cache-DrXNCy3T.mjs";
1
+ import { m as fingerprintProject } from "./build-cache-CZULpXVl.mjs";
2
2
  import * as fingerprint from "@expo/fingerprint";
3
3
  //#region bin/doctor-fingerprint.ts
4
4
  let input = "";
@@ -1,8 +1,8 @@
1
- import { E as upsertProject, O as withConfigLockAsync$1, d as getConfigDir, p as getProject } from "./config-BktkY_zC.mjs";
2
- import { l as gitQuietAsync } from "./operation-exec-CUZifp6Z.mjs";
3
- import { Dt as listWorktreesAsync, Pt as repoRootAsync } from "./settings-CosW5X-S.mjs";
4
- import { f as projectRegistry } from "./project-BUu6Is4k.mjs";
5
- import { d as parseWatchRoots, m as runWatchman, s as compareStimVersions } from "./eas-session-ledger-B5vygTiD.mjs";
1
+ import { E as upsertProject, O as withConfigLockAsync$1, d as getConfigDir, p as getProject } from "./config-Cn94Jc0g.mjs";
2
+ import { l as gitQuietAsync } from "./operation-exec-Dp4FuIGR.mjs";
3
+ import { Vt as repoRootAsync, jt as listWorktreesAsync } from "./settings-CY5JZlNN.mjs";
4
+ import { f as projectRegistry } from "./project-Sui52ywT.mjs";
5
+ import { d as parseWatchRoots, m as runWatchman, s as compareStimVersions } from "./eas-session-ledger-CBFo_Uo1.mjs";
6
6
  import { mkdirSync, readFileSync, realpathSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
7
7
  import { dirname, isAbsolute, join, relative, sep } from "node:path";
8
8
  import { isJsonObject } from "@stim-cli/core/state";