stim 1.20.2 → 1.22.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 (231) hide show
  1. package/README.md +141 -8
  2. package/dist/acquire-artifact-Co2k4f7O.mjs +171 -0
  3. package/dist/act-DsuqEkiM.mjs +2801 -0
  4. package/dist/activity-CMLmzp7o.mjs +1397 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-DUFaTMdd.mjs} +23 -67
  6. package/dist/{android-DCKZrNvV.mjs → android-ByRMUoiJ.mjs} +157 -93
  7. package/dist/{android-Mz_Inn3w.mjs → android-C7sVmyI9.mjs} +299 -116
  8. package/dist/{android-Dlzxshgp.mjs → android-DGkNqa_c.mjs} +5 -5
  9. package/dist/{android-HqP1_vB_.mjs → android-DR5lZ2Az.mjs} +2 -2
  10. package/dist/android-cas-compiler.mjs +2 -2
  11. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-ngferVq2.mjs} +7 -6
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/android-project-DVWyCbWU.d.mts +391 -0
  14. package/dist/api.d.mts +810 -64
  15. package/dist/api.mjs +782 -1
  16. package/dist/{artifact-HSwkIWEQ.mjs → artifact-8EY8SAPw.mjs} +240 -213
  17. package/dist/{artifact-D3czlUvT.mjs → artifact-DJPy518Y.mjs} +203 -164
  18. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  19. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-Bcv99PBM.mjs} +194 -64
  20. package/dist/budget-Cvwn54qV.mjs +9285 -0
  21. package/dist/{build-DYDbfkk5.mjs → build-CabC3G23.mjs} +153 -98
  22. package/dist/build-cache-Dv7RN200.mjs +602 -0
  23. package/dist/build-plan-DUC8Ka9y.mjs +248 -0
  24. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DSeQjt-Q.mjs} +2 -2
  25. package/dist/cache-manifest.mjs +1 -1
  26. package/dist/{ccache-zdKiYQ3E.mjs → ccache-Btwc36-I.mjs} +10 -9
  27. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-3fwICjzi.mjs} +18 -5
  28. package/dist/{chrome-BnzZMqsR.mjs → chrome-Bbw689-6.mjs} +7 -4
  29. package/dist/{cli-CLP3diBm.mjs → cli-CHZa9Lvk.mjs} +20 -20
  30. package/dist/cli.mjs +1 -1
  31. package/dist/client-OyRoEuSr.mjs +1577 -0
  32. package/dist/collector-run.d.mts +4 -40
  33. package/dist/collector-run.mjs +9 -8
  34. package/dist/{command-output-BTy8hZ0F.mjs → command-output-gwpm28fu.mjs} +1 -1
  35. package/dist/config-DlrsduwG.mjs +955 -0
  36. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-x9rN6bhs.mjs} +14 -4
  37. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-1I9KZT1Y.mjs} +20 -5
  38. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
  39. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-BSDR5h3F.mjs} +2 -2
  40. package/dist/{device-BECOiufl.mjs → device-B-L3Fbxy.mjs} +91 -34
  41. package/dist/device-DklWZLqb.mjs +1068 -0
  42. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-DK5_EwRS.mjs} +42 -13
  43. package/dist/device-host-worker.mjs +76 -79
  44. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DoB6KFCO.mjs} +77 -51
  45. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-xJPQ_QQG.mjs} +14 -26
  46. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-BMkdsefq.mjs} +5 -5
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-Bo7BXLux.mjs} +271 -320
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-D5_EzwfA.mjs} +186 -91
  49. package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
  50. package/dist/doctor-fingerprint.mjs +19 -0
  51. package/dist/doctor-thjWAV0z.mjs +2 -0
  52. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-N2wDotwQ.mjs} +40 -21
  53. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-CwknaQYj.mjs} +53 -20
  54. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-CSgAulr5.mjs} +41 -214
  55. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-DlY_serQ.mjs} +230 -11
  56. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-DBWO2rxE.mjs} +172 -82
  57. package/dist/exec-DEoAhcze.mjs +858 -0
  58. package/dist/exec-DnYc4HGH.d.mts +78 -0
  59. package/dist/{gc-qWOMdnER.mjs → gc-CXxN-4SE.mjs} +1091 -1029
  60. package/dist/gc-DnNDQyaP.mjs +3 -0
  61. package/dist/{guide-G9cAbVAc.mjs → guide-Br0LEfKy.mjs} +1165 -297
  62. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-B-9f-jkd.mjs} +10 -8
  63. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DZAPrcro.mjs} +34 -19
  64. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
  65. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-FIRx9X2f.mjs} +77 -43
  66. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-_awYSpfv.mjs} +35 -22
  67. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-BdzE668-.mjs} +49 -27
  68. package/dist/idle-C4cZ757K.d.mts +24 -0
  69. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DDg3SdvY.mjs} +11 -10
  70. package/dist/ios-CDvlmUs7.d.mts +24 -0
  71. package/dist/{ios-BwVCF7oA.mjs → ios-Ds1clbIt.mjs} +8 -8
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device--h_-8ENa.mjs} +51 -26
  73. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  74. package/dist/{ios-RkW4pnQf.mjs → ios-hcBpnEGk.mjs} +200 -93
  75. package/dist/{ios-Ce7bc7br.mjs → ios-pm4nL6By.mjs} +160 -108
  76. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-CZhKODF3.mjs} +13 -13
  77. package/dist/ios-signing-BtAffm0A.mjs +489 -0
  78. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  79. package/dist/{ios-nOLJGVdy.mjs → ios-xtlRHaeB.mjs} +1 -1
  80. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Bwhh4S7V.mjs} +30 -25
  81. package/dist/{launch-C3qJ6Agb.mjs → launch-BjxemNpK.mjs} +85 -543
  82. package/dist/{launch-F4sOqAhB.mjs → launch-CCzXlc8r.mjs} +91 -90
  83. package/dist/logs-BfwwadsZ.mjs +479 -0
  84. package/dist/logs-jTS_lHSo.mjs +248 -0
  85. package/dist/{macos-D7uDvO-z.mjs → macos-DVlSSyUg.mjs} +1 -1
  86. package/dist/macos-NfV2D7dO.mjs +694 -0
  87. package/dist/macos-run.mjs +1 -1
  88. package/dist/maintenance-run.mjs +123 -248
  89. package/dist/{metro-DnCEjCxs.mjs → metro-DiXtA3Ty.mjs} +107 -30
  90. package/dist/metro-gateway-CKZqKqx7.mjs +209 -0
  91. package/dist/{named-ports-4WopRPg-.mjs → named-ports-DkEzOfzO.mjs} +42 -90
  92. package/dist/native-android-CqgnOgsT.mjs +645 -0
  93. package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
  94. package/dist/native-gradle-inputs-Dnh84Zbd.mjs +211 -0
  95. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  96. package/dist/native-run-NwUuxbkg.mjs +276 -0
  97. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-B7KIafpM.mjs} +11 -9
  98. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  99. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-D_VOfFL7.mjs} +26 -18
  100. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-BYDOHWLN.mjs} +104 -60
  101. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  102. package/dist/offload-worker.d.mts +59 -41
  103. package/dist/offload-worker.mjs +478 -115
  104. package/dist/operation-exec-BW0em61G.mjs +171 -0
  105. package/dist/{ownership-DCtw_2IA.mjs → ownership-C5fo5Edb.mjs} +3 -3
  106. package/dist/{page-DRHy329N.mjs → page-DBL2PiUU.mjs} +12 -5
  107. package/dist/paths-BsJMoPP2.mjs +12 -0
  108. package/dist/paths-DQtTgsBf.mjs +42 -0
  109. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BnGgJRRZ.mjs} +5 -5
  110. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-DIsMtN-d.mjs} +15 -11
  111. package/dist/{ports-DdSUicVo.mjs → ports-Cy1RkmuQ.mjs} +3 -3
  112. package/dist/prebuild-D4JoEAEs.mjs +484 -0
  113. package/dist/{project-_phNIJfs.mjs → project-wM_XFTvE.mjs} +65 -37
  114. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-W1IuLXDt.mjs} +102 -20
  115. package/dist/pull-request-eODyIqZF.d.mts +124 -0
  116. package/dist/pull-requests.d.mts +2 -120
  117. package/dist/pull-requests.mjs +2 -2
  118. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-6OZ7MSM7.mjs} +121 -72
  119. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-Dvd8hC21.mjs} +292 -15
  120. package/dist/react-native-doctor-DsoSF1Y9.mjs +234 -0
  121. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-4u1Rn-GR.mjs} +71 -39
  122. package/dist/{recordings-D0d5aQt0.mjs → recordings-CQmfzAh7.mjs} +12 -9
  123. package/dist/registration-BcRgF6Ox.mjs +51 -0
  124. package/dist/{reload-C8JhxjSh.mjs → reload-BzkYabB-.mjs} +94 -47
  125. package/dist/reload-D7AVlb8N.mjs +2 -0
  126. package/dist/{remote-BiR6aYjy.mjs → remote-DjGDmlTZ.mjs} +26 -18
  127. package/dist/result-D2Ykz_iD.mjs +435 -0
  128. package/dist/{run-BtPgpKks.mjs → run-DidHghD1.mjs} +5 -5
  129. package/dist/selection-DSMbWEX2.mjs +620 -0
  130. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CafzuyFB.mjs} +3 -4
  131. package/dist/{server-command-CTtCkmcQ.mjs → server-command-C6QjeupS.mjs} +14 -7
  132. package/dist/{server-expo-DsguMGUF.mjs → server-expo-CrjB29pq.mjs} +54 -11
  133. package/dist/server-expo-D58c9L0M.mjs +2 -0
  134. package/dist/{settings-B717odTD.mjs → settings-C7O8A6ZI.mjs} +309 -119
  135. package/dist/settings-DpR-1Wnn.mjs +114 -0
  136. package/dist/settings-write-CzD60rOD.mjs +360 -0
  137. package/dist/settings.schema.json +176 -16
  138. package/dist/{simslim-CCr3rE-A.mjs → simslim-BNckWpXi.mjs} +14 -12
  139. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-CbfmNgM6.mjs} +15 -20
  140. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  141. package/dist/stage-Bps5oius.mjs +200 -0
  142. package/dist/{start-TXeMmmO2.mjs → start-Br-oxqMD.mjs} +1 -1
  143. package/dist/start-EojN4WFz.mjs +1364 -0
  144. package/dist/{state-D1Icyjlu.mjs → state--smjFSTL.mjs} +55 -13
  145. package/dist/{state-CG_OFoaA.mjs → state-08I3hw3_.mjs} +3 -2
  146. package/dist/{stats-BoY5sEPU.mjs → stats-D3GerlFW.mjs} +7 -13
  147. package/dist/stats-report-BzaPrRm6.mjs +16 -0
  148. package/dist/{status-BTA7kKiQ.mjs → status-BRROykC8.mjs} +7 -5
  149. package/dist/status-EvrK72L2.mjs +2 -0
  150. package/dist/{status-WgFbkRzj.mjs → status-WBDajew2.mjs} +554 -452
  151. package/dist/{status-watch-C23ILtf9.mjs → status-watch-Bg_u-pwR.mjs} +222 -25
  152. package/dist/status-worker.d.mts +1 -0
  153. package/dist/status-worker.mjs +19 -0
  154. package/dist/stim-desktop-D5OGpYZM.mjs +112 -0
  155. package/dist/{stop-DR6VoDIk.mjs → stop-DTZ9uTw3.mjs} +2 -2
  156. package/dist/{stop-DPEhunlw.mjs → stop-Dky10AEJ.mjs} +33 -23
  157. package/dist/{stop-BNmBMi1F.mjs → stop-Mv6W9FAk.mjs} +137 -98
  158. package/dist/supervisor-run.d.mts +8 -17
  159. package/dist/supervisor-run.mjs +56 -28
  160. package/dist/{support-CwjbFs9H.mjs → support-CNioewsd.mjs} +14 -14
  161. package/dist/{support-DMTqj3Hm.mjs → support-yUiOjnVY.mjs} +20 -13
  162. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  163. package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
  164. package/dist/toolchain-BY8X8HXx.mjs +2 -0
  165. package/dist/toolchain-DpJMHq0n.mjs +876 -0
  166. package/dist/{trigger-CigAYjeL.mjs → trigger-Cbyc41d_.mjs} +21 -6
  167. package/dist/trigger-yb_nFzPF.mjs +2 -0
  168. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-CA3TgT3-.mjs} +263 -156
  169. package/dist/web-CZ07gd77.mjs +2 -0
  170. package/dist/{web-BDBMxDpx.mjs → web-DKx6yoFA.mjs} +20 -14
  171. package/dist/web-run.mjs +13 -12
  172. package/dist/windows-report.d.mts +1 -0
  173. package/dist/windows-report.mjs +18 -0
  174. package/dist/windows-report.ps1 +43 -0
  175. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-U08dEzhG.mjs} +62 -58
  176. package/dist/{workspaces-C36s2jb9.mjs → workspaces-CpANmBlq.mjs} +1723 -1286
  177. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-CHecZ4Oq.mjs} +1097 -547
  178. package/dist/worktree-ZqZVjD9K.mjs +2 -0
  179. package/dist/xcode-BXn9-xYx.mjs +896 -0
  180. package/package.json +7 -5
  181. package/shim/android-audio/Main.java +24 -0
  182. package/shim/android-audio/README.md +17 -0
  183. package/shim/android-audio.jar +0 -0
  184. package/shim/android-optimizations.gradle +7 -5
  185. package/dist/activity-BSV745Kz.mjs +0 -629
  186. package/dist/api-qvOzWyfO.mjs +0 -154
  187. package/dist/api-run.mjs +0 -294
  188. package/dist/app-install-BIKtMfPq.mjs +0 -896
  189. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  190. package/dist/budget-f7516Zk0.mjs +0 -4106
  191. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  192. package/dist/cancellation-C_22VQTH.mjs +0 -24
  193. package/dist/client-qQAaXSUs.mjs +0 -1771
  194. package/dist/config-BYDxlMY3.mjs +0 -562
  195. package/dist/device-DuiPJQSn.mjs +0 -290
  196. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  197. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  198. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  199. package/dist/exec-DqKo9GKJ.mjs +0 -268
  200. package/dist/git-DDfFzkMm.mjs +0 -45
  201. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  202. package/dist/logs-BGrEUaEs.mjs +0 -383
  203. package/dist/macos-Ch5VJmcS.mjs +0 -584
  204. package/dist/metro-gateway-CX9Xlkq2.mjs +0 -103
  205. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  206. package/dist/native-android-D5qc3-_v.mjs +0 -226
  207. package/dist/native-gradle-inputs-BsLRrl7u.mjs +0 -349
  208. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  209. package/dist/plan-C4TjdPsR.mjs +0 -260
  210. package/dist/prebuild-DYbucPXy.mjs +0 -212
  211. package/dist/preview-78a9kR_-.mjs +0 -1011
  212. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  213. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  214. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  215. package/dist/result-CaJg5Iat.mjs +0 -186
  216. package/dist/server-expo-Bigriskl.mjs +0 -2
  217. package/dist/settings-BORNaaCO.mjs +0 -402
  218. package/dist/settings-vk3mJGSm.d.mts +0 -13
  219. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  220. package/dist/stage-KNTQopqv.mjs +0 -157
  221. package/dist/start-BWqzODpb.mjs +0 -1116
  222. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  223. package/dist/swiftpm-macos-DRNVJWlb.mjs +0 -119
  224. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  225. package/dist/toolchain-BFkAcstd.mjs +0 -2
  226. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  227. package/dist/trigger-9_USgmxz.mjs +0 -2
  228. package/dist/web-Dq-i3wzJ.mjs +0 -2
  229. package/dist/worktree-DpLdCHga.mjs +0 -2
  230. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  231. package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
@@ -1,41 +1,39 @@
1
- import { B as deviceSlotKey, H as parseDeviceSlotKey, L as volumeRootFor, N as formatBytes, W as projectDeviceSlots, _ as loadConfig$1, d as getConfigDir, k as process_identity_exports } from "./config-BYDxlMY3.mjs";
2
- import { t as getExecutor } from "./exec-DqKo9GKJ.mjs";
3
- import { n as gitAsync } from "./git-DDfFzkMm.mjs";
4
- import { Dt as repoRoot, gt as gitCommonDirOnDisk, ht as gitCommonDir, it as workspaceHiddenSetting, q as resolveSettings, xt as linkedWorktreesOnDisk } from "./settings-B717odTD.mjs";
5
- import { i as listLeaseFiles, r as leaseIsExpired, s as parseWorkspaceLeases } from "./device-lease-BX1sJQ2E.mjs";
6
- import { C as workspaceLogErrorIndex, r as readWorkspaceState$1, w as workspaceLogsDir$1 } from "./workspace-state-DJt_MMvf.mjs";
7
- import { a as formatElapsed, i as formatDuration, r as clockTime, u as plural } from "./command-output-BTy8hZ0F.mjs";
8
- import { F as readWorkspaceLaunches, N as readRemoteSession, _ as detectIsExpo, c as projectShortcut, i as findServerWorkspace, j as readMetroTunnel, l as detectPlatforms, v as detectTutorial, x as readAppJson } from "./project-_phNIJfs.mjs";
9
- import { F as ownedAvdDeviceProfile, O as listAdbDevices, at as POOL_SETTING_REMEDY, dt as parkedMaxSetting, ft as readParked, z as ownedAvdSerialResolver } from "./android-Mz_Inn3w.mjs";
10
- import { a as listeningPidsByPort, c as processCwd, i as listeningPids, l as processCwds, p as isMetroRunning, s as pidExists, u as resolveProjectMetro } from "./metro-DnCEjCxs.mjs";
11
- import { P as resolveSupervisorTarget } from "./workspaces-C36s2jb9.mjs";
12
- import { Ct as bundlingActivity, It as statsProjectKey$1, Mt as readStats$1, St as buildStatusLine, Tt as parseActiveBuild, bt as activeBuildState, it as readFootprints, mt as metroLastStop, o as machineNumber, rt as attributeMachineUsage, ut as describeMetroLastStop, vt as ACTIVE_BUILD_KEY, xt as buildReport } from "./budget-f7516Zk0.mjs";
13
- import { a as parseNdjsonLine } from "./ndjson-GOnbyvso.mjs";
14
- import { a as readWebPage, o as readWebRecord, u as webFacts } from "./state-D1Icyjlu.mjs";
15
- import { C as statusActivity, E as withWebFacts, S as remoteDeviceState, T as unprovisionedWorktrees, _ as gitSummaryText, b as poolLine, c as activityLabel, d as capacity, f as deviceLeaseLines, h as environmentState, l as addReverseMissingIssue, m as diskLine, p as deviceLeaseStates, u as applyMachineMemory, v as metroReverseTargets, w as tightVolumes, x as remoteDeviceLine, y as parseDfFree } from "./watchman-CPQFZLXY.mjs";
16
- import { d as readWebActivity, f as tailLines, i as createDeviceProcessTables, r as createActivityReader } from "./activity-BSV745Kz.mjs";
17
- import { b as parseSimctlList, f as listAllIosSimsAsync } from "./ios-RkW4pnQf.mjs";
18
- import { h as hasMetroReverse } from "./app-install-BIKtMfPq.mjs";
19
- import { d as probeHostedSession } from "./hosted-client-ZEKpS9vw.mjs";
20
- import { r as readEasSessionLedger$1 } from "./eas-session-ledger-Cm0Gwq2F.mjs";
21
- import { d as readIosDevices, s as isReachable } from "./ios-device-D7pi2Sca.mjs";
22
- import "./hosted-macos-BACVAVqE.mjs";
23
- import { i as readSupervisorState } from "./stop-BNmBMi1F.mjs";
24
- import { i as createStatusMeasurer, n as workspacePhase, r as applyStatusMeasures, s as mergeState } from "./warm-progress-BuY-Fvfn.mjs";
25
- import { r as workspaceRecordingEnabled } from "./recordings-D0d5aQt0.mjs";
26
- import { n as maintenanceLines, r as maintenanceStatus } from "./status-BTA7kKiQ.mjs";
27
- import { a as watchStatusSources, i as watchPayload, n as WATCH_LIGHT_INTERVAL_MS, r as createRefreshScheduler, t as WATCH_FALLBACK_MS } from "./status-watch-C23ILtf9.mjs";
1
+ import { g as process_identity_exports, t as getExecutor } from "./exec-DEoAhcze.mjs";
2
+ import { m as workspaceLogsDir$1, p as workspaceLogErrorIndex } from "./paths-DQtTgsBf.mjs";
3
+ import { G as projectDeviceSlots, P as formatBytes, R as volumeRootFor, U as parseDeviceSlotKey, V as deviceSlotKey, _ as loadConfig$1, d as getConfigDir } from "./config-DlrsduwG.mjs";
4
+ import { a as formatElapsed, i as formatDuration, r as clockTime, u as plural } from "./command-output-gwpm28fu.mjs";
5
+ import { s as gitAsync } from "./operation-exec-BW0em61G.mjs";
6
+ import { r as readWorkspaceState$1 } from "./workspace-state-U08dEzhG.mjs";
7
+ import { Mt as repoRoot, Y as resolveSettings, _t as gitCommonDir, ot as workspaceHiddenSetting, wt as linkedWorktreesOnDisk, yt as gitCommonDirOnDisk } from "./settings-C7O8A6ZI.mjs";
8
+ import { I as readWorkspaceLaunches, M as readMetroTunnel, P as readRemoteSession, S as readAppJson, a as findServerWorkspace, l as projectShortcut, u as detectPlatforms, v as detectIsExpo, y as detectTutorial } from "./project-wM_XFTvE.mjs";
9
+ import { a as parseNdjsonLine } from "./ndjson-CgE_o3Dl.mjs";
10
+ import { c as pidExists, d as resolveProjectMetro, h as isMetroRunning, i as listeningPids, l as processCwd, o as listeningPidsByPort, u as processCwds } from "./metro-DiXtA3Ty.mjs";
11
+ import { a as readWebPage, o as readWebRecord, u as webFacts } from "./state--smjFSTL.mjs";
12
+ import { A as remoteDeviceState, C as environmentState, D as parseDfFree, E as metroReverseTargets, M as tightVolumes, N as unprovisionedWorktrees, O as poolLine, P as withWebFacts, S as diskLine, T as gitSummaryText, _ as addReverseMissingIssue, b as deviceLeaseLines, g as activityLabel, j as statusActivity, k as remoteDeviceLine, r as readEasSessionLedger$1, v as applyMachineMemory, x as deviceLeaseStates, y as capacity } from "./eas-session-ledger-DlY_serQ.mjs";
13
+ import { F as buildStatusLine, G as readStats$1, I as bundlingActivity, N as activeBuildState, P as buildReport, R as parseActiveBuild, Y as statsProjectKey$1, h as describeMetroLastStop, j as ACTIVE_BUILD_KEY, o as machineNumber, vn as hasMetroReverse, vr as attributeMachineUsage, y as metroLastStop, yr as readFootprints } from "./budget-Cvwn54qV.mjs";
14
+ import { h as resolveSupervisorTarget } from "./workspaces-CpANmBlq.mjs";
15
+ import { a as createDeviceProcessTables, b as leaseIsExpired, h as tailLines, m as readWebActivity, r as createActivityReader, w as parseWorkspaceLeases, x as listLeaseFiles } from "./activity-CMLmzp7o.mjs";
16
+ import { A as listAdbDevices, B as ownedAvdDeviceProfile, W as ownedAvdSerialResolver, _t as parkedMaxSetting, dt as POOL_SETTING_REMEDY, vt as readParked } from "./android-C7sVmyI9.mjs";
17
+ import { b as parseSimctlList, f as listAllIosSimsAsync } from "./ios-hcBpnEGk.mjs";
18
+ import { f as probeHostedSession } from "./hosted-client-DZAPrcro.mjs";
19
+ import "./hosted-macos-_awYSpfv.mjs";
20
+ import { i as readSupervisorState } from "./stop-Mv6W9FAk.mjs";
21
+ import { n as maintenanceLines, r as maintenanceStatus } from "./status-BRROykC8.mjs";
22
+ import { f as mergeState, i as createStatusMeasurer, n as workspacePhase, r as applyStatusMeasures } from "./warm-progress-CA3TgT3-.mjs";
23
+ import { r as workspaceRecordingEnabled } from "./recordings-CQmfzAh7.mjs";
24
+ import { d as readIosDevices, s as isReachable } from "./ios-device--h_-8ENa.mjs";
25
+ import { t as triggerMaintenance } from "./trigger-Cbyc41d_.mjs";
26
+ import { a as createRefreshScheduler, c as watchStatusSources, n as WATCH_LIGHT_INTERVAL_MS, o as watchChangeKey, r as WATCH_MACHINE_INTERVAL_MS, s as watchPayload, t as WATCH_FALLBACK_MS } from "./status-watch-Bg_u-pwR.mjs";
28
27
  import { t as watchStdoutReader } from "./stdout-reader-C8yjre1x.mjs";
29
- import { t as triggerMaintenance } from "./trigger-CigAYjeL.mjs";
28
+ import { createHash, randomUUID } from "node:crypto";
30
29
  import { mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
31
30
  import { join, posix, resolve } from "node:path";
32
- import { basename as basename$1, dirname as dirname$1, join as join$1 } from "path";
33
- import { DEVICE_RECLAIM_REASON, ERROR_SOURCES, archiveRoot, archivedUsage, bundleMarkerPlatform, countErrorEntries, gitMergeCacheDir, hostedAndroidPlacements, hostedAndroidRecords, hostedAndroidStatus, hostedIosPlacements, hostedIosRecords, hostedIosStatus, linkReplacedArchives, logFiles, macosAppState, parseHostedAndroidPlacement, parseHostedIosPlacement, queryLogs, readArchives, readBuildDetail, readBuildHistory, readDeviceIdleShutdowns, readDevicePlacement, readIdleStop, readLastBuilds, readMacosRecord, recordMatches, sortByTs, unreadableHostedAndroid, unreadableHostedIos, withDerivedFacts, withGitChip, withStateReadCache } from "@stim-cli/core/state";
34
- import { closeSync as closeSync$1, existsSync as existsSync$1, fstatSync as fstatSync$1, openSync as openSync$1, readFileSync as readFileSync$1, readSync as readSync$1, renameSync as renameSync$1, rmSync as rmSync$1, statSync as statSync$1, writeFileSync as writeFileSync$1 } from "fs";
35
31
  import { rotatedLogPath } from "@stim-cli/core";
36
- import { homedir, totalmem } from "os";
37
- import { createHash, randomUUID } from "node:crypto";
32
+ import { DEVICE_RECLAIM_REASON, ERROR_SOURCES, archiveRoot, archivedUsage, bundleMarkerPlatform, countErrorEntries, gitMergeCacheDir, hostedAndroidPlacements, hostedAndroidRecords, hostedAndroidStatus, hostedIosPlacements, hostedIosRecords, hostedIosStatus, linkReplacedArchives, logFiles, macosAppState, parseHostedAndroidPlacement, parseHostedIosPlacement, queryLogs, readArchives, readBuildDetail, readBuildHistory, readDeviceIdleShutdowns, readDevicePlacement, readIdleStop, readLastBuilds, readMacosRecord, recordMatches, sortByTs, unreadableHostedAndroid, unreadableHostedIos, withDerivedFacts, withGitChip, withStateReadCache } from "@stim-cli/core/state";
33
+ import { basename as basename$1, dirname as dirname$1, join as join$1 } from "path";
38
34
  import chalk from "chalk";
35
+ import { closeSync as closeSync$1, existsSync as existsSync$1, fstatSync as fstatSync$1, openSync as openSync$1, readFileSync as readFileSync$1, readSync as readSync$1, renameSync as renameSync$1, rmSync as rmSync$1, statSync as statSync$1, writeFileSync as writeFileSync$1 } from "fs";
36
+ import { homedir, totalmem, userInfo } from "os";
39
37
  //#region src/device-host/hosted-native-status.ts
40
38
  function hostedNativeProbe(placement, probe, slot, platform) {
41
39
  const label = platform === "ios" ? "iOS" : "Android";
@@ -502,7 +500,8 @@ function gitFilesStamp(worktree, refs) {
502
500
  * default-branch commit stands in, because a merged branch stays merged. A judgement that timed out is not retried
503
501
  * for the same HEAD and target for five minutes. With `maxAgeMs`, a summary made that recently in this process is
504
502
  * reused while the git files it depends on are unchanged, so a change that is not staged can take up to `maxAgeMs`
505
- * to show; so is the null of a worktree whose directory is gone.
503
+ * to show; so is the null of a worktree whose directory is gone. Deferred merge verdicts are retried independently
504
+ * of the cached counts without renewing their age.
506
505
  */
507
506
  async function readWorktreeGit(worktrees, { skip, maxAgeMs = 0 }) {
508
507
  const now = Date.now();
@@ -520,7 +519,7 @@ async function readWorktreeGit(worktrees, { skip, maxAgeMs = 0 }) {
520
519
  const files = maxAgeMs > 0 ? gitFilesStamp(worktree, refs) : null;
521
520
  if (memo && memo.files !== null && memo.files === files?.stamp && now - memo.at < maxAgeMs) return {
522
521
  path: worktree.path,
523
- memo: memo.git
522
+ memo
524
523
  };
525
524
  const repository = worktree.repository;
526
525
  if (repository && !targets.has(repository)) targets.set(repository, defaultBranchOf(repository));
@@ -543,7 +542,16 @@ async function readWorktreeGit(worktrees, { skip, maxAgeMs = 0 }) {
543
542
  const summaries = /* @__PURE__ */ new Map();
544
543
  for (const read of reads) {
545
544
  if ("memo" in read) {
546
- summaries.set(read.path, read.memo ?? null);
545
+ const memo = read.memo;
546
+ if (memo?.git && memo.pendingMerge) {
547
+ const merge = mergedInto(read.path, memo.pendingMerge.head, memo.pendingMerge.target, budget);
548
+ memo.git = {
549
+ ...memo.git,
550
+ mergedInto: merge.into
551
+ };
552
+ if (!merge.deferred) delete memo.pendingMerge;
553
+ }
554
+ summaries.set(read.path, memo?.git ?? null);
547
555
  continue;
548
556
  }
549
557
  if (!read.status) {
@@ -566,12 +574,16 @@ async function readWorktreeGit(worktrees, { skip, maxAgeMs = 0 }) {
566
574
  upstream: counts.upstream,
567
575
  target: read.target?.ref ?? null
568
576
  };
569
- const settled = !merge?.deferred && refs.upstream === read.refs.upstream && refs.target === read.refs.target;
577
+ const settled = refs.upstream === read.refs.upstream && refs.target === read.refs.target;
570
578
  recent.set(read.path, {
571
579
  at: read.at,
572
580
  files: settled ? read.files?.stamp ?? null : null,
573
581
  refs,
574
- git: summary
582
+ git: summary,
583
+ ...merge?.deferred && head && read.target ? { pendingMerge: {
584
+ head,
585
+ target: read.target
586
+ } } : {}
575
587
  });
576
588
  summaries.set(read.path, summary);
577
589
  }
@@ -778,31 +790,11 @@ function physicalDeviceLine(device, now) {
778
790
  return `${device.platform}${slot}: ${name} (physical${model}) ${device.connection} -- leased until ${clockTime(device.lease.expiresAt)} (${remaining} left)`;
779
791
  }
780
792
  //#endregion
781
- //#region src/commands/status.ts
782
- const WATCH_GIT_MAX_AGE_MS = 6e4;
793
+ //#region src/status-read.ts
783
794
  function iosStatusName(ios) {
784
795
  const host = ios.host;
785
796
  return host && !ios.udid ? `${host.device?.name ?? "iOS simulator"} (${host.device ? `iOS ${host.device.runtime.replace(/^iOS /, "")}` : "runtime pending"}) on ${host.machine}${host.selected === "auto" && host.reason ? ` (auto: ${host.reason})` : ""}` : ios.name ?? ios.udid;
786
797
  }
787
- function iosStatusLines(record, slotLabel) {
788
- const out = [];
789
- const host = record?.udid ? record.host : void 0;
790
- const iosDevices = [record, ...host ? [{
791
- host,
792
- name: host.device?.name ?? null,
793
- udid: "",
794
- owned: false,
795
- state: host.state ?? "unverified"
796
- }] : []];
797
- for (const ios of iosDevices) {
798
- if (!ios) continue;
799
- const booted = ios.state === "Booted" ? chalk.green("booted") : chalk.dim(ios.state.toLowerCase());
800
- const owned = ios.owned ? chalk.dim(" (owned)") : "";
801
- out.push(` ios${slotLabel}: ${chalk.cyan(iosStatusName(ios))} ${booted}${owned}${activitySuffix(ios.activity)}${appSuffix(ios.app)}${idleShutdownSuffix(ios.idleShutdown)}`);
802
- if (!ios.udid && ios.host?.agent.driver === "agent-device") out.push(chalk.dim(` agent: ${ios.host.agent.command}`));
803
- }
804
- return out;
805
- }
806
798
  function applyHostedAndroidStates(state, saved, factsBySlot) {
807
799
  for (const [slot, record] of Object.entries(hostedAndroidRecords(saved))) if (!parseHostedAndroidPlacement(record)) state.warnings.push(unreadableHostedAndroid(slot));
808
800
  for (const [slot, facts] of Object.entries(factsBySlot)) {
@@ -828,23 +820,6 @@ function applyHostedAndroidStates(state, saved, factsBySlot) {
828
820
  state.live ||= facts.android.state === "ready";
829
821
  }
830
822
  }
831
- function androidStatusLines(record, slotLabel) {
832
- const out = [];
833
- if (record?.host && !record.serial) {
834
- const host = record.host;
835
- out.push(` android${slotLabel}: ${chalk.cyan(`${host.device?.name ?? "Android emulator"} on ${host.machine}${host.selected === "auto" && host.reason ? ` (auto: ${host.reason})` : ""}`)} ${host.state ?? "unverified"}`);
836
- } else if (record) {
837
- const kind = record.physical ? chalk.dim("(physical)") : chalk.dim("(emulator)");
838
- const observed = record.state ? ` ${record.state}${record.serial ? ` (${record.serial})` : ""}` : "";
839
- out.push(` android${slotLabel}: ${chalk.cyan(record.name)} ${kind}${observed}${record.owned ? chalk.dim(" (owned)") : ""}${activitySuffix(record.activity)}${appSuffix(record.app)}${idleShutdownSuffix(record.idleShutdown)}`);
840
- if (record.host) {
841
- const host = record.host;
842
- out.push(` android${slotLabel}: ${chalk.cyan(`${host.device?.name ?? "Android emulator"} on ${host.machine}${host.selected === "auto" && host.reason ? ` (auto: ${host.reason})` : ""}`)} ${host.state ?? "unverified"}`);
843
- }
844
- }
845
- if (record?.host?.agent.driver === "agent-device") out.push(chalk.dim(` agent: ${record.host.agent.command}`));
846
- return out;
847
- }
848
823
  function doctorRunTimes(proj) {
849
824
  const runs = {};
850
825
  for (const platform of ["ios", "android"]) {
@@ -853,48 +828,55 @@ function doctorRunTimes(proj) {
853
828
  }
854
829
  return Object.keys(runs).length ? runs : void 0;
855
830
  }
856
- function formatGb(mb) {
857
- return `${(mb / 1024).toFixed(1)} GB`;
858
- }
859
- function statusCommand(program) {
860
- program.command("status").description("Show every environment on this machine: devices, ports, what is actually running, and anything stuck.").option("--json", "print the state as JSON").option("--watch", "keep running and print the state again each time it changes").action(async (opts) => {
861
- if (opts.watch) return watchStatus(Boolean(opts.json));
862
- const json = Boolean(opts.json);
863
- for (const line of renderStatus(await readStatus(0), json)) console.log(line);
864
- });
831
+ /**
832
+ * Probes that read everything when asked. `simctlListing`, when given, answers `simulators` without running simctl,
833
+ * `gitMaxAgeMs` reuses git summaries read that recently, and `archives` answers `archives` without reading them.
834
+ */
835
+ function liveProbes({ simctlListing = null, gitMaxAgeMs = 0, archives } = {}) {
836
+ return {
837
+ simulators: () => simctlListing === null ? listAllIosSimsAsync() : Promise.resolve().then(() => parseSimctlList(simctlListing)),
838
+ metro: readMetroFacts,
839
+ hostedIos: readHostedIosStatus,
840
+ hostedAndroid: readHostedAndroidStatus,
841
+ hostedMacos: readHostedMacosStatus,
842
+ git: (worktrees, skip) => readWorktreeGit(worktrees, {
843
+ maxAgeMs: gitMaxAgeMs,
844
+ skip
845
+ }),
846
+ androidRuntime: androidRuntimeReader(),
847
+ physicalDevice: physicalDeviceReader(),
848
+ deviceTables: createDeviceProcessTables,
849
+ metroReverses: (serial) => getExecutor().runFileQuiet("adb", [
850
+ "-s",
851
+ serial,
852
+ "reverse",
853
+ "--list"
854
+ ], { timeoutMs: 5e3 }),
855
+ footprints: readFootprints,
856
+ archives: () => archives ?? readArchives()
857
+ };
865
858
  }
866
- function readStatus(gitMaxAgeMs, simctlListing = null, archives) {
867
- return withStateReadCache(() => readStatusFacts(gitMaxAgeMs, simctlListing, archives));
859
+ /**
860
+ * Reads the status of every environment. With `git: 'all'` it reads the git summary of every worktree before
861
+ * composing; with `'live'` only those of live environments, after composing; with `'none'` no git summary.
862
+ */
863
+ function readStatus({ probes = liveProbes(), git = "live", cwd = process.cwd() } = {}) {
864
+ return withStateReadCache(() => readStatusFacts(probes, git, cwd));
868
865
  }
869
- async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
866
+ async function readStatusFacts(probes, gitScope, cwd) {
870
867
  const cfg = loadConfig$1();
871
868
  const projects = Object.entries(cfg?.projects || {});
872
- const iosReads = projects.map(([path]) => readHostedIosStatus(hostedIosPlacements(readWorkspaceState$1(path))));
873
- const androidReads = projects.map(([path]) => readHostedAndroidStatus(hostedAndroidPlacements(readWorkspaceState$1(path))));
874
- const macosReads = projects.map(([path]) => readHostedMacosStatus(readMacosRecord(path)));
875
- const cwdRoot = findServerWorkspace(process.cwd())?.root ?? null;
876
- const worktrees = linkedWorktrees([process.cwd(), ...projects.map(([path]) => path)]);
869
+ const iosReads = projects.map(([path]) => probes.hostedIos(hostedIosPlacements(readWorkspaceState$1(path))));
870
+ const androidReads = projects.map(([path]) => probes.hostedAndroid(hostedAndroidPlacements(readWorkspaceState$1(path))));
871
+ const macosReads = projects.map(([path]) => probes.hostedMacos(readMacosRecord(path)));
872
+ const cwdRoot = findServerWorkspace(cwd)?.root ?? null;
873
+ const { worktrees, commonDirs } = linkedWorktrees([cwd, ...projects.map(([path]) => path)]);
877
874
  const orphanWorktrees = unprovisionedWorktrees(worktrees, projects.map(([p]) => p));
878
- const simsRead = simctlListing === null ? listAllIosSimsAsync() : Promise.resolve().then(() => parseSimctlList(simctlListing));
875
+ const simsRead = probes.simulators();
879
876
  simsRead.catch(() => {});
880
- const ports = await portLookup(projects.flatMap(([, proj]) => proj.metroPort ? [proj.metroPort] : []));
881
- const processes = Promise.all(projects.map(async ([path, proj]) => {
882
- const metro = proj.metroPort ? await resolveOnPort(proj.metroPort, path, ports) : null;
883
- return {
884
- metro,
885
- supervisor: await supervisorFacts(path, proj, metro, ports)
886
- };
887
- }));
877
+ const processes = probes.metro(projects);
888
878
  processes.catch(() => {});
889
- const watching = gitMaxAgeMs > 0;
890
- const gitRead = watching ? readGitInto(worktrees, orphanWorktrees, gitMaxAgeMs) : null;
891
- const androidRuntimeOf = androidRuntimeReader();
892
- const devices = projects.map(([, proj]) => ({
893
- androidRuntimes: Object.fromEntries(projectDeviceSlots(proj).slice(1).map(({ slot, platforms }) => [slot, platforms.android?.owned && platforms.android.avdName ? androidRuntimeOf(platforms.android.avdName) : null])),
894
- androidRuntime: proj.platforms?.android?.owned && proj.platforms.android.avdName ? androidRuntimeOf(proj.platforms.android.avdName) : null,
895
- androidDeviceProfiles: Object.fromEntries(projectDeviceSlots(proj).slice(1).map(({ slot, platforms }) => [slot, platforms.android?.owned && platforms.android.avdName ? ownedAvdDeviceProfile(platforms.android.avdName) : null])),
896
- androidDeviceProfile: proj.platforms?.android?.owned && proj.platforms.android.avdName ? ownedAvdDeviceProfile(proj.platforms.android.avdName) : null
897
- }));
879
+ const gitRead = gitScope === "all" ? readGitInto(probes, worktrees, orphanWorktrees) : null;
898
880
  const logs = projects.map(([path]) => logFacts(path));
899
881
  const simsByUdid = {};
900
882
  let simsAvailable = true;
@@ -906,6 +888,12 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
906
888
  simctlError = String(e?.message || e).split("\n")[0] ?? "";
907
889
  }
908
890
  const running = await processes;
891
+ const devices = projects.map(([, proj]) => ({
892
+ androidRuntimes: Object.fromEntries(projectDeviceSlots(proj).slice(1).map(({ slot, platforms }) => [slot, platforms.android?.owned && platforms.android.avdName ? probes.androidRuntime(platforms.android.avdName) : null])),
893
+ androidRuntime: proj.platforms?.android?.owned && proj.platforms.android.avdName ? probes.androidRuntime(proj.platforms.android.avdName) : null,
894
+ androidDeviceProfiles: Object.fromEntries(projectDeviceSlots(proj).slice(1).map(({ slot, platforms }) => [slot, platforms.android?.owned && platforms.android.avdName ? ownedAvdDeviceProfile(platforms.android.avdName) : null])),
895
+ androidDeviceProfile: proj.platforms?.android?.owned && proj.platforms.android.avdName ? ownedAvdDeviceProfile(proj.platforms.android.avdName) : null
896
+ }));
909
897
  await gitRead;
910
898
  const history = readStats$1().record?.history;
911
899
  const states = [];
@@ -919,7 +907,6 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
919
907
  now: leaseNow
920
908
  });
921
909
  const roots = [];
922
- const readPhysicalDevice = physicalDeviceReader();
923
910
  const simulatorUdids = new Set([...Object.keys(simsByUdid), ...projects.flatMap(([, proj]) => projectDeviceSlots(proj).flatMap(({ platforms }) => platforms.ios?.deviceUdid ?? []))].map((udid) => udid.toUpperCase()));
924
911
  for (const [i, [path, proj]] of projects.entries()) {
925
912
  const { metro, supervisor } = running[i];
@@ -1024,20 +1011,20 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
1024
1011
  root: path,
1025
1012
  now: leaseNow,
1026
1013
  simulatorUdids,
1027
- read: readPhysicalDevice
1014
+ read: (platform, id) => probes.physicalDevice(platform, id)
1028
1015
  });
1029
1016
  if (state && physicalDevices.length) state.physicalDevices = physicalDevices;
1030
1017
  labelOnlyRoots.push(Boolean(proj.worktreeRoot && !proj.bundleId && !state?.metro && !state?.ios && !state?.android && !state?.web && !state?.macos));
1031
1018
  }
1032
- if (!watching) await readGitInto(worktrees, orphanWorktrees, gitMaxAgeMs, new Set(states.flatMap((state) => state.live && state.worktree ? [state.worktree.path] : [])));
1019
+ if (gitScope === "live") await readGitInto(probes, worktrees, orphanWorktrees, new Set(states.flatMap((state) => state.live && state.worktree ? [state.worktree.path] : [])));
1033
1020
  applyStatusMeasures(states, worktrees);
1034
1021
  readLogDerivedFacts(states);
1035
- const tables = createDeviceProcessTables();
1022
+ const tables = probes.deviceTables();
1036
1023
  readDeviceProcesses(states, tables, {
1037
1024
  projects,
1038
1025
  launchesByState
1039
1026
  });
1040
- readMetroReverses(states, launchesByState);
1027
+ readMetroReverses(states, launchesByState, probes);
1041
1028
  const sims = Object.values(simsByUdid);
1042
1029
  const simNames = Object.fromEntries(sims.map((sim) => [sim.udid.toUpperCase(), sim.name]));
1043
1030
  const machine = await readMachineUsage({
@@ -1045,9 +1032,10 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
1045
1032
  roots,
1046
1033
  simNames,
1047
1034
  tables,
1048
- busy: sims.some((sim) => sim.state === "Booted")
1035
+ busy: sims.some((sim) => sim.state === "Booted"),
1036
+ probes
1049
1037
  });
1050
- const archives = cachedArchives ?? readArchives();
1038
+ const archives = probes.archives();
1051
1039
  const maxCount = machineNumber("archive.maxCount", cfg, process.env);
1052
1040
  return {
1053
1041
  archived: linkReplacedArchives(archives.slice(0, maxCount.value ?? 200), states.map((state) => state.path)),
@@ -1065,7 +1053,9 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
1065
1053
  tables,
1066
1054
  machine,
1067
1055
  roots,
1068
- simNames
1056
+ simNames,
1057
+ probes,
1058
+ gitCommonDirs: commonDirs
1069
1059
  };
1070
1060
  }
1071
1061
  /** Sets the facts status derives from workspace logs, the running build's record and its detail file. */
@@ -1120,11 +1110,6 @@ function readLogDerivedFacts(states) {
1120
1110
  }
1121
1111
  }
1122
1112
  }
1123
- function phaseMarker({ phase, live, warmStep }) {
1124
- if (phase === "warming") return chalk.cyan(` [warming: ${warmStep}]`);
1125
- if (phase === "ready") return chalk.green(" [ready]");
1126
- return live ? "" : chalk.dim(" [idle]");
1127
- }
1128
1113
  function browserPids(web) {
1129
1114
  if (!web) return [];
1130
1115
  const chrome = web.record.chromeProcess?.pid;
@@ -1136,10 +1121,10 @@ function browserPids(web) {
1136
1121
  * `memoryMb` from them. Reads both only when a simulator is booted, a workspace is live or a build runs, so an idle
1137
1122
  * machine runs no `ps` and keeps the estimate.
1138
1123
  */
1139
- async function readMachineUsage({ states, roots, simNames, tables, busy }) {
1124
+ async function readMachineUsage({ states, roots, simNames, tables, busy, probes }) {
1140
1125
  const processes = busy || states.some((state) => state.live || state.build?.state === "running") ? tables.host() : null;
1141
1126
  if (!processes) return null;
1142
- const footprints = await readFootprints();
1127
+ const footprints = await probes.footprints();
1143
1128
  const machine = attributeMachineUsage({
1144
1129
  processes,
1145
1130
  footprints,
@@ -1151,338 +1136,112 @@ async function readMachineUsage({ states, roots, simNames, tables, busy }) {
1151
1136
  return machine;
1152
1137
  }
1153
1138
  /**
1154
- * Rereads only the error counts, device activity and machine usage. With `machine`, and when the snapshot measured
1155
- * machine usage, it reads the host process table again; it reuses every other subprocess fact of the full read.
1139
+ * Rereads the log-derived facts and the cached measures. With `tables` it also rereads the process tables and the
1140
+ * device activity they show; with `machine` as well, and when the snapshot measured machine usage, the host process
1141
+ * table and machine usage. It reuses every other subprocess fact of the full read.
1156
1142
  */
1157
- async function refreshLightFacts(snapshot, machine) {
1158
- const fresh = createDeviceProcessTables();
1159
- snapshot.tables = {
1160
- host: machine && snapshot.machine ? fresh.host : snapshot.tables.host,
1161
- android: snapshot.tables.android,
1162
- tcpConnections: fresh.tcpConnections,
1163
- clients: fresh.host
1164
- };
1143
+ async function refreshLightFacts(snapshot, { tables, machine }) {
1144
+ if (tables) {
1145
+ const fresh = snapshot.probes.deviceTables();
1146
+ snapshot.tables = {
1147
+ host: machine && snapshot.machine ? fresh.host : snapshot.tables.host,
1148
+ android: snapshot.tables.android,
1149
+ tcpConnections: fresh.tcpConnections,
1150
+ clients: fresh.host
1151
+ };
1152
+ }
1165
1153
  withStateReadCache(() => {
1166
1154
  for (const state of snapshot.states) state.logs = logFacts(state.path);
1167
1155
  applyStatusMeasures(snapshot.states, snapshot.worktrees);
1168
1156
  readLogDerivedFacts(snapshot.states);
1169
- readDeviceProcesses(snapshot.states, snapshot.tables, null);
1157
+ if (tables) readDeviceProcesses(snapshot.states, snapshot.tables, null);
1170
1158
  });
1171
1159
  if (machine && snapshot.machine) snapshot.machine = await readMachineUsage({
1172
1160
  ...snapshot,
1173
1161
  busy: true
1174
1162
  });
1175
1163
  }
1176
- function renderStatus({ archived, archivedUsage: usage, projects, states, labelOnlyRoots, leases, leaseNow, orphanWorktrees, simsAvailable, simctlError, cwdRoot, machine }, json, settle = (payload) => payload) {
1177
- const out = [];
1178
- const totalMemoryMb = Math.round(totalmem() / 1048576);
1179
- const cap = capacity(states, totalMemoryMb);
1180
- const pools = ["ios", "android"].map((platform) => {
1181
- const { max, error } = parkedMaxSetting(platform);
1182
- return {
1183
- error,
1184
- line: poolLine({
1185
- platform,
1186
- parked: readParked(platform).length,
1187
- max
1188
- })
1189
- };
1190
- });
1191
- const maintenance = maintenanceStatus();
1192
- if (json) {
1193
- const payload = {
1194
- environments: states.map((state, i) => withDerivedFacts(labelOnlyRoots[i] ? {
1195
- ...state,
1196
- labelOnly: true
1197
- } : state)),
1198
- archived,
1199
- archivedUsage: usage,
1200
- capacity: cap,
1201
- deviceLeases: leases,
1202
- unprovisionedWorktrees: orphanWorktrees.map(withGitChip),
1203
- simctlAvailable: simsAvailable,
1204
- machine,
1205
- maintenance
1164
+ async function readGitInto(probes, worktrees, orphans, only) {
1165
+ const home = homedir();
1166
+ const byPath = await probes.git(worktrees, (w) => only !== void 0 && !only.has(w.path) || process.platform === "darwin" && orphans.includes(w) && inPrivacyProtectedFolder(w.path, home));
1167
+ for (const worktree of worktrees) worktree.git = byPath.get(worktree.path) ?? null;
1168
+ }
1169
+ function readDeviceProcesses(states, tables, apps) {
1170
+ const readActivity = createActivityReader({ tables });
1171
+ const readAppProcess = createAppProcessReader(tables);
1172
+ for (const [i, state] of states.entries()) {
1173
+ const appIdOn = (platform, slot, deviceId) => {
1174
+ if (!apps) return void 0;
1175
+ const project = apps.projects[i][1];
1176
+ const launch = apps.launchesByState[i][deviceSlotKey(platform, slot)];
1177
+ return launch?.deviceId === deviceId ? launch.appId : platform === "ios" ? project.bundleId : project.androidPackage;
1206
1178
  };
1207
- out.push(JSON.stringify(settle(payload)));
1208
- return out;
1209
- }
1210
- out.push(...maintenanceLines(maintenance).map((line) => chalk.dim(line)));
1211
- if (usage.count) out.push(`Archived: ${plural(usage.count, "workspace")}, ${formatBytes(usage.bytes)}`);
1212
- if (projects.length === 0 && orphanWorktrees.length === 0) {
1213
- out.push(chalk.dim("No projects registered."));
1214
- for (const pool of pools) {
1215
- if (pool.error) out.push(chalk.yellow(`${pool.error} ${POOL_SETTING_REMEDY}`));
1216
- if (pool.line) out.push(chalk.dim(pool.line));
1217
- }
1218
- for (const line of deviceLeaseLines(leases, leaseNow)) out.push(line);
1219
- return out;
1220
- }
1221
- if (!simsAvailable) out.push(chalk.yellow(`simctl could not be read (${simctlError}), so no iOS sim below could be checked.`));
1222
- for (const [i, [path, proj]] of projects.entries()) {
1223
- const state = states[i];
1224
- if (!state) continue;
1225
- const shortcut = projectShortcut(path, proj);
1226
- const marker = path === cwdRoot ? chalk.bold.cyan(`* ${shortcut}`) : shortcut;
1227
- const idle = phaseMarker(state);
1228
- out.push(`\n${marker}${idle} ${chalk.dim(`(${path})`)}`);
1229
- out.push(labelOnlyRoots[i] ? chalk.dim(" worktree root (holds the label; the app registers its own entry)") : chalk.dim(` app: ${proj.bundleId ?? "?"} (${proj.isExpo ?? detectIsExpo(path) ? "expo" : "bare"})`));
1230
- if (state.metro) {
1231
- const label = state.metro.running ? chalk.green(`running (pid ${state.metro.pid})`) : state.metro.idleStop ? chalk.dim(`stopped (idle) after ${state.metro.idleStop.idleMinutes}m; \`stim start\`, \`ios\` or \`android\` restarts it`) : state.metro.lastStop ? chalk.dim(`not running${state.metro.lastStop.reason === "vanished" ? "" : ` since ${state.metro.lastStop.at}`}; ${describeMetroLastStop(state.metro.lastStop)}`) : chalk.dim("not running");
1232
- out.push(` metro: port ${state.metro.port} ${label}`);
1233
- if (state.metro.tunnel) {
1234
- const { provider, url } = state.metro.tunnel;
1235
- out.push(` tunnel: ${provider}${provider === "tailscale" ? " (tailnet-only)" : ""} ${url}`);
1236
- }
1237
- }
1238
- if (state.supervisor) {
1239
- const health = state.supervisor.healthy ? chalk.green("healthy") : chalk.yellow("not answering");
1240
- const mode = state.supervisor.mode ? chalk.dim(` (${state.supervisor.mode})`) : "";
1241
- out.push(` supervisor: pid ${state.supervisor.pid}${mode} ${health}`);
1242
- }
1243
- if (state.build) {
1244
- const line = ` ${buildStatusLine(state.build, Date.now())}`;
1245
- out.push(state.build.state === "running" ? line : chalk.yellow(line));
1246
- }
1247
- out.push(...lastBuildsLines(state.lastBuilds));
1248
- if (state.worktree?.git) out.push(chalk.dim(` git: ${gitSummaryText(state.worktree.git)}`));
1249
- for (const agent of state.agents ?? []) out.push(chalk.dim(` agent: ${agentLine(agent)}`));
1250
- if (state.logs) {
1251
- const n = state.logs.errorsSinceMarker;
1252
- const errs = n > 0 ? chalk.yellow(` (${n} error${n === 1 ? "" : "s"} since the last marker)`) : "";
1253
- out.push(chalk.dim(` logs: ${state.logs.dir}`) + errs);
1254
- }
1255
- for (const deviceState of [{
1179
+ for (const device of [{
1256
1180
  slot: "default",
1257
1181
  ios: state.ios,
1258
1182
  android: state.android
1259
1183
  }, ...state.slots ?? []]) {
1260
- const slotLabel = deviceState.slot === "default" ? "" : ` [${deviceState.slot}]`;
1261
- out.push(...iosStatusLines(deviceState.ios, slotLabel));
1262
- out.push(...androidStatusLines(deviceState.android, slotLabel));
1263
- }
1264
- if (state.macos) {
1265
- const host = state.macos.host;
1266
- const where = host ? ` on ${host.machine} as ${host.bundleId}${chalk.dim(` (session ${host.session})`)}` : "";
1267
- const build = state.macos.build;
1268
- const placement = build.buildMachine === void 0 ? "" : `; build placement ${build.buildMachine}, built on ${build.builtOn ?? "none"}`;
1269
- out.push(` macOS ${state.macos.product}: ${state.macos.state}${where}; build ${build.state}${placement}`);
1270
- if (host?.agent.driver === "agent-device") out.push(chalk.dim(` agent: ${host.agent.command}`));
1184
+ const base = {
1185
+ slot: device.slot,
1186
+ workspace: state.path
1187
+ };
1188
+ if (device.ios?.state === "Booted") {
1189
+ const id = device.ios.udid;
1190
+ device.ios.activity = statusActivity(readActivity({
1191
+ ...base,
1192
+ platform: "ios",
1193
+ id
1194
+ }));
1195
+ const appId = device.ios.owned ? appIdOn("ios", device.slot, id) : void 0;
1196
+ if (appId) device.ios.app = readAppProcess({
1197
+ platform: "ios",
1198
+ id,
1199
+ appId
1200
+ });
1201
+ }
1202
+ if (device.android && !device.android.physical && device.android.serial) {
1203
+ const id = device.android.serial;
1204
+ device.android.activity = statusActivity(readActivity({
1205
+ ...base,
1206
+ platform: "android",
1207
+ id
1208
+ }));
1209
+ const appId = device.android.owned ? appIdOn("android", device.slot, id) : void 0;
1210
+ if (appId) device.android.app = readAppProcess({
1211
+ platform: "android",
1212
+ id,
1213
+ appId
1214
+ });
1215
+ }
1271
1216
  }
1272
- if (state.web) {
1273
- const browser = state.web.running ? chalk.green(`running (pid ${state.web.pid}, DevTools ${state.web.cdpEndpoint})`) : chalk.dim("not running");
1274
- const page = state.web.page;
1275
- const failed = page?.state === "failed" ? ` -- ${chalk.yellow(`page failed: ${page.error}`)}` : "";
1276
- out.push(` web: ${chalk.cyan(page?.url ?? state.web.url)} ${browser}${state.web.headless ? "" : chalk.dim(" (headed)")}${activitySuffix(state.web.activity)}${failed}`);
1217
+ const web = state.web;
1218
+ const port = web?.cdpEndpoint ? Number(new URL(web.cdpEndpoint).port) : null;
1219
+ if (web?.running && port) {
1220
+ web.page = readWebPage(state.path);
1221
+ const ownPids = [web.pid, web.supervisorPid].filter((pid) => pid !== null);
1222
+ web.activity = statusActivity(readWebActivity({
1223
+ port,
1224
+ ownPids,
1225
+ workspace: state.path
1226
+ }, tables));
1277
1227
  }
1278
- for (const device of state.physicalDevices ?? []) out.push(` ${physicalDeviceLine(device, leaseNow)}`);
1279
- for (const remote of state.remoteDevices ?? []) out.push(` ${remoteDeviceLine(remote)}`);
1280
- for (const w of state.warnings) out.push(chalk.yellow(` ! ${w}`));
1281
- for (const note of state.issues.filter((issue) => issue.severity === "info")) out.push(chalk.dim(` - ${note.message}`));
1282
- }
1283
- for (const pool of pools) {
1284
- if (pool.error) out.push(chalk.yellow(`\n${pool.error} ${POOL_SETTING_REMEDY}`));
1285
- if (pool.line) out.push(chalk.dim(`\n${pool.line}`));
1286
- }
1287
- const leaseLines = deviceLeaseLines(leases, leaseNow);
1288
- if (leaseLines.length) {
1289
- out.push("");
1290
- for (const line of leaseLines) out.push(line);
1291
1228
  }
1292
- if (orphanWorktrees.length) {
1293
- out.push(chalk.dim(`\nWorktrees with no environment (${orphanWorktrees.length}):`));
1294
- for (const w of orphanWorktrees) out.push(chalk.dim(` ${orphanWorktreeLine(w)}`));
1229
+ }
1230
+ function readMetroReverses(states, launchesByState, probes) {
1231
+ for (const [i, state] of states.entries()) for (const target of metroReverseTargets(state, launchesByState[i])) {
1232
+ const listing = probes.metroReverses(target.serial);
1233
+ if (listing !== null && !hasMetroReverse(listing, target.metroPort)) addReverseMissingIssue(state, target);
1295
1234
  }
1296
- out.push(chalk.dim(machine?.memorySource === "footprint" ? `\n${cap.liveCount} active environment(s) use ${formatGb(cap.committedMb)} of ${formatGb(cap.totalMemoryMb)}.` : `\n${cap.liveCount} active environment(s), roughly ${formatGb(cap.committedMb)} of ${formatGb(cap.totalMemoryMb)} committed.`));
1297
- const volumes = readVolumes(cwdRoot || process.cwd());
1298
- const line = diskLine(volumes);
1299
- if (line) {
1300
- const tight = tightVolumes(volumes);
1301
- if (tight.length) {
1302
- const which = tight.map((v) => v.volume).join(" and ");
1303
- out.push(chalk.yellow(`${line} A single iOS build can exhaust ${which} -- run \`stim gc\` before starting another environment.`));
1304
- } else out.push(chalk.dim(line));
1305
- }
1306
- if (cap.overCapacity) out.push(chalk.yellow("Over comfortable capacity. A machine that swaps is slower than one working in sequence -- release one before starting another."));
1307
- return out;
1308
- }
1309
- async function watchStatus(json) {
1310
- let last = null;
1311
- let lastPayload = null;
1312
- let archiveStamp = null;
1313
- let archives;
1314
- let snapshot = null;
1315
- let sources = null;
1316
- const measurer = createStatusMeasurer({ updated: () => scheduler.trigger("light") });
1317
- const scheduler = createRefreshScheduler({
1318
- debounceMs: 250,
1319
- lightIntervalMs: WATCH_LIGHT_INTERVAL_MS,
1320
- run: async (kind) => {
1321
- triggerMaintenance("status-watch");
1322
- let text;
1323
- let payload = null;
1324
- try {
1325
- if (kind === "light" && snapshot) await refreshLightFacts(snapshot, json);
1326
- else {
1327
- let stamp = null;
1328
- try {
1329
- stamp = statSync$1(archiveRoot()).mtimeMs;
1330
- } catch {}
1331
- if (archives === void 0 || stamp !== archiveStamp) {
1332
- archives = readArchives();
1333
- archiveStamp = stamp;
1334
- }
1335
- snapshot = await readStatus(WATCH_GIT_MAX_AGE_MS, sources?.simulatorListing(), archives);
1336
- }
1337
- measurer.schedule(snapshot.states, snapshot.worktrees);
1338
- text = renderStatus(snapshot, json, (full) => payload = watchPayload(lastPayload, full)).join("\n");
1339
- } catch (error) {
1340
- console.error(chalk.red(String(error?.message || error)));
1341
- return;
1342
- } finally {
1343
- sources?.reconcile();
1344
- }
1345
- if (text === last) return;
1346
- last = text;
1347
- lastPayload = payload;
1348
- process.stdout.write(`${!json && process.stdout.isTTY ? "\x1B[2J\x1B[H" : ""}${text}\n`);
1349
- }
1350
- });
1351
- const fallback = setInterval(() => scheduler.trigger("full"), WATCH_FALLBACK_MS);
1352
- const machine = setInterval(() => json && snapshot?.machine && scheduler.trigger("light"), WATCH_LIGHT_INTERVAL_MS);
1353
- const finish = () => {
1354
- clearInterval(fallback);
1355
- clearInterval(machine);
1356
- stopReader();
1357
- scheduler.stop();
1358
- sources?.stop();
1359
- process.exit(0);
1360
- };
1361
- const stopReader = watchStdoutReader(finish);
1362
- process.on("SIGINT", finish);
1363
- process.on("SIGTERM", finish);
1364
- sources = watchStatusSources({
1365
- home: getConfigDir(),
1366
- onChange: (kind) => scheduler.trigger(kind)
1367
- });
1368
- scheduler.trigger("full", 0);
1369
- await new Promise(() => {});
1370
- }
1371
- async function readGitInto(worktrees, orphans, maxAgeMs, only) {
1372
- const home = homedir();
1373
- const byPath = await readWorktreeGit(worktrees, {
1374
- maxAgeMs,
1375
- skip: (w) => only !== void 0 && !only.has(w.path) || process.platform === "darwin" && orphans.includes(w) && inPrivacyProtectedFolder(w.path, home)
1376
- });
1377
- for (const worktree of worktrees) worktree.git = byPath.get(worktree.path) ?? null;
1378
- }
1379
- function agentLine({ tool, title, sessionId, lastActiveAt }) {
1380
- const at = lastActiveAt ? `, active ${lastActiveAt}` : "";
1381
- return `${tool === "codex" ? "Codex" : "Claude Code"} ${title ? `"${title}"` : sessionId}${at}`;
1382
- }
1383
- function orphanWorktreeLine(w) {
1384
- return `${w.path}${w.branch ? ` [${w.branch}]` : ""}${w.git ? ` -- ${gitSummaryText(w.git)}` : ""}`;
1385
- }
1386
- function lastBuildsLines(reports) {
1387
- const texts = Object.values(reports ?? {}).map(lastBuildText);
1388
- return texts.length ? [chalk.dim(` last build: ${texts.join(", ")}`)] : [];
1389
- }
1390
- function lastBuildText(report) {
1391
- const source = report.cacheHit ? `${report.cacheHit} cache` : report.status === "ok" ? "compiled" : "no cache hit";
1392
- const took = report.durationMs === null ? "" : ` in ${formatDuration(report.durationMs)}`;
1393
- const placement = report.buildMachine === void 0 ? "" : `; build placement ${report.buildMachine}, built on ${report.builtOn ?? (report.cacheHit ? "none (cache)" : "none")}`;
1394
- return `${report.platform} ${report.status === "ok" ? source : `failed (${report.errorCode ?? "error"}), ${source}`}${took}${placement}`;
1395
- }
1396
- function idleShutdownSuffix(record) {
1397
- return record ? chalk.dim(` -- shut down after ${record.idleMinutes}m idle at ${record.at} (${record.reason === DEVICE_RECLAIM_REASON ? "reclaimed for a waiting run; devices.reclaimIdleMinutes" : "devices.idleShutdownMinutes"})`) : "";
1398
- }
1399
- function activitySuffix(activity) {
1400
- const label = activityLabel(activity, Date.now());
1401
- return label ? ` -- ${activity?.state === "driven" ? chalk.magenta(label) : chalk.dim(label)}` : "";
1402
- }
1403
- function readDeviceProcesses(states, tables, apps) {
1404
- const readActivity = createActivityReader({ tables });
1405
- const readAppProcess = createAppProcessReader(tables);
1406
- for (const [i, state] of states.entries()) {
1407
- const appIdOn = (platform, slot, deviceId) => {
1408
- if (!apps) return void 0;
1409
- const project = apps.projects[i][1];
1410
- const launch = apps.launchesByState[i][deviceSlotKey(platform, slot)];
1411
- return launch?.deviceId === deviceId ? launch.appId : platform === "ios" ? project.bundleId : project.androidPackage;
1412
- };
1413
- for (const device of [{
1414
- slot: "default",
1415
- ios: state.ios,
1416
- android: state.android
1417
- }, ...state.slots ?? []]) {
1418
- const base = {
1419
- slot: device.slot,
1420
- workspace: state.path
1421
- };
1422
- if (device.ios?.state === "Booted") {
1423
- const id = device.ios.udid;
1424
- device.ios.activity = statusActivity(readActivity({
1425
- ...base,
1426
- platform: "ios",
1427
- id
1428
- }));
1429
- const appId = device.ios.owned ? appIdOn("ios", device.slot, id) : void 0;
1430
- if (appId) device.ios.app = readAppProcess({
1431
- platform: "ios",
1432
- id,
1433
- appId
1434
- });
1435
- }
1436
- if (device.android && !device.android.physical && device.android.serial) {
1437
- const id = device.android.serial;
1438
- device.android.activity = statusActivity(readActivity({
1439
- ...base,
1440
- platform: "android",
1441
- id
1442
- }));
1443
- const appId = device.android.owned ? appIdOn("android", device.slot, id) : void 0;
1444
- if (appId) device.android.app = readAppProcess({
1445
- platform: "android",
1446
- id,
1447
- appId
1448
- });
1449
- }
1450
- }
1451
- const web = state.web;
1452
- const port = web?.cdpEndpoint ? Number(new URL(web.cdpEndpoint).port) : null;
1453
- if (web?.running && port) {
1454
- web.page = readWebPage(state.path);
1455
- const ownPids = [web.pid, web.supervisorPid].filter((pid) => pid !== null);
1456
- web.activity = statusActivity(readWebActivity({
1457
- port,
1458
- ownPids,
1459
- workspace: state.path
1460
- }, tables));
1461
- }
1462
- }
1463
- }
1464
- function readMetroReverses(states, launchesByState) {
1465
- for (const [i, state] of states.entries()) for (const target of metroReverseTargets(state, launchesByState[i])) {
1466
- const listing = getExecutor().runFileQuiet("adb", [
1467
- "-s",
1468
- target.serial,
1469
- "reverse",
1470
- "--list"
1471
- ], { timeoutMs: 5e3 });
1472
- if (listing !== null && !hasMetroReverse(listing, target.metroPort)) addReverseMissingIssue(state, target);
1473
- }
1474
- }
1475
- function appSuffix(app) {
1476
- if (!app) return "";
1477
- if (app.state === "running") return chalk.dim(` -- ${app.id} running`);
1478
- if (app.state === "stopped") return ` -- ${chalk.yellow(`${app.id} not running`)}`;
1479
- return chalk.dim(` -- ${app.id} process unknown`);
1480
1235
  }
1481
1236
  function linkedWorktrees(paths) {
1482
- return [...new Set(paths.flatMap((path) => gitCommonDirOnDisk(path) ?? []))].flatMap((common) => {
1483
- const repository = basename$1(common) === ".git" ? dirname$1(common) : common;
1484
- return linkedWorktreesOnDisk(common).map((entry) => Object.assign(entry, { repository }));
1485
- });
1237
+ const commonDirs = [...new Set(paths.flatMap((path) => gitCommonDirOnDisk(path) ?? []))];
1238
+ return {
1239
+ worktrees: commonDirs.flatMap((common) => {
1240
+ const repository = basename$1(common) === ".git" ? dirname$1(common) : common;
1241
+ return linkedWorktreesOnDisk(common).map((entry) => Object.assign(entry, { repository }));
1242
+ }),
1243
+ commonDirs
1244
+ };
1486
1245
  }
1487
1246
  function workspaceBuilds(path, saved, history) {
1488
1247
  const lastBuilds = readLastBuilds(saved);
@@ -1551,21 +1310,15 @@ function readAndroidRuntime(resolveSerial) {
1551
1310
  };
1552
1311
  }
1553
1312
  }
1554
- function readVolumes(projectPath) {
1555
- const roots = [.../* @__PURE__ */ new Set([
1556
- "/",
1557
- volumeRootFor(getConfigDir()),
1558
- volumeRootFor(projectPath)
1559
- ])];
1560
- const volumes = [];
1561
- for (const volume of roots) {
1562
- const disk = parseDfFree(getExecutor().runFileQuiet("df", ["-k", volume], { timeoutMs: 5e3 }));
1563
- if (disk) volumes.push({
1564
- volume,
1565
- disk
1566
- });
1567
- }
1568
- return volumes;
1313
+ async function readMetroFacts(projects) {
1314
+ const ports = await portLookup(projects.flatMap(([, proj]) => proj.metroPort ? [proj.metroPort] : []));
1315
+ return Promise.all(projects.map(async ([path, proj]) => {
1316
+ const metro = proj.metroPort ? await resolveOnPort(proj.metroPort, path, ports) : null;
1317
+ return {
1318
+ metro,
1319
+ supervisor: await supervisorFacts(path, proj, metro, ports)
1320
+ };
1321
+ }));
1569
1322
  }
1570
1323
  async function portLookup(metroPorts) {
1571
1324
  const ports = [...new Set(metroPorts)];
@@ -1626,4 +1379,353 @@ function logFacts(path) {
1626
1379
  }
1627
1380
  }
1628
1381
  //#endregion
1629
- export { statusCommand as default, readVolumes };
1382
+ //#region src/commands/status.ts
1383
+ function iosStatusLines(record, slotLabel) {
1384
+ const out = [];
1385
+ const host = record?.udid ? record.host : void 0;
1386
+ const iosDevices = [record, ...host ? [{
1387
+ host,
1388
+ name: host.device?.name ?? null,
1389
+ udid: "",
1390
+ owned: false,
1391
+ state: host.state ?? "unverified"
1392
+ }] : []];
1393
+ for (const ios of iosDevices) {
1394
+ if (!ios) continue;
1395
+ const booted = ios.state === "Booted" ? chalk.green("booted") : chalk.dim(ios.state.toLowerCase());
1396
+ const owned = ios.owned ? chalk.dim(" (owned)") : "";
1397
+ out.push(` ios${slotLabel}: ${chalk.cyan(iosStatusName(ios))} ${booted}${owned}${activitySuffix(ios.activity)}${appSuffix(ios.app)}${idleShutdownSuffix(ios.idleShutdown)}`);
1398
+ if (!ios.udid && ios.host && "command" in ios.host.agent) out.push(chalk.dim(` agent: ${ios.host.agent.command}`));
1399
+ }
1400
+ return out;
1401
+ }
1402
+ function androidStatusLines(record, slotLabel) {
1403
+ const out = [];
1404
+ if (record?.host && !record.serial) {
1405
+ const host = record.host;
1406
+ out.push(` android${slotLabel}: ${chalk.cyan(`${host.device?.name ?? "Android emulator"} on ${host.machine}${host.selected === "auto" && host.reason ? ` (auto: ${host.reason})` : ""}`)} ${host.state ?? "unverified"}`);
1407
+ } else if (record) {
1408
+ const kind = record.physical ? chalk.dim("(physical)") : chalk.dim("(emulator)");
1409
+ const observed = record.state ? ` ${record.state}${record.serial ? ` (${record.serial})` : ""}` : "";
1410
+ out.push(` android${slotLabel}: ${chalk.cyan(record.name)} ${kind}${observed}${record.owned ? chalk.dim(" (owned)") : ""}${activitySuffix(record.activity)}${appSuffix(record.app)}${idleShutdownSuffix(record.idleShutdown)}`);
1411
+ if (record.host) {
1412
+ const host = record.host;
1413
+ out.push(` android${slotLabel}: ${chalk.cyan(`${host.device?.name ?? "Android emulator"} on ${host.machine}${host.selected === "auto" && host.reason ? ` (auto: ${host.reason})` : ""}`)} ${host.state ?? "unverified"}`);
1414
+ }
1415
+ }
1416
+ if (record?.host && "command" in record.host.agent) out.push(chalk.dim(` agent: ${record.host.agent.command}`));
1417
+ return out;
1418
+ }
1419
+ function formatGb(mb) {
1420
+ return `${(mb / 1024).toFixed(1)} GB`;
1421
+ }
1422
+ function phaseMarker({ phase, live, warmStep }) {
1423
+ if (phase === "warming") return chalk.cyan(` [warming: ${warmStep}]`);
1424
+ if (phase === "ready") return chalk.green(" [ready]");
1425
+ return live ? "" : chalk.dim(" [idle]");
1426
+ }
1427
+ const WATCH_GIT_MAX_AGE_MS = 6e4;
1428
+ function statusCommand(program) {
1429
+ program.command("status").description("Show every environment on this machine: devices, ports, what is actually running, and anything stuck.").option("--json", "print the state as JSON").option("--watch", "keep running and print the state again each time it changes").action(async (opts) => {
1430
+ if (opts.watch) return watchStatus(Boolean(opts.json));
1431
+ const json = Boolean(opts.json);
1432
+ for (const line of renderStatus(await readStatus(), json)) console.log(line);
1433
+ });
1434
+ }
1435
+ function renderStatus({ archived, archivedUsage: usage, projects, states, labelOnlyRoots, leases, leaseNow, orphanWorktrees, simsAvailable, simctlError, cwdRoot, machine }, json, settle = (payload) => payload, cwd = process.cwd()) {
1436
+ const out = [];
1437
+ const totalMemoryMb = Math.round(totalmem() / 1048576);
1438
+ const cap = capacity(states, totalMemoryMb);
1439
+ const pools = ["ios", "android"].map((platform) => {
1440
+ const { max, error } = parkedMaxSetting(platform);
1441
+ return {
1442
+ error,
1443
+ line: poolLine({
1444
+ platform,
1445
+ parked: readParked(platform).length,
1446
+ max
1447
+ })
1448
+ };
1449
+ });
1450
+ const maintenance = maintenanceStatus();
1451
+ if (json) {
1452
+ const payload = {
1453
+ environments: states.map((state, i) => withDerivedFacts(labelOnlyRoots[i] ? {
1454
+ ...state,
1455
+ labelOnly: true
1456
+ } : state)),
1457
+ archived,
1458
+ archivedUsage: usage,
1459
+ capacity: cap,
1460
+ deviceLeases: leases,
1461
+ unprovisionedWorktrees: orphanWorktrees.map(withGitChip),
1462
+ simctlAvailable: simsAvailable,
1463
+ machine,
1464
+ maintenance
1465
+ };
1466
+ out.push(JSON.stringify(settle(payload)));
1467
+ return out;
1468
+ }
1469
+ out.push(...maintenanceLines(maintenance).map((line) => chalk.dim(line)));
1470
+ if (usage.count) out.push(`Archived: ${plural(usage.count, "workspace")}, ${formatBytes(usage.bytes)}`);
1471
+ if (projects.length === 0 && orphanWorktrees.length === 0) {
1472
+ out.push(chalk.dim("No projects registered."));
1473
+ for (const pool of pools) {
1474
+ if (pool.error) out.push(chalk.yellow(`${pool.error} ${POOL_SETTING_REMEDY}`));
1475
+ if (pool.line) out.push(chalk.dim(pool.line));
1476
+ }
1477
+ for (const line of deviceLeaseLines(leases, leaseNow)) out.push(line);
1478
+ return out;
1479
+ }
1480
+ if (!simsAvailable) out.push(chalk.yellow(`simctl could not be read (${simctlError}), so no iOS sim below could be checked.`));
1481
+ for (const [i, [path, proj]] of projects.entries()) {
1482
+ const state = states[i];
1483
+ if (!state) continue;
1484
+ const shortcut = projectShortcut(path, proj);
1485
+ const marker = path === cwdRoot ? chalk.bold.cyan(`* ${shortcut}`) : shortcut;
1486
+ const idle = phaseMarker(state);
1487
+ out.push(`\n${marker}${idle} ${chalk.dim(`(${path})`)}`);
1488
+ out.push(labelOnlyRoots[i] ? chalk.dim(" worktree root (holds the label; the app registers its own entry)") : chalk.dim(` app: ${proj.bundleId ?? "?"} (${proj.isExpo ?? detectIsExpo(path) ? "expo" : "bare"})`));
1489
+ if (state.metro) {
1490
+ const label = state.metro.running ? chalk.green(`running (pid ${state.metro.pid})`) : state.metro.idleStop ? chalk.dim(`stopped (idle) after ${state.metro.idleStop.idleMinutes}m; \`stim start\`, \`ios\` or \`android\` restarts it`) : state.metro.lastStop ? chalk.dim(`not running${state.metro.lastStop.reason === "vanished" ? "" : ` since ${state.metro.lastStop.at}`}; ${describeMetroLastStop(state.metro.lastStop)}`) : chalk.dim("not running");
1491
+ out.push(` metro: port ${state.metro.port} ${label}`);
1492
+ if (state.metro.tunnel) {
1493
+ const { provider, url } = state.metro.tunnel;
1494
+ out.push(` tunnel: ${provider}${provider === "tailscale" ? " (tailnet-only)" : ""} ${url}`);
1495
+ }
1496
+ }
1497
+ if (state.supervisor) {
1498
+ const health = state.supervisor.healthy ? chalk.green("healthy") : chalk.yellow("not answering");
1499
+ const mode = state.supervisor.mode ? chalk.dim(` (${state.supervisor.mode})`) : "";
1500
+ out.push(` supervisor: pid ${state.supervisor.pid}${mode} ${health}`);
1501
+ }
1502
+ if (state.build) {
1503
+ const line = ` ${buildStatusLine(state.build, Date.now())}`;
1504
+ out.push(state.build.state === "running" ? line : chalk.yellow(line));
1505
+ }
1506
+ out.push(...lastBuildsLines(state.lastBuilds));
1507
+ if (state.worktree?.git) out.push(chalk.dim(` git: ${gitSummaryText(state.worktree.git)}`));
1508
+ for (const agent of state.agents ?? []) out.push(chalk.dim(` agent: ${agentLine(agent)}`));
1509
+ if (state.logs) {
1510
+ const n = state.logs.errorsSinceMarker;
1511
+ const errs = n > 0 ? chalk.yellow(` (${n} error${n === 1 ? "" : "s"} since the last marker)`) : "";
1512
+ out.push(chalk.dim(` logs: ${state.logs.dir}`) + errs);
1513
+ }
1514
+ for (const deviceState of [{
1515
+ slot: "default",
1516
+ ios: state.ios,
1517
+ android: state.android
1518
+ }, ...state.slots ?? []]) {
1519
+ const slotLabel = deviceState.slot === "default" ? "" : ` [${deviceState.slot}]`;
1520
+ out.push(...iosStatusLines(deviceState.ios, slotLabel));
1521
+ out.push(...androidStatusLines(deviceState.android, slotLabel));
1522
+ }
1523
+ if (state.macos) {
1524
+ const host = state.macos.host;
1525
+ const where = host ? ` on ${host.machine} as ${host.bundleId}${chalk.dim(` (session ${host.session})`)}` : "";
1526
+ const build = state.macos.build;
1527
+ const placement = build.buildMachine === void 0 ? "" : `; build placement ${build.buildMachine}, built on ${build.builtOn ?? "none"}`;
1528
+ out.push(` macOS ${state.macos.product}: ${state.macos.state}${where}; build ${build.state}${placement}`);
1529
+ if (host && "command" in host.agent) out.push(chalk.dim(` agent: ${host.agent.command}`));
1530
+ }
1531
+ if (state.web) {
1532
+ const browser = state.web.running ? chalk.green(`running (pid ${state.web.pid}, DevTools ${state.web.cdpEndpoint})`) : chalk.dim("not running");
1533
+ const page = state.web.page;
1534
+ const failed = page?.state === "failed" ? ` -- ${chalk.yellow(`page failed: ${page.error}`)}` : "";
1535
+ out.push(` web: ${chalk.cyan(page?.url ?? state.web.url)} ${browser}${state.web.headless ? "" : chalk.dim(" (headed)")}${activitySuffix(state.web.activity)}${failed}`);
1536
+ }
1537
+ for (const device of state.physicalDevices ?? []) out.push(` ${physicalDeviceLine(device, leaseNow)}`);
1538
+ for (const remote of state.remoteDevices ?? []) out.push(` ${remoteDeviceLine(remote)}`);
1539
+ for (const w of state.warnings) out.push(chalk.yellow(` ! ${w}`));
1540
+ for (const note of state.issues.filter((issue) => issue.severity === "info")) out.push(chalk.dim(` - ${note.message}`));
1541
+ }
1542
+ for (const pool of pools) {
1543
+ if (pool.error) out.push(chalk.yellow(`\n${pool.error} ${POOL_SETTING_REMEDY}`));
1544
+ if (pool.line) out.push(chalk.dim(`\n${pool.line}`));
1545
+ }
1546
+ const leaseLines = deviceLeaseLines(leases, leaseNow);
1547
+ if (leaseLines.length) {
1548
+ out.push("");
1549
+ for (const line of leaseLines) out.push(line);
1550
+ }
1551
+ if (orphanWorktrees.length) {
1552
+ out.push(chalk.dim(`\nWorktrees with no environment (${orphanWorktrees.length}):`));
1553
+ for (const w of orphanWorktrees) out.push(chalk.dim(` ${orphanWorktreeLine(w)}`));
1554
+ }
1555
+ out.push(chalk.dim(machine?.memorySource === "footprint" ? `\n${cap.liveCount} active environment(s) use ${formatGb(cap.committedMb)} of ${formatGb(cap.totalMemoryMb)}.` : `\n${cap.liveCount} active environment(s), roughly ${formatGb(cap.committedMb)} of ${formatGb(cap.totalMemoryMb)} committed.`));
1556
+ const volumes = readVolumes(cwdRoot || cwd);
1557
+ const line = diskLine(volumes);
1558
+ if (line) {
1559
+ const tight = tightVolumes(volumes);
1560
+ if (tight.length) {
1561
+ const which = tight.map((v) => v.volume).join(" and ");
1562
+ out.push(chalk.yellow(`${line} A single iOS build can exhaust ${which} -- run \`stim gc\` before starting another environment.`));
1563
+ } else out.push(chalk.dim(line));
1564
+ }
1565
+ if (cap.overCapacity) out.push(chalk.yellow("Over comfortable capacity. A machine that swaps is slower than one working in sequence -- release one before starting another."));
1566
+ return out;
1567
+ }
1568
+ function watchedPids({ roots, states }) {
1569
+ return [...roots.flatMap((root) => [
1570
+ ...root.supervisorPid ? [root.supervisorPid] : [],
1571
+ ...root.build ? [root.build.pid] : [],
1572
+ ...root.browserPids,
1573
+ ...root.macosPids ?? []
1574
+ ]), ...states.flatMap((state) => state.metro?.running && state.metro.pid ? [state.metro.pid] : [])];
1575
+ }
1576
+ /**
1577
+ * Reads status now and again on every change until stopped, and calls `emit` with each new rendering: the JSON payload
1578
+ * with `json`, the human view otherwise. `emit` never sees the same rendering twice in a row. `cwd` stands for the
1579
+ * directory status runs in, which marks the current workspace.
1580
+ */
1581
+ function runStatusWatch({ json, cwd = process.cwd(), emit, failed }) {
1582
+ let last = null;
1583
+ let lastPayload = null;
1584
+ let archiveStamp = null;
1585
+ let archives;
1586
+ let snapshot = null;
1587
+ let sources = null;
1588
+ let tablesAt = 0;
1589
+ let machineDue = false;
1590
+ const measurer = createStatusMeasurer({ updated: () => scheduler.trigger("light") });
1591
+ const scheduler = createRefreshScheduler({
1592
+ debounceMs: 250,
1593
+ lightIntervalMs: WATCH_LIGHT_INTERVAL_MS,
1594
+ run: async (kind) => {
1595
+ triggerMaintenance("status-watch", { warn: false });
1596
+ let text;
1597
+ let payload = null;
1598
+ try {
1599
+ const now = Date.now();
1600
+ if (kind === "light" && snapshot) {
1601
+ const machine = json && machineDue;
1602
+ const tables = machine || now - tablesAt >= 5e3;
1603
+ machineDue = false;
1604
+ await refreshLightFacts(snapshot, {
1605
+ tables,
1606
+ machine
1607
+ });
1608
+ if (tables) tablesAt = now;
1609
+ } else {
1610
+ let stamp = null;
1611
+ try {
1612
+ stamp = statSync$1(archiveRoot()).mtimeMs;
1613
+ } catch {}
1614
+ if (archives === void 0 || stamp !== archiveStamp) {
1615
+ archives = readArchives();
1616
+ archiveStamp = stamp;
1617
+ }
1618
+ const first = snapshot === null;
1619
+ snapshot = await readStatus({
1620
+ git: first ? "none" : "all",
1621
+ cwd,
1622
+ probes: liveProbes({
1623
+ simctlListing: sources?.simulatorListing(),
1624
+ gitMaxAgeMs: WATCH_GIT_MAX_AGE_MS,
1625
+ archives
1626
+ })
1627
+ });
1628
+ tablesAt = now;
1629
+ machineDue = false;
1630
+ sources?.watchRepositories(snapshot.gitCommonDirs);
1631
+ sources?.watchProcesses(watchedPids(snapshot));
1632
+ if (first) scheduler.trigger("full", 0);
1633
+ }
1634
+ measurer.schedule(snapshot.states, snapshot.worktrees);
1635
+ text = renderStatus(snapshot, json, (full) => payload = watchPayload(lastPayload, full), cwd).join("\n");
1636
+ } catch (error) {
1637
+ failed(String(error?.message || error));
1638
+ return;
1639
+ } finally {
1640
+ sources?.reconcile();
1641
+ }
1642
+ const key = json && payload ? watchChangeKey(payload) : text;
1643
+ if (key === last) return;
1644
+ last = key;
1645
+ lastPayload = payload;
1646
+ emit(text);
1647
+ }
1648
+ });
1649
+ const fallback = setInterval(() => scheduler.trigger("full"), WATCH_FALLBACK_MS);
1650
+ const machine = setInterval(() => {
1651
+ if (!json || !snapshot?.machine) return;
1652
+ machineDue = true;
1653
+ scheduler.trigger("light");
1654
+ }, WATCH_MACHINE_INTERVAL_MS);
1655
+ sources = watchStatusSources({
1656
+ home: getConfigDir(),
1657
+ deviceSet: process.platform === "darwin" ? join$1(userInfo().homedir, "Library", "Developer", "CoreSimulator", "Devices") : null,
1658
+ onChange: (kind) => scheduler.trigger(kind)
1659
+ });
1660
+ scheduler.trigger("full", 0);
1661
+ return { stop() {
1662
+ clearInterval(fallback);
1663
+ clearInterval(machine);
1664
+ scheduler.stop();
1665
+ sources?.stop();
1666
+ } };
1667
+ }
1668
+ async function watchStatus(json) {
1669
+ const finish = () => {
1670
+ stopReader();
1671
+ watch.stop();
1672
+ process.exit(0);
1673
+ };
1674
+ process.on("SIGINT", finish);
1675
+ process.on("SIGTERM", finish);
1676
+ const watch = runStatusWatch({
1677
+ json,
1678
+ emit: (text) => process.stdout.write(`${!json && process.stdout.isTTY ? "\x1B[2J\x1B[H" : ""}${text}\n`),
1679
+ failed: (message) => console.error(chalk.red(message))
1680
+ });
1681
+ const stopReader = watchStdoutReader(finish);
1682
+ await new Promise(() => {});
1683
+ }
1684
+ function agentLine({ tool, title, sessionId, lastActiveAt }) {
1685
+ const at = lastActiveAt ? `, active ${lastActiveAt}` : "";
1686
+ return `${tool === "codex" ? "Codex" : "Claude Code"} ${title ? `"${title}"` : sessionId}${at}`;
1687
+ }
1688
+ function orphanWorktreeLine(w) {
1689
+ return `${w.path}${w.branch ? ` [${w.branch}]` : ""}${w.git ? ` -- ${gitSummaryText(w.git)}` : ""}`;
1690
+ }
1691
+ function lastBuildsLines(reports) {
1692
+ const texts = Object.values(reports ?? {}).map(lastBuildText);
1693
+ return texts.length ? [chalk.dim(` last build: ${texts.join(", ")}`)] : [];
1694
+ }
1695
+ function lastBuildText(report) {
1696
+ const source = report.cacheHit ? `${report.cacheHit} cache` : report.status === "ok" ? "compiled" : "no cache hit";
1697
+ const took = report.durationMs === null ? "" : ` in ${formatDuration(report.durationMs)}`;
1698
+ const placement = report.buildMachine === void 0 ? "" : `; build placement ${report.buildMachine}, built on ${report.builtOn ?? (report.cacheHit ? "none (cache)" : "none")}`;
1699
+ return `${report.platform} ${report.status === "ok" ? source : `failed (${report.errorCode ?? "error"}), ${source}`}${took}${placement}`;
1700
+ }
1701
+ function idleShutdownSuffix(record) {
1702
+ return record ? chalk.dim(` -- shut down after ${record.idleMinutes}m idle at ${record.at} (${record.reason === DEVICE_RECLAIM_REASON ? "reclaimed for a waiting run; devices.reclaimIdleMinutes" : "devices.idleShutdownMinutes"})`) : "";
1703
+ }
1704
+ function activitySuffix(activity) {
1705
+ const label = activityLabel(activity, Date.now());
1706
+ return label ? ` -- ${activity?.state === "driven" ? chalk.magenta(label) : chalk.dim(label)}` : "";
1707
+ }
1708
+ function appSuffix(app) {
1709
+ if (!app) return "";
1710
+ if (app.state === "running") return chalk.dim(` -- ${app.id} running`);
1711
+ if (app.state === "stopped") return ` -- ${chalk.yellow(`${app.id} not running`)}`;
1712
+ return chalk.dim(` -- ${app.id} process unknown`);
1713
+ }
1714
+ function readVolumes(projectPath) {
1715
+ const roots = [.../* @__PURE__ */ new Set([
1716
+ "/",
1717
+ volumeRootFor(getConfigDir()),
1718
+ volumeRootFor(projectPath)
1719
+ ])];
1720
+ const volumes = [];
1721
+ for (const volume of roots) {
1722
+ const disk = parseDfFree(getExecutor().runFileQuiet("df", ["-k", volume], { timeoutMs: 5e3 }));
1723
+ if (disk) volumes.push({
1724
+ volume,
1725
+ disk
1726
+ });
1727
+ }
1728
+ return volumes;
1729
+ }
1730
+ //#endregion
1731
+ export { runStatusWatch as n, statusCommand as r, readVolumes as t };