peachsim 0.1.527 → 0.1.570

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 (158) hide show
  1. package/README.md +26 -26
  2. package/cli/app-fonts.ts +1 -1
  3. package/cli/app-splash.ts +1 -1
  4. package/cli/bin.ts +1 -1
  5. package/cli/bridge-diagnostics.ts +1 -1
  6. package/cli/bridge-flow-runner.ts +57 -5
  7. package/cli/cloud-client.ts +273 -6
  8. package/cli/cloud-dispatch.ts +22 -2
  9. package/cli/cloud-session.ts +60 -4
  10. package/cli/cloud-test-tunnel.ts +354 -0
  11. package/cli/commands/box/bundle-plane.ts +2 -2
  12. package/cli/commands/box/checkout-plane.ts +1 -1
  13. package/cli/commands/box/rnx-command.ts +2 -2
  14. package/cli/commands/box/search-command.ts +2 -2
  15. package/cli/commands/box.ts +8 -8
  16. package/cli/commands/compat.ts +1 -1
  17. package/cli/commands/control.ts +22 -3
  18. package/cli/commands/detox.ts +1 -1
  19. package/cli/commands/device.ts +1 -1
  20. package/cli/commands/diagnose.ts +1 -1
  21. package/cli/commands/film.ts +1 -1
  22. package/cli/commands/flow.ts +60 -3
  23. package/cli/commands/inspect/actions.ts +1 -1
  24. package/cli/commands/inspect/core.ts +6 -7
  25. package/cli/commands/inspect/find.ts +2 -1
  26. package/cli/commands/inspect/resolve-target.ts +5 -3
  27. package/cli/commands/inspect/shared.ts +1 -1
  28. package/cli/commands/inspect/wait-event.ts +1 -1
  29. package/cli/commands/inspect/wait-selector.ts +15 -4
  30. package/cli/commands/inspect.ts +19 -14
  31. package/cli/commands/maestro.ts +464 -43
  32. package/cli/commands/permissions.ts +1 -1
  33. package/cli/commands/platform.ts +205 -8
  34. package/cli/commands/preview.ts +2 -2
  35. package/cli/commands/record.ts +2 -2
  36. package/cli/commands/report-issue.ts +2 -2
  37. package/cli/commands/screenshot-layers.ts +1 -1
  38. package/cli/commands/screenshot.ts +1 -1
  39. package/cli/commands/setup.ts +2 -2
  40. package/cli/commands/test.ts +440 -115
  41. package/cli/commands/three-mode.ts +1 -1
  42. package/cli/commands/upload.ts +5 -5
  43. package/cli/commands/what-happened.ts +1 -1
  44. package/cli/desktop-companion.ts +3 -3
  45. package/cli/drivers/playwright-sim-host.ts +2 -2
  46. package/cli/flow-file.ts +7 -0
  47. package/cli/flow-live-status.ts +65 -8
  48. package/cli/help-core.ts +3 -3
  49. package/cli/hidden-runtime-alias.ts +1 -1
  50. package/cli/maestro-report.ts +178 -0
  51. package/cli/main.ts +1 -1
  52. package/cli/outbound-endpoints.ts +185 -136
  53. package/cli/parse-args.ts +1 -1
  54. package/cli/registry.ts +1 -1
  55. package/cli/resolve-assets.ts +1 -1
  56. package/cli/run-registry.ts +8 -0
  57. package/cli/send-to-box.ts +4 -4
  58. package/cli/ws-bridge.ts +3 -5
  59. package/detox/expectations.ts +1 -1
  60. package/detox/gestures.ts +2 -2
  61. package/detox/index.ts +71 -29
  62. package/detox/jest-preset.cjs +3 -3
  63. package/detox/jest-setup-after-env.cjs +1 -1
  64. package/dist-lib/agent-daemon-client.cjs +2 -2
  65. package/dist-lib/agent-events.cjs +1 -1
  66. package/dist-lib/agent-identity.cjs +1 -1
  67. package/dist-lib/agent-sessions.cjs +2 -2
  68. package/dist-lib/attached-projects.cjs +2 -2
  69. package/dist-lib/auth/shared-session.cjs +1 -1
  70. package/dist-lib/backend-origin.cjs +1 -1
  71. package/dist-lib/beta.cjs +1 -1
  72. package/dist-lib/beta.mjs +1 -1
  73. package/dist-lib/bridge-constants.cjs +1 -1
  74. package/dist-lib/bridge-contract-input.cjs +1 -1
  75. package/dist-lib/bridge-contract-input.mjs +1 -1
  76. package/dist-lib/bridge-contract.cjs +1 -1
  77. package/dist-lib/bridge-contract.mjs +1 -1
  78. package/dist-lib/capture-contract.cjs +94 -3
  79. package/dist-lib/capture-contract.mjs +93 -3
  80. package/dist-lib/cli-constants.cjs +1 -1
  81. package/dist-lib/cloud-contract.cjs +1 -1
  82. package/dist-lib/cloud-contract.mjs +1 -1
  83. package/dist-lib/cloud.cjs +2 -2
  84. package/dist-lib/cloud.mjs +2 -2
  85. package/dist-lib/config.cjs +1 -1
  86. package/dist-lib/detox/index.cjs +106 -25
  87. package/dist-lib/detox/jest-preset.cjs +3 -3
  88. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  89. package/dist-lib/home-paths.cjs +1 -1
  90. package/dist-lib/host/bridge-host.cjs +137 -61
  91. package/dist-lib/host/fetch-proxy-handler.cjs +28 -2
  92. package/dist-lib/host/fetch-proxy-overrides.cjs +33 -3
  93. package/dist-lib/host/fetch-proxy-overrides.mjs +30 -2
  94. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  95. package/dist-lib/host/websocket-proxy.cjs +1 -1
  96. package/dist-lib/index.cjs +209 -16
  97. package/dist-lib/jump-to-source-babel.cjs +1 -1
  98. package/dist-lib/jump-to-source-native.cjs +1 -1
  99. package/dist-lib/menu.cjs +2 -2
  100. package/dist-lib/menu.mjs +2 -2
  101. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  102. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  103. package/dist-lib/metro-production-bundle.cjs +3 -3
  104. package/dist-lib/metro-production-bundle.mjs +3 -3
  105. package/dist-lib/metro.cjs +8 -8
  106. package/dist-lib/profiles.cjs +1 -1
  107. package/dist-lib/public-brand.cjs +2 -2
  108. package/dist-lib/react-native-host-modules.cjs +1 -1
  109. package/dist-lib/react-native-host-modules.mjs +1 -1
  110. package/dist-lib/render-mode.cjs +1 -1
  111. package/dist-lib/scripts/dev-server-scanner.cjs +31 -15
  112. package/dist-lib/sdk.cjs +3 -2
  113. package/dist-lib/sdk.mjs +3 -2
  114. package/dist-lib/skills.cjs +362 -163
  115. package/dist-lib/swift-submit.cjs +1 -1
  116. package/dist-lib/swift-submit.mjs +1 -1
  117. package/dist-lib/swift.cjs +583 -16
  118. package/dist-lib/vite.cjs +29 -14
  119. package/package.json +9 -9
  120. package/scripts/dev-server-scanner.ts +41 -14
  121. package/scripts/optional-demo-registry.ts +3 -3
  122. package/skills/contrast/SKILL.md +9 -9
  123. package/skills/rnx-debug/SKILL.md +14 -4
  124. package/skills/rnx-perf/SKILL.md +5 -5
  125. package/skills/rnx-setup/SKILL.md +11 -11
  126. package/skills/rnx-test/SKILL.md +11 -11
  127. package/skills/rnx-visual/SKILL.md +6 -6
  128. package/src/agent-sessions.ts +3 -3
  129. package/src/attached-projects.ts +1 -1
  130. package/src/bridge-contract-input.ts +1 -1
  131. package/src/bridge-contract.ts +23 -5
  132. package/src/capture-contract.ts +145 -3
  133. package/src/config.ts +2 -2
  134. package/src/connect.ts +2 -2
  135. package/src/home-paths.ts +3 -3
  136. package/src/host/bridge-host.ts +2 -2
  137. package/src/host/fetch-proxy-handler.ts +4 -3
  138. package/src/host/fetch-proxy-overrides.ts +41 -0
  139. package/src/host/plane-host.ts +2 -2
  140. package/src/index.ts +3 -0
  141. package/src/metro-plugin.ts +4 -4
  142. package/src/metro-production-bundle.ts +2 -2
  143. package/src/native-seam-manifest.ts +6 -6
  144. package/src/public-brand.ts +1 -1
  145. package/src/rolldown-plugin-swift.ts +8 -5
  146. package/src/runtime-assets.ts +8 -6
  147. package/src/screenshots/frame-compose.ts +24 -56
  148. package/src/screenshots/org-deck.ts +1 -1
  149. package/src/screenshots/registry.ts +4 -4
  150. package/src/screenshots/schema.ts +1 -1
  151. package/src/sdk.ts +2 -2
  152. package/src/settings-bundle.ts +1 -1
  153. package/src/sim-client.ts +2 -4
  154. package/src/skills/builtin/compat-check.ts +1 -1
  155. package/src/vite-plugin-one.ts +1 -1
  156. package/src/vite-plugin-swift.ts +11 -6
  157. package/src/vite-plugin.ts +30 -17
  158. package/src/worklets-babel.ts +2 -2
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # rnx
1
+ # Peach
2
2
 
3
3
  The source owner for the standalone `rnx` executable and the public `rnxsim`
4
4
  integration library used to drive a browser-native React Native simulator.
@@ -202,7 +202,7 @@ bridge always addresses the **shell worker**, never an undifferentiated sim.
202
202
 
203
203
  | component | role | key files |
204
204
  | --- | --- | --- |
205
- | rnx CLI (bin + dispatcher) | Short-lived terminal entry point. Parses argv, owns the private-by-default one-time choice, lazy-imports one command per run, and routes direct open/runtime/inspection flows. | `cli/bin.ts`, `cli/main.ts`, `cli/privacy.ts`, `cli/parse-args.ts`, `cli/help.ts`, `cli/commands/setup.ts`, `cli/commands/control.ts` |
205
+ | Peach CLI (bin + dispatcher) | Short-lived terminal entry point. Parses argv, owns the private-by-default one-time choice, lazy-imports one command per run, and routes direct open/runtime/inspection flows. | `cli/bin.ts`, `cli/main.ts`, `cli/privacy.ts`, `cli/parse-args.ts`, `cli/help.ts`, `cli/commands/setup.ts`, `cli/commands/control.ts` |
206
206
  | WsBridge client | Client side of the CLI→daemon link. Resolves the daemon port from the lockfile, opens a WS to `:7668`, sends JSON commands and awaits `{id,result}`/`{id,error}`. Used by every interactive command. | `cli/ws-bridge.ts`, `src/bridge-constants.ts`, `cli/current-sim.ts` |
207
207
  | inspect / SDK command surface | Runtime inspection + interaction verbs (describe, find, do tap, get errors, wait, layout, settle). Re-exported as `rnxsim/sdk` so programmatic callers drive a sim the same way the CLI does. | `cli/commands/inspect/core.ts`, `cli/commands/inspect/actions.ts`, `cli/commands/inspect.ts`, `src/sdk.ts` |
208
208
  | bridge-contract input parsers | Turn untrusted JSON into typed bridge-contract arguments, so a transport in front of a sim validates request bodies once instead of writing a second reader. | `src/bridge-contract-input.ts`, `src/bridge-contract.ts` |
@@ -211,11 +211,11 @@ bridge always addresses the **shell worker**, never an undifferentiated sim.
211
211
  | SootSimBridgeHost (serve/daemon) | The bridge process (`rnx serve`, or autostarted as the daemon via launchd/systemd). HTTP+WS hub on `:7668`: relays commands between CLI clients and registered sims; also serves runtime HTTP, `/__server-scan`, and fetch/WS proxies. | `src/host/bridge-host.ts`, `cli/commands/serve.ts`, `cli/commands/daemon.ts`, `src/home-paths.ts` |
212
212
  | AgentHost + sessions | Agent-routing extension of the host: owns the single FIFO reader per agent session and fans `agent:event`/`session-status` pushes to every WS subscriber. Backed by agent-sessions + attached-projects stores. | `src/host/agent-host.ts`, `src/agent-sessions.ts`, `src/attached-projects.ts`, `src/agent-daemon-client.ts` |
213
213
  | host proxies + dev-server scan | Host-side helpers so a cross-origin tenant worker can reach local dev servers and same-origin APIs: `/__server-scan` discovers running metro/expo/vxrn/one servers; fetch + websocket proxies relay guest-app network through the daemon. | `src/host/fetch-proxy-handler.ts`, `src/host/websocket-proxy.ts`, `scripts/dev-server-scanner.ts`, `src/dev-bundle-resolution.ts` |
214
- | runtime delivery + rnx home | Versioned engine runtime management. The shared machinery owns manifest fetch, sha256 verification, channels, and auto-update. rnx binds it to `https://contrast.dev` and `~/.rnx/runtimes/<version>`. A repo can select `runtimeVersion` without changing the machine default. | `src/runtime-delivery.ts`, `packages/contrast-runtime-delivery/`, `src/home-paths.ts`, `src/runtime-assets.ts` |
214
+ | runtime delivery + Peach home | Versioned engine runtime management. The shared machinery owns manifest fetch, sha256 verification, channels, and auto-update. Peach binds it to `https://contrast.dev` and `~/.rnx/runtimes/<version>`. A repo can select `runtimeVersion` without changing the machine default. | `src/runtime-delivery.ts`, `packages/contrast-runtime-delivery/`, `src/home-paths.ts`, `src/runtime-assets.ts` |
215
215
  | standalone CLI delivery | Cached stable-version checks, bounded interactive notices, and verified atomic executable replacement. | `cli/cli-update.ts`, `cli/commands/upgrade.ts`, `cli/commands/version.ts`, `src/cli-version.ts` |
216
216
  | `rnxsim/vite` + `rnxsim/metro` (runtime serving) | Published bundler plugins. Both serve the installed engine runtime at `/__soot/` from `~/.rnx/runtimes/<version>` so an app's own dev server can host the sim shell; the Vite plugin can opt into a named Electron window. | `src/vite-plugin-one.ts`, `src/metro-plugin.ts`, `src/runtime-assets.ts` |
217
- | `sootsim()` vite resolver plugin (internal) | The large RN-resolution / native-stub vite plugin: aliases `react-native` to the engine shim, native packages to `@sootsim/compat` stubs, applies worklets/babel transforms, and instantiates `SootSimBridgeHost` in its dev server. Distinct from the published `rnxsim/vite` export. | `src/vite-plugin.ts`, `src/worklets-babel.ts`, `packages/compat/src/stub-manifest.ts` |
218
- | skills registry | rnx agent skills (`rnx-setup`, `rnx-debug`, `rnx-test`, `rnx-visual`, and the generated `contrast` index) installable with `rnx skill`. | `skills/*.md`, `src/skills/registry.ts`, `src/skills/types.ts` |
217
+ | `sootsim()` vite resolver plugin (internal) | The large RN-resolution / native-stub vite plugin: aliases `react-native` to the engine shim, native packages to `@sootsim/compat` stubs, applies worklets/babel transforms, and instantiates `SootSimBridgeHost` in its dev server. Distinct from the published `rnxsim/vite` export. | `src/vite-plugin.ts`, `src/worklets-babel.ts`, `packages/peach-compat/src/stub-manifest.ts` |
218
+ | skills registry | Peach agent skills (`rnx-setup`, `rnx-debug`, `rnx-test`, `rnx-visual`, and the generated `contrast` index) installable with `rnx skill`. | `skills/*.md`, `src/skills/registry.ts`, `src/skills/types.ts` |
219
219
 
220
220
  ## Getting started
221
221
 
@@ -245,7 +245,7 @@ The `rnxsim` npm package contains bundler plugins and library exports, not a CLI
245
245
  binary. Start your Metro, Expo, or One dev server the way you already do, then
246
246
  open it from the CLI. There is no iOS native build in the inner loop; Metro alone is
247
247
  enough. The manifest bundle path and query remain authoritative. When both the
248
- discovery request and manifest target are loopback addresses, RNX keeps the
248
+ discovery request and manifest target are loopback addresses, Peach keeps the
249
249
  loopback host that answered discovery so an IPv6-only listener is not reopened
250
250
  through an unreachable IPv4 address. `rnx open` starts a local bridge when no
251
251
  daemon is reachable. The background service is strongly recommended for local
@@ -253,7 +253,7 @@ agent work because inspect, interaction, and test commands reuse one ready bridg
253
253
  and runtime. Enable it at any time with `rnx daemon install`; it is never required
254
254
  in CI. The packaged Desktop app is optional and available through first-run
255
255
  onboarding or `rnx desktop install`. A downloaded app starts its own bundled
256
- daemon on first launch, then offers **Install the rnx command** over the running
256
+ daemon on first launch, then offers **Install the Peach command** over the running
257
257
  simulator. That action installs `~/.local/bin/rnx`, updates shell startup, and
258
258
  hands the daemon to launchd or systemd without reloading the window. Windows
259
259
  keeps the desktop-owned daemon because it has no daemon service yet. Native Electron windows created by `rnx open` belong to that CLI
@@ -264,7 +264,7 @@ window for a selected device (same device list as the `Window >` menu).
264
264
 
265
265
  ### Privacy
266
266
 
267
- rnx sends no analytics, crash report, command event, app data, project data, or
267
+ Peach sends no analytics, crash report, command event, app data, project data, or
268
268
  identity by default. An unsigned-in interactive run may request the runtime it
269
269
  is about to execute and the stable standalone CLI version document. The latter
270
270
  runs after the command in a detached process at most once every 20 hours and can
@@ -275,7 +275,7 @@ consuming the later human choice. Legacy browser and Electron telemetry senders
275
275
  are removed rather than being enabled by this consent.
276
276
 
277
277
  Opt-in diagnostics are limited to package name/version/unsupported API or error
278
- class. rnx never sends source, file paths, project names, app content, commands,
278
+ class. Peach never sends source, file paths, project names, app content, commands,
279
279
  identity, screenshots, or recordings as diagnostics. Cloud commands such as
280
280
  login, upload, billing, issue reporting, generated flows, and screenshot decks
281
281
  contact their documented service only when explicitly invoked. The complete
@@ -317,7 +317,7 @@ preset configures it automatically.
317
317
  For One's Rolldown native bundler, use the native transform in `vite.config.ts`:
318
318
 
319
319
  ```ts
320
- import { jumpToSourceNativePlugin } from 'rnxsim/jump-to-source-native'
320
+ import { jumpToSourceNativePlugin } from 'peachsim/jump-to-source-native'
321
321
 
322
322
  one({
323
323
  native: {
@@ -335,7 +335,7 @@ For One's `nativeTransformModules`, export
335
335
 
336
336
  ## CLI
337
337
 
338
- The CLI is the primary debugging surface for rnx — use it first for runtime
338
+ The CLI is the primary debugging surface for Peach — use it first for runtime
339
339
  inspection, interaction, animation debugging, shell tracing, screenshots, and
340
340
  flow capture, not just as a test runner.
341
341
 
@@ -381,11 +381,11 @@ rnx do tap email --then type user@example.com --then tap submit
381
381
 
382
382
  ## Bundler plugins (`rnxsim/vite` and `rnxsim/metro`)
383
383
 
384
- The Vite plugin serves the installed RNX runtime from your existing dev server.
384
+ The Vite plugin serves the installed Peach runtime from your existing dev server.
385
385
 
386
386
  ```ts
387
387
  // vite.config.ts
388
- import { rnxPlugin } from 'rnxsim/vite'
388
+ import { rnxPlugin } from 'peachsim/vite'
389
389
 
390
390
  export default {
391
391
  plugins: [rnxPlugin({ open: { appName: 'My App' } })],
@@ -395,17 +395,17 @@ export default {
395
395
  ```js
396
396
  // metro.config.js
397
397
  const { getDefaultConfig } = require('expo/metro-config')
398
- const { withRNX } = require('rnxsim/metro')
398
+ const { withRNX } = require('peachsim/metro')
399
399
 
400
400
  const config = getDefaultConfig(__dirname)
401
401
 
402
402
  module.exports = withRNX(config)
403
403
  ```
404
404
 
405
- rnx works directly with regular, unannotated Metro production JavaScript bundles
405
+ Peach works directly with regular, unannotated Metro production JavaScript bundles
406
406
  out of the box. It identifies modules by matching package graph fingerprints
407
407
  against a separately updated, integrity-checked registry. Hermes bytecode is not
408
- a supported input; pass rnx the JavaScript bundle produced before Hermes
408
+ a supported input; pass Peach the JavaScript bundle produced before Hermes
409
409
  compilation.
410
410
 
411
411
  If an app has unusual dependencies or fingerprint inference fails, you can
@@ -417,7 +417,7 @@ options and enables two integrations:
417
417
  bundle. Resolution, transforms, minification, and source maps stay the app's
418
418
  own, so the annotated bundle is the exact bundle you ship: the footer assigns
419
419
  one unused global on a device, and Hermes drops it during bytecode compilation.
420
- 2. **In-browser dev shell:** serves the rnx simulator shell at `/__soot/` on
420
+ 2. **In-browser dev shell:** serves the Peach simulator shell at `/__soot/` on
421
421
  the Metro dev server.
422
422
 
423
423
  The URL helpers request ordinary Metro graphs: `dev=false&minify=true` for
@@ -427,7 +427,7 @@ production and `dev=true&minify=false` for development.
427
427
  const {
428
428
  toRNXProductionBundleUrl,
429
429
  toRNXDevelopmentBundleUrl,
430
- } = require('rnxsim/metro')
430
+ } = require('peachsim/metro')
431
431
 
432
432
  const productionUrl = toRNXProductionBundleUrl(
433
433
  'http://localhost:8081/index.bundle?platform=ios',
@@ -439,8 +439,8 @@ const developmentUrl = toRNXDevelopmentBundleUrl(
439
439
 
440
440
  ## Coming from Detox
441
441
 
442
- rnx ships a drop-in Detox driver. Existing Detox test files
443
- (`import { by, element, expect, device } from 'detox'`) run against rnx with
442
+ Peach ships a drop-in Detox driver. Existing Detox test files
443
+ (`import { by, element, expect, device } from 'detox'`) run against Peach with
444
444
  no code changes — just add one line to your jest config:
445
445
 
446
446
  ```js
@@ -459,7 +459,7 @@ See `../../docs/migrating-from-detox.md` for details.
459
459
 
460
460
  ## Coming from Maestro
461
461
 
462
- Maestro is rnx's single YAML test surface. Point it at your existing
462
+ Maestro is Peach's single YAML test surface. Point it at your existing
463
463
  `.maestro/` directory, generate a test, or author one from live actions:
464
464
 
465
465
  ```sh
@@ -489,7 +489,7 @@ rnx screenshot --with-frame --output /tmp/rnx-framed.png
489
489
  rnx record --duration 5 --output /tmp/rnx-anim.mp4
490
490
  ```
491
491
 
492
- `rnx screenshot --with-frame` composes the real rnx shell device chrome
492
+ `rnx screenshot --with-frame` composes the real Peach shell device chrome
493
493
  around the raw screen bitmap (reusing the shell bezel/button geometry, excluding
494
494
  the Electron top bar, rail gutter, and other window chrome). Flows can request
495
495
  the framed export inline without changing Maestro syntax:
@@ -553,13 +553,13 @@ frame for quick art-direction passes.
553
553
 
554
554
  ## Skills registry
555
555
 
556
- `rnx skill install` installs rnx agent skills in the standard
556
+ `rnx skill install` installs Peach agent skills in the standard
557
557
  `<skill-name>/SKILL.md` layout used by Codex and Claude Code. The bundled
558
558
  skills cover setup, debugging/perf/accessibility, testing, visual review, and
559
559
  the generated `contrast` command index. The published CLI registry and generated
560
560
  website docs both come from `packages/rnx-skills/`:
561
561
 
562
- - `packages/sootsim/skills/contrast/SKILL.md` is generated from that registry
562
+ - `packages/peachsim/skills/contrast/SKILL.md` is generated from that registry
563
563
  - `src/features/site/docs/rnx/cli/*` is generated output, not hand-edited
564
564
 
565
565
  When command docs or examples drift, update `packages/rnx-skills/` and run:
@@ -568,10 +568,10 @@ When command docs or examples drift, update `packages/rnx-skills/` and run:
568
568
  bun run generate:sootsim-docs
569
569
  ```
570
570
 
571
- ## Runtime delivery (the rnx home and CDN)
571
+ ## Runtime delivery (the Peach home and CDN)
572
572
 
573
573
  The engine never ships inside this package. `runtime-delivery.ts` names
574
- rnx's CDN origin (default `https://contrast.dev`, overridable in
574
+ Peach's CDN origin (default `https://contrast.dev`, overridable in
575
575
  `config.json`), its `SOOTSIM_*` env overrides, and its hosted paths, then hands
576
576
  them to the shared delivery machinery in `@contrast/runtime-delivery` — an
577
577
  internal workspace package the CLI bundles, so a published install has it
package/cli/app-fonts.ts CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  expoFontPathsFromPlugins,
7
7
  metroFontSpecsFromPaths,
8
8
  type ConfigPluginFontSpec,
9
- } from 'sootsim-engine/engine/config-plugin-fonts'
9
+ } from 'peach-engine/engine/config-plugin-fonts'
10
10
  import { resolveListeningPid, resolveProcessCwd } from '../scripts/dev-server-scanner'
11
11
  import { parsePlistSource } from '../src/plist.ts'
12
12
  import { resolveAppProject } from './app-project'
package/cli/app-splash.ts CHANGED
@@ -5,7 +5,7 @@ import path from 'node:path'
5
5
  import {
6
6
  configPluginSplashFromExpoConfig,
7
7
  type ConfigPluginSplashSpec,
8
- } from 'sootsim-engine/engine/config-plugin-splash'
8
+ } from 'peach-engine/engine/config-plugin-splash'
9
9
  import { resolveAppProject } from './app-project'
10
10
 
11
11
  const require = createRequire(import.meta.url)
package/cli/bin.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // rnx CLI entry point. the full command and verb surface lives in the
4
- // registry at `packages/rnx-skills/src/cli/meta.ts` — help output,
4
+ // registry at `packages/peach-skills/src/cli/meta.ts` — help output,
5
5
  // website docs, and agent skills all read from there. do not duplicate
6
6
  // command listings in this file; run `rnx --help` for the canonical
7
7
  // surface.
@@ -1,7 +1,7 @@
1
1
  import { MERGED_CONSOLE_COUNT_EVAL, inspectErrors } from './commands/inspect/core'
2
2
  import { formatLogTimestamp } from './commands/inspect/shared'
3
3
  import type { WsBridge } from './ws-bridge'
4
- import type { SootSimRequestEntry } from '@rnx/globals'
4
+ import type { SootSimRequestEntry } from '@peach/globals'
5
5
 
6
6
  interface ConsoleSummaryOptions {
7
7
  includeTail?: boolean
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'fs'
2
2
  import * as path from 'path'
3
- import { devices, type DeviceModel } from 'sootsim-engine/settings'
3
+ import { devices, type DeviceModel } from 'peach-engine/settings'
4
4
  import yaml from 'yaml'
5
5
  import { REQUIRED_IDENTICAL_FLOW_FRAMES, framesIdentical } from '../detox/proof-frame.cjs'
6
6
  import { flowTimeoutScale } from '../src/flow-timeout-scale'
@@ -14,11 +14,11 @@ import { MaestroJsContext, scriptConditionIsTruthy } from './maestro-js'
14
14
  import { ensureCliRecordingEntitlement } from './recording-access'
15
15
  import type { PerformResult, PerformStep, ResetResult } from '../src/bridge-contract'
16
16
  import type { WsBridge } from './ws-bridge'
17
- import type { SootSimReplayTarget, SootSimTapResult } from '@rnx/globals'
17
+ import type { SootSimReplayTarget, SootSimTapResult } from '@peach/globals'
18
18
  import type {
19
19
  SootSimExternalAppLifecycleOptions,
20
20
  SootSimLaunchArguments,
21
- } from '@rnx/globals'
21
+ } from '@peach/globals'
22
22
 
23
23
  const DEFAULT_TIMEOUT = 10000
24
24
  const FLOW_TIMEOUT_SCALE = flowTimeoutScale()
@@ -2027,7 +2027,33 @@ export class SootSimBridgeFlowRunner {
2027
2027
  // begin its pixels only after launch has mounted and settled, leaving the
2028
2028
  // loading prelude outside the playable video while its trace stays visible.
2029
2029
  await this.waitForVisualSettle()
2030
+ const videoAlreadyStarted = this.recordingStartedAtMs != null
2030
2031
  await this.ensureRecordingStarted()
2032
+ if (!videoAlreadyStarted && this.recordingStartedAtMs != null) {
2033
+ // the preview event recorder has been running since before launch,
2034
+ // so its clock includes the boot prelude the video just skipped.
2035
+ // rebase it to the video's first frame — without this every event
2036
+ // timestamp overshoots the playable video and preview playback can
2037
+ // never align (play stuck disabled). no-op unless the preview
2038
+ // event recorder is running.
2039
+ await this.rebaseEventRecorderToVideoStart(this.recordingStartedAtMs)
2040
+ }
2041
+ }
2042
+ }
2043
+
2044
+ private async rebaseEventRecorderToVideoStart(videoStartedAtMs: number) {
2045
+ try {
2046
+ await this.evaluate(
2047
+ `(() => {
2048
+ const recorder = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
2049
+ if (!recorder?.isRecording?.()) return 'not-recording'
2050
+ return recorder.markVisibleStart?.(${JSON.stringify(videoStartedAtMs)}) ?? 'no-mark'
2051
+ })()`,
2052
+ )
2053
+ } catch (err) {
2054
+ console.warn(
2055
+ ` warn: event-recorder rebase to video start failed: ${err instanceof Error ? err.message : err}`,
2056
+ )
2031
2057
  }
2032
2058
  }
2033
2059
 
@@ -2258,6 +2284,7 @@ export class SootSimBridgeFlowRunner {
2258
2284
  }
2259
2285
 
2260
2286
  async runStep(rawStepInput: MaestroStep | string, stepIndex: number) {
2287
+ await this.liveStatus?.waitWhilePaused()
2261
2288
  // maestro allows several commands in BARE-STRING form (`- back`,
2262
2289
  // `- hideKeyboard`, `- waitForAnimationToEnd`, `- scrollUp`, …). yaml parses
2263
2290
  // those to a plain string, so normalize to the `{ verb: true }` object form
@@ -2384,7 +2411,14 @@ export class SootSimBridgeFlowRunner {
2384
2411
  step.waitFor
2385
2412
  )
2386
2413
  if (this.stepDelay > 0 && !isAssertion) {
2387
- await sleep(this.stepDelay)
2414
+ const chunkMs = 50
2415
+ let elapsed = 0
2416
+ while (elapsed < this.stepDelay) {
2417
+ await this.liveStatus?.waitWhilePaused()
2418
+ const toSleep = Math.min(chunkMs, this.stepDelay - elapsed)
2419
+ await sleep(toSleep)
2420
+ elapsed += toSleep
2421
+ }
2388
2422
  }
2389
2423
  this.recordFlowTraceStep({
2390
2424
  stepIndex,
@@ -2621,7 +2655,12 @@ export class SootSimBridgeFlowRunner {
2621
2655
  // runFlowPlayback; absent for programmatic callers.
2622
2656
  liveStatus: FlowLiveStatusReporter | null = null
2623
2657
 
2624
- async runFlow(steps: MaestroStep[]) {
2658
+ resetFlowState() {
2659
+ this.flowTraceSteps = []
2660
+ this.lastFailedStep = null
2661
+ }
2662
+
2663
+ extractFlowBody(steps: MaestroStep[]) {
2625
2664
  // maestro `onFlowStart` / `onFlowComplete` lifecycle hooks: if any step
2626
2665
  // in the array is a sole-key entry whose key is one of these names and
2627
2666
  // whose value is a list of sub-steps, pull them out and run them as
@@ -2649,7 +2688,11 @@ export class SootSimBridgeFlowRunner {
2649
2688
  }
2650
2689
  body.push(step)
2651
2690
  }
2691
+ return { onStart, onComplete, body }
2692
+ }
2652
2693
 
2694
+ async planFlow(steps: MaestroStep[], options: { dryRun?: boolean } = {}) {
2695
+ const { body } = this.extractFlowBody(steps)
2653
2696
  if (this.liveStatus) {
2654
2697
  await this.liveStatus.plan(
2655
2698
  body.map((rawStep, index) => {
@@ -2660,8 +2703,17 @@ export class SootSimBridgeFlowRunner {
2660
2703
  const name = Object.keys(step).find((k) => k !== 'when') ?? Object.keys(step)[0]
2661
2704
  return { index, name, target: this.flowStepTargetLabel(step, name) }
2662
2705
  }),
2706
+ options,
2663
2707
  )
2664
2708
  }
2709
+ }
2710
+
2711
+ async runFlow(steps: MaestroStep[], options: { skipPlan?: boolean } = {}) {
2712
+ const { onStart, onComplete, body } = this.extractFlowBody(steps)
2713
+
2714
+ if (!options.skipPlan && this.liveStatus) {
2715
+ await this.planFlow(steps)
2716
+ }
2665
2717
 
2666
2718
  if (onStart.length > 0) {
2667
2719
  console.log(`[flow] onFlowStart (${onStart.length} steps)`)