peachsim 0.1.639 → 0.1.641

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 (68) hide show
  1. package/cli/commands/control.ts +33 -1
  2. package/detox/index.ts +31 -11
  3. package/dist-lib/agent-daemon-client.cjs +1 -1
  4. package/dist-lib/agent-events.cjs +1 -1
  5. package/dist-lib/agent-identity.cjs +1 -1
  6. package/dist-lib/agent-sessions.cjs +1 -1
  7. package/dist-lib/attached-projects.cjs +1 -1
  8. package/dist-lib/auth/shared-session.cjs +1 -1
  9. package/dist-lib/backend-origin.cjs +1 -1
  10. package/dist-lib/beta.cjs +1 -1
  11. package/dist-lib/beta.mjs +1 -1
  12. package/dist-lib/bridge-constants.cjs +1 -1
  13. package/dist-lib/bridge-contract-input.cjs +1 -1
  14. package/dist-lib/bridge-contract-input.mjs +1 -1
  15. package/dist-lib/bridge-contract.cjs +1 -1
  16. package/dist-lib/bridge-contract.mjs +1 -1
  17. package/dist-lib/capture-contract.cjs +1 -1
  18. package/dist-lib/capture-contract.mjs +1 -1
  19. package/dist-lib/cli-constants.cjs +1 -1
  20. package/dist-lib/cloud-contract.cjs +1 -1
  21. package/dist-lib/cloud-contract.mjs +1 -1
  22. package/dist-lib/cloud-test-args.cjs +1 -1
  23. package/dist-lib/cloud-test-args.mjs +1 -1
  24. package/dist-lib/cloud.cjs +1 -1
  25. package/dist-lib/cloud.mjs +1 -1
  26. package/dist-lib/config.cjs +1 -1
  27. package/dist-lib/detox/index.cjs +24 -4
  28. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  29. package/dist-lib/home-paths.cjs +1 -1
  30. package/dist-lib/host/bridge-host.cjs +1 -1
  31. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  34. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  35. package/dist-lib/host/websocket-proxy.cjs +1 -1
  36. package/dist-lib/index.cjs +1 -1
  37. package/dist-lib/jump-to-source-babel.cjs +1 -1
  38. package/dist-lib/jump-to-source-native.cjs +1 -1
  39. package/dist-lib/kotlin-host.cjs +1 -1
  40. package/dist-lib/menu.cjs +1 -1
  41. package/dist-lib/menu.mjs +1 -1
  42. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  43. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  44. package/dist-lib/metro-production-bundle.cjs +1 -1
  45. package/dist-lib/metro-production-bundle.mjs +1 -1
  46. package/dist-lib/metro.cjs +1 -1
  47. package/dist-lib/native-app-identity.cjs +1 -1
  48. package/dist-lib/native-app-identity.mjs +1 -1
  49. package/dist-lib/profiles.cjs +1 -1
  50. package/dist-lib/public-brand.cjs +1 -1
  51. package/dist-lib/react-native-host-modules.cjs +1 -1
  52. package/dist-lib/react-native-host-modules.mjs +1 -1
  53. package/dist-lib/render-mode.cjs +1 -1
  54. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  55. package/dist-lib/sdk.cjs +1 -1
  56. package/dist-lib/sdk.mjs +1 -1
  57. package/dist-lib/skills.cjs +342 -200
  58. package/dist-lib/swift-compile.cjs +1 -1
  59. package/dist-lib/swift-compile.mjs +1 -1
  60. package/dist-lib/swift-package.cjs +1 -1
  61. package/dist-lib/swift-package.mjs +1 -1
  62. package/dist-lib/swift-submit.cjs +1 -1
  63. package/dist-lib/swift-submit.mjs +1 -1
  64. package/dist-lib/swift.cjs +1 -1
  65. package/dist-lib/vite-swift.cjs +1 -1
  66. package/dist-lib/vite.cjs +1 -1
  67. package/package.json +1 -1
  68. package/src/dot-env.ts +148 -0
@@ -24,6 +24,7 @@ import {
24
24
  resolveConnectionInput,
25
25
  type ResolvedDevBundle,
26
26
  } from '../../src/dev-bundle-resolution'
27
+ import { readProjectDotEnv } from '../../src/dot-env'
27
28
  import { flowTimeoutScale } from '../../src/flow-timeout-scale'
28
29
  import {
29
30
  isDaemonLockfileFresh,
@@ -886,6 +887,9 @@ export interface BuildShellUrlOptions {
886
887
  // launch-time environment variables, stamped as repeated ?env=KEY%3DVALUE.
887
888
  // see the --env flag above.
888
889
  env?: string[]
890
+ // the project's env file as react-native-config's iOS build compiles it,
891
+ // stamped as ?dotEnv=<json>. set by `peach open --load-env` only.
892
+ dotEnv?: Record<string, string>
889
893
  }
890
894
 
891
895
  function bundleUrlOf(urlStr: string): string | undefined {
@@ -921,10 +925,12 @@ export async function buildShellUrl(
921
925
  !opts.proof &&
922
926
  !opts.posture &&
923
927
  !opts.osVersion &&
924
- !opts.env?.length
928
+ !opts.env?.length &&
929
+ !opts.dotEnv
925
930
  )
926
931
  return stamped
927
932
  const url = new URL(stamped)
933
+ if (opts.dotEnv) url.searchParams.set('dotEnv', JSON.stringify(opts.dotEnv))
928
934
  if (opts.device) url.searchParams.set('device', opts.device)
929
935
  if (opts.posture) url.searchParams.set('posture', opts.posture)
930
936
  if (opts.osVersion) url.searchParams.set('osVersion', opts.osVersion)
@@ -1467,6 +1473,7 @@ export async function runOpenCommand(
1467
1473
  '--no-describe',
1468
1474
  '--quiet',
1469
1475
  '--proof',
1476
+ '--load-env',
1470
1477
  ],
1471
1478
  stripValueFlags: [
1472
1479
  '--base-url',
@@ -1727,6 +1734,30 @@ export async function runOpenCommand(
1727
1734
  ? { width: Number(viewportMatch[1]), height: Number(viewportMatch[2]) }
1728
1735
  : undefined
1729
1736
 
1737
+ // --load-env reads the project's env file the way react-native-config's iOS
1738
+ // build phase compiles it into the binary (ENVFILE, then .env), so the app's
1739
+ // `Config` holds those values. without it `Config` is empty, as in a build
1740
+ // that found no env file, and the app's first read warns in the console.
1741
+ let dotEnv: Record<string, string> | undefined
1742
+ if (args.includes('--load-env')) {
1743
+ if (!project) {
1744
+ console.error(
1745
+ ' peach open: --load-env needs a local app project to read the env file from',
1746
+ )
1747
+ rnxExit(1)
1748
+ }
1749
+ try {
1750
+ const result = readProjectDotEnv(project.appDir)
1751
+ if (!quiet) for (const notice of result.notices) console.log(` ${notice}`)
1752
+ dotEnv = result.config
1753
+ } catch (error) {
1754
+ console.error(
1755
+ ` peach open: ${error instanceof Error ? error.message : String(error)}`,
1756
+ )
1757
+ rnxExit(1)
1758
+ }
1759
+ }
1760
+
1730
1761
  const buildShellUrlOpts: BuildShellUrlOptions = {
1731
1762
  hot: hotMode,
1732
1763
  device: deviceArg,
@@ -1736,6 +1767,7 @@ export async function runOpenCommand(
1736
1767
  project,
1737
1768
  proof: args.includes('--proof'),
1738
1769
  env: envArgs.length ? envArgs : undefined,
1770
+ dotEnv,
1739
1771
  }
1740
1772
 
1741
1773
  // resolve the shell base URL from the bridge port we settled on, so the page
package/detox/index.ts CHANGED
@@ -2232,6 +2232,7 @@ export const device = {
2232
2232
  }
2233
2233
  lockstepCapture?: {
2234
2234
  begin: (fps: number) => Promise<{
2235
+ readonly initialFrame: FrameReceipt
2235
2236
  stepFrame: () => Promise<FrameReceipt>
2236
2237
  stepToOffset: (
2237
2238
  anchor: FrameReceipt,
@@ -2422,8 +2423,28 @@ export const device = {
2422
2423
  let detectedMeasurement: MotionChangeMeasurement | null = null
2423
2424
  let previousReceipt: FrameReceipt | null = null
2424
2425
  let previousBitmap: ImageBitmap | null = null
2426
+ // android can publish mount layout at p=0 before a clock step.
2427
+ if (input.platform === 'android') {
2428
+ const candidateBitmap = await captureBitmap()
2429
+ const bounds = boundsFor(candidateBitmap)
2430
+ const measurement = measureChange({
2431
+ baseline,
2432
+ candidate: regionPixels(candidateBitmap),
2433
+ definition: input.motionChangeDefinition,
2434
+ height: bounds.height,
2435
+ label: 'peach initial-frame visible-change detector',
2436
+ width: bounds.width,
2437
+ })
2438
+ if (measurement.passedMinimum) {
2439
+ visibleStart = controller.initialFrame
2440
+ detectedMeasurement = measurement
2441
+ keptFrames.set(visibleStart.frameIndex, candidateBitmap)
2442
+ } else {
2443
+ candidateBitmap.close()
2444
+ }
2445
+ }
2425
2446
  const detectionFrameLimit = Math.ceil((input.detectionTimeoutMs * 60) / 1000)
2426
- for (let frame = 0; frame < detectionFrameLimit; frame++) {
2447
+ for (let frame = 0; !visibleStart && frame < detectionFrameLimit; frame++) {
2427
2448
  if (state.cancelled) throw new Error('peach motion capture was cancelled')
2428
2449
  const receipt = await controller.stepFrame()
2429
2450
  await advanceHold(receipt)
@@ -2455,15 +2476,13 @@ export const device = {
2455
2476
  `peach motion had no visible change before ${input.detectionTimeoutMs}ms`,
2456
2477
  )
2457
2478
  }
2458
- // the drive started on the tick the tap landed, which renders no
2459
- // visible change: the transition opens at p=0 with the snapshot
2460
- // identical to the source view still underneath it, so the gate
2461
- // cannot trip before the morph's first tick. stages measure from
2462
- // that tap tick (or the change itself when the first stepped frame
2463
- // already moves). native's tap tick trips the gate on the touch
2464
- // highlight, so its onset frame is the same event tick: same
2465
- // event, per-leg rule, not same gate side.
2466
- const driveStart = previousReceipt ?? visibleStart
2479
+ // android screenrecord stages measure from the detected frame.
2480
+ // ios morphs retain the preceding event tick: the browser paints
2481
+ // p=0 unchanged while native's touch highlight trips its gate.
2482
+ const driveStart =
2483
+ input.platform === 'android'
2484
+ ? visibleStart
2485
+ : (previousReceipt ?? visibleStart)
2467
2486
  let currentReceipt = visibleStart
2468
2487
  const resolvedAnchors = new Map<string, FrameReceipt>()
2469
2488
  const anchorRecords: Array<{
@@ -2584,7 +2603,7 @@ export const device = {
2584
2603
  const stageFrameIndex =
2585
2604
  anchorReceipt.frameIndex + Math.ceil(stage.offsetMs / frameMs)
2586
2605
  const kept = keptFrames.get(stageFrameIndex)
2587
- if (kept && stageFrameIndex < currentReceipt.frameIndex) {
2606
+ if (kept && stageFrameIndex <= currentReceipt.frameIndex) {
2588
2607
  snapshots.push({
2589
2608
  actualMs: 0,
2590
2609
  anchorId,
@@ -2665,6 +2684,7 @@ export const device = {
2665
2684
  frame: options.frame ?? null,
2666
2685
  hold: options.hold ?? null,
2667
2686
  motionChangeDefinition: MOTION_CHANGE_DEFINITION,
2687
+ platform: device.getPlatform(),
2668
2688
  rootFrame: options.rootFrame ?? null,
2669
2689
  settleMs,
2670
2690
  stages,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var REFUSED_PERFORM_STEP_TYPES = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-test-args.ts
4
4
  var CLOUD_TEST_ARGS_MAX_COUNT = 32;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -3707,8 +3707,27 @@ var device = {
3707
3707
  let detectedMeasurement = null;
3708
3708
  let previousReceipt = null;
3709
3709
  let previousBitmap = null;
3710
+ if (input.platform === "android") {
3711
+ const candidateBitmap = await captureBitmap();
3712
+ const bounds = boundsFor(candidateBitmap);
3713
+ const measurement = measureChange({
3714
+ baseline,
3715
+ candidate: regionPixels(candidateBitmap),
3716
+ definition: input.motionChangeDefinition,
3717
+ height: bounds.height,
3718
+ label: "peach initial-frame visible-change detector",
3719
+ width: bounds.width
3720
+ });
3721
+ if (measurement.passedMinimum) {
3722
+ visibleStart = controller.initialFrame;
3723
+ detectedMeasurement = measurement;
3724
+ keptFrames.set(visibleStart.frameIndex, candidateBitmap);
3725
+ } else {
3726
+ candidateBitmap.close();
3727
+ }
3728
+ }
3710
3729
  const detectionFrameLimit = Math.ceil(input.detectionTimeoutMs * 60 / 1e3);
3711
- for (let frame = 0; frame < detectionFrameLimit; frame++) {
3730
+ for (let frame = 0; !visibleStart && frame < detectionFrameLimit; frame++) {
3712
3731
  if (state.cancelled) throw new Error("peach motion capture was cancelled");
3713
3732
  const receipt = await controller.stepFrame();
3714
3733
  await advanceHold(receipt);
@@ -3740,7 +3759,7 @@ var device = {
3740
3759
  `peach motion had no visible change before ${input.detectionTimeoutMs}ms`
3741
3760
  );
3742
3761
  }
3743
- const driveStart = previousReceipt ?? visibleStart;
3762
+ const driveStart = input.platform === "android" ? visibleStart : previousReceipt ?? visibleStart;
3744
3763
  let currentReceipt = visibleStart;
3745
3764
  const resolvedAnchors = /* @__PURE__ */ new Map();
3746
3765
  const anchorRecords = [];
@@ -3832,7 +3851,7 @@ var device = {
3832
3851
  const { anchorId, receipt: anchorReceipt } = await resolveAnchor(stage);
3833
3852
  const stageFrameIndex = anchorReceipt.frameIndex + Math.ceil(stage.offsetMs / frameMs);
3834
3853
  const kept = keptFrames.get(stageFrameIndex);
3835
- if (kept && stageFrameIndex < currentReceipt.frameIndex) {
3854
+ if (kept && stageFrameIndex <= currentReceipt.frameIndex) {
3836
3855
  snapshots.push({
3837
3856
  actualMs: 0,
3838
3857
  anchorId,
@@ -3905,6 +3924,7 @@ var device = {
3905
3924
  frame: options.frame ?? null,
3906
3925
  hold: options.hold ?? null,
3907
3926
  motionChangeDefinition: import_motion_change.MOTION_CHANGE_DEFINITION,
3927
+ platform: device.getPlatform(),
3908
3928
  rootFrame: options.rootFrame ?? null,
3909
3929
  settleMs,
3910
3930
  stages,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/menu.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/menu.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/public-brand.ts
4
4
  var name = "Peach";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/is-record.ts
4
4
  function isRecord(value) {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-production-bundle.ts
4
4
  var RNXSIM_METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/native-app-identity.ts
4
4
  var NATIVE_APP_IDENTITY_PREFIX = "globalThis.__sootsimNativeAppIdentity=";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.639 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.641 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);