rnxsim 0.1.445 → 0.1.447

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 (58) hide show
  1. package/README.md +3 -0
  2. package/cli/commands/detox.ts +18 -0
  3. package/cli/commands/inspect.ts +2 -2
  4. package/cli/outbound-endpoints.ts +0 -2
  5. package/detox/index.ts +21 -1
  6. package/dist-lib/agent-daemon-client.cjs +1 -1
  7. package/dist-lib/agent-events.cjs +1 -1
  8. package/dist-lib/agent-identity.cjs +1 -1
  9. package/dist-lib/agent-sessions.cjs +1 -1
  10. package/dist-lib/attached-projects.cjs +1 -1
  11. package/dist-lib/auth/shared-session.cjs +1 -1
  12. package/dist-lib/backend-origin.cjs +1 -1
  13. package/dist-lib/beta.cjs +1 -1
  14. package/dist-lib/beta.mjs +1 -1
  15. package/dist-lib/bridge-constants.cjs +1 -1
  16. package/dist-lib/bridge-contract-input.cjs +1 -1
  17. package/dist-lib/bridge-contract-input.mjs +1 -1
  18. package/dist-lib/bridge-contract.cjs +1 -1
  19. package/dist-lib/bridge-contract.mjs +1 -1
  20. package/dist-lib/capture-contract.cjs +1 -1
  21. package/dist-lib/capture-contract.mjs +1 -1
  22. package/dist-lib/cli-constants.cjs +1 -1
  23. package/dist-lib/cloud-contract.cjs +1 -1
  24. package/dist-lib/cloud-contract.mjs +1 -1
  25. package/dist-lib/cloud.cjs +1 -1
  26. package/dist-lib/cloud.mjs +1 -1
  27. package/dist-lib/config.cjs +1 -1
  28. package/dist-lib/detox/index.cjs +16 -1
  29. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  30. package/dist-lib/home-paths.cjs +1 -1
  31. package/dist-lib/host/bridge-host.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  34. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  35. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  36. package/dist-lib/host/websocket-proxy.cjs +1 -1
  37. package/dist-lib/index.cjs +1 -1
  38. package/dist-lib/jump-to-source-babel.cjs +1 -1
  39. package/dist-lib/menu.cjs +1 -1
  40. package/dist-lib/menu.mjs +1 -1
  41. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  42. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  43. package/dist-lib/metro-production-bundle.cjs +1 -1
  44. package/dist-lib/metro-production-bundle.mjs +1 -1
  45. package/dist-lib/metro.cjs +1 -1
  46. package/dist-lib/profiles.cjs +1 -1
  47. package/dist-lib/public-brand.cjs +1 -1
  48. package/dist-lib/react-native-host-modules.cjs +1 -1
  49. package/dist-lib/react-native-host-modules.mjs +1 -1
  50. package/dist-lib/render-mode.cjs +1 -1
  51. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  52. package/dist-lib/sdk.cjs +1 -1
  53. package/dist-lib/sdk.mjs +1 -1
  54. package/dist-lib/skills.cjs +35 -38
  55. package/dist-lib/vite.cjs +1 -1
  56. package/package.json +1 -1
  57. package/src/shell-bridge-identity.ts +15 -0
  58. package/src/vite-plugin.ts +85 -52
package/README.md CHANGED
@@ -174,6 +174,9 @@ During source development, each Vite bridge owns one
174
174
  `~/.rnx/dev-bridges/<port>.json` heartbeat record. CLI defaults select the
175
175
  current `PORT_OFFSET`, then the current checkout, then the canonical `:7668`
176
176
  bridge, so concurrent worktrees cannot replace or delete one another's address.
177
+ Each Vite shell also publishes its exact bridge at `/__sootsim/bridge`, so a
178
+ launcher that reuses a shell from another isolated `RNX_HOME` stays in that
179
+ shell's bridge world without reading the other process's lockfile directory.
177
180
 
178
181
  **The sim** is a browser/Electron *page* launched by a CLI driver. Inside that
179
182
  page run three workers: the **shell worker** owns device and native state, the
@@ -86,6 +86,7 @@ export async function runDetox(args: string[], opts: RunDetoxOpts = {}): Promise
86
86
  prev === '-t' ||
87
87
  prev === '--testNamePattern' ||
88
88
  prev === '--grep' ||
89
+ prev === '--outputFile' ||
89
90
  prev === '--maxWorkers' ||
90
91
  prev === '--shard'
91
92
  )
@@ -154,11 +155,28 @@ export async function runDetox(args: string[], opts: RunDetoxOpts = {}): Promise
154
155
  // scope roots + testMatch to the discovered test dir so jest doesn't
155
156
  // scan the entire repo (which causes haste collisions in monorepos).
156
157
  const presetPath = resolve(resolveDetoxDir(), 'jest-preset.cjs')
158
+ // an external suite may optionally declare its own ignore patterns via e2e/jest-ignore.cjs
159
+ const suiteIgnoreFile = testDir ? join(testDir, 'e2e', 'jest-ignore.cjs') : null
160
+ let suiteIgnorePatterns: string[] = []
161
+ if (suiteIgnoreFile && existsSync(suiteIgnoreFile)) {
162
+ try {
163
+ const req = createRequire(import.meta.url)
164
+ const exported = req(suiteIgnoreFile)
165
+ suiteIgnorePatterns = Array.isArray(exported)
166
+ ? exported
167
+ : Array.isArray(exported.testPathIgnorePatterns)
168
+ ? exported.testPathIgnorePatterns
169
+ : []
170
+ } catch {}
171
+ }
157
172
  tempConfig = join(tmpdir(), `rnx-detox-${process.pid}.config.cjs`)
158
173
  const cfg = {
159
174
  rootDir: testDir,
160
175
  roots: ['<rootDir>'],
161
176
  testMatch: ['<rootDir>/**/*.test.ts', '<rootDir>/**/*.test.js'],
177
+ ...(suiteIgnorePatterns.length > 0
178
+ ? { testPathIgnorePatterns: suiteIgnorePatterns }
179
+ : {}),
162
180
  }
163
181
  writeFileSync(
164
182
  tempConfig,
@@ -475,9 +475,9 @@ function printRenderProfile(worker: string, rp: Record<string, any> | undefined)
475
475
  )
476
476
  }
477
477
  }
478
- if (rp.paragraphBuilds || rp.paragraphLayouts) {
478
+ if (rp.paragraphBuilds || rp.prewarmParagraphBuilds || rp.paragraphLayouts) {
479
479
  console.log(
480
- ` text shaping: ${rp.paragraphBuilds} shaped ${Number(rp.paragraphBuildMs ?? 0).toFixed(1)}ms · ${rp.paragraphLayouts} re-broken ${Number(rp.paragraphLayoutMs ?? 0).toFixed(1)}ms`,
480
+ ` text shaping: ${rp.paragraphBuilds} shaped on frame ${Number(rp.paragraphBuildMs ?? 0).toFixed(1)}ms · ${rp.prewarmParagraphBuilds ?? 0} shaped on idle ${Number(rp.prewarmParagraphBuildMs ?? 0).toFixed(1)}ms · ${rp.paragraphLayouts} re-broken ${Number(rp.paragraphLayoutMs ?? 0).toFixed(1)}ms (all phases)`,
481
481
  )
482
482
  }
483
483
  console.log(` blur: ${rp.avgBlurMs}ms`)
@@ -250,8 +250,6 @@ export const DECLARED_OUTBOUND_CALLS: Record<string, OutboundCallDeclaration> =
250
250
  { category: 'contrast_user_action', count: 1 },
251
251
  'packages/sootsim-engine/src/auth/shared-session.ts :: fetch :: `${CONTRAST_ORIGIN}/api/auth/sign-out`':
252
252
  { category: 'contrast_user_action', count: 1 },
253
- 'packages/sootsim-engine/src/auth/UploadsMenu.tsx :: fetch :: `${CONTRAST_ORIGIN}/api/preview/uploads?limit=20`':
254
- { category: 'contrast_user_action', count: 1 },
255
253
  "packages/sootsim-engine/src/billing/client.ts :: fetch :: apiUrl('/api/sootsim/billing/checkout')":
256
254
  { category: 'contrast_user_action', count: 1 },
257
255
  'packages/sootsim-engine/src/billing/client.ts :: fetch :: apiUrl(path)': {
package/detox/index.ts CHANGED
@@ -7,7 +7,12 @@ import * as path from 'path'
7
7
  import { chromium } from 'playwright'
8
8
  import { launchReapedChromeScoped } from '../../../scripts/lib/reap-browser'
9
9
  import { pollUntil } from '../src/poll-until'
10
- import { createExpect, createWaitFor } from './expectations'
10
+ import {
11
+ createExpect,
12
+ createWaitFor,
13
+ describeNodeVisibility,
14
+ isNodeVisible,
15
+ } from './expectations'
11
16
  import {
12
17
  dispatchTwoFingerGesture,
13
18
  dragScrollNode,
@@ -725,6 +730,11 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
725
730
  await waitForSootsimWorkletsIdle(page, 3000)
726
731
  const node = await findNodeByMatcher(matcher)
727
732
  if (!node) throw new Error(`element not found for tap: ${JSON.stringify(matcher)}`)
733
+ if (!isNodeVisible(node)) {
734
+ throw new Error(
735
+ `Cannot perform action due to constraint failure: element not visible (${describeNodeVisibility(node)}): ${JSON.stringify(matcher)}`,
736
+ )
737
+ }
728
738
  const defaultPoint = point ? null : await getDefaultTapPoint(page, node)
729
739
  const targetSootSimX =
730
740
  typeof point?.x === 'number'
@@ -750,6 +760,11 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
750
760
  const node = await findNodeByMatcher(matcher)
751
761
  if (!node)
752
762
  throw new Error(`element not found for multiTap: ${JSON.stringify(matcher)}`)
763
+ if (!isNodeVisible(node)) {
764
+ throw new Error(
765
+ `Cannot perform action due to constraint failure: element not visible (${describeNodeVisibility(node)}): ${JSON.stringify(matcher)}`,
766
+ )
767
+ }
753
768
  const center = getNodeCenter(node)
754
769
  const pageCoords = await sootsimToPage(page, center.x, center.y)
755
770
 
@@ -775,6 +790,11 @@ function createSootSimElement(matcher: Matcher): SootSimElement {
775
790
  const node = await findNodeByMatcher(matcher)
776
791
  if (!node)
777
792
  throw new Error(`element not found for longPress: ${JSON.stringify(matcher)}`)
793
+ if (!isNodeVisible(node)) {
794
+ throw new Error(
795
+ `Cannot perform action due to constraint failure: element not visible (${describeNodeVisibility(node)}): ${JSON.stringify(matcher)}`,
796
+ )
797
+ }
778
798
  const duration = typeof pointOrDuration === 'number' ? pointOrDuration : durationArg
779
799
  const target =
780
800
  typeof pointOrDuration === 'object'
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_DEFAULT_MS = 500;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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;
@@ -2319,6 +2319,11 @@ function createSootSimElement(matcher) {
2319
2319
  await waitForSootsimWorkletsIdle(page, 3e3);
2320
2320
  const node = await findNodeByMatcher(matcher);
2321
2321
  if (!node) throw new Error(`element not found for tap: ${JSON.stringify(matcher)}`);
2322
+ if (!isNodeVisible(node)) {
2323
+ throw new Error(
2324
+ `Cannot perform action due to constraint failure: element not visible (${describeNodeVisibility(node)}): ${JSON.stringify(matcher)}`
2325
+ );
2326
+ }
2322
2327
  const defaultPoint = point ? null : await getDefaultTapPoint(page, node);
2323
2328
  const targetSootSimX = typeof point?.x === "number" ? node.absolutePosition.x + point.x : defaultPoint?.x ?? node.absolutePosition.x + node.layout.width / 2;
2324
2329
  const targetSootSimY = typeof point?.y === "number" ? node.absolutePosition.y + point.y : defaultPoint?.y ?? node.absolutePosition.y + node.layout.height / 2;
@@ -2332,6 +2337,11 @@ function createSootSimElement(matcher) {
2332
2337
  const node = await findNodeByMatcher(matcher);
2333
2338
  if (!node)
2334
2339
  throw new Error(`element not found for multiTap: ${JSON.stringify(matcher)}`);
2340
+ if (!isNodeVisible(node)) {
2341
+ throw new Error(
2342
+ `Cannot perform action due to constraint failure: element not visible (${describeNodeVisibility(node)}): ${JSON.stringify(matcher)}`
2343
+ );
2344
+ }
2335
2345
  const center = getNodeCenter(node);
2336
2346
  const pageCoords = await sootsimToPage(page, center.x, center.y);
2337
2347
  for (let i = 0; i < times; i++) {
@@ -2352,6 +2362,11 @@ function createSootSimElement(matcher) {
2352
2362
  const node = await findNodeByMatcher(matcher);
2353
2363
  if (!node)
2354
2364
  throw new Error(`element not found for longPress: ${JSON.stringify(matcher)}`);
2365
+ if (!isNodeVisible(node)) {
2366
+ throw new Error(
2367
+ `Cannot perform action due to constraint failure: element not visible (${describeNodeVisibility(node)}): ${JSON.stringify(matcher)}`
2368
+ );
2369
+ }
2355
2370
  const duration = typeof pointOrDuration === "number" ? pointOrDuration : durationArg;
2356
2371
  const target = typeof pointOrDuration === "object" ? {
2357
2372
  x: node.absolutePosition.x + pointOrDuration.x,
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/public-brand.ts
4
4
  var name = "rnx";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-fingerprint-registry.ts
4
4
  var RNX_METRO_FINGERPRINT_SCHEMA_VERSION = 2;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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;
@@ -693,25 +693,25 @@ var init_capability_inventory_coverage = __esm({
693
693
  ios: {
694
694
  combined: {
695
695
  raw: {
696
- covered: 213,
697
- ratio: 0.153127246585,
696
+ covered: 233,
697
+ ratio: 0.167505391804,
698
698
  total: 1391
699
699
  },
700
700
  weighted: {
701
- covered: 1.38498343762,
702
- ratio: 0.289659691768,
701
+ covered: 1.63749741651,
702
+ ratio: 0.34247124121,
703
703
  total: 4.78141583721
704
704
  }
705
705
  },
706
706
  semantic: {
707
707
  raw: {
708
- covered: 213,
709
- ratio: 0.213855421687,
708
+ covered: 233,
709
+ ratio: 0.233935742972,
710
710
  total: 996
711
711
  },
712
712
  weighted: {
713
- covered: 1.38498343762,
714
- ratio: 0.578085386368,
713
+ covered: 1.63749741651,
714
+ ratio: 0.683483499504,
715
715
  total: 2.39581119032
716
716
  }
717
717
  },
@@ -1334,13 +1334,13 @@ var init_capability_outcomes2 = __esm({
1334
1334
  assessed: 0
1335
1335
  },
1336
1336
  ios: {
1337
- passedWeight: 0,
1338
- failedWeight: 0,
1339
- unassessedWeight: 0.957145688695477,
1340
- totalWeight: 0.957145688695477,
1341
- assessedWeight: 0,
1342
- compatibility: null,
1343
- assessed: 0
1337
+ passedWeight: 0.32201435438317577,
1338
+ failedWeight: 22084925244e-15,
1339
+ unassessedWeight: 0.6351092493870464,
1340
+ totalWeight: 0.9571456886954661,
1341
+ assessedWeight: 0.3220364393084198,
1342
+ compatibility: 0.9999314210364161,
1343
+ assessed: 0.3364549860192514
1344
1344
  }
1345
1345
  }
1346
1346
  },
@@ -1469,10 +1469,11 @@ var init_capability_outcomes2 = __esm({
1469
1469
  });
1470
1470
 
1471
1471
  // ../compat/src/generated/react-native-root-export-coverage.ts
1472
- var REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE;
1472
+ var REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE, REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE;
1473
1473
  var init_react_native_root_export_coverage = __esm({
1474
1474
  "../compat/src/generated/react-native-root-export-coverage.ts"() {
1475
1475
  "use strict";
1476
+ REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE = 0.99;
1476
1477
  REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE = 0.765;
1477
1478
  }
1478
1479
  });
@@ -1794,7 +1795,7 @@ var init_supported_native_packages = __esm({
1794
1795
  "react-native-fs",
1795
1796
  // coverage
1796
1797
  "react-native-gesture-handler",
1797
- // preset
1798
+ // preset+coverage
1798
1799
  "react-native-get-device-locale",
1799
1800
  // coverage
1800
1801
  "react-native-get-location",
@@ -1872,7 +1873,7 @@ var init_supported_native_packages = __esm({
1872
1873
  "react-native-randombytes",
1873
1874
  // coverage
1874
1875
  "react-native-reanimated",
1875
- // preset+visual-proof
1876
+ // preset+visual-proof+coverage
1876
1877
  "react-native-restart",
1877
1878
  // coverage
1878
1879
  "react-native-restart-newarch",
@@ -1884,7 +1885,7 @@ var init_supported_native_packages = __esm({
1884
1885
  "react-native-screen-corner-radius",
1885
1886
  // coverage
1886
1887
  "react-native-screens",
1887
- // preset+visual-proof
1888
+ // preset+visual-proof+coverage
1888
1889
  "react-native-securerandom",
1889
1890
  // coverage
1890
1891
  "react-native-settings",
@@ -1993,6 +1994,13 @@ var init_unsupported_packages = __esm({
1993
1994
  });
1994
1995
 
1995
1996
  // ../compat/src/registry.ts
1997
+ function scoredCoverage(packageName, estimate) {
1998
+ const outcomes = CAPABILITY_PACKAGE_OUTCOMES[packageName];
1999
+ const measured = outcomes.byPlatform.ios.compatibility;
2000
+ if (measured === null)
2001
+ return { coverage: estimate, estimate, coverageSource: "estimated" };
2002
+ return { coverage: measured, estimate, coverageSource: "measured", outcomes };
2003
+ }
1996
2004
  var COMPAT_CATEGORIES, POLYFILL_REGISTRY;
1997
2005
  var init_registry = __esm({
1998
2006
  "../compat/src/registry.ts"() {
@@ -2035,10 +2043,8 @@ var init_registry = __esm({
2035
2043
  range: ">=0.86.0 <0.87.0",
2036
2044
  // outcomes measure declared scenarios; strictCoverage remains an
2037
2045
  // independent equal-export implementation estimate.
2038
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native"].byPlatform.ios.compatibility,
2046
+ ...scoredCoverage("react-native", REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE),
2039
2047
  strictCoverage: REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE,
2040
- coverageSource: "measured",
2041
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native"],
2042
2048
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native"],
2043
2049
  note: "React Native 0.86 root surface with useful core rendering, input, scrolling, animation, list, platform, and native-module behavior",
2044
2050
  working: "all 99 React Native 0.86.2 public runtime root export names; flex and absolute layout, text shaping and wrapping, image loading and resize modes, touch and responder routing, controlled text input and keyboard presentation, vertical and horizontal scrolling with paging/snapping/sticky and maintained content, windowed/inverted/horizontal lists, common Animated graphs and composition, core LayoutAnimation create/update/delete geometry, alerts and action sheets, live platform/dimension/appearance state, and explicit native-module lookup",
@@ -2059,9 +2065,7 @@ var init_registry = __esm({
2059
2065
  },
2060
2066
  {
2061
2067
  range: ">=4.0.0 <5.0.0",
2062
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-reanimated"].byPlatform.ios.compatibility,
2063
- coverageSource: "measured",
2064
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-reanimated"],
2068
+ ...scoredCoverage("react-native-reanimated", 0.97),
2065
2069
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-reanimated"],
2066
2070
  note: "core animations, gestures, scroll, layout transitions, common CSS opacity, transform, and processed-color transitions and keyframes, keyboard, sensors, reduced motion, native view property reads, and direct static style snapshots",
2067
2071
  working: "useSharedValue, useAnimatedStyle/Props/Reaction, useDerivedValue, useAnimatedScrollHandler, useScrollViewOffset, useFrameCallback, useAnimatedRef, useAnimatedKeyboard, useAnimatedSensor, useReducedMotion, entering/exiting/layout transitions, css/createCSSAnimatedComponent with cubicBezier/linear/steps timing for common opacity and transform transitions, opacity and transform keyframes with retained forwards fill, withTiming/Spring/Decay/Delay/Sequence/Repeat/Clamp, interpolate, interpolateColor, runOnJS/UI, measure, scrollTo, getViewProp (layout, opacity, zIndex, backgroundColor, boxShadow), direct setViewStyle snapshots, Easing, createAnimatedComponent, Animated.View/Text/Image/ScrollView/FlatList",
@@ -2077,9 +2081,7 @@ var init_registry = __esm({
2077
2081
  { range: ">=2.0.0 <2.30.0", coverage: 0.7, note: "tap, pan, long press" },
2078
2082
  {
2079
2083
  range: ">=2.30.0 <3.0.0",
2080
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-gesture-handler"].byPlatform.ios.compatibility,
2081
- coverageSource: "measured",
2082
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-gesture-handler"],
2084
+ ...scoredCoverage("react-native-gesture-handler", 0.9),
2083
2085
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-gesture-handler"],
2084
2086
  note: "tap, pan, pinch, rotation, fling, long press, race, manual, simultaneous, force touch unavailable-hardware parity",
2085
2087
  working: "GestureDetector, Gesture.Tap/Pan/Pinch/Rotation/Fling/LongPress/ForceTouch/Manual/Race/Simultaneous/Exclusive/Hover, ForceTouchGestureHandler unavailable-hardware fallback (children render, forceTouchAvailable false, no force events), simultaneousWithExternalGesture/requireExternalGestureToFail/blocksExternalGesture, ScrollView/FlatList, Switch/RefreshControl, Pressable/Text, Touchables, BaseButton/RawButton/RectButton/BorderlessButton/PureNativeButton, Swipeable, ReanimatedSwipeable, DrawerLayout (the upstream component running on this seam: renderNavigationView, drawerPosition/drawerType/drawerWidth/edgeWidth, openDrawer/closeDrawer, edge-swipe drag, onDrawerOpen/onDrawerClose/onDrawerStateChanged), GestureHandlerRootView, createNativeWrapper, gestureHandlerRootHOC, PointerType/MouseButton/HoverEffect exports, velocity tracking, activeOffsets, multi-tap"
@@ -2094,9 +2096,7 @@ var init_registry = __esm({
2094
2096
  { range: ">=3.0.0 <4.0.0", coverage: 0.6, note: "basic screen container" },
2095
2097
  {
2096
2098
  range: ">=4.0.0",
2097
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-screens"].byPlatform.ios.compatibility,
2098
- coverageSource: "measured",
2099
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-screens"],
2099
+ ...scoredCoverage("react-native-screens", 0.95),
2100
2100
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-screens"],
2101
2101
  note: "screen container, stack, header config, search bar, navigation props",
2102
2102
  working: "Screen, ScreenContainer, ScreenStack, enableFreeze/freezeEnabled with delayed React freeze, Android modal/pageSheet push fallback, Android statusBarHidden/statusBarStyle/navigationBarHidden traits, push/pop slide, replaceAnimation push/pop direction, zoom/fade/fade_from_bottom transitions, edge swipe-back, parallax behind-screen, large title collapse, header (back button, inline/large title, custom left/center/right/search bar subviews, native header bar buttons/menus/badges, crossfade), formSheet custom initial detents/corner radius/grabber/undimmed range and stacked sheets, useHeaderHeight, useTransitionProgress, FullWindowOverlay, SearchBar with stacked and iOS 26 automatic/inline/integrated/integratedCentered/integratedButton toolbar placement, Tabs.Host/Screen, lifecycle callbacks (onAppear/onDisappear/onWillAppear/onWillDisappear), onDismissed",
@@ -2125,9 +2125,7 @@ var init_registry = __esm({
2125
2125
  versions: [
2126
2126
  {
2127
2127
  range: ">=13.0.0",
2128
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-svg"].byPlatform.ios.compatibility,
2129
- coverageSource: "measured",
2130
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-svg"],
2128
+ ...scoredCoverage("react-native-svg", 0.85),
2131
2129
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-svg"],
2132
2130
  note: "full CanvasKit rendering for shapes, text, XML, gradients, references, masks, clipping, and images; SVG filter elements skipped",
2133
2131
  working: "Svg, Path, Circle, Rect, Line, Ellipse, Polygon, Polyline, G, Text, TSpan, Defs, LinearGradient and RadialGradient with objectBoundingBox/userSpaceOnUse coordinates, focal points and gradientTransform, Stop, Mask, ClipPath, Image, Use and Symbol references, SvgXml, SvgUri, SvgAst, SvgFromXml, SvgCss, parse, fetchText, camelCase, shape transforms, fill/stroke/opacity/dasharray, currentColor, viewBox scaling",
@@ -2243,9 +2241,7 @@ var init_registry = __esm({
2243
2241
  versions: [
2244
2242
  {
2245
2243
  range: ">=1.0.0",
2246
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-keyboard-controller"].byPlatform.ios.compatibility,
2247
- coverageSource: "measured",
2248
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-keyboard-controller"],
2244
+ ...scoredCoverage("react-native-keyboard-controller", 0.88),
2249
2245
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-keyboard-controller"],
2250
2246
  note: "native bindings stubbed (KeyboardControllerNative, KeyboardEvents, FocusedInputEvents, WindowDimensionsEvents, KeyboardControllerView + sibling native views); upstream pure-JS components, hooks, animated module, and KeyboardAvoidingView resolve from node_modules unchanged",
2251
2247
  working: "every upstream JS export runs through reanimated worklets; Android KeyboardGestureArea drives the existing keyboard owner through drag progress, velocity/distance settling, cancellation, focus retention, and cleanup; supported exports include KeyboardProvider, KeyboardAvoidingView, KeyboardStickyView, KeyboardAwareScrollView, KeyboardToolbar, KeyboardGestureArea, useReanimatedKeyboardAnimation, useKeyboardAnimation, useKeyboardHandler, useGenericKeyboardHandler, useKeyboardController, useKeyboardState, useKeyboardContext, useReanimatedFocusedInput, useFocusedInputHandler, useResizeMode, useWindowDimensions, KeyboardEvents, FocusedInputEvents, WindowDimensionsEvents resize events, KeyboardController (dismiss/setFocusTo/isVisible/state/preload/setInputMode/setDefaultMode), KeyboardControllerView, OverKeyboardView, KeyboardBackgroundView, KeyboardExtender, ClippingScrollView, KeyboardToolbarGroupView, and AndroidSoftInputModes",
@@ -14302,6 +14298,7 @@ function matchCompatVersion(entry, declaredVersion) {
14302
14298
  return {
14303
14299
  ...resolution,
14304
14300
  coverage: selected.coverage,
14301
+ ...selected.estimate !== void 0 ? { estimate: selected.estimate } : {},
14305
14302
  coverageSource: selected.coverageSource ?? "estimated",
14306
14303
  ...selected.outcomes ? { outcomes: selected.outcomes } : {},
14307
14304
  note: selected.note,
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.445 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.447 | (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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnxsim",
3
- "version": "0.1.445",
3
+ "version": "0.1.447",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for rnx.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -0,0 +1,15 @@
1
+ export const SHELL_BRIDGE_IDENTITY_PATH = '/__sootsim/bridge'
2
+
3
+ export interface ShellBridgeIdentity {
4
+ schema: 1
5
+ bridgePort: number
6
+ }
7
+
8
+ export function isShellBridgeIdentity(value: unknown): value is ShellBridgeIdentity {
9
+ if (typeof value !== 'object' || value === null) return false
10
+ return (
11
+ Reflect.get(value, 'schema') === 1 &&
12
+ Number.isInteger(Reflect.get(value, 'bridgePort')) &&
13
+ Reflect.get(value, 'bridgePort') > 0
14
+ )
15
+ }
@@ -23,6 +23,10 @@ import {
23
23
  reactNativeDeepStubsForBuildResolver,
24
24
  } from '../../compat/src/stub-manifest.ts'
25
25
  import { resolveSootsimBridgePort } from './bridge-constants.ts'
26
+ import {
27
+ SHELL_BRIDGE_IDENTITY_PATH,
28
+ type ShellBridgeIdentity,
29
+ } from './shell-bridge-identity.ts'
26
30
  import {
27
31
  REANIMATED_WORKLETIZATION_REGEX,
28
32
  shouldApplyWorkletsPlugin,
@@ -842,63 +846,92 @@ export function wsBridgePlugin(options: { ownedBridgePort?: number } = {}): Plug
842
846
  name: 'sootsim-ws-bridge',
843
847
  apply: 'serve',
844
848
  configureServer(server) {
845
- if (boundPort) return
846
- const preferredPort = resolveSootsimBridgePort({
847
- explicitPort: process.env.SOOTSIM_BRIDGE_PORT,
848
- portOffset: process.env.PORT_OFFSET,
849
- })
850
- const readShellPort = () => {
851
- const addr = server.httpServer?.address()
852
- if (addr && typeof addr === 'object') return addr.port
853
- return server.config.server.port || null
854
- }
855
- const existing = viteBridgeProcesses.get(preferredPort)
856
- if (existing) {
857
- existing.owners.add(owner)
858
- existing.shellPort.read = readShellPort
859
- boundPort = existing.boundPort
860
- } else {
861
- // lazy import to avoid pulling ws into the main bundle.
862
- // note: the .ts extension is required on vite 8 / node ESM — without
863
- // it, import() throws "Cannot find module" and the bridge silently
864
- // never starts.
865
- const shellPort = { read: readShellPort }
866
- const host = import('./host/bridge-host.ts').then(({ SootSimBridgeHost }) => {
867
- return new SootSimBridgeHost({
868
- port: preferredPort,
869
- writeDevLockfile: true,
870
- getShellPort: () => shellPort.read(),
871
- })
849
+ if (!boundPort) {
850
+ const preferredPort = resolveSootsimBridgePort({
851
+ explicitPort: process.env.SOOTSIM_BRIDGE_PORT,
852
+ portOffset: process.env.PORT_OFFSET,
872
853
  })
873
- let entry: ViteBridgeProcessEntry
874
- boundPort = host
875
- .then((bridgeHost) => bridgeHost.startAsync({ silent: true }))
876
- .catch((err: unknown) => {
877
- if (viteBridgeProcesses.get(preferredPort) === entry) {
878
- viteBridgeProcesses.delete(preferredPort)
879
- }
880
- const message = err instanceof Error ? err.message : String(err)
881
- console.warn('[rnx] ws bridge failed to start:', message)
882
- return null
854
+ const readShellPort = () => {
855
+ const addr = server.httpServer?.address()
856
+ if (addr && typeof addr === 'object') return addr.port
857
+ return server.config.server.port || null
858
+ }
859
+ const existing = viteBridgeProcesses.get(preferredPort)
860
+ if (existing) {
861
+ existing.owners.add(owner)
862
+ existing.shellPort.read = readShellPort
863
+ boundPort = existing.boundPort
864
+ } else {
865
+ // lazy import to avoid pulling ws into the main bundle.
866
+ // note: the .ts extension is required on vite 8 / node ESM — without
867
+ // it, import() throws "Cannot find module" and the bridge silently
868
+ // never starts.
869
+ const shellPort = { read: readShellPort }
870
+ const host = import('./host/bridge-host.ts').then(({ SootSimBridgeHost }) => {
871
+ return new SootSimBridgeHost({
872
+ port: preferredPort,
873
+ writeDevLockfile: true,
874
+ getShellPort: () => shellPort.read(),
875
+ })
883
876
  })
884
- entry = {
885
- boundPort,
886
- close: async () => {
887
- try {
888
- await (await host).close()
889
- } catch {}
890
- },
891
- owners: new Set([owner]),
892
- shellPort,
877
+ let entry: ViteBridgeProcessEntry
878
+ boundPort = host
879
+ .then((bridgeHost) => bridgeHost.startAsync({ silent: true }))
880
+ .catch((err: unknown) => {
881
+ if (viteBridgeProcesses.get(preferredPort) === entry) {
882
+ viteBridgeProcesses.delete(preferredPort)
883
+ }
884
+ const message = err instanceof Error ? err.message : String(err)
885
+ console.warn('[rnx] ws bridge failed to start:', message)
886
+ return null
887
+ })
888
+ entry = {
889
+ boundPort,
890
+ close: async () => {
891
+ try {
892
+ await (await host).close()
893
+ } catch {}
894
+ },
895
+ owners: new Set([owner]),
896
+ shellPort,
897
+ }
898
+ viteBridgeProcesses.set(preferredPort, entry)
893
899
  }
894
- viteBridgeProcesses.set(preferredPort, entry)
900
+
901
+ server.httpServer?.once('close', () => {
902
+ const entry = viteBridgeProcesses.get(preferredPort)
903
+ if (!entry || !entry.owners.delete(owner) || entry.owners.size > 0) return
904
+ viteBridgeProcesses.delete(preferredPort)
905
+ void entry.close()
906
+ })
895
907
  }
896
908
 
897
- server.httpServer?.once('close', () => {
898
- const entry = viteBridgeProcesses.get(preferredPort)
899
- if (!entry || !entry.owners.delete(owner) || entry.owners.size > 0) return
900
- viteBridgeProcesses.delete(preferredPort)
901
- void entry.close()
909
+ if (!boundPort) throw new Error('rnx bridge identity was not initialized')
910
+ const identityPort = boundPort
911
+ server.middlewares.use((req, res, next) => {
912
+ if (req.url?.split('?')[0] !== SHELL_BRIDGE_IDENTITY_PATH) {
913
+ next()
914
+ return
915
+ }
916
+ void identityPort
917
+ .then((bridgePort) => {
918
+ if (bridgePort === null) {
919
+ res.statusCode = 503
920
+ res.end('rnx bridge unavailable')
921
+ return
922
+ }
923
+ const identity = {
924
+ schema: 1,
925
+ bridgePort,
926
+ } satisfies ShellBridgeIdentity
927
+ res.setHeader('Content-Type', 'application/json')
928
+ res.setHeader('Cache-Control', 'no-store')
929
+ res.end(JSON.stringify(identity))
930
+ })
931
+ .catch(() => {
932
+ res.statusCode = 503
933
+ res.end('rnx bridge unavailable')
934
+ })
902
935
  })
903
936
  },
904
937
  // publish the bound port to the page. head-prepend so it lands before the