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
package/README.md CHANGED
@@ -171,7 +171,7 @@ Cache providers must settle after cancellation. If cleanup cannot finish within
171
171
  35 seconds, the plan refuses with `STIM_CLAIM_UNAVAILABLE` and retains the download
172
172
  directory; it does not delete files a broken provider may still be writing.
173
173
 
174
- `doctor({ platform?, record? })` and `gc({ cache?, olderThan?, worktrees? })` read their CLI
174
+ `doctor({ platform?, record? })` and `gc({ cache?, olderThan?, worktrees?, measureBuildState? })` read their CLI
175
175
  JSON reports with a 60 second execution budget and optional `signal`. Doctor
176
176
  never repairs; its `stim.runningPath` is null. By default it does not record a
177
177
  check. Pass `record: true` to register the supported iOS/Android project and record
@@ -1,5 +1,5 @@
1
1
  import { l as WorkspaceProcessCleanupError } from "./exec-VFRpu1iA.mjs";
2
- import { I as waitForSharedBuild } from "./activity-BpjwrQXU.mjs";
2
+ import { I as waitForSharedBuild } from "./activity-Lnb_EoRY.mjs";
3
3
  import { rmSync } from "node:fs";
4
4
  //#region src/engine/artifact-lifecycle.ts
5
5
  async function runArtifactLifecycle(phases) {
@@ -1,22 +1,22 @@
1
- import { l as WorkspaceProcessCleanupError, n as isTimeoutError, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { g as workspaceStateFile$1, m as workspaceLogsDir$1 } from "./paths-DQtTgsBf.mjs";
3
- import { F as isOnMountedVolume, G as projectDeviceSlots, I as listMountedVolumes, L as measuredDirectorySizeAsync, N as directorySizeAsync, P as formatBytes, _ as loadConfig$1, p as getProject } from "./config-BZhXY15H.mjs";
4
- import { o as formatLongDuration, u as plural } from "./command-output-BBvS1H6v.mjs";
1
+ import { b as operationState, l as WorkspaceProcessCleanupError, n as isTimeoutError, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
+ import { j as workspaceStateFile$1, k as workspaceLogsDir$1, r as readWorkspaceState$1, u as workspaceLastUsed } from "./workspace-state-pUg3_RRA.mjs";
3
+ import { F as isOnMountedVolume, G as projectDeviceSlots, I as listMountedVolumes, L as measuredDirectorySizeAsync, N as directorySizeAsync, P as formatBytes, _ as loadConfig$1, p as getProject } from "./config-BktkY_zC.mjs";
4
+ import { o as formatLongDuration, u as plural } from "./command-output-BF5AR2dL.mjs";
5
5
  import { c as gitQuiet, l as gitQuietAsync, n as runOperationFileQuiet, r as childEnvironment } from "./operation-exec-CUZifp6Z.mjs";
6
- import { r as readWorkspaceState$1, u as workspaceLastUsed } from "./workspace-state-CPSp3mav.mjs";
7
- import { Bt as unpushedCommitsAsync, Ct as hasUncommittedWorkAsync, D as maintenanceKeepSetting, Dt as listWorktreesAsync, Et as listWorktrees, Gt as removeTemporaryEntryAsync, It as resolveFullRefAsync, J as resolveProjectSettings, Lt as resolveSourceCheckoutAsync, Y as resolveProjectSettingsAsync, _t as dirtyPathsAsync, xt as hasPopulatedSubmodulesAsync, zt as sourceCheckoutOf } from "./settings-B5tCoq9N.mjs";
8
- import { i as findProjectRoot$1 } from "./project-BiC68mIp.mjs";
9
- import { F as listAvdsAsync, G as ownedAvdSerialResolverAsync, P as listAvds, V as ownedAvdDirectory, yt as readParked } from "./android-Cjcj8MCw.mjs";
10
- import { a as unregister, n as readManifest } from "./cache-manifest-BPXRONJz.mjs";
11
- import { A as workspaceBuildInProgress, Cr as discoverCaches, Ct as deleteParkedSims, Dt as deviceSweepIsScoped, E as collectOwnedDeviceActivityAsync, Q as emptyCaches, St as deleteParkedAvds, T as collectOwnedDeviceActivity, br as phase, bt as collectParkedAvds, d as trimmableCaches, f as stopOwnedMetro, hr as memorySweepIsScoped, ht as waitForGradleExit, i as enforceBudget, it as planCacheEmptying, jt as findStaleProjectDevices, lt as collectGradleVersions, o as machineNumber, r as cacheLabel, u as resolveBudget, ur as collectMemoryReport, ut as deleteGradleVersion, vt as DEVICE_LIST_TIMEOUT_MS, wr as pruneCache, wt as deleteProjectDevices, xt as collectParkedSims, yr as stopIdleGradleDaemons } from "./budget-HyShrIpL.mjs";
6
+ import { Bt as unpushedCommitsAsync, Ct as hasUncommittedWorkAsync, D as maintenanceKeepSetting, Dt as listWorktreesAsync, Et as listWorktrees, Gt as removeTemporaryEntryAsync, It as resolveFullRefAsync, J as resolveProjectSettings, Lt as resolveSourceCheckoutAsync, Y as resolveProjectSettingsAsync, _t as dirtyPathsAsync, h as deviceIdleShutdownMinutesSetting, xt as hasPopulatedSubmodulesAsync, zt as sourceCheckoutOf } from "./settings-CosW5X-S.mjs";
7
+ import { i as findProjectRoot$1 } from "./project-BUu6Is4k.mjs";
8
+ import { F as listAvdsAsync, G as ownedAvdSerialResolverAsync, P as listAvds, V as ownedAvdDirectory, yt as readParked } from "./android-DTAcRwBC.mjs";
9
+ import { a as unregister, n as readManifest } from "./cache-manifest-BEZ9Bpl1.mjs";
10
+ import { A as collectOwnedDeviceActivityAsync, Cr as stopIdleGradleDaemons, Dr as discoverCaches, Dt as deleteParkedSims, Et as deleteParkedAvds, Ft as findStaleProjectDevices, Or as pruneCache, Ot as deleteProjectDevices, P as workspaceBuildInProgress, St as DEVICE_LIST_TIMEOUT_MS, Tt as collectParkedSims, ct as planCacheEmptying, d as trimmableCaches, f as stopOwnedMetro, i as enforceBudget, jt as deviceSweepIsScoped, k as collectOwnedDeviceActivity, mr as collectMemoryReport, mt as deleteGradleVersion, nt as emptyCaches, o as machineNumber, pt as collectGradleVersions, r as cacheLabel, u as resolveBudget, wr as phase, wt as collectParkedAvds, yr as memorySweepIsScoped, yt as waitForGradleExit } from "./budget-k2mZGvvk.mjs";
12
11
  import { t as canonicalPath } from "./paths-BsJMoPP2.mjs";
13
- import { B as GC_OUTPUT, H as takeGcResults, a as collectWorkspaceOutputs, c as listWorkspaceDirs, d as workspaceDirRemoved, h as workspaceInUseAsync, i as collectOrphanedWorkspaces, m as workspaceInUse, o as deleteOrphanedWorkspaces, p as withIdleWorkspace, r as clearWorkspaceOutputs, s as isInsideWorkspaces } from "./workspaces-C9w4aeXF.mjs";
14
- import { N as listBuildLocks, b as leaseIsExpired, g as workspaceActivity, x as listLeaseFiles } from "./activity-BpjwrQXU.mjs";
15
- import { d as listAllIosSims, f as listAllIosSimsAsync } from "./ios-BQzvJlzw.mjs";
12
+ import { B as GC_OUTPUT, H as takeGcResults, a as collectWorkspaceOutputs, c as listWorkspaceDirs, d as workspaceDirRemoved, h as workspaceInUseAsync, i as collectOrphanedWorkspaces, m as workspaceInUse, o as deleteOrphanedWorkspaces, p as withIdleWorkspace, r as clearWorkspaceOutputs, s as isInsideWorkspaces } from "./workspaces-g2lhdBXF.mjs";
13
+ import { N as listBuildLocks, _ as workspaceDeviceLastUseAt, b as leaseIsExpired, g as workspaceActivity, x as listLeaseFiles } from "./activity-Lnb_EoRY.mjs";
14
+ import { d as listAllIosSims, f as listAllIosSimsAsync } from "./ios-WxpDJ5T1.mjs";
16
15
  import { s as metroStoreRoot } from "./errors-DHm_U5gv.mjs";
17
16
  import { t as resolveMaintenanceSettings } from "./settings-Djl-mpjX.mjs";
18
- import { A as measurePressureAsync, D as measureDisk, E as cacheBlocked, I as lowestFree, L as protectWindowMs, N as diskPressureLevel, O as measureDiskAsync, P as levelFloors, a as matchWorktreeEntry, c as reclaimKeys, i as excludeWatchmanCookies, k as measurePressure, m as removeWorktreeTarget, o as nestedWorktrees, r as excludePodChurn, s as porcelainPath } from "./worktree-CclFIe1Z.mjs";
19
- import { c as FETCH_FRESH_MS, d as localDefaultBranchAsync, l as fetchDefaultBranchAsync, o as recordPullRequestLookup, p as mergeStateAsync, u as lastFetchedAtAsync } from "./warm-progress-BV3ZPmcY.mjs";
17
+ import { i as writeIdleShutdownEvent, n as dueIdleDevices, r as shutDownIdleDevices } from "./idle-shutdown-FfxL1KdG.mjs";
18
+ import { A as measurePressureAsync, D as measureDisk, E as cacheBlocked, I as lowestFree, L as protectWindowMs, N as diskPressureLevel, O as measureDiskAsync, P as levelFloors, a as matchWorktreeEntry, c as reclaimKeys, i as excludeWatchmanCookies, k as measurePressure, m as removeWorktreeTarget, o as nestedWorktrees, r as excludePodChurn, s as porcelainPath } from "./worktree-BKuklFh_.mjs";
19
+ import { c as FETCH_FRESH_MS, d as localDefaultBranchAsync, l as fetchDefaultBranchAsync, o as recordPullRequestLookup, p as mergeStateAsync, u as lastFetchedAtAsync } from "./warm-progress-DvhTX_eu.mjs";
20
20
  import { n as describePullRequest, r as endedPullRequest, s as pullRequestLookups } from "./pull-request-CbNlkFok.mjs";
21
21
  import { readClaimSet } from "@stim-cli/core/ownership-claim";
22
22
  import { existsSync, lstatSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
@@ -28,6 +28,29 @@ import { isAbsolute as isAbsolute$1, join as join$1 } from "path";
28
28
  import chalk from "chalk";
29
29
  import { existsSync as existsSync$1, readdirSync as readdirSync$1, statSync as statSync$1 } from "fs";
30
30
  import { lstat, readdir, realpath, rename, stat } from "node:fs/promises";
31
+ //#region src/commands/gc/limited.ts
32
+ const isCleanupFailure = (error) => error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error;
33
+ async function eachLimited(items, limit, run) {
34
+ const queue = items[Symbol.iterator]();
35
+ let failed = false;
36
+ const worker = async () => {
37
+ for (const item of queue) {
38
+ if (failed) return;
39
+ try {
40
+ await run(item);
41
+ } catch (error) {
42
+ failed = true;
43
+ throw error;
44
+ }
45
+ }
46
+ };
47
+ const errors = (await Promise.allSettled(Array.from({ length: Math.min(limit, items.length) }, worker))).flatMap((result) => result.status === "rejected" ? [result.reason] : []);
48
+ if (errors.length) throw errors.find(isCleanupFailure) ?? errors[0];
49
+ }
50
+ function readConcurrency(operation) {
51
+ return operationState(operation).declaring.size ? 1 : 6;
52
+ }
53
+ //#endregion
31
54
  //#region src/commands/gc/worktrees.ts
32
55
  const DEFAULT_WORKTREE_IDLE_DAYS = 7;
33
56
  const DIRTY_PATHS_SHOWN = 3;
@@ -448,7 +471,7 @@ async function checkMergeStates(pending, idle, grace, noOwnCommitsIdleMs, refres
448
471
  operation?.signal.throwIfAborted();
449
472
  const target = refresh ? await fetchDefaultBranchAsync(repo, grace.now, execution) : await localDefaultBranchAsync(repo, execution);
450
473
  const fetch = refresh ? null : await staleFetch(repo, grace.now, freshMs, execution);
451
- for (const { candidate, facts } of entries) {
474
+ await eachLimited(entries, readConcurrency(operation), async ({ candidate, facts }) => {
452
475
  operation?.signal.throwIfAborted();
453
476
  const merge = "error" in target ? {
454
477
  merged: false,
@@ -466,7 +489,7 @@ async function checkMergeStates(pending, idle, grace, noOwnCommitsIdleMs, refres
466
489
  skipped: verdict ? note ? `${verdict.text}; ${note}` : verdict.text : null,
467
490
  eligibleAt: verdict?.eligibleAt ?? null
468
491
  });
469
- }
492
+ });
470
493
  }
471
494
  }
472
495
  /**
@@ -496,9 +519,13 @@ async function collectWorktreeSweep({ idle, olderThan, now, graceMs, removesNoOw
496
519
  const outside = [];
497
520
  const candidates = await candidateRootsAsync(operation);
498
521
  if (candidates.length) phase("worktrees", `checking ${plural(candidates.length, "project")} for merged or idle worktrees`, operation);
499
- for (const root of candidates) {
522
+ const matched = [];
523
+ await eachLimited([...candidates.entries()], readConcurrency(operation), async ([index, root]) => {
500
524
  operation?.signal.throwIfAborted();
501
- const entry = matchWorktreeEntry(await listWorktreesAsync(root, read), root);
525
+ matched[index] = matchWorktreeEntry(await listWorktreesAsync(root, read), root);
526
+ });
527
+ for (const [index, root] of candidates.entries()) {
528
+ const entry = matched[index];
502
529
  if (!entry) {
503
530
  outside.push({
504
531
  path: root,
@@ -517,7 +544,7 @@ async function collectWorktreeSweep({ idle, olderThan, now, graceMs, removesNoOw
517
544
  groups.set(entry.path, [...groups.get(entry.path) ?? [], root]);
518
545
  }
519
546
  const inspected = [];
520
- for (const [path, roots] of groups) {
547
+ await eachLimited([...[...groups].entries()], readConcurrency(operation), async ([index, [path, roots]]) => {
521
548
  operation?.signal.throwIfAborted();
522
549
  const { entries, ...source } = await resolveSourceCheckoutAsync(path, read);
523
550
  const entry = matchWorktreeEntry(entries, path);
@@ -541,7 +568,7 @@ async function collectWorktreeSweep({ idle, olderThan, now, graceMs, removesNoOw
541
568
  pullRequest: null,
542
569
  activity
543
570
  };
544
- inspected.push({
571
+ inspected[index] = {
545
572
  candidate: {
546
573
  path,
547
574
  keys,
@@ -557,8 +584,8 @@ async function collectWorktreeSweep({ idle, olderThan, now, graceMs, removesNoOw
557
584
  facts,
558
585
  repo: "refusal" in source ? null : source.path,
559
586
  branch: head && entry?.branch ? entry.branch : null
560
- });
561
- }
587
+ };
588
+ });
562
589
  const linked = inspected.filter(({ facts }) => facts.source === "linked");
563
590
  for (const { candidate, facts } of linked) for (const key of candidate.keys) facts.inUse.push(...await workspaceInUseAsync(key, { managedLocks: true }, operation?.signal, operation));
564
591
  const devices = await reportDeviceReads(linked.flatMap(({ candidate }) => candidate.keys), operation);
@@ -1213,6 +1240,44 @@ function finishedWorkspaces(sweep, now) {
1213
1240
  }));
1214
1241
  });
1215
1242
  }
1243
+ /** Each workspace's effective devices.idleShutdownMinutes, or 0 when it cannot be resolved. */
1244
+ function idleShutdownMinutes(root) {
1245
+ try {
1246
+ return deviceIdleShutdownMinutesSetting(resolveProjectSettings(root).settings);
1247
+ } catch {
1248
+ return 0;
1249
+ }
1250
+ }
1251
+ /**
1252
+ * Plans shutting down each booted owned simulator and emulator idle for its workspace's devices.idleShutdownMinutes,
1253
+ * whether or not a supervisor runs there. The devices are shut down, never deleted.
1254
+ */
1255
+ function planIdleShutdown({ protectedRoot, now, env = process.env }) {
1256
+ const plan = {
1257
+ actions: [],
1258
+ blocked: [],
1259
+ skips: []
1260
+ };
1261
+ if (deviceSweepIsScoped(env)) return plan;
1262
+ const minutes = new Map(Object.entries(loadConfig$1()?.projects ?? {}).flatMap(([root, project]) => {
1263
+ const value = !projectDeviceSlots(project).some(({ platforms }) => platforms.ios?.owned === true || platforms.android?.owned === true) || canonicalPath(root) === protectedRoot ? 0 : idleShutdownMinutes(root);
1264
+ return value > 0 ? [[root, value]] : [];
1265
+ }));
1266
+ if (minutes.size === 0) return plan;
1267
+ for (const { device, idleForMs } of dueIdleDevices(void 0, Math.min(...minutes.values()) * 6e4, now)) {
1268
+ const own = minutes.get(device.project);
1269
+ if (own === void 0 || idleForMs < own * 6e4 || now - workspaceDeviceLastUseAt(device.project) < own * 6e4) continue;
1270
+ const root = canonicalPath(device.project);
1271
+ plan.actions.push({
1272
+ kind: "would-shutdown-device",
1273
+ target: device.id,
1274
+ workspace: root,
1275
+ bytes: 0,
1276
+ reason: `${device.kind === "ios" ? "simulator" : "emulator"} ${device.name} idle ${formatLongDuration(idleForMs)}, over devices.idleShutdownMinutes ${own}`
1277
+ });
1278
+ }
1279
+ return plan;
1280
+ }
1216
1281
  //#endregion
1217
1282
  //#region src/maintenance/sweep.ts
1218
1283
  async function planSweep({ settings, sizes, protectedRoot, pinned, now, devices = true, operation }) {
@@ -1220,13 +1285,13 @@ async function planSweep({ settings, sizes, protectedRoot, pinned, now, devices
1220
1285
  const skips = [];
1221
1286
  const blocked = [];
1222
1287
  const days = settings.olderThanDays;
1223
- const outputs = await collectWorkspaceOutputs({
1288
+ const outputs = days > 0 ? await collectWorkspaceOutputs({
1224
1289
  olderThan: days,
1225
1290
  now,
1226
1291
  measure: false,
1227
1292
  signal: operation?.signal,
1228
1293
  operation
1229
- });
1294
+ }) : { workspaces: [] };
1230
1295
  for (const entry of outputs.workspaces) {
1231
1296
  const root = entry.projectRoot === null ? null : canonicalPath(entry.projectRoot);
1232
1297
  if (root === null || !entry.willClear || root === protectedRoot) continue;
@@ -1249,7 +1314,7 @@ async function planSweep({ settings, sizes, protectedRoot, pinned, now, devices
1249
1314
  check: "sweep"
1250
1315
  });
1251
1316
  }
1252
- for (const cache of trimmableCaches(operation?.env, operation?.cwd).filter((candidate) => !isInsideWorkspaces(candidate.dir))) actions.push({
1317
+ for (const cache of days > 0 ? trimmableCaches(operation?.env, operation?.cwd).filter((candidate) => !isInsideWorkspaces(candidate.dir)) : []) actions.push({
1253
1318
  kind: "would-trim-cache",
1254
1319
  target: cacheLabel(cache),
1255
1320
  dir: cache.dir,
@@ -1298,6 +1363,19 @@ async function planSweep({ settings, sizes, protectedRoot, pinned, now, devices
1298
1363
  actions.push(...reaped.actions);
1299
1364
  skips.push(...reaped.skips);
1300
1365
  }
1366
+ if (devices && days > 0 && !deviceSweepIsScoped(operation?.env ?? process.env)) for (const kind of ["ios", "android"]) for (const record of readParked(kind)) {
1367
+ const parkedDays = Math.floor((now - Date.parse(record.parkedAt)) / 864e5);
1368
+ if (!(parkedDays >= days)) continue;
1369
+ const label = `parked ${kind === "ios" ? "simulator" : "emulator"} ${record.name}`;
1370
+ actions.push({
1371
+ kind: "would-delete-parked-device",
1372
+ target: kind === "ios" ? record.udid : record.name,
1373
+ bytes: sizes.find((size) => size.category === "owned-devices" && !size.workspace && size.name === label)?.bytes ?? 0,
1374
+ olderThanDays: days,
1375
+ reason: `${label} unused for ${parkedDays} days, older than ${days} days (age sweep)`,
1376
+ check: "sweep"
1377
+ });
1378
+ }
1301
1379
  const mounted = listMountedVolumes();
1302
1380
  for (const cache of readManifest().caches) {
1303
1381
  if (!isAbsolute(cache.dir) || existsSync(cache.dir) || !isOnMountedVolume(cache.dir, mounted)) continue;
@@ -1316,10 +1394,10 @@ async function planSweep({ settings, sizes, protectedRoot, pinned, now, devices
1316
1394
  skips
1317
1395
  };
1318
1396
  }
1319
- async function planWorktrees({ protectedRoot, pinned, now, level, graceMs, sizes, protectRecentMs = 0, refresh, operation }) {
1397
+ async function planWorktrees({ protectedRoot, pinned, now, level, graceMs, sizes, protectRecentMs = 0, refresh, idleDays = null, operation }) {
1320
1398
  const sweep = await collectWorktreeSweep({
1321
- idle: false,
1322
- olderThan: null,
1399
+ idle: idleDays !== null,
1400
+ olderThan: idleDays,
1323
1401
  now,
1324
1402
  removesNoOwnCommits: level === 3,
1325
1403
  operation,
@@ -1346,7 +1424,7 @@ async function planWorktrees({ protectedRoot, pinned, now, level, graceMs, sizes
1346
1424
  target: worktree.path,
1347
1425
  bytes: 0,
1348
1426
  reason: worktreeRemovalReason(worktree, sweep),
1349
- check: "worktree",
1427
+ check: level === void 0 && idleDays !== null && !worktree.merge?.merged && !endedPullRequest(worktree.pullRequest) ? "sweep" : "worktree",
1350
1428
  ...level ? { level } : {}
1351
1429
  });
1352
1430
  }
@@ -2256,7 +2334,7 @@ async function planPressureLevels(level, context) {
2256
2334
  function triggeringRoot(operation) {
2257
2335
  return canonicalPath(findProjectRoot$1(operation?.cwd ?? process.cwd()) ?? join(configDir(), "maintenance", "no-project"));
2258
2336
  }
2259
- async function plannedMaintenance(pressure, recordedSizes, settings, { devices = true, sweep = false, worktrees = false, refresh = true, operation } = {}) {
2337
+ async function plannedMaintenance(pressure, recordedSizes, settings, { devices = true, sweep = false, worktrees = false, idle = false, refresh = true, operation } = {}) {
2260
2338
  const env = operation?.env ?? process.env;
2261
2339
  const resolved = resolveBudget({ env });
2262
2340
  if (resolved.error) throw new Error(resolved.error);
@@ -2353,11 +2431,17 @@ async function plannedMaintenance(pressure, recordedSizes, settings, { devices =
2353
2431
  sizes: currentSizes,
2354
2432
  protectRecentMs: settings.protectRecentHours * 36e5,
2355
2433
  refresh,
2434
+ idleDays: sweep && settings.removeIdleWorktrees && settings.olderThanDays > 0 ? settings.olderThanDays : null,
2356
2435
  operation
2357
2436
  });
2358
2437
  merge(planned);
2359
2438
  result.worktreeSweep = planned.sweep;
2360
2439
  }
2440
+ if (idle && devices) merge(planIdleShutdown({
2441
+ protectedRoot: root,
2442
+ now: Date.now(),
2443
+ env
2444
+ }));
2361
2445
  if (pressure) {
2362
2446
  const pressured = await planPressureLevels(diskPressureLevel(lowestFree(pressure.disk), budget, settings), {
2363
2447
  settings,
@@ -2405,6 +2489,7 @@ async function previewMaintenance({ devices = true, refresh = true, operation }
2405
2489
  ...await plannedMaintenance(pressure, state?.sizes ?? [], settings, {
2406
2490
  devices,
2407
2491
  sweep: true,
2492
+ idle: true,
2408
2493
  refresh,
2409
2494
  operation
2410
2495
  }),
@@ -2583,11 +2668,47 @@ async function removeOrphan(action) {
2583
2668
  const { results } = await quietly(() => deleteOrphanedWorkspaces([orphan]));
2584
2669
  return outcomeOf(results, orphan.bytes ?? 0);
2585
2670
  }
2671
+ async function shutDownIdleDevice(action) {
2672
+ if (deviceSweepIsScoped()) return kept("STIM_HOME scopes this config, and devices are machine-wide");
2673
+ const root = action.workspace ?? action.target;
2674
+ const minutes = idleShutdownMinutes(root);
2675
+ if (minutes === 0) return kept("devices.idleShutdownMinutes is 0 for this workspace");
2676
+ const idleMs = minutes * 6e4;
2677
+ const due = dueIdleDevices(root, idleMs).find(({ device }) => device.id === action.target);
2678
+ if (!due) return kept(`it is no longer idle for ${minutes} minutes`);
2679
+ const failures = [];
2680
+ const skips = [];
2681
+ const log = (event) => {
2682
+ writeIdleShutdownEvent(root, event);
2683
+ if (event.event === "device_idle_shutdown_failed") (event.skipped ? skips : failures).push(event.msg);
2684
+ };
2685
+ const run = await withIdleWorkspace(root, () => shutDownIdleDevices(root, idleMs, log, Date.now(), { only: due.device }), {
2686
+ purpose: "automatic maintenance idle shutdown",
2687
+ supervisor: false,
2688
+ managedLocks: false
2689
+ });
2690
+ if (!run.ran) return kept(`in use: ${run.reasons.join("; ")}`);
2691
+ if (run.value) return {
2692
+ status: "done",
2693
+ bytes: 0,
2694
+ detail: action.target
2695
+ };
2696
+ if (failures.length) return {
2697
+ status: "failed",
2698
+ bytes: 0,
2699
+ detail: failures.join("; ")
2700
+ };
2701
+ return kept(skips.join("; ") || `it is no longer idle for ${minutes} minutes`);
2702
+ }
2586
2703
  async function deleteParkedDevice(action) {
2587
2704
  if (deviceSweepIsScoped()) return kept("STIM_HOME scopes this config, and devices are machine-wide");
2588
- const sims = (await collectParkedSims({})).filter((sim) => sim.udid === action.target);
2589
- const avds = sims.length ? [] : (await collectParkedAvds({})).filter((avd) => avd.name === action.target);
2590
- if (!sims.length && !avds.length) return kept("it is no longer parked");
2705
+ const age = {
2706
+ olderThanDays: action.olderThanDays ?? null,
2707
+ now: Date.now()
2708
+ };
2709
+ const sims = (await collectParkedSims({}, age)).filter((sim) => sim.udid === action.target);
2710
+ const avds = sims.length ? [] : (await collectParkedAvds({}, age)).filter((avd) => avd.name === action.target);
2711
+ if (!sims.length && !avds.length) return kept(action.olderThanDays === void 0 ? "it is no longer parked" : `it is no longer parked, or was parked within ${action.olderThanDays} days`);
2591
2712
  const before = lowestFree(measureDisk());
2592
2713
  const { results } = await quietly(async () => await deleteParkedSims(sims) + await deleteParkedAvds(avds));
2593
2714
  return outcomeOf(results, freedSince(before));
@@ -2799,6 +2920,7 @@ async function executeAction(action, context) {
2799
2920
  case "would-unregister-cache": return unregisterCache(action);
2800
2921
  case "would-delete-parked-device": return deleteParkedDevice(action);
2801
2922
  case "would-delete-devices": return deleteDevices(action, context);
2923
+ case "would-shutdown-device": return action.check === "disk" ? kept("automatic maintenance does not stop devices or dev servers for disk") : shutDownIdleDevice(action);
2802
2924
  case "would-stop-workspace": return action.level === 3 ? stopWorkspace(action, context) : kept("automatic maintenance stops dev servers only at disk pressure level 3");
2803
2925
  case "would-clear-build-dirs":
2804
2926
  case "would-delete-dependencies": return clearArtifacts(action, context);
@@ -2813,4 +2935,4 @@ function diskRecovered(budget) {
2813
2935
  return measureDisk().every((disk) => disk.freeMb >= floor);
2814
2936
  }
2815
2937
  //#endregion
2816
- export { collectWorktreeSweep as _, previewMaintenance as a, worktreeRemovalReason as b, deleteTempLeftovers as c, ARTIFACT_DIRS as d, appRoots as f, candidateRootsAsync as g, ownedDeviceUsage as h, plannedMaintenance as i, tempLeftoverLines as l, measureOwnedDevices as m, diskRecovered as n, triggeringRoot as o, finishedWorkspaces as p, executeAction as r, collectTempLeftovers as s, deleteIdleWorkspaceDevices as t, tempLeftoverSection as u, removeWorktrees as v, worktreePullRequestNote as y };
2938
+ export { readConcurrency as S, collectWorktreeSweep as _, previewMaintenance as a, worktreeRemovalReason as b, deleteTempLeftovers as c, ARTIFACT_DIRS as d, appRoots as f, candidateRootsAsync as g, ownedDeviceUsage as h, plannedMaintenance as i, tempLeftoverLines as l, measureOwnedDevices as m, diskRecovered as n, triggeringRoot as o, finishedWorkspaces as p, executeAction as r, collectTempLeftovers as s, deleteIdleWorkspaceDevices as t, tempLeftoverSection as u, removeWorktrees as v, eachLimited as x, worktreePullRequestNote as y };
@@ -1,10 +1,9 @@
1
1
  import { D as ownership_claim_exports, S as process_identity_exports, m as declareSpawnsOn, t as getExecutor, v as stopDeclaringSpawnsOn } from "./exec-VFRpu1iA.mjs";
2
- import { m as workspaceLogsDir$1, v as withDirLock$1, y as withDirLockAsync$1 } from "./paths-DQtTgsBf.mjs";
3
- import { U as parseDeviceSlotKey, V as deviceSlotKey, d as getConfigDir, q as validateDeviceSlot } from "./config-BZhXY15H.mjs";
4
- import { a as formatElapsed, i as formatDuration, m as shortHash } from "./command-output-BBvS1H6v.mjs";
2
+ import { M as withDirLock$1, N as withDirLockAsync$1, c as withWorkspaceStateLock, d as writeWorkspaceState, k as workspaceLogsDir$1, l as withWorkspaceStateLockAsync, n as clearWorkspaceStateKeys, r as readWorkspaceState$1 } from "./workspace-state-pUg3_RRA.mjs";
3
+ import { U as parseDeviceSlotKey, V as deviceSlotKey, d as getConfigDir, q as validateDeviceSlot } from "./config-BktkY_zC.mjs";
4
+ import { a as formatElapsed, i as formatDuration, m as shortHash } from "./command-output-BF5AR2dL.mjs";
5
5
  import { n as runOperationFileQuiet } from "./operation-exec-CUZifp6Z.mjs";
6
- import { c as withWorkspaceStateLock, d as writeWorkspaceState, l as withWorkspaceStateLockAsync, n as clearWorkspaceStateKeys, r as readWorkspaceState$1 } from "./workspace-state-CPSp3mav.mjs";
7
- import { y as resolveBuild } from "./build-cache-CKCzxzxA.mjs";
6
+ import { S as resolveBuild } from "./build-cache-DrXNCy3T.mjs";
8
7
  import { randomBytes } from "node:crypto";
9
8
  import { closeSync, fstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
10
9
  import { homedir } from "node:os";
@@ -1,8 +1,8 @@
1
1
  import { S as process_identity_exports } from "./exec-VFRpu1iA.mjs";
2
- import { P as formatBytes } from "./config-BZhXY15H.mjs";
3
- import { o as formatLongDuration } from "./command-output-BBvS1H6v.mjs";
4
- import { F as measureDu, I as writeUsageCache, P as canonical, c as listWorkspaceDirs } from "./workspaces-C9w4aeXF.mjs";
5
- import { c as parseAgentDeviceRecord, o as envDir, u as processMatches } from "./activity-BpjwrQXU.mjs";
2
+ import { P as formatBytes } from "./config-BktkY_zC.mjs";
3
+ import { o as formatLongDuration } from "./command-output-BF5AR2dL.mjs";
4
+ import { F as measureDu, I as writeUsageCache, P as canonical, c as listWorkspaceDirs } from "./workspaces-g2lhdBXF.mjs";
5
+ import { c as parseAgentDeviceRecord, o as envDir, u as processMatches } from "./activity-Lnb_EoRY.mjs";
6
6
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
7
7
  import { homedir } from "node:os";
8
8
  import { isAbsolute, join, relative, sep } from "node:path";
@@ -1,5 +1,5 @@
1
1
  import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { u as androidToolCwd } from "./android-Cjcj8MCw.mjs";
2
+ import { u as androidToolCwd } from "./android-DTAcRwBC.mjs";
3
3
  //#region src/collector/android.ts
4
4
  const LEVEL_BY_LETTER = {
5
5
  V: "debug",
@@ -1,6 +1,6 @@
1
- import { i as formatDuration, l as phaseLine, m as shortHash } from "./command-output-BBvS1H6v.mjs";
2
- import { E as resolveVariant, T as resolveSystemImage, _ as findAapt, b as noDeviceDiagnostic, d as androidVariantSetting, f as apkDevClientFacts, g as dumpApkManifest, h as displayPath, i as NO_FINGERPRINT, p as apkPackage, r as NO_DEVICE, s as androidDevClientScheme, u as androidSystemImageSetting, x as parseXmltree, y as isReleaseVariant } from "./support-Cxj9CmII.mjs";
3
- import { r as lastBuildRecord, t as androidFacts } from "./result-CR2vk2cj.mjs";
4
- import { i as runAndroidOperation, n as registerAndroid, r as runAndroid, t as androidCommand } from "./android-BGwuK3Mc.mjs";
5
- import { a as killPreviousCollector, i as collectorLogFile, o as startCollector } from "./launch-D0lPvFFu.mjs";
1
+ import { i as formatDuration, l as phaseLine, m as shortHash } from "./command-output-BF5AR2dL.mjs";
2
+ import { E as resolveVariant, T as resolveSystemImage, _ as findAapt, b as noDeviceDiagnostic, d as androidVariantSetting, f as apkDevClientFacts, g as dumpApkManifest, h as displayPath, i as NO_FINGERPRINT, p as apkPackage, r as NO_DEVICE, s as androidDevClientScheme, u as androidSystemImageSetting, x as parseXmltree, y as isReleaseVariant } from "./support-BGSCBoib.mjs";
3
+ import { r as lastBuildRecord, t as androidFacts } from "./result-7F5hEwQJ.mjs";
4
+ import { i as runAndroidOperation, n as registerAndroid, r as runAndroid, t as androidCommand } from "./android-CiNQw3kq.mjs";
5
+ import { a as collectorLogFile, o as killPreviousCollector, s as startCollector } from "./launch-DOp8RjDz.mjs";
6
6
  export { NO_DEVICE, NO_FINGERPRINT, androidDevClientScheme, androidFacts, androidSystemImageSetting, androidVariantSetting, apkDevClientFacts, apkPackage, collectorLogFile, androidCommand as default, displayPath, dumpApkManifest, findAapt, formatDuration, isReleaseVariant, killPreviousCollector, lastBuildRecord, noDeviceDiagnostic, parseXmltree, phaseLine, registerAndroid, resolveSystemImage, resolveVariant, runAndroid, runAndroidOperation, shortHash, startCollector };
@@ -1,41 +1,41 @@
1
1
  import { D as ownership_claim_exports, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { m as workspaceLogsDir$1, t as emulatorLogFile } from "./paths-DQtTgsBf.mjs";
3
- import { B as deviceSlotFileKey, E as upsertProject, H as deviceSlotPlatforms, O as withConfigLockAsync$1, W as parseDeviceSlotOption, p as getProject, q as validateDeviceSlot, u as getConcurrencyLimits } from "./config-BZhXY15H.mjs";
4
- import { _ as stepTimer, f as refuseNoProject, g as stepClock, i as formatDuration, l as phaseLine } from "./command-output-BBvS1H6v.mjs";
5
- import { a as recordWorkspaceUseAsync, f as writeWorkspaceStateAsync, r as readWorkspaceState$1 } from "./workspace-state-CPSp3mav.mjs";
6
- import { K as resolveCacheProviderConfig, M as metroPortSetting, P as metroWarmupUrlSetting, R as projectSettingsContextAsync, U as remoteEasFallbackSetting, X as resolveSettings, Y as resolveProjectSettingsAsync, a as SETTING_SHAPE_REMEDY, g as deviceReclaimIdleMinutesSetting, it as tunnelModeSetting, lt as detectProviders, z as publicUrlSetting } from "./settings-B5tCoq9N.mjs";
7
- import { L as workspaceDevServerMode, f as projectRegistry, i as findProjectRoot$1, l as projectShortcut, t as NO_PROJECT_REFUSAL, z as writeWorkspaceLaunchAsync } from "./project-BiC68mIp.mjs";
8
- import { A as listAdbDevices, I as listInstalledSystemImages, St as configuredAndroidEmulatorApp, Y as physicalDeviceModel, Z as probeEmulatorSerial, a as androidDeviceAbi, ct as waitForBoot, nt as resolveOwnedAvdSerialAsync, rt as resolvePhysicalDevice } from "./android-Cjcj8MCw.mjs";
9
- import { c as pidExists, d as resolveProjectMetro } from "./metro-1pJgCX4U.mjs";
2
+ import { a as recordWorkspaceUseAsync, f as writeWorkspaceStateAsync, g as emulatorLogFile, k as workspaceLogsDir$1, r as readWorkspaceState$1 } from "./workspace-state-pUg3_RRA.mjs";
3
+ import { B as deviceSlotFileKey, E as upsertProject, H as deviceSlotPlatforms, O as withConfigLockAsync$1, W as parseDeviceSlotOption, p as getProject, q as validateDeviceSlot, u as getConcurrencyLimits } from "./config-BktkY_zC.mjs";
4
+ import { _ as stepTimer, f as refuseNoProject, g as stepClock, i as formatDuration, l as phaseLine } from "./command-output-BF5AR2dL.mjs";
5
+ import { K as resolveCacheProviderConfig, M as metroPortSetting, P as metroWarmupUrlSetting, R as projectSettingsContextAsync, U as remoteEasFallbackSetting, X as resolveSettings, Y as resolveProjectSettingsAsync, a as SETTING_SHAPE_REMEDY, g as deviceReclaimIdleMinutesSetting, it as tunnelModeSetting, lt as detectProviders, z as publicUrlSetting } from "./settings-CosW5X-S.mjs";
6
+ import { f as projectRegistry, i as findProjectRoot$1, l as projectShortcut, t as NO_PROJECT_REFUSAL, z as writeWorkspaceLaunchAsync } from "./project-BUu6Is4k.mjs";
7
+ import { A as listAdbDevices, Dt as configuredAndroidEmulatorApp, I as listInstalledSystemImages, Y as physicalDeviceModel, Z as probeEmulatorSerial, a as androidDeviceAbi, ct as waitForBoot, nt as resolveOwnedAvdSerialAsync, rt as resolvePhysicalDevice } from "./android-DTAcRwBC.mjs";
8
+ import { c as pidExists, d as resolveProjectMetro } from "./metro-CjC10t6E.mjs";
10
9
  import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
11
- import { Dn as launchAndroidReleaseApp, En as launchAndroidApp, G as createRunRecorder, Gt as remoteAndroidDeps, H as startBuildProgress, Ht as ensureMetroReachable, J as recordCapacityRefusal, K as readRunEstimates, Ln as exitAfterFlush, M as NO_BUILD_PROGRESS, Qn as uploadRemote, Sn as installAndroidApp, U as tapBuildLog, Un as checkEasAuth, Ut as ensureRemoteBootOwned, V as runFailureRecord, W as thrownRunFailureRecord, X as recordRunStats, Xn as resolveEasCliBin, Z as statsProjectKey$1, Zn as resolveRemote, dn as DEFAULT_METRO_PORT, on as verifyAndroidReleaseLaunch, or as ownedSessionName, qt as resolveRemoteContext, sn as verifyLaunch, t as budgetGate, un as ADB_INSTALL_TIMEOUT_MS, zn as runProcessOperation, zt as binOnPath } from "./budget-HyShrIpL.mjs";
12
- import { d as runCancellationSignal, f as withNativeBuildRun, r as cancelledFailure, u as runCancellation } from "./native-run-D5OJsGwA.mjs";
13
- import { L as acquireBuildSlot, z as releaseBuildSlot } from "./workspaces-C9w4aeXF.mjs";
14
- import { F as waitForBuild, M as acquireBuildLock, P as releaseBuildLock } from "./activity-BpjwrQXU.mjs";
15
- import { x as storedAppId } from "./build-cache-CKCzxzxA.mjs";
16
- import { t as CCACHE_NOT_RUN } from "./ccache-h1FKhZeg.mjs";
17
- import { S as setRemoteLogSink } from "./client-BQsmyp_-.mjs";
18
- import { a as parseBuildMachineOption, c as resolveBuildPlacement } from "./selection-D5cxEl3t.mjs";
19
- import { r as hostedMetroSettings } from "./metro-gateway-Bp9gJQAN.mjs";
20
- import { a as writeHostedAndroidAsync, i as writeDevicePlacementAsync, t as readHostedAndroid } from "./ios-state-CT9nV5SP.mjs";
21
- import { n as prepareHostedAndroid, t as placeHostedAndroid } from "./hosted-android-Bvb2-ZxD.mjs";
22
- import { n as verifyCollectorOwnership } from "./ownership-jxxz-19m.mjs";
23
- import { r as siblingPlatformSlots, t as launchSlotScope } from "./slot-launch-QeuJMlnJ.mjs";
24
- import { c as startDevServer } from "./start-YMpNwLhh.mjs";
25
- import { a as acquireRunLease, d as runLease, f as waitFlagConflict, o as leaseExpiryText, u as releaseLeaseOnAbort } from "./device-lease-run-ogEeJ62K.mjs";
26
- import { n as DeviceAdmissionRefusal, r as checkDeviceCapacity } from "./device-capacity-ZYaRALv5.mjs";
27
- import { a as resolveEasDevelopmentBuild, r as isEasBuildFailure } from "./eas-build-CyDKNTBP.mjs";
28
- import { n as ensureWorkspaceStorageSafely, r as isPhysicalDeviceRequest, t as ensureDevServer } from "./native-runtime-B9w_Qyz3.mjs";
29
- import { n as devicePlacementRecord } from "./placement-log-DjOXJRIH.mjs";
30
- import { S as pooledAndroidDevice, a as PLATFORM, b as noDeviceDiagnostic, g as dumpApkManifest, h as displayPath, o as androidBuildOptions, p as apkPackage, r as NO_DEVICE, s as androidDevClientScheme } from "./support-Cxj9CmII.mjs";
31
- import { t as acquireAndroidArtifact } from "./artifact-Co8zixVx.mjs";
32
- import { a as persistLastBuild, c as androidDeviceSelectorRefusal, i as logPostBuildFailure, n as finishAndroidUpload, o as persistThrownBuild, s as reportAndroidResult, u as resolveAndroidRunPlan } from "./result-CR2vk2cj.mjs";
33
- import { n as automaticDevicePlacement, r as devicePlacementLine, t as checkEasFallback } from "./eas-fallback-gaZi-dJL.mjs";
34
- import { a as AvdRecoveryError, i as AvdBootError, n as ensureBooted, o as warmMetro, r as ensureOwnedDevice, t as didSetUpDevice } from "./device-B9FqTBYW.mjs";
35
- import { t as selectFromPool } from "./device-pool-BIg8MU8l.mjs";
36
- import { r as finishAndroidRun } from "./launch-D0lPvFFu.mjs";
10
+ import { An as launchAndroidApp, En as installAndroidApp, G as runFailureRecord, I as NO_BUILD_PROGRESS, J as thrownRunFailureRecord, K as startBuildProgress, Kt as ensureMetroReachable, Q as recordCapacityRefusal, Un as runProcessOperation, Ut as binOnPath, Vn as exitAfterFlush, X as readRunEstimates, Y as createRunRecorder, Yt as remoteAndroidDeps, Zt as resolveRemoteContext, dn as verifyLaunch, er as resolveEasCliBin, et as recordRunStats, hn as DEFAULT_METRO_PORT, jn as launchAndroidReleaseApp, mn as ADB_INSTALL_TIMEOUT_MS, nr as uploadRemote, q as tapBuildLog, qn as checkEasAuth, qt as ensureRemoteBootOwned, t as budgetGate, tr as resolveRemote, tt as statsProjectKey$1, un as verifyAndroidReleaseLaunch, ur as ownedSessionName } from "./budget-k2mZGvvk.mjs";
11
+ import { d as runCancellationSignal, f as withNativeBuildRun, r as cancelledFailure, u as runCancellation } from "./native-run-BfIDFKLH.mjs";
12
+ import { L as acquireBuildSlot, z as releaseBuildSlot } from "./workspaces-g2lhdBXF.mjs";
13
+ import { F as waitForBuild, M as acquireBuildLock, P as releaseBuildLock } from "./activity-Lnb_EoRY.mjs";
14
+ import { w as storedAppId } from "./build-cache-DrXNCy3T.mjs";
15
+ import { t as CCACHE_NOT_RUN } from "./ccache-Bx5TbxwG.mjs";
16
+ import { S as setRemoteLogSink } from "./client-D9CaRks-.mjs";
17
+ import { a as parseBuildMachineOption, l as resolveBuildPlacement } from "./selection-BNPBZ6T5.mjs";
18
+ import { r as hostedMetroSettings } from "./metro-gateway-B6_PgD0L.mjs";
19
+ import { a as writeHostedAndroidAsync, i as writeDevicePlacementAsync, t as readHostedAndroid } from "./ios-state-Cw7-WQf2.mjs";
20
+ import { n as prepareHostedAndroid, t as placeHostedAndroid } from "./hosted-android-Bk54ej6n.mjs";
21
+ import { n as verifyCollectorOwnership } from "./ownership-BjYvMNX_.mjs";
22
+ import { c as startDevServer } from "./start-_BdJ32cZ.mjs";
23
+ import { a as acquireRunLease, d as runLease, f as waitFlagConflict, o as leaseExpiryText, u as releaseLeaseOnAbort } from "./device-lease-run-BmvIl7bI.mjs";
24
+ import { n as DeviceAdmissionRefusal, r as checkDeviceCapacity } from "./device-capacity-DCSvUF0l.mjs";
25
+ import { a as resolveEasDevelopmentBuild, r as isEasBuildFailure } from "./eas-build-Dsj93iM9.mjs";
26
+ import { t as followHostedLaunchLogs } from "./hosted-logs-sync-B0pvmOk-.mjs";
27
+ import { f as settleFingerprintCheck } from "./prebuild-gmouvmJZ.mjs";
28
+ import { n as ensureWorkspaceStorageSafely, r as isPhysicalDeviceRequest, t as ensureDevServer } from "./native-runtime-Dq3RBcON.mjs";
29
+ import { n as devicePlacementRecord } from "./placement-log-DIFPQAXp.mjs";
30
+ import { S as pooledAndroidDevice, a as PLATFORM, b as noDeviceDiagnostic, g as dumpApkManifest, h as displayPath, o as androidBuildOptions, p as apkPackage, r as NO_DEVICE, s as androidDevClientScheme } from "./support-BGSCBoib.mjs";
31
+ import { t as acquireAndroidArtifact } from "./artifact-BxREhAaV.mjs";
32
+ import { a as persistLastBuild, c as androidDeviceSelectorRefusal, i as logPostBuildFailure, n as finishAndroidUpload, o as persistThrownBuild, s as reportAndroidResult, u as resolveAndroidRunPlan } from "./result-7F5hEwQJ.mjs";
33
+ import { n as automaticDevicePlacement, r as devicePlacementLine, t as checkEasFallback } from "./eas-fallback-FwkeqqGi.mjs";
34
+ import { i as verifyAndroidMetroRun, r as finishAndroidRun } from "./launch-DOp8RjDz.mjs";
35
+ import { a as AvdRecoveryError, i as AvdBootError, n as ensureBooted, o as warmMetro, r as ensureOwnedDevice, t as didSetUpDevice } from "./device-BK-zwyd_.mjs";
36
+ import { t as selectFromPool } from "./device-pool-Dluix4H3.mjs";
37
37
  import { t as unsupportedPlan } from "./project-plan-BPwbLwQu.mjs";
38
- import { a as refusePlan, i as printPlan, n as planFlagRefusal } from "./build-plan-zCuHGlA8.mjs";
38
+ import { a as refusePlan, i as printPlan, n as planFlagRefusal } from "./build-plan-DrMMdayj.mjs";
39
39
  import { basename, join } from "node:path";
40
40
  import { workspaceId } from "@stim-cli/core";
41
41
  import { hostedAndroidStatus, parseMachine } from "@stim-cli/core/state";
@@ -182,9 +182,10 @@ async function selectAndroidPlacement({ target: selected, automatic = automaticD
182
182
  }
183
183
  //#endregion
184
184
  //#region src/commands/android/hosted.ts
185
- async function finishHostedAndroidRun({ target, artifact, root, slot = "default", release, appMode = release ? "release" : "development", isExpo, metroPort, logsDir, selectors, place, writePlacement, verifyLaunch: verify, writeLaunch, readApkPackage, resolveDevClientScheme, now, started, startedAt, fail, phase, enterPhase, out, recordBuild, ...report }) {
185
+ async function finishHostedAndroidRun({ target, artifact, root, slot = "default", release, appMode = release ? "release" : "development", isExpo, metroPort, logsDir, selectors, place, writePlacement, verifyLaunch: verify, followLogs, writeLaunch, readApkPackage, resolveDevClientScheme, now, started, startedAt, fail, phase, enterPhase, enterActivity, out, recordBuild, ...report }) {
186
186
  const packageName = artifact.androidPackage ?? await readApkPackage(artifact.apkPath);
187
187
  if (!artifact.apkPath || !packageName) return fail("STIM_INSTALL_FAILED", "The built APK has no package identity.");
188
+ const devClientScheme = appMode === "development" && isExpo ? await resolveDevClientScheme(root, artifact.apkPath) ?? void 0 : void 0;
188
189
  const launchedAt = now();
189
190
  try {
190
191
  const run = await place(target, {
@@ -197,7 +198,7 @@ async function finishHostedAndroidRun({ target, artifact, root, slot = "default"
197
198
  ...appMode === "process" ? { mode: appMode } : {},
198
199
  metroPort,
199
200
  selectors,
200
- ...appMode === "development" && isExpo ? { devClientScheme: await resolveDevClientScheme(root, artifact.apkPath) ?? void 0 } : {},
201
+ ...appMode === "development" && isExpo ? { devClientScheme } : {},
201
202
  reserved: (placement) => writePlacement(root, slot, placement),
202
203
  note: out,
203
204
  enterPhase
@@ -212,19 +213,37 @@ async function finishHostedAndroidRun({ target, artifact, root, slot = "default"
212
213
  launchedAt: new Date(launchedAt).toISOString()
213
214
  }, slot);
214
215
  let launched = run.launched;
216
+ let launchWarning;
215
217
  if (appMode === "development") {
216
- const evidence = await verify({
217
- requireBundleResponse: true,
218
- platform: "android",
219
- logsDir: logsDir ?? void 0,
220
- since: launchedAt,
221
- metroPort,
222
- mode: workspaceDevServerMode(root, isExpo),
223
- slot: launchSlotScope(root, slot),
224
- platformShared: (await siblingPlatformSlots(root, "android", slot)).length > 0
225
- });
226
- if (evidence.fatal) return fail("STIM_LAUNCH_FAILED", "Metro could not deliver the hosted app bundle.", "Run stim logs --errors and fix the bundle error.");
227
- launched = evidence.verified ? true : evidence.requested ? "bundling" : "unverified";
218
+ const hostedLogs = followLogs(root, slot, "android", launchedAt);
219
+ let verification;
220
+ try {
221
+ verification = await verifyAndroidMetroRun({
222
+ root,
223
+ slot,
224
+ remoteDevice: false,
225
+ verifyLaunched: verify,
226
+ serial: run.placement.device?.serial ?? "",
227
+ androidPackage: packageName,
228
+ metroCheck: report.metroCheck,
229
+ logsDir: logsDir ?? "",
230
+ launchedAt,
231
+ metroPort,
232
+ isExpo,
233
+ physical: false,
234
+ device: {},
235
+ scheme: devClientScheme,
236
+ phase,
237
+ enterActivity,
238
+ hostedLogs,
239
+ hostedRunCommand: `stim android --remote ${run.placement.selected}${slot === "default" ? "" : ` --slot ${slot}`}`
240
+ });
241
+ } finally {
242
+ hostedLogs.stop();
243
+ }
244
+ if (verification.state === "fatal") return fail("STIM_LAUNCH_FAILED", "The app failed its launch readiness check.", `Read the launch error above or run \`stim logs --errors\`. The full timeline is in ${logsDir}.`, { lastBuildStatus: true });
245
+ launched = verification.state === true ? true : verification.state === "bundling" ? "bundling" : "unverified";
246
+ launchWarning = verification.warning;
228
247
  }
229
248
  if (launched === "unverified") out(`Launch on ${target.host.machine} is unverified; check the hosted app, then retry stim android --remote ${target.host.machine}.`);
230
249
  const host = hostedAndroidStatus(run.placement);
@@ -241,6 +260,7 @@ async function finishHostedAndroidRun({ target, artifact, root, slot = "default"
241
260
  });
242
261
  await finishAndroidUpload(artifact.uploadPending, artifact.remote, phase);
243
262
  await artifact.providerUpload;
263
+ await settleFingerprintCheck(artifact.fingerprintCheck, "android", (line) => phase("fingerprint", chalk.yellow(line)), (entry) => report.writer.write(entry));
244
264
  return {
245
265
  ok: true,
246
266
  facts: reportAndroidResult({
@@ -261,6 +281,7 @@ async function finishHostedAndroidRun({ target, artifact, root, slot = "default"
261
281
  remote: artifact.remote,
262
282
  providerName: artifact.providerName,
263
283
  launchState: launched,
284
+ launchWarning,
264
285
  launched: {},
265
286
  ccache: artifact.ccache,
266
287
  durationMs: now() - started
@@ -1145,6 +1166,7 @@ async function runAndroid(options = {}) {
1145
1166
  place: options.placeHostedAndroid ?? placeHostedAndroid,
1146
1167
  writePlacement: options.writeHostedAndroid ?? writeHostedAndroidAsync,
1147
1168
  verifyLaunch: verifyLaunched,
1169
+ followLogs: options.followHostedLaunchLogs ?? followHostedLaunchLogs,
1148
1170
  writeLaunch,
1149
1171
  readApkPackage,
1150
1172
  resolveDevClientScheme,
@@ -1155,6 +1177,7 @@ async function runAndroid(options = {}) {
1155
1177
  fail,
1156
1178
  phase,
1157
1179
  enterPhase: progress.step,
1180
+ enterActivity: progress.activity,
1158
1181
  out,
1159
1182
  json,
1160
1183
  useBuildCache,
@@ -1263,6 +1286,7 @@ async function runAndroid(options = {}) {
1263
1286
  waitedForBuild: artifact.waitedForBuild,
1264
1287
  ccache: ccacheActivity,
1265
1288
  uploadPending: artifact.uploadPending,
1289
+ fingerprintCheck: artifact.fingerprintCheck,
1266
1290
  providerUpload: artifact.providerUpload,
1267
1291
  providerName: artifact.providerName,
1268
1292
  remote: artifact.remote,