stim 1.26.0 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/dist/{acquire-artifact-DVsvSwf7.mjs → acquire-artifact-BKN2Yuhg.mjs} +2 -2
  2. package/dist/{act-C-BqJEpu.mjs → act-ROviTF_t.mjs} +297 -122
  3. package/dist/{activity-Lnb_EoRY.mjs → activity-Cd-ysFes.mjs} +6 -6
  4. package/dist/{agent-device-usage-output-DbXy5tg8.mjs → agent-device-usage-output-C5nCKWp9.mjs} +5 -5
  5. package/dist/{android-CSbLRD53.mjs → android--HBgpvpW.mjs} +5 -5
  6. package/dist/{android-CiNQw3kq.mjs → android-Cd6w7_qw.mjs} +96 -43
  7. package/dist/{android-B5P81yI-.mjs → android-Deb9X3_Y.mjs} +37 -15
  8. package/dist/{android-DTAcRwBC.mjs → android-DriNoAVy.mjs} +23 -18
  9. package/dist/{android-cas-BTVhZ0Qs.mjs → android-cas-D5e6ecUg.mjs} +4 -4
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/api.d.mts +13 -3
  12. package/dist/api.mjs +39 -29
  13. package/dist/{apk-signed-tail-B46U9hXc.mjs → apk-signed-tail-BHQHx3Rm.mjs} +2 -2
  14. package/dist/{artifact-BxREhAaV.mjs → artifact-0AGJYB9O.mjs} +18 -23
  15. package/dist/{artifact-CsAP6AGK.mjs → artifact-faemIZv5.mjs} +19 -24
  16. package/dist/{artifact-platform-CMRc0M_r.mjs → artifact-platform-BO2Uvk_A.mjs} +1 -1
  17. package/dist/auto-placement-z-H5pJza.mjs +350 -0
  18. package/dist/{browser-web-rYPyqhTf.mjs → browser-web-slD8AvLp.mjs} +16 -16
  19. package/dist/{build-cache-DrXNCy3T.mjs → build-cache-gBJ-WKzA.mjs} +43 -21
  20. package/dist/{build-DPhApsjV.mjs → build-hS0QyFlQ.mjs} +35 -31
  21. package/dist/{build-plan-DrMMdayj.mjs → build-plan-CBqYbzYM.mjs} +7 -6
  22. package/dist/{cache-manifest-BEZ9Bpl1.mjs → cache-manifest-DEjqGGat.mjs} +1 -1
  23. package/dist/cache-manifest.mjs +1 -1
  24. package/dist/{budget-k2mZGvvk.mjs → ccache-BWTze1Ls.mjs} +560 -1603
  25. package/dist/{cdp-BG3FJCCx.mjs → cdp-C3svvXiE.mjs} +1 -1
  26. package/dist/{chrome-BvV8ssI3.mjs → chrome-DyDWurWG.mjs} +1 -1
  27. package/dist/{cli-BBKFGOFl.mjs → cli-ftXDLto1.mjs} +24 -23
  28. package/dist/cli.mjs +1 -1
  29. package/dist/{client-D9CaRks-.mjs → client-xsdxrhWA.mjs} +48 -62
  30. package/dist/collector-run.d.mts +10 -9
  31. package/dist/collector-run.mjs +42 -27
  32. package/dist/{command-output-BF5AR2dL.mjs → command-output-Dj-WT4BP.mjs} +1 -1
  33. package/dist/{config-BktkY_zC.mjs → config-Cn94Jc0g.mjs} +23 -4
  34. package/dist/{dependencies-Dw6wfQdv.mjs → dependencies-BGokZ-Ng.mjs} +108 -60
  35. package/dist/{dependency-state-DFB41vfr.mjs → dependency-state-C3OtgG94.mjs} +14 -7
  36. package/dist/{detached-entry-KmieOKgN.mjs → detached-entry-BPlSaCwC.mjs} +1 -1
  37. package/dist/{dev-client-DXR_tPVY.mjs → dev-client-BMca82xo.mjs} +2 -2
  38. package/dist/{device-BcYeHSFu.mjs → device-BJm0irrq.mjs} +16 -16
  39. package/dist/{device-capacity-DCSvUF0l.mjs → device-capacity-6LP7QsaA.mjs} +101 -16
  40. package/dist/device-host-worker.mjs +19 -19
  41. package/dist/{device-ios-BLGfXQeK.mjs → device-ios-534c14fz.mjs} +251 -23
  42. package/dist/{device-lease-run-BmvIl7bI.mjs → device-lease-run-DwsGfjUN.mjs} +5 -5
  43. package/dist/{device-pool-Dluix4H3.mjs → device-pool-BnQqvs6o.mjs} +3 -3
  44. package/dist/{device-BK-zwyd_.mjs → device-tM41-TUq.mjs} +25 -24
  45. package/dist/{doctor-Cp-BhzTS.mjs → doctor-Dbx1ZpD2.mjs} +1 -1
  46. package/dist/{doctor-Bhg1ii70.mjs → doctor-DyqE9n1J.mjs} +28 -16
  47. package/dist/{doctor-OnwP94ne.mjs → doctor-F-3VUUyN.mjs} +76 -32
  48. package/dist/{doctor-fingerprint-D3a04Mhu.mjs → doctor-fingerprint-o7ZI9YLn.mjs} +1 -1
  49. package/dist/doctor-fingerprint.mjs +1 -1
  50. package/dist/{doctor-watchman-BStK05nt.mjs → doctor-watchman-CxDbyrrt.mjs} +5 -5
  51. package/dist/{eas-build-Dsj93iM9.mjs → eas-build-CjNSWmjo.mjs} +4 -4
  52. package/dist/eas-fallback-9fqb46kW.mjs +87 -0
  53. package/dist/{eas-session-ledger-B5vygTiD.mjs → eas-session-ledger-DrP4OuuM.mjs} +6 -6
  54. package/dist/{error-diagnostics-BOOm9Db7.mjs → error-diagnostics-snej9k4j.mjs} +51 -25
  55. package/dist/{exec-VFRpu1iA.mjs → exec-aULwtNly.mjs} +57 -6
  56. package/dist/{gc-C_79zvz4.mjs → gc-BRwAY3qT.mjs} +2 -2
  57. package/dist/{gc-ldgr-hXU.mjs → gc-CGZ1Yg88.mjs} +160 -45
  58. package/dist/{guide-D7K0X6KG.mjs → guide-_rfEh_zM.mjs} +580 -183
  59. package/dist/{hosted-android-Bk54ej6n.mjs → hosted-android-BMKzUNnY.mjs} +4 -4
  60. package/dist/{hosted-client-fHO8yqzc.mjs → hosted-client-D7Pk_Oo1.mjs} +12 -8
  61. package/dist/{hosted-logs-BfbmDM4M.mjs → hosted-logs-B1gqQuva.mjs} +8 -8
  62. package/dist/{hosted-logs-sync-B0pvmOk-.mjs → hosted-logs-sync-Dg3qrZmV.mjs} +5 -5
  63. package/dist/{hosted-macos-CPl0OZ9h.mjs → hosted-macos-B9w4H8hc.mjs} +6 -6
  64. package/dist/{hosted-native-CpDB3-PO.mjs → hosted-native-CdgaiuyP.mjs} +17 -16
  65. package/dist/{idle-shutdown-FfxL1KdG.mjs → idle-shutdown-Cbvo5KEh.mjs} +7 -8
  66. package/dist/{ios-ftxdQbJS.mjs → ios-B5HlVMhQ.mjs} +92 -37
  67. package/dist/{ios-B7-lToDu.mjs → ios-Bk4mWbtS.mjs} +8 -8
  68. package/dist/{ios-ENC4sRPA.mjs → ios-CsRVik64.mjs} +7 -1
  69. package/dist/{ios-WxpDJ5T1.mjs → ios-E26qSpkb.mjs} +27 -11
  70. package/dist/{ios-device-CsyryvpT.mjs → ios-device-C_QkIf1Z.mjs} +3 -3
  71. package/dist/{ios-device-B6HK951C.mjs → ios-device-CiBA-er9.mjs} +1 -1
  72. package/dist/{ios-project-Ty5pHl9O.mjs → ios-project-D8Jcy_br.mjs} +22 -9
  73. package/dist/{ios-signing-4c_qXvQm.mjs → ios-signing-BJzvDPfU.mjs} +2 -2
  74. package/dist/{ios-state-Cw7-WQf2.mjs → ios-state-BZ03NFgF.mjs} +1 -1
  75. package/dist/{js-swap-BMhXYVDS.mjs → js-swap-Dg2a945i.mjs} +8 -7
  76. package/dist/{launch-DOp8RjDz.mjs → launch-CRyBeNsA.mjs} +42 -38
  77. package/dist/lightened-BCsdAGj_.mjs +171 -0
  78. package/dist/{logs-dQDki6Tt.mjs → logs-CC_-ZzEE.mjs} +7 -7
  79. package/dist/{logs-s1dRIG1E.mjs → logs-aJQb-RDg.mjs} +46 -21
  80. package/dist/{macos-B0VEV3Gf.mjs → macos-BGmTpnv9.mjs} +1 -1
  81. package/dist/{macos-DBBPNnIA.mjs → macos-DlCBhMw5.mjs} +73 -38
  82. package/dist/macos-run.mjs +1 -1
  83. package/dist/maintenance-run.mjs +7 -7
  84. package/dist/{metro-CjC10t6E.mjs → metro-CvyD-xwe.mjs} +4 -4
  85. package/dist/{metro-gateway-B6_PgD0L.mjs → metro-gateway-BnHdqMO_.mjs} +3 -3
  86. package/dist/{named-ports-BG0j1X4g.mjs → named-ports-BCyMWA6b.mjs} +3 -3
  87. package/dist/{native-android-CL2NGiik.mjs → native-android-DlpxCyOP.mjs} +17 -18
  88. package/dist/{native-gradle-artifact-inputs-btSUulme.mjs → native-gradle-artifact-inputs-C13qT7R_.mjs} +5 -5
  89. package/dist/{native-runtime-Dq3RBcON.mjs → native-runtime-DqaIBO5w.mjs} +9 -8
  90. package/dist/{native-source-D-4Dh4JU.mjs → native-source-D1AzWiuP.mjs} +1 -1
  91. package/dist/{native-xcode-inputs-BW7H8JGu.mjs → native-xcode-inputs-B1W8SrxB.mjs} +3 -3
  92. package/dist/{native-xcode-ios-CBXJAxfC.mjs → native-xcode-ios-QPP0Rm68.mjs} +17 -17
  93. package/dist/{ndjson-CgE_o3Dl.mjs → ndjson-Dy2W4vRa.mjs} +2 -2
  94. package/dist/offload-worker.mjs +23 -24
  95. package/dist/{operation-exec-CUZifp6Z.mjs → operation-exec-Dp4FuIGR.mjs} +1 -1
  96. package/dist/{ownership-BjYvMNX_.mjs → ownership-Bx-0cku-.mjs} +3 -3
  97. package/dist/{page-CzEA_-5_.mjs → page-CQJlcj3x.mjs} +2 -2
  98. package/dist/{phone-reverses-lmj6kcPm.mjs → phone-reverses-C9yAaKEv.mjs} +18 -4
  99. package/dist/{placement-log-DIFPQAXp.mjs → placement-log-BXUbiZM6.mjs} +3 -3
  100. package/dist/{plan-placement-IiiSQhtz.mjs → plan-placement-UxnQjv5Z.mjs} +36 -10
  101. package/dist/{ports-C2_w1Z0Z.mjs → ports-uUrghqWN.mjs} +3 -3
  102. package/dist/{prebuild-gmouvmJZ.mjs → prebuild-BDpToDgR.mjs} +16 -17
  103. package/dist/{project-BUu6Is4k.mjs → project-DYj-HVx6.mjs} +17 -17
  104. package/dist/{pull-request-CbNlkFok.mjs → pull-request-BzLmzAIQ.mjs} +2 -2
  105. package/dist/pull-requests.mjs +1 -1
  106. package/dist/{react-native-android-Cgg99REN.mjs → react-native-android-DDBccgJw.mjs} +32 -26
  107. package/dist/{react-native-build-oNwqF5Wb.mjs → react-native-build-DaK2IFyP.mjs} +9 -9
  108. package/dist/{react-native-doctor-BhA3KUte.mjs → react-native-doctor-B-Mw6DcR.mjs} +6 -6
  109. package/dist/{react-native-ios-B-nf4rjN.mjs → react-native-ios-DjYwUF9U.mjs} +23 -17
  110. package/dist/{recordings-BldzVKq0.mjs → recordings-C20iUZfp.mjs} +1 -1
  111. package/dist/{registration-CN6nlhcD.mjs → registration-BwCe64PH.mjs} +1 -1
  112. package/dist/{reload-C9OduiNc.mjs → reload-DJBeF_rC.mjs} +1 -1
  113. package/dist/{reload-CCR7KC_l.mjs → reload-fUdkH2_p.mjs} +16 -16
  114. package/dist/{remote-C8S7FlPF.mjs → remote-y6n99WMW.mjs} +22 -9
  115. package/dist/{result-7F5hEwQJ.mjs → result-CTqBw2Te.mjs} +32 -21
  116. package/dist/{run-BqB0v3pt.mjs → run-DaCeNKRm.mjs} +3 -3
  117. package/dist/{selection-BNPBZ6T5.mjs → selection-Bs8phwhN.mjs} +37 -29
  118. package/dist/{server-bare-A75rDIdD.mjs → server-bare-BOh-iZEj.mjs} +2 -2
  119. package/dist/{server-command-CssKFOD7.mjs → server-command-8CuA51Cv.mjs} +6 -6
  120. package/dist/{server-expo-eQfOdydb.mjs → server-expo-ABQs2XFA.mjs} +4 -4
  121. package/dist/server-expo-Ba_Y21vB.mjs +2 -0
  122. package/dist/{settings-CosW5X-S.mjs → settings-BDVI8Ivc.mjs} +331 -62
  123. package/dist/{settings-OaGQF-ri.mjs → settings-CMHhQNwI.mjs} +24 -3
  124. package/dist/settings-payload-cm60Zhib.mjs +257 -0
  125. package/dist/settings-write-BdNRLlBn.mjs +185 -0
  126. package/dist/settings.schema.json +51 -33
  127. package/dist/{simslim-Bax1qcxu.mjs → simslim-DCQwzoPy.mjs} +2 -2
  128. package/dist/{slot-launch-CYCEhfBY.mjs → slot-launch-0l7RqSpr.mjs} +6 -6
  129. package/dist/{stage-jKQ7CP_B.mjs → stage-F4cAfJGi.mjs} +2 -2
  130. package/dist/{start-C_wefNKB.mjs → start-DcqnF9p8.mjs} +1 -1
  131. package/dist/{start-_BdJ32cZ.mjs → start-DrPwER_2.mjs} +27 -22
  132. package/dist/{state-C1i2nMOP.mjs → state-BX1y5syV.mjs} +4 -4
  133. package/dist/{state-C4OdpOTF.mjs → state-CZxLyetD.mjs} +2 -2
  134. package/dist/{stats-tEpEEH-u.mjs → stats-GxuCbles.mjs} +5 -5
  135. package/dist/{stats-report-n2U5plhk.mjs → stats-report-B86Cv7Uc.mjs} +1 -1
  136. package/dist/{status-CRXz-Gtj.mjs → status-7ULDEJ1e.mjs} +1 -1
  137. package/dist/{status-DQrqodLj.mjs → status-BfnK9pUd.mjs} +25 -25
  138. package/dist/{status-B9M7x4CZ.mjs → status-Bj7ZYvvc.mjs} +1 -1
  139. package/dist/{status-watch-B5wDIH_o.mjs → status-watch-BfabQn03.mjs} +5 -5
  140. package/dist/status-worker.mjs +1 -1
  141. package/dist/{stim-desktop-6Dqp-gjX.mjs → stim-desktop-CbWo21kb.mjs} +2 -2
  142. package/dist/{stop-ySNQHXMG.mjs → stop-CH79S3IZ.mjs} +5 -5
  143. package/dist/{stop-DRqQVqDJ.mjs → stop-D-EAr25B.mjs} +21 -20
  144. package/dist/{stop-CmdNhGlC.mjs → stop-x1Yu3He4.mjs} +2 -2
  145. package/dist/supervisor-run.mjs +17 -17
  146. package/dist/{support-CVOCp0Ft.mjs → support-Be0UeVZU.mjs} +10 -10
  147. package/dist/{support-BGSCBoib.mjs → support-CNg_YsOk.mjs} +6 -6
  148. package/dist/{swiftpm-artifact-inputs-CfUzt_0Z.mjs → swiftpm-artifact-inputs-uPqYvGBv.mjs} +4 -4
  149. package/dist/{swiftpm-macos-x6HPpl_2.mjs → swiftpm-macos-Ch4YjY_A.mjs} +11 -12
  150. package/dist/{toolchain-J4J8MrAr.mjs → toolchain-CbCG6C5Z.mjs} +321 -15
  151. package/dist/{toolchain-DoavrvIA.mjs → toolchain-JYAOquPg.mjs} +1 -1
  152. package/dist/{trigger-KVaWWNyn.mjs → trigger-DMou-X7j.mjs} +2 -2
  153. package/dist/trigger-qp2ji5wE.mjs +2 -0
  154. package/dist/{warm-progress-DvhTX_eu.mjs → warm-progress-C0RsbngN.mjs} +731 -727
  155. package/dist/{web-Bihbf7-u.mjs → web-Cq_AQ4DK.mjs} +9 -9
  156. package/dist/web-Je6abcpz.mjs +2 -0
  157. package/dist/web-run.mjs +9 -9
  158. package/dist/windows-report.mjs +1 -1
  159. package/dist/{workspace-state-pUg3_RRA.mjs → workspace-state-BjqdjnJR.mjs} +3 -3
  160. package/dist/{workspaces-g2lhdBXF.mjs → workspaces-DFbj07jp.mjs} +1795 -70
  161. package/dist/{worktree-BKuklFh_.mjs → worktree-COAJ3-OD.mjs} +934 -514
  162. package/dist/{worktree-Bm4cb-nU.mjs → worktree-JGUd_53L.mjs} +1 -1
  163. package/package.json +7 -7
  164. package/dist/ccache-Bx5TbxwG.mjs +0 -143
  165. package/dist/eas-fallback-FwkeqqGi.mjs +0 -381
  166. package/dist/hosted-ios-D55QhYaD.mjs +0 -15
  167. package/dist/native-run-BfIDFKLH.mjs +0 -275
  168. package/dist/server-expo-wvcj5tiZ.mjs +0 -2
  169. package/dist/settings-write-QjYfSrjF.mjs +0 -360
  170. package/dist/trigger-DzJu208Q.mjs +0 -2
  171. package/dist/web-BFLueSh-.mjs +0 -2
@@ -1,15 +1,16 @@
1
- import { c as throwIfCancelled, l as WorkspaceProcessCleanupError, n as isTimeoutError, t as getExecutor } from "./exec-VFRpu1iA.mjs";
2
- import { _ as loadConfig$1, d as getConfigDir, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-BktkY_zC.mjs";
3
- import { c as gitQuiet, l as gitQuietAsync, n as runOperationFileQuiet, o as git, r as childEnvironment, s as gitAsync, t as runOperationFile } from "./operation-exec-CUZifp6Z.mjs";
4
- import { accessSync, chmodSync, constants, lstatSync, mkdirSync, mkdtempSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
1
+ import { D as ownership_claim_exports, c as throwIfCancelled, l as WorkspaceProcessCleanupError, n as isTimeoutError, t as getExecutor } from "./exec-aULwtNly.mjs";
2
+ import { _ as loadConfig$1, d as getConfigDir, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-Cn94Jc0g.mjs";
3
+ import { c as gitQuiet, l as gitQuietAsync, n as runOperationFileQuiet, o as git, r as childEnvironment, s as gitAsync, t as runOperationFile } from "./operation-exec-Dp4FuIGR.mjs";
4
+ import { accessSync, chmodSync, constants, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
5
5
  import { tmpdir } from "node:os";
6
6
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
7
7
  import { ambientEnv, buildCacheRoot, compiledHelper, configDir } from "@stim-cli/core";
8
- import { REMOTE_DEVICE_BACKENDS, SETTINGS, SETTING_GROUPS, TUNNEL_MODES, WEB_VIEWPORTS, acceptsShape, coerceSettingText, expectedShape, isLayeredSetting, settingDefinition, settingValueError } from "@stim-cli/core/state";
8
+ import { REMOTE_DEVICE_BACKENDS, REPLACED_SETTINGS, SETTINGS, SETTING_GROUPS, TUNNEL_MODES, WEB_VIEWPORTS, acceptsShape, coerceSettingText, expectedShape, isLayeredSetting, placementWord, replacementAdvice, settingDefinition, settingValueError, trashRoot } from "@stim-cli/core/state";
9
9
  import { basename as basename$1, dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, normalize, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
10
10
  import { fileURLToPath } from "node:url";
11
+ import { captureProcessIdentity } from "@stim-cli/core/process-identity";
11
12
  import { existsSync as existsSync$1, lstatSync as lstatSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, statSync as statSync$1 } from "fs";
12
- import { chmod, lstat, mkdir, readdir, realpath, rm, utimes } from "node:fs/promises";
13
+ import { chmod, lstat, mkdir, mkdtemp, readdir, realpath, rename, rm, rmdir, utimes, writeFile } from "node:fs/promises";
13
14
  //#region src/temporary.ts
14
15
  function existingPath(path) {
15
16
  const missing = [];
@@ -108,6 +109,248 @@ async function removeTemporaryEntryAsync(path, signal) {
108
109
  signal?.throwIfAborted();
109
110
  }
110
111
  //#endregion
112
+ //#region src/workspace/worktree-trash.ts
113
+ const TRASH_MANIFEST = "trash.json";
114
+ const TRASH_ENTRY_PREFIX = "remove-";
115
+ const TRASH_ENTRIES = "entries";
116
+ const TRASH_CLAIMS = "claims";
117
+ const LIST_TIMEOUT_MS = 3e4;
118
+ const DELETE_NICENESS = "10";
119
+ function rethrowCancellation(error, signal) {
120
+ if (error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error) throw error;
121
+ signal?.throwIfAborted();
122
+ }
123
+ async function isPlainDirectory(path) {
124
+ const stat = await lstat(path).catch(() => null);
125
+ return Boolean(stat?.isDirectory());
126
+ }
127
+ async function ignoredDirectories(worktree, options) {
128
+ const out = await gitAsync(worktree, [
129
+ "ls-files",
130
+ "--others",
131
+ "--ignored",
132
+ "--exclude-standard",
133
+ "--directory",
134
+ "--no-empty-directory",
135
+ "-z"
136
+ ], {
137
+ ...options.env ? childEnvironment(options.env) : {},
138
+ signal: options.signal,
139
+ declareFor: options.declareFor,
140
+ timeoutMs: LIST_TIMEOUT_MS,
141
+ untrimmed: true
142
+ });
143
+ const found = [];
144
+ for (const entry of out.split("\0")) {
145
+ if (!entry.endsWith("/")) continue;
146
+ const rel = entry.slice(0, -1);
147
+ const parts = rel.split("/");
148
+ let plain = true;
149
+ for (let depth = 1; depth <= parts.length && plain; depth++) plain = await isPlainDirectory(join(worktree, ...parts.slice(0, depth)));
150
+ if (plain) found.push(rel);
151
+ }
152
+ return found;
153
+ }
154
+ async function openTrash(worktree, options, kind) {
155
+ if ((options.platform ?? process.platform) === "win32") return null;
156
+ const root = trashRoot();
157
+ let dir = null;
158
+ let claim = null;
159
+ try {
160
+ await mkdir(root, { recursive: true });
161
+ if (filesystemDevice(root) !== filesystemDevice(worktree)) return null;
162
+ dir = await mkdtemp(join(root, TRASH_ENTRY_PREFIX));
163
+ claim = (0, ownership_claim_exports.tryAcquireClaim)({
164
+ root: join(dir, "claims"),
165
+ mode: "exclusive",
166
+ label: "worktree trash"
167
+ }).acquired ?? null;
168
+ if (!claim) throw new Error("the trash entry claim was not acquired");
169
+ const manifest = {
170
+ worktree,
171
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
172
+ ...kind ? { kind } : {}
173
+ };
174
+ await writeFile(join(dir, TRASH_MANIFEST), `${JSON.stringify(manifest)}\n`);
175
+ await mkdir(join(dir, TRASH_ENTRIES));
176
+ } catch (error) {
177
+ if (claim) (0, ownership_claim_exports.releaseClaim)(claim);
178
+ if (dir) await rm(dir, {
179
+ recursive: true,
180
+ force: true
181
+ }).catch(() => {});
182
+ rethrowCancellation(error, options.signal);
183
+ return null;
184
+ }
185
+ return {
186
+ dir,
187
+ worktree,
188
+ moved: [],
189
+ claim
190
+ };
191
+ }
192
+ /**
193
+ * Moves the worktree's ignored directories, which `git worktree remove` would delete, into a new entry under
194
+ * `$STIM_HOME/trash` held by an exclusive ownership claim. Null, with nothing moved, when the trash is on another
195
+ * filesystem, the platform is Windows, git cannot list the entries, or the claim cannot be taken. A directory that
196
+ * does not rename stays in the worktree for git to delete.
197
+ */
198
+ async function moveIgnoredTreesToTrash(worktree, options = {}) {
199
+ if ((options.platform ?? process.platform) === "win32") return null;
200
+ let listed;
201
+ try {
202
+ listed = await ignoredDirectories(worktree, options);
203
+ } catch (error) {
204
+ rethrowCancellation(error, options.signal);
205
+ return null;
206
+ }
207
+ if (!listed.length) return null;
208
+ const trash = await openTrash(worktree, options);
209
+ if (!trash) return null;
210
+ for (const from of listed) {
211
+ const to = String(trash.moved.length);
212
+ try {
213
+ await rename(join(worktree, from), join(trash.dir, TRASH_ENTRIES, to));
214
+ trash.moved.push({
215
+ from,
216
+ to
217
+ });
218
+ } catch {}
219
+ }
220
+ if (trash.moved.length) return trash;
221
+ await discardTrash(trash);
222
+ return null;
223
+ }
224
+ /**
225
+ * A trash entry that takes directories out of a live worktree while it warms, so the delete runs in the background.
226
+ * `take` is false, with the directory untouched, when the entry cannot be opened or the rename fails; the caller
227
+ * deletes it in place. gc deletes a crashed entry whatever the state of the worktree.
228
+ */
229
+ function warmTrash(worktree, options = {}) {
230
+ let trash;
231
+ return {
232
+ async take(path) {
233
+ if (trash === void 0) trash = await openTrash(worktree, options, "warm");
234
+ if (!trash) return false;
235
+ const to = String(trash.moved.length);
236
+ try {
237
+ await rename(path, join(trash.dir, TRASH_ENTRIES, to));
238
+ } catch {
239
+ return false;
240
+ }
241
+ trash.moved.push({
242
+ from: path,
243
+ to
244
+ });
245
+ return true;
246
+ },
247
+ async dispose(operation) {
248
+ if (!trash) return;
249
+ if (trash.moved.length) await disposeTrash(trash, operation);
250
+ else await discardTrash(trash);
251
+ }
252
+ };
253
+ }
254
+ async function discardTrash(trash) {
255
+ await rmdir(join(trash.dir, TRASH_ENTRIES)).catch(() => {});
256
+ await rm(join(trash.dir, TRASH_MANIFEST), { force: true }).catch(() => {});
257
+ (0, ownership_claim_exports.releaseClaim)(trash.claim);
258
+ await rmdir(trash.dir).catch(() => {});
259
+ }
260
+ /** Moves every tree back into the worktree. Returns the relative paths that stay in the trash for gc. */
261
+ async function restoreTrashedTrees(trash) {
262
+ const kept = [];
263
+ for (const entry of trash.moved.toReversed()) {
264
+ const target = join(trash.worktree, entry.from);
265
+ try {
266
+ if (await lstat(target).catch(() => null) || !await isPlainDirectory(dirname(target))) {
267
+ kept.push(entry.from);
268
+ continue;
269
+ }
270
+ await rename(join(trash.dir, TRASH_ENTRIES, entry.to), target);
271
+ } catch {
272
+ kept.push(entry.from);
273
+ }
274
+ }
275
+ if (kept.length) (0, ownership_claim_exports.releaseClaim)(trash.claim);
276
+ else await discardTrash(trash);
277
+ return kept;
278
+ }
279
+ /** Deletes one trash entry: `rm -rf` for the bulk, then a walk that also clears read-only directories. */
280
+ async function deleteTrashEntry(dir, operation) {
281
+ if (process.platform !== "win32") try {
282
+ await runOperationFile(operation, getExecutor(), "rm", [
283
+ "-rf",
284
+ "--",
285
+ join(dir, TRASH_ENTRIES)
286
+ ], {
287
+ timeoutMs: "unbounded",
288
+ signal: operation?.signal,
289
+ cwd: dirname(dir)
290
+ });
291
+ } catch (error) {
292
+ rethrowCancellation(error, operation?.signal);
293
+ }
294
+ await removeTemporaryEntryAsync(dir, operation?.signal);
295
+ }
296
+ function deleteInBackground(trash) {
297
+ try {
298
+ (0, ownership_claim_exports.markClaimChildPending)(trash.claim);
299
+ const child = getExecutor().spawn("nice", [
300
+ "-n",
301
+ DELETE_NICENESS,
302
+ "sh",
303
+ "-c",
304
+ "rm -rf -- \"$1\" && rm -rf -- \"$2\"",
305
+ "--",
306
+ join(trash.dir, TRASH_ENTRIES),
307
+ trash.dir
308
+ ], {
309
+ cwd: dirname(trash.dir),
310
+ detached: true,
311
+ stdio: "ignore"
312
+ });
313
+ child.on?.("error", () => {});
314
+ child.unref?.();
315
+ const captured = child.pid === void 0 ? null : captureProcessIdentity(child.pid);
316
+ if (captured?.ok === false && captured.reason.startsWith("NOT_FOUND")) {
317
+ (0, ownership_claim_exports.clearClaimChild)(trash.claim);
318
+ (0, ownership_claim_exports.releaseClaim)(trash.claim);
319
+ return existsSync(trash.dir) ? "left" : "deleted";
320
+ }
321
+ if (!captured?.ok || child.pid === void 0) throw new Error("the trash deletion process was not recorded");
322
+ (0, ownership_claim_exports.setClaimChild)(trash.claim, {
323
+ pid: child.pid,
324
+ processToken: captured.token
325
+ });
326
+ return "background";
327
+ } catch {
328
+ try {
329
+ (0, ownership_claim_exports.clearClaimChild)(trash.claim);
330
+ } catch {}
331
+ (0, ownership_claim_exports.releaseClaim)(trash.claim);
332
+ return "left";
333
+ }
334
+ }
335
+ /**
336
+ * Deletes the trash entry once its trees are out of the way. A CLI command starts a detached, low-priority `rm` recorded
337
+ * as the claim's child, so gc reports the entry as in use until `rm` exits. Inside a bounded report, such as the
338
+ * programmatic API, every child is stopped when the report settles, so the entry is deleted before returning.
339
+ * `left` means the entry waits for gc with its claim released.
340
+ */
341
+ async function disposeTrash(trash, operation) {
342
+ if (!getExecutor().reportSignal?.()) return deleteInBackground(trash);
343
+ try {
344
+ await deleteTrashEntry(trash.dir, operation);
345
+ return "deleted";
346
+ } catch (error) {
347
+ rethrowCancellation(error, operation?.signal);
348
+ return "left";
349
+ } finally {
350
+ (0, ownership_claim_exports.releaseClaim)(trash.claim);
351
+ }
352
+ }
353
+ //#endregion
111
354
  //#region src/clonefile.ts
112
355
  const SOURCE = "stim-clonefile.c";
113
356
  const COMPILE_TIMEOUT_MS = 12e4;
@@ -397,7 +640,7 @@ function knownCopiedPaths(rel) {
397
640
  function isMissingError(error) {
398
641
  return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
399
642
  }
400
- async function removeCopiedPath(root, rel, signal) {
643
+ async function removeCopiedPath(root, rel, signal, trash) {
401
644
  signal.throwIfAborted();
402
645
  const path = join$1(root, rel);
403
646
  let parent;
@@ -411,21 +654,22 @@ async function removeCopiedPath(root, rel, signal) {
411
654
  if (inside === ".." || inside.startsWith(`..${sep$1}`) || isAbsolute$1(inside)) return;
412
655
  const stat = await lstat(parent);
413
656
  const target = join$1(parent, basename$1(path));
657
+ let targetStat;
414
658
  try {
415
- await lstat(target);
659
+ targetStat = await lstat(target);
416
660
  } catch (error) {
417
661
  if (isMissingError(error)) return;
418
662
  throw error;
419
663
  }
420
664
  await chmod(parent, stat.mode | 448);
421
665
  try {
422
- await removeTemporaryEntryAsync(target, signal);
666
+ if (!(targetStat.isDirectory() && await trash.take(target))) await removeTemporaryEntryAsync(target, signal);
423
667
  } finally {
424
668
  await utimes(parent, stat.atime, stat.mtime);
425
669
  await chmod(parent, stat.mode);
426
670
  }
427
671
  }
428
- async function removeKnownCopiedPaths(path, rel, signal) {
672
+ async function removeKnownCopiedPaths(path, rel, signal, trash) {
429
673
  const paths = knownCopiedPaths(rel);
430
674
  if (basename$1(rel) === "node_modules") {
431
675
  const virtualStore = await readdir(join$1(path, ".pnpm")).catch((error) => {
@@ -435,7 +679,7 @@ async function removeKnownCopiedPaths(path, rel, signal) {
435
679
  for (const name of virtualStore) if (name.startsWith("expo-modules-jsi@")) paths.push(`.pnpm/${name}/node_modules/expo-modules-jsi/apple/.DerivedData`);
436
680
  }
437
681
  const root = await realpath(path);
438
- for (const known of paths) await removeCopiedPath(root, known, signal);
682
+ for (const known of paths) await removeCopiedPath(root, known, signal, trash);
439
683
  }
440
684
  async function cloneIgnoredEntries({ root, target, patterns, operation }) {
441
685
  const options = {
@@ -460,58 +704,65 @@ async function cloneIgnoredEntries({ root, target, patterns, operation }) {
460
704
  let cloned = true;
461
705
  let helper;
462
706
  const clonefile = () => helper ??= clonefileHelper(operation);
463
- for (const rel of entries) {
464
- operation.signal.throwIfAborted();
465
- const from = join$1(root, rel);
466
- const to = join$1(target, rel);
467
- let copying = false;
468
- try {
469
- const reason = guard.covers(rel) ? "tracked" : overlapsNestedWorktree(rel, nested) ? "nested worktree" : missingDestinationReason(target, rel);
470
- if (reason) {
471
- skipped.push({
472
- file: rel,
473
- reason
474
- });
475
- continue;
476
- }
477
- await mkdir(dirname$1(to), { recursive: true });
478
- copying = true;
479
- const copiedWith = async (file, args) => {
480
- try {
481
- await getExecutor().runFileAsync(file, args, options);
482
- return true;
483
- } catch (cause) {
484
- if (cause instanceof WorkspaceProcessCleanupError || cause instanceof Error && "reportCleanup" in cause) throw cause;
485
- operation.signal.throwIfAborted();
486
- await removeTemporaryEntryAsync(to);
487
- return false;
707
+ const trash = warmTrash(target, { signal: operation.signal });
708
+ try {
709
+ for (const rel of entries) {
710
+ operation.signal.throwIfAborted();
711
+ const from = join$1(root, rel);
712
+ const to = join$1(target, rel);
713
+ let copying = false;
714
+ try {
715
+ const reason = guard.covers(rel) ? "tracked" : overlapsNestedWorktree(rel, nested) ? "nested worktree" : missingDestinationReason(target, rel);
716
+ if (reason) {
717
+ skipped.push({
718
+ file: rel,
719
+ reason
720
+ });
721
+ continue;
488
722
  }
489
- };
490
- const directoryClone = (await lstat(from)).isDirectory() ? await clonefile() : null;
491
- if (!(directoryClone && await copiedWith(directoryClone, [from, to])) && !await copiedWith("cp", [
492
- "-Rc",
493
- from,
494
- to
495
- ])) {
496
- await getExecutor().runFileAsync("cp", [
497
- "-R",
723
+ await mkdir(dirname$1(to), { recursive: true });
724
+ copying = true;
725
+ const copiedWith = async (file, args) => {
726
+ try {
727
+ await getExecutor().runFileAsync(file, args, options);
728
+ return true;
729
+ } catch (cause) {
730
+ if (cause instanceof WorkspaceProcessCleanupError || cause instanceof Error && "reportCleanup" in cause) throw cause;
731
+ operation.signal.throwIfAborted();
732
+ await removeTemporaryEntryAsync(to);
733
+ return false;
734
+ }
735
+ };
736
+ const directoryClone = (await lstat(from)).isDirectory() ? await clonefile() : null;
737
+ if (!(directoryClone && await copiedWith(directoryClone, [from, to])) && !await copiedWith("cp", [
738
+ "-Rc",
498
739
  from,
499
740
  to
500
- ], options);
501
- cloned = false;
741
+ ])) {
742
+ await getExecutor().runFileAsync("cp", [
743
+ "-R",
744
+ from,
745
+ to
746
+ ], options);
747
+ cloned = false;
748
+ }
749
+ if ((await lstat(to)).isDirectory()) await removeKnownCopiedPaths(to, rel, operation.signal, trash);
750
+ copied.push(rel);
751
+ } catch (cause) {
752
+ if (cause instanceof WorkspaceProcessCleanupError || cause instanceof Error && "reportCleanup" in cause) throw cause;
753
+ if (copying) await removeTemporaryEntryAsync(to);
754
+ operation.signal.throwIfAborted();
755
+ failed.push({
756
+ file: rel,
757
+ error: String(cause?.message || cause)
758
+ });
502
759
  }
503
- if ((await lstat(to)).isDirectory()) await removeKnownCopiedPaths(to, rel, operation.signal);
504
- copied.push(rel);
505
- } catch (cause) {
506
- if (cause instanceof WorkspaceProcessCleanupError || cause instanceof Error && "reportCleanup" in cause) throw cause;
507
- if (copying) await removeTemporaryEntryAsync(to);
508
- operation.signal.throwIfAborted();
509
- failed.push({
510
- file: rel,
511
- error: String(cause?.message || cause)
512
- });
513
760
  }
761
+ } catch (error) {
762
+ await trash.dispose(operation).catch(() => {});
763
+ throw error;
514
764
  }
765
+ await trash.dispose(operation);
515
766
  return {
516
767
  copied,
517
768
  skipped,
@@ -1043,7 +1294,7 @@ function settingShapeErrors(settings) {
1043
1294
  if (SETTINGS_WITH_RESOLVE_TIME_FALLBACK.has(setting.key)) continue;
1044
1295
  const value = settingValueAt(settings, setting.key);
1045
1296
  if (value === void 0) continue;
1046
- const expected = setting.key === "ios.remote" || setting.key === "android.remote" || setting.key === "android.deviceProfile" || setting.type.kind === "number" && !BOUNDS_CHECKED_WHEN_USED.has(setting.key) ? settingValueError(setting, value) : acceptsShape(setting, value) ? null : expectedShape(setting.type);
1297
+ const expected = setting.key === "ios.remote" || setting.key === "android.remote" || setting.key === "macos.remote" || setting.key === "android.deviceProfile" || setting.type.kind === "number" && !BOUNDS_CHECKED_WHEN_USED.has(setting.key) ? settingValueError(setting, value) : acceptsShape(setting, value) ? null : expectedShape(setting.type);
1047
1298
  if (expected) errors.push(`Invalid ${setting.key} setting ${JSON.stringify(value)}. Expected ${expected}.`);
1048
1299
  }
1049
1300
  return errors;
@@ -1440,6 +1691,10 @@ function unknownSettingKeys(settings, prefix = "") {
1440
1691
  }
1441
1692
  return unknown;
1442
1693
  }
1694
+ function inertSettingWarning(settings, key) {
1695
+ const advice = replacementAdvice(key, settingValueAt(settings, key));
1696
+ return `Warning: setting "${key}" is not read by Stim and will be ignored.${advice ? advice.command ? ` Run \`${advice.command}\` instead.` : ` Use ${advice.key} instead.` : ""}`;
1697
+ }
1443
1698
  function readCommittedSettings(directory) {
1444
1699
  if (!directory) return {};
1445
1700
  const p = join$1(directory, ".stim.json");
@@ -1462,8 +1717,16 @@ function setSettingValueAt(settings, path, value) {
1462
1717
  node[segments[segments.length - 1]] = value;
1463
1718
  }
1464
1719
  const MACHINE_READABLE_SETTINGS = SETTINGS.filter((setting) => isLayeredSetting(setting) && setting.scopes.includes("machine") && !setting.key.startsWith("optimizations."));
1465
- function machineLayerSettings(machine) {
1720
+ function removedMachineSettings(machine) {
1466
1721
  const settings = {};
1722
+ for (const key of Object.keys(REPLACED_SETTINGS)) {
1723
+ const value = settingValueAt(machine, key);
1724
+ if (value !== void 0) setSettingValueAt(settings, key, value);
1725
+ }
1726
+ return settings;
1727
+ }
1728
+ function machineLayerSettings(machine) {
1729
+ const settings = removedMachineSettings(machine);
1467
1730
  const optimizations = settingValueAt(machine, "optimizations");
1468
1731
  if (optimizations !== void 0) settings.optimizations = optimizations;
1469
1732
  for (const setting of MACHINE_READABLE_SETTINGS) {
@@ -1635,13 +1898,19 @@ function cacheProviderSettingError(settings) {
1635
1898
  function parseIosRemote(remote) {
1636
1899
  const selected = remote.trim();
1637
1900
  const reserved = selected.toLowerCase();
1638
- if (reserved === "local") return null;
1901
+ const word = placementWord(selected);
1902
+ if (word === "local") return null;
1903
+ if (word) return {
1904
+ kind: "machine",
1905
+ machine: "auto",
1906
+ placement: word
1907
+ };
1639
1908
  return REMOTE_DEVICE_BACKENDS.includes(reserved) ? {
1640
1909
  kind: "backend",
1641
1910
  backend: reserved
1642
1911
  } : {
1643
1912
  kind: "machine",
1644
- machine: reserved === "auto" ? "auto" : selected
1913
+ machine: selected
1645
1914
  };
1646
1915
  }
1647
1916
  function remoteIosSetting(settings) {
@@ -1742,4 +2011,4 @@ function webSettings(settings) {
1742
2011
  };
1743
2012
  }
1744
2013
  //#endregion
1745
- export { settingOrigin as $, metroCommandSettingError as A, podsOutOfSync as At, readCommittedSettings as B, unpushedCommitsAsync as Bt, iosSigningIdentitySha1Setting as C, hasUncommittedWorkAsync as Ct, maintenanceKeepSetting as D, listWorktreesAsync as Dt, iosSimSlimProfileSetting as E, listWorktrees as Et, ngrokUrlSetting as F, resolveFullRef as Ft, resolveAndroidLayout as G, removeTemporaryEntryAsync as Gt, remoteAndroidSetting as H, filesystemDevice as Ht, parseIosRemote as I, resolveFullRefAsync as It, resolveProjectSettings as J, resolveCacheProviderConfig as K, temporaryRoot as Kt, projectSettingsContext as L, resolveSourceCheckoutAsync as Lt, metroPortSetting as M, removeWorktreeAsync as Mt, metroTunnelSettingError as N, repoRoot as Nt, mergeSettingsLayers as O, locallyKnownUpstream as Ot, metroWarmupUrlSetting as P, repoRootAsync as Pt, settingFile as Q, projectSettingsContextAsync as R, restoreFileAsync as Rt, iosSigningIdentitySettingError as S, hasRemoteAsync as St, iosSimSlimDefaultSetting as T, linkedWorktreesOnDisk as Tt, remoteEasFallbackSetting as U, makeTemporaryDirectory as Ut, realpathInside as V, warmWorktreePaths as Vt, remoteIosSetting as W, removeTemporaryEntry as Wt, resolveSettings as X, resolveProjectSettingsAsync as Y, runnableMetroCommand as Z, iosLanHostSetting as _, dirtyPathsAsync as _t, SETTING_SHAPE_REMEDY as a, unknownSettingKeys as at, iosProjectDirSettingError as b, gitCommonDirOnDisk as bt, androidDataPartitionSizeBytes as c, PUBLIC_METRO_ENV as ct, androidLayoutSetting as d, resolveTailscaleBinary as dt, settingOriginScope as et, androidLayoutSettingError as f, branchExistsAsync as ft, deviceReclaimIdleMinutesSetting as g, dirtyFingerprintFiles as gt, deviceIdleShutdownMinutesSetting as h, depsOutOfSync as ht, SETTINGS_WITH_RESOLVE_TIME_FALLBACK as i, tunnelModeSetting as it, metroIdleStopMinutesSetting as j, readWorktreeExclude as jt, metroCommandSetting as k, locallyKnownUpstreamAsync as kt, androidDataPartitionSizeGbSetting as l, detectProviders as lt, defaultAndroidLayout as m, deleteBranchAsync as mt, METRO_COMMAND_PORT as n, settingValueAt as nt, androidAvdConfigSetting as o, webSettings as ot, cacheProviderSettingError as p, cloneIgnoredEntries as pt, resolveIosProjectDir as q, PATH_SETTINGS as r, settingsLayers as rt, androidAvdConfigSettingError as s, workspaceHiddenSetting as st, ANDROID_AVD_CONFIG_HELP as t, settingShapeErrors as tt, androidDataPartitionSizeGbSettingError as u, planMetroReach as ut, iosLanHostSettingError as v, gitCommonDir as vt, iosSigningIdentitySha1SettingError as w, isPodInstallChurn as wt, iosSigningIdentitySetting as x, hasPopulatedSubmodulesAsync as xt, iosProjectDirSetting as y, gitCommonDirAsync as yt, publicUrlSetting as z, sourceCheckoutOf as zt };
2014
+ export { runnableMetroCommand as $, makeTemporaryDirectory as $t, metroCommandSetting as A, listWorktreesAsync as At, publicUrlSetting as B, resolveSourceCheckoutAsync as Bt, iosSigningIdentitySettingError as C, hasPopulatedSubmodulesAsync as Ct, iosSimSlimProfileSetting as D, linkedWorktreesOnDisk as Dt, iosSimSlimDefaultSetting as E, isPodInstallChurn as Et, metroWarmupUrlSetting as F, removeWorktreeAsync as Ft, remoteIosSetting as G, TRASH_CLAIMS as Gt, realpathInside as H, sourceCheckoutOf as Ht, ngrokUrlSetting as I, repoRoot as It, resolveCacheProviderConfig as J, deleteTrashEntry as Jt, removedMachineSettings as K, TRASH_ENTRY_PREFIX as Kt, parseIosRemote as L, repoRootAsync as Lt, metroIdleStopMinutesSetting as M, locallyKnownUpstreamAsync as Mt, metroPortSetting as N, podsOutOfSync as Nt, maintenanceKeepSetting as O, listCarryableIgnoredEntries as Ot, metroTunnelSettingError as P, readWorktreeExclude as Pt, resolveSettings as Q, filesystemDevice as Qt, projectSettingsContext as R, resolveFullRef as Rt, iosSigningIdentitySetting as S, gitCommonDirOnDisk as St, iosSigningIdentitySha1SettingError as T, hasUncommittedWorkAsync as Tt, remoteAndroidSetting as U, unpushedCommitsAsync as Ut, readCommittedSettings as V, restoreFileAsync as Vt, remoteEasFallbackSetting as W, warmWorktreePaths as Wt, resolveProjectSettings as X, moveIgnoredTreesToTrash as Xt, resolveIosProjectDir as Y, disposeTrash as Yt, resolveProjectSettingsAsync as Z, restoreTrashedTrees as Zt, inertSettingWarning as _, depsOutOfSync as _t, SETTING_SHAPE_REMEDY as a, settingsLayers as at, iosProjectDirSetting as b, gitCommonDir as bt, androidDataPartitionSizeBytes as c, webSettings as ct, androidLayoutSetting as d, detectProviders as dt, removeTemporaryEntry as en, settingFile as et, androidLayoutSettingError as f, planMetroReach as ft, deviceReclaimIdleMinutesSetting as g, deleteBranchAsync as gt, deviceIdleShutdownMinutesSetting as h, cloneIgnoredEntries as ht, SETTINGS_WITH_RESOLVE_TIME_FALLBACK as i, settingValueAt as it, metroCommandSettingError as j, locallyKnownUpstream as jt, mergeSettingsLayers as k, listWorktrees as kt, androidDataPartitionSizeGbSetting as l, workspaceHiddenSetting as lt, defaultAndroidLayout as m, branchExistsAsync as mt, METRO_COMMAND_PORT as n, temporaryRoot as nn, settingOriginScope as nt, androidAvdConfigSetting as o, tunnelModeSetting as ot, cacheProviderSettingError as p, resolveTailscaleBinary as pt, resolveAndroidLayout as q, TRASH_MANIFEST as qt, PATH_SETTINGS as r, settingShapeErrors as rt, androidAvdConfigSettingError as s, unknownSettingKeys as st, ANDROID_AVD_CONFIG_HELP as t, removeTemporaryEntryAsync as tn, settingOrigin as tt, androidDataPartitionSizeGbSettingError as u, PUBLIC_METRO_ENV as ut, iosLanHostSetting as v, dirtyFingerprintFiles as vt, iosSigningIdentitySha1Setting as w, hasRemoteAsync as wt, iosProjectDirSettingError as x, gitCommonDirAsync as xt, iosLanHostSettingError as y, dirtyPathsAsync as yt, projectSettingsContextAsync as z, resolveFullRefAsync as zt };
@@ -1,5 +1,6 @@
1
- import { a as layerFile, c as settingEntry, i as SettingsRefusal, n as readScope, o as readSettingsContext, r as requireSetting, s as readSettingsPayload, t as mutateSetting } from "./settings-write-QjYfSrjF.mjs";
2
- import { SETTING_SCOPES } from "@stim-cli/core/state";
1
+ import { c as readSettingsPayload, l as settingEntry, o as layerFile, s as readSettingsContext, t as SettingsRefusal } from "./settings-payload-cm60Zhib.mjs";
2
+ import { i as unsetReplacedSetting, n as readScope, r as requireSetting, t as mutateSetting } from "./settings-write-BdNRLlBn.mjs";
3
+ import { REPLACED_SETTINGS, SETTING_SCOPES } from "@stim-cli/core/state";
3
4
  import chalk from "chalk";
4
5
  //#region src/commands/settings.ts
5
6
  function formatValue(value) {
@@ -45,7 +46,7 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
45
46
  const shown = entry.origin === null ? "" : formatValue(entry.value);
46
47
  io.out(`${entry.key.padEnd(width)} ${shown}${shown ? " " : ""}${chalk.dim(`(${formatOrigin(entry)})`)}`);
47
48
  }
48
- for (const entry of payload.unknown) io.note(chalk.yellow(`Warning: ${entry.key} in ${entry.file} is not read by Stim.`));
49
+ for (const entry of payload.unknown) io.note(chalk.yellow(`Warning: ${entry.key} in ${entry.file} is not read by Stim.${entry.replacement ? ` Run \`${entry.replacement}\` instead.` : ""}`));
49
50
  }));
50
51
  settings.command("get <key>").description("Print the effective value of a setting, or its value in one layer").option("--scope <scope>", `read one layer: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the setting entry as JSON").action((key, opts, command) => run(wantsJson(opts, command), io, async () => {
51
52
  const setting = requireSetting(key);
@@ -80,6 +81,18 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
80
81
  report(io, wantsJson(opts, command), result, "set");
81
82
  }));
82
83
  settings.command("unset <key>").description("Remove a setting from one layer").option("--scope <scope>", `the layer to clear: ${SETTING_SCOPES.join(", ")}`).option("--json", "print the setting after removal as JSON").action((key, opts, command) => run(wantsJson(opts, command), io, async () => {
84
+ if (Object.hasOwn(REPLACED_SETTINGS, key)) {
85
+ const removal = await unsetReplacedSetting({
86
+ key,
87
+ scope: opts.scope
88
+ }, {
89
+ cwd: process.cwd(),
90
+ env,
91
+ note: io.note
92
+ });
93
+ reportRemoval(io, wantsJson(opts, command), removal, opts.scope);
94
+ return;
95
+ }
83
96
  const result = await mutateSetting({
84
97
  action: "unset",
85
98
  key,
@@ -92,6 +105,14 @@ function registerSettings(program, io = CONSOLE, env = process.env) {
92
105
  report(io, wantsJson(opts, command), result, "unset");
93
106
  }));
94
107
  }
108
+ function reportRemoval(io, json, removal, scope) {
109
+ if (json) {
110
+ io.out(JSON.stringify(removal));
111
+ return;
112
+ }
113
+ for (const { file } of removal.removed) io.out(`unset ${removal.key} in ${file}`);
114
+ if (removal.removed.length === 0) io.out(`${removal.key} was not set in ${scope ? `the ${scope} layer` : "any layer"}.`);
115
+ }
95
116
  function report(io, json, result, verb) {
96
117
  const { setting: entry, recordingsDeleted, ...write } = result;
97
118
  if (json) {