stim 1.17.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 (47) hide show
  1. package/dist/{android--GorydsK.mjs → android-B6rDWrTm.mjs} +15 -15
  2. package/dist/{budget-DM984mnd.mjs → budget-CUDz870h.mjs} +30 -9
  3. package/dist/{build-plan-CmQCoyT-.mjs → build-plan-BJSXzsCL.mjs} +14 -14
  4. package/dist/{idle-B2m-Ovod.mjs → build-progress-D0WkjCPd.mjs} +56 -183
  5. package/dist/{cli-Daxug5-K.mjs → cli-BLQqDGlX.mjs} +13 -13
  6. package/dist/cli.mjs +1 -1
  7. package/dist/{machines-C2XiNwh9.mjs → client-CxNotugx.mjs} +314 -303
  8. package/dist/{deps-DNWaQs4V.mjs → deps-CVxlsRFn.mjs} +1 -1
  9. package/dist/{device-capacity-D0GWHnTM.mjs → device-capacity-ZC4XSZ4R.mjs} +2 -2
  10. package/dist/device-host-worker.mjs +3 -3
  11. package/dist/{device-ios-Bc7vbGwl.mjs → device-ios-C2Um-XUR.mjs} +1 -1
  12. package/dist/{doctor-Cnk9d7Hm.mjs → doctor-BF_435OC.mjs} +14 -13
  13. package/dist/{gc-DxCL2A46.mjs → gc-BsWKa_-d.mjs} +9 -8
  14. package/dist/{gradle-D7-L2Th3.mjs → gradle-bsBRy6i9.mjs} +1 -1
  15. package/dist/{guide-DjrTQGik.mjs → guide-DC3n6-NH.mjs} +134 -110
  16. package/dist/{hosted-android-DwLS4Mse.mjs → hosted-android-DgU31wY3.mjs} +3 -3
  17. package/dist/{hosted-client-wk1W_CNW.mjs → hosted-client-CdSoH-G6.mjs} +4 -4
  18. package/dist/{hosted-ios-aMo7Cljf.mjs → hosted-ios-BTaVj4Jb.mjs} +1 -1
  19. package/dist/{hosted-logs-DqYmWtXc.mjs → hosted-logs-SxfBvSvc.mjs} +2 -2
  20. package/dist/{hosted-macos-dlHXEeF5.mjs → hosted-macos-CT9E3meL.mjs} +2 -2
  21. package/dist/{hosted-native-C9xJ9rpA.mjs → hosted-native-CZLOrMrN.mjs} +3 -3
  22. package/dist/idle-BXG__1BA.mjs +176 -0
  23. package/dist/{idle-shutdown-_3oOV1V_.mjs → idle-shutdown-IGyNV8Cr.mjs} +1 -1
  24. package/dist/{ios-DE6duQoz.mjs → ios-C7JuT1bI.mjs} +18 -18
  25. package/dist/{logs-DUoKlDoS.mjs → logs-DNxKcok9.mjs} +3 -3
  26. package/dist/{macos-32po3kUq.mjs → macos-BEs8cwKx.mjs} +66 -25
  27. package/dist/maintenance-run.mjs +2 -2
  28. package/dist/{metro-gateway-DmslUM30.mjs → metro-gateway-CHqK0p-a.mjs} +1 -1
  29. package/dist/{native-runtime-DhJI3IVQ.mjs → native-runtime-YhaSxP4v.mjs} +1 -1
  30. package/dist/offload-worker.mjs +5 -5
  31. package/dist/{preview-CxPRIEht.mjs → preview-C_JjkEy4.mjs} +1 -1
  32. package/dist/{reload-qZei6iWn.mjs → reload-byOjE3P4.mjs} +2 -2
  33. package/dist/settings.schema.json +84 -66
  34. package/dist/{start-BopZcr4n.mjs → start-BEP-XmEA.mjs} +1 -1
  35. package/dist/{start-uee1wWjY.mjs → start-BHIersSm.mjs} +1 -1
  36. package/dist/{status-dXX2JX1C.mjs → status-CqeWbIWW.mjs} +8 -8
  37. package/dist/{stop-BjizrQwv.mjs → stop-Cj01je8D.mjs} +3 -3
  38. package/dist/{stop-Cr1d8DSE.mjs → stop-D03prQnW.mjs} +1 -1
  39. package/dist/{stop-BCwvvs7F.mjs → stop-DOxwkH4j.mjs} +1 -1
  40. package/dist/supervisor-run.mjs +4 -4
  41. package/dist/{support-BJPgYCu-.mjs → support-BE-tbOP9.mjs} +4 -4
  42. package/dist/{support-F9-sr0Oi.mjs → support-WvD__tSV.mjs} +2 -2
  43. package/dist/{toolchain-CNIBTIOv.mjs → toolchain-CdrxgUeA.mjs} +1 -1
  44. package/dist/{web-exQtGkoc.mjs → web-DddUdJzr.mjs} +2 -2
  45. package/dist/{worktree-ZpZR3S1k.mjs → worktree-AK_m-d_m.mjs} +6 -6
  46. package/dist/{worktree-Dc98cE6_.mjs → worktree-CsAjSmEo.mjs} +1 -1
  47. package/package.json +5 -5
@@ -1,6 +1,6 @@
1
- import { a as call, o as connectHost } from "./hosted-client-wk1W_CNW.mjs";
2
- import { i as requestHostedMetro } from "./metro-gateway-DmslUM30.mjs";
3
- import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-C9xJ9rpA.mjs";
1
+ import { a as call, o as connectHost } from "./hosted-client-CdSoH-G6.mjs";
2
+ import { i as requestHostedMetro } from "./metro-gateway-CHqK0p-a.mjs";
3
+ import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-CZLOrMrN.mjs";
4
4
  //#region src/device-host/hosted-android.ts
5
5
  async function prepareHostedAndroid(machine, selectors, recorded) {
6
6
  return await prepareHostedNative(machine, selectors, recorded, "android");
@@ -1,4 +1,4 @@
1
- import { b as pinnedEndpoint$1, r as BuildConnection, t as configuredMachines } from "./machines-C2XiNwh9.mjs";
1
+ import { _ as configuredMachines, t as BuildConnection, x as pinnedEndpoint$1 } from "./client-CxNotugx.mjs";
2
2
  import { createHash } from "node:crypto";
3
3
  import { lstatSync, readFileSync, readdirSync, readlinkSync } from "node:fs";
4
4
  import { join } from "node:path";
@@ -18,8 +18,8 @@ function credentialRefusal(message, remedy = "Run stim doctor.") {
18
18
  }
19
19
  function hostingCredential(machine) {
20
20
  const configured = configuredMachines();
21
- if (configured === null) throw credentialRefusal("hosting.machines is invalid. Run stim guide settings and correct it.", "Run stim guide settings and correct hosting.machines.");
22
- if (!configured.includes(machine)) throw Object.assign(/* @__PURE__ */ new Error(`${machine} is not in hosting.machines. Add it with stim settings set hosting.machines, then run stim doctor --fix to ask it for hosting access.`), { code: "STIM_BAD_ARG" });
21
+ if (configured === null) throw credentialRefusal("remote.machines is invalid. Run stim guide settings and correct it.", "Run stim guide settings and correct remote.machines.");
22
+ if (!configured.includes(machine)) throw Object.assign(/* @__PURE__ */ new Error(`${machine} is not in remote.machines. Add it with stim settings set remote.machines, then run stim doctor --fix to ask it for hosting access.`), { code: "STIM_BAD_ARG" });
23
23
  let credentials;
24
24
  try {
25
25
  credentials = readDeviceHostMachines();
@@ -34,7 +34,7 @@ function hostingCredential(machine) {
34
34
  }
35
35
  return credential;
36
36
  }
37
- /** Connects only to the pinned node of an approved hosting machine, and only when it grants `device-host`. */
37
+ /** Connects only to the pinned node of an approved remote Mac, and only when it grants `device-host`. */
38
38
  async function connectHost(machine, timeoutMs = CONNECT_TIMEOUT_MS, strict = false) {
39
39
  const credential = hostingCredential(machine);
40
40
  const target = pinnedEndpoint$1(credential);
@@ -1,4 +1,4 @@
1
- import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-C9xJ9rpA.mjs";
1
+ import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-CZLOrMrN.mjs";
2
2
  //#region src/device-host/hosted-ios.ts
3
3
  async function prepareHostedIos(machine, selectors, recorded) {
4
4
  return await prepareHostedNative(machine, selectors, recorded, "ios");
@@ -4,8 +4,8 @@ import { l as phaseLine } from "./command-output-CDAIFD-8.mjs";
4
4
  import { v as workspaceDir, x as workspaceLogsDir$1 } from "./workspace-state-DqcCbpE7.mjs";
5
5
  import { t as macosDir } from "./state-DyaNTgfR.mjs";
6
6
  import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
7
- import { y as parseMachine$1 } from "./machines-C2XiNwh9.mjs";
8
- import { a as call } from "./hosted-client-wk1W_CNW.mjs";
7
+ import { b as parseMachine$1 } from "./client-CxNotugx.mjs";
8
+ import { a as call } from "./hosted-client-CdSoH-G6.mjs";
9
9
  import { mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
10
10
  import { dirname, join } from "node:path";
11
11
  import { LOG_ROTATE_BYTES, withDirLock } from "@stim-cli/core";
@@ -1,7 +1,7 @@
1
1
  import { l as phaseLine } from "./command-output-CDAIFD-8.mjs";
2
2
  import { t as macosDir } from "./state-DyaNTgfR.mjs";
3
- import { a as call, c as hostedSession, d as sha256, f as sleep, i as bundleManifest, m as upload, n as SESSION_TIMEOUT_MS, o as connectHost, p as unknownSession, r as attach, s as heldNoLonger, t as INSTALL_TIMEOUT_MS, u as settle } from "./hosted-client-wk1W_CNW.mjs";
4
- import { i as agentAccess, r as closeAgentConnection, t as pullHostedMacosLogs } from "./hosted-logs-DqYmWtXc.mjs";
3
+ import { a as call, c as hostedSession, d as sha256, f as sleep, i as bundleManifest, m as upload, n as SESSION_TIMEOUT_MS, o as connectHost, p as unknownSession, r as attach, s as heldNoLonger, t as INSTALL_TIMEOUT_MS, u as settle } from "./hosted-client-CdSoH-G6.mjs";
4
+ import { i as agentAccess, r as closeAgentConnection, t as pullHostedMacosLogs } from "./hosted-logs-SxfBvSvc.mjs";
5
5
  import { randomUUID } from "node:crypto";
6
6
  import { rmSync } from "node:fs";
7
7
  import { join } from "node:path";
@@ -1,7 +1,7 @@
1
1
  import { r as readWorkspaceState$1, v as workspaceDir } from "./workspace-state-DqcCbpE7.mjs";
2
- import { a as call, c as hostedSession, d as sha256, f as sleep, i as bundleManifest, m as upload, n as SESSION_TIMEOUT_MS, o as connectHost, p as unknownSession, r as attach, s as heldNoLonger, t as INSTALL_TIMEOUT_MS, u as settle } from "./hosted-client-wk1W_CNW.mjs";
3
- import { a as requireHostedMetro, i as requestHostedMetro, n as closeHostedMetro } from "./metro-gateway-DmslUM30.mjs";
4
- import { i as agentAccess, n as pullHostedNativeLogs, r as closeAgentConnection } from "./hosted-logs-DqYmWtXc.mjs";
2
+ import { a as call, c as hostedSession, d as sha256, f as sleep, i as bundleManifest, m as upload, n as SESSION_TIMEOUT_MS, o as connectHost, p as unknownSession, r as attach, s as heldNoLonger, t as INSTALL_TIMEOUT_MS, u as settle } from "./hosted-client-CdSoH-G6.mjs";
3
+ import { a as requireHostedMetro, i as requestHostedMetro, n as closeHostedMetro } from "./metro-gateway-CHqK0p-a.mjs";
4
+ import { i as agentAccess, n as pullHostedNativeLogs, r as closeAgentConnection } from "./hosted-logs-SxfBvSvc.mjs";
5
5
  import { s as writeHostedNative } from "./ios-state-8L3lgum6.mjs";
6
6
  import { randomUUID } from "node:crypto";
7
7
  import { readFileSync, rmSync } from "node:fs";
@@ -0,0 +1,176 @@
1
+ import { H as projectDeviceSlots } from "./config-D0DbpZtM.mjs";
2
+ import { o as formatLongDuration } from "./command-output-CDAIFD-8.mjs";
3
+ import { r as readWorkspaceState } from "./workspace-state-DqcCbpE7.mjs";
4
+ import { i as recordGcResult } from "./in-use-CvGOUn-x.mjs";
5
+ import { o as idleForMs, r as createActivityReader } from "./activity-IRvJY_ru.mjs";
6
+ import { z as ownedAvdSerialResolver } from "./android-B_YNZy61.mjs";
7
+ import { g as teardownOwnedIosSim, m as teardownOwnedAvd } from "./ownership-BMLqyBgJ.mjs";
8
+ import { r as activeBuildState, s as parseActiveBuild, t as ACTIVE_BUILD_KEY } from "./build-progress-D0WkjCPd.mjs";
9
+ import chalk from "chalk";
10
+ //#region src/commands/gc/idle.ts
11
+ function findOwnedDeviceActivity({ config, sims, androidSerial, readActivity, deadProjects = [] }) {
12
+ const booted = new Map(sims.filter((sim) => sim.state === "Booted").map((sim) => [sim.udid, sim.name]));
13
+ const dead = new Set(deadProjects);
14
+ const found = [];
15
+ for (const [project, record] of Object.entries(config?.projects ?? {})) {
16
+ if (dead.has(project)) continue;
17
+ for (const { slot, platforms } of projectDeviceSlots(record)) {
18
+ const ios = platforms.ios;
19
+ if (ios?.owned && ios.deviceUdid && booted.has(ios.deviceUdid)) found.push({
20
+ kind: "ios",
21
+ id: ios.deviceUdid,
22
+ name: booted.get(ios.deviceUdid) ?? ios.deviceUdid,
23
+ project,
24
+ slot,
25
+ activity: readActivity({
26
+ platform: "ios",
27
+ id: ios.deviceUdid,
28
+ slot,
29
+ workspace: project
30
+ })
31
+ });
32
+ const android = platforms.android;
33
+ const serial = android?.owned && android.avdName ? androidSerial(android.avdName) : null;
34
+ if (android?.avdName && serial) found.push({
35
+ kind: "android",
36
+ id: android.avdName,
37
+ name: android.avdName,
38
+ project,
39
+ slot,
40
+ activity: readActivity({
41
+ platform: "android",
42
+ id: serial,
43
+ slot,
44
+ workspace: project
45
+ })
46
+ });
47
+ }
48
+ }
49
+ return found;
50
+ }
51
+ function findIdleDevices({ buildInProgress, now, ...inputs }) {
52
+ return findOwnedDeviceActivity(inputs).filter((device) => device.activity.state === "idle").map(({ kind, id, name, project, slot, activity }) => ({
53
+ kind,
54
+ id,
55
+ name,
56
+ project,
57
+ slot,
58
+ lastActivityAt: activity.lastActivityAt ?? null,
59
+ idleForMs: idleForMs(activity, now),
60
+ buildInProgress: buildInProgress(project)
61
+ }));
62
+ }
63
+ function idleShutdownCandidates(devices, idleMs) {
64
+ return devices.filter((d) => !d.buildInProgress && d.idleForMs !== null && d.idleForMs >= idleMs);
65
+ }
66
+ function parseIdleDuration(value) {
67
+ const match = /^([1-9][0-9]*)(m|h|d)$/.exec(value.trim());
68
+ if (!match) return null;
69
+ const unit = {
70
+ m: 6e4,
71
+ h: 36e5,
72
+ d: 864e5
73
+ }[match[2]];
74
+ return Number(match[1]) * unit;
75
+ }
76
+ function workspaceBuildInProgress(project) {
77
+ const record = parseActiveBuild(readWorkspaceState(project)?.[ACTIVE_BUILD_KEY]);
78
+ if (!record) return false;
79
+ try {
80
+ return activeBuildState(record.claim) !== "stale";
81
+ } catch {
82
+ return true;
83
+ }
84
+ }
85
+ function deviceActivityInputs(config, sims, now) {
86
+ const resolve = ownedAvdSerialResolver({ timeoutMs: 5e3 });
87
+ return {
88
+ config,
89
+ sims,
90
+ readActivity: createActivityReader({ now }),
91
+ androidSerial: (avdName) => {
92
+ try {
93
+ return resolve(avdName).serial ?? null;
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
98
+ };
99
+ }
100
+ function collectOwnedDeviceActivity(config, sims, now = Date.now()) {
101
+ return findOwnedDeviceActivity(deviceActivityInputs(config, sims, now));
102
+ }
103
+ function collectIdleDevices(config, sims, deadProjects, now = Date.now()) {
104
+ return findIdleDevices({
105
+ ...deviceActivityInputs(config, sims, now),
106
+ deadProjects,
107
+ now,
108
+ buildInProgress: workspaceBuildInProgress
109
+ });
110
+ }
111
+ function idleDeviceLines(devices) {
112
+ if (devices.length === 0) return [];
113
+ return [`Idle owned devices (${devices.length}) - booted with no driver, claim, or recent activity:`, ...devices.map((d) => {
114
+ const slot = d.slot === "default" ? "" : ` [${d.slot}]`;
115
+ const idle = d.idleForMs === null ? "idle for an unknown time" : `idle ${formatLongDuration(d.idleForMs)}`;
116
+ const build = d.buildInProgress ? ", build in progress" : "";
117
+ return ` ${d.kind}${slot} ${d.name} (${d.project}) -- ${idle}${build}`;
118
+ })];
119
+ }
120
+ function shutDownIdleDevices(devices, idleMs, recollect) {
121
+ const candidates = idleShutdownCandidates(devices, idleMs);
122
+ const shutDown = [];
123
+ if (candidates.length === 0) {
124
+ console.log(chalk.dim(`No owned device has been idle for ${formatLongDuration(idleMs)} or more.`));
125
+ return {
126
+ failures: 0,
127
+ shutDown
128
+ };
129
+ }
130
+ const fresh = idleShutdownCandidates(recollect(), idleMs);
131
+ let failures = 0;
132
+ for (const device of candidates) {
133
+ const what = `${device.kind} ${device.name}`;
134
+ const current = fresh.find((d) => d.kind === device.kind && d.id === device.id && d.project === device.project && d.slot === device.slot);
135
+ if (!current) {
136
+ console.log(chalk.dim(`Kept ${what}: it is no longer idle for ${formatLongDuration(idleMs)}.`));
137
+ recordGcResult("idleDevice", "kept", device.name, {
138
+ id: device.id,
139
+ detail: `it is no longer idle for ${formatLongDuration(idleMs)}`
140
+ });
141
+ continue;
142
+ }
143
+ const outcome = device.kind === "ios" ? teardownOwnedIosSim(device.id, { label: device.name }) : teardownOwnedAvd(device.id, { owner: {
144
+ projectPath: device.project,
145
+ slot: device.slot
146
+ } });
147
+ if (outcome.status === "torn-down") {
148
+ shutDown.push(device);
149
+ console.log(chalk.green(`Shut down ${what}, idle ${formatLongDuration(current.idleForMs)}`));
150
+ recordGcResult("idleDevice", "done", device.name, {
151
+ id: device.id,
152
+ detail: `idle ${formatLongDuration(current.idleForMs)}`
153
+ });
154
+ } else if (outcome.status === "missing") console.log(chalk.dim(`${what} is already gone; nothing to shut down.`));
155
+ else if (outcome.status === "skipped") {
156
+ console.log(chalk.yellow(`Skipped ${what}: ${outcome.reason}`));
157
+ recordGcResult("idleDevice", "kept", device.name, {
158
+ id: device.id,
159
+ detail: outcome.reason
160
+ });
161
+ } else {
162
+ failures++;
163
+ console.log(chalk.red(`Failed to shut down ${what}: ${outcome.reason}`));
164
+ recordGcResult("idleDevice", "failed", device.name, {
165
+ id: device.id,
166
+ detail: outcome.reason
167
+ });
168
+ }
169
+ }
170
+ return {
171
+ failures,
172
+ shutDown
173
+ };
174
+ }
175
+ //#endregion
176
+ export { parseIdleDuration as a, idleShutdownCandidates as i, collectOwnedDeviceActivity as n, shutDownIdleDevices as o, idleDeviceLines as r, workspaceBuildInProgress as s, collectIdleDevices as t };
@@ -5,7 +5,7 @@ import { o as canonicalPath } from "./in-use-CvGOUn-x.mjs";
5
5
  import { m as workspaceDeviceLastUseAt } from "./activity-IRvJY_ru.mjs";
6
6
  import { u as listAllIosSims } from "./ios-DSfnPfse.mjs";
7
7
  import { g as teardownOwnedIosSim, m as teardownOwnedAvd } from "./ownership-BMLqyBgJ.mjs";
8
- import { n as collectOwnedDeviceActivity, s as workspaceBuildInProgress } from "./idle-B2m-Ovod.mjs";
8
+ import { n as collectOwnedDeviceActivity, s as workspaceBuildInProgress } from "./idle-BXG__1BA.mjs";
9
9
  import { DEVICE_IDLE_SHUTDOWN_KEY, DEVICE_RECLAIM_REASON, readDeviceIdleShutdowns } from "@stim-cli/core/state";
10
10
  //#region src/devices/idle-shutdown.ts
11
11
  const SIM_LIST_TIMEOUT_MS = 1e4;
@@ -6,42 +6,42 @@ import { B as settingsLayers, C as metroWarmupUrlSetting, G as detectProviders,
6
6
  import { n as appProjectProblem, r as detectIsExpo, s as findProjectRoot$1, t as NO_PROJECT_REFUSAL } from "./project-D47Rh0ly.mjs";
7
7
  import { l as resolveProjectMetro, o as pidExists, u as signalProcessTree } from "./metro-g8NqiJp-.mjs";
8
8
  import { c as writeWorkspaceState, g as workspaceAgentDeviceDir, i as recordWorkspaceUse, r as readWorkspaceState$1, v as workspaceDir, x as workspaceLogsDir$1 } from "./workspace-state-DqcCbpE7.mjs";
9
- import { t as budgetGate } from "./budget-DM984mnd.mjs";
9
+ import { t as budgetGate } from "./budget-CUDz870h.mjs";
10
10
  import { A as providerDownloadPath, D as fingerprintProject, E as fingerprintDiffRecord, L as untrackedMissLine, M as refingerprintAfterMutation, N as resolveBuild, O as inputsChangedDuringBuild, P as storeBuild, R as untrackedNativeFiles, S as configInputsChanged, T as filesystemBuildCapability, _ as waitForBuild, b as buildCacheKey, g as releaseBuildLock, j as providerUploadOutcome, k as prepareProviderDownloadDir, m as acquireBuildLock, v as waitForSharedBuild, x as changedDuringBuildLine } from "./device-lease-DpoS36_u.mjs";
11
11
  import { r as releaseBuildSlot, t as acquireBuildSlot } from "./build-slots-41v_d2x9.mjs";
12
12
  import { m as writeWorkspaceLaunch, n as MODE_EXPO, t as MODE_BARE } from "./state-BKa8wNN5.mjs";
13
13
  import { ft as parkedMaxSetting, ot as POOL_SETTING_REMEDY } from "./android-B_YNZy61.mjs";
14
14
  import { p as listIosRuntimes, r as clearIosAppData, u as listAllIosSims } from "./ios-DSfnPfse.mjs";
15
15
  import { a as workspaceLinks, i as workspaceLinkLine } from "./stim-desktop-Cnz8CPnl.mjs";
16
- import { C as recordRunStats, _ as tapBuildLog, g as startBuildProgress, h as recordFinishedBuild, l as NO_BUILD_PROGRESS, v as createRunRecorder, w as statsProjectKey$1, x as recordCapacityRefusal, y as readRunEstimates } from "./idle-B2m-Ovod.mjs";
16
+ import { _ as statsProjectKey$1, c as recordFinishedBuild, d as createRunRecorder, f as readRunEstimates, g as recordRunStats, l as startBuildProgress, m as recordCapacityRefusal, n as NO_BUILD_PROGRESS, u as tapBuildLog } from "./build-progress-D0WkjCPd.mjs";
17
17
  import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
18
- import { S as bundlerPin, _ as readBundleId, c as COMPILATION_CACHE_NOT_RUN, d as buildIos, g as readBundleExecutable, h as discoverXcodeProject, p as compilationCacheActivityLine, r as iosToolchain, v as resolveScheme } from "./toolchain-CNIBTIOv.mjs";
19
- import { _ as resolveBuildPlacement, a as chooseBuildMachine, d as remotePhaseText, f as simulatorRuntime, h as parseBuildMachineOption, i as buildPlacementCandidates, l as offloadPlacement, m as namedBuildMachine, o as closeOffload, p as OffloadRefusal, s as offloadBuild, u as placementLoad } from "./machines-C2XiNwh9.mjs";
20
- import { r as hostedMetroSettings } from "./metro-gateway-DmslUM30.mjs";
18
+ import { S as bundlerPin, _ as readBundleId, c as COMPILATION_CACHE_NOT_RUN, d as buildIos, g as readBundleExecutable, h as discoverXcodeProject, p as compilationCacheActivityLine, r as iosToolchain, v as resolveScheme } from "./toolchain-CdrxgUeA.mjs";
19
+ import { a as offloadBuild, c as placementLoad, d as OffloadRefusal, f as namedBuildMachine, h as resolveBuildPlacement, i as closeOffload, l as remotePhaseText, n as buildPlacementCandidates, p as parseBuildMachineOption, r as chooseBuildMachine, s as offloadPlacement, u as simulatorRuntime } from "./client-CxNotugx.mjs";
20
+ import { r as hostedMetroSettings } from "./metro-gateway-CHqK0p-a.mjs";
21
21
  import { n as verifyCollectorOwnership } from "./ownership-DyRQru0q.mjs";
22
- import { r as checkDeviceCapacity } from "./device-capacity-D0GWHnTM.mjs";
22
+ import { r as checkDeviceCapacity } from "./device-capacity-ZC4XSZ4R.mjs";
23
23
  import { D as schemesFromInfoPlist, S as restartedAppNote, T as pickDevClientScheme, _ as installIosApp, a as IOS_DEV_MENU_OFF_DEFAULTS_PLIST, d as devClientUrl, l as clearOtherUserApps, r as DEFAULT_METRO_PORT, v as iosAppProcess, x as launchIosApp } from "./app-install-VPkI5WEg.mjs";
24
24
  import { n as devClientTakesDevMenuParams, t as devClientScheme } from "./dev-client-B-XC4uRH.mjs";
25
25
  import { t as spawnEntry } from "./spawn-entry-jw19m8Nl.mjs";
26
- import { a as runPodInstall, n as podsAreStale, r as readPodState } from "./deps-DNWaQs4V.mjs";
26
+ import { a as runPodInstall, n as podsAreStale, r as readPodState } from "./deps-CVxlsRFn.mjs";
27
27
  import { i as staleNativeDirRefusal, n as recordPrebuild, r as runPrebuild, t as planPrebuild } from "./prebuild-D7RUMkwN.mjs";
28
28
  import { c as readMetroRecords, f as verifyLaunch, i as RELEASE_VERIFY_WAIT_MS, l as unattributedLaunchLines, n as LAUNCH_FATAL, o as isBundleProof, p as verifyReleaseLaunch, r as LAUNCH_UNVERIFIED, s as readCollectorRecords, t as LAUNCH_BUNDLING, u as unverifiedLaunchLines } from "./launch-verify-lTnWZikR.mjs";
29
29
  import { a as acquireRunLease, c as lostRefusal, d as runLease, f as waitFlagConflict, o as leaseExpiryText, s as lostLine, t as DEBUG_VERIFY_STEP_MS, u as releaseLeaseOnSignal } from "./device-lease-run-B8YltIH_.mjs";
30
- import { n as clearIosAdoptionPending } from "./device-ios-Bc7vbGwl.mjs";
31
- import { _ as resolveSimulatorAppFlag, a as deviceModelRefusal, c as iosProviderRunOptions, d as podAction, f as printDiagnostics, g as resolveRuntime, h as resolveIosWait, i as deviceLabel, l as isReleaseConfiguration, m as resolveDeviceType, n as buildLogFile, o as deviceShortName, p as resolveConfiguration, r as createIosDeviceWaitRun, s as iosConfigurationSetting, t as appNameFromPath, u as ownedSimFailure, v as simulatorBuildArch, y as xcodeFailureReport } from "./support-BJPgYCu-.mjs";
30
+ import { n as clearIosAdoptionPending } from "./device-ios-C2Um-XUR.mjs";
31
+ import { _ as resolveSimulatorAppFlag, a as deviceModelRefusal, c as iosProviderRunOptions, d as podAction, f as printDiagnostics, g as resolveRuntime, h as resolveIosWait, i as deviceLabel, l as isReleaseConfiguration, m as resolveDeviceType, n as buildLogFile, o as deviceShortName, p as resolveConfiguration, r as createIosDeviceWaitRun, s as iosConfigurationSetting, t as appNameFromPath, u as ownedSimFailure, v as simulatorBuildArch, y as xcodeFailureReport } from "./support-BE-tbOP9.mjs";
32
32
  import { i as writeDevicePlacement, n as readHostedIos, o as writeHostedIos } from "./ios-state-8L3lgum6.mjs";
33
- import { a as refusePlan, b as devicePlacementLine, c as skippedMissReason, f as swapJsBundle, h as ensureOwnedDevice, i as printPlan, m as ensureBooted, n as planFlagRefusal, o as explainBuildMiss, p as didSetUpDevice, r as planPayload, s as fingerprintErrorMissReason, t as planCachedBuild, v as warmMetro, y as automaticDevicePlacement } from "./build-plan-CmQCoyT-.mjs";
33
+ import { a as refusePlan, b as devicePlacementLine, c as skippedMissReason, f as swapJsBundle, h as ensureOwnedDevice, i as printPlan, m as ensureBooted, n as planFlagRefusal, o as explainBuildMiss, p as didSetUpDevice, r as planPayload, s as fingerprintErrorMissReason, t as planCachedBuild, v as warmMetro, y as automaticDevicePlacement } from "./build-plan-BJSXzsCL.mjs";
34
34
  import { n as nativeRunCommand, r as siblingPlatformSlots, t as launchSlotScope } from "./slot-launch-DmjBmpQV.mjs";
35
35
  import { a as easAuthNote, c as loadProjectProvider, f as resolveEasCliBin, i as checkEasAuth, m as uploadRemote, n as UPLOAD_TIMEOUT_MS, o as exitAfterFlush, p as resolveRemote, r as cacheLevel, s as isEasAuthFailureText, t as RESOLVE_TIMEOUT_MS } from "./remote-cache-Ci4DQYYj.mjs";
36
36
  import { O as readRemoteSimulatorArch, a as ensureMetroReachable, k as gateMetroOrigin, l as remoteIosDeps, n as binOnPath, o as ensureRemoteBootOwned, r as bundleEntryPoint, u as resolveRemoteContext, w as ownedSessionName } from "./device-remote-hFSkpfQu.mjs";
37
37
  import { d as runCancellationSignal, f as withNativeBuildRun, r as cancelledFailure, u as runCancellation } from "./native-run-D1Q56rAD.mjs";
38
38
  import { a as isEasBuildFailure, i as easDeviceBuildRemedy, o as planEasDevelopmentBuild, s as resolveEasDevelopmentBuild } from "./simslim-BWNrc3M3.mjs";
39
- import { c as startDevServer, h as detectBundleId } from "./start-uee1wWjY.mjs";
40
- import { a as sleep, i as launchOutcomeRecord, n as ensureWorkspaceStorageSafely, r as isPhysicalDeviceRequest, t as ensureDevServer } from "./native-runtime-DhJI3IVQ.mjs";
39
+ import { c as startDevServer, h as detectBundleId } from "./start-BHIersSm.mjs";
40
+ import { a as sleep, i as launchOutcomeRecord, n as ensureWorkspaceStorageSafely, r as isPhysicalDeviceRequest, t as ensureDevServer } from "./native-runtime-YhaSxP4v.mjs";
41
41
  import { t as selectFromPool } from "./device-pool-3o7s5lo4.mjs";
42
42
  import { a as printNativeCrashReport, n as IOS_CRASH_REPORT_RETRY, o as simulatorConsolePaths, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-C-NMnhrk.mjs";
43
43
  import { a as iosPoolCandidates, c as isWirelessIosDevice, f as resolveIosPhysicalDevice, i as iosDeviceProcess, l as listIosDevices, n as installIosDeviceApp, o as iosPoolNoCandidatesRefusal, p as verifyIosDeviceReleaseLaunch, r as iosDeviceBounds, t as awaitIosDeviceLaunch, u as localNetworkPending } from "./ios-device-pAN4t54-.mjs";
44
- import { n as prepareHostedIos, t as placeHostedIos } from "./hosted-ios-aMo7Cljf.mjs";
44
+ import { n as prepareHostedIos, t as placeHostedIos } from "./hosted-ios-BTaVj4Jb.mjs";
45
45
  import { X509Certificate } from "node:crypto";
46
46
  import { existsSync, mkdirSync, mkdtempSync, openSync, rmSync, writeFileSync } from "node:fs";
47
47
  import { basename, join } from "node:path";
@@ -382,7 +382,7 @@ async function acquireIosArtifact({ root, logFile, udid, remoteDestination, host
382
382
  let handoff = null;
383
383
  let offloadFallback = null;
384
384
  let fallbackMachine = null;
385
- let hereReason = "no build machine is paired";
385
+ let hereReason = "no remote Mac is paired";
386
386
  let slotWaitMs;
387
387
  let builtOn;
388
388
  const fallBack = (reason, line = reason) => {
@@ -1323,7 +1323,7 @@ async function selectIosPlacement(args) {
1323
1323
  slot,
1324
1324
  platform: "ios",
1325
1325
  selectors: hostedIosSelectors(deviceType, runtime),
1326
- buildMachine: opts.buildMachine,
1326
+ buildMachine: opts.remoteBuild,
1327
1327
  noWait
1328
1328
  });
1329
1329
  phase("placement:", devicePlacementLine(placed.placement, placed.skipped));
@@ -3002,9 +3002,9 @@ function iosCommand(program) {
3002
3002
  registerIos(program);
3003
3003
  }
3004
3004
  function registerIos(program, deps = {}) {
3005
- program.command("ios").description("Build (or restore from the fingerprint cache), install and launch this workspace's app on its owned simulator, wired to the reserved Metro port. A Debug run starts the dev server when it is not running.").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", parseDeviceSlotOption).option("--build-machine <value>", "Build on auto, local, or one named machine; a name refuses without fallback", parseBuildMachineOption).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--plan", "Predict the next build without building, booting or installing: resolve the fingerprint, check the local then remote cache, and print the expected cache result and duration. Writes no Stim state.").option("--scheme <name>", "Shared Xcode app scheme to build; overrides automatic scheme selection, not the app URL scheme").option("--no-metro-check", "Skip the \"is this workspace's dev server running?\" check: do not start it, and build anyway").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--configuration <name>", "Xcode configuration to build (e.g. Release). A non-Debug configuration embeds the JS bundle and skips Metro entirely. Overrides the ios.configuration setting. Default: Debug").option("--device-type <name>", "Simulator model to create this workspace's owned sim as, exactly as `xcrun simctl list devicetypes` names it (e.g. \"iPad Pro 13-inch (M5)\"). Overrides the ios.deviceType setting for this invocation. A model no installed runtime can create refuses with STIM_BAD_ARG and prints the models they do offer.").option("--runtime <version>", "Simulator runtime to create this workspace's owned sim on, as a version (\"18.5\") or a runtime's full name (\"iOS 18.5\"); nothing else matches. Overrides the ios.runtime setting for this invocation. An unknown version refuses with STIM_BAD_ARG and prints the installed runtimes.").option("--simulator-app <app>", "Open the owned simulator in xcode, siniulator, or stim-desktop for this run, overriding the machine iosSimulatorApp setting. Also opens an already running simulator; local simulators only.").option("--device [udid]", "Build the iphoneos slice for a connected iPhone, install it, and launch it, instead of using this workspace's owned simulator. The phone can be cabled or paired over Wi-Fi. With no UDID, the first cabled device this workspace can lease is used, waiting for one that is busy; a Wi-Fi device is used only when no cabled one is connected and ready. In Debug the app is wired to this workspace's Metro over the LAN. Stim never creates, boots, or deletes a physical device.").option("--remote <target>", "Run on eas, proxy, or an approved Mac in hosting.machines; named Macs never fall back locally. auto places on an approved Mac when this Mac is full or busy.", (value) => {
3005
+ program.command("ios").description("Build (or restore from the fingerprint cache), install and launch this workspace's app on its owned simulator, wired to the reserved Metro port. A Debug run starts the dev server when it is not running.").option("--eas-profile <name>", "Download a matching EAS development build; on a miss, print the build command without running it").option("--slot <name>", "Reusable device slot within this workspace (default: default)", parseDeviceSlotOption).option("--remote-build <value>", "Build on auto, local, or one named machine; a name refuses without fallback", parseBuildMachineOption).option("--json", "Emit the facts as a single JSON line on stdout; every other line goes to stderr").option("--plan", "Predict the next build without building, booting or installing: resolve the fingerprint, check the local then remote cache, and print the expected cache result and duration. Writes no Stim state.").option("--scheme <name>", "Shared Xcode app scheme to build; overrides automatic scheme selection, not the app URL scheme").option("--no-metro-check", "Skip the \"is this workspace's dev server running?\" check: do not start it, and build anyway").option("--no-build-cache", "Build fresh, ignoring cached artifacts (local and the project's build-cache provider); the fresh build still replaces the cache entry").option("--configuration <name>", "Xcode configuration to build (e.g. Release). A non-Debug configuration embeds the JS bundle and skips Metro entirely. Overrides the ios.configuration setting. Default: Debug").option("--device-type <name>", "Simulator model to create this workspace's owned sim as, exactly as `xcrun simctl list devicetypes` names it (e.g. \"iPad Pro 13-inch (M5)\"). Overrides the ios.deviceType setting for this invocation. A model no installed runtime can create refuses with STIM_BAD_ARG and prints the models they do offer.").option("--runtime <version>", "Simulator runtime to create this workspace's owned sim on, as a version (\"18.5\") or a runtime's full name (\"iOS 18.5\"); nothing else matches. Overrides the ios.runtime setting for this invocation. An unknown version refuses with STIM_BAD_ARG and prints the installed runtimes.").option("--simulator-app <app>", "Open the owned simulator in xcode, siniulator, or stim-desktop for this run, overriding the machine iosSimulatorApp setting. Also opens an already running simulator; local simulators only.").option("--device [udid]", "Build the iphoneos slice for a connected iPhone, install it, and launch it, instead of using this workspace's owned simulator. The phone can be cabled or paired over Wi-Fi. With no UDID, the first cabled device this workspace can lease is used, waiting for one that is busy; a Wi-Fi device is used only when no cabled one is connected and ready. In Debug the app is wired to this workspace's Metro over the LAN. Stim never creates, boots, or deletes a physical device.").option("--remote <target>", "Run on eas, proxy, or an approved Mac in remote.machines; named Macs never fall back locally. auto places on an approved Mac when this Mac is full or busy.", (value) => {
3006
3006
  if (parseMachine(value)) return value.trim();
3007
- throw new InvalidArgumentError("expected eas, proxy, auto, or a hosting Mac name");
3007
+ throw new InvalidArgumentError("expected eas, proxy, auto, or a remote Mac name");
3008
3008
  }).option("--wait <seconds>", "How long to wait for another workspace to release the phone it leases, before refusing with STIM_DEVICE_BUSY (default 60, 0 refuses at once). Without --device, wait for an owned-device slot (default 600 seconds; --no-wait refuses immediately).").option("--no-wait", "Install on a phone another workspace leases instead of waiting: this run takes no lease and, when both workspaces build the same app id, the install terminates the holder's running app. Without --device, refuse a full device cap or existing slot queue immediately.").action(async (opts) => {
3009
3009
  if (opts.plan) {
3010
3010
  const d = {
@@ -3291,7 +3291,7 @@ async function runIos(opts = {}, overrides = {}, progress = NO_BUILD_PROGRESS) {
3291
3291
  lines: moreShapeErrors,
3292
3292
  remedy: SETTING_SHAPE_REMEDY
3293
3293
  });
3294
- const setup = resolveIosBuildSetup(opts.buildMachine, settings);
3294
+ const setup = resolveIosBuildSetup(opts.remoteBuild, settings);
3295
3295
  if (!setup.ok) return fail(setup.failure);
3296
3296
  buildMachine = setup.buildMachine;
3297
3297
  const { optimizations } = setup;
@@ -5,9 +5,9 @@ import { o as findCommandWorkspace } from "./project-D47Rh0ly.mjs";
5
5
  import { r as readWorkspaceState$1, x as workspaceLogsDir$1 } from "./workspace-state-DqcCbpE7.mjs";
6
6
  import { n as agentDeviceLiveness, u as readAgentDeviceRecords } from "./activity-IRvJY_ru.mjs";
7
7
  import { n as SOURCES, t as LEVELS } from "./ndjson-PclOIwVY.mjs";
8
- import { o as connectHost } from "./hosted-client-wk1W_CNW.mjs";
9
- import { n as pullHostedNativeLogs, t as pullHostedMacosLogs } from "./hosted-logs-DqYmWtXc.mjs";
10
- import "./hosted-macos-dlHXEeF5.mjs";
8
+ import { o as connectHost } from "./hosted-client-CdSoH-G6.mjs";
9
+ import { n as pullHostedNativeLogs, t as pullHostedMacosLogs } from "./hosted-logs-SxfBvSvc.mjs";
10
+ import "./hosted-macos-CT9E3meL.mjs";
11
11
  import { n as readHostedIos, t as readHostedAndroid } from "./ios-state-8L3lgum6.mjs";
12
12
  import { i as captureWorkspaceCrashes, t as errorDiagnostics } from "./error-diagnostics-C-NMnhrk.mjs";
13
13
  import { t as watchStdoutReader } from "./stdout-reader-C8yjre1x.mjs";
@@ -8,14 +8,15 @@ import { c as writeWorkspaceState, g as workspaceAgentDeviceDir, i as recordWork
8
8
  import { a as spawnDeclared } from "./spawn-claims-D0XfSe8u.mjs";
9
9
  import { r as releaseBuildSlot, t as acquireBuildSlot } from "./build-slots-41v_d2x9.mjs";
10
10
  import { t as withWorkspaceProcessLock } from "./workspace-process-lock-2mNzOlaB.mjs";
11
+ import { c as recordFinishedBuild, l as startBuildProgress, n as NO_BUILD_PROGRESS, u as tapBuildLog } from "./build-progress-D0WkjCPd.mjs";
11
12
  import { a as requiredMacosRecord, n as macosLogFile, r as macosProcess, t as macosDir } from "./state-DyaNTgfR.mjs";
12
13
  import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
13
- import { i as macosToolchain } from "./toolchain-CNIBTIOv.mjs";
14
- import { _ as resolveBuildPlacement, a as chooseBuildMachine, d as remotePhaseText, h as parseBuildMachineOption, i as buildPlacementCandidates, l as offloadPlacement, m as namedBuildMachine, o as closeOffload, p as OffloadRefusal, s as offloadBuild, u as placementLoad } from "./machines-C2XiNwh9.mjs";
15
- import { o as connectHost } from "./hosted-client-wk1W_CNW.mjs";
14
+ import { i as macosToolchain } from "./toolchain-CdrxgUeA.mjs";
15
+ import { a as offloadBuild, c as placementLoad, d as OffloadRefusal, f as namedBuildMachine, h as resolveBuildPlacement, i as closeOffload, l as remotePhaseText, n as buildPlacementCandidates, p as parseBuildMachineOption, r as chooseBuildMachine, s as offloadPlacement } from "./client-CxNotugx.mjs";
16
+ import { o as connectHost } from "./hosted-client-CdSoH-G6.mjs";
16
17
  import { t as logLines } from "./run-CkE9y0nc.mjs";
17
- import { t as placeHostedMacos } from "./hosted-macos-dlHXEeF5.mjs";
18
- import { n as stopMacosAppHeld } from "./stop-Cr1d8DSE.mjs";
18
+ import { t as placeHostedMacos } from "./hosted-macos-CT9E3meL.mjs";
19
+ import { n as stopMacosAppHeld } from "./stop-D03prQnW.mjs";
19
20
  import { t as spawnEntry } from "./spawn-entry-jw19m8Nl.mjs";
20
21
  import { n as stageBundle, r as validateInfoPlist, t as resolveBundleExtras } from "./stage-CzaiwFsI.mjs";
21
22
  import { f as withNativeBuildRun } from "./native-run-D1Q56rAD.mjs";
@@ -56,7 +57,7 @@ async function tool(root, args, writer, note, capture = false) {
56
57
  });
57
58
  return stdout.trim();
58
59
  }
59
- async function buildMacosBundle({ root, product, infoPlist, bundle, bundleId, scratch, writer, note, record, buildMachine, resources, assetCatalog }) {
60
+ async function buildMacosBundle({ root, product, infoPlist, bundle, bundleId, scratch, writer, note, record, buildMachine, resources, assetCatalog, progress = NO_BUILD_PROGRESS }) {
60
61
  if (record) record.buildMachine = buildMachine;
61
62
  validateInfoPlist(root, product, infoPlist);
62
63
  const repository = realpathSync(repoRoot(root) ?? root);
@@ -145,6 +146,11 @@ async function buildMacosBundle({ root, product, infoPlist, bundle, bundleId, sc
145
146
  "prebuild",
146
147
  "pods"
147
148
  ].includes(phase)) record.builtOn = choice.machine;
149
+ progress.place({
150
+ host: choice.machine,
151
+ phase
152
+ });
153
+ progress.step(phase === "fetch" ? "install" : "compile");
148
154
  },
149
155
  onRecord: (entry) => writer.write({
150
156
  ...entry,
@@ -152,7 +158,9 @@ async function buildMacosBundle({ root, product, infoPlist, bundle, bundleId, sc
152
158
  }),
153
159
  note: write
154
160
  });
161
+ progress.place(null);
155
162
  if (!outcome.ok) throw new Error(`${outcome.machine}: ${outcome.reason}`);
163
+ progress.step("install");
156
164
  const executable = join(outcome.artifactPath, "Contents", "MacOS", product);
157
165
  const plist = JSON.parse(getExecutor().runFile("plutil", [
158
166
  "-convert",
@@ -192,9 +200,11 @@ async function buildMacosBundle({ root, product, infoPlist, bundle, bundleId, sc
192
200
  max: getConcurrencyLimits().maxBuilds,
193
201
  root,
194
202
  logFile: writer.file,
195
- out: note
203
+ out: note,
204
+ waitingFor: (info) => progress.waitingFor(info, "build-slot")
196
205
  });
197
206
  if (record) record.builtOn = "here";
207
+ progress.step("compile");
198
208
  await tool(root, [
199
209
  "build",
200
210
  "-c",
@@ -214,6 +224,7 @@ async function buildMacosBundle({ root, product, infoPlist, bundle, bundleId, sc
214
224
  scratch,
215
225
  "--show-bin-path"
216
226
  ], writer, () => {}, true);
227
+ progress.step("install");
217
228
  const staged = join(staging, `${product}.app`);
218
229
  stageBundle(root, product, infoPlist, bin, staged, bundleId, extras);
219
230
  promote(staged);
@@ -238,13 +249,13 @@ async function buildMacosBundle({ root, product, infoPlist, bundle, bundleId, sc
238
249
  //#endregion
239
250
  //#region src/commands/macos.ts
240
251
  /**
241
- * Builds the Debug app and launches it here, or with `remote` on that approved hosting Mac. A named host never falls
252
+ * Builds the Debug app and launches it here, or with `remote` on that approved remote Mac. A named host never falls
242
253
  * back to a local launch.
243
254
  */
244
255
  async function runMacos(root, note = console.error, remote, buildMachineFlag) {
245
256
  const backend = remote?.trim().toLowerCase();
246
- if (backend === "eas" || backend === "proxy") throw Object.assign(/* @__PURE__ */ new Error("stim macos --remote takes a hosting Mac name from hosting.machines; macOS has no eas or proxy backend."), { code: "STIM_BAD_ARG" });
247
- 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 hosting.machines."), { code: "STIM_BAD_ARG" });
257
+ 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" });
258
+ 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" });
248
259
  if (process.platform !== "darwin") throw new Error("stim macos requires a Mac with Swift installed.");
249
260
  root = realpathSync(root);
250
261
  if (!existsSync(join(root, "Package.swift"))) throw new Error("Run stim macos from the directory containing Package.swift.");
@@ -264,7 +275,14 @@ async function runMacos(root, note = console.error, remote, buildMachineFlag) {
264
275
  return withNativeBuildRun(root, {
265
276
  command: "macos",
266
277
  platform: "macos"
267
- }, async () => {
278
+ }, async (claim) => {
279
+ const progress = startBuildProgress({
280
+ root,
281
+ platform: "macos",
282
+ slot: "default",
283
+ claim,
284
+ note
285
+ });
268
286
  return withWorkspaceProcessLock(workspaceDir(root), "macos-launch", async () => {
269
287
  const previous = requiredMacosRecord(root);
270
288
  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}` : ""}.`);
@@ -292,7 +310,8 @@ async function runMacos(root, note = console.error, remote, buildMachineFlag) {
292
310
  hostLaunched: previous.hostLaunched ?? false
293
311
  } : {}
294
312
  };
295
- const handoff = await buildBundle(root, macos.infoPlist, record, remote !== void 0, note, macos);
313
+ const handoff = await buildBundle(root, macos.infoPlist, record, remote !== void 0, note, macos, progress);
314
+ progress.step("launch");
296
315
  if (!remote) return launchHere(root, record);
297
316
  const connection = await connectHost(remote);
298
317
  const write = (patch) => writeWorkspaceState(root, { macos: {
@@ -342,14 +361,14 @@ async function runMacos(root, note = console.error, remote, buildMachineFlag) {
342
361
  external: true,
343
362
  declareSpawns: true,
344
363
  ownerPurpose: "build and launch macOS app"
345
- });
364
+ }).finally(() => progress.clear());
346
365
  }, { write: note });
347
366
  }
348
- async function buildBundle(root, infoPlist, record, hosted, note, extras) {
367
+ async function buildBundle(root, infoPlist, record, hosted, note, extras, progress = NO_BUILD_PROGRESS) {
349
368
  const started = Date.parse(record.build.startedAt);
350
369
  const scratch = join(macosDir(root), "build");
351
370
  writeWorkspaceState(root, { macos: record });
352
- const writer = createNdjsonWriter(macosLogFile(root), { maxBytes: LOG_ROTATE_BYTES });
371
+ const writer = tapBuildLog(createNdjsonWriter(macosLogFile(root), { maxBytes: LOG_ROTATE_BYTES }), progress);
353
372
  try {
354
373
  const { bundleId: base } = validateInfoPlist(root, record.product, infoPlist);
355
374
  const bundleId = hosted ? base : `${base}.stim.${createHash("sha256").update(root).digest("hex").slice(0, 12)}`;
@@ -362,6 +381,7 @@ async function buildBundle(root, infoPlist, record, hosted, note, extras) {
362
381
  scratch,
363
382
  writer,
364
383
  note,
384
+ progress,
365
385
  record: record.build,
366
386
  buildMachine: record.build.buildMachine,
367
387
  resources: extras.resources,
@@ -377,6 +397,7 @@ async function buildBundle(root, infoPlist, record, hosted, note, extras) {
377
397
  durationMs: Date.now() - started
378
398
  };
379
399
  writeWorkspaceState(root, { macos: record });
400
+ recordMacosBuild(root, record.build);
380
401
  return built.handoff;
381
402
  } catch (error) {
382
403
  const message = error instanceof Error ? error.message : String(error);
@@ -386,23 +407,43 @@ async function buildBundle(root, infoPlist, record, hosted, note, extras) {
386
407
  level: "error",
387
408
  msg: message
388
409
  });
410
+ const build = {
411
+ ...record.build,
412
+ state: "failed",
413
+ finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
414
+ durationMs: Date.now() - started,
415
+ error: message,
416
+ ..."code" in Object(error) && typeof error.code === "string" ? { errorCode: error.code } : {}
417
+ };
389
418
  writeWorkspaceState(root, { macos: {
390
419
  ...record,
391
420
  supervisor: void 0,
392
- build: {
393
- ...record.build,
394
- state: "failed",
395
- finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
396
- durationMs: Date.now() - started,
397
- error: message,
398
- ..."code" in Object(error) && typeof error.code === "string" ? { errorCode: error.code } : {}
399
- }
421
+ build
400
422
  } });
423
+ recordMacosBuild(root, build);
401
424
  throw error;
402
425
  } finally {
403
426
  writer.close();
404
427
  }
405
428
  }
429
+ function recordMacosBuild(root, build) {
430
+ recordFinishedBuild(root, {
431
+ platform: "macos",
432
+ status: build.state === "ok" ? "ok" : "failed",
433
+ configuration: "Debug",
434
+ fingerprint: null,
435
+ cacheKey: null,
436
+ cacheHit: false,
437
+ cacheSkipped: false,
438
+ durationMs: build.durationMs,
439
+ startedAt: build.startedAt,
440
+ errorCode: build.errorCode,
441
+ buildMachine: build.buildMachine,
442
+ builtOn: build.builtOn,
443
+ offloadedTo: build.offloadedTo,
444
+ offloadFallback: build.offloadFallback
445
+ });
446
+ }
406
447
  async function launchHere(root, record) {
407
448
  const fd = openSync(join(workspaceLogsDir$1(root), "macos-supervisor.log"), "a");
408
449
  let child;
@@ -455,10 +496,10 @@ function launchPayload(root, record) {
455
496
  };
456
497
  }
457
498
  function macosCommand(program) {
458
- program.command("macos").description("Build and launch an owned Swift Package macOS Debug app.").option("--build-machine <value>", "Build on auto, local, or one named machine; a name refuses without fallback", parseBuildMachineOption).option("--json", "print one launch payload; build output goes to stderr").option("--remote <machine>", "run it on this approved hosting Mac from hosting.machines").action(async (options) => {
499
+ 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 payload; build output goes to stderr").option("--remote <machine>", "run it on this approved remote Mac from remote.machines").action(async (options) => {
459
500
  const root = findProjectRoot$1(process.cwd());
460
501
  if (!root) throw new Error("Run stim macos from the Swift Package directory.");
461
- const record = await runMacos(root, console.error, options.remote, options.buildMachine).catch((error) => {
502
+ const record = await runMacos(root, console.error, options.remote, options.remoteBuild).catch((error) => {
462
503
  const remedy = error.remedy;
463
504
  if (typeof remedy === "string") console.error(`remedy: ${remedy}`);
464
505
  throw error;
@@ -1,10 +1,10 @@
1
1
  import { j as formatBytes } from "./config-D0DbpZtM.mjs";
2
2
  import { t as relaunchWithLogFile } from "./detached-entry-CiTEgMR1.mjs";
3
- import { c as resolveBudget } from "./budget-DM984mnd.mjs";
3
+ import { c as resolveBudget } from "./budget-CUDz870h.mjs";
4
4
  import { r as createNdjsonWriter } from "./ndjson-PclOIwVY.mjs";
5
5
  import { t as resolveMaintenanceSettings } from "./settings-BBpMcDbD.mjs";
6
6
  import { r as due, t as capChildLog } from "./attempt-Bk2ouQVL.mjs";
7
- import { a as sizeScanDeferred, i as measureSizes, r as measurePressure, t as plannedMaintenance } from "./preview-CxPRIEht.mjs";
7
+ import { a as sizeScanDeferred, i as measureSizes, r as measurePressure, t as plannedMaintenance } from "./preview-C_JjkEy4.mjs";
8
8
  import { appendFileSync, mkdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
9
9
  import { basename, join, resolve } from "node:path";
10
10
  import { LOG_ROTATE_BYTES, rotatedLogPath, withDirLock } from "@stim-cli/core";