stim 1.16.0 → 1.17.1

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 (108) hide show
  1. package/dist/{activity-BxwdD81S.mjs → activity-IRvJY_ru.mjs} +23 -3
  2. package/dist/{agent-device-usage-output-Dpih1Tfa.mjs → agent-device-usage-output-BK41vnzN.mjs} +3 -3
  3. package/dist/{android-Ift4kVvt.mjs → android-B6rDWrTm.mjs} +681 -319
  4. package/dist/{android-B_NumVyQ.mjs → android-B_YNZy61.mjs} +7 -43
  5. package/dist/{android-r2rBL8kV.mjs → android-DE4v59Mb.mjs} +12 -3
  6. package/dist/{android-cas-8U4DPqeR.mjs → android-cas-ZFpjJBL_.mjs} +6 -5
  7. package/dist/{app-install-CKWdbXIX.mjs → app-install-VPkI5WEg.mjs} +6 -5
  8. package/dist/{budget-DjrURfQn.mjs → budget-CUDz870h.mjs} +62 -25
  9. package/dist/{build-plan-DjeSb2Xl.mjs → build-plan-BJSXzsCL.mjs} +345 -86
  10. package/dist/{idle-DYVymG92.mjs → build-progress-D0WkjCPd.mjs} +170 -233
  11. package/dist/{build-slots-rUk77xqh.mjs → build-slots-41v_d2x9.mjs} +35 -25
  12. package/dist/{cli-BkYZ_6hy.mjs → cli-BLQqDGlX.mjs} +17 -17
  13. package/dist/cli.mjs +1 -1
  14. package/dist/{client-BTY686R6.mjs → client-CxNotugx.mjs} +313 -44
  15. package/dist/collector-run.mjs +3 -3
  16. package/dist/{command-output-DnJMdEY-.mjs → command-output-CDAIFD-8.mjs} +3 -3
  17. package/dist/{created-devices-D5owjN4C.mjs → created-devices-CpvzBL25.mjs} +1 -1
  18. package/dist/{dependency-state-B6cMXZab.mjs → dependency-state-CLcBHH2M.mjs} +1 -1
  19. package/dist/{deps-urbmfXig.mjs → deps-CVxlsRFn.mjs} +1 -1
  20. package/dist/{dev-client-CroAIjjj.mjs → dev-client-B-XC4uRH.mjs} +2 -2
  21. package/dist/{device-DZQjF7H5.mjs → device-C8IOoJPv.mjs} +7 -7
  22. package/dist/device-capacity-ZC4XSZ4R.mjs +580 -0
  23. package/dist/device-host-worker.mjs +436 -154
  24. package/dist/{device-ios-BadmeL2V.mjs → device-ios-C2Um-XUR.mjs} +75 -44
  25. package/dist/{device-lease-D-hLqx1b.mjs → device-lease-DpoS36_u.mjs} +2 -2
  26. package/dist/{device-lease-run-CqjShqWW.mjs → device-lease-run-B8YltIH_.mjs} +3 -3
  27. package/dist/{device-pool-CUaEWMMm.mjs → device-pool-3o7s5lo4.mjs} +2 -2
  28. package/dist/{device-remote-D5WVWqOq.mjs → device-remote-hFSkpfQu.mjs} +12 -12
  29. package/dist/{doctor-Cimf-gGB.mjs → doctor-BF_435OC.mjs} +40 -58
  30. package/dist/{error-diagnostics-B9L4Ae0x.mjs → error-diagnostics-C-NMnhrk.mjs} +7 -7
  31. package/dist/{gc-Bqy4bjEu.mjs → gc-BsWKa_-d.mjs} +313 -30
  32. package/dist/{gradle-BsO1MdsH.mjs → gradle-bsBRy6i9.mjs} +3 -3
  33. package/dist/{guide-B_uyKTxW.mjs → guide-DC3n6-NH.mjs} +1776 -655
  34. package/dist/{guide-status-CjEZMAD4.mjs → guide-status-Du-ZQ3FD.mjs} +1 -1
  35. package/dist/hosted-android-DgU31wY3.mjs +32 -0
  36. package/dist/{hosted-client-a-WmqE2L.mjs → hosted-client-CdSoH-G6.mjs} +5 -6
  37. package/dist/hosted-ios-BTaVj4Jb.mjs +15 -0
  38. package/dist/{hosted-logs-D5g041Q3.mjs → hosted-logs-SxfBvSvc.mjs} +16 -16
  39. package/dist/{hosted-macos-BSZyIb3y.mjs → hosted-macos-CT9E3meL.mjs} +4 -4
  40. package/dist/{hosted-ios-CIWelIqf.mjs → hosted-native-CZLOrMrN.mjs} +77 -42
  41. package/dist/idle-BXG__1BA.mjs +176 -0
  42. package/dist/{idle-shutdown-CTsDnAde.mjs → idle-shutdown-IGyNV8Cr.mjs} +25 -17
  43. package/dist/{in-use-DvBw0Kxo.mjs → in-use-CvGOUn-x.mjs} +11 -11
  44. package/dist/{ios-aq3QoGI3.mjs → ios-C7JuT1bI.mjs} +173 -91
  45. package/dist/{ios-BaInn3sW.mjs → ios-DSfnPfse.mjs} +4 -4
  46. package/dist/{ios-device-FfCN_C8p.mjs → ios-device-pAN4t54-.mjs} +1 -1
  47. package/dist/ios-state-8L3lgum6.mjs +89 -0
  48. package/dist/{launch-verify-2DBRizjo.mjs → launch-verify-lTnWZikR.mjs} +2 -2
  49. package/dist/{logs-CHEVK8zD.mjs → logs-DNxKcok9.mjs} +36 -23
  50. package/dist/{macos-CSYEAFmF.mjs → macos-BEs8cwKx.mjs} +75 -34
  51. package/dist/macos-run.mjs +1 -1
  52. package/dist/maintenance-run.mjs +2 -2
  53. package/dist/{metro-BeK1ZPz1.mjs → metro-g8NqiJp-.mjs} +1 -1
  54. package/dist/{metro-gateway-BJ-rxQAB.mjs → metro-gateway-CHqK0p-a.mjs} +22 -3
  55. package/dist/{named-ports-Bk_YXEmE.mjs → named-ports-C8m8EQs2.mjs} +2 -2
  56. package/dist/{native-run-NaBrRFtQ.mjs → native-run-D1Q56rAD.mjs} +17 -6
  57. package/dist/{native-runtime-DBzRnEKS.mjs → native-runtime-YhaSxP4v.mjs} +6 -6
  58. package/dist/offload-worker.mjs +9 -9
  59. package/dist/{teardown-CL6vDs2Y.mjs → ownership-BMLqyBgJ.mjs} +603 -26
  60. package/dist/{ownership-DiA16AsN.mjs → ownership-DyRQru0q.mjs} +2 -2
  61. package/dist/{ports-R2k4Knz3.mjs → ports-4nYqxPWC.mjs} +2 -2
  62. package/dist/{prebuild-D2fsca_Z.mjs → prebuild-D7RUMkwN.mjs} +3 -3
  63. package/dist/{preview-DhVbvPAZ.mjs → preview-C_JjkEy4.mjs} +7 -7
  64. package/dist/{project-Du91Ilvc.mjs → project-D47Rh0ly.mjs} +7 -2
  65. package/dist/{recordings-BIXOzVnr.mjs → recordings-BNgsD1Tr.mjs} +1 -1
  66. package/dist/{reload-rM9jV1fz.mjs → reload-byOjE3P4.mjs} +62 -35
  67. package/dist/{remote-cache-C8-V13XN.mjs → remote-cache-Ci4DQYYj.mjs} +3 -3
  68. package/dist/{run-f4vI6EnK.mjs → run-CkE9y0nc.mjs} +1 -1
  69. package/dist/{server-bare-CpPGmnmO.mjs → server-bare-BkrSxSsZ.mjs} +1 -1
  70. package/dist/{server-expo-MC0rHlOC.mjs → server-expo-CHTyXD0G.mjs} +2 -2
  71. package/dist/server-expo-CeakhI8P.mjs +2 -0
  72. package/dist/{settings-oTSkkNrM.mjs → settings-Cfd-0r2d.mjs} +10 -9
  73. package/dist/{settings-ZkDzkzvB.mjs → settings-SR9OmW9h.mjs} +3 -3
  74. package/dist/settings.schema.json +123 -76
  75. package/dist/{simslim-B8-7AoTI.mjs → simslim-BWNrc3M3.mjs} +3 -3
  76. package/dist/{slot-launch-B8VrHxn1.mjs → slot-launch-DmjBmpQV.mjs} +8 -8
  77. package/dist/{start-CX8Ig-U2.mjs → start-BEP-XmEA.mjs} +1 -1
  78. package/dist/{start-ClDfwXa4.mjs → start-BHIersSm.mjs} +11 -11
  79. package/dist/{state-DcW6vOd_.mjs → state-BKa8wNN5.mjs} +1 -1
  80. package/dist/{state-3DwSQIBK.mjs → state-DyaNTgfR.mjs} +1 -1
  81. package/dist/{state-C1jB7Q8q.mjs → state-PeQiJuIu.mjs} +2 -2
  82. package/dist/{stats-CEZ_i5je.mjs → stats-Bq4fJOdB.mjs} +7 -4
  83. package/dist/{status-Cs7VLg9D.mjs → status-CqeWbIWW.mjs} +128 -38
  84. package/dist/{status-BuvBFeII.mjs → status-CzS4bPO9.mjs} +4 -4
  85. package/dist/{stop-Bffozsac.mjs → stop-Cj01je8D.mjs} +48 -27
  86. package/dist/{stop-B0Yxtmiy.mjs → stop-D03prQnW.mjs} +4 -4
  87. package/dist/{stop-Dt_dM16A.mjs → stop-DOxwkH4j.mjs} +2 -2
  88. package/dist/{stop-cause-CidxIqup.mjs → stop-cause-rhmGfwvt.mjs} +1 -1
  89. package/dist/supervisor-run.d.mts +7 -4
  90. package/dist/supervisor-run.mjs +26 -28
  91. package/dist/{support-D4aYJniO.mjs → support-BE-tbOP9.mjs} +45 -20
  92. package/dist/{support-CAP8qDUF.mjs → support-WvD__tSV.mjs} +7 -7
  93. package/dist/{toolchain-DkUflduf.mjs → toolchain-CdrxgUeA.mjs} +8 -8
  94. package/dist/{warm-progress-CpGv3Wb6.mjs → warm-progress-DF4JRvYI.mjs} +3 -3
  95. package/dist/watchman-APYjXSQa.mjs +48 -0
  96. package/dist/{web-DWUaMp8P.mjs → web-DddUdJzr.mjs} +12 -13
  97. package/dist/web-run.mjs +4 -4
  98. package/dist/{workspace-process-lock-BL7Q0HCO.mjs → workspace-process-lock-2mNzOlaB.mjs} +3 -2
  99. package/dist/{workspace-state-B8-aJ1_5.mjs → workspace-state-DqcCbpE7.mjs} +2 -2
  100. package/dist/{workspaces-BV4pdHFz.mjs → workspaces-Bcib97-6.mjs} +3 -3
  101. package/dist/{worktree-K-xj9Db0.mjs → worktree-AK_m-d_m.mjs} +141 -40
  102. package/dist/{worktree-jnG8Iph5.mjs → worktree-CsAjSmEo.mjs} +1 -1
  103. package/package.json +5 -5
  104. package/dist/device-capacity-BHwxNBlu.mjs +0 -136
  105. package/dist/ios-state-DS5UpYTH.mjs +0 -48
  106. package/dist/machines-BIBUdhpj.mjs +0 -265
  107. package/dist/ownership-hCkPzGmr.mjs +0 -571
  108. package/dist/server-expo-CVqO2c35.mjs +0 -2
@@ -3,23 +3,23 @@ import { readFileSync } from "node:fs";
3
3
  import { Command } from "commander";
4
4
  //#region bin/cli.ts
5
5
  const commands = /* @__PURE__ */ new Map([
6
- ["doctor", () => import("./doctor-Cimf-gGB.mjs")],
7
- ["worktree", () => import("./worktree-jnG8Iph5.mjs")],
8
- ["start", () => import("./start-CX8Ig-U2.mjs")],
9
- ["ports", () => import("./ports-R2k4Knz3.mjs")],
10
- ["stop", () => import("./stop-Dt_dM16A.mjs")],
11
- ["ios", () => import("./ios-aq3QoGI3.mjs")],
12
- ["android", () => import("./android-Ift4kVvt.mjs")],
13
- ["web", () => import("./web-DWUaMp8P.mjs")],
14
- ["macos", () => import("./macos-CSYEAFmF.mjs")],
15
- ["reload", () => import("./reload-rM9jV1fz.mjs")],
16
- ["device", () => import("./device-DZQjF7H5.mjs")],
17
- ["logs", () => import("./logs-CHEVK8zD.mjs")],
18
- ["settings", () => import("./settings-ZkDzkzvB.mjs")],
19
- ["status", () => import("./status-Cs7VLg9D.mjs")],
20
- ["stats", () => import("./stats-CEZ_i5je.mjs")],
21
- ["gc", () => import("./gc-Bqy4bjEu.mjs")],
22
- ["guide", () => import("./guide-B_uyKTxW.mjs")]
6
+ ["doctor", () => import("./doctor-BF_435OC.mjs")],
7
+ ["worktree", () => import("./worktree-CsAjSmEo.mjs")],
8
+ ["start", () => import("./start-BEP-XmEA.mjs")],
9
+ ["ports", () => import("./ports-4nYqxPWC.mjs")],
10
+ ["stop", () => import("./stop-DOxwkH4j.mjs")],
11
+ ["ios", () => import("./ios-C7JuT1bI.mjs")],
12
+ ["android", () => import("./android-B6rDWrTm.mjs")],
13
+ ["web", () => import("./web-DddUdJzr.mjs")],
14
+ ["macos", () => import("./macos-BEs8cwKx.mjs")],
15
+ ["reload", () => import("./reload-byOjE3P4.mjs")],
16
+ ["device", () => import("./device-C8IOoJPv.mjs")],
17
+ ["logs", () => import("./logs-DNxKcok9.mjs")],
18
+ ["settings", () => import("./settings-SR9OmW9h.mjs")],
19
+ ["status", () => import("./status-CqeWbIWW.mjs")],
20
+ ["stats", () => import("./stats-Bq4fJOdB.mjs")],
21
+ ["gc", () => import("./gc-BsWKa_-d.mjs")],
22
+ ["guide", () => import("./guide-DC3n6-NH.mjs")]
23
23
  ]);
24
24
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
25
25
  const program = new Command();
package/dist/cli.mjs CHANGED
@@ -4,6 +4,6 @@ const encode = (version) => version.split(".", 3).reduce((sum, part) => sum * 1e
4
4
  if (encode(process.versions.node) < encode("22.12.0")) {
5
5
  process.stderr.write(`STIM_NODE_UNSUPPORTED: Stim needs Node 22.12.0 or later; this is Node ${process.versions.node} at ${process.execPath}. To run Stim where a project pins an older Node, see https://stim.appandflow.com/docs/requirements#older-node-pins\n`);
6
6
  process.exitCode = 1;
7
- } else import("./cli-BkYZ_6hy.mjs");
7
+ } else import("./cli-BLQqDGlX.mjs");
8
8
  //#endregion
9
9
  export {};
@@ -1,12 +1,13 @@
1
1
  import { t as getExecutor } from "./exec-CaErVv7t.mjs";
2
2
  import { _ as loadConfig$1, d as getConfigDir } from "./config-D0DbpZtM.mjs";
3
- import { w as withDirLock } from "./workspace-state-B8-aJ1_5.mjs";
4
- import { T as CCACHE_UNAVAILABLE, a as toolchainMismatches, l as COMPILATION_CACHE_UNAVAILABLE, s as manifestDigest } from "./toolchain-DkUflduf.mjs";
3
+ import { w as withDirLock } from "./workspace-state-DqcCbpE7.mjs";
4
+ import { T as CCACHE_UNAVAILABLE, a as toolchainMismatches, l as COMPILATION_CACHE_UNAVAILABLE, s as manifestDigest } from "./toolchain-CdrxgUeA.mjs";
5
5
  import { createHash } from "node:crypto";
6
6
  import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readlinkSync, realpathSync, renameSync, rmSync, writeFileSync, writeSync } from "node:fs";
7
7
  import { basename, dirname, join, relative } from "node:path";
8
8
  import { InvalidArgumentError } from "commander";
9
- import { OFFLOAD_MODES, buildMachinesFile, buildMachinesLock, endpoint, findPeer as findPeer$1, isJsonObject, parseMachine, parseMachine as parseMachine$1, pinnedEndpoint, readBuildMachines, saturation } from "@stim-cli/core/state";
9
+ import { OFFLOAD_MODES, acceptsShape, buildMachinesFile, buildMachinesLock, deviceHostMachinesClaims, deviceHostMachinesFile, deviceHostMachinesLock, endpoint, findPeer as findPeer$1, isJsonObject, parseMachine, parseMachine as parseMachine$1, pinnedEndpoint, readBuildMachines, readDeviceHostMachines, saturation, settingDefinition } from "@stim-cli/core/state";
10
+ import { releaseClaim, tryAcquireClaim } from "@stim-cli/core/ownership-claim";
10
11
  import { hostname } from "node:os";
11
12
  import { WebSocket } from "ws";
12
13
  //#region src/offload/access-ticket.ts
@@ -93,16 +94,280 @@ function pinnedEndpoint$1(credential, status = tailscaleStatus) {
93
94
  return pinnedEndpoint(credential, parseMachine(credential.machine) ? status() : null);
94
95
  }
95
96
  //#endregion
97
+ //#region src/device-host/machines.ts
98
+ function note$1(title, detail, fix = null) {
99
+ return {
100
+ code: "device-host-machine",
101
+ level: "note",
102
+ title,
103
+ detail,
104
+ fix
105
+ };
106
+ }
107
+ const approval$1 = (machine, id) => `A person on ${machine} approves it with \`stim-server devices grant ${id} --device-host\`.`;
108
+ function configuredMachines() {
109
+ const remote = loadConfig$1()?.remote;
110
+ if (remote !== void 0 && !isJsonObject(remote)) return null;
111
+ const machines = remote?.machines;
112
+ if (machines === void 0) return [];
113
+ return acceptsShape(settingDefinition("remote.machines"), machines) ? machines : null;
114
+ }
115
+ /** The `remote.machines` entries this Mac asked for device-host access, in setting order; null when the setting is invalid. */
116
+ function hostingMachines() {
117
+ const configured = configuredMachines();
118
+ if (configured === null) return null;
119
+ try {
120
+ const asked = readDeviceHostMachines();
121
+ return configured.filter((machine) => asked.some((each) => each.machine === machine));
122
+ } catch {
123
+ return configured;
124
+ }
125
+ }
126
+ function store(machines) {
127
+ withDirLock(deviceHostMachinesLock(), () => {
128
+ const file = deviceHostMachinesFile();
129
+ const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
130
+ try {
131
+ writeFileSync(tmp, `${JSON.stringify({
132
+ version: 1,
133
+ machines
134
+ }, null, 2)}\n`, { mode: 384 });
135
+ renameSync(tmp, file);
136
+ } finally {
137
+ rmSync(tmp, { force: true });
138
+ }
139
+ }, { ensureParent: () => mkdirSync(getConfigDir(), { recursive: true }) });
140
+ }
141
+ async function request(machine, peer, port, deviceName, io) {
142
+ const ticket = readAccessTicket();
143
+ const reply = await io.hello(endpoint(peer, port), {
144
+ request: "device-host",
145
+ deviceName,
146
+ ...ticket ? { setupTicket: ticket.ticket } : {}
147
+ });
148
+ if (!("result" in reply) || reply.result?.approval?.state !== "pending" || typeof reply.result.deviceToken !== "string" || !reply.result.deviceToken || typeof reply.result.device?.id !== "string" || !reply.result.device.id || typeof reply.result.approval.expiresAt !== "string" || !reply.result.approval.expiresAt) return {
149
+ report: {
150
+ machine,
151
+ dnsName: peer.dnsName,
152
+ state: "unreachable"
153
+ },
154
+ finding: note$1(`Could not ask ${machine} for hosting access`, "The worker did not return a pending request.")
155
+ };
156
+ const credential = {
157
+ machine,
158
+ nodeId: peer.nodeId,
159
+ dnsName: peer.dnsName,
160
+ deviceId: reply.result.device.id,
161
+ deviceToken: reply.result.deviceToken,
162
+ state: "pending",
163
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
164
+ ...ticket ? { ticketHash: ticket.ticketHash } : {}
165
+ };
166
+ return {
167
+ report: {
168
+ machine,
169
+ dnsName: peer.dnsName,
170
+ state: "pending",
171
+ deviceId: credential.deviceId,
172
+ requestedAt: credential.requestedAt
173
+ },
174
+ finding: note$1(`Asked ${machine} for hosting access`, `The request lapses at ${reply.result.approval.expiresAt}.`, approval$1(machine, credential.deviceId)),
175
+ credential
176
+ };
177
+ }
178
+ /** Reports the device-host approval of each remote Mac, separate from its build approval. Only --fix asks or forgets credentials; every token stays pinned. */
179
+ async function inspectDeviceHostMachines({ fix }, io = realIo, entries = configuredMachines()) {
180
+ if (entries === null) return {
181
+ findings: [note$1("Invalid remote.machines setting", "Use a remote object with machines as an array of tailnet names. Existing hosting credentials and pinned nodes are preserved.", "Run `stim guide settings` and correct the setting before running doctor again.")],
182
+ machines: []
183
+ };
184
+ const unavailable = (state, finding) => ({
185
+ findings: [finding],
186
+ machines: entries.map((machine) => ({
187
+ machine,
188
+ state
189
+ }))
190
+ });
191
+ const unreadable = () => unavailable("credentials-unavailable", note$1("Hosting credentials are unreadable", `Stim preserves ${deviceHostMachinesFile()} and its pinned nodes.`, "Restore the existing file from a trusted backup or restore read access before running doctor again."));
192
+ if (!entries.length) {
193
+ if (!fix) return {
194
+ findings: [],
195
+ machines: []
196
+ };
197
+ try {
198
+ if (!readDeviceHostMachines().length) return {
199
+ findings: [],
200
+ machines: []
201
+ };
202
+ } catch {
203
+ return unreadable();
204
+ }
205
+ }
206
+ const claim = tryAcquireClaim({
207
+ root: deviceHostMachinesClaims(),
208
+ mode: "exclusive",
209
+ label: "device-host approval"
210
+ });
211
+ if (!claim.acquired) {
212
+ releaseClaim(claim.pending);
213
+ return unavailable("busy", note$1("Device-host approval is in use", "Another doctor run holds the hosting credential claim. Run doctor again after it finishes."));
214
+ }
215
+ try {
216
+ let credentials;
217
+ try {
218
+ credentials = readDeviceHostMachines();
219
+ } catch {
220
+ return unreadable();
221
+ }
222
+ if (fix) {
223
+ const kept = credentials.filter((each) => entries.includes(each.machine));
224
+ if (kept.length !== credentials.length) {
225
+ store(kept);
226
+ credentials = kept;
227
+ }
228
+ }
229
+ if (!entries.length) return {
230
+ findings: [],
231
+ machines: []
232
+ };
233
+ const status = io.status();
234
+ if (!isJsonObject(status)) return unavailable("tailscale-off", note$1("Remote Macs are unreachable", "remote.machines names remote Macs, but Tailscale is not running."));
235
+ const self = isJsonObject(status.Self) ? status.Self : {};
236
+ const deviceName = (typeof self.HostName === "string" && self.HostName ? self.HostName : hostname()).replace(/[\p{Cc}\p{Cf}]/gu, "").trim().slice(0, 64) || "Mac";
237
+ const inspected = {
238
+ findings: [],
239
+ machines: []
240
+ };
241
+ const namedNodes = /* @__PURE__ */ new Set();
242
+ for (const machine of new Set(entries)) {
243
+ const parsed = parseMachine$1(machine);
244
+ if (!parsed) {
245
+ inspected.machines.push({
246
+ machine,
247
+ state: "invalid"
248
+ });
249
+ inspected.findings.push(note$1(`Remote Mac ${machine} is not a tailnet name`, "Expected `name` or `name:port`."));
250
+ continue;
251
+ }
252
+ const current = io.status();
253
+ if (!isJsonObject(current)) {
254
+ inspected.machines.push({
255
+ machine,
256
+ state: "tailscale-off"
257
+ });
258
+ inspected.findings.push(note$1(`Remote Mac ${machine} is unreachable`, "Tailscale stopped before this connection."));
259
+ continue;
260
+ }
261
+ const peer = findPeer$1(current, parsed.name);
262
+ if (peer === "missing" || peer === "ambiguous") {
263
+ inspected.machines.push({
264
+ machine,
265
+ state: "not-on-tailnet"
266
+ });
267
+ inspected.findings.push(note$1(`Remote Mac ${machine} is not on this tailnet`, peer === "missing" ? "No peer has that name." : "Several peers match that name."));
268
+ continue;
269
+ }
270
+ const nodeRoute = `${peer.nodeId}:${parsed.port}`;
271
+ if (namedNodes.has(nodeRoute)) {
272
+ inspected.machines.push({
273
+ machine,
274
+ dnsName: peer.dnsName,
275
+ state: "invalid"
276
+ });
277
+ inspected.findings.push(note$1(`Remote Mac ${machine} repeats a named node`, "Name each tailnet node and serve port only once in remote.machines."));
278
+ continue;
279
+ }
280
+ namedNodes.add(nodeRoute);
281
+ const credential = credentials.find((each) => each.machine === machine);
282
+ const known = {
283
+ machine,
284
+ dnsName: peer.dnsName,
285
+ ...credential ? {
286
+ deviceId: credential.deviceId,
287
+ requestedAt: credential.requestedAt
288
+ } : {}
289
+ };
290
+ if (credential && credential.nodeId !== peer.nodeId) {
291
+ inspected.machines.push({
292
+ ...known,
293
+ state: "node-changed"
294
+ });
295
+ inspected.findings.push(note$1(`Remote Mac ${machine} is a different tailnet node`, "Stim refuses to connect or send the saved token.", `If that Mac was replaced, remove ${machine} from remote.machines, run \`stim doctor --fix\`, then add it back and run \`stim doctor --fix\` again to request approval on the new node.`));
296
+ continue;
297
+ }
298
+ let ask = !credential && fix;
299
+ if (credential) {
300
+ const reply = await io.hello(endpoint(peer, parsed.port), { deviceToken: credential.deviceToken });
301
+ if ("result" in reply && reply.result?.device?.id === credential.deviceId && Array.isArray(reply.result.capabilities) && reply.result.capabilities.includes("device-host")) {
302
+ if (credential.state !== "approved") {
303
+ credentials = credentials.map((each) => each.machine === machine ? {
304
+ ...each,
305
+ state: "approved"
306
+ } : each);
307
+ store(credentials);
308
+ }
309
+ const host = readHostPermissions(reply.result.host);
310
+ if (host && (host.screenRecording === false || host.accessibility === false)) {
311
+ const panes = [...host.screenRecording === false ? ["Screen & System Audio Recording (Screen Recording on macOS 14)"] : [], ...host.accessibility === false ? ["Device Control and Data Access (Accessibility on macOS 26 and earlier)"] : []];
312
+ const detail = [...host.screenRecording === false ? ["Viewing hosted macOS apps needs Screen Recording."] : [], ...host.accessibility === false ? ["Controlling them needs the control permission."] : []];
313
+ inspected.findings.push(note$1(`Remote Mac ${machine} needs ${panes.join(" and ")} for ${host.name}`, detail.join(" "), `On ${machine}, approve ${host.name} in System Settings > Privacy & Security, or run \`stim-server service install\` there again to show the requests.`));
314
+ }
315
+ inspected.machines.push({
316
+ ...known,
317
+ state: "approved",
318
+ ...host ? { host } : {}
319
+ });
320
+ continue;
321
+ }
322
+ const pending = "error" in reply && reply.error?.code === "approval-pending";
323
+ const revoked = "error" in reply && reply.error?.code === "unauthorized";
324
+ const ticket = fix && pending && credential.state !== "approved" ? readAccessTicket() : void 0;
325
+ ask = fix && (revoked || !!ticket && credential.ticketHash !== ticket.ticketHash);
326
+ if (pending && !ask) {
327
+ inspected.machines.push({
328
+ ...known,
329
+ state: "pending"
330
+ });
331
+ inspected.findings.push(note$1(`Remote Mac ${machine} has not approved this Mac for device hosting yet`, `Requested at ${credential.requestedAt}.`, approval$1(machine, credential.deviceId)));
332
+ continue;
333
+ }
334
+ if (!ask) {
335
+ inspected.machines.push({
336
+ ...known,
337
+ state: revoked ? "revoked" : "unreachable"
338
+ });
339
+ inspected.findings.push(note$1(`Remote Mac ${machine} ${revoked ? "no longer accepts this Mac for device hosting" : "did not confirm hosting access"}`, "The saved token and pinned node are preserved.", revoked ? "Run `stim doctor --fix` to ask again." : `Check stim-server and its tailnet serve route on ${machine}, then run doctor again.`));
340
+ continue;
341
+ }
342
+ }
343
+ if (ask) {
344
+ const result = await request(machine, peer, parsed.port, deviceName, io);
345
+ if (result.credential) {
346
+ credentials = [...credentials.filter((each) => each.machine !== machine), result.credential];
347
+ store(credentials);
348
+ }
349
+ inspected.machines.push(result.report);
350
+ inspected.findings.push(result.finding);
351
+ } else {
352
+ inspected.machines.push({
353
+ ...known,
354
+ state: "not-asked"
355
+ });
356
+ inspected.findings.push(note$1(`Remote Mac ${machine} has not approved this Mac for device hosting`, "This Mac has not asked for hosting access.", "Run `stim doctor --fix` to ask."));
357
+ }
358
+ }
359
+ return inspected;
360
+ } finally {
361
+ releaseClaim(claim.acquired);
362
+ }
363
+ }
364
+ //#endregion
96
365
  //#region src/offload/build-machines.ts
97
- /** The build machines named in `offload.machines` that this Mac asked for build access, in that order. */
98
- function pairedMachines(entries = configuredMachines()) {
366
+ /** The `remote.machines` entries that this Mac asked for build access, in that order. */
367
+ function pairedMachines(entries = configuredMachines() ?? []) {
99
368
  const credentials = readBuildMachines();
100
369
  return entries.flatMap((entry) => credentials.filter((each) => each.machine === entry));
101
370
  }
102
- function configuredMachines() {
103
- const machines = loadConfig$1()?.offload?.machines;
104
- return Array.isArray(machines) ? machines.filter((entry) => typeof entry === "string") : [];
105
- }
106
371
  function updateCredentials(change) {
107
372
  const dir = getConfigDir();
108
373
  withDirLock(buildMachinesLock(), () => {
@@ -154,7 +419,7 @@ function problemFix(code, entry) {
154
419
  case "unreachable": return `Check that stim-server runs on ${entry} and that its tailscale serve route answers, then run \`stim doctor\` again. To keep it running there, run \`stim-server service install --serve\` on ${entry}.`;
155
420
  case "checkout": return "Offload syncs the files git lists; run Stim from a git checkout of the app.";
156
421
  case "stim-build": return `Update stim-server on ${entry} to the same Stim build as this Mac: there, run \`stim-server service update --release <version>\` for this Mac's release, or \`--from <dir>\` with the packed packages of this Mac's checkout.`;
157
- case "arch": return "Use a build machine with the same CPU architecture as this Mac.";
422
+ case "arch": return "Use a remote Mac with the same CPU architecture as this Mac.";
158
423
  case "xcode":
159
424
  case "simulator-sdk":
160
425
  case "macos-sdk": return `Install and select the same Xcode on ${entry} and this Mac (\`xcode-select -p\` on each).`;
@@ -166,8 +431,8 @@ function problemFix(code, entry) {
166
431
  case "ndk":
167
432
  case "build-tools":
168
433
  case "compile-sdk": return `Install the missing package with sdkmanager in the Android SDK stim-server on ${entry} uses (its ANDROID_HOME, else ~/Library/Android/sdk).`;
169
- case "disk": return `Free space on ${entry}'s worker root (offload.workerRoot there).`;
170
- case "busy": return `Builds stay on this Mac until ${entry} has capacity. On ${entry}, offload.maxLoadPerCore sets the load it accepts and concurrency.maxBuilds how many of its own builds it runs; it takes one offloaded build at a time.`;
434
+ case "disk": return `Free space on ${entry}'s worker root (server.workerRoot there).`;
435
+ case "busy": return `Builds stay on this Mac until ${entry} has capacity. On ${entry}, server.maxLoadPerCore sets the load it accepts and concurrency.maxBuilds how many of its own builds it runs; it takes one offloaded build at a time.`;
171
436
  }
172
437
  }
173
438
  const TRANSIENT = /* @__PURE__ */ new Set(["unreachable", "busy"]);
@@ -175,7 +440,7 @@ function offloadFindings(entry, problems) {
175
440
  return problems.map((problem) => ({
176
441
  code: `build-machine-${problem.code}`,
177
442
  level: TRANSIENT.has(problem.code) ? "note" : "cost",
178
- title: `Build machine ${entry} ${PROBLEM_TITLES[problem.code]}`,
443
+ title: `Remote Mac ${entry} ${PROBLEM_TITLES[problem.code]}`,
179
444
  detail: `Builds fall back to this Mac: ${problem.reason}.`,
180
445
  fix: problemFix(problem.code, entry)
181
446
  }));
@@ -227,7 +492,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
227
492
  machine: entry,
228
493
  state: "invalid"
229
494
  },
230
- finding: note(`Build machine ${entry} is not a tailnet name`, "Expected `name` or `name:port`.")
495
+ finding: note(`Remote Mac ${entry} is not a tailnet name`, "Expected `name` or `name:port`.")
231
496
  };
232
497
  const peer = findPeer$1(status, parsed.name);
233
498
  if (peer === "missing" || peer === "ambiguous") {
@@ -237,7 +502,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
237
502
  machine: entry,
238
503
  state: "not-on-tailnet"
239
504
  },
240
- finding: note(`Build machine ${entry} is not on this tailnet`, detail)
505
+ finding: note(`Remote Mac ${entry} is not on this tailnet`, detail)
241
506
  };
242
507
  }
243
508
  const credential = readBuildMachines().find((each) => each.machine === entry);
@@ -252,7 +517,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
252
517
  deviceId: credential.deviceId,
253
518
  requestedAt: credential.requestedAt
254
519
  },
255
- finding: note(`Build machine ${entry} is a different tailnet node`, `This Mac paired with node ${credential.nodeId}, but ${peer.dnsName} is now node ${peer.nodeId}. Stim does not connect to it.`, `If that Mac was replaced, remove ${entry} from offload.machines, run \`stim doctor --fix\` to forget the old pairing, then add it back and run \`stim doctor --fix\` again.`)
520
+ finding: note(`Remote Mac ${entry} is a different tailnet node`, `This Mac paired with node ${credential.nodeId}, but ${peer.dnsName} is now node ${peer.nodeId}. Stim does not connect to it.`, `If that Mac was replaced, remove ${entry} from remote.machines, run \`stim doctor --fix\` to forget the old pairing, then add it back and run \`stim doctor --fix\` again.`)
256
521
  };
257
522
  if (!credential) {
258
523
  if (fix) return requestAccess(entry, peer, parsed.port, deviceName, io);
@@ -261,7 +526,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
261
526
  ...known,
262
527
  state: "not-asked"
263
528
  },
264
- finding: note(`Build machine ${entry} has not approved this Mac`, "This Mac has not asked it for build access.", "Run `stim doctor --fix` to ask.")
529
+ finding: note(`Remote Mac ${entry} has not approved this Mac for builds`, "This Mac has not asked it for build access.", "Run `stim doctor --fix` to ask.")
265
530
  };
266
531
  }
267
532
  const paired = {
@@ -311,7 +576,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
311
576
  ...paired,
312
577
  state: "pending"
313
578
  },
314
- finding: note(`Build machine ${entry} has not approved this Mac yet`, `Requested at ${credential.requestedAt}.`, approval(entry, credential.deviceId))
579
+ finding: note(`Remote Mac ${entry} has not approved this Mac for builds yet`, `Requested at ${credential.requestedAt}.`, approval(entry, credential.deviceId))
315
580
  };
316
581
  }
317
582
  if ("error" in reply && reply.error.code === "unauthorized") {
@@ -321,7 +586,7 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
321
586
  ...paired,
322
587
  state: "revoked"
323
588
  },
324
- finding: note(`Build machine ${entry} no longer accepts this Mac`, `${reply.error.message} It was revoked, or the request lapsed before approval.`, "Run `stim doctor --fix` to ask again.")
589
+ finding: note(`Remote Mac ${entry} no longer accepts this Mac for builds`, `${reply.error.message} It was revoked, or the request lapsed before approval.`, "Run `stim doctor --fix` to ask again.")
325
590
  };
326
591
  }
327
592
  const reason = "failed" in reply ? reply.failed : "error" in reply ? reply.error.message : "unexpected reply";
@@ -330,17 +595,21 @@ async function inspectMachine(entry, status, deviceName, fix, io, check) {
330
595
  ...paired,
331
596
  state: "unreachable"
332
597
  },
333
- finding: note(`Could not reach build machine ${entry}`, reason, `Check that stim-server runs on ${entry}. To keep it running there, run \`stim-server service install --serve\` on ${entry}.`)
598
+ finding: note(`Could not reach remote Mac ${entry}`, reason, `Check that stim-server runs on ${entry}. To keep it running there, run \`stim-server service install --serve\` on ${entry}.`)
334
599
  };
335
600
  }
336
601
  /**
337
- * Doctor findings and a report for each `offload.machines` entry. The worker's node is pinned when access is
602
+ * Doctor findings and a report for each `remote.machines` entry. The worker's node is pinned when access is
338
603
  * requested; a later connection goes only to the current MagicDNS name of that same node, checked before the token
339
604
  * is sent. With `fix`, requests access from a named machine this Mac holds no pairing for, requests again when the
340
605
  * pinned node forgot this Mac or, with `STIM_ACCESS_TICKET` set, when a pending request carries another ticket, and forgets pairings of machines no longer named. With `check`, each approved
341
606
  * machine is asked for one build offer and reports every reason it would not take this project's build.
342
607
  */
343
608
  async function inspectBuildMachines({ fix, check = null }, io = realIo, entries = configuredMachines()) {
609
+ if (entries === null) return {
610
+ findings: [note("Invalid remote.machines setting", "Use a remote object with machines as an array of tailnet names. Existing credentials and pinned nodes are preserved.", "Run `stim guide settings` and correct the setting before running doctor again.")],
611
+ machines: []
612
+ };
344
613
  const unnamed = (each) => !entries.includes(each.machine);
345
614
  if (fix && readBuildMachines().some(unnamed)) updateCredentials((credentials) => credentials.filter((each) => !unnamed(each)));
346
615
  if (entries.length === 0) return {
@@ -349,7 +618,7 @@ async function inspectBuildMachines({ fix, check = null }, io = realIo, entries
349
618
  };
350
619
  const status = io.status();
351
620
  if (!isJsonObject(status)) return {
352
- findings: [note("Build machines are unreachable", "offload.machines names build machines, but Tailscale is not running.")],
621
+ findings: [note("Remote Macs are unreachable", "remote.machines names remote Macs, but Tailscale is not running.")],
353
622
  machines: entries.map((machine) => ({
354
623
  machine,
355
624
  state: "tailscale-off"
@@ -373,14 +642,14 @@ async function inspectBuildMachines({ fix, check = null }, io = realIo, entries
373
642
  //#region src/offload/selection.ts
374
643
  var OffloadRefusal = class extends Error {
375
644
  code = "STIM_OFFLOAD_REFUSED";
376
- remedy = "Run stim doctor --fix to ask for build access if not paired. On the worker, a person finds the id with stim-server devices and approves it with stim-server devices grant <id> --build. Check stim settings get offload.machines, or rerun with --build-machine auto or --build-machine local.";
645
+ remedy = "Run stim doctor --fix to ask for build access if not paired. On the worker, a person finds the id with stim-server devices and approves it with stim-server devices grant <id> --build. Check stim settings get remote.machines, or rerun with --remote-build auto or --remote-build local.";
377
646
  constructor(machine, reason) {
378
647
  super(reason.startsWith(`${machine}: `) ? reason : `${machine}: ${reason}`);
379
648
  }
380
649
  };
381
650
  function resolveBuildMachine(flag, env, setting) {
382
651
  const selected = flag ?? (env?.trim() || void 0) ?? setting ?? "auto";
383
- if (typeof selected !== "string" || !selected.trim() || !parseMachine(selected)) throw Object.assign(/* @__PURE__ */ new Error("--build-machine / offload.machine must be auto, local, or a tailnet machine name."), { code: "STIM_BAD_ARG" });
652
+ if (typeof selected !== "string" || !selected.trim() || !parseMachine(selected)) throw Object.assign(/* @__PURE__ */ new Error("--remote-build / remote.build must be auto, local, or a tailnet machine name."), { code: "STIM_BAD_ARG" });
384
653
  const trimmed = selected.trim();
385
654
  const reserved = trimmed.toLowerCase();
386
655
  return reserved === "auto" || reserved === "local" ? reserved : trimmed;
@@ -403,16 +672,16 @@ function requireConfiguredMachine(selected, machines) {
403
672
  const candidate = parseMachine(entry);
404
673
  return candidate?.name === parsed.name && candidate.port === parsed.port;
405
674
  });
406
- if (!match) throw new OffloadRefusal(selected, `not listed in offload.machines (configured: ${entries.join(", ") || "none"})`);
675
+ if (!match) throw new OffloadRefusal(selected, `not listed in remote.machines (configured: ${entries.join(", ") || "none"})`);
407
676
  return match;
408
677
  }
409
678
  function resolveBuildPlacement(flag) {
410
- const offload = loadConfig$1()?.offload;
679
+ const remote = loadConfig$1()?.remote;
411
680
  let selected = "auto";
412
681
  try {
413
- selected = resolveBuildMachine(flag, process.env.STIM_OFFLOAD_MACHINE, offload?.machine);
414
- selected = requireConfiguredMachine(selected, offload?.machines);
415
- if (namedBuildMachine(selected) && pairedMachines([selected]).length === 0) throw new OffloadRefusal(selected, "no build machine is paired");
682
+ selected = resolveBuildMachine(flag, process.env.STIM_REMOTE_BUILD, remote?.build);
683
+ selected = requireConfiguredMachine(selected, remote?.machines);
684
+ if (namedBuildMachine(selected) && pairedMachines([selected]).length === 0) throw new OffloadRefusal(selected, "no remote Mac is paired");
416
685
  return { selected };
417
686
  } catch (error) {
418
687
  return {
@@ -420,7 +689,7 @@ function resolveBuildPlacement(flag) {
420
689
  failure: {
421
690
  code: error.code,
422
691
  message: error.message,
423
- remedy: error instanceof OffloadRefusal ? error.remedy : "Pass --build-machine auto, local, or an entry from stim settings get offload.machines."
692
+ remedy: error instanceof OffloadRefusal ? error.remedy : "Pass --remote-build auto, local, or an entry from stim settings get remote.machines."
424
693
  }
425
694
  };
426
695
  }
@@ -449,7 +718,7 @@ const CHUNK_BYTES = 61440;
449
718
  const MAX_BUFFERED = 8388608;
450
719
  const DIGEST_BYTES = 32;
451
720
  function offloadMode(env = process.env) {
452
- const raw = env.STIM_OFFLOAD_MODE || loadConfig$1()?.offload?.mode;
721
+ const raw = env.STIM_REMOTE_BUILD_MODE || loadConfig$1()?.remote?.buildMode;
453
722
  return OFFLOAD_MODES.includes(raw) ? raw : "auto";
454
723
  }
455
724
  function buildPlacementCandidates(selected) {
@@ -477,30 +746,30 @@ function placementLoad(choice) {
477
746
  })} there`;
478
747
  }
479
748
  /**
480
- * Whether a build may go to a build machine at all, before any machine is asked. `auto` keeps the build here while
481
- * this Mac has a free `concurrency.maxBuilds` slot and its load per core is under `offload.maxLoadPerCore`.
749
+ * Whether a build may go to a remote Mac at all, before any machine is asked. `auto` keeps the build here while
750
+ * this Mac has a free `concurrency.maxBuilds` slot and its load per core is under `server.maxLoadPerCore`.
482
751
  * A named selection ignores local capacity and mode, and refuses an unsupported build or missing pairing.
483
752
  */
484
753
  function offloadPlacement({ mode, machines, here, unsupported, selected = "auto" }) {
485
754
  if (namedBuildMachine(selected)) {
486
- if (unsupported) throw new OffloadRefusal(selected, `${unsupported}, so a named build machine cannot take it`);
487
- if (machines === 0) throw new OffloadRefusal(selected, "no build machine is paired");
755
+ if (unsupported) throw new OffloadRefusal(selected, `${unsupported}, so a named remote Mac cannot take it`);
756
+ if (machines === 0) throw new OffloadRefusal(selected, "no remote Mac is paired");
488
757
  return {
489
758
  offload: true,
490
- reason: `selected with --build-machine ${selected}`
759
+ reason: `selected with --remote-build ${selected}`
491
760
  };
492
761
  }
493
762
  if (selected === "local") return {
494
763
  offload: false,
495
- reason: "--build-machine local"
764
+ reason: "--remote-build local"
496
765
  };
497
766
  if (mode === "off") return {
498
767
  offload: false,
499
- reason: "offload.mode is off"
768
+ reason: "remote.buildMode is off"
500
769
  };
501
770
  if (machines === 0) return {
502
771
  offload: false,
503
- reason: "no build machine is paired"
772
+ reason: "no remote Mac is paired"
504
773
  };
505
774
  if (unsupported) return {
506
775
  offload: false,
@@ -508,7 +777,7 @@ function offloadPlacement({ mode, machines, here, unsupported, selected = "auto"
508
777
  };
509
778
  if (mode === "force") return {
510
779
  offload: true,
511
- reason: "offload.mode is force"
780
+ reason: "remote.buildMode is force"
512
781
  };
513
782
  const busy = saturation(here);
514
783
  return busy ? {
@@ -796,7 +1065,7 @@ var BuildConnection = class BuildConnection {
796
1065
  function replyError(reply) {
797
1066
  return "error" in reply ? `${reply.error.code}: ${reply.error.message}` : null;
798
1067
  }
799
- /** The repository on the build machine: one area per git common dir, shared by all its worktrees. */
1068
+ /** The repository on the remote Mac: one area per git common dir, shared by all its worktrees. */
800
1069
  function repoIdentity(projectRoot) {
801
1070
  const run = getExecutor().runFile;
802
1071
  const repoRoot = realpathSync(run("git", [
@@ -936,7 +1205,7 @@ async function chooseBuildMachine({ projectRoot, target, mode, here, note, machi
936
1205
  asked.forEach((each, at) => {
937
1206
  if (!order.includes(at) && "connection" in each) each.connection.close();
938
1207
  });
939
- if (order.length === 0) return reasons.length ? reasons.join("; ") : "no build machine is paired";
1208
+ if (order.length === 0) return reasons.length ? reasons.join("; ") : "no remote Mac is paired";
940
1209
  for (const reason of reasons) note(reason);
941
1210
  const [first, ...rest] = order.map((at) => {
942
1211
  const pick = asked[at];
@@ -1240,7 +1509,7 @@ async function offloadBuild({ choice, expectedFingerprint, request, stagingDir,
1240
1509
  ok: true,
1241
1510
  machine,
1242
1511
  artifactPath,
1243
- ...request.platform === "macos" && typeof declared.handoff === "string" && /^[0-9a-f]{64}$/.test(declared.handoff) ? { handoff: {
1512
+ ...typeof declared.handoff === "string" && /^[0-9a-f]{64}$/.test(declared.handoff) ? { handoff: {
1244
1513
  nodeId: choice.credential.nodeId,
1245
1514
  token: declared.handoff,
1246
1515
  sha256: digest
@@ -1365,4 +1634,4 @@ function offloadCheck(projectRoot, targets) {
1365
1634
  };
1366
1635
  }
1367
1636
  //#endregion
1368
- export { readHostPermissions as S, findPeer$1 as _, offloadBuild as a, realIo as b, placementLoad as c, OffloadRefusal as d, namedBuildMachine as f, endpoint as g, inspectBuildMachines as h, closeOffload as i, remotePhaseText as l, resolveBuildPlacement as m, buildPlacementCandidates as n, offloadCheck as o, parseBuildMachineOption as p, chooseBuildMachine as r, offloadPlacement as s, BuildConnection as t, simulatorRuntime as u, parseMachine$1 as v, readAccessTicket as x, pinnedEndpoint$1 as y };
1637
+ export { realIo as S, configuredMachines as _, offloadBuild as a, parseMachine$1 as b, placementLoad as c, OffloadRefusal as d, namedBuildMachine as f, inspectBuildMachines as g, resolveBuildPlacement as h, closeOffload as i, remotePhaseText as l, resolveBuildMachine as m, buildPlacementCandidates as n, offloadCheck as o, parseBuildMachineOption as p, chooseBuildMachine as r, offloadPlacement as s, BuildConnection as t, simulatorRuntime as u, hostingMachines as v, pinnedEndpoint$1 as x, inspectDeviceHostMachines as y };
@@ -1,12 +1,12 @@
1
1
  import { R as deviceSlotKey, W as validateDeviceSlot } from "./config-D0DbpZtM.mjs";
2
2
  import { t as process_identity_exports } from "./process-identity-BmRm1qV0.mjs";
3
3
  import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
- import { x as workspaceLogsDir } from "./workspace-state-B8-aJ1_5.mjs";
4
+ import { x as workspaceLogsDir } from "./workspace-state-DqcCbpE7.mjs";
5
5
  import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
6
6
  import { a as startIosDeviceConsole, i as parseDeviceConsoleLine } from "./ios-device-Ee7sDXfp.mjs";
7
7
  import { n as parseLogStreamLine, r as startIosLogStream, t as appNameFromBundleId } from "./ios-Cr1h5gnO.mjs";
8
- import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-DiA16AsN.mjs";
9
- import { a as watchAppPid, i as waitForAppPid, n as parseLogcatLine, r as startAndroidLogcat, t as androidClockOffset } from "./android-r2rBL8kV.mjs";
8
+ import { a as unregisterCollector, i as registerCollector, r as readCollectors, t as collectorProcessTitle } from "./ownership-DyRQru0q.mjs";
9
+ import { a as waitForAppPid, i as startAndroidLogcat, n as parseLogcatLine, o as watchAppPid, t as androidClockOffset } from "./android-DE4v59Mb.mjs";
10
10
  import { existsSync } from "node:fs";
11
11
  import { isAbsolute, join, resolve } from "node:path";
12
12
  import { LOG_ROTATE_BYTES } from "@stim-cli/core";
@@ -1,6 +1,6 @@
1
1
  import { n as stripAnsi } from "./process-output-Fpl8PYi8.mjs";
2
- import { t as NO_PROJECT_REFUSAL } from "./project-Du91Ilvc.mjs";
3
- import { quotedPath } from "@stim-cli/core";
2
+ import { t as NO_PROJECT_REFUSAL } from "./project-D47Rh0ly.mjs";
3
+ import { quotedPath as quotedPath$1 } from "@stim-cli/core";
4
4
  import chalk from "chalk";
5
5
  //#region src/diagnostics/launch-error-preview.ts
6
6
  function framePriority(frame, root) {
@@ -292,4 +292,4 @@ function stepTimer(now = Date.now) {
292
292
  return () => `(${formatDuration(elapsed())})`;
293
293
  }
294
294
  //#endregion
295
- export { stepTimer as _, formatElapsed as a, launchErrorReport as c, quotedPath as d, refuseNoProject as f, stepClock as g, shortUdid as h, formatDuration as i, phaseLine as l, shortHash as m, appReadinessMessage as n, formatLongDuration as o, releasedLeaseFact as p, clockTime as r, isAppLaunchError as s, SLOW_STEP_MS as t, plural as u, launchErrorPreview as v };
295
+ export { stepTimer as _, formatElapsed as a, launchErrorReport as c, quotedPath$1 as d, refuseNoProject as f, stepClock as g, shortUdid as h, formatDuration as i, phaseLine as l, shortHash as m, appReadinessMessage as n, formatLongDuration as o, releasedLeaseFact as p, clockTime as r, isAppLaunchError as s, SLOW_STEP_MS as t, plural as u, launchErrorPreview as v };
@@ -1,5 +1,5 @@
1
1
  import { d as getConfigDir } from "./config-D0DbpZtM.mjs";
2
- import { w as withDirLock } from "./workspace-state-B8-aJ1_5.mjs";
2
+ import { w as withDirLock } from "./workspace-state-DqcCbpE7.mjs";
3
3
  import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { createdDevicesFile, createdDevicesLock, readCreatedDevices, readCreatedDevices as readCreatedDevices$1 } from "@stim-cli/core/state";
5
5
  //#region src/devices/created-devices.ts