stim 1.25.0 → 1.27.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 (182) hide show
  1. package/README.md +1 -1
  2. package/dist/{acquire-artifact-zA4S7RHE.mjs → acquire-artifact-BKN2Yuhg.mjs} +2 -2
  3. package/dist/{act-BbHS3oV8.mjs → act-ROviTF_t.mjs} +415 -118
  4. package/dist/{activity-BpjwrQXU.mjs → activity-Cd-ysFes.mjs} +6 -7
  5. package/dist/{agent-device-usage-output-Bnkerfod.mjs → agent-device-usage-output-C5nCKWp9.mjs} +5 -5
  6. package/dist/{android-CNZgRC-4.mjs → android--HBgpvpW.mjs} +5 -5
  7. package/dist/{android-BGwuK3Mc.mjs → android-Cd6w7_qw.mjs} +134 -57
  8. package/dist/{android-saBeB4lr.mjs → android-Deb9X3_Y.mjs} +37 -15
  9. package/dist/{android-Cjcj8MCw.mjs → android-DriNoAVy.mjs} +99 -47
  10. package/dist/{android-cas-BVqh2Zep.mjs → android-cas-D5e6ecUg.mjs} +4 -4
  11. package/dist/android-cas-compiler.mjs +1 -1
  12. package/dist/{android-project-CTYaETc0.d.mts → android-project-DUGMbq28.d.mts} +55 -1
  13. package/dist/api.d.mts +20 -7
  14. package/dist/api.mjs +42 -32
  15. package/dist/apk-signed-tail-BHQHx3Rm.mjs +142 -0
  16. package/dist/{artifact-Co8zixVx.mjs → artifact-0AGJYB9O.mjs} +28 -28
  17. package/dist/{artifact-DN8JNwqS.mjs → artifact-faemIZv5.mjs} +40 -30
  18. package/dist/{artifact-platform-CMRc0M_r.mjs → artifact-platform-BO2Uvk_A.mjs} +1 -1
  19. package/dist/{attempt-DW-mQqM7.mjs → attempt-ClyJlZPT.mjs} +4 -2
  20. package/dist/auto-placement-z-H5pJza.mjs +350 -0
  21. package/dist/{browser-web-CCgZsHmI.mjs → browser-web-slD8AvLp.mjs} +16 -17
  22. package/dist/{build-cache-CKCzxzxA.mjs → build-cache-gBJ-WKzA.mjs} +141 -37
  23. package/dist/{build-CAiw8Ezm.mjs → build-hS0QyFlQ.mjs} +38 -31
  24. package/dist/{build-plan-zCuHGlA8.mjs → build-plan-CBqYbzYM.mjs} +7 -6
  25. package/dist/{cache-manifest-BPXRONJz.mjs → cache-manifest-DEjqGGat.mjs} +1 -1
  26. package/dist/cache-manifest.mjs +1 -1
  27. package/dist/{budget-HyShrIpL.mjs → ccache-BWTze1Ls.mjs} +634 -1514
  28. package/dist/{cdp-BG3FJCCx.mjs → cdp-C3svvXiE.mjs} +1 -1
  29. package/dist/{chrome-BvV8ssI3.mjs → chrome-DyDWurWG.mjs} +1 -1
  30. package/dist/{cli-C4w607Pz.mjs → cli-ftXDLto1.mjs} +24 -23
  31. package/dist/cli.mjs +1 -1
  32. package/dist/{client-BQsmyp_-.mjs → client-xsdxrhWA.mjs} +77 -116
  33. package/dist/collector-run.d.mts +10 -9
  34. package/dist/collector-run.mjs +42 -27
  35. package/dist/{command-output-BBvS1H6v.mjs → command-output-Dj-WT4BP.mjs} +1 -1
  36. package/dist/{config-BZhXY15H.mjs → config-Cn94Jc0g.mjs} +343 -18
  37. package/dist/{launch-DscF1QfM.mjs → dependencies-BGokZ-Ng.mjs} +330 -279
  38. package/dist/{dependency-state-BwNCYG5Q.mjs → dependency-state-C3OtgG94.mjs} +14 -7
  39. package/dist/{detached-entry-KmieOKgN.mjs → detached-entry-BPlSaCwC.mjs} +1 -1
  40. package/dist/{dev-client-CHoXXZeg.mjs → dev-client-BMca82xo.mjs} +2 -2
  41. package/dist/{device-F5-4z9ef.mjs → device-BJm0irrq.mjs} +16 -16
  42. package/dist/{device-capacity-ZYaRALv5.mjs → device-capacity-6LP7QsaA.mjs} +103 -25
  43. package/dist/device-host-worker.mjs +19 -21
  44. package/dist/{device-ios-DkHBrmvH.mjs → device-ios-534c14fz.mjs} +288 -28
  45. package/dist/{device-lease-run-ogEeJ62K.mjs → device-lease-run-DwsGfjUN.mjs} +5 -5
  46. package/dist/{device-pool-BIg8MU8l.mjs → device-pool-BnQqvs6o.mjs} +3 -3
  47. package/dist/{device-B9FqTBYW.mjs → device-tM41-TUq.mjs} +25 -24
  48. package/dist/{doctor-A_Nr_fDe.mjs → doctor-Dbx1ZpD2.mjs} +1 -1
  49. package/dist/{doctor-k3P3PizH.mjs → doctor-DyqE9n1J.mjs} +28 -16
  50. package/dist/{doctor-Bm8TVpGn.mjs → doctor-F-3VUUyN.mjs} +128 -35
  51. package/dist/{doctor-fingerprint-zlujA1Gs.mjs → doctor-fingerprint-o7ZI9YLn.mjs} +9 -3
  52. package/dist/doctor-fingerprint.mjs +1 -1
  53. package/dist/{doctor-watchman-BovI1y3-.mjs → doctor-watchman-CxDbyrrt.mjs} +5 -5
  54. package/dist/{eas-build-CyDKNTBP.mjs → eas-build-CjNSWmjo.mjs} +4 -4
  55. package/dist/eas-fallback-9fqb46kW.mjs +87 -0
  56. package/dist/{eas-session-ledger-BMCA1gdO.mjs → eas-session-ledger-DrP4OuuM.mjs} +6 -6
  57. package/dist/{error-diagnostics-B1Mj_-7h.mjs → error-diagnostics-snej9k4j.mjs} +51 -25
  58. package/dist/{exec-VFRpu1iA.mjs → exec-aULwtNly.mjs} +57 -6
  59. package/dist/{gc-eaz403W6.mjs → gc-BRwAY3qT.mjs} +2 -2
  60. package/dist/{gc-B9jcnmIk.mjs → gc-CGZ1Yg88.mjs} +218 -72
  61. package/dist/{guide-DR0K0xW9.mjs → guide-_rfEh_zM.mjs} +839 -222
  62. package/dist/{hosted-android-Bvb2-ZxD.mjs → hosted-android-BMKzUNnY.mjs} +4 -4
  63. package/dist/{hosted-client-rsRqysJc.mjs → hosted-client-D7Pk_Oo1.mjs} +13 -9
  64. package/dist/{hosted-logs-CWKGYWNX.mjs → hosted-logs-B1gqQuva.mjs} +18 -12
  65. package/dist/hosted-logs-sync-Dg3qrZmV.mjs +195 -0
  66. package/dist/{hosted-macos-d0pv9Tth.mjs → hosted-macos-B9w4H8hc.mjs} +6 -6
  67. package/dist/{hosted-native-BxTizGU2.mjs → hosted-native-CdgaiuyP.mjs} +17 -17
  68. package/dist/{idle-shutdown-BIyfl0Zj.mjs → idle-shutdown-Cbvo5KEh.mjs} +21 -9
  69. package/dist/{ios-BRVM8b0P.mjs → ios-B5HlVMhQ.mjs} +138 -55
  70. package/dist/{ios-Dvt97HgQ.mjs → ios-Bk4mWbtS.mjs} +8 -8
  71. package/dist/{ios-ENC4sRPA.mjs → ios-CsRVik64.mjs} +7 -1
  72. package/dist/{ios-BQzvJlzw.mjs → ios-E26qSpkb.mjs} +94 -11
  73. package/dist/{ios-device-CKSvk0bu.mjs → ios-device-C_QkIf1Z.mjs} +3 -3
  74. package/dist/{ios-device-B6HK951C.mjs → ios-device-CiBA-er9.mjs} +1 -1
  75. package/dist/{ios-project-DCUDo06I.mjs → ios-project-D8Jcy_br.mjs} +22 -9
  76. package/dist/{ios-signing-4c_qXvQm.mjs → ios-signing-BJzvDPfU.mjs} +2 -2
  77. package/dist/{ios-state-CT9nV5SP.mjs → ios-state-BZ03NFgF.mjs} +1 -1
  78. package/dist/{js-swap-Z9HbC4cj.mjs → js-swap-Dg2a945i.mjs} +8 -7
  79. package/dist/{launch-D0lPvFFu.mjs → launch-CRyBeNsA.mjs} +53 -44
  80. package/dist/lightened-BCsdAGj_.mjs +171 -0
  81. package/dist/{logs-BsIRre8x.mjs → logs-CC_-ZzEE.mjs} +10 -174
  82. package/dist/{logs-Crs9y34Z.mjs → logs-aJQb-RDg.mjs} +112 -38
  83. package/dist/{macos-CcUlJPMu.mjs → macos-BGmTpnv9.mjs} +1 -1
  84. package/dist/{macos-D477nfzH.mjs → macos-DlCBhMw5.mjs} +73 -39
  85. package/dist/macos-run.mjs +1 -1
  86. package/dist/maintenance-run.mjs +30 -13
  87. package/dist/{metro-1pJgCX4U.mjs → metro-CvyD-xwe.mjs} +4 -4
  88. package/dist/{metro-gateway-Bp9gJQAN.mjs → metro-gateway-BnHdqMO_.mjs} +3 -4
  89. package/dist/{named-ports-BVbn8SvC.mjs → named-ports-BCyMWA6b.mjs} +3 -3
  90. package/dist/{native-android-BvMizJn1.mjs → native-android-DlpxCyOP.mjs} +17 -18
  91. package/dist/{native-gradle-artifact-inputs-BJscK4vN.mjs → native-gradle-artifact-inputs-C13qT7R_.mjs} +5 -5
  92. package/dist/{native-runtime-B9w_Qyz3.mjs → native-runtime-DqaIBO5w.mjs} +9 -9
  93. package/dist/{native-source-D-4Dh4JU.mjs → native-source-D1AzWiuP.mjs} +1 -1
  94. package/dist/{native-xcode-inputs-Cv4l-obn.mjs → native-xcode-inputs-B1W8SrxB.mjs} +3 -3
  95. package/dist/{native-xcode-ios-DGrg90hE.mjs → native-xcode-ios-QPP0Rm68.mjs} +17 -18
  96. package/dist/{ndjson-CgE_o3Dl.mjs → ndjson-Dy2W4vRa.mjs} +2 -2
  97. package/dist/offload-worker.d.mts +3 -1
  98. package/dist/offload-worker.mjs +34 -25
  99. package/dist/{operation-exec-CUZifp6Z.mjs → operation-exec-Dp4FuIGR.mjs} +1 -1
  100. package/dist/{ownership-jxxz-19m.mjs → ownership-Bx-0cku-.mjs} +3 -3
  101. package/dist/{page-CzEA_-5_.mjs → page-CQJlcj3x.mjs} +2 -2
  102. package/dist/{phone-reverses-CYb7RRAx.mjs → phone-reverses-C9yAaKEv.mjs} +18 -4
  103. package/dist/{placement-log-DjOXJRIH.mjs → placement-log-BXUbiZM6.mjs} +3 -3
  104. package/dist/{plan-placement-BqKgKHCi.mjs → plan-placement-UxnQjv5Z.mjs} +36 -10
  105. package/dist/{ports-DtS1Amb0.mjs → ports-uUrghqWN.mjs} +3 -3
  106. package/dist/prebuild-BDpToDgR.mjs +1246 -0
  107. package/dist/{project-BiC68mIp.mjs → project-DYj-HVx6.mjs} +17 -18
  108. package/dist/{pull-request-CbNlkFok.mjs → pull-request-BzLmzAIQ.mjs} +2 -2
  109. package/dist/pull-requests.mjs +1 -1
  110. package/dist/{react-native-android-DRYqoJc4.mjs → react-native-android-DDBccgJw.mjs} +56 -36
  111. package/dist/{react-native-build-CwZB-agu.mjs → react-native-build-DaK2IFyP.mjs} +9 -9
  112. package/dist/{react-native-doctor-BCrytK7h.mjs → react-native-doctor-B-Mw6DcR.mjs} +50 -9
  113. package/dist/{react-native-ios-Cr1buNFo.mjs → react-native-ios-DjYwUF9U.mjs} +45 -25
  114. package/dist/{recordings-BaoQ0t-J.mjs → recordings-C20iUZfp.mjs} +1 -1
  115. package/dist/{registration-CN6nlhcD.mjs → registration-BwCe64PH.mjs} +1 -1
  116. package/dist/{reload-Beftw2X3.mjs → reload-DJBeF_rC.mjs} +1 -1
  117. package/dist/{reload-FbSgMF8x.mjs → reload-fUdkH2_p.mjs} +16 -16
  118. package/dist/{remote-BuZj6AyU.mjs → remote-y6n99WMW.mjs} +22 -9
  119. package/dist/{result-CR2vk2cj.mjs → result-CTqBw2Te.mjs} +32 -21
  120. package/dist/{run-BtzE09Dl.mjs → run-DaCeNKRm.mjs} +3 -3
  121. package/dist/{selection-D5cxEl3t.mjs → selection-Bs8phwhN.mjs} +183 -62
  122. package/dist/{server-bare-CH9X0RLn.mjs → server-bare-BOh-iZEj.mjs} +2 -2
  123. package/dist/{server-command-CaBbDNU2.mjs → server-command-8CuA51Cv.mjs} +6 -6
  124. package/dist/{server-expo-Ck8EIidM.mjs → server-expo-ABQs2XFA.mjs} +4 -4
  125. package/dist/server-expo-Ba_Y21vB.mjs +2 -0
  126. package/dist/{settings-B5tCoq9N.mjs → settings-BDVI8Ivc.mjs} +331 -62
  127. package/dist/{settings-DzH9mGQZ.mjs → settings-CMHhQNwI.mjs} +24 -3
  128. package/dist/settings-payload-cm60Zhib.mjs +257 -0
  129. package/dist/settings-write-BdNRLlBn.mjs +185 -0
  130. package/dist/settings.schema.json +84 -39
  131. package/dist/{simslim-BjxszUAb.mjs → simslim-DCQwzoPy.mjs} +4 -3
  132. package/dist/{slot-launch-QeuJMlnJ.mjs → slot-launch-0l7RqSpr.mjs} +6 -6
  133. package/dist/{stage-D8xlRU2D.mjs → stage-F4cAfJGi.mjs} +2 -2
  134. package/dist/{start-C1JLjkNw.mjs → start-DcqnF9p8.mjs} +1 -1
  135. package/dist/{start-YMpNwLhh.mjs → start-DrPwER_2.mjs} +27 -23
  136. package/dist/{state-DMRNP7-4.mjs → state-BX1y5syV.mjs} +4 -5
  137. package/dist/{state-DPaM3u5K.mjs → state-CZxLyetD.mjs} +2 -3
  138. package/dist/{stats-CP7STzZw.mjs → stats-GxuCbles.mjs} +5 -5
  139. package/dist/{stats-report-n2U5plhk.mjs → stats-report-B86Cv7Uc.mjs} +1 -1
  140. package/dist/{status-Fect2w9R.mjs → status-7ULDEJ1e.mjs} +1 -1
  141. package/dist/{status-CRLiJ-O_.mjs → status-BfnK9pUd.mjs} +25 -26
  142. package/dist/{status-cNw6i0_t.mjs → status-Bj7ZYvvc.mjs} +1 -1
  143. package/dist/{status-watch-Bc2J4TZn.mjs → status-watch-BfabQn03.mjs} +5 -5
  144. package/dist/status-worker.mjs +1 -1
  145. package/dist/{stim-desktop-DS0mzR8U.mjs → stim-desktop-CbWo21kb.mjs} +2 -2
  146. package/dist/{stop-COP6PQqw.mjs → stop-CH79S3IZ.mjs} +5 -6
  147. package/dist/{stop-Db9Kh-UA.mjs → stop-D-EAr25B.mjs} +25 -22
  148. package/dist/{stop-Br7LKxBE.mjs → stop-x1Yu3He4.mjs} +2 -2
  149. package/dist/supervisor-run.d.mts +1 -0
  150. package/dist/supervisor-run.mjs +17 -18
  151. package/dist/{support-qKcbgmI5.mjs → support-Be0UeVZU.mjs} +10 -10
  152. package/dist/{support-Cxj9CmII.mjs → support-CNg_YsOk.mjs} +6 -6
  153. package/dist/{swiftpm-artifact-inputs-iY9fsmOc.mjs → swiftpm-artifact-inputs-uPqYvGBv.mjs} +4 -4
  154. package/dist/{swiftpm-macos-Bp_sn9P4.mjs → swiftpm-macos-Ch4YjY_A.mjs} +11 -12
  155. package/dist/toolchain-CbCG6C5Z.mjs +2413 -0
  156. package/dist/toolchain-JYAOquPg.mjs +2 -0
  157. package/dist/{trigger-CBMe2YLH.mjs → trigger-DMou-X7j.mjs} +3 -3
  158. package/dist/trigger-qp2ji5wE.mjs +2 -0
  159. package/dist/{warm-progress-BV3ZPmcY.mjs → warm-progress-C0RsbngN.mjs} +731 -728
  160. package/dist/{web-B4Yjyt1G.mjs → web-Cq_AQ4DK.mjs} +9 -10
  161. package/dist/web-Je6abcpz.mjs +2 -0
  162. package/dist/web-run.mjs +9 -9
  163. package/dist/windows-report.mjs +1 -1
  164. package/dist/{workspace-state-CPSp3mav.mjs → workspace-state-BjqdjnJR.mjs} +46 -8
  165. package/dist/{workspaces-C9w4aeXF.mjs → workspaces-DFbj07jp.mjs} +1801 -76
  166. package/dist/{worktree-CclFIe1Z.mjs → worktree-COAJ3-OD.mjs} +934 -511
  167. package/dist/{worktree-Ct9Gk3KL.mjs → worktree-JGUd_53L.mjs} +1 -1
  168. package/package.json +8 -8
  169. package/dist/ccache-h1FKhZeg.mjs +0 -143
  170. package/dist/created-devices-D2Aca-xu.mjs +0 -52
  171. package/dist/eas-fallback-gaZi-dJL.mjs +0 -381
  172. package/dist/hosted-ios-RtVcJH3u.mjs +0 -15
  173. package/dist/native-run-D5OJsGwA.mjs +0 -276
  174. package/dist/paths-DQtTgsBf.mjs +0 -42
  175. package/dist/prebuild-JUaqOLpc.mjs +0 -501
  176. package/dist/server-expo-C16Zf2k7.mjs +0 -2
  177. package/dist/settings-write-n0zwfohx.mjs +0 -360
  178. package/dist/toolchain-DB1aeqxO.mjs +0 -2
  179. package/dist/toolchain-VzLJzZ7O.mjs +0 -908
  180. package/dist/trigger-BLsHgAGR.mjs +0 -2
  181. package/dist/web-DS4UDWvf.mjs +0 -2
  182. package/dist/xcode-CiIIDnuD.mjs +0 -910
@@ -1,18 +1,19 @@
1
- import { m as workspaceLogsDir$1 } from "./paths-DQtTgsBf.mjs";
2
- import { W as parseDeviceSlotOption, _ as loadConfig$1, g as isPathPrefix } from "./config-BZhXY15H.mjs";
3
- import { f as refuseNoProject, v as launchErrorPreview } from "./command-output-BBvS1H6v.mjs";
4
- import { r as readWorkspaceState$1 } from "./workspace-state-CPSp3mav.mjs";
5
- import { n as findCommandWorkspace } from "./project-BiC68mIp.mjs";
6
- import { n as SOURCES$1, t as LEVELS$1 } from "./ndjson-CgE_o3Dl.mjs";
7
- import { a as followAgentActions, i as followHostedLogs, n as openWorkspaceLogs } from "./logs-BsIRre8x.mjs";
8
- import { t as errorDiagnostics } from "./error-diagnostics-B1Mj_-7h.mjs";
1
+ import { k as workspaceLogsDir$1, r as readWorkspaceState$1 } from "./workspace-state-BjqdjnJR.mjs";
2
+ import { W as parseDeviceSlotOption, _ as loadConfig$1, g as isPathPrefix$1 } from "./config-Cn94Jc0g.mjs";
3
+ import { f as refuseNoProject, v as launchErrorPreview } from "./command-output-Dj-WT4BP.mjs";
4
+ import { n as findCommandWorkspace } from "./project-DYj-HVx6.mjs";
5
+ import { n as SOURCES$1, t as LEVELS$1 } from "./ndjson-Dy2W4vRa.mjs";
6
+ import { i as followAgentActions, n as openWorkspaceLogs } from "./logs-CC_-ZzEE.mjs";
7
+ import { t as errorDiagnostics } from "./error-diagnostics-snej9k4j.mjs";
8
+ import { n as followHostedLogs } from "./hosted-logs-sync-Dg3qrZmV.mjs";
9
9
  import { t as watchStdoutReader } from "./stdout-reader-C8yjre1x.mjs";
10
10
  import { realpathSync } from "node:fs";
11
11
  import { relative, sep } from "node:path";
12
12
  import { configDir } from "@stim-cli/core";
13
- import { buildCriteria, compileGrep, followLogs, logFiles, parseSince, queryLogs, recordMatches, runId, sortByTs } from "@stim-cli/core/state";
13
+ import { buildCriteria, buildLedgerDir, compileGrep, fileSizes, followLogs, gcLogDir, logFiles, parseSince, queryLogs, readBuildLedger, readGcLog, recordMatches, runId, sortByTs } from "@stim-cli/core/state";
14
14
  import chalk from "chalk";
15
15
  //#region src/commands/logs.ts
16
+ const MACHINE_SOURCES = ["gc", "builds"];
16
17
  const LEVEL_WIDTH = 5;
17
18
  const SRC_WIDTH = 6;
18
19
  const INDENT = " ";
@@ -57,7 +58,9 @@ function parseTail(value) {
57
58
  function validateSources(sources) {
58
59
  if (sources === void 0 || sources === null) return { sources: void 0 };
59
60
  const list = Array.isArray(sources) ? sources : [sources];
60
- if (list.includes("all")) return { sources: [...SOURCES$1] };
61
+ if (list.includes("gc") && list.length > 1) return { error: "--source gc reads the machine-wide gc log and cannot be combined with other sources." };
62
+ if (list.includes("builds") && list.length > 1) return { error: "--source builds reads the machine-wide build ledger and cannot be combined with other sources." };
63
+ if (list.includes("all")) return { sources: SOURCES$1.filter((source) => !MACHINE_SOURCES.includes(source)) };
61
64
  const unknown = list.filter((s) => !SOURCES$1.includes(s));
62
65
  if (unknown.length > 0) return { error: `Unknown --source value(s): ${unknown.join(", ")}. Use one or more of: ${SOURCES$1.join(", ")}, or all.` };
63
66
  return { sources: list };
@@ -68,7 +71,7 @@ function validateLevel(level) {
68
71
  }
69
72
  const ERRORS_PRINT_CAP = 20;
70
73
  function nearestRegisteredLogsProject(root, candidates) {
71
- return candidates.filter((candidate) => candidate !== root && isPathPrefix(root, candidate)).toSorted((a, b) => {
74
+ return candidates.filter((candidate) => candidate !== root && isPathPrefix$1(root, candidate)).toSorted((a, b) => {
72
75
  const depth = (path) => relative(root, path).split(sep).length;
73
76
  return depth(a) - depth(b) || a.length - b.length || a.localeCompare(b);
74
77
  })[0] ?? null;
@@ -97,39 +100,21 @@ const LEVEL_COLOURS = {
97
100
  fatal: chalk.bgRed
98
101
  };
99
102
  function logsCommand(program) {
100
- program.command("logs").description("Query this workspace's merged NDJSON log timeline (bundler, client, device, build, agent actions, maintenance). Prints and exits; an existing timeline with nothing matching is a successful, empty result. Use --follow to stream.").option("--slot <name>", "Only this device slot's records, plus the shared Metro and app client records once it has launched", parseDeviceSlotOption).option("--source <s...>", "Only these sources: metro, client, device, build, agent, maintenance, placement, or all").option("--level <l>", `Minimum level: ${LEVELS$1.join(", ")}`).option("--since <d>", "Only records newer than this, e.g. 30s, 5m, 2h").option("--grep <re>", "Only records whose message matches this regular expression").option("--tail <n>", "Only the last n matching records").option("--errors", "Errors and fatals since the last marker, from metro, client and build, plus confirmed native app-crash reports and stim web browser errors. Add --source maintenance for maintenance failures, or --source device or --source all for general device errors.").option("--follow", "Keep streaming new records until interrupted").option("--json", "Emit the raw records, one per line (valid NDJSON; zero matches is zero bytes, exit 0)").action(async (opts) => {
103
+ program.command("logs").description("Query this workspace's merged NDJSON log timeline (bundler, client, device, build, agent actions, maintenance). Prints and exits; an existing timeline with nothing matching is a successful, empty result. Use --follow to stream.").option("--slot <name>", "Only this device slot's records, plus the shared Metro and app client records once it has launched", parseDeviceSlotOption).option("--source <s...>", "Only these sources: metro, client, device, build, agent, maintenance, placement, or all; gc alone reads the machine-wide gc log of what gc and maintenance cleared, and builds alone reads the machine-wide ledger of native builds").option("--level <l>", `Minimum level: ${LEVELS$1.join(", ")}`).option("--since <d>", "Only records newer than this, e.g. 30s, 5m, 2h").option("--grep <re>", "Only records whose message matches this regular expression").option("--tail <n>", "Only the last n matching records").option("--errors", "Errors and fatals since the last marker, from metro, client and build, plus confirmed native app-crash reports and stim web browser errors. Add --source maintenance for maintenance failures, or --source device or --source all for general device errors.").option("--follow", "Keep streaming new records until interrupted").option("--json", "Emit the raw records, one per line (valid NDJSON; zero matches is zero bytes, exit 0)").action(async (opts) => {
104
+ const requested = [opts.source ?? []].flat();
105
+ const [only] = requested;
106
+ if (requested.length === 1 && only !== void 0 && MACHINE_SOURCES.includes(only)) {
107
+ const { minLevel, tail } = validateOptions(opts);
108
+ printMachineLog(only === "gc" ? GC_LOG : BUILD_LEDGER, opts, opts.errors ? "error" : minLevel, tail);
109
+ return;
110
+ }
101
111
  const root = findCommandWorkspace(process.cwd());
102
112
  if (!root) {
103
113
  refuseNoProject({ json: false });
104
114
  return;
105
115
  }
106
116
  const dir = workspaceLogsDir$1(root);
107
- let sources;
108
- if (opts.source !== void 0) {
109
- const checked = validateSources(opts.source);
110
- if (checked.error) fail(checked.error);
111
- sources = checked.sources;
112
- }
113
- let minLevel;
114
- if (opts.level !== void 0) {
115
- const checked = validateLevel(opts.level);
116
- if (checked.error) fail(checked.error);
117
- minLevel = checked.level;
118
- }
119
- if (opts.since !== void 0) {
120
- const parsed = parseSince(opts.since);
121
- if (parsed.error) fail(parsed.error);
122
- }
123
- let tail;
124
- if (opts.tail !== void 0) {
125
- const parsed = parseTail(opts.tail);
126
- if (parsed.error) fail(parsed.error);
127
- tail = parsed.n;
128
- }
129
- if (opts.grep !== void 0) {
130
- const compiled = compileGrep(opts.grep);
131
- if (compiled.error) fail(compiled.error);
132
- }
117
+ const { sources, minLevel, tail } = validateOptions(opts);
133
118
  requireLogsWorkspace(root, dir);
134
119
  const query = {
135
120
  slot: opts.slot,
@@ -242,6 +227,95 @@ function logsCommand(program) {
242
227
  process.on("SIGTERM", finish);
243
228
  });
244
229
  }
230
+ function validateOptions(opts) {
231
+ let sources;
232
+ if (opts.source !== void 0) {
233
+ const checked = validateSources(opts.source);
234
+ if (checked.error) fail(checked.error);
235
+ sources = checked.sources;
236
+ }
237
+ let minLevel;
238
+ if (opts.level !== void 0) {
239
+ const checked = validateLevel(opts.level);
240
+ if (checked.error) fail(checked.error);
241
+ minLevel = checked.level;
242
+ }
243
+ if (opts.since !== void 0) {
244
+ const parsed = parseSince(opts.since);
245
+ if (parsed.error) fail(parsed.error);
246
+ }
247
+ let tail;
248
+ if (opts.tail !== void 0) {
249
+ const parsed = parseTail(opts.tail);
250
+ if (parsed.error) fail(parsed.error);
251
+ tail = parsed.n;
252
+ }
253
+ if (opts.grep !== void 0) {
254
+ const compiled = compileGrep(opts.grep);
255
+ if (compiled.error) fail(compiled.error);
256
+ }
257
+ return {
258
+ sources,
259
+ minLevel,
260
+ tail
261
+ };
262
+ }
263
+ const GC_LOG = {
264
+ source: "gc",
265
+ dir: gcLogDir,
266
+ read: readGcLog
267
+ };
268
+ const BUILD_LEDGER = {
269
+ source: "builds",
270
+ dir: buildLedgerDir,
271
+ read: readBuildLedger,
272
+ key: (record) => `${record.id}:${record.ts}`
273
+ };
274
+ function printMachineLog(log, opts, minLevel, tail) {
275
+ const printed = /* @__PURE__ */ new Set();
276
+ const emit = (record) => {
277
+ if (opts.follow && log.key) {
278
+ const key = log.key(record);
279
+ if (printed.has(key)) return;
280
+ printed.add(key);
281
+ }
282
+ console.log(opts.json ? JSON.stringify(record) : formatRecord(record, { paint: record.level ? LEVEL_COLOURS[record.level] : void 0 }));
283
+ };
284
+ const query = {
285
+ sources: [log.source],
286
+ minLevel,
287
+ since: opts.since,
288
+ grep: opts.grep
289
+ };
290
+ const dir = log.dir();
291
+ const offsets = opts.follow ? fileSizes(dir) : null;
292
+ const all = log.read();
293
+ const records = queryLogs({
294
+ ...query,
295
+ records: all,
296
+ tail
297
+ });
298
+ for (const record of records) emit(record);
299
+ if (opts.follow && log.key) for (const record of all) printed.add(log.key(record));
300
+ if (!opts.follow) {
301
+ if (records.length === 0 && !opts.json) console.error(chalk.dim(`No matching log records in ${dir}`));
302
+ return;
303
+ }
304
+ const stop = followLogs({
305
+ dir,
306
+ offsets,
307
+ criteria: buildCriteria(query),
308
+ onRecord: emit
309
+ });
310
+ const finish = () => {
311
+ stop();
312
+ stopReader();
313
+ process.exit(0);
314
+ };
315
+ const stopReader = watchStdoutReader(finish);
316
+ process.on("SIGINT", finish);
317
+ process.on("SIGTERM", finish);
318
+ }
245
319
  function fail(message) {
246
320
  console.error(chalk.red(message));
247
321
  process.exit(1);
@@ -1,2 +1,2 @@
1
- import { n as runMacos, r as waitForLaunchServices, t as macosCommand } from "./macos-D477nfzH.mjs";
1
+ import { n as runMacos, r as waitForLaunchServices, t as macosCommand } from "./macos-DlCBhMw5.mjs";
2
2
  export { macosCommand as default, runMacos, waitForLaunchServices };
@@ -1,37 +1,37 @@
1
- import { _ as spawnDeclared, c as throwIfCancelled, t as getExecutor, u as withWorkspaceProcessLock, x as withDrainingCancellation } from "./exec-VFRpu1iA.mjs";
2
- import { d as workspaceDir, l as workspaceAgentDeviceDir, m as workspaceLogsDir$1, r as ensureWorkspaceStorageAsync } from "./paths-DQtTgsBf.mjs";
3
- import { E as upsertProject, O as withConfigLockAsync$1, u as getConcurrencyLimits } from "./config-BZhXY15H.mjs";
4
- import { l as phaseLine } from "./command-output-BBvS1H6v.mjs";
5
- import { a as recordWorkspaceUseAsync, f as writeWorkspaceStateAsync } from "./workspace-state-CPSp3mav.mjs";
6
- import { Y as resolveProjectSettingsAsync, a as SETTING_SHAPE_REMEDY, tt as settingShapeErrors } from "./settings-B5tCoq9N.mjs";
7
- import { f as projectRegistry, i as findProjectRoot$1, s as ownedDeviceLabel } from "./project-BiC68mIp.mjs";
8
- import { i as macosProcess, n as macosDir, o as requiredMacosRecord, r as macosLogFile } from "./state-DPaM3u5K.mjs";
9
- import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
10
- import { B as recordFinishedBuild, H as startBuildProgress, M as NO_BUILD_PROGRESS, Rn as processContext, U as tapBuildLog, z as recordBuildPhase, zn as runProcessOperation } from "./budget-HyShrIpL.mjs";
11
- import { d as runCancellationSignal, f as withNativeBuildRun } from "./native-run-D5OJsGwA.mjs";
12
- import { L as acquireBuildSlot, z as releaseBuildSlot } from "./workspaces-C9w4aeXF.mjs";
13
- import { D as sanitizeDeviceLabel } from "./ios-BQzvJlzw.mjs";
14
- import { S as setRemoteLogSink, c as offloadPlacement, i as closeOffload, l as placementLoad, n as buildPlacementCandidates, o as offloadBuild, r as chooseBuildMachine, u as remotePhaseText } from "./client-BQsmyp_-.mjs";
15
- import { a as parseBuildMachineOption, c as resolveBuildPlacement, i as namedBuildMachine, o as requireLocalBuild, t as OffloadRefusal } from "./selection-D5cxEl3t.mjs";
16
- import { l as connectHost } from "./hosted-client-rsRqysJc.mjs";
17
- import { t as placeHostedMacos } from "./hosted-macos-d0pv9Tth.mjs";
18
- import { r as stopMacosAppHeld, t as stopBundleInstances } from "./stop-COP6PQqw.mjs";
1
+ import { _ as spawnDeclared, c as throwIfCancelled, t as getExecutor, u as withWorkspaceProcessLock, x as withDrainingCancellation } from "./exec-aULwtNly.mjs";
2
+ import { E as workspaceDir, a as recordWorkspaceUseAsync, f as writeWorkspaceStateAsync, k as workspaceLogsDir$1, v as ensureWorkspaceStorageAsync, w as workspaceAgentDeviceDir } from "./workspace-state-BjqdjnJR.mjs";
3
+ import { E as upsertProject, O as withConfigLockAsync$1, u as getConcurrencyLimits } from "./config-Cn94Jc0g.mjs";
4
+ import { l as phaseLine } from "./command-output-Dj-WT4BP.mjs";
5
+ import { Z as resolveProjectSettingsAsync, a as SETTING_SHAPE_REMEDY, it as settingValueAt, rt as settingShapeErrors } from "./settings-BDVI8Ivc.mjs";
6
+ import { f as projectRegistry, i as findProjectRoot$1, s as ownedDeviceLabel } from "./project-DYj-HVx6.mjs";
7
+ import { i as macosProcess, n as macosDir, o as requiredMacosRecord, r as macosLogFile } from "./state-CZxLyetD.mjs";
8
+ import { i as createNdjsonWriter } from "./ndjson-Dy2W4vRa.mjs";
9
+ import { En as runProcessOperation, Tn as processContext } from "./ccache-BWTze1Ls.mjs";
10
+ import { K as recordBuildPhase, Q as errorRemedy, X as tapBuildLog, Y as startBuildProgress, q as recordFinishedBuild, xt as releaseBuildSlot, yt as acquireBuildSlot, z as NO_BUILD_PROGRESS } from "./workspaces-DFbj07jp.mjs";
11
+ import { ot as runCancellationSignal, st as withNativeBuildRun } from "./toolchain-CbCG6C5Z.mjs";
12
+ import { O as sanitizeDeviceLabel } from "./ios-E26qSpkb.mjs";
13
+ import { S as setRemoteLogSink, c as offloadPlacement, i as closeOffload, l as placementLoad, n as buildPlacementCandidates, o as offloadBuild, r as chooseBuildMachine, u as remotePhaseText } from "./client-xsdxrhWA.mjs";
14
+ import { d as resolveBuildPlacement, l as requireLocalBuild, n as automaticBuild, o as namedBuildMachine, s as parseBuildMachineOption, t as OffloadRefusal } from "./selection-Bs8phwhN.mjs";
15
+ import { l as connectHost } from "./hosted-client-D7Pk_Oo1.mjs";
16
+ import { t as placeHostedMacos } from "./hosted-macos-B9w4H8hc.mjs";
17
+ import { r as stopMacosAppHeld, t as stopBundleInstances } from "./stop-CH79S3IZ.mjs";
19
18
  import { t as spawnEntry } from "./spawn-entry-jw19m8Nl.mjs";
20
- import { t as buildPlacementRecord } from "./placement-log-DjOXJRIH.mjs";
21
- import { t as reidentifyBundle } from "./stage-D8xlRU2D.mjs";
22
- import { t as validateMacosArtifactPlatform } from "./artifact-platform-CMRc0M_r.mjs";
23
- import { t as waitForMacosRegistration } from "./registration-CN6nlhcD.mjs";
19
+ import { t as buildPlacementRecord } from "./placement-log-BXUbiZM6.mjs";
20
+ import { n as devicePlacementLine, t as automaticDevicePlacement } from "./auto-placement-z-H5pJza.mjs";
21
+ import { t as reidentifyBundle } from "./stage-F4cAfJGi.mjs";
22
+ import { t as validateMacosArtifactPlatform } from "./artifact-platform-BO2Uvk_A.mjs";
23
+ import { t as waitForMacosRegistration } from "./registration-BwCe64PH.mjs";
24
24
  import { createHash, randomUUID } from "node:crypto";
25
25
  import { closeSync, existsSync, openSync, promises, realpathSync, renameSync } from "node:fs";
26
26
  import { join } from "node:path";
27
27
  import { LOG_ROTATE_BYTES, ambientEnv } from "@stim-cli/core";
28
- import { machineCapacity, validHostedAppArguments } from "@stim-cli/core/state";
28
+ import { machineCapacity, placementWord, validHostedAppArguments } from "@stim-cli/core/state";
29
29
  //#region src/macos/build.ts
30
30
  async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displayName, scratch, writer, note, record, buildMachine, hostServerKey, progress = NO_BUILD_PROGRESS }) {
31
31
  const signal = runCancellationSignal(context) ?? context.signal;
32
32
  return withDrainingCancellation(context, signal, async () => {
33
33
  throwIfCancelled(signal, "macOS build");
34
- const { mode, machines, localEnabled } = buildPlacementCandidates(buildMachine);
34
+ const { machines, localEnabled } = buildPlacementCandidates(buildMachine);
35
35
  const builder = namedBuildMachine(buildMachine) ? machines[0] : void 0;
36
36
  const runsOnWorker = hostServerKey !== void 0 && builder?.serverKey === hostServerKey;
37
37
  if (record) record.buildMachine = buildMachine;
@@ -64,7 +64,7 @@ async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displ
64
64
  }
65
65
  }));
66
66
  if (namedBuildMachine(buildMachine)) throw new OffloadRefusal(buildMachine, reason);
67
- requireLocalBuild(buildMachine);
67
+ requireLocalBuild(buildMachine, reason);
68
68
  offloadFallback = reason;
69
69
  if (record) record.offloadFallback = reason;
70
70
  writer.write({
@@ -162,7 +162,6 @@ async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displ
162
162
  };
163
163
  const here = machineCapacity();
164
164
  const placement = offloadPlacement({
165
- mode,
166
165
  localEnabled,
167
166
  machines: machines.length,
168
167
  here,
@@ -174,7 +173,6 @@ async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displ
174
173
  const chosen = await chooseBuildMachine({
175
174
  projectRoot: root,
176
175
  target: await recipe.offload.target(runsOnWorker),
177
- mode,
178
176
  here,
179
177
  machines,
180
178
  selected: buildMachine,
@@ -269,7 +267,7 @@ async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displ
269
267
  try {
270
268
  slot = await acquireBuildSlot({
271
269
  signal,
272
- automatic: buildMachine === "auto",
270
+ automatic: automaticBuild(buildMachine),
273
271
  max: getConcurrencyLimits().maxBuilds,
274
272
  root,
275
273
  logFile: writer.file,
@@ -346,7 +344,7 @@ async function planMacos(context, root, buildMachineFlag) {
346
344
  if (selected.failure) throw Object.assign(new Error(selected.failure.message), selected.failure);
347
345
  const macos = settings.macos;
348
346
  if (!macos?.product || !macos.infoPlist) throw Object.assign(/* @__PURE__ */ new Error("Set macos.product and macos.infoPlist explicitly in .stim.json. See stim guide macos."), { code: "STIM_BAD_ARG" });
349
- const { swiftpmMacosProject } = await import("./swiftpm-macos-Bp_sn9P4.mjs");
347
+ const { swiftpmMacosProject } = await import("./swiftpm-macos-Ch4YjY_A.mjs");
350
348
  const recipe = await swiftpmMacosProject(root).prepare(context, settings);
351
349
  let identity = null;
352
350
  let cacheHit = false;
@@ -375,13 +373,11 @@ async function planMacos(context, root, buildMachineFlag) {
375
373
  //#endregion
376
374
  //#region src/commands/macos.ts
377
375
  /**
378
- * Builds the Debug app and launches it here, or with `remote` on that approved remote Mac. A named host never falls
379
- * back to a local launch.
376
+ * Builds the Debug app and launches it where `remoteFlag` or `macos.remote` says: here, on one named approved remote
377
+ * Mac with no fallback, or on the Mac an automatic placement word chooses. A recorded hosted app keeps its Mac.
380
378
  */
381
- async function runMacos(context, root, note = console.error, remote, buildMachineFlag) {
382
- const backend = remote?.trim().toLowerCase();
383
- if (backend === "eas" || backend === "proxy") throw Object.assign(/* @__PURE__ */ new Error("stim macos --remote takes a remote Mac name from remote.machines; macOS has no eas or proxy backend."), { code: "STIM_BAD_ARG" });
384
- if (backend === "auto") throw Object.assign(/* @__PURE__ */ new Error("stim macos --remote auto is not available yet: automatic placement has not shipped. Name a hosting Mac from remote.machines."), { code: "STIM_BAD_ARG" });
379
+ async function runMacos(context, root, note = console.error, remoteFlag, buildMachineFlag) {
380
+ refuseDeviceBackend(remoteFlag);
385
381
  if (process.platform !== "darwin") throw new Error("stim macos requires a Mac with Swift installed.");
386
382
  root = realpathSync(root);
387
383
  const operation = projectRegistry.selectMacos(root);
@@ -398,6 +394,9 @@ async function runMacos(context, root, note = console.error, remote, buildMachin
398
394
  const selected = resolveBuildPlacement(buildMachineFlag);
399
395
  if (selected.failure) throw Object.assign(new Error(selected.failure.message), selected.failure);
400
396
  const buildMachine = selected.selected;
397
+ const configured = settingValueAt(settings, "macos.remote");
398
+ const requested = remoteFlag ?? (typeof configured === "string" ? configured : void 0);
399
+ refuseDeviceBackend(requested);
401
400
  const macos = await (await operation.load()).prepare(context, settings);
402
401
  await ensureWorkspaceStorageAsync(root, context.signal);
403
402
  return withNativeBuildRun(context, root, {
@@ -413,6 +412,14 @@ async function runMacos(context, root, note = console.error, remote, buildMachin
413
412
  });
414
413
  return withWorkspaceProcessLock(workspaceDir(root), "macos-launch", async () => {
415
414
  const previous = requiredMacosRecord(root);
415
+ const remote = await macosHost({
416
+ requested,
417
+ previous,
418
+ root,
419
+ buildMachine,
420
+ note,
421
+ signal: context.signal
422
+ });
416
423
  if (previous?.host && previous.host.machine !== remote) throw new Error(`This workspace's macOS app runs on ${previous.host.machine}. Run stim stop first, then stim macos${remote ? ` --remote ${remote}` : ""}.`);
417
424
  if (remote && !validHostedAppArguments(macos.arguments)) throw new Error("macos.arguments is too large for a hosted app: at most 32 arguments of 1024 characters (8192 in total), without NUL or line breaks.");
418
425
  let hostServerKey;
@@ -509,6 +516,29 @@ async function runMacos(context, root, note = console.error, remote, buildMachin
509
516
  }).finally(() => progress.clear());
510
517
  }, { write: note });
511
518
  }
519
+ function refuseDeviceBackend(requested) {
520
+ if (requested !== void 0 && ["eas", "proxy"].includes(requested.trim().toLowerCase())) throw Object.assign(/* @__PURE__ */ new Error("stim macos --remote and macos.remote take local, auto, remote, remote-only or a remote Mac name from remote.machines; macOS has no eas or proxy backend."), { code: "STIM_BAD_ARG" });
521
+ }
522
+ async function macosHost({ requested, previous, root, buildMachine, note, signal }) {
523
+ if (requested === void 0) return void 0;
524
+ const word = placementWord(requested);
525
+ if (word === "local") return void 0;
526
+ if (word === null) return requested.trim();
527
+ if (previous?.host) return previous.host.machine;
528
+ const placed = await automaticDevicePlacement({
529
+ root,
530
+ slot: "default",
531
+ platform: "macos",
532
+ placement: word,
533
+ selectors: {},
534
+ buildMachine,
535
+ noWait: false,
536
+ onWait: (line) => note(phaseLine("placement:", line)),
537
+ signal
538
+ });
539
+ note(phaseLine("placement:", devicePlacementLine(placed.placement, placed.skipped)));
540
+ return placed.placement.decision === "hosted" ? placed.placement.machine : void 0;
541
+ }
512
542
  async function buildBundle(context, root, recipe, record, hosted, hostServerKey, note, progress = NO_BUILD_PROGRESS) {
513
543
  const started = Date.parse(record.build.startedAt);
514
544
  const scratch = join(macosDir(root), "build");
@@ -567,13 +597,13 @@ async function buildBundle(context, root, recipe, record, hosted, hostServerKey,
567
597
  supervisor: void 0,
568
598
  build
569
599
  } });
570
- recordMacosBuild(root, build, progress.steps());
600
+ recordMacosBuild(root, build, progress.steps(), errorRemedy(error));
571
601
  throw error;
572
602
  } finally {
573
603
  writer.close();
574
604
  }
575
605
  }
576
- function recordMacosBuild(root, build, compileSteps) {
606
+ function recordMacosBuild(root, build, compileSteps, remedy) {
577
607
  recordFinishedBuild(root, {
578
608
  platform: "macos",
579
609
  status: build.state === "ok" ? "ok" : "failed",
@@ -589,7 +619,11 @@ function recordMacosBuild(root, build, compileSteps) {
589
619
  builtOn: build.builtOn,
590
620
  offloadedTo: build.offloadedTo,
591
621
  offloadFallback: build.offloadFallback,
592
- ...compileSteps === null ? {} : { compileSteps }
622
+ ...compileSteps === null ? {} : { compileSteps },
623
+ ...build.error ? { ledger: {
624
+ message: build.error,
625
+ remedy
626
+ } } : {}
593
627
  });
594
628
  }
595
629
  const LAUNCH_SERVICES_CALL_MS = 2e3;
@@ -660,7 +694,7 @@ function launchPayload(root, record) {
660
694
  };
661
695
  }
662
696
  function macosCommand(program) {
663
- program.command("macos").description("Build and launch an owned Swift Package macOS Debug app.").option("--remote-build <value>", "Build on auto, local, or one named machine; a name refuses without fallback", parseBuildMachineOption).option("--json", "print one launch or plan payload; build output goes to stderr").option("--plan", "validate the next SwiftPM Debug build without building or launching").option("--remote <machine>", "run it on this approved remote Mac from remote.machines").action(async (options) => {
697
+ program.command("macos").description("Build and launch an owned Swift Package macOS Debug app.").option("--remote-build <value>", "Build on local, auto, remote (remote machines first), remote-only (never here), or one named machine; a name refuses without fallback", parseBuildMachineOption).option("--json", "print one launch or plan payload; build output goes to stderr").option("--plan", "validate the next SwiftPM Debug build without building or launching").option("--remote <placement>", "run it here (local), on the Mac a placement word chooses (auto, remote, remote-only), or on one approved remote Mac from remote.machines").action(async (options) => {
664
698
  const root = findProjectRoot$1(process.cwd());
665
699
  if (options.plan) {
666
700
  try {
@@ -1,2 +1,2 @@
1
- import { n as runMacosSupervisor, t as logLines } from "./run-BtzE09Dl.mjs";
1
+ import { n as runMacosSupervisor, t as logLines } from "./run-DaCeNKRm.mjs";
2
2
  export { logLines, runMacosSupervisor };
@@ -1,12 +1,11 @@
1
- import { P as formatBytes } from "./config-BZhXY15H.mjs";
2
- import { Dt as deviceSweepIsScoped, u as resolveBudget } from "./budget-HyShrIpL.mjs";
3
- import { P as memoryCulpritsUnder, z as memoryCulpritAdvice } from "./ios-BQzvJlzw.mjs";
4
- import { T as maintenanceLogger } from "./client-BQsmyp_-.mjs";
1
+ import { P as formatBytes } from "./config-Cn94Jc0g.mjs";
2
+ import { A as diskPressureLevel, I as maintenanceItem, L as openGcLog, M as levelStillShort, N as lowestFree, R as maintenanceLogger, _ as resolveBudget, j as levelFloors, mt as deviceSweepIsScoped } from "./ccache-BWTze1Ls.mjs";
3
+ import { I as memoryCulpritsUnder, V as memoryCulpritAdvice } from "./ios-E26qSpkb.mjs";
5
4
  import { t as resolveMaintenanceSettings } from "./settings-Djl-mpjX.mjs";
6
- import { t as relaunchWithLogFile } from "./detached-entry-KmieOKgN.mjs";
7
- import { D as measureDisk, F as levelStillShort, I as lowestFree, M as sizeScanDeferred, N as diskPressureLevel, P as levelFloors, j as measureSizes, k as measurePressure } from "./worktree-CclFIe1Z.mjs";
8
- import { i as plannedMaintenance, m as measureOwnedDevices, n as diskRecovered, o as triggeringRoot, r as executeAction } from "./act-BbHS3oV8.mjs";
9
- import { r as due, t as capChildLog } from "./attempt-DW-mQqM7.mjs";
5
+ import { C as measureSizes, w as sizeScanDeferred, x as measurePressure, y as measureDisk } from "./worktree-COAJ3-OD.mjs";
6
+ import { t as relaunchWithLogFile } from "./detached-entry-BPlSaCwC.mjs";
7
+ import { g as measureOwnedDevices, i as plannedMaintenance, n as diskRecovered, o as triggeringRoot, r as executeAction } from "./act-ROviTF_t.mjs";
8
+ import { r as due, t as capChildLog } from "./attempt-ClyJlZPT.mjs";
10
9
  import { releaseClaim, tryAcquireClaim } from "@stim-cli/core/ownership-claim";
11
10
  import { randomBytes } from "node:crypto";
12
11
  import { appendFileSync, mkdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
@@ -82,6 +81,7 @@ const EXECUTION_ORDER = {
82
81
  "would-clear-build-dirs": 3,
83
82
  "would-empty-cache": 3,
84
83
  "would-remove-worktree": 4,
84
+ "would-shutdown-device": 5,
85
85
  "would-stop-workspace": 5,
86
86
  "would-delete-devices": 5,
87
87
  "would-delete-dependencies": 6,
@@ -118,6 +118,7 @@ function describeDone(action) {
118
118
  case "would-stop-gradle-daemons": return "Stopped idle Gradle and Kotlin daemons";
119
119
  case "would-delete-gradle-version": return `Deleted the unpinned Gradle ${action.target} caches and distributions`;
120
120
  case "would-stop-workspace": return `Stopped ${name} and deleted its owned devices`;
121
+ case "would-shutdown-device": return `Shut down the idle device ${action.target} of ${name}`;
121
122
  default: return `Unregistered the stale cache ${action.target}`;
122
123
  }
123
124
  }
@@ -135,6 +136,7 @@ async function runMaintenance(trigger) {
135
136
  }
136
137
  if (!claim) return;
137
138
  let logger;
139
+ let gcLog;
138
140
  try {
139
141
  const settings = resolveMaintenanceSettings();
140
142
  if (settings.mode === "off") return;
@@ -165,6 +167,11 @@ async function runMaintenance(trigger) {
165
167
  } catch (error) {
166
168
  noteWriteError(error);
167
169
  }
170
+ gcLog = openGcLog({
171
+ trigger: "maintenance",
172
+ runId: `p-${claim.claimId}`,
173
+ via: trigger
174
+ });
168
175
  const record = (event, level, msg, fields = {}) => {
169
176
  let entry = null;
170
177
  try {
@@ -196,7 +203,7 @@ async function runMaintenance(trigger) {
196
203
  delete state.deferredAt?.[check];
197
204
  keepState();
198
205
  try {
199
- if (check === "worktree" || check === "sweep") continue;
206
+ if (check === "worktree" || check === "sweep" || check === "idle") continue;
200
207
  if (check === "pressure") {
201
208
  state.pressure = measurePressure(settings, state.pressure, state.lastAt[check]);
202
209
  state.pressure.diskLevel = diskPressureLevel(lowestFree(state.pressure.disk), budget, settings);
@@ -245,11 +252,13 @@ async function runMaintenance(trigger) {
245
252
  });
246
253
  }
247
254
  }
255
+ const plannedWorktrees = ran.has("worktree") || ran.has("sweep") && settings.removeFinishedWorktrees && settings.removeIdleWorktrees;
248
256
  let result;
249
257
  try {
250
258
  result = await plannedMaintenance(state.pressure, state.sizes, settings, {
251
259
  sweep: ran.has("sweep"),
252
- worktrees: ran.has("worktree")
260
+ worktrees: plannedWorktrees,
261
+ idle: ran.has("idle")
253
262
  });
254
263
  } catch (error) {
255
264
  const message = error instanceof Error ? error.message : String(error);
@@ -299,6 +308,7 @@ async function runMaintenance(trigger) {
299
308
  action,
300
309
  outcome
301
310
  });
311
+ if (outcome.status !== "kept") gcLog?.record(maintenanceItem(action, outcome));
302
312
  const fields = {
303
313
  action: {
304
314
  kind: executedKind(action),
@@ -308,7 +318,7 @@ async function runMaintenance(trigger) {
308
318
  },
309
319
  ...action.workspace && action.kind !== "would-remove-worktree" ? { workspace: action.workspace } : {}
310
320
  };
311
- if (outcome.status === "done") record("maintenance_action", action.kind === "would-remove-worktree" ? "warn" : "info", `${describeDone(action)} (${formatBytes(outcome.bytes)}): ${action.reason}`, fields);
321
+ if (outcome.status === "done") record("maintenance_action", action.kind === "would-remove-worktree" ? "warn" : "info", `${describeDone(action)} (${formatBytes(outcome.bytes)}): ${action.kind === "would-remove-worktree" ? outcome.detail : action.reason}`, fields);
312
322
  else if (outcome.status === "failed") {
313
323
  failures.push(`${describeDone(action)} failed: ${outcome.detail}`);
314
324
  record("maintenance_failure", "error", `Could not process ${action.target}: ${outcome.detail}`, {
@@ -318,6 +328,7 @@ async function runMaintenance(trigger) {
318
328
  });
319
329
  } else if (!loggedSkips.has(action.target)) {
320
330
  loggedSkips.add(action.target);
331
+ gcLog?.record(maintenanceItem(action, outcome));
321
332
  record("maintenance_skip", "info", `Kept ${action.target}: ${outcome.detail}`, {
322
333
  target: action.target,
323
334
  reason: outcome.detail,
@@ -327,7 +338,7 @@ async function runMaintenance(trigger) {
327
338
  }
328
339
  return results;
329
340
  }
330
- const retained = state.plan.filter((action) => (action.check === "sweep" || action.check === "worktree") && !ran.has(action.check));
341
+ const retained = state.plan.filter((action) => action.check === "sweep" && !ran.has("sweep") || action.check === "worktree" && !plannedWorktrees || action.kind === "would-shutdown-device" && action.check === void 0 && !ran.has("idle"));
331
342
  const previousActions = new Set(state.plan.map(actionKey));
332
343
  const previousSkips = new Set(state.skipKeys ?? []);
333
344
  const nextSkips = new Set(result.skips.map((skip) => skip.target));
@@ -371,7 +382,13 @@ async function runMaintenance(trigger) {
371
382
  if (done.length || measuredSizes || blockedChanged || (state.pressure?.diskLevel ?? 0) > 0) record("maintenance_pass", state.lastPass.blocked.length ? "warn" : "info", `Pass: ${done.length} actions, ${formatBytes(freedBytes)} freed${state.lastPass.blocked.length ? `; ${state.lastPass.blocked.join("; ")}` : ""}`, { ...state.lastPass });
372
383
  } else {
373
384
  const blocked = [...result.blocked, ...failures];
374
- const planned = [...result.actions, ...retained];
385
+ const keys = /* @__PURE__ */ new Set();
386
+ const planned = [...result.actions, ...retained].filter((action) => {
387
+ const key = actionKey(action);
388
+ if (keys.has(key)) return false;
389
+ keys.add(key);
390
+ return true;
391
+ });
375
392
  const nextActions = new Set(planned.map(actionKey));
376
393
  const changed = !state.lastPass || !sameSet(previousActions, nextActions) || !sameSet(previousSkips, nextSkips) || !sameSet(new Set(state.lastPass.blocked.map(stableText)), new Set(blocked.map(stableText)));
377
394
  for (const action of result.actions) {
@@ -1,7 +1,7 @@
1
- import { S as process_identity_exports, l as WorkspaceProcessCleanupError, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { F as isOnMountedVolume, I as listMountedVolumes, O as withConfigLockAsync, _ as loadConfig, n as allMetroPorts, r as claimMetroPort, x as releaseMetroPort } from "./config-BZhXY15H.mjs";
3
- import { t as runOperationFile } from "./operation-exec-CUZifp6Z.mjs";
4
- import { r as readWorkspaceState } from "./workspace-state-CPSp3mav.mjs";
1
+ import { S as process_identity_exports, l as WorkspaceProcessCleanupError, t as getExecutor } from "./exec-aULwtNly.mjs";
2
+ import { r as readWorkspaceState } from "./workspace-state-BjqdjnJR.mjs";
3
+ import { F as isOnMountedVolume, I as listMountedVolumes, O as withConfigLockAsync, _ as loadConfig, n as allMetroPorts, r as claimMetroPort, x as releaseMetroPort } from "./config-Cn94Jc0g.mjs";
4
+ import { t as runOperationFile } from "./operation-exec-Dp4FuIGR.mjs";
5
5
  import { sep } from "path";
6
6
  import { existsSync, readlinkSync, realpathSync } from "fs";
7
7
  import { readFile } from "node:fs/promises";
@@ -1,7 +1,6 @@
1
- import { S as process_identity_exports, c as throwIfCancelled, s as cancelledError } from "./exec-VFRpu1iA.mjs";
2
- import { g as workspaceStateFile$1 } from "./paths-DQtTgsBf.mjs";
3
- import { ot as tailscaleStatusAsync } from "./config-BZhXY15H.mjs";
4
- import { l as withWorkspaceStateLockAsync, o as updateWorkspaceState, r as readWorkspaceState$1, s as updateWorkspaceStateAsync } from "./workspace-state-CPSp3mav.mjs";
1
+ import { S as process_identity_exports, c as throwIfCancelled, s as cancelledError } from "./exec-aULwtNly.mjs";
2
+ import { j as workspaceStateFile$1, l as withWorkspaceStateLockAsync, o as updateWorkspaceState, r as readWorkspaceState$1, s as updateWorkspaceStateAsync } from "./workspace-state-BjqdjnJR.mjs";
3
+ import { lt as tailscaleStatusAsync } from "./config-Cn94Jc0g.mjs";
5
4
  import { randomBytes, randomUUID } from "node:crypto";
6
5
  import { statSync, watch } from "node:fs";
7
6
  import { HOSTED_METRO_REQUESTS_KEY, findPeer, hostedMetroGateways, hostedMetroRequests, isJsonObject, parseMachine } from "@stim-cli/core/state";
@@ -1,6 +1,6 @@
1
- import { S as process_identity_exports, t as getExecutor, u as withWorkspaceProcessLock } from "./exec-VFRpu1iA.mjs";
2
- import { C as saveConfig, O as withConfigLockAsync, _ as loadConfig, c as ensureConfig, d as getConfigDir, p as getProject } from "./config-BZhXY15H.mjs";
3
- import { f as signalProcessTree, m as createPortProbe, s as parseNetstatPids } from "./metro-1pJgCX4U.mjs";
1
+ import { S as process_identity_exports, t as getExecutor, u as withWorkspaceProcessLock } from "./exec-aULwtNly.mjs";
2
+ import { C as saveConfig, O as withConfigLockAsync, _ as loadConfig, c as ensureConfig, d as getConfigDir, p as getProject } from "./config-Cn94Jc0g.mjs";
3
+ import { f as signalProcessTree, m as createPortProbe, s as parseNetstatPids } from "./metro-CvyD-xwe.mjs";
4
4
  import { realpathSync } from "node:fs";
5
5
  //#region src/named-ports.ts
6
6
  const FIRST_PORT = 8900;
@@ -1,21 +1,20 @@
1
- import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { d as workspaceDir, i as sharedBuildCache } from "./paths-DQtTgsBf.mjs";
3
- import { H as deviceSlotPlatforms, p as getProject, q as validateDeviceSlot } from "./config-BZhXY15H.mjs";
4
- import { nt as settingValueAt } from "./settings-B5tCoq9N.mjs";
5
- import { B as ownedAvdDeviceProfile, E as findBuildTool, I as listInstalledSystemImages, K as ownedAvdSystemImage, V as ownedAvdDirectory, X as pickDefaultSystemImage, l as androidSystemImageAbi, o as androidHome } from "./android-Cjcj8MCw.mjs";
6
- import { r as register } from "./cache-manifest-BPXRONJz.mjs";
7
- import { Z as statsProjectKey } from "./budget-HyShrIpL.mjs";
8
- import { d as runCancellationSignal } from "./native-run-D5OJsGwA.mjs";
9
- import { s as entryDir, t as artifactIn, y as resolveBuild } from "./build-cache-CKCzxzxA.mjs";
10
- import { o as resolveCcache } from "./ccache-h1FKhZeg.mjs";
11
- import { h as gradleOffloadInputs, y as nativeGradleTransfer } from "./client-BQsmyp_-.mjs";
12
- import { r as androidToolchainAsync } from "./toolchain-VzLJzZ7O.mjs";
13
- import { d as buildGradle, l as androidSdkRefusal } from "./react-native-build-CwZB-agu.mjs";
14
- import { s as explainBuildMiss, u as skippedMissReason } from "./prebuild-JUaqOLpc.mjs";
15
- import { u as resolveAndroidRunPlan } from "./result-CR2vk2cj.mjs";
16
- import { n as androidProcessRuntime } from "./launch-D0lPvFFu.mjs";
17
- import { n as planFlagRefusal, r as planPayload } from "./build-plan-zCuHGlA8.mjs";
18
- import { a as nativeGradleWorkerArtifactIdentity, n as gradleArtifactInputs, r as nativeGradleArtifactSnapshot, t as NATIVE_GRADLE_CACHE_LIMIT } from "./native-gradle-artifact-inputs-BJscK4vN.mjs";
1
+ import { t as getExecutor } from "./exec-aULwtNly.mjs";
2
+ import { E as workspaceDir, y as sharedBuildCache } from "./workspace-state-BjqdjnJR.mjs";
3
+ import { H as deviceSlotPlatforms, p as getProject, q as validateDeviceSlot } from "./config-Cn94Jc0g.mjs";
4
+ import { it as settingValueAt } from "./settings-BDVI8Ivc.mjs";
5
+ import { B as ownedAvdDeviceProfile, E as findBuildTool, I as listInstalledSystemImages, K as ownedAvdSystemImage, V as ownedAvdDirectory, X as pickDefaultSystemImage, l as androidSystemImageAbi, o as androidHome } from "./android-DriNoAVy.mjs";
6
+ import { s as resolveCcache } from "./ccache-BWTze1Ls.mjs";
7
+ import { r as register } from "./cache-manifest-DEjqGGat.mjs";
8
+ import { ot as statsProjectKey } from "./workspaces-DFbj07jp.mjs";
9
+ import { ot as runCancellationSignal, r as androidToolchainAsync } from "./toolchain-CbCG6C5Z.mjs";
10
+ import { C as resolveBuild, s as entryDir, t as artifactIn } from "./build-cache-gBJ-WKzA.mjs";
11
+ import { h as gradleOffloadInputs, y as nativeGradleTransfer } from "./client-xsdxrhWA.mjs";
12
+ import { d as buildGradle, l as androidSdkRefusal } from "./react-native-build-DaK2IFyP.mjs";
13
+ import { s as explainBuildMiss, u as skippedMissReason } from "./prebuild-BDpToDgR.mjs";
14
+ import { u as resolveAndroidRunPlan } from "./result-CTqBw2Te.mjs";
15
+ import { n as androidProcessRuntime } from "./launch-CRyBeNsA.mjs";
16
+ import { n as planFlagRefusal, r as planPayload } from "./build-plan-CBqYbzYM.mjs";
17
+ import { a as nativeGradleWorkerArtifactIdentity, n as gradleArtifactInputs, r as nativeGradleArtifactSnapshot, t as NATIVE_GRADLE_CACHE_LIMIT } from "./native-gradle-artifact-inputs-C13qT7R_.mjs";
19
18
  import { createHash } from "node:crypto";
20
19
  import { createReadStream, createWriteStream, existsSync, readFileSync, statSync } from "node:fs";
21
20
  import { tmpdir } from "node:os";