rnxsim 0.1.317 → 0.1.319

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 (183) hide show
  1. package/cli/bin.ts +1 -8
  2. package/cli/commands/debug.ts +1 -8
  3. package/cli/commands/detox.ts +16 -4
  4. package/cli/commands/flow.ts +1 -2
  5. package/cli/commands/inspect/wait-event.ts +1 -1
  6. package/cli/commands/inspect/wait-selector.ts +1 -1
  7. package/cli/commands/inspect.ts +56 -33
  8. package/cli/commands/maestro.ts +1 -1
  9. package/cli/commands/profile.ts +4 -6
  10. package/cli/commands/runtime.ts +0 -4
  11. package/cli/commands/storage.ts +1 -1
  12. package/cli/commands/telemetry.ts +0 -2
  13. package/cli/commands/timeline.ts +2 -4
  14. package/cli/parse-args.ts +0 -3
  15. package/detox/index.ts +155 -15
  16. package/detox/jest-preset.cjs +0 -1
  17. package/dist-cli/bin.js +5 -5
  18. package/dist-cli/chunks/{agent-EKGLRJEN.js → agent-Q4VAKGOL.js} +2 -2
  19. package/dist-cli/chunks/{agent-wrapper-FONNWB7J.js → agent-wrapper-Q2O4TR7H.js} +2 -2
  20. package/dist-cli/chunks/{app-fonts-XPM54HRY.js → app-fonts-B7UP3XTI.js} +2 -2
  21. package/dist-cli/chunks/{assert-PILHTZRZ.js → assert-NAFO4KMH.js} +2 -2
  22. package/dist-cli/chunks/{auth-Q2VUD5NQ.js → auth-CNUGYLCX.js} +2 -2
  23. package/dist-cli/chunks/{beta-P4XLZ3KL.js → beta-GN5BSED6.js} +2 -2
  24. package/dist-cli/chunks/{camera-O4PEVPI4.js → camera-EJRFUEXV.js} +2 -2
  25. package/dist-cli/chunks/{chunk-R6DDJVBB.js → chunk-2TNUPISH.js} +2 -2
  26. package/dist-cli/chunks/{chunk-BJ5CYKA7.js → chunk-3DEQXXSF.js} +4 -4
  27. package/dist-cli/chunks/{chunk-VB2ZZ4JI.js → chunk-3F3R7BM4.js} +2 -2
  28. package/dist-cli/chunks/{chunk-CUILVYWI.js → chunk-4UY4JSQ4.js} +1 -1
  29. package/dist-cli/chunks/chunk-522E7BRF.js +937 -0
  30. package/dist-cli/chunks/{chunk-NF63TOPI.js → chunk-5ABSWU6L.js} +2 -2
  31. package/dist-cli/chunks/{chunk-NA4AMR2E.js → chunk-5KXQT465.js} +1 -1
  32. package/dist-cli/chunks/{chunk-6WG4RQKM.js → chunk-6BGXKWGF.js} +2 -2
  33. package/dist-cli/chunks/{chunk-67ZR7PU7.js → chunk-72VB52IV.js} +1 -1
  34. package/dist-cli/chunks/{chunk-JQ4Y2XVT.js → chunk-76EVUPAL.js} +1 -1
  35. package/dist-cli/chunks/{chunk-OWADERTW.js → chunk-7DABL656.js} +2 -2
  36. package/dist-cli/chunks/{chunk-WWW5DC3G.js → chunk-7IW3PBRN.js} +2 -2
  37. package/dist-cli/chunks/{chunk-S23KHLTR.js → chunk-AX7PASOS.js} +2 -2
  38. package/dist-cli/chunks/{chunk-SZIPYT3D.js → chunk-AZ6S36CJ.js} +2 -2
  39. package/dist-cli/chunks/{chunk-T6W3B2KA.js → chunk-B27W3QWS.js} +1 -1
  40. package/dist-cli/chunks/{chunk-GQ3D2D4O.js → chunk-BQEWRZON.js} +1 -1
  41. package/dist-cli/chunks/{chunk-ADAIY3DX.js → chunk-BSCOA6LL.js} +2 -2
  42. package/dist-cli/chunks/{chunk-NUSBQSRQ.js → chunk-BVVUWEDG.js} +2 -2
  43. package/dist-cli/chunks/chunk-DD6F2WOA.js +4 -0
  44. package/dist-cli/chunks/{chunk-J4MCKLWE.js → chunk-DIADYUIH.js} +4 -4
  45. package/dist-cli/chunks/{chunk-KO7UG262.js → chunk-GHHVBATM.js} +2 -2
  46. package/dist-cli/chunks/{chunk-QCQQ2VDW.js → chunk-HCM7K4AU.js} +2 -2
  47. package/dist-cli/chunks/chunk-HPO2HNJX.js +124 -0
  48. package/dist-cli/chunks/{chunk-67OCUGZD.js → chunk-IHBAZ6ZJ.js} +2 -2
  49. package/dist-cli/chunks/{chunk-QGPNBTHT.js → chunk-IJYWC6QT.js} +2 -2
  50. package/dist-cli/chunks/{chunk-JZXCQEKO.js → chunk-JWAF5GXK.js} +2 -2
  51. package/dist-cli/chunks/{chunk-LSC2HFAB.js → chunk-JZIFPU64.js} +1 -1
  52. package/dist-cli/chunks/{chunk-RCPPPW7B.js → chunk-KMOLZN54.js} +1 -1
  53. package/dist-cli/chunks/{chunk-GMWPCQ63.js → chunk-L5JZXGYY.js} +1 -1
  54. package/dist-cli/chunks/{chunk-YRVJHPCU.js → chunk-LKO7E4VO.js} +2 -2
  55. package/dist-cli/chunks/{chunk-WJVNVBAI.js → chunk-M52VGRRN.js} +1 -1
  56. package/dist-cli/chunks/{chunk-7Q7IQ2SS.js → chunk-PFRV3TNY.js} +2 -2
  57. package/dist-cli/chunks/{chunk-3G7I72XV.js → chunk-PYDVLJOW.js} +2 -2
  58. package/dist-cli/chunks/{chunk-ATOUAYJP.js → chunk-QNNCKWZF.js} +1 -1
  59. package/dist-cli/chunks/{chunk-ODHQKXLB.js → chunk-R4JD7RQ5.js} +2 -2
  60. package/dist-cli/chunks/chunk-RIRZMX6H.js +4 -0
  61. package/dist-cli/chunks/{chunk-FIPCJ5OS.js → chunk-RVKU4F4H.js} +1 -1
  62. package/dist-cli/chunks/{chunk-A3GVXVSG.js → chunk-S5XIMHEZ.js} +2 -2
  63. package/dist-cli/chunks/{chunk-HJKQ6NEU.js → chunk-SPHYBQAZ.js} +2 -2
  64. package/dist-cli/chunks/chunk-TJSU45JD.js +4 -0
  65. package/dist-cli/chunks/{chunk-R6MEMDNB.js → chunk-UGYANOZR.js} +2 -2
  66. package/dist-cli/chunks/{chunk-W4YHMJOO.js → chunk-VB6FBQBW.js} +2 -2
  67. package/dist-cli/chunks/{chunk-5XVHBFAT.js → chunk-VLT3KCQT.js} +3 -3
  68. package/dist-cli/chunks/{chunk-OO5D7IJE.js → chunk-VQJMFDUN.js} +1 -1
  69. package/dist-cli/chunks/{chunk-EL23MRFL.js → chunk-WUZNWEBT.js} +1 -1
  70. package/dist-cli/chunks/{chunk-5BYFLVSZ.js → chunk-X2AHIPGY.js} +1 -1
  71. package/dist-cli/chunks/{chunk-OXSCF4UD.js → chunk-XJHAGKJD.js} +2 -2
  72. package/dist-cli/chunks/{chunk-RG3CME4Y.js → chunk-YPDFFAE7.js} +2 -2
  73. package/dist-cli/chunks/{chunk-HF4NZ5SD.js → chunk-YS6EWKGV.js} +2 -2
  74. package/dist-cli/chunks/{chunk-2SAOKV6V.js → chunk-YT6RDBLT.js} +1 -1
  75. package/dist-cli/chunks/{chunk-KZS5VM6Y.js → chunk-Z4LSUN4M.js} +1 -1
  76. package/dist-cli/chunks/{chunk-TUFL7CQK.js → chunk-Z72QDFQG.js} +2 -2
  77. package/dist-cli/chunks/{chunk-ARICQ4CG.js → chunk-ZH5X2H73.js} +2 -2
  78. package/dist-cli/chunks/{cleanup-O6IWLGDY.js → cleanup-GBLORG7C.js} +2 -2
  79. package/dist-cli/chunks/cli-version-6C4ZR7I7.js +4 -0
  80. package/dist-cli/chunks/{compat-562BT6JM.js → compat-OIWTQTTQ.js} +2 -2
  81. package/dist-cli/chunks/{config-7RO6O45J.js → config-DZCL6YFH.js} +2 -2
  82. package/dist-cli/chunks/{control-XYKZG442.js → control-MY5IZSCI.js} +2 -2
  83. package/dist-cli/chunks/daemon-42K3PILG.js +4 -0
  84. package/dist-cli/chunks/{debug-3VCEOVRM.js → debug-6UQUAZKP.js} +4 -4
  85. package/dist-cli/chunks/{desktop-K3PPS6VL.js → desktop-DFBFLSQ3.js} +3 -3
  86. package/dist-cli/chunks/detox-CIHUJOCI.js +52 -0
  87. package/dist-cli/chunks/{device-NZCR7JIN.js → device-7SOHSSJO.js} +2 -2
  88. package/dist-cli/chunks/{diagnose-VVJY6RF2.js → diagnose-P2FMX5HU.js} +2 -2
  89. package/dist-cli/chunks/{disk-cleanup-2VJMHUIY.js → disk-cleanup-6PP5CQVO.js} +2 -2
  90. package/dist-cli/chunks/drivers-CFJGYQFX.js +4 -0
  91. package/dist-cli/chunks/{film-CEMBA2DA.js → film-2WWHMPGU.js} +3 -3
  92. package/dist-cli/chunks/flow-KL7ZTVKL.js +4 -0
  93. package/dist-cli/chunks/help-T2OCMQPI.js +4 -0
  94. package/dist-cli/chunks/hidden-runtime-alias-ZZMC3E6R.js +4 -0
  95. package/dist-cli/chunks/{home-paths-TKPTU62O.js → home-paths-Y6X4LFSU.js} +2 -2
  96. package/dist-cli/chunks/inspect-PVMJQHMF.js +4 -0
  97. package/dist-cli/chunks/install-desktop-NHQZI4EH.js +4 -0
  98. package/dist-cli/chunks/{login-CIQT627K.js → login-BARKKDRL.js} +4 -4
  99. package/dist-cli/chunks/{logout-V2DJVY3U.js → logout-YVUMTGMP.js} +2 -2
  100. package/dist-cli/chunks/{maestro-YSZ6ZC5C.js → maestro-UPVELJ7G.js} +7 -7
  101. package/dist-cli/chunks/{maestro-generate-6JUELIXK.js → maestro-generate-EP76F4GB.js} +3 -3
  102. package/dist-cli/chunks/{mode-D4HQ6YN3.js → mode-ULOBJKDO.js} +2 -2
  103. package/dist-cli/chunks/{optional-demo-registry-AC6YJKT4.js → optional-demo-registry-O6RANNU3.js} +2 -2
  104. package/dist-cli/chunks/{perf-5GRZ4G5X.js → perf-ANPUHMRS.js} +2 -2
  105. package/dist-cli/chunks/{permissions-4V6UVWGK.js → permissions-NGMRAUGD.js} +2 -2
  106. package/dist-cli/chunks/{record-IDNLOQLR.js → record-CBO3QGRB.js} +3 -3
  107. package/dist-cli/chunks/{report-issue-TF6R77TT.js → report-issue-K7XKNJ2D.js} +2 -2
  108. package/dist-cli/chunks/reset-FXAX2W5A.js +4 -0
  109. package/dist-cli/chunks/runtime-GNCU66RR.js +4 -0
  110. package/dist-cli/chunks/{screenshot-command-CHJN7WUT.js → screenshot-command-KZZSYRX5.js} +3 -3
  111. package/dist-cli/chunks/{screenshot-layers-MSDCGYNE.js → screenshot-layers-Z3KSMJ3R.js} +2 -2
  112. package/dist-cli/chunks/{screenshots-capture-OGP3OQYR.js → screenshots-capture-QTB5GQNA.js} +2 -2
  113. package/dist-cli/chunks/{serve-GPBLCMXX.js → serve-JKTMCDG2.js} +2 -2
  114. package/dist-cli/chunks/{setup-S2KYWZZO.js → setup-GCAPEHZH.js} +2 -2
  115. package/dist-cli/chunks/{skills-AUS5DTUE.js → skills-Y4YDYEKA.js} +2 -2
  116. package/dist-cli/chunks/{state-QLYTMIKF.js → state-3HTG2CZU.js} +2 -2
  117. package/dist-cli/chunks/storage-XQE2XZJM.js +37 -0
  118. package/dist-cli/chunks/store-22QXHYUS.js +4 -0
  119. package/dist-cli/chunks/telemetry-VYGOHQWW.js +4 -0
  120. package/dist-cli/chunks/{timeline-EUHPXPFP.js → timeline-XYACO63Y.js} +3 -3
  121. package/dist-cli/chunks/{upgrade-JMMBM3ZN.js → upgrade-EVQTCUSG.js} +2 -2
  122. package/dist-cli/chunks/upload-XH3RQR4U.js +4 -0
  123. package/dist-cli/chunks/{version-QCF7RCA2.js → version-NLGYSRXS.js} +2 -2
  124. package/dist-cli/chunks/{web-WPYHMOVH.js → web-25OBFWDS.js} +2 -2
  125. package/dist-cli/chunks/{what-happened-3RNZP4MB.js → what-happened-MRN6CH5W.js} +2 -2
  126. package/dist-lib/agent-daemon-client.cjs +1 -1
  127. package/dist-lib/agent-events.cjs +1 -1
  128. package/dist-lib/agent-identity.cjs +1 -1
  129. package/dist-lib/agent-sessions.cjs +1 -1
  130. package/dist-lib/attached-projects.cjs +1 -1
  131. package/dist-lib/auth/shared-session.cjs +1 -1
  132. package/dist-lib/backend-origin.cjs +1 -1
  133. package/dist-lib/beta.cjs +1 -1
  134. package/dist-lib/beta.mjs +1 -1
  135. package/dist-lib/bridge-constants.cjs +1 -1
  136. package/dist-lib/bridge-contract.cjs +1 -1
  137. package/dist-lib/cli-constants.cjs +1 -1
  138. package/dist-lib/config.cjs +1 -1
  139. package/dist-lib/detox/index.cjs +93 -11
  140. package/dist-lib/detox/jest-preset.cjs +0 -1
  141. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  142. package/dist-lib/home-paths.cjs +1 -1
  143. package/dist-lib/host/bridge-host.cjs +1 -1
  144. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  145. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  146. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  147. package/dist-lib/host/websocket-proxy.cjs +1 -1
  148. package/dist-lib/index.cjs +1 -1
  149. package/dist-lib/jump-to-source-babel.cjs +1 -1
  150. package/dist-lib/menu.cjs +1 -1
  151. package/dist-lib/menu.mjs +1 -1
  152. package/dist-lib/metro.cjs +1 -1
  153. package/dist-lib/profiles.cjs +1 -1
  154. package/dist-lib/public-brand.cjs +1 -1
  155. package/dist-lib/render-mode.cjs +1 -1
  156. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  157. package/dist-lib/sdk.cjs +1 -1
  158. package/dist-lib/sdk.mjs +1 -1
  159. package/dist-lib/skills.cjs +62 -28
  160. package/dist-lib/vite.cjs +1 -1
  161. package/package.json +1 -1
  162. package/skills/contrast/SKILL.md +0 -1
  163. package/skills/rnx-perf/SKILL.md +17 -0
  164. package/src/vite-plugin.ts +74 -43
  165. package/dist-cli/chunks/chunk-744422UA.js +0 -4
  166. package/dist-cli/chunks/chunk-CHKTOWRH.js +0 -939
  167. package/dist-cli/chunks/chunk-O6OIXJ54.js +0 -4
  168. package/dist-cli/chunks/chunk-VUKB6JW3.js +0 -125
  169. package/dist-cli/chunks/cli-version-F2R7SUY7.js +0 -4
  170. package/dist-cli/chunks/daemon-WE37QLQC.js +0 -4
  171. package/dist-cli/chunks/detox-6ODNKASO.js +0 -52
  172. package/dist-cli/chunks/drivers-44ZJZ37B.js +0 -4
  173. package/dist-cli/chunks/flow-ORGIXYVS.js +0 -4
  174. package/dist-cli/chunks/help-UW52M7FZ.js +0 -4
  175. package/dist-cli/chunks/hidden-runtime-alias-R2QQLZZA.js +0 -4
  176. package/dist-cli/chunks/inspect-TNFI6C6G.js +0 -4
  177. package/dist-cli/chunks/install-desktop-NEJEPL4L.js +0 -4
  178. package/dist-cli/chunks/reset-D7WAFOZO.js +0 -4
  179. package/dist-cli/chunks/runtime-O5TNQBYH.js +0 -4
  180. package/dist-cli/chunks/storage-2MNS4TYO.js +0 -37
  181. package/dist-cli/chunks/store-UT52X7AA.js +0 -4
  182. package/dist-cli/chunks/telemetry-CAQVTTHY.js +0 -4
  183. package/dist-cli/chunks/upload-CEX4UBJL.js +0 -4
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.317 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.319 | (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.317 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.319 | (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.317 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.319 | (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.317 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.319 | (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;
@@ -577,7 +577,7 @@ var init_registry = __esm({
577
577
  "react-native-safe-area-context": {
578
578
  category: "Essentials",
579
579
  stubType: "native",
580
- proofCoverage: 0.7,
580
+ proofCoverage: 0.95,
581
581
  versions: [
582
582
  {
583
583
  range: ">=4.0.0",
@@ -1141,13 +1141,49 @@ var init_registry = __esm({
1141
1141
  versions: [
1142
1142
  {
1143
1143
  range: ">=55.0.0",
1144
- coverage: 0.9,
1145
- note: "SymbolView renders the shared SootSim SF Symbol vector and preserves the requested system name for frozen Design replay. Unknown names use the supplied fallback. unstable_getMaterialSymbolSourceAsync returns a stable URI/size shape so apps that gate on the source resolve correctly.",
1146
- working: "SymbolView, name object/string selection (string | { ios, android, web }), size/tintColor styling, fallback rendering, unstable_getMaterialSymbolSourceAsync",
1144
+ coverage: 0.95,
1145
+ note: "SymbolView renders the shared SootSim SF Symbol vector with support for monochrome, hierarchical, palette, and multicolor rendering, weight-based stroke width, and scale sizing. Unknown names use the supplied fallback. unstable_getMaterialSymbolSourceAsync returns a stable URI/size shape so apps that gate on the source resolve correctly.",
1146
+ working: "SymbolView (named + default export), name object/string selection (string | { ios, android, web }), size, tintColor, colors array, type (monochrome/hierarchical/palette/multicolor), weight stroke-width scaling, scale multiplier sizing, animationSpec/resizeMode props, fallback rendering, unstable_getMaterialSymbolSourceAsync, type exports",
1147
1147
  missing: "bundled SF Symbols font (Apple license), bundled Material Symbols font (size budget), animation/effect modifiers (.bounce, .scale)"
1148
1148
  }
1149
1149
  ]
1150
1150
  },
1151
+ "expo-android-shared-preferences": {
1152
+ category: "Storage & Data",
1153
+ stubType: "native",
1154
+ versions: [
1155
+ {
1156
+ range: ">=1.0.0",
1157
+ coverage: 1,
1158
+ note: "native-seam only \u2014 upstream Expo module wrapper runs from the bundle; ExpoAndroidSharedPreferences provides full persistent key-value SharedPreferences operations backed by tenant localStorage",
1159
+ working: "getString, setString, getInt, setInt, getLong, setLong, getFloat, setFloat, getBoolean, setBoolean, contains, remove, clear, default values, filename partitioning, and change listener subscriptions"
1160
+ }
1161
+ ]
1162
+ },
1163
+ "expo-winter-fetch": {
1164
+ category: "Networking",
1165
+ stubType: "native",
1166
+ versions: [
1167
+ {
1168
+ range: ">=1.0.0",
1169
+ coverage: 1,
1170
+ note: "routes expo/fetch calls through the runtime fetch router, preserving the browser-native Response prototype chain and CORS proxy routing",
1171
+ working: "fetch function (named + default export), RequestInfo/URL and RequestInit handling, response JSON/text streaming"
1172
+ }
1173
+ ]
1174
+ },
1175
+ "expo-winter-formdata": {
1176
+ category: "Networking",
1177
+ stubType: "native",
1178
+ versions: [
1179
+ {
1180
+ range: ">=1.0.0",
1181
+ coverage: 1,
1182
+ note: "installFormDataPatch preserves browser-native FormData class and prototype intact, allowing browser networking stack uploads and WinterCG methods without undefined _parts crashes",
1183
+ working: "installFormDataPatch (named + default export), append, set, get, getAll, has, delete, entries, keys, values, and iterators"
1184
+ }
1185
+ ]
1186
+ },
1151
1187
  "expo-liquid-glass-view": {
1152
1188
  category: "UI Components",
1153
1189
  stubType: "native",
@@ -1180,10 +1216,10 @@ var init_registry = __esm({
1180
1216
  versions: [
1181
1217
  {
1182
1218
  range: ">=17.0.0",
1183
- coverage: 0.4,
1184
- note: "the published SDK 57 package runs unchanged against one ExpoLocation native seam with the exact SDK subscriber contract and the shared app-scoped permission registry; the tenant worker does not currently expose browser position or orientation sources, and the simulator does not send location data to a third-party geocoder",
1185
- working: "upstream enums, validation, subscriber bookkeeping and permission hooks; getProviderStatusAsync, foreground/background permission getters and requests, hasServicesEnabledAsync, getLastKnownPositionAsync before a reading, unavailable motion-permission state, and isBackgroundLocationAvailableAsync=false; the native watch-id event routing, removal, and heading accuracy mapping are ready for a real tenant sensor source",
1186
- missing: "a worker-to-host position and device-orientation source, current and watched position readings, heading readings, an app-selected geocoder, motion activity readings, background location task registration and delivery, geofencing, and Android network-provider enablement"
1219
+ coverage: 0.6,
1220
+ note: "the published SDK 57 package runs unchanged against one ExpoLocation native seam backed by host browser geolocation and the shared app-scoped permission registry",
1221
+ working: "upstream enums, validation, subscriber bookkeeping and permission hooks; getProviderStatusAsync, getCurrentPositionAsync, filtered getLastKnownPositionAsync, watchPositionAsync with native watch-id event routing and removal, foreground/background permission getters and requests, hasServicesEnabledAsync, unavailable motion-permission state, and isBackgroundLocationAvailableAsync=false",
1222
+ missing: "device-orientation heading readings, an app-selected geocoder, motion activity readings, background location task registration and delivery, geofencing, and Android network-provider enablement"
1187
1223
  }
1188
1224
  ]
1189
1225
  },
@@ -1279,7 +1315,7 @@ var init_registry = __esm({
1279
1315
  range: ">=0.7.0",
1280
1316
  coverage: 0.9,
1281
1317
  note: "MenuView renders real iOS-style canvas menu via sootsim ContextMenu",
1282
- working: "MenuView, actions (title, subtitle, id, state, attributes: disabled/destructive/hidden), subactions (nested menus), onPressAction, shouldOpenOnLongPress, themeVariant, isAnchoredToRight, NativeActionEvent",
1318
+ working: "MenuView, actions (title, subtitle, id, state, attributes: disabled/destructive/hidden), subactions (nested menus), onPressAction, onOpenMenu, onCloseMenu, shouldOpenOnLongPress, themeVariant, isAnchoredToRight, NativeActionEvent",
1283
1319
  missing: "keepsMenuPresented attribute (iOS 16+), image/imageColor rendering in menu items, inline element actions"
1284
1320
  }
1285
1321
  ]
@@ -3117,10 +3153,10 @@ var init_registry = __esm({
3117
3153
  versions: [
3118
3154
  {
3119
3155
  range: ">=1.0.0",
3120
- coverage: 0,
3121
- note: "the reference iOS simulator performs this package's behavior. SootSim currently provides only this unsupported shape: all lock/unlock are noops : orientation cannot be forced in browser. imports and API shape receive no behavior credit",
3122
- working: "lockToPortrait, lockToLandscape, lockToLandscapeLeft/Right, lockToPortraitUpsideDown, lockToAllOrientationsButUpsideDown, unlockAllOrientations, getOrientation (returns PORTRAIT), getAutoRotateState (returns true), all add/remove listener methods, orientation constants",
3123
- missing: "lockAsync not wired to browser ScreenOrientation API"
3156
+ coverage: 0.5,
3157
+ note: "native-seam: the published package runs unchanged against the shared simulator orientation state. lock intent, getters, component/hooks, and NativeEventEmitter subscriptions work while the fixed device frame remains portrait.",
3158
+ working: "published Orientation class, OrientationLocker component, hooks, OrientationType/constants, configure, lockToPortrait/PortraitUpsideDown/Landscape/Left/Right/AllButUpsideDown, unlockAllOrientations, isLocked, getInitialOrientation/getOrientation/getDeviceOrientation/getAutoRotateState, orientationDidChange/lockDidChange listeners with removal",
3159
+ missing: "the fixed simulator viewport does not physically rotate and there is no device orientation sensor, so deviceOrientationDidChange never fires"
3124
3160
  }
3125
3161
  ]
3126
3162
  },
@@ -4584,9 +4620,10 @@ var init_registry = __esm({
4584
4620
  versions: [
4585
4621
  {
4586
4622
  range: ">=2.0.0",
4587
- coverage: 0,
4588
- note: "the reference iOS simulator performs this package's behavior. SootSim currently provides only this unsupported shape: setItems accepts; getItems returns []; isSupported=false; initial=null; addListener returns a removable subscription that never fires. imports and API shape receive no behavior credit",
4589
- missing: "no 3D Touch / long-press app-icon shortcuts in browser. apps that gate quick-action UI on isSupported take their fallback path"
4623
+ coverage: 0.5,
4624
+ note: "native-seam only. The published package runs unchanged against the shared dynamic shortcut registry used by the React Native quick-action packages.",
4625
+ working: "setItems and clearing, isSupported, maxCount=4, initial=null, removable addListener subscriptions, and shared item state across expo-quick-actions, react-native-quick-actions, react-native-actions-shortcuts, and @rn-org/react-native-shortcuts",
4626
+ missing: "the simulator home-screen app icon does not display the registered shortcuts yet, so there is no user-selected onQuickAction event or initial launch action"
4590
4627
  }
4591
4628
  ]
4592
4629
  },
@@ -6281,10 +6318,11 @@ var init_registry = __esm({
6281
6318
  stubType: "native",
6282
6319
  versions: [
6283
6320
  {
6284
- range: ">=1.0.0",
6285
- coverage: 0,
6286
- note: "the reference iOS simulator performs this package's behavior. SootSim currently provides only this unsupported shape: getInitialOrientation/getDeviceOrientation/getInterfaceOrientation report Portrait; lockTo/unlock accepted; full Orientation enum exposed. imports and API shape receive no behavior credit",
6287
- missing: "sootsim canvas is portrait-only; this matches"
6321
+ range: ">=3.0.0",
6322
+ coverage: 0.5,
6323
+ note: "native-seam: the published package runs unchanged against the shared simulator orientation state, including its TurboModule and codegen event surface.",
6324
+ working: "Orientation/OrientationType/AutoRotation enums, getInterfaceOrientation/getDeviceOrientation, lockTo/unlock/isLocked, resetSupportedInterfaceOrientations, interface and lock subscriptions, hooks, human-readable conversion helpers, isLockableOrientation; lock state stays consistent with expo-screen-orientation and react-native-orientation-locker",
6325
+ missing: "the fixed simulator viewport does not physically rotate and there is no device orientation sensor, so device-orientation subscriptions never fire; iOS reports auto-rotation as unknown exactly like upstream"
6288
6326
  }
6289
6327
  ]
6290
6328
  },
@@ -7012,10 +7050,10 @@ var init_registry = __esm({
7012
7050
  versions: [
7013
7051
  {
7014
7052
  range: ">=2.0.0",
7015
- coverage: 0.4,
7053
+ coverage: 0.5,
7016
7054
  note: "orientation state and subscriptions have the right shape, but lock calls never rotate the viewport as they do in the reference iOS simulator",
7017
- working: "startOrientationTracking/stopOrientationTracking, lockToPortrait/lockToLandscape/unlockAllOrientations (intent tracked \u2192 isLocked correct), getCurrentOrientation (PORTRAIT \u2014 real), isLocked, getDeviceAutoRotateStatus (null, faithful iOS), onOrientationChange/onLockOrientationChange (removable subscriptions), all enums",
7018
- missing: "a browser cannot force device rotation, so lock* does not visually rotate and orientation-change callbacks never fire (faithful iOS-sim/browser limitation, identical to react-native-orientation-locker \u2014 not a sootsim-specific gap)"
7055
+ working: "startOrientationTracking/stopOrientationTracking, lockToPortrait/lockToLandscape/unlockAllOrientations (shared intent tracked \u2192 isLocked correct), getCurrentOrientation (requested interface orientation), isLocked, getDeviceAutoRotateStatus (null, faithful iOS), onOrientationChange/onLockOrientationChange (emitting removable subscriptions), all enums",
7056
+ missing: "the fixed simulator viewport does not physically rotate and there is no device orientation sensor"
7019
7057
  }
7020
7058
  ]
7021
7059
  },
@@ -18739,18 +18777,14 @@ async function runRuntime(args, opts = {}) {
18739
18777
  case "install":
18740
18778
  return runtimeInstall(rest, opts);
18741
18779
  case "list":
18742
- case "ls":
18743
18780
  return runtimeList(rest);
18744
18781
  case "use":
18745
18782
  return runtimeUse(rest);
18746
18783
  case "remove":
18747
- case "rm":
18748
18784
  return runtimeRemove(rest);
18749
18785
  case "which":
18750
- case "active":
18751
18786
  return runtimeWhich();
18752
18787
  case "notes":
18753
- case "changelog":
18754
18788
  return runtimeNotes(rest);
18755
18789
  default:
18756
18790
  console.error(` unknown runtime subcommand: ${sub}`);
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.317 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.319 | (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.317",
3
+ "version": "0.1.319",
4
4
  "description": "rnxsim CLI, Vite and Metro plugins, and agent skills for driving React Native apps in the browser.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -37,7 +37,6 @@ automation, inspecting the render tree, and managing sims.
37
37
  | `rnxsim shell` | drive shell state and simulator chrome |
38
38
  | `rnxsim mode` | toggle screenshot and 3D display modes |
39
39
  | `rnxsim device` | inspect or change the live device preset for a sim |
40
- | `rnxsim inspect` | query, describe, and drive the running rnx instance |
41
40
  | `rnxsim network` | inspect live network traffic from the running rnx worker |
42
41
  | `rnxsim logs` | inspect live console output from the running rnx worker |
43
42
  | `rnxsim debug` | drive __sootsimDebug: channels, snapshots, and inspectors |
@@ -170,6 +170,23 @@ the report and how to read it:
170
170
  three runs minimum; single-run p95 is noise. a fresh `perf start` between
171
171
  runs clears the buffer.
172
172
 
173
+ ### confirm which build you measured, every time
174
+
175
+ Against a dev-source sim, the FIRST reload after an engine edit serves the
176
+ PREVIOUS module. The sim reports ready, the app runs, the numbers look real, and
177
+ they describe the build before yours. Two screenshots were read as a fidelity
178
+ regression this way before the cause was found.
179
+
180
+ So make every capture say which build it came from, rather than assuming the
181
+ reload took. Put a marker in something the capture already returns - a counter
182
+ name in `saveLayerReasons`, a debug event, a log line - and treat a capture with
183
+ no marker as a capture of the wrong build. Reload twice and re-read the marker.
184
+
185
+ This costs one line and it is the difference between a measurement and a guess.
186
+ The same rule covers any A/B where you edit between arms: an arm you cannot
187
+ identify from its own output is not evidence.
188
+
189
+
173
190
  deeper tools when the frame report isn't enough:
174
191
 
175
192
  ```sh
@@ -729,14 +729,27 @@ export function manifestNativeSeamRedirect(): Plugin {
729
729
  }
730
730
  }
731
731
 
732
+ interface ViteBridgeProcessEntry {
733
+ boundPort: Promise<number | null>
734
+ close: () => Promise<void>
735
+ owners: Set<object>
736
+ shellPort: { read: () => number | null }
737
+ }
738
+
739
+ declare global {
740
+ var __sootsimViteBridgeProcesses: Map<number, ViteBridgeProcessEntry> | undefined
741
+ }
742
+
743
+ // vite creates the replacement server before closing the prior server during a
744
+ // config restart. keep the independently listening bridge owned by that process
745
+ // across the overlap so every connected sim stays on the same websocket.
746
+ const viteBridgeProcesses = (globalThis.__sootsimViteBridgeProcesses ??= new Map())
747
+
732
748
  // start WS bridge server for debug CLI connectivity. exported so shell
733
749
  // vite can install it standalone (engine builds via `vite build --watch`,
734
750
  // which doesn't fire configureServer — the bridge has to run on shell).
735
751
  export function wsBridgePlugin(): Plugin {
736
- let bridgeHost: {
737
- startAsync?: (options?: { silent?: boolean }) => Promise<number>
738
- close?: () => Promise<void> | void
739
- } | null = null
752
+ const owner = {}
740
753
  // the port the bridge ACTUALLY bound, which is not necessarily the one it
741
754
  // asked for: the host scans forward from its preferred port on EADDRINUSE.
742
755
  // the page has to be told this value. when it derived its own guess from
@@ -749,48 +762,62 @@ export function wsBridgePlugin(): Plugin {
749
762
  apply: 'serve',
750
763
  configureServer(server) {
751
764
  if (boundPort) return
752
- // lazy import to avoid pulling ws into the main bundle.
753
- // note: the .ts extension is required on vite 8 / node ESM — without
754
- // it, import() throws "Cannot find module" and the bridge silently
755
- // never starts.
756
- boundPort = import('./host/bridge-host.ts')
757
- .then(({ SootSimBridgeHost }) => {
758
- const host = new SootSimBridgeHost({
759
- port: resolveSootsimBridgePort({
760
- explicitPort: process.env.SOOTSIM_BRIDGE_PORT,
761
- portOffset: process.env.PORT_OFFSET,
762
- }),
765
+ const preferredPort = resolveSootsimBridgePort({
766
+ explicitPort: process.env.SOOTSIM_BRIDGE_PORT,
767
+ portOffset: process.env.PORT_OFFSET,
768
+ })
769
+ const readShellPort = () => {
770
+ const addr = server.httpServer?.address()
771
+ if (addr && typeof addr === 'object') return addr.port
772
+ return server.config.server.port || null
773
+ }
774
+ const existing = viteBridgeProcesses.get(preferredPort)
775
+ if (existing) {
776
+ existing.owners.add(owner)
777
+ existing.shellPort.read = readShellPort
778
+ boundPort = existing.boundPort
779
+ } else {
780
+ // lazy import to avoid pulling ws into the main bundle.
781
+ // note: the .ts extension is required on vite 8 / node ESM — without
782
+ // it, import() throws "Cannot find module" and the bridge silently
783
+ // never starts.
784
+ const shellPort = { read: readShellPort }
785
+ const host = import('./host/bridge-host.ts').then(({ SootSimBridgeHost }) => {
786
+ return new SootSimBridgeHost({
787
+ port: preferredPort,
763
788
  writeDevLockfile: true,
764
- // resolved on every lockfile heartbeat: the address is null until
765
- // vite's http server is listening, then the real bound port. lets
766
- // CLI commands resolve the shell base URL from the same lockfile
767
- // that names the bridge port (one world, no split-brain).
768
- getShellPort: () => {
769
- const addr = server.httpServer?.address()
770
- if (addr && typeof addr === 'object') return addr.port
771
- return server.config.server.port || null
772
- },
789
+ getShellPort: () => shellPort.read(),
773
790
  })
774
- bridgeHost = host
775
- // startAsync, not start: the whole point is to learn the bound port.
776
- return host.startAsync({ silent: true })
777
- })
778
- .catch((err: unknown) => {
779
- // log but don't crash — some environments (e.g. production builds)
780
- // don't have ws available. silently swallowing has caused debugging
781
- // pain; print the message instead.
782
- const message = err instanceof Error ? err.message : String(err)
783
- console.warn('[rnx] ws bridge failed to start:', message)
784
- return null
785
791
  })
786
-
787
- // cleanup on server close (HMR restart)
788
- server.httpServer?.on('close', () => {
789
- if (bridgeHost) {
790
- void bridgeHost.close?.()
791
- bridgeHost = null
792
+ let entry: ViteBridgeProcessEntry
793
+ boundPort = host
794
+ .then((bridgeHost) => bridgeHost.startAsync({ silent: true }))
795
+ .catch((err: unknown) => {
796
+ if (viteBridgeProcesses.get(preferredPort) === entry) {
797
+ viteBridgeProcesses.delete(preferredPort)
798
+ }
799
+ const message = err instanceof Error ? err.message : String(err)
800
+ console.warn('[rnx] ws bridge failed to start:', message)
801
+ return null
802
+ })
803
+ entry = {
804
+ boundPort,
805
+ close: async () => {
806
+ try {
807
+ await (await host).close()
808
+ } catch {}
809
+ },
810
+ owners: new Set([owner]),
811
+ shellPort,
792
812
  }
793
- boundPort = null
813
+ viteBridgeProcesses.set(preferredPort, entry)
814
+ }
815
+
816
+ server.httpServer?.once('close', () => {
817
+ const entry = viteBridgeProcesses.get(preferredPort)
818
+ if (!entry || !entry.owners.delete(owner) || entry.owners.size > 0) return
819
+ viteBridgeProcesses.delete(preferredPort)
820
+ void entry.close()
794
821
  })
795
822
  },
796
823
  // publish the bound port to the page. head-prepend so it lands before the
@@ -839,7 +866,11 @@ function sootsimConfigPlugin(
839
866
  // their parent package (e.g. foo) — vite processes aliases in order
840
867
  .sort((a, b) => b[0].length - a[0].length)
841
868
  .map(([find, file]) => ({
842
- find,
869
+ // the bare expo entry is a facade while its package subpaths are
870
+ // independent upstream modules. a string alias is prefix-matched by
871
+ // vite, so make this one exact or expo/devtools and future subpaths
872
+ // become impossible paths such as expo.ts/devtools.
873
+ find: find === 'expo' ? /^expo$/ : find,
843
874
  replacement: path.resolve(compatStubsDir, file),
844
875
  }))
845
876