stim 1.26.0 → 1.28.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 (172) hide show
  1. package/dist/{acquire-artifact-DVsvSwf7.mjs → acquire-artifact-CKByBnTD.mjs} +2 -2
  2. package/dist/{act-C-BqJEpu.mjs → act-8iswyfRa.mjs} +319 -126
  3. package/dist/{activity-Lnb_EoRY.mjs → activity-DRMg4_mD.mjs} +6 -6
  4. package/dist/{agent-device-usage-output-DbXy5tg8.mjs → agent-device-usage-output-tE90fDdo.mjs} +5 -5
  5. package/dist/{android-CiNQw3kq.mjs → android-CHmSU4B4.mjs} +101 -45
  6. package/dist/{android-DTAcRwBC.mjs → android-CsPs-7Mg.mjs} +23 -18
  7. package/dist/{android-B5P81yI-.mjs → android-D577ApKG.mjs} +37 -15
  8. package/dist/{android-CSbLRD53.mjs → android-YWCbmkVK.mjs} +5 -5
  9. package/dist/{android-cas-BTVhZ0Qs.mjs → android-cas-_aDifWW0.mjs} +4 -4
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/api.d.mts +14 -4
  12. package/dist/api.mjs +39 -29
  13. package/dist/{apk-signed-tail-B46U9hXc.mjs → apk-signed-tail-CQbwM0qO.mjs} +2 -2
  14. package/dist/{artifact-CsAP6AGK.mjs → artifact-DYtHjxsn.mjs} +19 -24
  15. package/dist/{artifact-BxREhAaV.mjs → artifact-bFkfD3vf.mjs} +18 -23
  16. package/dist/{artifact-platform-CMRc0M_r.mjs → artifact-platform-BO2Uvk_A.mjs} +1 -1
  17. package/dist/auto-placement-BVqs8AJi.mjs +350 -0
  18. package/dist/{browser-web-rYPyqhTf.mjs → browser-web-BUaLcafY.mjs} +16 -16
  19. package/dist/{build-DPhApsjV.mjs → build-cQURy_KW.mjs} +35 -31
  20. package/dist/{build-cache-DrXNCy3T.mjs → build-cache-CZULpXVl.mjs} +43 -21
  21. package/dist/{build-plan-DrMMdayj.mjs → build-plan-CxoYfxsc.mjs} +7 -6
  22. package/dist/{cache-manifest-BEZ9Bpl1.mjs → cache-manifest-DEjqGGat.mjs} +1 -1
  23. package/dist/cache-manifest.mjs +1 -1
  24. package/dist/{budget-k2mZGvvk.mjs → ccache-Bm_A1xX9.mjs} +562 -1604
  25. package/dist/{cdp-BG3FJCCx.mjs → cdp-C3svvXiE.mjs} +1 -1
  26. package/dist/{chrome-BvV8ssI3.mjs → chrome-DyDWurWG.mjs} +1 -1
  27. package/dist/{cli-BBKFGOFl.mjs → cli-CpbaLDa7.mjs} +24 -23
  28. package/dist/cli.mjs +1 -1
  29. package/dist/{client-D9CaRks-.mjs → client-YxCer6ab.mjs} +84 -65
  30. package/dist/collector-run.d.mts +10 -9
  31. package/dist/collector-run.mjs +42 -27
  32. package/dist/{command-output-BF5AR2dL.mjs → command-output-C8R1KIvi.mjs} +1 -1
  33. package/dist/{config-BktkY_zC.mjs → config-Cn94Jc0g.mjs} +23 -4
  34. package/dist/{dependencies-Dw6wfQdv.mjs → dependencies-DKeMzwXY.mjs} +108 -60
  35. package/dist/{dependency-state-DFB41vfr.mjs → dependency-state-CojA2o0t.mjs} +14 -7
  36. package/dist/{detached-entry-KmieOKgN.mjs → detached-entry-BPlSaCwC.mjs} +1 -1
  37. package/dist/{dev-client-DXR_tPVY.mjs → dev-client-D-BW5uiq.mjs} +2 -2
  38. package/dist/{device-BK-zwyd_.mjs → device-CgXfbcz5.mjs} +25 -24
  39. package/dist/{device-capacity-DCSvUF0l.mjs → device-capacity-Cd8lMSn3.mjs} +175 -22
  40. package/dist/{device-BcYeHSFu.mjs → device-eeK95Lir.mjs} +16 -16
  41. package/dist/device-host-worker.mjs +22 -20
  42. package/dist/{device-ios-BLGfXQeK.mjs → device-ios-Cc9ulihb.mjs} +251 -23
  43. package/dist/{device-lease-run-BmvIl7bI.mjs → device-lease-run-Mtzp4THX.mjs} +5 -5
  44. package/dist/{device-pool-Dluix4H3.mjs → device-pool-eRz6DtCg.mjs} +3 -3
  45. package/dist/{doctor-Bhg1ii70.mjs → doctor-Bz_ouYAW.mjs} +28 -16
  46. package/dist/{doctor-Cp-BhzTS.mjs → doctor-C2QyhejJ.mjs} +1 -1
  47. package/dist/{doctor-fingerprint-D3a04Mhu.mjs → doctor-fingerprint-o7ZI9YLn.mjs} +1 -1
  48. package/dist/doctor-fingerprint.mjs +1 -1
  49. package/dist/{doctor-watchman-BStK05nt.mjs → doctor-watchman-BTW82PDC.mjs} +5 -5
  50. package/dist/{doctor-OnwP94ne.mjs → doctor-xf7ht-5n.mjs} +76 -32
  51. package/dist/{eas-build-Dsj93iM9.mjs → eas-build-Dm6q68QY.mjs} +4 -4
  52. package/dist/eas-fallback-DajNpxf-.mjs +87 -0
  53. package/dist/{eas-session-ledger-B5vygTiD.mjs → eas-session-ledger-CBFo_Uo1.mjs} +37 -8
  54. package/dist/{error-diagnostics-BOOm9Db7.mjs → error-diagnostics-D1QfyJzQ.mjs} +51 -25
  55. package/dist/{exec-VFRpu1iA.mjs → exec-aULwtNly.mjs} +57 -6
  56. package/dist/{gc-ldgr-hXU.mjs → gc-DM5oMm-J.mjs} +161 -45
  57. package/dist/{gc-C_79zvz4.mjs → gc-PLFwb0k4.mjs} +2 -2
  58. package/dist/{guide-D7K0X6KG.mjs → guide-C4I46XAk.mjs} +674 -213
  59. package/dist/{hosted-android-Bk54ej6n.mjs → hosted-android-DlaKLbW0.mjs} +6 -7
  60. package/dist/{hosted-client-fHO8yqzc.mjs → hosted-client-DDRm9hPJ.mjs} +51 -20
  61. package/dist/{hosted-logs-BfbmDM4M.mjs → hosted-logs-bSebOKbz.mjs} +8 -8
  62. package/dist/{hosted-logs-sync-B0pvmOk-.mjs → hosted-logs-sync-B0c53W_c.mjs} +5 -5
  63. package/dist/{hosted-macos-CPl0OZ9h.mjs → hosted-macos-B7-8Pv4H.mjs} +6 -6
  64. package/dist/{hosted-native-CpDB3-PO.mjs → hosted-native-CDe33CSr.mjs} +22 -18
  65. package/dist/{idle-shutdown-FfxL1KdG.mjs → idle-shutdown-CQ0QwU9J.mjs} +7 -8
  66. package/dist/{ios-WxpDJ5T1.mjs → ios-B1DYuOjh.mjs} +27 -11
  67. package/dist/{ios-B7-lToDu.mjs → ios-B1HvafEG.mjs} +8 -8
  68. package/dist/{ios-ENC4sRPA.mjs → ios-CsRVik64.mjs} +7 -1
  69. package/dist/{ios-device-CsyryvpT.mjs → ios-device-B4elVFKi.mjs} +3 -3
  70. package/dist/{ios-device-B6HK951C.mjs → ios-device-CiBA-er9.mjs} +1 -1
  71. package/dist/{ios-project-Ty5pHl9O.mjs → ios-project-CR4mZ7CH.mjs} +22 -9
  72. package/dist/{ios-signing-4c_qXvQm.mjs → ios-signing-BJzvDPfU.mjs} +2 -2
  73. package/dist/{ios-state-Cw7-WQf2.mjs → ios-state-BPHqMDdZ.mjs} +1 -1
  74. package/dist/{ios-ftxdQbJS.mjs → ios-tg4tp3q1.mjs} +94 -37
  75. package/dist/{js-swap-BMhXYVDS.mjs → js-swap-CVpSW1fn.mjs} +8 -7
  76. package/dist/{launch-DOp8RjDz.mjs → launch-DoySmhjz.mjs} +42 -38
  77. package/dist/lightened-DFAJgfIk.mjs +171 -0
  78. package/dist/{logs-s1dRIG1E.mjs → logs-BGsW7iPe.mjs} +46 -21
  79. package/dist/{logs-dQDki6Tt.mjs → logs-DI5ILkYB.mjs} +7 -7
  80. package/dist/{macos-DBBPNnIA.mjs → macos-Bo9st9Di.mjs} +73 -38
  81. package/dist/{macos-B0VEV3Gf.mjs → macos-C12RMJQF.mjs} +1 -1
  82. package/dist/macos-run.mjs +1 -1
  83. package/dist/maintenance-run.mjs +7 -7
  84. package/dist/{metro-CjC10t6E.mjs → metro-BnhXV2Mj.mjs} +4 -4
  85. package/dist/{metro-gateway-B6_PgD0L.mjs → metro-request-DXyKjVDF.mjs} +26 -47
  86. package/dist/{named-ports-BG0j1X4g.mjs → named-ports-Phoi2POD.mjs} +3 -3
  87. package/dist/{native-android-CL2NGiik.mjs → native-android-vxgtLD7w.mjs} +17 -18
  88. package/dist/{native-gradle-artifact-inputs-btSUulme.mjs → native-gradle-artifact-inputs-BN96IVw8.mjs} +5 -5
  89. package/dist/{native-runtime-Dq3RBcON.mjs → native-runtime-DG4Rodzj.mjs} +9 -8
  90. package/dist/{native-source-D-4Dh4JU.mjs → native-source-D1AzWiuP.mjs} +1 -1
  91. package/dist/{native-xcode-inputs-BW7H8JGu.mjs → native-xcode-inputs-BKarCoKg.mjs} +3 -3
  92. package/dist/{native-xcode-ios-CBXJAxfC.mjs → native-xcode-ios-8A-efGa5.mjs} +17 -17
  93. package/dist/{ndjson-CgE_o3Dl.mjs → ndjson-Dy2W4vRa.mjs} +2 -2
  94. package/dist/offload-worker.mjs +23 -24
  95. package/dist/{operation-exec-CUZifp6Z.mjs → operation-exec-Dp4FuIGR.mjs} +1 -1
  96. package/dist/{ownership-BjYvMNX_.mjs → ownership-DJCq48IJ.mjs} +3 -3
  97. package/dist/{page-CzEA_-5_.mjs → page-CQJlcj3x.mjs} +2 -2
  98. package/dist/{phone-reverses-lmj6kcPm.mjs → phone-reverses-BzTa8g1F.mjs} +18 -4
  99. package/dist/{placement-log-DIFPQAXp.mjs → placement-log-Cvhta5ib.mjs} +3 -3
  100. package/dist/{plan-placement-IiiSQhtz.mjs → plan-placement-WkZdccuN.mjs} +36 -10
  101. package/dist/{ports-C2_w1Z0Z.mjs → ports-UV4mJgyC.mjs} +3 -3
  102. package/dist/{prebuild-gmouvmJZ.mjs → prebuild-k8d_tqOq.mjs} +16 -17
  103. package/dist/{project-BUu6Is4k.mjs → project-Sui52ywT.mjs} +17 -17
  104. package/dist/{pull-request-CbNlkFok.mjs → pull-request-BzLmzAIQ.mjs} +2 -2
  105. package/dist/pull-requests.mjs +1 -1
  106. package/dist/{react-native-android-Cgg99REN.mjs → react-native-android-DANlGGQf.mjs} +32 -26
  107. package/dist/{react-native-build-oNwqF5Wb.mjs → react-native-build-jUHnIfZ9.mjs} +9 -9
  108. package/dist/{react-native-doctor-BhA3KUte.mjs → react-native-doctor-DCWRjS7K.mjs} +6 -6
  109. package/dist/{react-native-ios-B-nf4rjN.mjs → react-native-ios-BwMsFMXi.mjs} +23 -17
  110. package/dist/{recordings-BldzVKq0.mjs → recordings-iy0mkm7b.mjs} +1 -1
  111. package/dist/{registration-CN6nlhcD.mjs → registration-BwCe64PH.mjs} +1 -1
  112. package/dist/{reload-C9OduiNc.mjs → reload-Bj7QyuDy.mjs} +1 -1
  113. package/dist/{reload-CCR7KC_l.mjs → reload-c_uEyc_X.mjs} +16 -16
  114. package/dist/{remote-C8S7FlPF.mjs → remote-DFlpAqdV.mjs} +23 -10
  115. package/dist/{result-7F5hEwQJ.mjs → result-BIcXREyC.mjs} +32 -21
  116. package/dist/{run-BqB0v3pt.mjs → run-y2HwyNvg.mjs} +3 -3
  117. package/dist/{selection-BNPBZ6T5.mjs → selection-CXgM_VK_.mjs} +37 -29
  118. package/dist/{server-bare-A75rDIdD.mjs → server-bare-2N4vSRZG.mjs} +2 -2
  119. package/dist/{server-command-CssKFOD7.mjs → server-command-qneHPcRI.mjs} +6 -6
  120. package/dist/{server-expo-eQfOdydb.mjs → server-expo-Ccm9zB0o.mjs} +4 -4
  121. package/dist/server-expo-WulkyAwT.mjs +2 -0
  122. package/dist/{settings-CosW5X-S.mjs → settings-CY5JZlNN.mjs} +375 -62
  123. package/dist/{settings-OaGQF-ri.mjs → settings-Cfd_Q6ys.mjs} +24 -3
  124. package/dist/settings-payload-DwQiEMCn.mjs +257 -0
  125. package/dist/settings-write-CJpjkeAd.mjs +185 -0
  126. package/dist/settings.schema.json +51 -33
  127. package/dist/{simslim-Bax1qcxu.mjs → simslim-DCQwzoPy.mjs} +2 -2
  128. package/dist/{slot-launch-CYCEhfBY.mjs → slot-launch-BpmanOnk.mjs} +6 -6
  129. package/dist/{stage-jKQ7CP_B.mjs → stage-CmugrSG5.mjs} +2 -2
  130. package/dist/{start-C_wefNKB.mjs → start-CHH3zgIU.mjs} +1 -1
  131. package/dist/{start-_BdJ32cZ.mjs → start-DYLk6GXn.mjs} +27 -22
  132. package/dist/{state-C1i2nMOP.mjs → state-B2QJbDwz.mjs} +4 -4
  133. package/dist/{state-C4OdpOTF.mjs → state-BXC1Lfxw.mjs} +2 -2
  134. package/dist/{stats-tEpEEH-u.mjs → stats-DxKqhcGp.mjs} +5 -5
  135. package/dist/{stats-report-n2U5plhk.mjs → stats-report-B86Cv7Uc.mjs} +1 -1
  136. package/dist/{status-CRXz-Gtj.mjs → status-7ULDEJ1e.mjs} +1 -1
  137. package/dist/{status-DQrqodLj.mjs → status-BHCkOZga.mjs} +51 -28
  138. package/dist/{status-B9M7x4CZ.mjs → status-D_Ljc89p.mjs} +1 -1
  139. package/dist/{status-watch-B5wDIH_o.mjs → status-watch-BmsPqYSU.mjs} +18 -7
  140. package/dist/status-worker.mjs +1 -1
  141. package/dist/{stim-desktop-6Dqp-gjX.mjs → stim-desktop-CbWo21kb.mjs} +2 -2
  142. package/dist/{stop-DRqQVqDJ.mjs → stop-D-dGE9gh.mjs} +21 -20
  143. package/dist/{stop-ySNQHXMG.mjs → stop-DQvE-P76.mjs} +10 -6
  144. package/dist/{stop-CmdNhGlC.mjs → stop-b2pouxAO.mjs} +2 -2
  145. package/dist/supervisor-run.mjs +237 -63
  146. package/dist/{support-BGSCBoib.mjs → support-04IhBUTT.mjs} +6 -6
  147. package/dist/{support-CVOCp0Ft.mjs → support-BtlJKjyQ.mjs} +12 -11
  148. package/dist/{swiftpm-artifact-inputs-CfUzt_0Z.mjs → swiftpm-artifact-inputs-Cj2UpmPN.mjs} +4 -4
  149. package/dist/{swiftpm-macos-x6HPpl_2.mjs → swiftpm-macos-BhF2stxY.mjs} +11 -12
  150. package/dist/{toolchain-J4J8MrAr.mjs → toolchain-mLA_km-b.mjs} +321 -15
  151. package/dist/{toolchain-DoavrvIA.mjs → toolchain-qktiV8xc.mjs} +1 -1
  152. package/dist/{trigger-KVaWWNyn.mjs → trigger-DMou-X7j.mjs} +2 -2
  153. package/dist/trigger-qp2ji5wE.mjs +2 -0
  154. package/dist/{warm-progress-DvhTX_eu.mjs → warm-progress-B0Vpuvpl.mjs} +731 -727
  155. package/dist/{web-Bihbf7-u.mjs → web-BYmK0TjL.mjs} +9 -9
  156. package/dist/web-CrVLVQZY.mjs +2 -0
  157. package/dist/web-run.mjs +9 -9
  158. package/dist/windows-report.mjs +1 -1
  159. package/dist/{workspace-state-pUg3_RRA.mjs → workspace-state-kIZrdlSg.mjs} +3 -3
  160. package/dist/{workspaces-g2lhdBXF.mjs → workspaces-CmOcceDN.mjs} +1879 -74
  161. package/dist/{worktree-BKuklFh_.mjs → worktree-2dk5edza.mjs} +933 -534
  162. package/dist/worktree-nliAoHxB.mjs +2 -0
  163. package/package.json +7 -7
  164. package/dist/ccache-Bx5TbxwG.mjs +0 -143
  165. package/dist/eas-fallback-FwkeqqGi.mjs +0 -381
  166. package/dist/hosted-ios-D55QhYaD.mjs +0 -15
  167. package/dist/native-run-BfIDFKLH.mjs +0 -275
  168. package/dist/server-expo-wvcj5tiZ.mjs +0 -2
  169. package/dist/settings-write-QjYfSrjF.mjs +0 -360
  170. package/dist/trigger-DzJu208Q.mjs +0 -2
  171. package/dist/web-BFLueSh-.mjs +0 -2
  172. package/dist/worktree-Bm4cb-nU.mjs +0 -2
@@ -1,18 +1,19 @@
1
- import { k as workspaceLogsDir$1, r as readWorkspaceState$1 } from "./workspace-state-pUg3_RRA.mjs";
2
- import { W as parseDeviceSlotOption, _ as loadConfig$1, g as isPathPrefix } from "./config-BktkY_zC.mjs";
3
- import { f as refuseNoProject, v as launchErrorPreview } from "./command-output-BF5AR2dL.mjs";
4
- import { n as findCommandWorkspace } from "./project-BUu6Is4k.mjs";
5
- import { n as SOURCES$1, t as LEVELS$1 } from "./ndjson-CgE_o3Dl.mjs";
6
- import { i as followAgentActions, n as openWorkspaceLogs } from "./logs-dQDki6Tt.mjs";
7
- import { t as errorDiagnostics } from "./error-diagnostics-BOOm9Db7.mjs";
8
- import { n as followHostedLogs } from "./hosted-logs-sync-B0pvmOk-.mjs";
1
+ import { k as workspaceLogsDir$1, r as readWorkspaceState$1 } from "./workspace-state-kIZrdlSg.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-C8R1KIvi.mjs";
4
+ import { n as findCommandWorkspace } from "./project-Sui52ywT.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-DI5ILkYB.mjs";
7
+ import { t as errorDiagnostics } from "./error-diagnostics-D1QfyJzQ.mjs";
8
+ import { n as followHostedLogs } from "./hosted-logs-sync-B0c53W_c.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, fileSizes, followLogs, gcLogDir, logFiles, parseSince, queryLogs, readGcLog, 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 = " ";
@@ -58,7 +59,8 @@ 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
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." };
61
- if (list.includes("all")) return { sources: SOURCES$1.filter((source) => source !== "gc") };
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)) };
62
64
  const unknown = list.filter((s) => !SOURCES$1.includes(s));
63
65
  if (unknown.length > 0) return { error: `Unknown --source value(s): ${unknown.join(", ")}. Use one or more of: ${SOURCES$1.join(", ")}, or all.` };
64
66
  return { sources: list };
@@ -69,7 +71,7 @@ function validateLevel(level) {
69
71
  }
70
72
  const ERRORS_PRINT_CAP = 20;
71
73
  function nearestRegisteredLogsProject(root, candidates) {
72
- 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) => {
73
75
  const depth = (path) => relative(root, path).split(sep).length;
74
76
  return depth(a) - depth(b) || a.length - b.length || a.localeCompare(b);
75
77
  })[0] ?? null;
@@ -98,11 +100,12 @@ const LEVEL_COLOURS = {
98
100
  fatal: chalk.bgRed
99
101
  };
100
102
  function logsCommand(program) {
101
- 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").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) => {
102
104
  const requested = [opts.source ?? []].flat();
103
- if (requested.length === 1 && requested[0] === "gc") {
105
+ const [only] = requested;
106
+ if (requested.length === 1 && only !== void 0 && MACHINE_SOURCES.includes(only)) {
104
107
  const { minLevel, tail } = validateOptions(opts);
105
- printGcLog(opts, opts.errors ? "error" : minLevel, tail);
108
+ printMachineLog(only === "gc" ? GC_LOG : BUILD_LEDGER, opts, opts.errors ? "error" : minLevel, tail);
106
109
  return;
107
110
  }
108
111
  const root = findCommandWorkspace(process.cwd());
@@ -257,27 +260,49 @@ function validateOptions(opts) {
257
260
  tail
258
261
  };
259
262
  }
260
- function printGcLog(opts, minLevel, tail) {
261
- const emit = (record) => console.log(opts.json ? JSON.stringify(record) : formatRecord(record, { paint: record.level ? LEVEL_COLOURS[record.level] : void 0 }));
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
+ };
262
284
  const query = {
263
- sources: ["gc"],
285
+ sources: [log.source],
264
286
  minLevel,
265
287
  since: opts.since,
266
288
  grep: opts.grep
267
289
  };
268
- const offsets = opts.follow ? fileSizes(gcLogDir()) : null;
290
+ const dir = log.dir();
291
+ const offsets = opts.follow ? fileSizes(dir) : null;
292
+ const all = log.read();
269
293
  const records = queryLogs({
270
294
  ...query,
271
- records: readGcLog(),
295
+ records: all,
272
296
  tail
273
297
  });
274
298
  for (const record of records) emit(record);
299
+ if (opts.follow && log.key) for (const record of all) printed.add(log.key(record));
275
300
  if (!opts.follow) {
276
- if (records.length === 0 && !opts.json) console.error(chalk.dim(`No matching log records in ${gcLogDir()}`));
301
+ if (records.length === 0 && !opts.json) console.error(chalk.dim(`No matching log records in ${dir}`));
277
302
  return;
278
303
  }
279
304
  const stop = followLogs({
280
- dir: gcLogDir(),
305
+ dir,
281
306
  offsets,
282
307
  criteria: buildCriteria(query),
283
308
  onRecord: emit
@@ -1,9 +1,9 @@
1
- import { S as process_identity_exports } from "./exec-VFRpu1iA.mjs";
2
- import { k as workspaceLogsDir$1 } from "./workspace-state-pUg3_RRA.mjs";
3
- import { G as projectDeviceSlots, _ as loadConfig$1 } from "./config-BktkY_zC.mjs";
4
- import { f as readAgentDeviceRecordsAsync, n as agentDeviceLiveness, o as envDir } from "./activity-Lnb_EoRY.mjs";
5
- import { i as captureWorkspaceCrashes } from "./error-diagnostics-BOOm9Db7.mjs";
6
- import { n as followHostedLogs, r as syncHostedLogs } from "./hosted-logs-sync-B0pvmOk-.mjs";
1
+ import { S as process_identity_exports } from "./exec-aULwtNly.mjs";
2
+ import { k as workspaceLogsDir$1 } from "./workspace-state-kIZrdlSg.mjs";
3
+ import { G as projectDeviceSlots, _ as loadConfig$1 } from "./config-Cn94Jc0g.mjs";
4
+ import { f as readAgentDeviceRecordsAsync, n as agentDeviceLiveness, o as envDir } from "./activity-DRMg4_mD.mjs";
5
+ import { o as captureWorkspaceCrashes } from "./error-diagnostics-D1QfyJzQ.mjs";
6
+ import { n as followHostedLogs, r as syncHostedLogs } from "./hosted-logs-sync-B0c53W_c.mjs";
7
7
  import { readdirSync, statSync, watch } from "node:fs";
8
8
  import { homedir } from "node:os";
9
9
  import { dirname, join, relative, resolve, sep } from "node:path";
@@ -264,7 +264,7 @@ async function readWorkspaceLogs(context, options = {}) {
264
264
  await view.close();
265
265
  }
266
266
  }
267
- const WORKSPACE_SOURCES = SOURCES.filter((source) => source !== "gc");
267
+ const WORKSPACE_SOURCES = SOURCES.filter((source) => source !== "gc" && source !== "builds");
268
268
  function validateLogOptions(options) {
269
269
  const invalid = (options.tail !== void 0 && (!Number.isSafeInteger(options.tail) || options.tail < 0) ? "tail must be a non-negative integer." : options.sources?.some((source) => !WORKSPACE_SOURCES.includes(source)) ? `sources must contain only ${WORKSPACE_SOURCES.join(", ")}.` : options.minLevel !== void 0 && !LEVELS.includes(options.minLevel) ? `minLevel must be one of ${LEVELS.join(", ")}.` : void 0) ?? (options.since !== void 0 ? parseSince(options.since).error : void 0) ?? (options.grep !== void 0 ? compileGrep(options.grep).error : void 0);
270
270
  if (invalid) throw Object.assign(new Error(invalid), { code: "STIM_BAD_ARG" });
@@ -1,36 +1,37 @@
1
- import { _ as spawnDeclared, c as throwIfCancelled, t as getExecutor, u as withWorkspaceProcessLock, x as withDrainingCancellation } from "./exec-VFRpu1iA.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-pUg3_RRA.mjs";
3
- import { E as upsertProject, O as withConfigLockAsync$1, u as getConcurrencyLimits } from "./config-BktkY_zC.mjs";
4
- import { l as phaseLine } from "./command-output-BF5AR2dL.mjs";
5
- import { Y as resolveProjectSettingsAsync, a as SETTING_SHAPE_REMEDY, tt as settingShapeErrors } from "./settings-CosW5X-S.mjs";
6
- import { f as projectRegistry, i as findProjectRoot$1, s as ownedDeviceLabel } from "./project-BUu6Is4k.mjs";
7
- import { i as macosProcess, n as macosDir, o as requiredMacosRecord, r as macosLogFile } from "./state-C4OdpOTF.mjs";
8
- import { r as createNdjsonWriter } from "./ndjson-CgE_o3Dl.mjs";
9
- import { Hn as processContext, I as NO_BUILD_PROGRESS, K as startBuildProgress, U as recordBuildPhase, Un as runProcessOperation, W as recordFinishedBuild, q as tapBuildLog } from "./budget-k2mZGvvk.mjs";
10
- import { d as runCancellationSignal, f as withNativeBuildRun } from "./native-run-BfIDFKLH.mjs";
11
- import { L as acquireBuildSlot, z as releaseBuildSlot } from "./workspaces-g2lhdBXF.mjs";
12
- import { O as sanitizeDeviceLabel } from "./ios-WxpDJ5T1.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-D9CaRks-.mjs";
14
- import { a as parseBuildMachineOption, i as namedBuildMachine, l as resolveBuildPlacement, s as requireLocalBuild, t as OffloadRefusal } from "./selection-BNPBZ6T5.mjs";
15
- import { l as connectHost } from "./hosted-client-fHO8yqzc.mjs";
16
- import { t as placeHostedMacos } from "./hosted-macos-CPl0OZ9h.mjs";
17
- import { r as stopMacosAppHeld, t as stopBundleInstances } from "./stop-ySNQHXMG.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-kIZrdlSg.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-C8R1KIvi.mjs";
5
+ import { Z as resolveProjectSettingsAsync, a as SETTING_SHAPE_REMEDY, it as settingValueAt, rt as settingShapeErrors } from "./settings-CY5JZlNN.mjs";
6
+ import { f as projectRegistry, i as findProjectRoot$1, s as ownedDeviceLabel } from "./project-Sui52ywT.mjs";
7
+ import { i as macosProcess, n as macosDir, o as requiredMacosRecord, r as macosLogFile } from "./state-BXC1Lfxw.mjs";
8
+ import { i as createNdjsonWriter } from "./ndjson-Dy2W4vRa.mjs";
9
+ import { En as runProcessOperation, Tn as processContext } from "./ccache-Bm_A1xX9.mjs";
10
+ import { $ as tapBuildLog, H as NO_BUILD_PROGRESS, Q as startBuildProgress, St as acquireBuildSlot, Tt as releaseBuildSlot, X as recordFinishedBuild, Y as recordBuildPhase, tt as errorRemedy } from "./workspaces-CmOcceDN.mjs";
11
+ import { ot as runCancellationSignal, st as withNativeBuildRun } from "./toolchain-mLA_km-b.mjs";
12
+ import { O as sanitizeDeviceLabel } from "./ios-B1DYuOjh.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-YxCer6ab.mjs";
14
+ import { d as resolveBuildPlacement, l as requireLocalBuild, n as automaticBuild, o as namedBuildMachine, s as parseBuildMachineOption, t as OffloadRefusal } from "./selection-CXgM_VK_.mjs";
15
+ import { l as connectHost } from "./hosted-client-DDRm9hPJ.mjs";
16
+ import { t as placeHostedMacos } from "./hosted-macos-B7-8Pv4H.mjs";
17
+ import { i as stopMacosAppHeld, t as stopBundleInstances } from "./stop-DQvE-P76.mjs";
18
18
  import { t as spawnEntry } from "./spawn-entry-jw19m8Nl.mjs";
19
- import { t as buildPlacementRecord } from "./placement-log-DIFPQAXp.mjs";
20
- import { t as reidentifyBundle } from "./stage-jKQ7CP_B.mjs";
21
- import { t as validateMacosArtifactPlatform } from "./artifact-platform-CMRc0M_r.mjs";
22
- import { t as waitForMacosRegistration } from "./registration-CN6nlhcD.mjs";
19
+ import { t as buildPlacementRecord } from "./placement-log-Cvhta5ib.mjs";
20
+ import { n as devicePlacementLine, t as automaticDevicePlacement } from "./auto-placement-BVqs8AJi.mjs";
21
+ import { t as reidentifyBundle } from "./stage-CmugrSG5.mjs";
22
+ import { t as validateMacosArtifactPlatform } from "./artifact-platform-BO2Uvk_A.mjs";
23
+ import { t as waitForMacosRegistration } from "./registration-BwCe64PH.mjs";
23
24
  import { createHash, randomUUID } from "node:crypto";
24
25
  import { closeSync, existsSync, openSync, promises, realpathSync, renameSync } from "node:fs";
25
26
  import { join } from "node:path";
26
27
  import { LOG_ROTATE_BYTES, ambientEnv } from "@stim-cli/core";
27
- import { machineCapacity, validHostedAppArguments } from "@stim-cli/core/state";
28
+ import { machineCapacity, placementWord, validHostedAppArguments } from "@stim-cli/core/state";
28
29
  //#region src/macos/build.ts
29
30
  async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displayName, scratch, writer, note, record, buildMachine, hostServerKey, progress = NO_BUILD_PROGRESS }) {
30
31
  const signal = runCancellationSignal(context) ?? context.signal;
31
32
  return withDrainingCancellation(context, signal, async () => {
32
33
  throwIfCancelled(signal, "macOS build");
33
- const { mode, machines, localEnabled } = buildPlacementCandidates(buildMachine);
34
+ const { machines, localEnabled } = buildPlacementCandidates(buildMachine);
34
35
  const builder = namedBuildMachine(buildMachine) ? machines[0] : void 0;
35
36
  const runsOnWorker = hostServerKey !== void 0 && builder?.serverKey === hostServerKey;
36
37
  if (record) record.buildMachine = buildMachine;
@@ -63,7 +64,7 @@ async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displ
63
64
  }
64
65
  }));
65
66
  if (namedBuildMachine(buildMachine)) throw new OffloadRefusal(buildMachine, reason);
66
- requireLocalBuild(buildMachine);
67
+ requireLocalBuild(buildMachine, reason);
67
68
  offloadFallback = reason;
68
69
  if (record) record.offloadFallback = reason;
69
70
  writer.write({
@@ -161,7 +162,6 @@ async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displ
161
162
  };
162
163
  const here = machineCapacity();
163
164
  const placement = offloadPlacement({
164
- mode,
165
165
  localEnabled,
166
166
  machines: machines.length,
167
167
  here,
@@ -173,7 +173,6 @@ async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displ
173
173
  const chosen = await chooseBuildMachine({
174
174
  projectRoot: root,
175
175
  target: await recipe.offload.target(runsOnWorker),
176
- mode,
177
176
  here,
178
177
  machines,
179
178
  selected: buildMachine,
@@ -268,7 +267,7 @@ async function buildMacosBundle({ context, root, recipe, bundle, bundleId, displ
268
267
  try {
269
268
  slot = await acquireBuildSlot({
270
269
  signal,
271
- automatic: buildMachine === "auto",
270
+ automatic: automaticBuild(buildMachine),
272
271
  max: getConcurrencyLimits().maxBuilds,
273
272
  root,
274
273
  logFile: writer.file,
@@ -345,7 +344,7 @@ async function planMacos(context, root, buildMachineFlag) {
345
344
  if (selected.failure) throw Object.assign(new Error(selected.failure.message), selected.failure);
346
345
  const macos = settings.macos;
347
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" });
348
- const { swiftpmMacosProject } = await import("./swiftpm-macos-x6HPpl_2.mjs");
347
+ const { swiftpmMacosProject } = await import("./swiftpm-macos-BhF2stxY.mjs");
349
348
  const recipe = await swiftpmMacosProject(root).prepare(context, settings);
350
349
  let identity = null;
351
350
  let cacheHit = false;
@@ -374,13 +373,11 @@ async function planMacos(context, root, buildMachineFlag) {
374
373
  //#endregion
375
374
  //#region src/commands/macos.ts
376
375
  /**
377
- * Builds the Debug app and launches it here, or with `remote` on that approved remote Mac. A named host never falls
378
- * 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.
379
378
  */
380
- async function runMacos(context, root, note = console.error, remote, buildMachineFlag) {
381
- const backend = remote?.trim().toLowerCase();
382
- 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" });
383
- 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);
384
381
  if (process.platform !== "darwin") throw new Error("stim macos requires a Mac with Swift installed.");
385
382
  root = realpathSync(root);
386
383
  const operation = projectRegistry.selectMacos(root);
@@ -397,6 +394,9 @@ async function runMacos(context, root, note = console.error, remote, buildMachin
397
394
  const selected = resolveBuildPlacement(buildMachineFlag);
398
395
  if (selected.failure) throw Object.assign(new Error(selected.failure.message), selected.failure);
399
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);
400
400
  const macos = await (await operation.load()).prepare(context, settings);
401
401
  await ensureWorkspaceStorageAsync(root, context.signal);
402
402
  return withNativeBuildRun(context, root, {
@@ -412,6 +412,14 @@ async function runMacos(context, root, note = console.error, remote, buildMachin
412
412
  });
413
413
  return withWorkspaceProcessLock(workspaceDir(root), "macos-launch", async () => {
414
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
+ });
415
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}` : ""}.`);
416
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.");
417
425
  let hostServerKey;
@@ -508,6 +516,29 @@ async function runMacos(context, root, note = console.error, remote, buildMachin
508
516
  }).finally(() => progress.clear());
509
517
  }, { write: note });
510
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
+ }
511
542
  async function buildBundle(context, root, recipe, record, hosted, hostServerKey, note, progress = NO_BUILD_PROGRESS) {
512
543
  const started = Date.parse(record.build.startedAt);
513
544
  const scratch = join(macosDir(root), "build");
@@ -566,13 +597,13 @@ async function buildBundle(context, root, recipe, record, hosted, hostServerKey,
566
597
  supervisor: void 0,
567
598
  build
568
599
  } });
569
- recordMacosBuild(root, build, progress.steps());
600
+ recordMacosBuild(root, build, progress.steps(), errorRemedy(error));
570
601
  throw error;
571
602
  } finally {
572
603
  writer.close();
573
604
  }
574
605
  }
575
- function recordMacosBuild(root, build, compileSteps) {
606
+ function recordMacosBuild(root, build, compileSteps, remedy) {
576
607
  recordFinishedBuild(root, {
577
608
  platform: "macos",
578
609
  status: build.state === "ok" ? "ok" : "failed",
@@ -588,7 +619,11 @@ function recordMacosBuild(root, build, compileSteps) {
588
619
  builtOn: build.builtOn,
589
620
  offloadedTo: build.offloadedTo,
590
621
  offloadFallback: build.offloadFallback,
591
- ...compileSteps === null ? {} : { compileSteps }
622
+ ...compileSteps === null ? {} : { compileSteps },
623
+ ...build.error ? { ledger: {
624
+ message: build.error,
625
+ remedy
626
+ } } : {}
592
627
  });
593
628
  }
594
629
  const LAUNCH_SERVICES_CALL_MS = 2e3;
@@ -659,7 +694,7 @@ function launchPayload(root, record) {
659
694
  };
660
695
  }
661
696
  function macosCommand(program) {
662
- 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) => {
663
698
  const root = findProjectRoot$1(process.cwd());
664
699
  if (options.plan) {
665
700
  try {
@@ -1,2 +1,2 @@
1
- import { n as runMacos, r as waitForLaunchServices, t as macosCommand } from "./macos-DBBPNnIA.mjs";
1
+ import { n as runMacos, r as waitForLaunchServices, t as macosCommand } from "./macos-Bo9st9Di.mjs";
2
2
  export { macosCommand as default, runMacos, waitForLaunchServices };
@@ -1,2 +1,2 @@
1
- import { n as runMacosSupervisor, t as logLines } from "./run-BqB0v3pt.mjs";
1
+ import { n as runMacosSupervisor, t as logLines } from "./run-y2HwyNvg.mjs";
2
2
  export { logLines, runMacosSupervisor };
@@ -1,10 +1,10 @@
1
- import { P as formatBytes } from "./config-BktkY_zC.mjs";
2
- import { E as maintenanceLogger, T as openGcLog, jt as deviceSweepIsScoped, u as resolveBudget, w as maintenanceItem } from "./budget-k2mZGvvk.mjs";
3
- import { B as memoryCulpritAdvice, F as memoryCulpritsUnder } from "./ios-WxpDJ5T1.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-Bm_A1xX9.mjs";
3
+ import { I as memoryCulpritsUnder, V as memoryCulpritAdvice } from "./ios-B1DYuOjh.mjs";
4
4
  import { t as resolveMaintenanceSettings } from "./settings-Djl-mpjX.mjs";
5
- import { t as relaunchWithLogFile } from "./detached-entry-KmieOKgN.mjs";
6
- 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-BKuklFh_.mjs";
7
- import { i as plannedMaintenance, m as measureOwnedDevices, n as diskRecovered, o as triggeringRoot, r as executeAction } from "./act-C-BqJEpu.mjs";
5
+ import { C as sizeScanDeferred, S as measureSizes, b as measurePressure, v as measureDisk } from "./worktree-2dk5edza.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-8iswyfRa.mjs";
8
8
  import { r as due, t as capChildLog } from "./attempt-ClyJlZPT.mjs";
9
9
  import { releaseClaim, tryAcquireClaim } from "@stim-cli/core/ownership-claim";
10
10
  import { randomBytes } from "node:crypto";
@@ -318,7 +318,7 @@ async function runMaintenance(trigger) {
318
318
  },
319
319
  ...action.workspace && action.kind !== "would-remove-worktree" ? { workspace: action.workspace } : {}
320
320
  };
321
- 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);
322
322
  else if (outcome.status === "failed") {
323
323
  failures.push(`${describeDone(action)} failed: ${outcome.detail}`);
324
324
  record("maintenance_failure", "error", `Could not process ${action.target}: ${outcome.detail}`, {
@@ -1,7 +1,7 @@
1
- import { S as process_identity_exports, l as WorkspaceProcessCleanupError, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { r as readWorkspaceState } from "./workspace-state-pUg3_RRA.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-BktkY_zC.mjs";
4
- import { t as runOperationFile } from "./operation-exec-CUZifp6Z.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-kIZrdlSg.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,10 +1,8 @@
1
- import { S as process_identity_exports, c as throwIfCancelled, s as cancelledError } from "./exec-VFRpu1iA.mjs";
2
- import { j as workspaceStateFile$1, l as withWorkspaceStateLockAsync, o as updateWorkspaceState, r as readWorkspaceState$1, s as updateWorkspaceStateAsync } from "./workspace-state-pUg3_RRA.mjs";
3
- import { ct as tailscaleStatusAsync } from "./config-BktkY_zC.mjs";
4
- import { randomBytes, randomUUID } from "node:crypto";
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-kIZrdlSg.mjs";
3
+ import { randomUUID } from "node:crypto";
5
4
  import { statSync, watch } from "node:fs";
6
- import { HOSTED_METRO_REQUESTS_KEY, findPeer, hostedMetroGateways, hostedMetroRequests, isJsonObject, parseMachine } from "@stim-cli/core/state";
7
- import { isIP } from "node:net";
5
+ import { HOSTED_METRO_REQUESTS_KEY, hostedMetroLinks, hostedMetroRequests, isJsonObject } from "@stim-cli/core/state";
8
6
  //#region src/workspace/workspace-state-watch.ts
9
7
  /** Filesystem events are hints; callers retain their own bounded repair and state verification. */
10
8
  function watchWorkspaceState(root, changed) {
@@ -58,8 +56,8 @@ function watchWorkspaceState(root, changed) {
58
56
  };
59
57
  }
60
58
  //#endregion
61
- //#region src/device-host/metro-gateway.ts
62
- async function waitForGateway(root, read, { waitMs, signal, what }) {
59
+ //#region src/device-host/metro-request.ts
60
+ async function waitForSupervisor(root, read, { waitMs, signal, what }) {
63
61
  throwIfCancelled(signal, what);
64
62
  const startedAt = Date.now();
65
63
  const deadline = startedAt + waitMs;
@@ -101,38 +99,23 @@ async function waitForGateway(root, read, { waitMs, signal, what }) {
101
99
  if (onAbort) signal?.removeEventListener("abort", onAbort);
102
100
  }
103
101
  }
104
- function gatewayAddresses(credential, status) {
105
- const machine = parseMachine(credential.machine);
106
- const peer = machine ? findPeer(status, machine.name) : "missing";
107
- if (typeof peer === "string") throw new Error(`${credential.machine} no longer resolves to one tailnet peer. Run stim doctor.`);
108
- const self = isJsonObject(status) && isJsonObject(status.Self) ? status.Self : null;
109
- const address = (Array.isArray(self?.TailscaleIPs) ? self.TailscaleIPs : []).find((ip) => typeof ip === "string" && isIP(ip) === isIP(peer.address) && isIP(ip) !== 0);
110
- if (!address) throw new Error("This machine has no Tailscale address compatible with the hosting Mac.");
111
- return {
112
- address,
113
- peer: peer.address
114
- };
115
- }
116
102
  function requireHostedMetro(root) {
117
103
  const supervisor = readWorkspaceState$1(root)?.supervisor;
118
- if (supervisor?.hostedMetro === true && (0, process_identity_exports.inspectProcessIdentity)(supervisor) === "same") return;
119
- throw Object.assign(/* @__PURE__ */ new Error("Hosted Debug runs require a running Metro supervisor with private gateway support. Run stim stop; stim start, then retry."), {
104
+ if (supervisor?.hostedMetroLinks === true && (0, process_identity_exports.inspectProcessIdentity)(supervisor) === "same") return;
105
+ throw Object.assign(/* @__PURE__ */ new Error("Hosted Debug runs require a running Metro supervisor that links Metro to the hosting machine. Run stim stop; stim start, then retry."), {
120
106
  code: "STIM_HOSTING_REFUSED",
121
107
  remedy: "Run stim stop; stim start, then retry."
122
108
  });
123
109
  }
124
110
  async function requestHostedMetro(root, session, credential, signal) {
125
- throwIfCancelled(signal, "hosted Metro gateway");
111
+ throwIfCancelled(signal, "hosted Metro link");
126
112
  requireHostedMetro(root);
127
- const addresses = gatewayAddresses(credential, await tailscaleStatusAsync(signal));
128
- throwIfCancelled(signal, "hosted Metro gateway");
129
- requireHostedMetro(root);
130
- const previous = hostedMetroRequests(readWorkspaceState$1(root))[session];
131
- const request = previous && previous.address === addresses.address && previous.peer === addresses.peer ? previous : {
113
+ const recorded = readWorkspaceState$1(root);
114
+ const previous = hostedMetroRequests(recorded)[session];
115
+ const answer = hostedMetroLinks(recorded)[session];
116
+ const request = previous?.machine === credential.machine && answer?.id === previous.id && answer.processToken === recorded?.supervisor?.processToken && answer.ready ? previous : {
132
117
  id: randomUUID(),
133
- machine: credential.machine,
134
- ...addresses,
135
- secret: randomBytes(32).toString("hex")
118
+ machine: credential.machine
136
119
  };
137
120
  await updateWorkspaceStateAsync(root, (state) => ({
138
121
  ...state,
@@ -141,24 +124,20 @@ async function requestHostedMetro(root, session, credential, signal) {
141
124
  [session]: request
142
125
  }
143
126
  }), signal);
144
- const opened = await waitForGateway(root, () => {
127
+ if (await waitForSupervisor(root, () => {
145
128
  const state = readWorkspaceState$1(root);
146
- const gateway = hostedMetroGateways(state)[session];
147
- if (gateway?.id === request.id && gateway.processToken === state?.supervisor?.processToken) {
148
- if (gateway.error) throw new Error(gateway.error);
149
- if (gateway.port) return {
150
- gatewayPort: gateway.port,
151
- secret: request.secret
152
- };
129
+ const links = hostedMetroLinks(state)[session];
130
+ if (links?.id === request.id && links.processToken === state?.supervisor?.processToken) {
131
+ if (links.error) throw new Error(links.error);
132
+ if (links.ready) return true;
153
133
  }
154
134
  return null;
155
135
  }, {
156
136
  waitMs: 15e3,
157
137
  signal,
158
- what: "hosted Metro gateway"
159
- });
160
- if (opened) return opened;
161
- throw new Error(`The Metro supervisor did not open a private gateway for ${credential.machine}. Run stim stop; stim start, then retry.`);
138
+ what: "hosted Metro link"
139
+ })) return;
140
+ throw new Error(`The Metro supervisor did not link Metro to ${credential.machine}. Run stim doctor, then stim stop; stim start and retry.`);
162
141
  }
163
142
  function clearHostedMetro(root, session) {
164
143
  updateWorkspaceState(root, (state) => {
@@ -172,17 +151,17 @@ function clearHostedMetro(root, session) {
172
151
  }
173
152
  async function closeHostedMetro(root, session, signal) {
174
153
  await withWorkspaceStateLockAsync(root, () => clearHostedMetro(root, session), signal);
175
- if (!await waitForGateway(root, () => {
154
+ if (!await waitForSupervisor(root, () => {
176
155
  const state = readWorkspaceState$1(root);
177
- const gateway = hostedMetroGateways(state)[session];
156
+ const links = hostedMetroLinks(state)[session];
178
157
  const supervisor = state?.supervisor;
179
- if (!gateway?.port || !supervisor || gateway.processToken !== supervisor.processToken) return true;
158
+ if (!links?.ready || !supervisor || links.processToken !== supervisor.processToken) return true;
180
159
  return (0, process_identity_exports.inspectProcessIdentity)(supervisor) === "gone" ? true : null;
181
160
  }, {
182
161
  waitMs: 5e3,
183
162
  signal,
184
163
  what: "close hosted Metro"
185
- })) throw new Error("The Metro supervisor did not close its private gateway. Restart Metro, then retry stim stop.");
164
+ })) throw new Error("The Metro supervisor did not close its Metro links. Restart Metro, then retry stim stop.");
186
165
  }
187
166
  function hostedMetroSettings(settings, hosted) {
188
167
  return hosted ? {
@@ -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-BktkY_zC.mjs";
3
- import { f as signalProcessTree, m as createPortProbe, s as parseNetstatPids } from "./metro-CjC10t6E.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-BnhXV2Mj.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 { E as workspaceDir, y as sharedBuildCache } from "./workspace-state-pUg3_RRA.mjs";
3
- import { H as deviceSlotPlatforms, p as getProject, q as validateDeviceSlot } from "./config-BktkY_zC.mjs";
4
- import { nt as settingValueAt } from "./settings-CosW5X-S.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-DTAcRwBC.mjs";
6
- import { r as register } from "./cache-manifest-BEZ9Bpl1.mjs";
7
- import { tt as statsProjectKey } from "./budget-k2mZGvvk.mjs";
8
- import { d as runCancellationSignal } from "./native-run-BfIDFKLH.mjs";
9
- import { S as resolveBuild, s as entryDir, t as artifactIn } from "./build-cache-DrXNCy3T.mjs";
10
- import { o as resolveCcache } from "./ccache-Bx5TbxwG.mjs";
11
- import { r as androidToolchainAsync } from "./toolchain-J4J8MrAr.mjs";
12
- import { h as gradleOffloadInputs, y as nativeGradleTransfer } from "./client-D9CaRks-.mjs";
13
- import { d as buildGradle, l as androidSdkRefusal } from "./react-native-build-oNwqF5Wb.mjs";
14
- import { s as explainBuildMiss, u as skippedMissReason } from "./prebuild-gmouvmJZ.mjs";
15
- import { u as resolveAndroidRunPlan } from "./result-7F5hEwQJ.mjs";
16
- import { n as androidProcessRuntime } from "./launch-DOp8RjDz.mjs";
17
- import { n as planFlagRefusal, r as planPayload } from "./build-plan-DrMMdayj.mjs";
18
- import { a as nativeGradleWorkerArtifactIdentity, n as gradleArtifactInputs, r as nativeGradleArtifactSnapshot, t as NATIVE_GRADLE_CACHE_LIMIT } from "./native-gradle-artifact-inputs-btSUulme.mjs";
1
+ import { t as getExecutor } from "./exec-aULwtNly.mjs";
2
+ import { E as workspaceDir, y as sharedBuildCache } from "./workspace-state-kIZrdlSg.mjs";
3
+ import { H as deviceSlotPlatforms, p as getProject, q as validateDeviceSlot } from "./config-Cn94Jc0g.mjs";
4
+ import { it as settingValueAt } from "./settings-CY5JZlNN.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-CsPs-7Mg.mjs";
6
+ import { s as resolveCcache } from "./ccache-Bm_A1xX9.mjs";
7
+ import { r as register } from "./cache-manifest-DEjqGGat.mjs";
8
+ import { lt as statsProjectKey } from "./workspaces-CmOcceDN.mjs";
9
+ import { ot as runCancellationSignal, r as androidToolchainAsync } from "./toolchain-mLA_km-b.mjs";
10
+ import { C as resolveBuild, s as entryDir, t as artifactIn } from "./build-cache-CZULpXVl.mjs";
11
+ import { h as gradleOffloadInputs, y as nativeGradleTransfer } from "./client-YxCer6ab.mjs";
12
+ import { d as buildGradle, l as androidSdkRefusal } from "./react-native-build-jUHnIfZ9.mjs";
13
+ import { s as explainBuildMiss, u as skippedMissReason } from "./prebuild-k8d_tqOq.mjs";
14
+ import { u as resolveAndroidRunPlan } from "./result-BIcXREyC.mjs";
15
+ import { n as androidProcessRuntime } from "./launch-DoySmhjz.mjs";
16
+ import { n as planFlagRefusal, r as planPayload } from "./build-plan-CxoYfxsc.mjs";
17
+ import { a as nativeGradleWorkerArtifactIdentity, n as gradleArtifactInputs, r as nativeGradleArtifactSnapshot, t as NATIVE_GRADLE_CACHE_LIMIT } from "./native-gradle-artifact-inputs-BN96IVw8.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";
@@ -1,8 +1,8 @@
1
- import { t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { r as childEnvironment } from "./operation-exec-CUZifp6Z.mjs";
3
- import { o as androidHome } from "./android-DTAcRwBC.mjs";
4
- import { n as buildCacheKey } from "./build-cache-DrXNCy3T.mjs";
5
- import { _ as nativeGradleLocalSourceDigest, h as gradleOffloadInputs } from "./client-D9CaRks-.mjs";
1
+ import { t as getExecutor } from "./exec-aULwtNly.mjs";
2
+ import { r as childEnvironment } from "./operation-exec-Dp4FuIGR.mjs";
3
+ import { o as androidHome } from "./android-CsPs-7Mg.mjs";
4
+ import { n as buildCacheKey } from "./build-cache-CZULpXVl.mjs";
5
+ import { _ as nativeGradleLocalSourceDigest, h as gradleOffloadInputs } from "./client-YxCer6ab.mjs";
6
6
  import { n as fingerprintNativeInputs } from "./native-inputs-TRTTTRxt.mjs";
7
7
  import { createHash } from "node:crypto";
8
8
  import { homedir } from "node:os";