stim 1.20.2 → 1.21.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 (217) hide show
  1. package/README.md +88 -8
  2. package/dist/acquire-artifact-CD4lbiWE.mjs +153 -0
  3. package/dist/act-DHAw2A2S.mjs +2667 -0
  4. package/dist/activity-BzVfHSrY.mjs +1376 -0
  5. package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-zh1vhbLp.mjs} +21 -65
  6. package/dist/{android-HqP1_vB_.mjs → android-BEJ8Jpl7.mjs} +2 -2
  7. package/dist/{android-DCKZrNvV.mjs → android-BLgbNqox.mjs} +128 -78
  8. package/dist/{android-Dlzxshgp.mjs → android-CV_GCELZ.mjs} +5 -5
  9. package/dist/{android-Mz_Inn3w.mjs → android-DUYkNF4u.mjs} +184 -102
  10. package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-Ct5b1xCK.mjs} +7 -6
  11. package/dist/android-cas-compiler.mjs +2 -2
  12. package/dist/android-project-BCAAmMwz.mjs +12 -0
  13. package/dist/api.d.mts +740 -8
  14. package/dist/api.mjs +585 -1
  15. package/dist/{artifact-HSwkIWEQ.mjs → artifact-B8T3S5gi.mjs} +223 -201
  16. package/dist/{artifact-D3czlUvT.mjs → artifact-DAuZ-FNU.mjs} +158 -148
  17. package/dist/{browser-web-CA-F1GQo.mjs → browser-web-QQzVjz3O.mjs} +26 -24
  18. package/dist/budget-Bs6SxxzO.mjs +9154 -0
  19. package/dist/{build-DYDbfkk5.mjs → build-CoPzQRNw.mjs} +144 -96
  20. package/dist/build-cache-DmyR9Zzc.mjs +602 -0
  21. package/dist/build-plan-CaFskB7_.mjs +188 -0
  22. package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DkkqguoK.mjs} +2 -2
  23. package/dist/cache-manifest.mjs +1 -1
  24. package/dist/{ccache-zdKiYQ3E.mjs → ccache-BJRZ9pG3.mjs} +10 -9
  25. package/dist/{cdp-Dq_ypAlJ.mjs → cdp-CWmIUMbw.mjs} +18 -5
  26. package/dist/{chrome-BnzZMqsR.mjs → chrome-B6tfCta1.mjs} +7 -4
  27. package/dist/{cli-CLP3diBm.mjs → cli-0DYf8QhQ.mjs} +20 -20
  28. package/dist/cli.mjs +1 -1
  29. package/dist/client-B7QVOlCr.d.mts +253 -0
  30. package/dist/client-UXD70ZbM.mjs +1406 -0
  31. package/dist/collector-run.d.mts +4 -40
  32. package/dist/collector-run.mjs +9 -8
  33. package/dist/{command-output-BTy8hZ0F.mjs → command-output-B1UrjZHL.mjs} +1 -1
  34. package/dist/config-CYcBF478.mjs +949 -0
  35. package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-CqeBlrEn.mjs} +3 -3
  36. package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-BbKQW83h.mjs} +20 -5
  37. package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-DFRyG1_o.mjs} +1 -1
  38. package/dist/{dev-client-DAWVIGBu.mjs → dev-client-UOeESKm6.mjs} +2 -2
  39. package/dist/device-DCxH7_By.mjs +1068 -0
  40. package/dist/{device-BECOiufl.mjs → device-ExJq8Ei7.mjs} +35 -35
  41. package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-CMlqEcvw.mjs} +43 -13
  42. package/dist/device-host-worker.mjs +65 -61
  43. package/dist/{device-ios-COSi6oS1.mjs → device-ios-DRUeKaFV.mjs} +48 -45
  44. package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-C8raGFoP.mjs} +14 -26
  45. package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-DMRpVX9a.mjs} +5 -5
  46. package/dist/doctor-BLHCYxzi.mjs +2 -0
  47. package/dist/{doctor-kfMBnUw6.mjs → doctor-DTvaDOda.mjs} +281 -317
  48. package/dist/{doctor-CB8oZKCk.mjs → doctor-Dhqebm0q.mjs} +183 -91
  49. package/dist/doctor-fingerprint.mjs +19 -0
  50. package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-Cv1F10Kj.mjs} +40 -21
  51. package/dist/{eas-build-JyfqyHfC.mjs → eas-build-BomfRnFT.mjs} +53 -20
  52. package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-DJwZpy0c.mjs} +26 -208
  53. package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-op6A54yi.mjs} +229 -11
  54. package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-Bf0rZvG9.mjs} +172 -82
  55. package/dist/exec-H20xSg2T.d.mts +65 -0
  56. package/dist/exec-_UbtCQcG.mjs +750 -0
  57. package/dist/gc-C-WwL0yi.mjs +3 -0
  58. package/dist/{gc-qWOMdnER.mjs → gc-_-dCXdyL.mjs} +584 -796
  59. package/dist/git-C3iTsJaZ.mjs +73 -0
  60. package/dist/{guide-G9cAbVAc.mjs → guide-Yqwt2bd6.mjs} +941 -269
  61. package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-Bw-honsd.mjs} +8 -6
  62. package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DB_gBPfY.mjs} +34 -19
  63. package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CUvOf4Vr.mjs} +1 -1
  64. package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-DL_P5AdN.mjs} +77 -43
  65. package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-QI141yKk.mjs} +21 -17
  66. package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-Ksyjgzq-.mjs} +30 -21
  67. package/dist/idle-BVeRGroT.d.mts +24 -0
  68. package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DaKmZi0z.mjs} +11 -10
  69. package/dist/{ios-BwVCF7oA.mjs → ios-CQ68hG9s.mjs} +8 -8
  70. package/dist/{ios-RkW4pnQf.mjs → ios-CpByZy12.mjs} +140 -80
  71. package/dist/{ios-device-B5veSDDQ.mjs → ios-device-CXGP1bsD.mjs} +1 -1
  72. package/dist/{ios-device-D7pi2Sca.mjs → ios-device-CwFMehUS.mjs} +51 -26
  73. package/dist/{ios-project-K9hY_Jab.mjs → ios-project-WuwwBdvW.mjs} +13 -13
  74. package/dist/{ios-nOLJGVdy.mjs → ios-qNJt4dFm.mjs} +1 -1
  75. package/dist/ios-signing-DTTIChGs.mjs +489 -0
  76. package/dist/{ios-state-CBLe1xYw.mjs → ios-state-DvFX-K_l.mjs} +1 -1
  77. package/dist/{ios-Ce7bc7br.mjs → ios-ubFsBzwq.mjs} +129 -86
  78. package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Cc1dttps.mjs} +53 -26
  79. package/dist/{launch-F4sOqAhB.mjs → launch-CD1yVc7U.mjs} +91 -90
  80. package/dist/{launch-C3qJ6Agb.mjs → launch-Zq2mOSDy.mjs} +82 -541
  81. package/dist/logs-BS00Anxf.mjs +352 -0
  82. package/dist/logs-CMm05HxN.mjs +255 -0
  83. package/dist/{macos-D7uDvO-z.mjs → macos-B65--pPd.mjs} +1 -1
  84. package/dist/{macos-Ch5VJmcS.mjs → macos-C-0qJ6zq.mjs} +225 -212
  85. package/dist/macos-run.mjs +1 -1
  86. package/dist/maintenance-run.mjs +122 -247
  87. package/dist/{metro-DnCEjCxs.mjs → metro-DEXpIhHC.mjs} +67 -12
  88. package/dist/{metro-gateway-CX9Xlkq2.mjs → metro-gateway-BMJNlj3E.mjs} +20 -12
  89. package/dist/{named-ports-4WopRPg-.mjs → named-ports-BWTzt6mu.mjs} +8 -63
  90. package/dist/native-android-JACyjTZs.mjs +844 -0
  91. package/dist/{native-gradle-inputs-BsLRrl7u.mjs → native-gradle-inputs-Bep9JcSF.mjs} +128 -140
  92. package/dist/native-inputs-TRTTTRxt.mjs +91 -0
  93. package/dist/native-run-DY_RLx3C.mjs +277 -0
  94. package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-Dg1Q7tfF.mjs} +9 -8
  95. package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-CB2iQeWq.mjs} +27 -18
  96. package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-CXX39F7o.mjs} +96 -47
  97. package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
  98. package/dist/offload-worker.d.mts +1 -46
  99. package/dist/offload-worker.mjs +197 -66
  100. package/dist/{ownership-DCtw_2IA.mjs → ownership-DEmM5vhh.mjs} +3 -3
  101. package/dist/{page-DRHy329N.mjs → page-CPaHeYqj.mjs} +7 -4
  102. package/dist/paths-BsJMoPP2.mjs +12 -0
  103. package/dist/paths-DQtTgsBf.mjs +42 -0
  104. package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BqGbTa61.mjs} +5 -5
  105. package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-Bwj-IjY1.mjs} +6 -6
  106. package/dist/{ports-DdSUicVo.mjs → ports-D-MmCTdv.mjs} +3 -3
  107. package/dist/prebuild-uD_ipCxF.mjs +449 -0
  108. package/dist/{project-_phNIJfs.mjs → project-BZNjmW_8.mjs} +65 -37
  109. package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-Lfetn8Kr.mjs} +2 -2
  110. package/dist/pull-request-zjCSAryH.d.mts +120 -0
  111. package/dist/pull-requests.d.mts +1 -119
  112. package/dist/pull-requests.mjs +1 -1
  113. package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-DuzH0cn3.mjs} +74 -48
  114. package/dist/{gradle-DSrXb6lG.mjs → react-native-build-rhk4smwQ.mjs} +292 -15
  115. package/dist/react-native-doctor-CQpuIMso.mjs +234 -0
  116. package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-Bhq1rJeV.mjs} +46 -28
  117. package/dist/{recordings-D0d5aQt0.mjs → recordings-DYteQSu4.mjs} +12 -9
  118. package/dist/{reload-C8JhxjSh.mjs → reload-CmTRFJaX.mjs} +93 -47
  119. package/dist/reload-DzjSl5P_.mjs +2 -0
  120. package/dist/{remote-BiR6aYjy.mjs → remote-ByYkXdGD.mjs} +15 -10
  121. package/dist/result-DNiS-tTP.mjs +434 -0
  122. package/dist/{run-BtPgpKks.mjs → run-D23HmJMs.mjs} +4 -5
  123. package/dist/selection-CSl9i5qU.mjs +619 -0
  124. package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CxTrvDg8.mjs} +3 -4
  125. package/dist/{server-command-CTtCkmcQ.mjs → server-command-CtzloH3v.mjs} +14 -7
  126. package/dist/server-expo-C-90EhcG.mjs +2 -0
  127. package/dist/{server-expo-DsguMGUF.mjs → server-expo-DT_F_uVI.mjs} +50 -9
  128. package/dist/{settings-B717odTD.mjs → settings-CsJDEXgK.mjs} +234 -24
  129. package/dist/{settings-vk3mJGSm.d.mts → settings-DkdmlelE.d.mts} +6 -4
  130. package/dist/settings-T1gtc3bf.mjs +114 -0
  131. package/dist/settings-write-HyVZ8eQ8.mjs +359 -0
  132. package/dist/settings.schema.json +163 -16
  133. package/dist/{simslim-CCr3rE-A.mjs → simslim-Cgk17SXV.mjs} +14 -12
  134. package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-DF8VfT64.mjs} +15 -20
  135. package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
  136. package/dist/stage-BIS0ydsV.mjs +183 -0
  137. package/dist/{start-BWqzODpb.mjs → start-7lpH7hmN.mjs} +63 -44
  138. package/dist/{start-TXeMmmO2.mjs → start-RChynRDp.mjs} +1 -1
  139. package/dist/{state-D1Icyjlu.mjs → state-C4ZtUisW.mjs} +40 -13
  140. package/dist/{state-CG_OFoaA.mjs → state-XMziexv2.mjs} +3 -2
  141. package/dist/{stats-BoY5sEPU.mjs → stats-53T7OTb9.mjs} +7 -13
  142. package/dist/stats-report-BFfMpWWF.mjs +16 -0
  143. package/dist/{status-WgFbkRzj.mjs → status-BL7jVyAB.mjs} +535 -447
  144. package/dist/status-CSi6tlRq.mjs +2 -0
  145. package/dist/{status-BTA7kKiQ.mjs → status-DqEUSSxs.mjs} +6 -4
  146. package/dist/{status-watch-C23ILtf9.mjs → status-watch-GDCfqpTE.mjs} +187 -22
  147. package/dist/status-worker.d.mts +1 -0
  148. package/dist/status-worker.mjs +19 -0
  149. package/dist/stim-desktop-C12we7lz.mjs +112 -0
  150. package/dist/{stop-DR6VoDIk.mjs → stop-Bk_1qiV6.mjs} +2 -2
  151. package/dist/{stop-BNmBMi1F.mjs → stop-CPzlM1L-.mjs} +138 -98
  152. package/dist/{stop-DPEhunlw.mjs → stop-D7h6jAXQ.mjs} +11 -10
  153. package/dist/supervisor-run.d.mts +8 -17
  154. package/dist/supervisor-run.mjs +63 -27
  155. package/dist/{support-DMTqj3Hm.mjs → support-67vraa1Q.mjs} +18 -11
  156. package/dist/{support-CwjbFs9H.mjs → support-Dlu37g6H.mjs} +12 -12
  157. package/dist/{swiftpm-macos-DRNVJWlb.mjs → swiftpm-macos-p8WZbxKU.mjs} +35 -24
  158. package/dist/toolchain-DhKwp9iI.mjs +2 -0
  159. package/dist/toolchain-Hp9sCpK4.mjs +873 -0
  160. package/dist/{trigger-CigAYjeL.mjs → trigger-BAahxUPq.mjs} +20 -5
  161. package/dist/trigger-Bf3uDcpv.mjs +2 -0
  162. package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-BHX5r0Ei.mjs} +250 -156
  163. package/dist/{web-BDBMxDpx.mjs → web-CJmIj6AI.mjs} +18 -13
  164. package/dist/web-DknQETPs.mjs +2 -0
  165. package/dist/web-run.mjs +11 -12
  166. package/dist/windows-report.d.mts +1 -0
  167. package/dist/windows-report.mjs +18 -0
  168. package/dist/windows-report.ps1 +43 -0
  169. package/dist/workspace-process-lock-1_1OoVW5.mjs +57 -0
  170. package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-Cjuigeeu.mjs} +62 -58
  171. package/dist/{workspaces-C36s2jb9.mjs → workspaces-BccMFmGQ.mjs} +1188 -1079
  172. package/dist/worktree-CK2MpJW5.mjs +2 -0
  173. package/dist/{worktree-CgvJYJ-Q.mjs → worktree-DQ6Zi2Mv.mjs} +304 -53
  174. package/dist/xcode-Zlx3qjEs.mjs +896 -0
  175. package/package.json +7 -5
  176. package/shim/android-optimizations.gradle +7 -5
  177. package/dist/activity-BSV745Kz.mjs +0 -629
  178. package/dist/api-qvOzWyfO.mjs +0 -154
  179. package/dist/api-run.mjs +0 -294
  180. package/dist/app-install-BIKtMfPq.mjs +0 -896
  181. package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
  182. package/dist/budget-f7516Zk0.mjs +0 -4106
  183. package/dist/build-facts-DcLv2HSd.d.mts +0 -111
  184. package/dist/cancellation-C_22VQTH.mjs +0 -24
  185. package/dist/client-qQAaXSUs.mjs +0 -1771
  186. package/dist/config-BYDxlMY3.mjs +0 -562
  187. package/dist/device-DuiPJQSn.mjs +0 -290
  188. package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
  189. package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
  190. package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
  191. package/dist/exec-DqKo9GKJ.mjs +0 -268
  192. package/dist/git-DDfFzkMm.mjs +0 -45
  193. package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
  194. package/dist/logs-BGrEUaEs.mjs +0 -383
  195. package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
  196. package/dist/native-android-D5qc3-_v.mjs +0 -226
  197. package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
  198. package/dist/plan-C4TjdPsR.mjs +0 -260
  199. package/dist/prebuild-DYbucPXy.mjs +0 -212
  200. package/dist/preview-78a9kR_-.mjs +0 -1011
  201. package/dist/react-native-build-CtCccJtb.mjs +0 -239
  202. package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
  203. package/dist/remote-cache-OyOyVIS3.mjs +0 -526
  204. package/dist/result-CaJg5Iat.mjs +0 -186
  205. package/dist/server-expo-Bigriskl.mjs +0 -2
  206. package/dist/settings-BORNaaCO.mjs +0 -402
  207. package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
  208. package/dist/stage-KNTQopqv.mjs +0 -157
  209. package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
  210. package/dist/tailnet-Dh-qiYzG.mjs +0 -265
  211. package/dist/toolchain-BFkAcstd.mjs +0 -2
  212. package/dist/toolchain-DxSsNssu.mjs +0 -1657
  213. package/dist/trigger-9_USgmxz.mjs +0 -2
  214. package/dist/web-Dq-i3wzJ.mjs +0 -2
  215. package/dist/worktree-DpLdCHga.mjs +0 -2
  216. package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
  217. 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 { p as process_identity_exports, t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
+ import { m as workspaceLogsDir$1, p as workspaceLogErrorIndex } from "./paths-DQtTgsBf.mjs";
3
+ import { H as deviceSlotKey, K as projectDeviceSlots, P as formatBytes, W as parseDeviceSlotKey, _ as loadConfig$1, d as getConfigDir, z as volumeRootFor } from "./config-CYcBF478.mjs";
4
+ import { a as formatElapsed, i as formatDuration, r as clockTime, u as plural } from "./command-output-B1UrjZHL.mjs";
5
+ import { r as readWorkspaceState$1 } from "./workspace-state-Cjuigeeu.mjs";
6
+ import { Dt as linkedWorktreesOnDisk, Ft as repoRoot, Y as resolveSettings, bt as gitCommonDirOnDisk, ot as workspaceHiddenSetting, vt as gitCommonDir } from "./settings-CsJDEXgK.mjs";
7
+ import { n as gitAsync } from "./git-C3iTsJaZ.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-BZNjmW_8.mjs";
9
+ import { a as parseNdjsonLine } from "./ndjson-CgE_o3Dl.mjs";
10
+ import { a as listeningPids, d as processCwds, f as resolveProjectMetro, g as isMetroRunning, l as pidExists, s as listeningPidsByPort, u as processCwd } from "./metro-DEXpIhHC.mjs";
11
+ import { a as readWebPage, o as readWebRecord, u as webFacts } from "./state-C4ZtUisW.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-op6A54yi.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-Bs6SxxzO.mjs";
14
+ import { m as resolveSupervisorTarget } from "./workspaces-BccMFmGQ.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-BzVfHSrY.mjs";
16
+ import { H as ownedAvdSerialResolver, R as ownedAvdDeviceProfile, gt as readParked, ht as parkedMaxSetting, k as listAdbDevices, lt as POOL_SETTING_REMEDY } from "./android-DUYkNF4u.mjs";
17
+ import { b as parseSimctlList, f as listAllIosSimsAsync } from "./ios-CpByZy12.mjs";
18
+ import { f as probeHostedSession } from "./hosted-client-DB_gBPfY.mjs";
19
+ import "./hosted-macos-QI141yKk.mjs";
20
+ import { i as readSupervisorState } from "./stop-CPzlM1L-.mjs";
21
+ import { n as maintenanceLines, r as maintenanceStatus } from "./status-DqEUSSxs.mjs";
22
+ import { f as mergeState, i as createStatusMeasurer, n as workspacePhase, r as applyStatusMeasures } from "./warm-progress-BHX5r0Ei.mjs";
23
+ import { r as workspaceRecordingEnabled } from "./recordings-DYteQSu4.mjs";
24
+ import { d as readIosDevices, s as isReachable } from "./ios-device-CwFMehUS.mjs";
25
+ import { t as triggerMaintenance } from "./trigger-BAahxUPq.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-GDCfqpTE.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";
@@ -778,31 +776,11 @@ function physicalDeviceLine(device, now) {
778
776
  return `${device.platform}${slot}: ${name} (physical${model}) ${device.connection} -- leased until ${clockTime(device.lease.expiresAt)} (${remaining} left)`;
779
777
  }
780
778
  //#endregion
781
- //#region src/commands/status.ts
782
- const WATCH_GIT_MAX_AGE_MS = 6e4;
779
+ //#region src/status-read.ts
783
780
  function iosStatusName(ios) {
784
781
  const host = ios.host;
785
782
  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
783
  }
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
784
  function applyHostedAndroidStates(state, saved, factsBySlot) {
807
785
  for (const [slot, record] of Object.entries(hostedAndroidRecords(saved))) if (!parseHostedAndroidPlacement(record)) state.warnings.push(unreadableHostedAndroid(slot));
808
786
  for (const [slot, facts] of Object.entries(factsBySlot)) {
@@ -828,23 +806,6 @@ function applyHostedAndroidStates(state, saved, factsBySlot) {
828
806
  state.live ||= facts.android.state === "ready";
829
807
  }
830
808
  }
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
809
  function doctorRunTimes(proj) {
849
810
  const runs = {};
850
811
  for (const platform of ["ios", "android"]) {
@@ -853,48 +814,55 @@ function doctorRunTimes(proj) {
853
814
  }
854
815
  return Object.keys(runs).length ? runs : void 0;
855
816
  }
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
- });
817
+ /**
818
+ * Probes that read everything when asked. `simctlListing`, when given, answers `simulators` without running simctl,
819
+ * `gitMaxAgeMs` reuses git summaries read that recently, and `archives` answers `archives` without reading them.
820
+ */
821
+ function liveProbes({ simctlListing = null, gitMaxAgeMs = 0, archives } = {}) {
822
+ return {
823
+ simulators: () => simctlListing === null ? listAllIosSimsAsync() : Promise.resolve().then(() => parseSimctlList(simctlListing)),
824
+ metro: readMetroFacts,
825
+ hostedIos: readHostedIosStatus,
826
+ hostedAndroid: readHostedAndroidStatus,
827
+ hostedMacos: readHostedMacosStatus,
828
+ git: (worktrees, skip) => readWorktreeGit(worktrees, {
829
+ maxAgeMs: gitMaxAgeMs,
830
+ skip
831
+ }),
832
+ androidRuntime: androidRuntimeReader(),
833
+ physicalDevice: physicalDeviceReader(),
834
+ deviceTables: createDeviceProcessTables,
835
+ metroReverses: (serial) => getExecutor().runFileQuiet("adb", [
836
+ "-s",
837
+ serial,
838
+ "reverse",
839
+ "--list"
840
+ ], { timeoutMs: 5e3 }),
841
+ footprints: readFootprints,
842
+ archives: () => archives ?? readArchives()
843
+ };
865
844
  }
866
- function readStatus(gitMaxAgeMs, simctlListing = null, archives) {
867
- return withStateReadCache(() => readStatusFacts(gitMaxAgeMs, simctlListing, archives));
845
+ /**
846
+ * Reads the status of every environment. With `git: 'all'` it reads the git summary of every worktree before
847
+ * composing; with `'live'` only those of live environments, after composing; with `'none'` no git summary.
848
+ */
849
+ function readStatus({ probes = liveProbes(), git = "live", cwd = process.cwd() } = {}) {
850
+ return withStateReadCache(() => readStatusFacts(probes, git, cwd));
868
851
  }
869
- async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
852
+ async function readStatusFacts(probes, gitScope, cwd) {
870
853
  const cfg = loadConfig$1();
871
854
  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)]);
855
+ const iosReads = projects.map(([path]) => probes.hostedIos(hostedIosPlacements(readWorkspaceState$1(path))));
856
+ const androidReads = projects.map(([path]) => probes.hostedAndroid(hostedAndroidPlacements(readWorkspaceState$1(path))));
857
+ const macosReads = projects.map(([path]) => probes.hostedMacos(readMacosRecord(path)));
858
+ const cwdRoot = findServerWorkspace(cwd)?.root ?? null;
859
+ const { worktrees, commonDirs } = linkedWorktrees([cwd, ...projects.map(([path]) => path)]);
877
860
  const orphanWorktrees = unprovisionedWorktrees(worktrees, projects.map(([p]) => p));
878
- const simsRead = simctlListing === null ? listAllIosSimsAsync() : Promise.resolve().then(() => parseSimctlList(simctlListing));
861
+ const simsRead = probes.simulators();
879
862
  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
- }));
863
+ const processes = probes.metro(projects);
888
864
  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
- }));
865
+ const gitRead = gitScope === "all" ? readGitInto(probes, worktrees, orphanWorktrees) : null;
898
866
  const logs = projects.map(([path]) => logFacts(path));
899
867
  const simsByUdid = {};
900
868
  let simsAvailable = true;
@@ -906,6 +874,12 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
906
874
  simctlError = String(e?.message || e).split("\n")[0] ?? "";
907
875
  }
908
876
  const running = await processes;
877
+ const devices = projects.map(([, proj]) => ({
878
+ androidRuntimes: Object.fromEntries(projectDeviceSlots(proj).slice(1).map(({ slot, platforms }) => [slot, platforms.android?.owned && platforms.android.avdName ? probes.androidRuntime(platforms.android.avdName) : null])),
879
+ androidRuntime: proj.platforms?.android?.owned && proj.platforms.android.avdName ? probes.androidRuntime(proj.platforms.android.avdName) : null,
880
+ androidDeviceProfiles: Object.fromEntries(projectDeviceSlots(proj).slice(1).map(({ slot, platforms }) => [slot, platforms.android?.owned && platforms.android.avdName ? ownedAvdDeviceProfile(platforms.android.avdName) : null])),
881
+ androidDeviceProfile: proj.platforms?.android?.owned && proj.platforms.android.avdName ? ownedAvdDeviceProfile(proj.platforms.android.avdName) : null
882
+ }));
909
883
  await gitRead;
910
884
  const history = readStats$1().record?.history;
911
885
  const states = [];
@@ -919,7 +893,6 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
919
893
  now: leaseNow
920
894
  });
921
895
  const roots = [];
922
- const readPhysicalDevice = physicalDeviceReader();
923
896
  const simulatorUdids = new Set([...Object.keys(simsByUdid), ...projects.flatMap(([, proj]) => projectDeviceSlots(proj).flatMap(({ platforms }) => platforms.ios?.deviceUdid ?? []))].map((udid) => udid.toUpperCase()));
924
897
  for (const [i, [path, proj]] of projects.entries()) {
925
898
  const { metro, supervisor } = running[i];
@@ -1024,20 +997,20 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
1024
997
  root: path,
1025
998
  now: leaseNow,
1026
999
  simulatorUdids,
1027
- read: readPhysicalDevice
1000
+ read: (platform, id) => probes.physicalDevice(platform, id)
1028
1001
  });
1029
1002
  if (state && physicalDevices.length) state.physicalDevices = physicalDevices;
1030
1003
  labelOnlyRoots.push(Boolean(proj.worktreeRoot && !proj.bundleId && !state?.metro && !state?.ios && !state?.android && !state?.web && !state?.macos));
1031
1004
  }
1032
- if (!watching) await readGitInto(worktrees, orphanWorktrees, gitMaxAgeMs, new Set(states.flatMap((state) => state.live && state.worktree ? [state.worktree.path] : [])));
1005
+ if (gitScope === "live") await readGitInto(probes, worktrees, orphanWorktrees, new Set(states.flatMap((state) => state.live && state.worktree ? [state.worktree.path] : [])));
1033
1006
  applyStatusMeasures(states, worktrees);
1034
1007
  readLogDerivedFacts(states);
1035
- const tables = createDeviceProcessTables();
1008
+ const tables = probes.deviceTables();
1036
1009
  readDeviceProcesses(states, tables, {
1037
1010
  projects,
1038
1011
  launchesByState
1039
1012
  });
1040
- readMetroReverses(states, launchesByState);
1013
+ readMetroReverses(states, launchesByState, probes);
1041
1014
  const sims = Object.values(simsByUdid);
1042
1015
  const simNames = Object.fromEntries(sims.map((sim) => [sim.udid.toUpperCase(), sim.name]));
1043
1016
  const machine = await readMachineUsage({
@@ -1045,9 +1018,10 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
1045
1018
  roots,
1046
1019
  simNames,
1047
1020
  tables,
1048
- busy: sims.some((sim) => sim.state === "Booted")
1021
+ busy: sims.some((sim) => sim.state === "Booted"),
1022
+ probes
1049
1023
  });
1050
- const archives = cachedArchives ?? readArchives();
1024
+ const archives = probes.archives();
1051
1025
  const maxCount = machineNumber("archive.maxCount", cfg, process.env);
1052
1026
  return {
1053
1027
  archived: linkReplacedArchives(archives.slice(0, maxCount.value ?? 200), states.map((state) => state.path)),
@@ -1065,7 +1039,9 @@ async function readStatusFacts(gitMaxAgeMs, simctlListing, cachedArchives) {
1065
1039
  tables,
1066
1040
  machine,
1067
1041
  roots,
1068
- simNames
1042
+ simNames,
1043
+ probes,
1044
+ gitCommonDirs: commonDirs
1069
1045
  };
1070
1046
  }
1071
1047
  /** Sets the facts status derives from workspace logs, the running build's record and its detail file. */
@@ -1120,11 +1096,6 @@ function readLogDerivedFacts(states) {
1120
1096
  }
1121
1097
  }
1122
1098
  }
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
1099
  function browserPids(web) {
1129
1100
  if (!web) return [];
1130
1101
  const chrome = web.record.chromeProcess?.pid;
@@ -1136,10 +1107,10 @@ function browserPids(web) {
1136
1107
  * `memoryMb` from them. Reads both only when a simulator is booted, a workspace is live or a build runs, so an idle
1137
1108
  * machine runs no `ps` and keeps the estimate.
1138
1109
  */
1139
- async function readMachineUsage({ states, roots, simNames, tables, busy }) {
1110
+ async function readMachineUsage({ states, roots, simNames, tables, busy, probes }) {
1140
1111
  const processes = busy || states.some((state) => state.live || state.build?.state === "running") ? tables.host() : null;
1141
1112
  if (!processes) return null;
1142
- const footprints = await readFootprints();
1113
+ const footprints = await probes.footprints();
1143
1114
  const machine = attributeMachineUsage({
1144
1115
  processes,
1145
1116
  footprints,
@@ -1151,338 +1122,112 @@ async function readMachineUsage({ states, roots, simNames, tables, busy }) {
1151
1122
  return machine;
1152
1123
  }
1153
1124
  /**
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.
1125
+ * Rereads the log-derived facts and the cached measures. With `tables` it also rereads the process tables and the
1126
+ * device activity they show; with `machine` as well, and when the snapshot measured machine usage, the host process
1127
+ * table and machine usage. It reuses every other subprocess fact of the full read.
1156
1128
  */
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
- };
1129
+ async function refreshLightFacts(snapshot, { tables, machine }) {
1130
+ if (tables) {
1131
+ const fresh = snapshot.probes.deviceTables();
1132
+ snapshot.tables = {
1133
+ host: machine && snapshot.machine ? fresh.host : snapshot.tables.host,
1134
+ android: snapshot.tables.android,
1135
+ tcpConnections: fresh.tcpConnections,
1136
+ clients: fresh.host
1137
+ };
1138
+ }
1165
1139
  withStateReadCache(() => {
1166
1140
  for (const state of snapshot.states) state.logs = logFacts(state.path);
1167
1141
  applyStatusMeasures(snapshot.states, snapshot.worktrees);
1168
1142
  readLogDerivedFacts(snapshot.states);
1169
- readDeviceProcesses(snapshot.states, snapshot.tables, null);
1143
+ if (tables) readDeviceProcesses(snapshot.states, snapshot.tables, null);
1170
1144
  });
1171
1145
  if (machine && snapshot.machine) snapshot.machine = await readMachineUsage({
1172
1146
  ...snapshot,
1173
1147
  busy: true
1174
1148
  });
1175
1149
  }
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
1150
+ async function readGitInto(probes, worktrees, orphans, only) {
1151
+ const home = homedir();
1152
+ const byPath = await probes.git(worktrees, (w) => only !== void 0 && !only.has(w.path) || process.platform === "darwin" && orphans.includes(w) && inPrivacyProtectedFolder(w.path, home));
1153
+ for (const worktree of worktrees) worktree.git = byPath.get(worktree.path) ?? null;
1154
+ }
1155
+ function readDeviceProcesses(states, tables, apps) {
1156
+ const readActivity = createActivityReader({ tables });
1157
+ const readAppProcess = createAppProcessReader(tables);
1158
+ for (const [i, state] of states.entries()) {
1159
+ const appIdOn = (platform, slot, deviceId) => {
1160
+ if (!apps) return void 0;
1161
+ const project = apps.projects[i][1];
1162
+ const launch = apps.launchesByState[i][deviceSlotKey(platform, slot)];
1163
+ return launch?.deviceId === deviceId ? launch.appId : platform === "ios" ? project.bundleId : project.androidPackage;
1206
1164
  };
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 [{
1165
+ for (const device of [{
1256
1166
  slot: "default",
1257
1167
  ios: state.ios,
1258
1168
  android: state.android
1259
1169
  }, ...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}`));
1170
+ const base = {
1171
+ slot: device.slot,
1172
+ workspace: state.path
1173
+ };
1174
+ if (device.ios?.state === "Booted") {
1175
+ const id = device.ios.udid;
1176
+ device.ios.activity = statusActivity(readActivity({
1177
+ ...base,
1178
+ platform: "ios",
1179
+ id
1180
+ }));
1181
+ const appId = device.ios.owned ? appIdOn("ios", device.slot, id) : void 0;
1182
+ if (appId) device.ios.app = readAppProcess({
1183
+ platform: "ios",
1184
+ id,
1185
+ appId
1186
+ });
1187
+ }
1188
+ if (device.android && !device.android.physical && device.android.serial) {
1189
+ const id = device.android.serial;
1190
+ device.android.activity = statusActivity(readActivity({
1191
+ ...base,
1192
+ platform: "android",
1193
+ id
1194
+ }));
1195
+ const appId = device.android.owned ? appIdOn("android", device.slot, id) : void 0;
1196
+ if (appId) device.android.app = readAppProcess({
1197
+ platform: "android",
1198
+ id,
1199
+ appId
1200
+ });
1201
+ }
1271
1202
  }
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}`);
1203
+ const web = state.web;
1204
+ const port = web?.cdpEndpoint ? Number(new URL(web.cdpEndpoint).port) : null;
1205
+ if (web?.running && port) {
1206
+ web.page = readWebPage(state.path);
1207
+ const ownPids = [web.pid, web.supervisorPid].filter((pid) => pid !== null);
1208
+ web.activity = statusActivity(readWebActivity({
1209
+ port,
1210
+ ownPids,
1211
+ workspace: state.path
1212
+ }, tables));
1277
1213
  }
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
1214
  }
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)}`));
1215
+ }
1216
+ function readMetroReverses(states, launchesByState, probes) {
1217
+ for (const [i, state] of states.entries()) for (const target of metroReverseTargets(state, launchesByState[i])) {
1218
+ const listing = probes.metroReverses(target.serial);
1219
+ if (listing !== null && !hasMetroReverse(listing, target.metroPort)) addReverseMissingIssue(state, target);
1295
1220
  }
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
1221
  }
1481
1222
  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
- });
1223
+ const commonDirs = [...new Set(paths.flatMap((path) => gitCommonDirOnDisk(path) ?? []))];
1224
+ return {
1225
+ worktrees: commonDirs.flatMap((common) => {
1226
+ const repository = basename$1(common) === ".git" ? dirname$1(common) : common;
1227
+ return linkedWorktreesOnDisk(common).map((entry) => Object.assign(entry, { repository }));
1228
+ }),
1229
+ commonDirs
1230
+ };
1486
1231
  }
1487
1232
  function workspaceBuilds(path, saved, history) {
1488
1233
  const lastBuilds = readLastBuilds(saved);
@@ -1551,21 +1296,15 @@ function readAndroidRuntime(resolveSerial) {
1551
1296
  };
1552
1297
  }
1553
1298
  }
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;
1299
+ async function readMetroFacts(projects) {
1300
+ const ports = await portLookup(projects.flatMap(([, proj]) => proj.metroPort ? [proj.metroPort] : []));
1301
+ return Promise.all(projects.map(async ([path, proj]) => {
1302
+ const metro = proj.metroPort ? await resolveOnPort(proj.metroPort, path, ports) : null;
1303
+ return {
1304
+ metro,
1305
+ supervisor: await supervisorFacts(path, proj, metro, ports)
1306
+ };
1307
+ }));
1569
1308
  }
1570
1309
  async function portLookup(metroPorts) {
1571
1310
  const ports = [...new Set(metroPorts)];
@@ -1626,4 +1365,353 @@ function logFacts(path) {
1626
1365
  }
1627
1366
  }
1628
1367
  //#endregion
1629
- export { statusCommand as default, readVolumes };
1368
+ //#region src/commands/status.ts
1369
+ function iosStatusLines(record, slotLabel) {
1370
+ const out = [];
1371
+ const host = record?.udid ? record.host : void 0;
1372
+ const iosDevices = [record, ...host ? [{
1373
+ host,
1374
+ name: host.device?.name ?? null,
1375
+ udid: "",
1376
+ owned: false,
1377
+ state: host.state ?? "unverified"
1378
+ }] : []];
1379
+ for (const ios of iosDevices) {
1380
+ if (!ios) continue;
1381
+ const booted = ios.state === "Booted" ? chalk.green("booted") : chalk.dim(ios.state.toLowerCase());
1382
+ const owned = ios.owned ? chalk.dim(" (owned)") : "";
1383
+ out.push(` ios${slotLabel}: ${chalk.cyan(iosStatusName(ios))} ${booted}${owned}${activitySuffix(ios.activity)}${appSuffix(ios.app)}${idleShutdownSuffix(ios.idleShutdown)}`);
1384
+ if (!ios.udid && ios.host && "command" in ios.host.agent) out.push(chalk.dim(` agent: ${ios.host.agent.command}`));
1385
+ }
1386
+ return out;
1387
+ }
1388
+ function androidStatusLines(record, slotLabel) {
1389
+ const out = [];
1390
+ if (record?.host && !record.serial) {
1391
+ const host = record.host;
1392
+ 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"}`);
1393
+ } else if (record) {
1394
+ const kind = record.physical ? chalk.dim("(physical)") : chalk.dim("(emulator)");
1395
+ const observed = record.state ? ` ${record.state}${record.serial ? ` (${record.serial})` : ""}` : "";
1396
+ out.push(` android${slotLabel}: ${chalk.cyan(record.name)} ${kind}${observed}${record.owned ? chalk.dim(" (owned)") : ""}${activitySuffix(record.activity)}${appSuffix(record.app)}${idleShutdownSuffix(record.idleShutdown)}`);
1397
+ if (record.host) {
1398
+ const host = record.host;
1399
+ 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"}`);
1400
+ }
1401
+ }
1402
+ if (record?.host && "command" in record.host.agent) out.push(chalk.dim(` agent: ${record.host.agent.command}`));
1403
+ return out;
1404
+ }
1405
+ function formatGb(mb) {
1406
+ return `${(mb / 1024).toFixed(1)} GB`;
1407
+ }
1408
+ function phaseMarker({ phase, live, warmStep }) {
1409
+ if (phase === "warming") return chalk.cyan(` [warming: ${warmStep}]`);
1410
+ if (phase === "ready") return chalk.green(" [ready]");
1411
+ return live ? "" : chalk.dim(" [idle]");
1412
+ }
1413
+ const WATCH_GIT_MAX_AGE_MS = 6e4;
1414
+ function statusCommand(program) {
1415
+ 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) => {
1416
+ if (opts.watch) return watchStatus(Boolean(opts.json));
1417
+ const json = Boolean(opts.json);
1418
+ for (const line of renderStatus(await readStatus(), json)) console.log(line);
1419
+ });
1420
+ }
1421
+ function renderStatus({ archived, archivedUsage: usage, projects, states, labelOnlyRoots, leases, leaseNow, orphanWorktrees, simsAvailable, simctlError, cwdRoot, machine }, json, settle = (payload) => payload, cwd = process.cwd()) {
1422
+ const out = [];
1423
+ const totalMemoryMb = Math.round(totalmem() / 1048576);
1424
+ const cap = capacity(states, totalMemoryMb);
1425
+ const pools = ["ios", "android"].map((platform) => {
1426
+ const { max, error } = parkedMaxSetting(platform);
1427
+ return {
1428
+ error,
1429
+ line: poolLine({
1430
+ platform,
1431
+ parked: readParked(platform).length,
1432
+ max
1433
+ })
1434
+ };
1435
+ });
1436
+ const maintenance = maintenanceStatus();
1437
+ if (json) {
1438
+ const payload = {
1439
+ environments: states.map((state, i) => withDerivedFacts(labelOnlyRoots[i] ? {
1440
+ ...state,
1441
+ labelOnly: true
1442
+ } : state)),
1443
+ archived,
1444
+ archivedUsage: usage,
1445
+ capacity: cap,
1446
+ deviceLeases: leases,
1447
+ unprovisionedWorktrees: orphanWorktrees.map(withGitChip),
1448
+ simctlAvailable: simsAvailable,
1449
+ machine,
1450
+ maintenance
1451
+ };
1452
+ out.push(JSON.stringify(settle(payload)));
1453
+ return out;
1454
+ }
1455
+ out.push(...maintenanceLines(maintenance).map((line) => chalk.dim(line)));
1456
+ if (usage.count) out.push(`Archived: ${plural(usage.count, "workspace")}, ${formatBytes(usage.bytes)}`);
1457
+ if (projects.length === 0 && orphanWorktrees.length === 0) {
1458
+ out.push(chalk.dim("No projects registered."));
1459
+ for (const pool of pools) {
1460
+ if (pool.error) out.push(chalk.yellow(`${pool.error} ${POOL_SETTING_REMEDY}`));
1461
+ if (pool.line) out.push(chalk.dim(pool.line));
1462
+ }
1463
+ for (const line of deviceLeaseLines(leases, leaseNow)) out.push(line);
1464
+ return out;
1465
+ }
1466
+ if (!simsAvailable) out.push(chalk.yellow(`simctl could not be read (${simctlError}), so no iOS sim below could be checked.`));
1467
+ for (const [i, [path, proj]] of projects.entries()) {
1468
+ const state = states[i];
1469
+ if (!state) continue;
1470
+ const shortcut = projectShortcut(path, proj);
1471
+ const marker = path === cwdRoot ? chalk.bold.cyan(`* ${shortcut}`) : shortcut;
1472
+ const idle = phaseMarker(state);
1473
+ out.push(`\n${marker}${idle} ${chalk.dim(`(${path})`)}`);
1474
+ 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"})`));
1475
+ if (state.metro) {
1476
+ 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");
1477
+ out.push(` metro: port ${state.metro.port} ${label}`);
1478
+ if (state.metro.tunnel) {
1479
+ const { provider, url } = state.metro.tunnel;
1480
+ out.push(` tunnel: ${provider}${provider === "tailscale" ? " (tailnet-only)" : ""} ${url}`);
1481
+ }
1482
+ }
1483
+ if (state.supervisor) {
1484
+ const health = state.supervisor.healthy ? chalk.green("healthy") : chalk.yellow("not answering");
1485
+ const mode = state.supervisor.mode ? chalk.dim(` (${state.supervisor.mode})`) : "";
1486
+ out.push(` supervisor: pid ${state.supervisor.pid}${mode} ${health}`);
1487
+ }
1488
+ if (state.build) {
1489
+ const line = ` ${buildStatusLine(state.build, Date.now())}`;
1490
+ out.push(state.build.state === "running" ? line : chalk.yellow(line));
1491
+ }
1492
+ out.push(...lastBuildsLines(state.lastBuilds));
1493
+ if (state.worktree?.git) out.push(chalk.dim(` git: ${gitSummaryText(state.worktree.git)}`));
1494
+ for (const agent of state.agents ?? []) out.push(chalk.dim(` agent: ${agentLine(agent)}`));
1495
+ if (state.logs) {
1496
+ const n = state.logs.errorsSinceMarker;
1497
+ const errs = n > 0 ? chalk.yellow(` (${n} error${n === 1 ? "" : "s"} since the last marker)`) : "";
1498
+ out.push(chalk.dim(` logs: ${state.logs.dir}`) + errs);
1499
+ }
1500
+ for (const deviceState of [{
1501
+ slot: "default",
1502
+ ios: state.ios,
1503
+ android: state.android
1504
+ }, ...state.slots ?? []]) {
1505
+ const slotLabel = deviceState.slot === "default" ? "" : ` [${deviceState.slot}]`;
1506
+ out.push(...iosStatusLines(deviceState.ios, slotLabel));
1507
+ out.push(...androidStatusLines(deviceState.android, slotLabel));
1508
+ }
1509
+ if (state.macos) {
1510
+ const host = state.macos.host;
1511
+ const where = host ? ` on ${host.machine} as ${host.bundleId}${chalk.dim(` (session ${host.session})`)}` : "";
1512
+ const build = state.macos.build;
1513
+ const placement = build.buildMachine === void 0 ? "" : `; build placement ${build.buildMachine}, built on ${build.builtOn ?? "none"}`;
1514
+ out.push(` macOS ${state.macos.product}: ${state.macos.state}${where}; build ${build.state}${placement}`);
1515
+ if (host && "command" in host.agent) out.push(chalk.dim(` agent: ${host.agent.command}`));
1516
+ }
1517
+ if (state.web) {
1518
+ const browser = state.web.running ? chalk.green(`running (pid ${state.web.pid}, DevTools ${state.web.cdpEndpoint})`) : chalk.dim("not running");
1519
+ const page = state.web.page;
1520
+ const failed = page?.state === "failed" ? ` -- ${chalk.yellow(`page failed: ${page.error}`)}` : "";
1521
+ out.push(` web: ${chalk.cyan(page?.url ?? state.web.url)} ${browser}${state.web.headless ? "" : chalk.dim(" (headed)")}${activitySuffix(state.web.activity)}${failed}`);
1522
+ }
1523
+ for (const device of state.physicalDevices ?? []) out.push(` ${physicalDeviceLine(device, leaseNow)}`);
1524
+ for (const remote of state.remoteDevices ?? []) out.push(` ${remoteDeviceLine(remote)}`);
1525
+ for (const w of state.warnings) out.push(chalk.yellow(` ! ${w}`));
1526
+ for (const note of state.issues.filter((issue) => issue.severity === "info")) out.push(chalk.dim(` - ${note.message}`));
1527
+ }
1528
+ for (const pool of pools) {
1529
+ if (pool.error) out.push(chalk.yellow(`\n${pool.error} ${POOL_SETTING_REMEDY}`));
1530
+ if (pool.line) out.push(chalk.dim(`\n${pool.line}`));
1531
+ }
1532
+ const leaseLines = deviceLeaseLines(leases, leaseNow);
1533
+ if (leaseLines.length) {
1534
+ out.push("");
1535
+ for (const line of leaseLines) out.push(line);
1536
+ }
1537
+ if (orphanWorktrees.length) {
1538
+ out.push(chalk.dim(`\nWorktrees with no environment (${orphanWorktrees.length}):`));
1539
+ for (const w of orphanWorktrees) out.push(chalk.dim(` ${orphanWorktreeLine(w)}`));
1540
+ }
1541
+ 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.`));
1542
+ const volumes = readVolumes(cwdRoot || cwd);
1543
+ const line = diskLine(volumes);
1544
+ if (line) {
1545
+ const tight = tightVolumes(volumes);
1546
+ if (tight.length) {
1547
+ const which = tight.map((v) => v.volume).join(" and ");
1548
+ out.push(chalk.yellow(`${line} A single iOS build can exhaust ${which} -- run \`stim gc\` before starting another environment.`));
1549
+ } else out.push(chalk.dim(line));
1550
+ }
1551
+ 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."));
1552
+ return out;
1553
+ }
1554
+ function watchedPids({ roots, states }) {
1555
+ return [...roots.flatMap((root) => [
1556
+ ...root.supervisorPid ? [root.supervisorPid] : [],
1557
+ ...root.build ? [root.build.pid] : [],
1558
+ ...root.browserPids,
1559
+ ...root.macosPids ?? []
1560
+ ]), ...states.flatMap((state) => state.metro?.running && state.metro.pid ? [state.metro.pid] : [])];
1561
+ }
1562
+ /**
1563
+ * Reads status now and again on every change until stopped, and calls `emit` with each new rendering: the JSON payload
1564
+ * with `json`, the human view otherwise. `emit` never sees the same rendering twice in a row. `cwd` stands for the
1565
+ * directory status runs in, which marks the current workspace.
1566
+ */
1567
+ function runStatusWatch({ json, cwd = process.cwd(), emit, failed }) {
1568
+ let last = null;
1569
+ let lastPayload = null;
1570
+ let archiveStamp = null;
1571
+ let archives;
1572
+ let snapshot = null;
1573
+ let sources = null;
1574
+ let tablesAt = 0;
1575
+ let machineDue = false;
1576
+ const measurer = createStatusMeasurer({ updated: () => scheduler.trigger("light") });
1577
+ const scheduler = createRefreshScheduler({
1578
+ debounceMs: 250,
1579
+ lightIntervalMs: WATCH_LIGHT_INTERVAL_MS,
1580
+ run: async (kind) => {
1581
+ triggerMaintenance("status-watch", { warn: false });
1582
+ let text;
1583
+ let payload = null;
1584
+ try {
1585
+ const now = Date.now();
1586
+ if (kind === "light" && snapshot) {
1587
+ const machine = json && machineDue;
1588
+ const tables = machine || now - tablesAt >= 5e3;
1589
+ machineDue = false;
1590
+ await refreshLightFacts(snapshot, {
1591
+ tables,
1592
+ machine
1593
+ });
1594
+ if (tables) tablesAt = now;
1595
+ } else {
1596
+ let stamp = null;
1597
+ try {
1598
+ stamp = statSync$1(archiveRoot()).mtimeMs;
1599
+ } catch {}
1600
+ if (archives === void 0 || stamp !== archiveStamp) {
1601
+ archives = readArchives();
1602
+ archiveStamp = stamp;
1603
+ }
1604
+ const first = snapshot === null;
1605
+ snapshot = await readStatus({
1606
+ git: first ? "none" : "all",
1607
+ cwd,
1608
+ probes: liveProbes({
1609
+ simctlListing: sources?.simulatorListing(),
1610
+ gitMaxAgeMs: WATCH_GIT_MAX_AGE_MS,
1611
+ archives
1612
+ })
1613
+ });
1614
+ tablesAt = now;
1615
+ machineDue = false;
1616
+ sources?.watchRepositories(snapshot.gitCommonDirs);
1617
+ sources?.watchProcesses(watchedPids(snapshot));
1618
+ if (first) scheduler.trigger("full", 0);
1619
+ }
1620
+ measurer.schedule(snapshot.states, snapshot.worktrees);
1621
+ text = renderStatus(snapshot, json, (full) => payload = watchPayload(lastPayload, full), cwd).join("\n");
1622
+ } catch (error) {
1623
+ failed(String(error?.message || error));
1624
+ return;
1625
+ } finally {
1626
+ sources?.reconcile();
1627
+ }
1628
+ const key = json && payload ? watchChangeKey(payload) : text;
1629
+ if (key === last) return;
1630
+ last = key;
1631
+ lastPayload = payload;
1632
+ emit(text);
1633
+ }
1634
+ });
1635
+ const fallback = setInterval(() => scheduler.trigger("full"), WATCH_FALLBACK_MS);
1636
+ const machine = setInterval(() => {
1637
+ if (!json || !snapshot?.machine) return;
1638
+ machineDue = true;
1639
+ scheduler.trigger("light");
1640
+ }, WATCH_MACHINE_INTERVAL_MS);
1641
+ sources = watchStatusSources({
1642
+ home: getConfigDir(),
1643
+ deviceSet: process.platform === "darwin" ? join$1(userInfo().homedir, "Library", "Developer", "CoreSimulator", "Devices") : null,
1644
+ onChange: (kind) => scheduler.trigger(kind)
1645
+ });
1646
+ scheduler.trigger("full", 0);
1647
+ return { stop() {
1648
+ clearInterval(fallback);
1649
+ clearInterval(machine);
1650
+ scheduler.stop();
1651
+ sources?.stop();
1652
+ } };
1653
+ }
1654
+ async function watchStatus(json) {
1655
+ const finish = () => {
1656
+ stopReader();
1657
+ watch.stop();
1658
+ process.exit(0);
1659
+ };
1660
+ process.on("SIGINT", finish);
1661
+ process.on("SIGTERM", finish);
1662
+ const watch = runStatusWatch({
1663
+ json,
1664
+ emit: (text) => process.stdout.write(`${!json && process.stdout.isTTY ? "\x1B[2J\x1B[H" : ""}${text}\n`),
1665
+ failed: (message) => console.error(chalk.red(message))
1666
+ });
1667
+ const stopReader = watchStdoutReader(finish);
1668
+ await new Promise(() => {});
1669
+ }
1670
+ function agentLine({ tool, title, sessionId, lastActiveAt }) {
1671
+ const at = lastActiveAt ? `, active ${lastActiveAt}` : "";
1672
+ return `${tool === "codex" ? "Codex" : "Claude Code"} ${title ? `"${title}"` : sessionId}${at}`;
1673
+ }
1674
+ function orphanWorktreeLine(w) {
1675
+ return `${w.path}${w.branch ? ` [${w.branch}]` : ""}${w.git ? ` -- ${gitSummaryText(w.git)}` : ""}`;
1676
+ }
1677
+ function lastBuildsLines(reports) {
1678
+ const texts = Object.values(reports ?? {}).map(lastBuildText);
1679
+ return texts.length ? [chalk.dim(` last build: ${texts.join(", ")}`)] : [];
1680
+ }
1681
+ function lastBuildText(report) {
1682
+ const source = report.cacheHit ? `${report.cacheHit} cache` : report.status === "ok" ? "compiled" : "no cache hit";
1683
+ const took = report.durationMs === null ? "" : ` in ${formatDuration(report.durationMs)}`;
1684
+ const placement = report.buildMachine === void 0 ? "" : `; build placement ${report.buildMachine}, built on ${report.builtOn ?? (report.cacheHit ? "none (cache)" : "none")}`;
1685
+ return `${report.platform} ${report.status === "ok" ? source : `failed (${report.errorCode ?? "error"}), ${source}`}${took}${placement}`;
1686
+ }
1687
+ function idleShutdownSuffix(record) {
1688
+ 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"})`) : "";
1689
+ }
1690
+ function activitySuffix(activity) {
1691
+ const label = activityLabel(activity, Date.now());
1692
+ return label ? ` -- ${activity?.state === "driven" ? chalk.magenta(label) : chalk.dim(label)}` : "";
1693
+ }
1694
+ function appSuffix(app) {
1695
+ if (!app) return "";
1696
+ if (app.state === "running") return chalk.dim(` -- ${app.id} running`);
1697
+ if (app.state === "stopped") return ` -- ${chalk.yellow(`${app.id} not running`)}`;
1698
+ return chalk.dim(` -- ${app.id} process unknown`);
1699
+ }
1700
+ function readVolumes(projectPath) {
1701
+ const roots = [.../* @__PURE__ */ new Set([
1702
+ "/",
1703
+ volumeRootFor(getConfigDir()),
1704
+ volumeRootFor(projectPath)
1705
+ ])];
1706
+ const volumes = [];
1707
+ for (const volume of roots) {
1708
+ const disk = parseDfFree(getExecutor().runFileQuiet("df", ["-k", volume], { timeoutMs: 5e3 }));
1709
+ if (disk) volumes.push({
1710
+ volume,
1711
+ disk
1712
+ });
1713
+ }
1714
+ return volumes;
1715
+ }
1716
+ //#endregion
1717
+ export { runStatusWatch as n, statusCommand as r, readVolumes as t };