stim 1.17.2 → 1.18.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 (150) hide show
  1. package/README.md +50 -1
  2. package/dist/{activity-IRvJY_ru.mjs → activity-BxnkDZDi.mjs} +4 -4
  3. package/dist/{agent-device-usage-output-BK41vnzN.mjs → agent-device-usage-output-CZ66YA4T.mjs} +8 -8
  4. package/dist/android-BKA16DTf.mjs +4 -0
  5. package/dist/{android-B9yaNKwa.mjs → android-BvwuMUJ9.mjs} +192 -98
  6. package/dist/{android-DE4v59Mb.mjs → android-CBwCNicO.mjs} +2 -2
  7. package/dist/{android-B_YNZy61.mjs → android-DC3ZLuw0.mjs} +9 -9
  8. package/dist/{android-cas-ZFpjJBL_.mjs → android-cas-BBFyr9CA.mjs} +5 -5
  9. package/dist/android-cas-compiler.mjs +2 -2
  10. package/dist/api-D0VtFhqk.mjs +152 -0
  11. package/dist/api-run.d.mts +1 -0
  12. package/dist/api-run.mjs +145 -0
  13. package/dist/api.d.mts +212 -0
  14. package/dist/api.mjs +2 -0
  15. package/dist/{app-install-VPkI5WEg.mjs → app-install-D-PUENug.mjs} +3 -3
  16. package/dist/{attempt-Bk2ouQVL.mjs → attempt-DW-mQqM7.mjs} +14 -4
  17. package/dist/{budget-DfcgFdQB.mjs → budget-DIhL2BKx.mjs} +1578 -58
  18. package/dist/build-facts-DcLv2HSd.d.mts +111 -0
  19. package/dist/{cache-manifest-DnUHBJaU.mjs → cache-manifest-BI7ozfmH.mjs} +3 -3
  20. package/dist/cache-manifest.mjs +1 -1
  21. package/dist/{chrome-BrcVWQyD.mjs → chrome-DJnmnS5q.mjs} +1 -1
  22. package/dist/cli-DNJMwADx.mjs +68 -0
  23. package/dist/cli.mjs +1 -1
  24. package/dist/{client-SvBdgObD.mjs → client-DzhapoMB.mjs} +139 -32
  25. package/dist/collector-run.mjs +9 -9
  26. package/dist/{command-output-CDAIFD-8.mjs → command-output-CBtzyIgF.mjs} +2 -2
  27. package/dist/{config-D0DbpZtM.mjs → config-CgYMahz7.mjs} +5 -5
  28. package/dist/{created-devices-CpvzBL25.mjs → created-devices-DKbeWsiK.mjs} +2 -2
  29. package/dist/{dependency-state-CLcBHH2M.mjs → dependency-state-xKoOypBm.mjs} +2 -2
  30. package/dist/{detached-entry-CiTEgMR1.mjs → detached-entry-BLfcgc4O.mjs} +1 -1
  31. package/dist/{dev-client-B-XC4uRH.mjs → dev-client-CLnIH02x.mjs} +2 -2
  32. package/dist/{device-C8IOoJPv.mjs → device-D7oCHGWi.mjs} +8 -8
  33. package/dist/{device-capacity-ZC4XSZ4R.mjs → device-capacity-EUOOYr8T.mjs} +13 -13
  34. package/dist/device-host-worker.mjs +19 -19
  35. package/dist/{device-ios-C2Um-XUR.mjs → device-ios-6MewKKnc.mjs} +13 -13
  36. package/dist/{device-lease-DpoS36_u.mjs → device-lease-Co-EwifR.mjs} +9 -9
  37. package/dist/{device-lease-run-B8YltIH_.mjs → device-lease-run-w1xhCqIW.mjs} +4 -4
  38. package/dist/{device-pool-3o7s5lo4.mjs → device-pool-F5WvRPtD.mjs} +3 -3
  39. package/dist/{device-remote-hFSkpfQu.mjs → device-remote-tHbd1fKy.mjs} +15 -15
  40. package/dist/{doctor-CFv1fCrF.mjs → doctor-B9ckYUoU.mjs} +33 -30
  41. package/dist/{error-diagnostics-C-NMnhrk.mjs → error-diagnostics-BRXOqDzG.mjs} +11 -11
  42. package/dist/{exec-CaErVv7t.mjs → exec-DWhCZDGm.mjs} +65 -2
  43. package/dist/{gc-DEmkg3Xh.mjs → gc-Dh6mXOKC.mjs} +23 -469
  44. package/dist/{gradle-dJpre3Yn.mjs → gradle-C6GKnunQ.mjs} +6 -6
  45. package/dist/{guide-status-Du-ZQ3FD.mjs → guide-status-Bhf9SJXc.mjs} +3 -3
  46. package/dist/{guide-CSmhMTf8.mjs → guide-tm6igAaa.mjs} +290 -53
  47. package/dist/{hosted-android-E1Heoqnv.mjs → hosted-android-Bv285t_t.mjs} +3 -3
  48. package/dist/{hosted-client-Bp4knSwu.mjs → hosted-client-C-rMtppF.mjs} +2 -2
  49. package/dist/{hosted-ios-BnbeYOUD.mjs → hosted-ios-D5mNmtj4.mjs} +1 -1
  50. package/dist/{hosted-logs-OcgIBvCT.mjs → hosted-logs-DN8Iz4mJ.mjs} +9 -9
  51. package/dist/{hosted-macos-DcxKjtfH.mjs → hosted-macos-B-wEjlwG.mjs} +5 -5
  52. package/dist/{hosted-native-1Ebbig4w.mjs → hosted-native-DeeOG8xZ.mjs} +6 -6
  53. package/dist/{idle-shutdown-IGyNV8Cr.mjs → idle-shutdown-jjtxAn5C.mjs} +7 -8
  54. package/dist/{ios-DSfnPfse.mjs → ios-B3SbOWdw.mjs} +19 -7
  55. package/dist/{ios-Cr1h5gnO.mjs → ios-Bvbf0SGY.mjs} +1 -1
  56. package/dist/{ios-BJ4XUSe1.mjs → ios-CPdkoKaa.mjs} +181 -95
  57. package/dist/ios-DNpdygiv.mjs +7 -0
  58. package/dist/{ios-device-Ee7sDXfp.mjs → ios-device-Bn7jWDB1.mjs} +1 -1
  59. package/dist/{ios-device-pAN4t54-.mjs → ios-device-vOaByMhw.mjs} +3 -3
  60. package/dist/{ios-state-8L3lgum6.mjs → ios-state-B2pES6Vs.mjs} +1 -1
  61. package/dist/{launch-verify-lTnWZikR.mjs → launch-verify-hskNcWkZ.mjs} +5 -5
  62. package/dist/{logs-BAaS7gS2.mjs → logs-1Ylc1Ri6.mjs} +13 -13
  63. package/dist/macos-Ck7OBMNY.mjs +2 -0
  64. package/dist/{macos-BIRQS90f.mjs → macos-DF6C7wUU.mjs} +118 -34
  65. package/dist/macos-run.mjs +1 -1
  66. package/dist/maintenance-run.mjs +349 -47
  67. package/dist/{metro-g8NqiJp-.mjs → metro-Dh8T4Ytd.mjs} +5 -5
  68. package/dist/{metro-gateway-C-ijGI2F.mjs → metro-gateway-CEUw9RMH.mjs} +4 -4
  69. package/dist/{metro-store-CDDZHtPl.mjs → metro-store-BAHFcJm6.mjs} +16 -2
  70. package/dist/{named-ports-C8m8EQs2.mjs → named-ports-BFIz1Shz.mjs} +61 -6
  71. package/dist/{native-run-D1Q56rAD.mjs → native-run-B06FkmZx.mjs} +4 -4
  72. package/dist/{native-runtime-BEK171xQ.mjs → native-runtime-D_603JiC.mjs} +6 -6
  73. package/dist/{ndjson-PclOIwVY.mjs → ndjson-LGZAMsqa.mjs} +8 -4
  74. package/dist/offload-worker.d.mts +3 -17
  75. package/dist/offload-worker.mjs +10 -11
  76. package/dist/{ownership-DyRQru0q.mjs → ownership-D6Se7gg_.mjs} +3 -3
  77. package/dist/{page-QF_Ke10s.mjs → page-Bv9s2KwY.mjs} +1 -1
  78. package/dist/placement-log-BcPhRwR4.mjs +84 -0
  79. package/dist/{build-plan-BDsSi09V.mjs → plan-placement-CtxkCO54.mjs} +122 -48
  80. package/dist/{ports-4nYqxPWC.mjs → ports-BLTtfBq-.mjs} +3 -3
  81. package/dist/{prebuild-D7RUMkwN.mjs → prebuild-juCyreaR.mjs} +5 -5
  82. package/dist/preview-D5V07Nrl.mjs +987 -0
  83. package/dist/{rolldown-runtime-BsOwBuO_.mjs → process-identity-Biv3arCO.mjs} +11 -1
  84. package/dist/{project-D47Rh0ly.mjs → project-C3ChRLZy.mjs} +4 -68
  85. package/dist/projects-DD7dBTCj.mjs +92 -0
  86. package/dist/{pull-request-pxnDCQzn.mjs → pull-request-u4vp7zmK.mjs} +1 -1
  87. package/dist/pull-requests.mjs +1 -1
  88. package/dist/{recordings-BNgsD1Tr.mjs → recordings-BAWltsVt.mjs} +1 -1
  89. package/dist/{reload-DcRxj3qG.mjs → reload-DvyWzVjJ.mjs} +15 -15
  90. package/dist/{remote-cache-Ci4DQYYj.mjs → remote-cache-BGg7aGIZ.mjs} +5 -5
  91. package/dist/{run-CkE9y0nc.mjs → run-vhtDgpHO.mjs} +5 -5
  92. package/dist/{server-bare-BkrSxSsZ.mjs → server-bare-B9E7S1aR.mjs} +4 -5
  93. package/dist/server-expo-Db9HBUoa.mjs +2 -0
  94. package/dist/{server-expo-CHTyXD0G.mjs → server-expo-DoBHhuzK.mjs} +5 -6
  95. package/dist/{settings-SR9OmW9h.mjs → settings-Byp2AQ_E.mjs} +6 -5
  96. package/dist/{settings-Cfd-0r2d.mjs → settings-CQyMElEP.mjs} +24 -763
  97. package/dist/{settings-BBpMcDbD.mjs → settings-Djl-mpjX.mjs} +1 -1
  98. package/dist/settings.schema.json +126 -3
  99. package/dist/{simslim-BWNrc3M3.mjs → simslim-EHBQ2R4G.mjs} +7 -7
  100. package/dist/{slot-launch-DmjBmpQV.mjs → slot-launch-C1nqh4mu.mjs} +6 -6
  101. package/dist/{spawn-claims-D0XfSe8u.mjs → spawn-claims-Kqiifsk2.mjs} +1 -1
  102. package/dist/{spawn-entry-jw19m8Nl.mjs → spawn-entry-Dcb7sDUz.mjs} +1 -0
  103. package/dist/{stage-CzaiwFsI.mjs → stage-g_WqWeaE.mjs} +14 -3
  104. package/dist/{start-DUz3mYdb.mjs → start-D-IeOyoK.mjs} +19 -19
  105. package/dist/{start-AlfCPRVU.mjs → start-NTc1Ifqs.mjs} +1 -1
  106. package/dist/{state-PeQiJuIu.mjs → state-BG-aAk4k.mjs} +4 -4
  107. package/dist/{state-B4PQFXMW.d.mts → state-lKh8shBp.d.mts} +2 -3
  108. package/dist/{state-DyaNTgfR.mjs → state-xnqpx3AD.mjs} +2 -2
  109. package/dist/{stats-Bq4fJOdB.mjs → stats-DY6ekz8F.mjs} +5 -5
  110. package/dist/{status-DlKvVJBE.mjs → status-BEeL6IKz.mjs} +6 -4
  111. package/dist/{status-BA2pehwf.mjs → status-DCjZeE-K.mjs} +33 -34
  112. package/dist/{status-CzS4bPO9.mjs → status-Dcr0Qexd.mjs} +5 -5
  113. package/dist/{stim-desktop-Cnz8CPnl.mjs → stim-desktop-Behws_fi.mjs} +1 -1
  114. package/dist/{stim-installations-QMEI32v1.mjs → stim-installations-aR_WsNOA.mjs} +1 -1
  115. package/dist/{stop-BIiM49EY.mjs → stop-BGhKMOuH.mjs} +5 -5
  116. package/dist/{stop-DQIasgKp.mjs → stop-BTjs3xbc.mjs} +17 -18
  117. package/dist/{stop-zF1y04f2.mjs → stop-DIJtD2GL.mjs} +2 -2
  118. package/dist/supervisor-run.d.mts +24 -22
  119. package/dist/supervisor-run.mjs +21 -22
  120. package/dist/{support-CsJNVfOc.mjs → support-BaayeYCf.mjs} +7 -7
  121. package/dist/{support-WvD__tSV.mjs → support-Bwvbrq5-.mjs} +5 -5
  122. package/dist/{toolchain-DNyR3NPq.mjs → toolchain-Bnyd_K3A.mjs} +471 -22
  123. package/dist/{trigger-Bemu8ytw.mjs → trigger-CJMhwXe8.mjs} +5 -5
  124. package/dist/trigger-DWAq9hkw.mjs +2 -0
  125. package/dist/{warm-progress-DF4JRvYI.mjs → warm-progress-CjB-MP6H.mjs} +7 -7
  126. package/dist/web-B6_bFDn7.mjs +2 -0
  127. package/dist/{web-Dl0KSRHf.mjs → web-DTU0uiWj.mjs} +22 -22
  128. package/dist/web-run.mjs +10 -10
  129. package/dist/{workspace-state-DqcCbpE7.mjs → workspace-state-C59dqG-Z.mjs} +3 -3
  130. package/dist/{ownership-BMLqyBgJ.mjs → workspaces-xXItD8Dj.mjs} +577 -23
  131. package/dist/{worktree-j3IcFAI5.mjs → worktree-BJfnU6r5.mjs} +1 -1
  132. package/dist/{worktree-Be_7NLKy.mjs → worktree-BSYlofkq.mjs} +234 -35
  133. package/dist/worktree-CsKYexJM.mjs +753 -0
  134. package/package.json +10 -5
  135. package/dist/build-progress-D0WkjCPd.mjs +0 -1036
  136. package/dist/build-slots-41v_d2x9.mjs +0 -142
  137. package/dist/cli-CYXb29oE.mjs +0 -51
  138. package/dist/deps-iKw0eD4P.mjs +0 -438
  139. package/dist/errors-B6W7FkxQ.mjs +0 -15
  140. package/dist/idle-BXG__1BA.mjs +0 -176
  141. package/dist/in-use-CvGOUn-x.mjs +0 -130
  142. package/dist/preview-B-g9d7kV.mjs +0 -318
  143. package/dist/process-identity-BmRm1qV0.mjs +0 -12
  144. package/dist/server-expo-CeakhI8P.mjs +0 -2
  145. package/dist/state-BKa8wNN5.mjs +0 -148
  146. package/dist/stop-cause-rhmGfwvt.mjs +0 -97
  147. package/dist/trigger-CXts6qt1.mjs +0 -2
  148. package/dist/watchman-APYjXSQa.mjs +0 -48
  149. package/dist/workspace-process-lock-2mNzOlaB.mjs +0 -58
  150. package/dist/workspaces-Bcib97-6.mjs +0 -306
@@ -1,7 +1,7 @@
1
- import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-Cfd-0r2d.mjs";
2
- import { s as findProjectRoot$1 } from "./project-D47Rh0ly.mjs";
3
- import { t as RECENT_LAUNCH_MS } from "./status-CzS4bPO9.mjs";
4
- import { t as guideStatus } from "./guide-status-Du-ZQ3FD.mjs";
1
+ import { s as findProjectRoot$1 } from "./project-C3ChRLZy.mjs";
2
+ import { t as RECENT_LAUNCH_MS } from "./status-Dcr0Qexd.mjs";
3
+ import { t as ANDROID_AVD_CONFIG_HELP } from "./settings-CQyMElEP.mjs";
4
+ import { t as guideStatus } from "./guide-status-Bhf9SJXc.mjs";
5
5
  import { SETTINGS, SETTINGS_SCHEMA_URL } from "@stim-cli/core/state";
6
6
  import chalk from "chalk";
7
7
  //#region src/guide/agent.ts
@@ -293,6 +293,11 @@ Ask the user before these actions:
293
293
  nothing else.
294
294
  - gc --delete --worktrees, because it runs worktree remove on every clean,
295
295
  idle linked worktree Stim manages, across projects.
296
+ - settings set maintenance.mode on in a home where it is off or report, because
297
+ it lets Stim itself clear build outputs, trim caches and remove finished
298
+ worktrees later, with no command from you. It is on by default outside CI
299
+ and scoped STIM_HOME homes. maintenance.keep true pins a workspace against
300
+ that; maintenance.mode report or off stops it.
296
301
  - stop when the workspace owns an EAS session, because it irreversibly ends
297
302
  that remote session. For a local device, stop shuts it down but does not
298
303
  delete it. An explicit stop shuts down a Stim-owned simulator even when
@@ -382,6 +387,7 @@ FULL TOPIC LIST
382
387
  stim guide lifecycle options # every flag, Android variants, --device-type, --system-image, --device-profile
383
388
  stim guide lifecycle devices # ios --device and android --device on a physical phone
384
389
  stim guide lifecycle release # Release configurations and ...Release variants
390
+ stim guide api # typed run, stop, diagnostics and cancellation from the main package
385
391
  stim guide facts # the --json payloads
386
392
  stim guide facts devmenu # the Expo dev menu or Tools button over the app
387
393
  stim guide macos # Swift Package Debug apps, logs, local preview, --remote on another Mac
@@ -397,6 +403,64 @@ FULL TOPIC LIST
397
403
  stim guide settings # configuration files and supported keys`
398
404
  };
399
405
  //#endregion
406
+ //#region src/guide/api.ts
407
+ var api_default = {
408
+ summary: "Typed lifecycle API: createStim, run, stop, diagnostics, and cancellation",
409
+ body: () => `PROGRAMMATIC API
410
+
411
+ Install stim as a project dependency: npm install --save-dev stim.
412
+ Import { createStim, StimError } from 'stim'. Node 22.12 or later is required.
413
+
414
+ const stim = createStim({ projectRoot: process.cwd() });
415
+ try {
416
+ const result = await stim.run({ platform: 'ios' });
417
+ } finally {
418
+ try {
419
+ const diagnostics = await stim.diagnostics({ errors: true });
420
+ } finally {
421
+ const cleanup = await stim.stop();
422
+ if (!cleanup.ok) throw new Error(cleanup.summary);
423
+ }
424
+ }
425
+
426
+ createStim takes projectRoot, optional absolute home and buildCache paths,
427
+ and onProgress({ stream, message }). message is an output chunk. Without
428
+ onProgress, operations write nothing to the caller's stdout or stderr. Each
429
+ operation uses a bundled worker that calls the same lifecycle operations as
430
+ the CLI; it never parses CLI arguments or changes the caller's cwd/environment.
431
+
432
+ run takes platform plus its options:
433
+ ios: configuration, scheme, deviceType, runtime
434
+ android: variant, systemImage, deviceProfile
435
+ macos: remoteBuild
436
+ web: headed (default false)
437
+ iOS and Android also accept slot, metroCheck, buildCache, and remoteBuild.
438
+ All methods accept signal. run builds, installs and launches; build-only is
439
+ not available. Web requires a running server, just like stim web.
440
+
441
+ run returns { platform, facts }. iOS facts include udid; Android includes
442
+ serial; both include bundleId, appPath, metroPort, cacheHit and launched.
443
+ macOS facts include bundle, bundleId, executable, pid, build and launched.
444
+ Web facts contain the owned browser's existing launch and page facts.
445
+ Do not interpret 'bundling' or 'unverified' as proven application readiness.
446
+
447
+ stop({ slot? }) returns { ok, outcomes, summary }. It acts on the workspace,
448
+ including resources from earlier runs. Use a dedicated workspace in CI.
449
+ Cancellation waits for the operation worker to exit; stop with a fresh signal
450
+ after cancellation or partial failure. Always inspect cleanup.ok.
451
+
452
+ diagnostics({ tail: 200, errors: false }) returns { directory, records } from
453
+ the local timeline, even before a successful run. tail: 0 returns paths only.
454
+ It does not fetch remote logs or capture new crashes. Stim failures reject with
455
+ StimError carrying code, message, remedy and details (including the log path).
456
+ An exception thrown by onProgress cancels its worker and propagates unchanged.
457
+
458
+ Normal ownership, device creation, cache locks and coordination remain active.
459
+ All concurrent artifact-cache writers must share the same coordinating home.
460
+ Do not point independent Stim homes at a concurrently writable shared cache.
461
+ `
462
+ };
463
+ //#endregion
400
464
  //#region src/guide/facts.ts
401
465
  const facts = {
402
466
  summary: "The --json payloads: `start`, `ios`, `android`, `web`, `ios|android --plan`, `reload`, `stop`, `status`, `doctor`, `device lock`/`unlock`, `gc`, and the error contract",
@@ -945,7 +1009,7 @@ leased until <time>" for each one.`,
945
1009
  reasons as { code, reason } with that code. capacity
946
1010
  is the machine's offer: { running, max, diskFreeBytes,
947
1011
  minDiskFreeBytes, cpus?, loadPerCore?, builds?, maxBuilds?,
948
- maxLoadPerCore?, declined? }; an older stim-server omits the
1012
+ maxLoadPerCore?, memoryUsedBytes?, memoryTotalBytes?, declined? }; an older stim-server omits the
949
1013
  optional fields
950
1014
  findings the diagnostic findings; a lower resolved Stim is a
951
1015
  costs-time finding with a PATH or installation remedy
@@ -1203,7 +1267,7 @@ RULES
1203
1267
  cannot read. A macOS privacy denial (EPERM) names the
1204
1268
  Privacy & Security setting to grant
1205
1269
  maintenance top-level { mode, pressure, actions, blocked,
1206
- skips, note, invalid? }, the next report-only maintenance plan
1270
+ skips, note, invalid? }, the next maintenance plan
1207
1271
  from live pressure and cached sizes. note says when no
1208
1272
  pass has run yet. No du runs for this preview.
1209
1273
  sections one array per report section, in the text order. Every key
@@ -1692,7 +1756,8 @@ RULES
1692
1756
  with detail), install (staging the bundle, or fetching
1693
1757
  it from a build machine) and launch. It has no cache
1694
1758
  lookup: outcome is null, plannedPhases is null, and
1695
- builds.macos holds its finished runs and their phases.
1759
+ builds.macos holds its finished runs, their phases and
1760
+ compileSteps.
1696
1761
  startedAt when the run started; phaseStartedAt when its phase did
1697
1762
  outcome "cold" after the local/provider lookups resolve a miss;
1698
1763
  "hit" after a cached artifact is ready to reuse, including
@@ -1957,13 +2022,15 @@ RULES
1957
2022
  and always uses the estimate. What is using CPU and memory now is the
1958
2023
  top-level machine section:
1959
2024
 
1960
- maintenance { mode, lastChecks: { pressure, size }, pressure, sizes,
2025
+ maintenance { mode, lastChecks: { pressure, size, worktree, sweep }, pressure, sizes,
1961
2026
  lastPass, running, recent, plan, invalid?, claim? }
1962
- Report-only observations; every plan action's kind starts with would-.
2027
+ mode is off, report or on. Plan actions start with would-; the records
2028
+ of actions taken drop the prefix (clear-outputs, trim-cache, empty-cache,
2029
+ remove-worktree, remove-orphan, unregister-cache).
1963
2030
  lastChecks are epoch milliseconds or null. running comes only from a
1964
2031
  live maintenance/run.claims owner, never from a check stamp.
1965
- lastPass carries startedAt, durationMs, trigger, mode, freedBytes (0),
1966
- actions, stopped (0), blocked. recent holds the last 20 action, failure
2032
+ lastPass carries startedAt, durationMs, trigger, mode, freedBytes
2033
+ (0 in report mode), actions, stopped (0), blocked. recent holds the last 20 action, failure
1967
2034
  and blocked NDJSON records from maintenance/maintenance.ndjson.
1968
2035
  invalid names invalid settings; invalid cache caps use their defaults,
1969
2036
  while invalid maintenance settings disable passes. claim contains an
@@ -2018,7 +2085,7 @@ RULES
2018
2085
 
2019
2086
  { platform, slot?, fingerprint, cacheKey, cacheHit, provider,
2020
2087
  cacheSkipped, prebuild, outcome, expectedMs, basis, missReason?,
2021
- refusal? }
2088
+ placement?, refusal? }
2022
2089
 
2023
2090
  fingerprint the fingerprint the run would look up first; with
2024
2091
  --eas-profile, the one EAS CLI computes
@@ -2044,6 +2111,9 @@ RULES
2044
2111
  plan does not, so changes compare the fingerprint before that
2045
2112
  prebuild; changeCount 0 then means those inputs match the
2046
2113
  baseline. rekeyedBy is empty.
2114
+ placement with ios.remote or android.remote set to auto or a Mac,
2115
+ where the plan assumes the device runs: "on <machine>" or
2116
+ "this Mac; auto may use <machines>"; absent otherwise
2047
2117
  refusal { code, message, remedy } when the run would refuse:
2048
2118
  STIM_PREBUILD_FAILED for a tracked native dir the fingerprint
2049
2119
  leaves out, STIM_EAS_BUILD_MISSING for an EAS miss
@@ -2646,7 +2716,7 @@ FLAGS
2646
2716
  --slot <name> only this slot's records plus, once it has launched, the
2647
2717
  shared untagged Metro and app client records (not the web
2648
2718
  page's); default also includes untagged legacy records
2649
- --source <s...> metro, client, device, build, agent, maintenance (one or more), or all.
2719
+ --source <s...> metro, client, device, build, agent, maintenance, placement (one or more), or all.
2650
2720
  An unknown value is REJECTED rather than quietly matching
2651
2721
  nothing.
2652
2722
  --level <l> minimum level: debug, info, warn, error, fatal
@@ -2783,6 +2853,12 @@ THE RECORD
2783
2853
  event the producer's own event name (bundle_build_done, client_log, ...)
2784
2854
  stack frames of { file, line, column, fn }, passed through as reported
2785
2855
  marker true on the records that close an error window
2856
+ runId the id of the stim invocation that wrote the record: STIM_RUN_ID
2857
+ when set to a valid id (letters, digits, . _ -, at most 64),
2858
+ else generated per run. Processes a command starts, such as the
2859
+ Metro supervisor and the collectors, keep the id of the command
2860
+ that started them. Debug records and the hello to stim-server
2861
+ carry it too, and stim-server puts it on its log lines.
2786
2862
  deviceTs Android logcat's original epoch milliseconds; ts is aligned to
2787
2863
  host time using a bounded clock query at each collector attachment
2788
2864
  clockOffsetMs the offset added to deviceTs; absent if the query failed.
@@ -2800,6 +2876,59 @@ Add --errors to --source maintenance to show only maintenance_failure events;
2800
2876
  failures before a later launch marker are hidden. Machine passes are reported in
2801
2877
  status and maintenance/maintenance.ndjson; this command reads workspace logs.
2802
2878
 
2879
+ REMOTE REQUEST RECORDS
2880
+ A request to another Mac that fails is a warn record with src: build in the
2881
+ run's build log: remote_connect_failed { host, capability, ms, timeoutMs, msg,
2882
+ code } (could not connect or say hello, e.g. "no reply in time" when the Mac
2883
+ did not answer hello) and remote_request_failed { method, ms, code, msg }.
2884
+ Timings of requests that succeed are debug records (below).
2885
+ stim-server writes to its service log (~/Library/Logs/Stim/<label>.log), with
2886
+ no tokens or tickets: "request failed method=<m> client=<device id> run=<runId>
2887
+ ms=<n> error=<code>" for an error reply (once a minute per client, method and
2888
+ code) and "host_connect ... error=<reason_with_underscores>" when its connection to a hosting
2889
+ Mac fails. With debug.logs on or STIM_DEBUG=1 for the server it logs every
2890
+ request instead: "debug request method=<m> client=<id> run=<runId> ms=<n>
2891
+ slow=true error=<code> whois=<ms> probe=<ms>" (slow means 1000 ms or more;
2892
+ whois and probe are the hello's Tailscale identity lookup and its wait for
2893
+ the host permission probe; a method name that is not a plain dotted lowercase
2894
+ name is logged as unknown)
2895
+ and "debug host_connect host=<mac> ms=<n> connectMs=<n> helloMs=<n>" (reused=true instead of the two
2896
+ timings when an open connection was shared), also as
2897
+ records in STIM_HOME/logs/debug/server.ndjson. Search the run id in both logs.
2898
+
2899
+ DEBUG LOGS
2900
+ With debug.logs on or STIM_DEBUG=1 (stim guide settings), the CLI also appends
2901
+ debug records to STIM_HOME/logs/debug/cli.ndjson, outside any workspace, so
2902
+ stim logs does not show them. Read them with jq:
2903
+ jq -c 'select(.event=="exec" and .ms>1000)' ~/.stim/logs/debug/cli.ndjson
2904
+ Events: run_start, run_end { exit, ms }, exec { program, ms, ok, exit? }, and
2905
+ remote_connect and remote_request { ms, ok, code? } for requests to another
2906
+ Mac. They carry no arguments, tokens or tickets.
2907
+
2908
+ Placement records use src: placement and sit in the run's build log
2909
+ (build-*.ndjson), so a new run replaces the previous run's. A run writes one
2910
+ record per decision it makes (a build that compiles and has a remote Mac to
2911
+ consider, or ios/android --remote auto), with event build_placement,
2912
+ device_placement or placement_fallback. A cache hit, a project with no paired
2913
+ remote Mac and a named --remote target write none:
2914
+ stim logs --source placement
2915
+ stim logs --source placement --json
2916
+ Fields: kind (build or device), platform, settings [{ key, value, from }] with
2917
+ from flag, env, setting or default (remote.build and remote.buildMode for a
2918
+ build, ios.remote or android.remote for a device), candidates [{ machine, code,
2919
+ msg, detail? }], choice { machine, code, msg } with machine local when the run
2920
+ stays on this Mac, and fallback { code, msg, machine? } when a remote Mac that
2921
+ was meant to take the run did not (level warn). The msg is the same text the
2922
+ placement: and build: phase lines print.
2923
+ Candidate codes: accepted, unreachable, busy, disk, load, version-mismatch
2924
+ (detail lists the toolchain parts: xcode, arch, jdk, ...), no-matching-device,
2925
+ declined, memory, no-capacity. Choice codes for a build: placed, named,
2926
+ forced, this-mac-busy, this-mac-free, mode-off, local-selected, no-remote-mac,
2927
+ unsupported; fallback codes: no-remote-mac-took-it, offload-failed, fallback.
2928
+ Choice codes for a device: placed, sticky, this-mac-free, no-remote-mac,
2929
+ device-count-unknown, no-host-admits. Machine names appear in these records;
2930
+ they stay in the local logs. These records carry no tokens.
2931
+
2803
2932
  WHAT WRITES WHAT
2804
2933
  maintenance.ndjson workspace maintenance actions, failures and explaining skips
2805
2934
  metro.ndjson the bundler, in both supervisor modes
@@ -3005,6 +3134,9 @@ Branch on the code, never on the message.`,
3005
3134
  an unavailable choice. A session that exists stays recorded even if delivery
3006
3135
  fails: retry stim ios|android --remote <machine>, or run stim stop to reconcile it.
3007
3136
  An unreachable stop keeps the placement; rerun stim stop when the host answers.
3137
+ To see why a host was slow or refused: stim logs --source placement (hosts checked and
3138
+ reason codes), stim logs --source build (remote_connect_failed, remote_request_failed),
3139
+ and the host's stim-server service log, searched for the run id (stim guide logs).
3008
3140
  A failed build handoff uses upload instead. If native log queries are unavailable,
3009
3141
  logs prints a note on stderr and shows copied records. Update an older stim-server
3010
3142
  on the host to enable handoff and native logs (hello features hosted-ios-data
@@ -4397,7 +4529,12 @@ not on any remote" (worktree remove)
4397
4529
  Warm copied ignored Pods from the source checkout, but their Manifest.lock
4398
4530
  differs from the tracked Podfile.lock in this worktree. Warm does not change
4399
4531
  tracked files. Run the printed pod-install command before building directly.
4400
- \`stim ios\` detects a mismatch and runs \`pod install\` for you.
4532
+ \`stim ios\` detects a mismatch and runs \`pod install\` for you. A mismatch
4533
+ limited to checksums of podspecs that embed the source checkout's path is
4534
+ resolved by warm itself ("carry moved <dir>/Pods to this checkout's path")
4535
+ and does not print this line. When the locks match but Pods still name the
4536
+ source path and warm cannot move it, it prints "removed <dir>/Pods/Manifest.lock
4537
+ so pod install runs" and \`stim ios\` runs \`pod install\`.
4401
4538
 
4402
4539
  "carry carried <dir>/Pods but there is no <dir>/Podfile.lock"
4403
4540
  Warm copied Pods but the destination has no Podfile.lock. Follow the printed
@@ -4523,6 +4660,22 @@ not on any remote" (worktree remove)
4523
4660
  Expo build-cache provider would each use a different store. Set the named
4524
4661
  variable to an absolute path, or unset it to use the default. Metro and the
4525
4662
  cache provider, which cannot refuse, ignore a relative value with a warning.`
4663
+ },
4664
+ STIM_WORKER_FAILED: {
4665
+ summary: "a programmatic API worker exited without returning an operation result",
4666
+ body: () => `STIM_WORKER_FAILED (programmatic API)
4667
+ The worker process ended without a structured result. StimError.details
4668
+ includes its final stderr output. Inspect that output and call diagnostics()
4669
+ for existing workspace logs, then stop() with a fresh signal to clean up
4670
+ any resources created before the failure. See stim guide api.`
4671
+ },
4672
+ STIM_RUN_FAILED: {
4673
+ summary: "a programmatic operation failed without a more specific Stim code",
4674
+ body: () => `STIM_RUN_FAILED (programmatic API)
4675
+ The underlying operation threw an error without a specific code. Its
4676
+ message and workspace log path are preserved in StimError. Read diagnostics()
4677
+ and call stop() in cleanup, including after a partial run. If the error is
4678
+ unexpected, report its message and logs at github.com/appandflow/stim/issues.`
4526
4679
  },
4527
4680
  STIM_NODE_UNSUPPORTED: {
4528
4681
  summary: "stim or stim-server started on a Node older than 22.12.0, often a project pin",
@@ -4986,6 +5139,8 @@ offload resolves later, after the device architecture is known.
4986
5139
  When no host admits, auto runs here and may wait in the existing FIFO device
4987
5140
  slot queue; --no-wait and --wait 0 refuse with STIM_AT_CAPACITY. The placement
4988
5141
  line explains the decision and the skipped hosts. JSON progress goes to stderr.
5142
+ The same decision, with a reason code per host, is a src: placement record in
5143
+ stim logs (stim guide logs).
4989
5144
  A recorded hosted session wins over load; a live local owned slot stays here.
4990
5145
  A stopped recorded session places again; unreachable or unknown sessions refuse.
4991
5146
 
@@ -5736,8 +5891,16 @@ PREDICTING THE NEXT BUILD (--plan)
5736
5891
  An Android plan reads the ABI from the emulator the slot records, or from
5737
5892
  the system image a new one would use. A plan refuses --device, --remote,
5738
5893
  --wait, --no-wait, --no-metro-check and --simulator-app with STIM_BAD_ARG.
5739
- Without --eas-profile it also refuses the ios.remote and android.remote
5740
- settings with STIM_BAD_ARG. Without --eas-profile an Android plan also
5894
+ With ios.remote or android.remote set to a Mac name, a plan reads the
5895
+ architecture or ABI from that Mac's device offer, the question a run asks
5896
+ before it reserves anything. With auto it repeats the placement decision a
5897
+ run would make now and reports where in the payload's placement field, for
5898
+ example "this Mac; auto may use janics-mac-mini". When the plan stays on
5899
+ this Mac and a listed Mac would build for another architecture, placement
5900
+ says so, since that Mac's key differs. The plan only predicts the key: a
5901
+ run reads the architecture of the device it actually gets. A Mac that does
5902
+ not answer, or ios.remote or android.remote set to eas or proxy, refuses
5903
+ with STIM_BAD_ARG. Without --eas-profile an Android plan also
5741
5904
  refuses the experimental compiler CAS with STIM_BAD_ARG, and refuses with
5742
5905
  STIM_NO_DEVICE when no system image is installed.
5743
5906
 
@@ -6493,6 +6656,24 @@ OPT-IN CONCURRENCY LIMITS (UNLIMITED BY DEFAULT)
6493
6656
  overlapping a nested destination worktree or below a symlink ancestor.
6494
6657
  Tracked .idea settings come from Git and stay untouched by warm.
6495
6658
 
6659
+ A carried ios/Pods still names the source checkout's path in its generated
6660
+ files and in the checksum of a podspec that embeds that path (the
6661
+ precompiled ExpoModulesCore). When ios/Podfile.lock and the carried
6662
+ ios/Pods/Manifest.lock differ only by those checksums, warm rewrites the
6663
+ source path to the worktree's path in Pods/Target Support Files,
6664
+ Pods.xcodeproj, Local Podspecs and absolute symlinks, then makes
6665
+ Manifest.lock equal Podfile.lock, so the first \`stim ios\` skips
6666
+ \`pod install\`. Any other difference, a missing podspec, or a podspec
6667
+ that does not embed the source path, any other file in Pods that names
6668
+ the source path, or carried node_modules that do not match the worktree's
6669
+ lockfile leaves Pods as copied, and \`pod install\` runs. Warm does not edit Podfile.lock.
6670
+
6671
+ When the two locks already match but the copied Pods still name the source
6672
+ path, warm applies the same rewrite and scan so builds do not read the
6673
+ source checkout's files (entitlements, Podfile.properties.json). If it
6674
+ cannot (stale node_modules, a leftover path, an error), warm deletes
6675
+ ios/Pods/Manifest.lock so \`stim ios\` runs \`pod install\`.
6676
+
6496
6677
  Other generated state stays eligible: .gradle, .cxx, *.tsbuildinfo, build
6497
6678
  directories, and embedded JavaScript need project-specific decisions about
6498
6679
  regeneration. Native intermediates can record the source checkout's paths;
@@ -7042,35 +7223,66 @@ $STIM_HOME/archive by default. See stim guide cleanup archive.
7042
7223
 
7043
7224
  MAINTENANCE
7044
7225
 
7045
- Automatic maintenance is report-only in this release: it measures, plans and
7046
- logs, and never stops or deletes resources. The default mode is report; it is
7047
- off in CI and scoped STIM_HOME homes unless STIM_MAINTENANCE is explicit.
7048
- Commands trigger a detached pass when disk and memory checks (every minute)
7049
- or directory sizes (hourly) are due. guide, settings and help do not trigger
7226
+ Automatic maintenance has three modes. on (the default) runs the disk actions
7227
+ below through gc's own removal code and logs each one. report measures, plans
7228
+ and logs, and never deletes anything. off disables it. It is off in CI and
7229
+ scoped STIM_HOME homes unless STIM_MAINTENANCE is explicit, so a scratch home
7230
+ or CI run never deletes on its own.
7231
+ Commands trigger a detached pass when a check is due: disk and memory pressure
7232
+ (every minute), directory sizes (hourly), finished worktrees (every 15
7233
+ minutes) and the age sweep (daily). guide, settings and help do not trigger
7050
7234
  it; gc --delete also skips the hook. status --watch also triggers checks.
7051
- Size checks defer under high load. Attempts back off for at least one minute.
7052
- Measured directories are workspace build outputs and Stim's shared native,
7053
- Metro, ccache, Swift compilation and registered caches. Pressure checks read
7054
- free disk on the Stim home, projects and worker root volumes. On macOS the
7055
- memory signal is the sysctl pressure level, with no signal if sysctl fails.
7056
- Other platforms use os.freemem(); macOS never falls back to it.
7057
- Memory pressure is recorded only; memory stops are deferred to a later phase.
7235
+ Size, worktree and sweep checks defer under high load. Attempts back off for at
7236
+ least one minute. Measured directories are workspace build outputs and Stim's
7237
+ shared native, Metro, ccache, Swift compilation and registered caches.
7238
+ Pressure checks read free disk on the Stim home, projects and worker root
7239
+ volumes. On macOS the memory signal is the sysctl pressure level, with no
7240
+ signal if sysctl fails. Other platforms use os.freemem(); macOS never falls
7241
+ back to it. Memory pressure is recorded only; stopping devices, dev servers
7242
+ and helpers is not automatic.
7243
+
7244
+ In on mode a pass runs, cheapest to rebuild first:
7245
+ 1. orphaned workspace directories whose project is gone, and registered
7246
+ caches whose directory no longer exists
7247
+ 2. build outputs of idle workspaces, over maintenance.workspaceOutputsMaxGb,
7248
+ below the free-disk floor, or unused for maintenance.olderThanDays
7249
+ 3. build-cache and Metro entries, least recently used first, down to
7250
+ maintenance.capTargetPercent of caches.buildCacheMaxGb or
7251
+ caches.metroCacheMaxGb, and entries unused for olderThanDays
7252
+ 4. the Swift compilation cache, emptied whole, only below
7253
+ budget.hardFloorDiskGb and with no build lock or slot held
7254
+ 5. linked worktrees whose branch or pull request finished (gc's finished
7255
+ worktree rules and gc.worktreeGraceMinutes; maintenance.removeFinishedWorktrees)
7256
+ Disk-driven steps stop once free space is back above the floor. Kept for
7257
+ every pass: a workspace that is in use, holds a lock, was used within
7258
+ maintenance.protectRecentHours, is pinned with maintenance.keep, or is the
7259
+ workspace of the command that started the pass; cache entries used within
7260
+ protectRecentHours, named by a project's last builds, a parked device or a
7261
+ live build lock, or in a Metro store with a running or unverifiable dev
7262
+ server. Anything the pass cannot verify is kept. A pass never shuts down idle devices or dev servers or stops watchman; removing a
7263
+ finished worktree or orphaned directory does tear down that workspace's own
7264
+ dev server, owned devices and Chrome profile, as gc --delete does. ccache evicts by itself under
7265
+ caches.ccacheMaxGb.
7058
7266
 
7059
7267
  stim status last checks, plan and running pass
7060
7268
  stim status --json maintenance observations and recent records
7061
7269
  stim logs --source maintenance this workspace's maintenance records
7062
7270
  stim gc live pressure and cached-size preview
7063
- stim settings set maintenance.mode off
7271
+ stim settings set maintenance.mode off turn automatic cleanup off
7272
+ stim settings set maintenance.mode report plan and log, delete nothing
7064
7273
 
7065
7274
  The machine log is $STIM_HOME/maintenance/maintenance.ndjson, rotated at
7066
7275
  maintenance.logMaxMb with the old generation retained for
7067
7276
  maintenance.logRetentionDays. Child crashes use maintenance/child.log.
7068
- Actions and explaining skips are logged only when newly planned. A pass is
7069
- logged after a size check or a change to actions, skips or blocked reasons.
7277
+ In report mode actions and explaining skips are logged only when newly
7278
+ planned; in on mode every action taken, failure and explaining skip is logged
7279
+ with its bytes, and a pass record carries the bytes freed. Removal of a
7280
+ worktree or orphaned directory is logged to the machine log only.
7070
7281
  maintenance.logChecks enables debug observations; default false.
7071
7282
  status and doctor report invalid settings and unresolved claims with a removal
7072
7283
  command to run only after confirming the holder is gone. Invalid cache caps
7073
7284
  fall back to their own defaults; invalid maintenance settings disable passes.
7285
+ Pin a workspace with \`stim settings set maintenance.keep true\` in its project.
7074
7286
  The run claim serializes passes with gc --delete; gc refuses a held claim
7075
7287
  with the holder and recovery guidance instead of waiting.
7076
7288
 
@@ -8267,12 +8479,26 @@ overrides the file:
8267
8479
  budget is off. A value of the wrong shape refuses start, ios and android with
8268
8480
  STIM_BAD_ARG. See \`guide lifecycle budget\` for what each limit reclaims.
8269
8481
 
8482
+ DEBUG LOGS ARE MACHINE-LEVEL AND OFF BY DEFAULT
8483
+ debug.logs STIM_DEBUG default false. STIM_DEBUG=1 (or 0) overrides the setting
8484
+ for one command. While on, the CLI writes debug records to
8485
+ STIM_HOME/logs/debug/cli.ndjson (run_start, run_end, exec with the program name,
8486
+ duration and exit status but never arguments, remote_connect and
8487
+ remote_request with durations and codes); stim-server writes server.ndjson there
8488
+ and logs every request with its timings to its service log. The file rotates at about 8 MiB and keeps one previous
8489
+ generation, and nothing is sent anywhere. Keys named like a secret are redacted.
8490
+ stim settings set debug.logs true --scope machine
8491
+ See \`guide logs\` for reading the files.
8492
+
8270
8493
  AUTOMATIC MAINTENANCE IS MACHINE-LEVEL
8271
- Report-only in this release: it measures and plans, and deletes or stops nothing.
8494
+ maintenance.mode on (the default) removes what gc would under the caps and
8495
+ floors below; report measures and plans and deletes nothing; off disables it.
8272
8496
  STIM_HOME and CI make the mode off unless STIM_MAINTENANCE is set.
8497
+ maintenance.keep is a project setting: pin a workspace so a pass never clears
8498
+ its build outputs or removes its worktree.
8273
8499
  See \`guide cleanup\` for checks, plans and log paths.
8274
8500
 
8275
- ${SETTINGS.filter((setting) => setting.key.startsWith("maintenance.") || /^caches\..*MaxGb$/.test(setting.key)).map((setting) => ` ${setting.key} ${setting.env} ${setting.default === void 0 ? "unset" : `default ${setting.default}`}
8501
+ ${SETTINGS.filter((setting) => setting.key.startsWith("maintenance.") || /^caches\..*MaxGb$/.test(setting.key)).map((setting) => ` ${setting.key} ${setting.env ?? "project setting"} ${setting.default === void 0 ? "unset" : `default ${setting.default}`}
8276
8502
  ${setting.description}`).join("\n")}
8277
8503
 
8278
8504
  Maintenance uses the sysctl pressure level on macOS, with no memory signal
@@ -8418,7 +8644,7 @@ DEVICE HOSTING
8418
8644
  Only \`doctor --fix\` asks for device-host access. A person on that Mac
8419
8645
  approves the printed id with \`stim-server devices grant <id> --device-host\`.
8420
8646
  A person can also run \`stim-server setup\` on the worker: one node, one ticket,
8421
- one expiry, at most one request per capability, with per-grant y/N in a
8647
+ one expiry, at most one request per capability, with a per-grant Y/n question (Enter approves) in a
8422
8648
  terminal or \`--yes\` otherwise. Agents never run \`stim-server setup\` or
8423
8649
  approve requests. Setup never changes TCC or enables Funnel; an SSH-driven
8424
8650
  run is not offered. Without a terminal or --yes, setup refuses before installing
@@ -8563,10 +8789,12 @@ preferring the one that already holds this repository, then the least loaded,
8563
8789
  and moves to the next one in that order when a machine that offered fails the
8564
8790
  sync or refuses to start the build.
8565
8791
  For iOS the machine's Xcode and simulator SDK must match, and it needs an
8566
- iPhone simulator on the target runtime. Its CocoaPods must match too, unless
8792
+ iPhone simulator on the target runtime. Its project-selected CocoaPods must match too, unless
8567
8793
  the app's Gemfile.lock pins CocoaPods: both Macs then run that version through
8568
8794
  bundler, so the machine needs only Bundler on its stim-server PATH and
8569
- installs the pinned gems itself on the first build. For Android its JDK major
8795
+ installs the pinned gems itself on the first build. The comparison selects
8796
+ the app's .ruby-version when installed, with pod install's UTF-8 locale defaults.
8797
+ For Android its JDK major
8570
8798
  version must match, and its Android SDK must hold the NDK, build-tools and
8571
8799
  compile platform that the project's React Native version names in
8572
8800
  gradle/libs.versions.toml; Gradle and AGP come from the synced project. When
@@ -9157,7 +9385,14 @@ macos.arguments is an array of arguments passed directly to the executable:
9157
9385
 
9158
9386
  The plist must contain CFBundleIdentifier and CFBundleExecutable matching the
9159
9387
  product. Use a development plist without shared URL schemes or an update feed.
9160
- Stim gives the copied bundle a workspace-specific identifier. SwiftPM resource
9388
+ Stim gives the copied bundle a workspace-specific identifier and name: it sets
9389
+ CFBundleDisplayName and CFBundleName on the copy to "<product> \u00b7 <label>",
9390
+ where label is the owned-device label (worktree and app directory names, cleaned
9391
+ to letters, digits, . _ -; at most 24 characters, cut with an ellipsis). The Dock,
9392
+ Cmd-Tab and lsappinfo show it, so several runs tell apart; the process name in
9393
+ System Events stays the executable. The project plist and the app's window titles
9394
+ are untouched. The name is displayName in the launch payload and status. Hosted
9395
+ (--remote) and offloaded builds get the same name. SwiftPM resource
9161
9396
  bundles and frameworks in the reported build directory are copied into it;
9162
9397
  macos.resources maps destinations under Contents/Resources to file or directory
9163
9398
  sources relative to the Swift Package directory, for example:
@@ -9199,8 +9434,9 @@ platform "macos": phase prepare, compile, install, then launch, and during
9199
9434
  compile detail.unit "steps" with SwiftPM's [done / total] counts (fetching and
9200
9435
  planning are detail.step "configure"). It has no cache lookup, so outcome and
9201
9436
  plannedPhases are null; finished runs and their phase times are in
9202
- environments[].builds.macos. An offloaded build reports the worker's steps the
9203
- same way.
9437
+ environments[].builds.macos, where phases includes launch once the launch step finishes
9438
+ and compileSteps is SwiftPM's step total. An offloaded build reports the worker's
9439
+ steps the same way.
9204
9440
  Runtime stdout and stderr become client records; build output becomes build
9205
9441
  records, all with platform "macos". Unexpected app exits are error records.
9206
9442
  Stim runs the app with NSUnbufferedIO=YES, so Swift print output arrives per
@@ -9654,7 +9890,7 @@ const TUTORIAL_RESTART_PROMPT = "Restart the Stim tutorial.";
9654
9890
  const TUTORIAL_STEPS = [
9655
9891
  {
9656
9892
  id: "begin",
9657
- title: "Create the tutorial",
9893
+ title: "Create the Tutorial",
9658
9894
  who: "agent",
9659
9895
  optional: false,
9660
9896
  prompt: TUTORIAL_PROMPTS.begin,
@@ -9683,7 +9919,7 @@ const TUTORIAL_STEPS = [
9683
9919
  },
9684
9920
  {
9685
9921
  id: "sidebar",
9686
- title: "Workspace in sidebar",
9922
+ title: "Workspace in Sidebar",
9687
9923
  who: "you",
9688
9924
  optional: false,
9689
9925
  prompt: null,
@@ -9692,7 +9928,7 @@ const TUTORIAL_STEPS = [
9692
9928
  },
9693
9929
  {
9694
9930
  id: "build",
9695
- title: "First iOS build",
9931
+ title: "First iOS Build",
9696
9932
  who: "you",
9697
9933
  optional: false,
9698
9934
  prompt: null,
@@ -9710,7 +9946,7 @@ const TUTORIAL_STEPS = [
9710
9946
  },
9711
9947
  {
9712
9948
  id: "rebuild",
9713
- title: "Rebuild from cache",
9949
+ title: "Rebuild from Cache",
9714
9950
  who: "agent",
9715
9951
  optional: false,
9716
9952
  prompt: TUTORIAL_PROMPTS.rebuild,
@@ -9723,7 +9959,7 @@ const TUTORIAL_STEPS = [
9723
9959
  },
9724
9960
  {
9725
9961
  id: "device",
9726
- title: "Live view and control",
9962
+ title: "Live View and Control",
9727
9963
  who: "you",
9728
9964
  optional: false,
9729
9965
  prompt: null,
@@ -9732,7 +9968,7 @@ const TUTORIAL_STEPS = [
9732
9968
  },
9733
9969
  {
9734
9970
  id: "logs",
9735
- title: "App logs",
9971
+ title: "App Logs",
9736
9972
  who: "you",
9737
9973
  optional: false,
9738
9974
  prompt: null,
@@ -9741,7 +9977,7 @@ const TUTORIAL_STEPS = [
9741
9977
  },
9742
9978
  {
9743
9979
  id: "agent",
9744
- title: "Agent actions and replay",
9980
+ title: "Agent Actions and Replay",
9745
9981
  who: "agent",
9746
9982
  optional: false,
9747
9983
  prompt: TUTORIAL_PROMPTS.agent,
@@ -9780,7 +10016,7 @@ const TUTORIAL_STEPS = [
9780
10016
  },
9781
10017
  {
9782
10018
  id: "phone",
9783
- title: "Watch on your phone",
10019
+ title: "Watch on Your Phone",
9784
10020
  who: "you",
9785
10021
  optional: true,
9786
10022
  prompt: null,
@@ -9789,7 +10025,7 @@ const TUTORIAL_STEPS = [
9789
10025
  },
9790
10026
  {
9791
10027
  id: "machine",
9792
- title: "Build on another Mac",
10028
+ title: "Build on Another Mac",
9793
10029
  who: "both",
9794
10030
  optional: true,
9795
10031
  prompt: TUTORIAL_PROMPTS.machine,
@@ -9798,7 +10034,7 @@ const TUTORIAL_STEPS = [
9798
10034
  },
9799
10035
  {
9800
10036
  id: "finish",
9801
- title: "Finish and archive",
10037
+ title: "Finish and Archive",
9802
10038
  who: "agent",
9803
10039
  optional: false,
9804
10040
  prompt: TUTORIAL_PROMPTS.finish,
@@ -9824,6 +10060,7 @@ function commands(id) {
9824
10060
  //#region src/guide/index.ts
9825
10061
  const TOPICS = {
9826
10062
  agent: agent_default,
10063
+ api: api_default,
9827
10064
  facts,
9828
10065
  metro: metro_default,
9829
10066
  ports: ports_default,
@@ -9971,7 +10208,7 @@ Remove the target-v1 evidence and dismiss-overlay lines before replay: replaying
9971
10208
  them can fail with REPLAY_DIVERGENCE on the recorded button identity.
9972
10209
  The scripts and screenshot stay in the tour worktree and are git-ignored.
9973
10210
 
9974
- PAUSE: end the turn. Point at Agent actions, or the agent log records just
10211
+ PAUSE: end the turn. Point at Agent Actions, or the agent log records just
9975
10212
  printed. Expect another error-button line after replay. When screen recording
9976
10213
  is enabled, the user can scrub Replay in Desktop. Give the next prompt:
9977
10214
  "${TUTORIAL_PROMPTS.refresh}".`
@@ -10068,7 +10305,7 @@ first failure. Read stderr and do not continue to later commands. Follow stim gu
10068
10305
  safety. Reuse only this version's tutorial app, never overwrite another folder.
10069
10306
  The creation block skips writes on reuse and checks the repository root.
10070
10307
 
10071
- Replace {base} and {tour} with absolute paths; {base} must end in stim-tutorial. For Agent actions, replace
10308
+ Replace {base} and {tour} with absolute paths; {base} must end in stim-tutorial. For Agent Actions, replace
10072
10309
  {stateDir} with agentDevice.stateDir from stim ios or stim status --json;
10073
10310
  when read -r iosUdid waits, type this workspace's ios.udid from that status.
10074
10311
  For the optional machine step,
@@ -10077,9 +10314,9 @@ replace {machine} with a machine you have already approved, or skip it.
10077
10314
  Look at the sidebar during warm and Build during the first build (about four
10078
10315
  minutes on a cold cache). Compare cacheHit and missReason on rebuild. At Live
10079
10316
  view and control, open the device viewer and tap Log an error; without Desktop
10080
- use the simulator. At App logs, try Crash me or Slow request if wanted. A JS
10317
+ use the simulator. At App Logs, try Crash me or Slow request if wanted. A JS
10081
10318
  crash shows a red box; the slow request is a local timer, not network capture.
10082
- At Watch on your phone, optionally open an already paired Stim phone to see
10319
+ At Watch on Your Phone, optionally open an already paired Stim phone to see
10083
10320
  the tour workspace; phone setup and machine approval stay with you.
10084
10321
  Use stim status, stim logs --errors, and stim stats without Desktop.
10085
10322
 
@@ -1,6 +1,6 @@
1
- import { a as call, o as connectHost } from "./hosted-client-Bp4knSwu.mjs";
2
- import { i as requestHostedMetro } from "./metro-gateway-C-ijGI2F.mjs";
3
- import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-1Ebbig4w.mjs";
1
+ import { a as call, o as connectHost } from "./hosted-client-C-rMtppF.mjs";
2
+ import { i as requestHostedMetro } from "./metro-gateway-CEUw9RMH.mjs";
3
+ import { n as prepareHostedNative, r as stopHostedNative, t as placeHostedNative } from "./hosted-native-DeeOG8xZ.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,8 +1,8 @@
1
- import { _ as configuredMachines, t as BuildConnection, x as pinnedEndpoint$1 } from "./client-SvBdgObD.mjs";
2
- import { createHash } from "node:crypto";
1
+ import { C as pinnedEndpoint$1, t as BuildConnection, y as configuredMachines } from "./client-DzhapoMB.mjs";
3
2
  import { lstatSync, readFileSync, readdirSync, readlinkSync } from "node:fs";
4
3
  import { join } from "node:path";
5
4
  import { HOSTED_APP_CHUNK_BYTES, hostedMacosAppSlot, isJsonObject, readDeviceHostMachines } from "@stim-cli/core/state";
5
+ import { createHash } from "node:crypto";
6
6
  //#region src/device-host/hosted-client.ts
7
7
  const CONNECT_TIMEOUT_MS = 1e4;
8
8
  /** Covers 90s stop + 15s final logs + three 10s worker group-settle bounds, with 45s for polling and transport. */