stim 1.17.2 → 1.18.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 (150) hide show
  1. package/README.md +50 -1
  2. package/dist/{activity-IRvJY_ru.mjs → activity-BxnkDZDi.mjs} +4 -4
  3. package/dist/{agent-device-usage-output-BK41vnzN.mjs → agent-device-usage-output-CZ66YA4T.mjs} +8 -8
  4. package/dist/android-BKA16DTf.mjs +4 -0
  5. package/dist/{android-B9yaNKwa.mjs → android-BvwuMUJ9.mjs} +192 -98
  6. package/dist/{android-DE4v59Mb.mjs → android-CBwCNicO.mjs} +2 -2
  7. package/dist/{android-B_YNZy61.mjs → android-DC3ZLuw0.mjs} +9 -9
  8. package/dist/{android-cas-ZFpjJBL_.mjs → android-cas-BBFyr9CA.mjs} +5 -5
  9. package/dist/android-cas-compiler.mjs +2 -2
  10. package/dist/api-D0VtFhqk.mjs +152 -0
  11. package/dist/api-run.d.mts +1 -0
  12. package/dist/api-run.mjs +145 -0
  13. package/dist/api.d.mts +212 -0
  14. package/dist/api.mjs +2 -0
  15. package/dist/{app-install-VPkI5WEg.mjs → app-install-D-PUENug.mjs} +3 -3
  16. package/dist/{attempt-Bk2ouQVL.mjs → attempt-DW-mQqM7.mjs} +14 -4
  17. package/dist/{budget-DfcgFdQB.mjs → budget-DIhL2BKx.mjs} +1578 -58
  18. package/dist/build-facts-DcLv2HSd.d.mts +111 -0
  19. package/dist/{cache-manifest-DnUHBJaU.mjs → cache-manifest-BI7ozfmH.mjs} +3 -3
  20. package/dist/cache-manifest.mjs +1 -1
  21. package/dist/{chrome-BrcVWQyD.mjs → chrome-DJnmnS5q.mjs} +1 -1
  22. package/dist/cli-DNJMwADx.mjs +68 -0
  23. package/dist/cli.mjs +1 -1
  24. package/dist/{client-SvBdgObD.mjs → client-DzhapoMB.mjs} +139 -32
  25. package/dist/collector-run.mjs +9 -9
  26. package/dist/{command-output-CDAIFD-8.mjs → command-output-CBtzyIgF.mjs} +2 -2
  27. package/dist/{config-D0DbpZtM.mjs → config-CgYMahz7.mjs} +5 -5
  28. package/dist/{created-devices-CpvzBL25.mjs → created-devices-DKbeWsiK.mjs} +2 -2
  29. package/dist/{dependency-state-CLcBHH2M.mjs → dependency-state-xKoOypBm.mjs} +2 -2
  30. package/dist/{detached-entry-CiTEgMR1.mjs → detached-entry-BLfcgc4O.mjs} +1 -1
  31. package/dist/{dev-client-B-XC4uRH.mjs → dev-client-CLnIH02x.mjs} +2 -2
  32. package/dist/{device-C8IOoJPv.mjs → device-D7oCHGWi.mjs} +8 -8
  33. package/dist/{device-capacity-ZC4XSZ4R.mjs → device-capacity-EUOOYr8T.mjs} +13 -13
  34. package/dist/device-host-worker.mjs +19 -19
  35. package/dist/{device-ios-C2Um-XUR.mjs → device-ios-6MewKKnc.mjs} +13 -13
  36. package/dist/{device-lease-DpoS36_u.mjs → device-lease-Co-EwifR.mjs} +9 -9
  37. package/dist/{device-lease-run-B8YltIH_.mjs → device-lease-run-w1xhCqIW.mjs} +4 -4
  38. package/dist/{device-pool-3o7s5lo4.mjs → device-pool-F5WvRPtD.mjs} +3 -3
  39. package/dist/{device-remote-hFSkpfQu.mjs → device-remote-tHbd1fKy.mjs} +15 -15
  40. package/dist/{doctor-CFv1fCrF.mjs → doctor-B9ckYUoU.mjs} +33 -30
  41. package/dist/{error-diagnostics-C-NMnhrk.mjs → error-diagnostics-BRXOqDzG.mjs} +11 -11
  42. package/dist/{exec-CaErVv7t.mjs → exec-DWhCZDGm.mjs} +65 -2
  43. package/dist/{gc-DEmkg3Xh.mjs → gc-Dh6mXOKC.mjs} +23 -469
  44. package/dist/{gradle-dJpre3Yn.mjs → gradle-C6GKnunQ.mjs} +6 -6
  45. package/dist/{guide-status-Du-ZQ3FD.mjs → guide-status-Bhf9SJXc.mjs} +3 -3
  46. package/dist/{guide-CSmhMTf8.mjs → guide-tm6igAaa.mjs} +290 -53
  47. package/dist/{hosted-android-E1Heoqnv.mjs → hosted-android-Bv285t_t.mjs} +3 -3
  48. package/dist/{hosted-client-Bp4knSwu.mjs → hosted-client-C-rMtppF.mjs} +2 -2
  49. package/dist/{hosted-ios-BnbeYOUD.mjs → hosted-ios-D5mNmtj4.mjs} +1 -1
  50. package/dist/{hosted-logs-OcgIBvCT.mjs → hosted-logs-DN8Iz4mJ.mjs} +9 -9
  51. package/dist/{hosted-macos-DcxKjtfH.mjs → hosted-macos-B-wEjlwG.mjs} +5 -5
  52. package/dist/{hosted-native-1Ebbig4w.mjs → hosted-native-DeeOG8xZ.mjs} +6 -6
  53. package/dist/{idle-shutdown-IGyNV8Cr.mjs → idle-shutdown-jjtxAn5C.mjs} +7 -8
  54. package/dist/{ios-DSfnPfse.mjs → ios-B3SbOWdw.mjs} +19 -7
  55. package/dist/{ios-Cr1h5gnO.mjs → ios-Bvbf0SGY.mjs} +1 -1
  56. package/dist/{ios-BJ4XUSe1.mjs → ios-CPdkoKaa.mjs} +181 -95
  57. package/dist/ios-DNpdygiv.mjs +7 -0
  58. package/dist/{ios-device-Ee7sDXfp.mjs → ios-device-Bn7jWDB1.mjs} +1 -1
  59. package/dist/{ios-device-pAN4t54-.mjs → ios-device-vOaByMhw.mjs} +3 -3
  60. package/dist/{ios-state-8L3lgum6.mjs → ios-state-B2pES6Vs.mjs} +1 -1
  61. package/dist/{launch-verify-lTnWZikR.mjs → launch-verify-hskNcWkZ.mjs} +5 -5
  62. package/dist/{logs-BAaS7gS2.mjs → logs-1Ylc1Ri6.mjs} +13 -13
  63. package/dist/macos-Ck7OBMNY.mjs +2 -0
  64. package/dist/{macos-BIRQS90f.mjs → macos-DF6C7wUU.mjs} +118 -34
  65. package/dist/macos-run.mjs +1 -1
  66. package/dist/maintenance-run.mjs +349 -47
  67. package/dist/{metro-g8NqiJp-.mjs → metro-Dh8T4Ytd.mjs} +5 -5
  68. package/dist/{metro-gateway-C-ijGI2F.mjs → metro-gateway-CEUw9RMH.mjs} +4 -4
  69. package/dist/{metro-store-CDDZHtPl.mjs → metro-store-BAHFcJm6.mjs} +16 -2
  70. package/dist/{named-ports-C8m8EQs2.mjs → named-ports-BFIz1Shz.mjs} +61 -6
  71. package/dist/{native-run-D1Q56rAD.mjs → native-run-B06FkmZx.mjs} +4 -4
  72. package/dist/{native-runtime-BEK171xQ.mjs → native-runtime-D_603JiC.mjs} +6 -6
  73. package/dist/{ndjson-PclOIwVY.mjs → ndjson-LGZAMsqa.mjs} +8 -4
  74. package/dist/offload-worker.d.mts +3 -17
  75. package/dist/offload-worker.mjs +10 -11
  76. package/dist/{ownership-DyRQru0q.mjs → ownership-D6Se7gg_.mjs} +3 -3
  77. package/dist/{page-QF_Ke10s.mjs → page-Bv9s2KwY.mjs} +1 -1
  78. package/dist/placement-log-BcPhRwR4.mjs +84 -0
  79. package/dist/{build-plan-BDsSi09V.mjs → plan-placement-CtxkCO54.mjs} +122 -48
  80. package/dist/{ports-4nYqxPWC.mjs → ports-BLTtfBq-.mjs} +3 -3
  81. package/dist/{prebuild-D7RUMkwN.mjs → prebuild-juCyreaR.mjs} +5 -5
  82. package/dist/preview-D5V07Nrl.mjs +987 -0
  83. package/dist/{rolldown-runtime-BsOwBuO_.mjs → process-identity-Biv3arCO.mjs} +11 -1
  84. package/dist/{project-D47Rh0ly.mjs → project-C3ChRLZy.mjs} +4 -68
  85. package/dist/projects-DD7dBTCj.mjs +92 -0
  86. package/dist/{pull-request-pxnDCQzn.mjs → pull-request-u4vp7zmK.mjs} +1 -1
  87. package/dist/pull-requests.mjs +1 -1
  88. package/dist/{recordings-BNgsD1Tr.mjs → recordings-BAWltsVt.mjs} +1 -1
  89. package/dist/{reload-DcRxj3qG.mjs → reload-DvyWzVjJ.mjs} +15 -15
  90. package/dist/{remote-cache-Ci4DQYYj.mjs → remote-cache-BGg7aGIZ.mjs} +5 -5
  91. package/dist/{run-CkE9y0nc.mjs → run-vhtDgpHO.mjs} +5 -5
  92. package/dist/{server-bare-BkrSxSsZ.mjs → server-bare-B9E7S1aR.mjs} +4 -5
  93. package/dist/server-expo-Db9HBUoa.mjs +2 -0
  94. package/dist/{server-expo-CHTyXD0G.mjs → server-expo-DoBHhuzK.mjs} +5 -6
  95. package/dist/{settings-SR9OmW9h.mjs → settings-Byp2AQ_E.mjs} +6 -5
  96. package/dist/{settings-Cfd-0r2d.mjs → settings-CQyMElEP.mjs} +24 -763
  97. package/dist/{settings-BBpMcDbD.mjs → settings-Djl-mpjX.mjs} +1 -1
  98. package/dist/settings.schema.json +126 -3
  99. package/dist/{simslim-BWNrc3M3.mjs → simslim-EHBQ2R4G.mjs} +7 -7
  100. package/dist/{slot-launch-DmjBmpQV.mjs → slot-launch-C1nqh4mu.mjs} +6 -6
  101. package/dist/{spawn-claims-D0XfSe8u.mjs → spawn-claims-Kqiifsk2.mjs} +1 -1
  102. package/dist/{spawn-entry-jw19m8Nl.mjs → spawn-entry-Dcb7sDUz.mjs} +1 -0
  103. package/dist/{stage-CzaiwFsI.mjs → stage-g_WqWeaE.mjs} +14 -3
  104. package/dist/{start-DUz3mYdb.mjs → start-D-IeOyoK.mjs} +19 -19
  105. package/dist/{start-AlfCPRVU.mjs → start-NTc1Ifqs.mjs} +1 -1
  106. package/dist/{state-PeQiJuIu.mjs → state-BG-aAk4k.mjs} +4 -4
  107. package/dist/{state-B4PQFXMW.d.mts → state-lKh8shBp.d.mts} +2 -3
  108. package/dist/{state-DyaNTgfR.mjs → state-xnqpx3AD.mjs} +2 -2
  109. package/dist/{stats-Bq4fJOdB.mjs → stats-DY6ekz8F.mjs} +5 -5
  110. package/dist/{status-DlKvVJBE.mjs → status-BEeL6IKz.mjs} +6 -4
  111. package/dist/{status-BA2pehwf.mjs → status-DCjZeE-K.mjs} +33 -34
  112. package/dist/{status-CzS4bPO9.mjs → status-Dcr0Qexd.mjs} +5 -5
  113. package/dist/{stim-desktop-Cnz8CPnl.mjs → stim-desktop-Behws_fi.mjs} +1 -1
  114. package/dist/{stim-installations-QMEI32v1.mjs → stim-installations-aR_WsNOA.mjs} +1 -1
  115. package/dist/{stop-BIiM49EY.mjs → stop-BGhKMOuH.mjs} +5 -5
  116. package/dist/{stop-DQIasgKp.mjs → stop-BTjs3xbc.mjs} +17 -18
  117. package/dist/{stop-zF1y04f2.mjs → stop-DIJtD2GL.mjs} +2 -2
  118. package/dist/supervisor-run.d.mts +24 -22
  119. package/dist/supervisor-run.mjs +21 -22
  120. package/dist/{support-CsJNVfOc.mjs → support-BaayeYCf.mjs} +7 -7
  121. package/dist/{support-WvD__tSV.mjs → support-Bwvbrq5-.mjs} +5 -5
  122. package/dist/{toolchain-DNyR3NPq.mjs → toolchain-Bnyd_K3A.mjs} +471 -22
  123. package/dist/{trigger-Bemu8ytw.mjs → trigger-CJMhwXe8.mjs} +5 -5
  124. package/dist/trigger-DWAq9hkw.mjs +2 -0
  125. package/dist/{warm-progress-DF4JRvYI.mjs → warm-progress-CjB-MP6H.mjs} +7 -7
  126. package/dist/web-B6_bFDn7.mjs +2 -0
  127. package/dist/{web-Dl0KSRHf.mjs → web-DTU0uiWj.mjs} +22 -22
  128. package/dist/web-run.mjs +10 -10
  129. package/dist/{workspace-state-DqcCbpE7.mjs → workspace-state-C59dqG-Z.mjs} +3 -3
  130. package/dist/{ownership-BMLqyBgJ.mjs → workspaces-xXItD8Dj.mjs} +577 -23
  131. package/dist/{worktree-j3IcFAI5.mjs → worktree-BJfnU6r5.mjs} +1 -1
  132. package/dist/{worktree-Be_7NLKy.mjs → worktree-BSYlofkq.mjs} +234 -35
  133. package/dist/worktree-CsKYexJM.mjs +753 -0
  134. package/package.json +10 -5
  135. package/dist/build-progress-D0WkjCPd.mjs +0 -1036
  136. package/dist/build-slots-41v_d2x9.mjs +0 -142
  137. package/dist/cli-CYXb29oE.mjs +0 -51
  138. package/dist/deps-iKw0eD4P.mjs +0 -438
  139. package/dist/errors-B6W7FkxQ.mjs +0 -15
  140. package/dist/idle-BXG__1BA.mjs +0 -176
  141. package/dist/in-use-CvGOUn-x.mjs +0 -130
  142. package/dist/preview-B-g9d7kV.mjs +0 -318
  143. package/dist/process-identity-BmRm1qV0.mjs +0 -12
  144. package/dist/server-expo-CeakhI8P.mjs +0 -2
  145. package/dist/state-BKa8wNN5.mjs +0 -148
  146. package/dist/stop-cause-rhmGfwvt.mjs +0 -97
  147. package/dist/trigger-CXts6qt1.mjs +0 -2
  148. package/dist/watchman-APYjXSQa.mjs +0 -48
  149. package/dist/workspace-process-lock-2mNzOlaB.mjs +0 -58
  150. package/dist/workspaces-Bcib97-6.mjs +0 -306
@@ -1,25 +1,192 @@
1
- import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
- import { D as withConfigLock, H as projectDeviceSlots, _ as loadConfig, d as getConfigDir, k as acquireAvdClaim, p as getProject, z as deviceSlotPlatforms } from "./config-D0DbpZtM.mjs";
3
- import { n as ownership_claim_exports, t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
1
+ import { n as ownership_claim_exports, t as process_identity_exports } from "./process-identity-Biv3arCO.mjs";
2
+ import { t as getExecutor } from "./exec-DWhCZDGm.mjs";
4
3
  import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
5
- import { l as phaseLine } from "./command-output-CDAIFD-8.mjs";
6
- import { gt as repoRoot, q as resolveTailscaleBinary } from "./settings-Cfd-0r2d.mjs";
7
- import { o as pidExists, u as signalProcessTree } from "./metro-g8NqiJp-.mjs";
8
- import { g as workspaceAgentDeviceDir, v as workspaceDir } from "./workspace-state-DqcCbpE7.mjs";
9
- import { _ as removeSingletonFiles, c as webClaimRoot, f as webProfileDir, g as liveProfileHolder, h as chromeProcessState, i as clearWebRecord, o as readWebRecord, t as CDP_PORT_LABEL } from "./state-PeQiJuIu.mjs";
10
- import { t as agentDeviceDaemon, u as readAgentDeviceRecords } from "./activity-IRvJY_ru.mjs";
11
- import { n as readCreatedDevices, r as recordCreatedDevice, t as forgetCreatedDevice } from "./created-devices-CpvzBL25.mjs";
12
- import { B as ownedAvdSystemImage, I as ownedAvdDirectory, J as resolveOwnedAvdSerial, L as ownedAvdMatchesConfiguration, M as listOrphanedAvdDirectories, O as listAdbDevices, X as shutdownAndroidEmulator, Z as sleepSync, _ as avdStorageRoots, dt as parkSim, et as waitForAndroidEmulatorShutdown, f as assertOwnedAvdStopped, h as avdPathExists, it as isStimOwnedAvd, lt as eraseParkedAfter, mt as removeParkedAfter, nt as wipeAvdUserData, pt as readParked, x as deleteAvd } from "./android-B_YNZy61.mjs";
13
- import { E as shutdownIosSim, _ as parseRuntimeVersion, a as deleteIosSim, b as renameIosSim, f as listIosDeviceTypes, g as parkedSimName, o as deleteParkedIosSim, s as eraseIosSim, w as resolveOwnedIosSim } from "./ios-DSfnPfse.mjs";
14
- import { r as workspaceProcessLockPath, t as withWorkspaceProcessLock } from "./workspace-process-lock-2mNzOlaB.mjs";
15
- import { r as releaseBrowserPort } from "./named-ports-C8m8EQs2.mjs";
16
- import { createHash, randomUUID } from "node:crypto";
17
- import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, realpathSync, renameSync, rmSync, unlinkSync } from "node:fs";
4
+ import { a as formatElapsed, l as phaseLine } from "./command-output-CBtzyIgF.mjs";
5
+ import { D as withConfigLock$1, H as projectDeviceSlots, M as isOnMountedVolume, N as listMountedVolumes, P as measuredDirectorySize, _ as loadConfig$1, d as getConfigDir, g as isPathPrefix, j as formatBytes, k as acquireAvdClaim, p as getProject, z as deviceSlotPlatforms } from "./config-CgYMahz7.mjs";
6
+ import { y as repoRoot } from "./worktree-CsKYexJM.mjs";
7
+ import { o as pidExists, u as signalProcessTree } from "./metro-Dh8T4Ytd.mjs";
8
+ import { S as workspaceName, g as workspaceAgentDeviceDir, r as readWorkspaceState$1, s as workspaceLastUsed, v as workspaceDir } from "./workspace-state-C59dqG-Z.mjs";
9
+ import { _ as removeSingletonFiles, c as webClaimRoot, f as webProfileDir, g as liveProfileHolder, h as chromeProcessState, i as clearWebRecord, o as readWebRecord, t as CDP_PORT_LABEL, u as webFacts } from "./state-BG-aAk4k.mjs";
10
+ import { t as agentDeviceDaemon, u as readAgentDeviceRecords } from "./activity-BxnkDZDi.mjs";
11
+ import { h as listBuildLocks } from "./device-lease-Co-EwifR.mjs";
12
+ import { n as declareSpawnsOn, o as stopDeclaringSpawnsOn } from "./spawn-claims-Kqiifsk2.mjs";
13
+ import { n as readCreatedDevices$1, r as recordCreatedDevice, t as forgetCreatedDevice } from "./created-devices-DKbeWsiK.mjs";
14
+ import { B as ownedAvdSystemImage, I as ownedAvdDirectory, J as resolveOwnedAvdSerial, L as ownedAvdMatchesConfiguration, M as listOrphanedAvdDirectories, O as listAdbDevices, X as shutdownAndroidEmulator, Z as sleepSync, _ as avdStorageRoots, dt as parkSim, et as waitForAndroidEmulatorShutdown, f as assertOwnedAvdStopped, h as avdPathExists, it as isStimOwnedAvd, lt as eraseParkedAfter, mt as removeParkedAfter, nt as wipeAvdUserData, pt as readParked, x as deleteAvd } from "./android-DC3ZLuw0.mjs";
15
+ import { D as shutdownIosSim, T as resolveOwnedIosSim, _ as parkedSimName, c as eraseIosSim, o as deleteIosSim, p as listIosDeviceTypes, s as deleteParkedIosSim, v as parseRuntimeVersion, x as renameIosSim } from "./ios-B3SbOWdw.mjs";
16
+ import { J as resolveTailscaleBinary } from "./settings-CQyMElEP.mjs";
17
+ import { a as withWorkspaceProcessLock, o as workspaceProcessLockError, r as releaseBrowserPort, s as workspaceProcessLockPath } from "./named-ports-BFIz1Shz.mjs";
18
+ import { i as macosRuntimeClaim } from "./state-xnqpx3AD.mjs";
19
+ import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync } from "node:fs";
18
20
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
21
+ import { basename as basename$1, isAbsolute as isAbsolute$1, join as join$1, relative as relative$1, resolve as resolve$1 } from "path";
22
+ import { buildSlotsDir, hostedNativeRecords, isJsonObject, macosAppState, parseHostedNativePlacement, readJsonFile, readMacosRecord, tryAcquireBuildSlotClaim, unreadableHostedNative } from "@stim-cli/core/state";
19
23
  import { homedir } from "node:os";
24
+ import chalk from "chalk";
20
25
  import { isDeepStrictEqual } from "node:util";
26
+ import { existsSync as existsSync$1, lstatSync as lstatSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, rmSync as rmSync$1, statSync as statSync$1 } from "fs";
27
+ import { createHash, randomUUID } from "node:crypto";
21
28
  import { resolve4 } from "node:dns/promises";
22
29
  import { request } from "node:https";
30
+ //#region src/commands/gc/paths.ts
31
+ function canonicalPath(p) {
32
+ try {
33
+ return realpathSync$1(p);
34
+ } catch {
35
+ return resolve$1(p);
36
+ }
37
+ }
38
+ //#endregion
39
+ //#region src/commands/gc/results.ts
40
+ const results = [];
41
+ function recordGcResult(kind, status, label, { id = null, bytes = null, detail = null } = {}) {
42
+ results.push({
43
+ kind,
44
+ status,
45
+ label,
46
+ id,
47
+ bytes,
48
+ detail
49
+ });
50
+ }
51
+ function takeGcResults() {
52
+ return results.splice(0);
53
+ }
54
+ //#endregion
55
+ //#region src/engine/build-slots.ts
56
+ const SLOT_PREFIX = "slot-";
57
+ const SLOT_POLL_MS = 1e3;
58
+ const SLOT_PROGRESS_MS = 3e4;
59
+ const SLOT_CEILING_MS = 54e5;
60
+ function sleepAsync$1(ms) {
61
+ return new Promise((resolve) => setTimeout(resolve, ms));
62
+ }
63
+ function toRecord(holder) {
64
+ const details = holder.details;
65
+ return {
66
+ pid: holder.owner.pid,
67
+ index: typeof details.index === "number" ? details.index : null,
68
+ projectRoot: typeof details.projectRoot === "string" ? details.projectRoot : null,
69
+ startedAt: holder.startedAt || null,
70
+ logFile: typeof details.logFile === "string" ? details.logFile : null
71
+ };
72
+ }
73
+ function tryAcquireBuildSlot({ max, root = null, logFile = null }) {
74
+ if (!max || max <= 0) return {
75
+ acquired: true,
76
+ unlimited: true
77
+ };
78
+ const got = tryAcquireBuildSlotClaim({
79
+ max,
80
+ details: {
81
+ projectRoot: root,
82
+ logFile
83
+ }
84
+ });
85
+ if (!got) return null;
86
+ declareSpawnsOn(got.claim);
87
+ return {
88
+ acquired: true,
89
+ path: got.path,
90
+ index: got.index,
91
+ slot: {
92
+ pid: got.claim.owner.pid,
93
+ index: got.index,
94
+ projectRoot: root,
95
+ startedAt: got.claim.startedAt,
96
+ logFile
97
+ },
98
+ claim: got.claim
99
+ };
100
+ }
101
+ function slotWaitingLine({ max, elapsedMs }) {
102
+ return `${"build".padEnd(11)} waiting for a build slot (all ${max} in use, ${formatElapsed(elapsedMs)} elapsed) -- stim guide lifecycle concurrency`;
103
+ }
104
+ async function acquireBuildSlot({ max, root = null, logFile = null, now = Date.now, out = () => {}, waitingFor = () => {}, sleep = sleepAsync$1, intervalMs = SLOT_POLL_MS, progressMs = SLOT_PROGRESS_MS, ceilingMs = SLOT_CEILING_MS }) {
105
+ if (!max || max <= 0) return {
106
+ acquired: true,
107
+ unlimited: true
108
+ };
109
+ const started = now();
110
+ let lastProgress = started;
111
+ let waited = false;
112
+ try {
113
+ for (;;) {
114
+ const got = tryAcquireBuildSlot({
115
+ max,
116
+ root,
117
+ logFile
118
+ });
119
+ if (got) return {
120
+ ...got,
121
+ slotWaitMs: waited ? Math.max(0, Math.round(now() - started)) : 0
122
+ };
123
+ waited = true;
124
+ waitingFor({
125
+ kind: "build-slot",
126
+ inUse: max,
127
+ max,
128
+ since: new Date(started).toISOString()
129
+ });
130
+ const elapsed = now() - started;
131
+ if (elapsed >= ceilingMs) {
132
+ const err = /* @__PURE__ */ new Error(`Waited ${formatElapsed(elapsed)} for one of ${max} build slots, and every slot is held by a process that is still running, or by a holder Stim cannot identify. Slots live under ` + buildSlotsDir() + "; remove a slot directory whose builder is not really building, or raise concurrency.maxBuilds.");
133
+ err.code = "STIM_BUILD_SLOT_TIMEOUT";
134
+ throw err;
135
+ }
136
+ if (now() - lastProgress >= progressMs) {
137
+ lastProgress = now();
138
+ out(slotWaitingLine({
139
+ max,
140
+ elapsedMs: elapsed
141
+ }));
142
+ }
143
+ await sleep(intervalMs);
144
+ }
145
+ } finally {
146
+ waitingFor(null);
147
+ }
148
+ }
149
+ function releaseBuildSlot(handle) {
150
+ if (!handle || handle.unlimited) return false;
151
+ stopDeclaringSpawnsOn(handle.claim);
152
+ return (0, ownership_claim_exports.releaseClaim)(handle.claim);
153
+ }
154
+ function listBuildSlots() {
155
+ const dir = buildSlotsDir();
156
+ let names;
157
+ try {
158
+ names = readdirSync(dir);
159
+ } catch {
160
+ return [];
161
+ }
162
+ const slots = [];
163
+ for (const name of names) {
164
+ if (!name.startsWith(SLOT_PREFIX)) continue;
165
+ const path = join(dir, name);
166
+ try {
167
+ if (!statSync(path).isDirectory()) continue;
168
+ } catch {
169
+ continue;
170
+ }
171
+ const survey = (0, ownership_claim_exports.readClaimSet)(path);
172
+ const holder = survey.live[0] ?? survey.dead[0];
173
+ const info = holder ? toRecord(holder) : null;
174
+ const index = Number(name.slice(5));
175
+ slots.push({
176
+ path,
177
+ name,
178
+ index: Number.isFinite(index) ? index : null,
179
+ pid: info?.pid ?? null,
180
+ projectRoot: info?.projectRoot ?? null,
181
+ startedAt: info?.startedAt ?? null,
182
+ logFile: info?.logFile ?? null,
183
+ alive: survey.live.length > 0,
184
+ unresolved: survey.unresolved.length > 0
185
+ });
186
+ }
187
+ return slots;
188
+ }
189
+ //#endregion
23
190
  //#region src/devices/agent-device-cleanup.ts
24
191
  function parseAgentDeviceSessions(output) {
25
192
  const result = JSON.parse(output);
@@ -392,7 +559,7 @@ function teardownOwnedIosSim(udid, { del = false, label, park, workspace, shutdo
392
559
  }
393
560
  }
394
561
  function assertAvdReferences(avdName, owner) {
395
- const config = loadConfig();
562
+ const config = loadConfig$1();
396
563
  if (!config) throw new Error("Cannot verify AVD references without a Stim config; the data was kept.");
397
564
  if (owner && "projectPath" in owner && owner.expectedRecord && !isDeepStrictEqual(deviceSlotPlatforms(config.projects[owner.projectPath], owner.slot)?.android, owner.expectedRecord)) throw new Error(`AVD ${avdName} has a changed workspace record; its data was kept.`);
398
565
  for (const [projectPath, project] of Object.entries(config.projects)) for (const { slot, platforms } of projectDeviceSlots(project)) {
@@ -405,7 +572,7 @@ function removeOrphanedAvdDirectory(candidate, owner) {
405
572
  const surveyed = listOrphanedAvdDirectories(candidate.name).find((entry) => entry.directory === candidate.directory);
406
573
  if (!surveyed || surveyed.name !== candidate.name || surveyed.dev !== candidate.dev || surveyed.ino !== candidate.ino) throw new Error(`AVD data at ${candidate.directory} changed or is registered; it was kept.`);
407
574
  assertOwnedAvdStopped(candidate.name, { resolveDirectory: () => candidate.directory });
408
- const detached = withConfigLock(() => {
575
+ const detached = withConfigLock$1(() => {
409
576
  const current = lstatSync(candidate.directory);
410
577
  if (!current.isDirectory() || current.dev !== candidate.dev || current.ino !== candidate.ino) throw new Error(`AVD data at ${candidate.directory} changed or is registered; it was kept.`);
411
578
  assertAvdReferences(candidate.name, owner);
@@ -481,7 +648,7 @@ function serialFree(serial) {
481
648
  function teardownClaimedAvd(avdName, claim, { del = false, wipe = false, park, owner, workspace, orphanedDirectory, onlyIfMissing = false, onWipeStart, waitForShutdown = waitForAndroidEmulatorShutdown, assertStopped = assertOwnedAvdStopped, resolveAvd = resolveOwnedAvdSerial }) {
482
649
  let parkFallback;
483
650
  try {
484
- if (del || wipe) withConfigLock(() => assertAvdReferences(avdName, owner));
651
+ if (del || wipe) withConfigLock$1(() => assertAvdReferences(avdName, owner));
485
652
  const resolved = resolveAvd(avdName);
486
653
  if (resolved.notOwned) return {
487
654
  status: "skipped",
@@ -547,7 +714,7 @@ function teardownClaimedAvd(avdName, claim, { del = false, wipe = false, park, o
547
714
  if (current.notOwned || current.missing) throw new Error(`AVD ${avdName} changed before its data was wiped.`);
548
715
  if (current.serial) throw new Error(`Owned AVD ${avdName} started again before its data was wiped.`);
549
716
  assertStopped(avdName);
550
- withConfigLock(() => assertAvdReferences(avdName, owner));
717
+ withConfigLock$1(() => assertAvdReferences(avdName, owner));
551
718
  const directory = ownedAvdDirectory(avdName);
552
719
  if (!directory) throw new Error(`The data directory of AVD ${avdName} could not be resolved.`);
553
720
  onWipeStart?.();
@@ -563,7 +730,7 @@ function teardownClaimedAvd(avdName, claim, { del = false, wipe = false, park, o
563
730
  if (current.missing) return teardownUnregisteredAvd(avdName, del, owner);
564
731
  if (current.serial) throw new Error(`Owned AVD ${avdName} started again before deletion.`);
565
732
  assertStopped(avdName);
566
- withConfigLock(() => assertAvdReferences(avdName, owner));
733
+ withConfigLock$1(() => assertAvdReferences(avdName, owner));
567
734
  if (park && park.max > 0) try {
568
735
  const systemImage = ownedAvdSystemImage(avdName);
569
736
  if (!systemImage || !park.configuration || !ownedAvdMatchesConfiguration(avdName, park.configuration)) throw new Error("the AVD has no verified creation configuration");
@@ -720,7 +887,7 @@ async function teardownBrowserHeld(root, { deleteProfile = false } = {}) {
720
887
  }
721
888
  if (existsSync(profile)) removeSingletonFiles(profile);
722
889
  if (deleteProfile && existsSync(profile)) {
723
- if (!readCreatedDevices().web.has(profile)) return {
890
+ if (!readCreatedDevices$1().web.has(profile)) return {
724
891
  status: "skipped",
725
892
  kind: "not-owned",
726
893
  reason: `${profile} is not in Stim's ledger; it was kept`
@@ -1301,4 +1468,391 @@ function numberOrNull(v) {
1301
1468
  return typeof v === "number" && Number.isSafeInteger(v) && v > 0 ? v : null;
1302
1469
  }
1303
1470
  //#endregion
1304
- export { teardownParkedAvd as _, terminateChild as a, withManagedTunnelLock as c, eraseParkedAvd as d, eraseParkedIosSim as f, teardownOwnedIosSim as g, teardownOwnedBrowser as h, stopTunnel as i, withManagedTunnelRemovalLock as l, teardownOwnedAvd as m, managedLockHolders as n, withManagedRemoteWorktreeLock as o, teardownBrowserHeld as p, startTunnelSequence as r, withManagedRemoteWorktreeRemovalLock as s, resolveSupervisorTarget as t, probePublicHttp as u, teardownParkedIosSim as v };
1471
+ //#region src/workspace/in-use.ts
1472
+ const NATIVE_RUN = "native-run";
1473
+ const NATIVE_RUN_HELD = "a stim ios, android or stop run holds its native-run.lock";
1474
+ function workspaceInUse(root, { supervisor = true, managedLocks = true, hosted = true, nativeRun = true } = {}) {
1475
+ const reasons = [];
1476
+ if (supervisor) {
1477
+ const project = getProject(root);
1478
+ const target = resolveSupervisorTarget({
1479
+ state: readWorkspaceState$1(root)?.supervisor,
1480
+ record: project?.supervisor,
1481
+ reservedPort: project?.metroPort
1482
+ });
1483
+ if (target.status === "ours") reasons.push(`its dev server supervisor (pid ${target.pid}) is running`);
1484
+ else if (target.status === "unverified") reasons.push(`its dev server supervisor cannot be verified: ${target.reason ?? "unknown identity"}`);
1485
+ const macos = macosAppState(readMacosRecord(root));
1486
+ if (macos?.host) reasons.push(`its macOS app runs on ${macos.host.machine}`);
1487
+ else if (macos?.state === "running" || macos?.state === "orphaned" || macos?.build.state === "running") reasons.push("its macOS app or build is running");
1488
+ else if (macos?.state === "unverified" || !macos && readWorkspaceState$1(root)?.macos !== void 0) reasons.push("its macOS process owner cannot be verified");
1489
+ const runtime = (0, ownership_claim_exports.readClaimSet)(macosRuntimeClaim(root));
1490
+ if (runtime.live.length) reasons.push("its macOS runtime claim is held");
1491
+ else if (runtime.unresolved[0]) reasons.push(`its macOS runtime cannot be verified: ${runtime.unresolved[0].reason}`);
1492
+ const browser = webFacts(readWebRecord(root));
1493
+ if (browser?.status === "running" || browser?.status === "orphaned") reasons.push(`its owned Chrome (pid ${browser.record.chromeProcess?.pid}) is running`);
1494
+ else if (browser?.status === "unverified") reasons.push("its owned Chrome cannot be verified");
1495
+ }
1496
+ if (nativeRun) {
1497
+ const claims = (0, ownership_claim_exports.readClaimSet)(workspaceProcessLockPath(workspaceDir(root), NATIVE_RUN, true));
1498
+ if (claims.live.length) reasons.push(NATIVE_RUN_HELD);
1499
+ else if (claims.unresolved[0]) reasons.push(`its native-run.lock cannot be resolved: ${claims.unresolved[0].reason}`);
1500
+ }
1501
+ for (const platform of ["ios", "android"]) for (const [slot, record] of Object.entries(hosted ? hostedNativeRecords(readWorkspaceState$1(root), platform) : {})) {
1502
+ const placement = parseHostedNativePlacement(record, platform);
1503
+ reasons.push(placement ? `its ${platform === "ios" ? "iOS simulator" : "Android emulator"} runs on ${placement.machine}` : unreadableHostedNative(slot, platform));
1504
+ }
1505
+ const self = canonicalPath(root);
1506
+ for (const [kind, entries] of [["build lock", listBuildLocks()], ["build slot", listBuildSlots()]]) for (const entry of entries) {
1507
+ if (!entry.alive && !entry.unresolved) continue;
1508
+ if (entry.projectRoot !== null && canonicalPath(entry.projectRoot) === self) reasons.push(`a ${entry.alive ? "live" : "unresolvable"} ${kind} at ${entry.path} names it`);
1509
+ }
1510
+ if (managedLocks) reasons.push(...managedLockHolders(root));
1511
+ return reasons;
1512
+ }
1513
+ function emptyWorkspaceDir(dir) {
1514
+ if (lstatSync(dir).isSymbolicLink()) {
1515
+ unlinkSync(dir);
1516
+ return;
1517
+ }
1518
+ for (const name of readdirSync(dir)) if (name !== `${NATIVE_RUN}.lock`) rmSync(join(dir, name), {
1519
+ recursive: true,
1520
+ force: true
1521
+ });
1522
+ }
1523
+ async function withIdleWorkspace(root, fn, { purpose, ...checks }) {
1524
+ try {
1525
+ return await withWorkspaceProcessLock(workspaceDir(root), NATIVE_RUN, async () => {
1526
+ const reasons = workspaceInUse(root, {
1527
+ ...checks,
1528
+ nativeRun: false
1529
+ });
1530
+ if (reasons.length) return {
1531
+ ran: false,
1532
+ reasons
1533
+ };
1534
+ return {
1535
+ ran: true,
1536
+ value: await fn()
1537
+ };
1538
+ }, {
1539
+ external: true,
1540
+ waitMs: 0,
1541
+ ownerPurpose: purpose
1542
+ });
1543
+ } catch (error) {
1544
+ if (workspaceProcessLockError(error)) return {
1545
+ ran: false,
1546
+ reasons: [NATIVE_RUN_HELD]
1547
+ };
1548
+ if ((0, ownership_claim_exports.isClaimRefusal)(error) || (0, ownership_claim_exports.isClaimUnavailable)(error)) return {
1549
+ ran: false,
1550
+ reasons: [`its native-run.lock cannot be taken: ${error.reason}`]
1551
+ };
1552
+ throw error;
1553
+ } finally {
1554
+ try {
1555
+ const dir = workspaceDir(root);
1556
+ if (!lstatSync(dir).isSymbolicLink()) rmdirSync(dir);
1557
+ } catch {}
1558
+ }
1559
+ }
1560
+ //#endregion
1561
+ //#region src/commands/gc/workspaces.ts
1562
+ function workspacesRoot() {
1563
+ return join$1(getConfigDir(), "workspaces");
1564
+ }
1565
+ function isInsideWorkspaces(dir) {
1566
+ const rel = relative$1(canonicalPath(workspacesRoot()), canonicalPath(dir));
1567
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute$1(rel);
1568
+ }
1569
+ function readRecordedRoot(dir, name) {
1570
+ let parsed;
1571
+ try {
1572
+ parsed = readJsonFile(join$1(dir, "workspace.json"));
1573
+ } catch (error) {
1574
+ return {
1575
+ projectRoot: null,
1576
+ problem: error?.code === "ENOENT" ? "it has no workspace.json" : "its workspace.json does not parse"
1577
+ };
1578
+ }
1579
+ const projectRoot = isJsonObject(parsed) ? parsed.projectRoot : void 0;
1580
+ if (typeof projectRoot !== "string" || !isAbsolute$1(projectRoot)) return {
1581
+ projectRoot: null,
1582
+ problem: "its workspace.json records no absolute project root"
1583
+ };
1584
+ if (workspaceName(projectRoot) !== name) return {
1585
+ projectRoot: null,
1586
+ problem: `its workspace.json records ${projectRoot}, whose workspace directory has another name`
1587
+ };
1588
+ return {
1589
+ projectRoot,
1590
+ problem: null
1591
+ };
1592
+ }
1593
+ function listWorkspaceDirs() {
1594
+ const root = workspacesRoot();
1595
+ let names;
1596
+ try {
1597
+ names = readdirSync$1(root).toSorted();
1598
+ } catch {
1599
+ return [];
1600
+ }
1601
+ const entries = [];
1602
+ for (const name of names) {
1603
+ const dir = join$1(root, name);
1604
+ try {
1605
+ if (!statSync$1(dir).isDirectory()) continue;
1606
+ } catch {
1607
+ continue;
1608
+ }
1609
+ entries.push({
1610
+ dir,
1611
+ ...readRecordedRoot(dir, name)
1612
+ });
1613
+ }
1614
+ return entries;
1615
+ }
1616
+ function classifyWorkspaceDirs(entries, { registryKeys, exists, isMounted, inUse }) {
1617
+ const orphaned = [];
1618
+ const skipped = [];
1619
+ for (const { dir, projectRoot, problem } of entries) {
1620
+ if (projectRoot === null) {
1621
+ skipped.push({
1622
+ dir,
1623
+ reason: `workspace directory not resolved: ${problem ?? "unknown project root"}`
1624
+ });
1625
+ continue;
1626
+ }
1627
+ const present = exists(projectRoot);
1628
+ if (present === null) {
1629
+ skipped.push({
1630
+ dir,
1631
+ reason: `cannot tell whether its project root ${projectRoot} still exists`
1632
+ });
1633
+ continue;
1634
+ }
1635
+ if (present) continue;
1636
+ if (registryKeys.some((key) => isPathPrefix(projectRoot, key))) continue;
1637
+ if (!isMounted(projectRoot)) {
1638
+ skipped.push({
1639
+ dir,
1640
+ reason: `the volume of its project root ${projectRoot} is not mounted`
1641
+ });
1642
+ continue;
1643
+ }
1644
+ const reasons = inUse(projectRoot);
1645
+ if (reasons.length) {
1646
+ skipped.push({
1647
+ dir,
1648
+ reason: `its project root ${projectRoot} is gone, but ${reasons.join("; ")}`
1649
+ });
1650
+ continue;
1651
+ }
1652
+ orphaned.push({
1653
+ dir,
1654
+ projectRoot
1655
+ });
1656
+ }
1657
+ return {
1658
+ orphaned,
1659
+ skipped
1660
+ };
1661
+ }
1662
+ function rootPresence(path) {
1663
+ try {
1664
+ lstatSync$1(path);
1665
+ return true;
1666
+ } catch (error) {
1667
+ const code = error?.code;
1668
+ return code === "ENOENT" || code === "ENOTDIR" ? false : null;
1669
+ }
1670
+ }
1671
+ function collectOrphanedWorkspaces(registryKeys, mountedVolumes, { measure = true } = {}) {
1672
+ const classified = classifyWorkspaceDirs(listWorkspaceDirs(), {
1673
+ registryKeys,
1674
+ exists: rootPresence,
1675
+ isMounted: (path) => isOnMountedVolume(path, mountedVolumes),
1676
+ inUse: (root) => workspaceInUse(root)
1677
+ });
1678
+ return {
1679
+ orphaned: measure ? classified.orphaned.map((entry) => Object.assign({}, entry, { bytes: sizeOf(entry.dir) })) : classified.orphaned,
1680
+ skipped: classified.skipped
1681
+ };
1682
+ }
1683
+ const REBUILD_COST = "The next build of an unchanged app installs from the shared build cache; after a native change the compilation cache speeds the rebuild, but on React Native 0.86 Swift does not use it (explicit modules are off), so that build recompiles Swift. The next stim macos in a cleared workspace is a full Swift build.";
1684
+ const WORKSPACE_OUTPUT_DIRS = [
1685
+ "derived-data",
1686
+ "gradle-build",
1687
+ "android-cas",
1688
+ "cache-provider"
1689
+ ];
1690
+ const DAY_MS = 864e5;
1691
+ function planWorkspaceOutputs(entries, { olderThan, now }) {
1692
+ return entries.map(({ dir, projectRoot, problem, bytes, lastUsed, inUse }) => {
1693
+ const idleDays = Number.isFinite(lastUsed) ? Math.max(0, Math.floor((now - lastUsed) / DAY_MS)) : null;
1694
+ const [keptCode, keptReason] = projectRoot === null ? ["unresolved", `workspace directory not resolved: ${problem ?? "unknown project root"}`] : inUse.length ? ["in-use", `in use: ${inUse.join("; ")}`] : olderThan === null ? [null, null] : idleDays === null ? ["last-use-unknown", "its last use is unknown"] : idleDays < olderThan ? ["recently-used", `used ${idleDays}d ago, within --older-than ${olderThan}`] : [null, null];
1695
+ return {
1696
+ dir,
1697
+ projectRoot,
1698
+ bytes,
1699
+ idleDays,
1700
+ willClear: keptCode === null,
1701
+ keptCode,
1702
+ keptReason
1703
+ };
1704
+ });
1705
+ }
1706
+ const SIZE_TIMEOUT_MS = 6e4;
1707
+ function sizeOf(dir, timeoutMs = SIZE_TIMEOUT_MS) {
1708
+ return measuredDirectorySize(dir, { timeoutMs });
1709
+ }
1710
+ function outputPaths(dir) {
1711
+ const paths = WORKSPACE_OUTPUT_DIRS.map((name) => join$1(dir, name)).filter((path) => existsSync$1(path));
1712
+ const macos = join$1(dir, "macos");
1713
+ try {
1714
+ if (!lstatSync$1(macos).isDirectory()) return paths;
1715
+ for (const entry of readdirSync$1(macos, { withFileTypes: true })) if (entry.name === "build" || entry.name.endsWith(".app") || entry.name.startsWith("staging-") && entry.isDirectory()) paths.push(join$1(macos, entry.name));
1716
+ } catch {}
1717
+ return paths;
1718
+ }
1719
+ function outputBytes(paths, timeoutMs) {
1720
+ let total = 0;
1721
+ for (const path of paths) {
1722
+ const size = sizeOf(path, timeoutMs);
1723
+ if (size === null) return null;
1724
+ total += size;
1725
+ }
1726
+ return total;
1727
+ }
1728
+ function collectWorkspaceOutputs({ olderThan, now, exclude = [], measure = true, sizeTimeoutMs = SIZE_TIMEOUT_MS }) {
1729
+ const mountedVolumes = listMountedVolumes();
1730
+ const entries = listWorkspaceDirs().filter((entry) => !exclude.includes(entry.dir)).filter((entry) => entry.projectRoot === null || isOnMountedVolume(entry.projectRoot, mountedVolumes)).map((entry) => Object.assign({}, entry, { paths: outputPaths(entry.dir) })).filter((entry) => entry.paths.length > 0).map(({ paths, ...entry }) => Object.assign({}, entry, { bytes: measure ? outputBytes(paths, sizeTimeoutMs) : null })).map((entry) => Object.assign({}, entry, {
1731
+ lastUsed: entry.projectRoot === null ? NaN : workspaceLastUsed(entry.projectRoot),
1732
+ inUse: entry.projectRoot === null ? [] : workspaceInUse(entry.projectRoot)
1733
+ }));
1734
+ return {
1735
+ root: workspacesRoot(),
1736
+ workspaces: planWorkspaceOutputs(entries, {
1737
+ olderThan,
1738
+ now
1739
+ })
1740
+ };
1741
+ }
1742
+ async function clearWorkspaceOutputs(report, { olderThan, now = Date.now() }) {
1743
+ let failures = 0;
1744
+ let cleared = 0;
1745
+ const clearedRoots = [];
1746
+ for (const entry of report.workspaces) {
1747
+ const root = entry.projectRoot;
1748
+ if (!entry.willClear || root === null) {
1749
+ if (entry.keptReason) {
1750
+ console.log(chalk.dim(`Kept the build outputs of ${root ?? entry.dir}: ${entry.keptReason}`));
1751
+ recordGcResult("workspaceOutputs", "kept", root ?? entry.dir, {
1752
+ bytes: entry.bytes,
1753
+ detail: entry.keptReason
1754
+ });
1755
+ }
1756
+ continue;
1757
+ }
1758
+ let run;
1759
+ try {
1760
+ run = await withIdleWorkspace(root, () => {
1761
+ const [again] = planWorkspaceOutputs([{
1762
+ ...entry,
1763
+ problem: null,
1764
+ lastUsed: workspaceLastUsed(root),
1765
+ inUse: []
1766
+ }], {
1767
+ olderThan,
1768
+ now
1769
+ });
1770
+ if (again?.keptReason) return again.keptReason;
1771
+ for (const path of outputPaths(entry.dir)) rmSync$1(path, {
1772
+ recursive: true,
1773
+ force: true
1774
+ });
1775
+ return null;
1776
+ }, { purpose: "gc" });
1777
+ } catch (error) {
1778
+ failures++;
1779
+ console.log(chalk.red(`Could not clear the build outputs of ${root}: ${error?.message || String(error)}`));
1780
+ recordGcResult("workspaceOutputs", "failed", root, {
1781
+ bytes: entry.bytes,
1782
+ detail: error?.message || String(error)
1783
+ });
1784
+ continue;
1785
+ }
1786
+ const kept = run.ran ? run.value : `in use: ${run.reasons.join("; ")}`;
1787
+ if (kept) {
1788
+ console.log(chalk.yellow(`Kept the build outputs of ${root}: ${kept}`));
1789
+ recordGcResult("workspaceOutputs", "kept", root, {
1790
+ bytes: entry.bytes,
1791
+ detail: kept
1792
+ });
1793
+ continue;
1794
+ }
1795
+ cleared += entry.bytes ?? 0;
1796
+ clearedRoots.push(root);
1797
+ console.log(chalk.green(`Cleared the build outputs of ${root} (${sizeText(entry.bytes)})`));
1798
+ recordGcResult("workspaceOutputs", "done", root, { bytes: entry.bytes });
1799
+ }
1800
+ if (cleared) console.log(chalk.dim(`Cleared ${formatBytes(cleared)} of workspace build outputs. ${REBUILD_COST}`));
1801
+ return {
1802
+ failures,
1803
+ cleared: clearedRoots
1804
+ };
1805
+ }
1806
+ function stillOrphaned({ dir, projectRoot }) {
1807
+ if (readRecordedRoot(dir, basename$1(dir)).projectRoot !== projectRoot || rootPresence(projectRoot) !== false || !isOnMountedVolume(projectRoot)) return false;
1808
+ return !Object.keys(loadConfig$1()?.projects ?? {}).some((key) => isPathPrefix(projectRoot, key));
1809
+ }
1810
+ async function deleteOrphanedWorkspaces(orphaned) {
1811
+ let failures = 0;
1812
+ for (const entry of orphaned) {
1813
+ if (!existsSync$1(entry.dir)) continue;
1814
+ let run;
1815
+ try {
1816
+ run = await withIdleWorkspace(entry.projectRoot, async () => {
1817
+ if (!stillOrphaned(entry)) return false;
1818
+ const browser = await teardownOwnedBrowser(entry.projectRoot, { deleteProfile: true });
1819
+ if (browser.status === "failed" || browser.status === "skipped") throw new Error(`its owned Chrome profile was kept: ${browser.reason}`);
1820
+ emptyWorkspaceDir(entry.dir);
1821
+ return true;
1822
+ }, { purpose: "gc" });
1823
+ } catch (error) {
1824
+ failures++;
1825
+ console.log(chalk.red(`Could not remove ${entry.dir}: ${error?.message || error}`));
1826
+ recordGcResult("workspaceDirectory", "failed", entry.dir, {
1827
+ bytes: entry.bytes ?? null,
1828
+ detail: error?.message || String(error)
1829
+ });
1830
+ continue;
1831
+ }
1832
+ if (!run.ran) {
1833
+ console.log(chalk.yellow(`Kept ${entry.dir}: ${run.reasons.join("; ")}`));
1834
+ recordGcResult("workspaceDirectory", "kept", entry.dir, {
1835
+ bytes: entry.bytes ?? null,
1836
+ detail: run.reasons.join("; ")
1837
+ });
1838
+ continue;
1839
+ }
1840
+ if (!run.value) {
1841
+ console.log(chalk.yellow(`Kept ${entry.dir}: it can no longer be confirmed orphaned.`));
1842
+ recordGcResult("workspaceDirectory", "kept", entry.dir, {
1843
+ bytes: entry.bytes ?? null,
1844
+ detail: "it can no longer be confirmed orphaned"
1845
+ });
1846
+ continue;
1847
+ }
1848
+ const size = entry.bytes === void 0 ? "" : ` (${sizeText(entry.bytes)})`;
1849
+ console.log(chalk.green(`Removed the orphaned workspace directory ${entry.dir}${size}`));
1850
+ recordGcResult("workspaceDirectory", "done", entry.dir, { bytes: entry.bytes ?? null });
1851
+ }
1852
+ return failures;
1853
+ }
1854
+ function sizeText(bytes) {
1855
+ return bytes === null ? "size unknown" : formatBytes(bytes);
1856
+ }
1857
+ //#endregion
1858
+ export { teardownParkedIosSim as A, eraseParkedAvd as C, teardownOwnedBrowser as D, teardownOwnedAvd as E, takeGcResults as F, canonicalPath as I, listBuildSlots as M, releaseBuildSlot as N, teardownOwnedIosSim as O, recordGcResult as P, probePublicHttp as S, teardownBrowserHeld as T, terminateChild as _, collectWorkspaceOutputs as a, withManagedTunnelLock as b, listWorkspaceDirs as c, emptyWorkspaceDir as d, withIdleWorkspace as f, stopTunnel as g, startTunnelSequence as h, collectOrphanedWorkspaces as i, acquireBuildSlot as j, teardownParkedAvd as k, rootPresence as l, resolveSupervisorTarget as m, WORKSPACE_OUTPUT_DIRS as n, deleteOrphanedWorkspaces as o, workspaceInUse as p, clearWorkspaceOutputs as r, isInsideWorkspaces as s, REBUILD_COST as t, sizeText as u, withManagedRemoteWorktreeLock as v, eraseParkedIosSim as w, withManagedTunnelRemovalLock as x, withManagedRemoteWorktreeRemovalLock as y };
@@ -1,2 +1,2 @@
1
- import { a as porcelainPath, c as registerWarm, d as removalRemedy, f as removeWorktreeTarget, i as matchWorktreeEntry, l as removalBlockers, m as worktreeCommand, n as excludePodChurn, o as reclaimKeys, p as warmedWorkspace, r as excludeWatchmanCookies, s as registerRemove, t as dependencyInstallCommand, u as removalPath } from "./worktree-Be_7NLKy.mjs";
1
+ import { a as porcelainPath, c as registerWarm, d as removalRemedy, f as removeWorktreeTarget, i as matchWorktreeEntry, l as removalBlockers, m as worktreeCommand, n as excludePodChurn, o as reclaimKeys, p as warmedWorkspace, r as excludeWatchmanCookies, s as registerRemove, t as dependencyInstallCommand, u as removalPath } from "./worktree-BSYlofkq.mjs";
2
2
  export { worktreeCommand as default, dependencyInstallCommand, excludePodChurn, excludeWatchmanCookies, matchWorktreeEntry, porcelainPath, reclaimKeys, registerRemove, registerWarm, removalBlockers, removalPath, removalRemedy, removeWorktreeTarget, warmedWorkspace };