@stim-cli/server 1.21.0 → 1.23.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.
package/README.md CHANGED
@@ -152,6 +152,100 @@ limits and the report execution/cleanup budgets apply. Disconnect or shutdown
152
152
  cancels the request and drains its owned work. Cached doctor report reads do not
153
153
  record checks.
154
154
 
155
+ The local-only `desktop-run` feature provides `desktop.run.subscribe` with an
156
+ absolute `cwd` and `options` matching the typed `stim.run` selectors. For example,
157
+ `{ "cwd": "/absolute/app", "options": { "platform": "ios", "slot": "fold", "remote": "mini" } }`
158
+ builds, installs and launches through the in-process API. Only a proved private
159
+ Desktop session can call it; adopted servers and local control alone cannot.
160
+ `desktop-run-progress` carries ordered `stream`/`message` chunks, followed by
161
+ `desktop-run-ended` with `exitCode`, a human `message`, and `stdout` containing
162
+ the serialized `{ platform, facts }` API result or typed refusal. The default
163
+ execution budget is one hour; progress plus the terminal JSON are limited to
164
+ 1 MiB. Cancellation, unsubscribe, disconnect and server shutdown cancel and drain
165
+ owned work before releasing workspace admission. Unresolved cleanup retains the
166
+ reservation until every recorded claim is recovered. If cleanup cannot name its
167
+ claims, admission stays blocked until the server restarts; recover the owned work
168
+ before restarting. Reconnect never replays a run. Desktop's platform buttons
169
+ still use the CLI until their consumer migration.
170
+
171
+ The private `desktop-build` feature provides `desktop.build.subscribe` with an
172
+ absolute `cwd` and artifact-only `options`: `ios` accepts `configuration`, `scheme`
173
+ and `arch`; `android` accepts `variant` and `abi`; both accept `buildCache` and
174
+ `remoteBuild`. `macos` accepts `remoteBuild`. It invokes `createStim.build`
175
+ without acquiring a device or starting a runtime. Device, slot, hosted-launch,
176
+ Metro and EAS selectors are refused. It uses the same proved Desktop authority,
177
+ one-hour default budget, 1 MiB output bound and cleanup admission as platform
178
+ run. Ordered `desktop-build-progress` events end with `desktop-build-ended`,
179
+ whose `stdout` contains `{ platform, facts }` or the typed refusal. Reconnecting
180
+ never replays a build. This transport is a migration prerequisite; existing
181
+ Desktop buttons do not use it yet.
182
+
183
+ The private `desktop-gc` feature provides `desktop.gc.subscribe` with an absolute
184
+ existing `cwd` and optional `cache`, `olderThan` (whole days), `worktrees`, `delete`
185
+ and `idleMs` (positive whole milliseconds). It invokes `createStim.collectGarbage`
186
+ with the same scoped cleanup and ownership rules as the CLI. Only the proved
187
+ Desktop connection can call it; phone, network and adopted-server connections
188
+ cannot. Ordered `desktop-gc-progress` events end with `desktop-gc-ended`, whose
189
+ `stdout` contains the GC JSON report or typed refusal and whose `exitCode` preserves
190
+ partial cleanup failures. It preserves the API's 60-second execution and 35-second
191
+ cleanup budgets. The server's request deadline can cancel execution earlier; its
192
+ progress plus terminal JSON bound is 1 MiB. Unsubscribe, disconnect, shutdown and timeout
193
+ cancel and drain owned work before releasing admission; unresolved cleanup retains
194
+ the reservation and its recovery claims. Settled requests invalidate cached Desktop
195
+ reports. Reconnect never repeats cleanup. Desktop GC buttons still use the CLI
196
+ until their consumer migration.
197
+
198
+ The private `desktop-worktree-remove` feature provides
199
+ `desktop.worktree.remove.subscribe` with an absolute existing `cwd`, an optional
200
+ absolute `target`, and optional boolean `force`. It calls `createStim.removeWorktree`
201
+ with the CLI's safety checks and ownership rules. A separate target can be absent
202
+ on disk when retrying pending branch cleanup. Only the proved connection of the
203
+ Desktop that started this server can call it; paired phones and adopted local
204
+ connections cannot.
205
+
206
+ Ordered `desktop-worktree-remove-progress` events end with
207
+ `desktop-worktree-remove-ended`. Its `stdout` contains `{ removed, exitCode }` or
208
+ a typed refusal. Admission covers the resolved checkout or project and every
209
+ registered descendant reclaimed by cleanup, including when the request names a
210
+ subfolder. Deletion and cleanup success remain separate: source cleanup
211
+ can succeed without deleting a checkout, and branch cleanup can fail after a
212
+ linked checkout was deleted. `force` has the CLI's destructive meaning. The API's
213
+ 60-second execution and 35-second cleanup budgets and the server's deadline and
214
+ output limit apply. Cancellation drains owned work before releasing admission;
215
+ unresolved cleanup retains its recovery claims. Settled requests invalidate
216
+ cached Desktop reports. Reconnect never repeats removal. Desktop callers migrate
217
+ separately.
218
+
219
+ The private `desktop-worktree-warm` feature provides
220
+ `desktop.worktree.warm.subscribe` with only an absolute existing `cwd`. It calls
221
+ `createStim.warmWorktree` for plain copying; refresh and dependency installation
222
+ remain CLI-only. Only the proved connection of the Desktop that started this
223
+ server can call it. Phones, network clients and adopted local connections cannot.
224
+
225
+ Ordered `desktop-worktree-warm-progress` events end with
226
+ `desktop-worktree-warm-ended`, whose `stdout` contains `{ exitCode }` or a typed
227
+ refusal. The default request budget is 90 minutes, with an explicitly configured
228
+ server action deadline taking precedence. The API's 35-second cleanup budget and
229
+ the server's 1 MiB progress-plus-result bound apply. Admission covers the resolved
230
+ linked checkout, its registered descendants and the inferred app before effects.
231
+ Cancellation drains owned work before releasing admission; unverifiable cleanup
232
+ retains admission until its exact recovery claims are cleared. Settled requests
233
+ invalidate cached Desktop reports. Reconnect never repeats warming. Desktop
234
+ callers migrate separately.
235
+
236
+ The private `desktop-plan` feature provides `desktop.plan.get` with an absolute
237
+ existing `cwd`, `platform` (`ios`, `android` or `macos`) and an optional iOS/Android
238
+ `slot`. An optional `request` identifies that connection's check. It returns the shared `createStim.plan` report or a typed `{ code, message, remedy }` refusal without a CLI process,
239
+ building or launching. Only the proved Desktop connection can select folders;
240
+ phones and ordinary local connections cannot use it. The existing `build.plan`
241
+ method remains limited to registered iOS/Android workspaces. Both paths share
242
+ per-directory queues, connection request limits, output bounds and cancellation.
243
+ The planner has a 60-second execution and 35-second cleanup budget inside the
244
+ server's 150-second request deadline, which starts after queued work drains.
245
+ These bounded plans support EAS and Stim cache providers; legacy custom Expo
246
+ cache plugins are checked only by CLI plans.
247
+ Desktop preview consumers use this private read. `desktop.plan.cancel { request }` cancels only a check on the same proved connection and replies after its queued work and cleanup drain. A retained cleanup failure is included as `refusal` in the cancellation result; other connections cannot cancel it. Shared subscriptions stay connected.
248
+
155
249
  The local-only `desktop-stop` feature provides `desktop.stop.subscribe` with an
156
250
  absolute `cwd` and optional `slot` (`web` closes only the owned Chrome). It stops
157
251
  that exact canonical workspace through the shared API, without searching for a
@@ -1191,11 +1285,17 @@ systems refuse; start stim-server from your own service manager there:
1191
1285
  stim-server service install [--port <n>] [--label <name>] [--serve]
1192
1286
  [--env KEY=VALUE]... [--path-prepend <dir>]...
1193
1287
  stim-server service status [--label <name>] [--json]
1194
- stim-server service update [--label <name>] --release <version>|--from <dir>
1288
+ stim-server service update [--label <name>] [--no-wait] --release <version>|--from <dir>
1195
1289
  stim-server service rollback [--label <name>]
1196
1290
  stim-server service uninstall [--label <name>]
1197
1291
  ```
1198
1292
 
1293
+ Updates wait for offloaded builds and hosted sessions to finish by default.
1294
+ Use `--no-wait` to restart with work still active: shutdown interrupts those
1295
+ builds and sessions. Service shutdown, health checks and rollback still apply.
1296
+ `stim-server setup --no-wait` uses the same policy when it updates a managed
1297
+ service; if setup requires a separate service update, its remedy includes the flag.
1298
+
1199
1299
  `install` writes `~/Library/LaunchAgents/<label>.plist` (label `dev.stim.server`
1200
1300
  by default) and starts it with `launchctl bootstrap gui/<uid>`. The job starts
1201
1301
  Stim Host, which stays alive as the parent of the absolute `node` and
@@ -1508,9 +1608,13 @@ connected since stim-server started keeps its directory when revoked.
1508
1608
  the JDK in `JAVA_HOME` or the macOS default; and `androidSdk`, the `ndk`,
1509
1609
  `buildTools` and `platforms` directories of the SDK in `ANDROID_HOME`, else `~/Library/Android/sdk` on macOS or
1510
1610
  `~/Android/Sdk` on Linux, null without one), `capacity` and `warm`
1511
- (`checkout`, `dependencies` when the last install used that lockfile, and
1512
- `build` once a build ran there, including a non-empty repository `macos/`
1513
- scratch directory) for that repository. `capacity` holds
1611
+ (`checkout`, `dependencies`, and the legacy `build` field, now always false)
1612
+ for that repository. For React Native and Expo builds, clients supporting `build-dependency-cache` can send
1613
+ `dependencies: { project, packageName }` alongside `lockfile`; the dependency
1614
+ hint requires the selected project's installed modules and a matching install
1615
+ marker, including the package-manager arguments. Without that query it is
1616
+ false. Clients ignore older workers' unverified warmth and do not rank
1617
+ checkout or build-directory presence as cache state. `capacity` holds
1514
1618
  `running` and `max` offloaded builds, `diskFreeBytes` of the worker root's
1515
1619
  volume and `minDiskFreeBytes`, `cpus`, `loadPerCore` (the 5-minute load
1516
1620
  average per CPU), `builds` (this machine's own Stim runs in prebuild, pods or
@@ -1532,6 +1636,31 @@ connected since stim-server started keeps its directory when revoked.
1532
1636
  or `{ fingerprint, cacheKey, name, size, sha256 }` for a completed archive in
1533
1637
  this client's repository area. The key includes source, toolchain, SDK,
1534
1638
  architecture and target options. These are exact lookups, not a full inventory.
1639
+ With `react-native-peer-cache`, a React Native/Expo development offer can send
1640
+ `reactNativeArtifact: { project, fingerprint, isExpo, platform, toolchain, ios | android }`.
1641
+ The query includes the caller's compatible toolchain and normalized native
1642
+ build choices; the worker constructs its own receipt around compilation.
1643
+ The returned identity is opaque, not an alias for the caller's local cache key.
1644
+ The completed receipt binds the worker-verified post-mutation fingerprint
1645
+ and native options to the toolchain checked before and after compilation.
1646
+ Lookup uses that immutable receipt, so a later checkout or toolchain change
1647
+ does not discard a matching archive. Older workers receive no new query
1648
+ parameters and continue through their normal build path.
1649
+ With `swiftpm-peer-cache`, `swiftpmArtifact` carries `project`, `sourceDigest`,
1650
+ `stimBuild`, complete `inputs` (`ignored`, `outputs`, `localFiles`,
1651
+ `environment`) and `build` (`product`, `infoPlist`, `resources`, `assetCatalog`).
1652
+ Resource and catalog paths are repository-relative; the plist is
1653
+ project-relative. The worker verifies actual transferred files and full
1654
+ artifact identity around compilation, then retains an opaque receipt.
1655
+ Private input values stay on that worker and are rechecked on every lookup.
1656
+ SDKROOT, then SWIFTPM_SDKROOT_macosx, selects the SDK ahead of the default;
1657
+ its real path and build version are revalidated.
1658
+ A matching archive survives checkout and job-output pruning when those
1659
+ private inputs remain available and unchanged and its direct Apple toolchain
1660
+ selection can be reproduced. Command paths and versions are checked from the
1661
+ package directory, including SWIFT_EXEC and SWIFT_EXEC_MANIFEST compiler overrides.
1662
+ Overrides and custom Swift, xcrun or xcodebuild launchers require the
1663
+ checkout and become a miss after it is removed.
1535
1664
  - `build.cached-artifact` takes `repo` and `artifact: { fingerprint, cacheKey }`.
1536
1665
  It requires the existing build approval. It verifies and streams the cached
1537
1666
  archive with the same digest-prefixed binary frames as `build.artifact`, and
@@ -1540,6 +1669,13 @@ connected since stim-server started keeps its directory when revoked.
1540
1669
  worker archives survive job-output cleanup in their client's repository cache;
1541
1670
  removing that client's worker area removes the cache too. Other clients and
1542
1671
  repositories cannot look up those entries.
1672
+ React Native archives also require the same `reactNativeArtifact` query on
1673
+ download, checked against the completed receipt again. An identity alone
1674
+ cannot fetch them. Archives use the existing complete-file cache and digest verification;
1675
+ a hit uploads no source and takes no compiler slot. A missing or corrupt
1676
+ archive falls back through the caller's existing placement policy.
1677
+ SwiftPM archives require the same `swiftpmArtifact` query on fetch and another
1678
+ private-input check; their opaque keys alone cannot fetch an archive.
1543
1679
  - `build.sync` takes `repo`, `files` and `done`. `files` is one page of the
1544
1680
  manifest, each `{ "path", "kind": "file"|"exec"|"link", "size", "sha256" }`,
1545
1681
  a link's blob being its target. Pages accumulate until `done`; the next
@@ -1562,7 +1698,9 @@ connected since stim-server started keeps its directory when revoked.
1562
1698
  `fingerprint`, `packageName`, `isExpo`, `optimizations`, `android` (for
1563
1699
  `android`: `variant`, `abi`, `gradleBuildCache`, `pch` and `compilerCache`,
1564
1700
  `ccache` or `none`) and `stimBuild`, after the whole manifest of `repo` was
1565
- synced on this connection. It returns `{ "job" }`. It fails with
1701
+ synced on this connection. A peer-cache-capable React Native caller can set
1702
+ `cacheArtifact: true` to retain a completed development archive when its cache
1703
+ write and remote policies allow it. It returns `{ "job" }`. It fails with
1566
1704
  `build-busy` while the offer would be declined, naming the reason, or while
1567
1705
  another build of the same client and repository runs, or while every one
1568
1706
  of this machine's `concurrency.maxBuilds` slots is held, and with
@@ -1619,7 +1757,11 @@ connected since stim-server started keeps its directory when revoked.
1619
1757
  It returns that app as a tar archive, its manifest fingerprint, timings and
1620
1758
  `compilationCache: {}`. The client verifies the digest, identity, executable
1621
1759
  and signature before promotion and launches locally. Every offload failure
1622
- falls back locally; macOS artifacts are not cached. Matching Xcode and macOS
1760
+ falls back locally. A caller with remote artifact caching enabled can set
1761
+ `cacheArtifact: true` and `macos.artifactInputs` for declared repeatable,
1762
+ relocatable apps. Completed archive retention requires matching worker
1763
+ input identities before and after the build; ignored bundle files need
1764
+ explicit private declarations. Matching Xcode and macOS
1623
1765
  SDK are required, and the worker needs network access for the first SwiftPM
1624
1766
  dependency fetch; the dependency cache is shared only within that client.
1625
1767
  - `build.progress` events `{ "event": "build.progress", "job", ... }` carry a
@@ -2070,13 +2212,13 @@ Events are `{ "event", "subscription", ... }`.
2070
2212
  deleted.
2071
2213
  - `build.plan` takes `workspace`, `platform` (`ios` or `android`) and `slot`
2072
2214
  (`default` when absent), and returns the payload of
2073
- `stim <platform> --plan --json` run in the workspace: the fingerprint, the
2215
+ `stim <platform> --plan --json` through the shared in-process API: the fingerprint, the
2074
2216
  cache result the next build would get (`local`, `remote` or `false`), the
2075
2217
  prebuild decision, `expectedMs` with its `basis`, and on a predicted cold
2076
2218
  build its `missReason`. It builds, boots and
2077
2219
  installs nothing and writes no Stim state; a remote cache check can
2078
- download the artifact into a temporary directory, so it gets 150 seconds
2079
- instead of 60. A plan predicting that the build would refuse is a result
2220
+ download the artifact into a temporary directory. The planner has a 60-second
2221
+ execution and 35-second cleanup budget inside the 150-second request limit. A plan predicting that the build would refuse is a result
2080
2222
  whose `refusal` holds the code, message and remedy. A plan that cannot be
2081
2223
  computed is a `stim-failed` error. One plan runs per workspace at a time,
2082
2224
  across all connections; later requests wait their turn, and the 150
@@ -2190,8 +2332,8 @@ a time. `logs.query`, `stats.get` and `settings.get` fail after 60 seconds,
2190
2332
  `build.plan` after 150; these four fail at 32 MiB of output. Closing the
2191
2333
  connection stops running requests. When the command refuses with Stim's error
2192
2334
  contract on stdout, the `stim-failed` message is its code, message and remedy;
2193
- otherwise it is the exit status and the end of stderr. A `stim` child that
2194
- ignores SIGTERM gets SIGKILL a second later. A log subscriber whose socket has more than
2335
+ otherwise the message describes the failed read. In-process reads cancel their
2336
+ owned children and drain cleanup before releasing their request slot. A log subscriber whose socket has more than
2195
2337
  4 MiB unsent gets no more batches until it catches up; past 20,000
2196
2338
  waiting records the server ends that subscription with `slow-client`.
2197
2339