rnxsim 0.1.365 → 0.1.367

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 (240) hide show
  1. package/README.md +14 -0
  2. package/cli/bin.ts +18 -0
  3. package/cli/bridge-flow-runner.ts +16 -153
  4. package/cli/commands/assert.ts +1 -1
  5. package/cli/commands/box/checkout-plane.ts +126 -0
  6. package/cli/commands/box/rnx-command.ts +68 -0
  7. package/cli/commands/box.ts +200 -0
  8. package/cli/commands/control.ts +15 -76
  9. package/cli/commands/detox.ts +18 -1
  10. package/cli/commands/do-chain.ts +412 -0
  11. package/cli/commands/flow.ts +2 -11
  12. package/cli/commands/inspect/core.ts +302 -725
  13. package/cli/commands/inspect/describe.ts +3 -76
  14. package/cli/commands/inspect/find.ts +3 -6
  15. package/cli/commands/inspect/get-layout.ts +14 -1
  16. package/cli/commands/inspect/resolve-target.ts +41 -47
  17. package/cli/commands/inspect/shared.ts +28 -123
  18. package/cli/commands/inspect/tree.ts +6 -15
  19. package/cli/commands/inspect/wait-ready.ts +2 -2
  20. package/cli/commands/inspect/wait-selector.ts +4 -8
  21. package/cli/commands/inspect.ts +23 -17
  22. package/cli/commands/install-desktop.ts +44 -7
  23. package/cli/commands/maestro-generate.ts +0 -2
  24. package/cli/commands/platform.ts +68 -0
  25. package/cli/commands/state.ts +5 -2
  26. package/cli/outbound-endpoints.ts +6 -1
  27. package/cli/parse-args.ts +13 -2
  28. package/cli/ws-bridge.ts +30 -2
  29. package/detox/index.ts +37 -18
  30. package/dist-cli/bin.js +5 -5
  31. package/dist-cli/chunks/{agent-BVMNQFKF.js → agent-EKKIAKP5.js} +2 -2
  32. package/dist-cli/chunks/{agent-wrapper-B6YFXGC3.js → agent-wrapper-MHLQUGA6.js} +2 -2
  33. package/dist-cli/chunks/{app-fonts-MEI6R6XR.js → app-fonts-HN6ADRTQ.js} +2 -2
  34. package/dist-cli/chunks/{assert-JGHI53HV.js → assert-IMR6QCN6.js} +3 -3
  35. package/dist-cli/chunks/{auth-STEOXUS7.js → auth-27LPMQNH.js} +2 -2
  36. package/dist-cli/chunks/{beta-HT3FLS5T.js → beta-6RXBB5AI.js} +2 -2
  37. package/dist-cli/chunks/box-DORLF3GP.js +1709 -0
  38. package/dist-cli/chunks/{camera-ZCLFSLON.js → camera-2G7JZ5DL.js} +2 -2
  39. package/dist-cli/chunks/{chunk-RI3NS77J.js → chunk-3QZJLNYY.js} +1 -1
  40. package/dist-cli/chunks/{chunk-FHWZPUGC.js → chunk-3VBVEDDA.js} +1 -1
  41. package/dist-cli/chunks/{chunk-EAFKG5R3.js → chunk-4BWGLTKU.js} +2 -2
  42. package/dist-cli/chunks/chunk-4XSNO374.js +423 -0
  43. package/dist-cli/chunks/{chunk-GZEUDDAW.js → chunk-5DGMFUZG.js} +2 -2
  44. package/dist-cli/chunks/{chunk-TKCGP3DD.js → chunk-6DBS5EGX.js} +2 -2
  45. package/dist-cli/chunks/{chunk-HIDS3PYC.js → chunk-6SO6I3D5.js} +2 -2
  46. package/dist-cli/chunks/chunk-75EFOPXE.js +32 -0
  47. package/dist-cli/chunks/{chunk-FIXRGPUT.js → chunk-A5AJFVOF.js} +1 -1
  48. package/dist-cli/chunks/{chunk-2SFMW5K6.js → chunk-AM2ODYAN.js} +1 -1
  49. package/dist-cli/chunks/{chunk-BGRGP3QR.js → chunk-AVOROGA3.js} +1 -1
  50. package/dist-cli/chunks/chunk-AXMMLO7D.js +130 -0
  51. package/dist-cli/chunks/{chunk-XXNPISER.js → chunk-BSEXEYNX.js} +2 -2
  52. package/dist-cli/chunks/{chunk-67ATAITF.js → chunk-CM6ZKZW7.js} +2 -2
  53. package/dist-cli/chunks/{chunk-MR3YPNUI.js → chunk-DNVABCEC.js} +2 -2
  54. package/dist-cli/chunks/{chunk-5AS7S6HY.js → chunk-E33A4AIR.js} +2 -2
  55. package/dist-cli/chunks/{chunk-DBJZUCFP.js → chunk-EFMOXYDD.js} +2 -2
  56. package/dist-cli/chunks/{chunk-ZTWUNK45.js → chunk-EV4P5UBP.js} +2 -2
  57. package/dist-cli/chunks/{chunk-EVBQDQVY.js → chunk-G5IUIGGC.js} +1 -1
  58. package/dist-cli/chunks/chunk-GMLOCV3E.js +312 -0
  59. package/dist-cli/chunks/{chunk-DQFOHIRF.js → chunk-GRN2FHVW.js} +1 -1
  60. package/dist-cli/chunks/{chunk-CYIE65QN.js → chunk-HFFXPUEP.js} +1 -1
  61. package/dist-cli/chunks/chunk-HG6T4OOR.js +4 -0
  62. package/dist-cli/chunks/{chunk-GK7PGYFH.js → chunk-HNT2OXPZ.js} +1 -1
  63. package/dist-cli/chunks/chunk-IPEURNLI.js +24 -0
  64. package/dist-cli/chunks/chunk-IR44SFBA.js +5 -0
  65. package/dist-cli/chunks/chunk-JMSLXZFW.js +4 -0
  66. package/dist-cli/chunks/{chunk-WGNDJARS.js → chunk-JPXQKLNH.js} +1 -1
  67. package/dist-cli/chunks/chunk-K3EC6JDE.js +4 -0
  68. package/dist-cli/chunks/chunk-KHX65HAU.js +4 -0
  69. package/dist-cli/chunks/{chunk-MACI34ST.js → chunk-LWOVKHRC.js} +2 -2
  70. package/dist-cli/chunks/{chunk-QIQL7Y5V.js → chunk-MQN5DWTI.js} +2 -2
  71. package/dist-cli/chunks/{chunk-5VHWQGGF.js → chunk-N3BXQEUF.js} +1 -1
  72. package/dist-cli/chunks/{chunk-O2ORLK6W.js → chunk-N5OSV26B.js} +2 -2
  73. package/dist-cli/chunks/chunk-PHNURIH3.js +4 -0
  74. package/dist-cli/chunks/{chunk-JRPU5TFI.js → chunk-PP2KNVXP.js} +3 -3
  75. package/dist-cli/chunks/{chunk-UR345KM3.js → chunk-PROKNJVY.js} +2 -2
  76. package/dist-cli/chunks/chunk-QXLLY4IM.js +7 -0
  77. package/dist-cli/chunks/{chunk-2CXHDTQ5.js → chunk-RNQTOGM7.js} +1 -1
  78. package/dist-cli/chunks/{chunk-M5KJCLUW.js → chunk-RPNKKVBN.js} +27 -27
  79. package/dist-cli/chunks/{chunk-EFXNSJ55.js → chunk-RSNLI2NH.js} +2 -2
  80. package/dist-cli/chunks/{chunk-25BTVHK2.js → chunk-RZGHV2WI.js} +2 -2
  81. package/dist-cli/chunks/chunk-SGGL3AFV.js +497 -0
  82. package/dist-cli/chunks/chunk-SH5ETJKG.js +4 -0
  83. package/dist-cli/chunks/{chunk-MRNW4GVL.js → chunk-T6J4YP56.js} +2 -2
  84. package/dist-cli/chunks/{chunk-R4FQZXJC.js → chunk-TWUE7WF5.js} +2 -2
  85. package/dist-cli/chunks/{chunk-X5ZOZVHC.js → chunk-U44VEQRN.js} +1 -1
  86. package/dist-cli/chunks/{chunk-XRO5WQXP.js → chunk-URLVQHC3.js} +1 -1
  87. package/dist-cli/chunks/{chunk-JAFF4RAU.js → chunk-VANZFTUE.js} +1 -1
  88. package/dist-cli/chunks/{chunk-6BAF6GFS.js → chunk-VB2YBH46.js} +1 -1
  89. package/dist-cli/chunks/{chunk-O6P4N2JD.js → chunk-VFU2SJ7M.js} +2 -2
  90. package/dist-cli/chunks/{chunk-XPOTXF5Q.js → chunk-VUBJ6FXU.js} +15 -15
  91. package/dist-cli/chunks/{chunk-XR4KID25.js → chunk-W5PATILQ.js} +2 -2
  92. package/dist-cli/chunks/chunk-WI5V4TYG.js +38 -0
  93. package/dist-cli/chunks/{chunk-NEH4T67X.js → chunk-XTRHQAOV.js} +2 -2
  94. package/dist-cli/chunks/chunk-XWUTJLBM.js +27 -0
  95. package/dist-cli/chunks/{chunk-TULWPOAY.js → chunk-XYRUQQUR.js} +2 -2
  96. package/dist-cli/chunks/chunk-YBFB3RM7.js +4 -0
  97. package/dist-cli/chunks/chunk-YGQVQ2VG.js +4 -0
  98. package/dist-cli/chunks/{chunk-J66US2OZ.js → chunk-YINACV32.js} +1 -1
  99. package/dist-cli/chunks/chunk-YV7ERO2V.js +5 -0
  100. package/dist-cli/chunks/{cleanup-G4TEYVKY.js → cleanup-GVFHQ3KH.js} +2 -2
  101. package/dist-cli/chunks/cli-version-DPX5MA2M.js +4 -0
  102. package/dist-cli/chunks/{compat-EZ5NP32J.js → compat-AYRTXYAM.js} +2 -2
  103. package/dist-cli/chunks/{config-27M2DGCS.js → config-K7LOOV62.js} +2 -2
  104. package/dist-cli/chunks/connect-H3CNY4IO.js +4 -0
  105. package/dist-cli/chunks/control-SMHZ2CF5.js +4 -0
  106. package/dist-cli/chunks/daemon-TEZUNI73.js +4 -0
  107. package/dist-cli/chunks/{debug-EXU3D7PC.js → debug-ELGHG57T.js} +3 -3
  108. package/dist-cli/chunks/{desktop-SHHPZAWQ.js → desktop-4G7FK3MP.js} +3 -3
  109. package/dist-cli/chunks/detox-JKXGEJIZ.js +52 -0
  110. package/dist-cli/chunks/{device-4NI26HG6.js → device-IV3AR6KG.js} +2 -2
  111. package/dist-cli/chunks/{diagnose-P4SFXH6J.js → diagnose-3ERGF7EW.js} +2 -2
  112. package/dist-cli/chunks/{disk-cleanup-BUAKWYMY.js → disk-cleanup-ALFEVZ4B.js} +2 -2
  113. package/dist-cli/chunks/do-chain-K2B4OHM7.js +5 -0
  114. package/dist-cli/chunks/drivers-KJYXA3M3.js +4 -0
  115. package/dist-cli/chunks/env-2KF6IYZE.js +4 -0
  116. package/dist-cli/chunks/{film-Y2BAQINB.js → film-UQXJFAD5.js} +3 -3
  117. package/dist-cli/chunks/flow-ASTUH56E.js +4 -0
  118. package/dist-cli/chunks/help-SNNYFELA.js +4 -0
  119. package/dist-cli/chunks/{hidden-runtime-alias-U2MAY2XV.js → hidden-runtime-alias-VJCWCFVO.js} +2 -2
  120. package/dist-cli/chunks/{home-paths-PAJMZCOS.js → home-paths-EGUZZ6J6.js} +2 -2
  121. package/dist-cli/chunks/inspect-XANAADQT.js +4 -0
  122. package/dist-cli/chunks/install-desktop-JKQA7UY6.js +4 -0
  123. package/dist-cli/chunks/{login-D53XKBEO.js → login-6KQGD7HK.js} +2 -2
  124. package/dist-cli/chunks/{logout-HZQKLNUJ.js → logout-2FCOVLBC.js} +2 -2
  125. package/dist-cli/chunks/{maestro-XSS2KX6L.js → maestro-HPSSEVJD.js} +3 -3
  126. package/dist-cli/chunks/{maestro-generate-DNDQX3JQ.js → maestro-generate-KQQ6JHMR.js} +5 -5
  127. package/dist-cli/chunks/{mode-LEVGOKI3.js → mode-SH7KRZET.js} +2 -2
  128. package/dist-cli/chunks/{optional-demo-registry-2XZIJNDG.js → optional-demo-registry-NAMCAVFX.js} +2 -2
  129. package/dist-cli/chunks/{perf-OKMAXDLB.js → perf-LWKAHXUL.js} +2 -2
  130. package/dist-cli/chunks/{permissions-VG5TBUTN.js → permissions-EZTKWTXV.js} +2 -2
  131. package/dist-cli/chunks/platform-KSOJIVN5.js +6 -0
  132. package/dist-cli/chunks/privacy-EJULWP7L.js +4 -0
  133. package/dist-cli/chunks/{record-BQYGZOMV.js → record-2IC7BAQN.js} +3 -3
  134. package/dist-cli/chunks/{report-issue-HCPZESWE.js → report-issue-MMX6HOQO.js} +2 -2
  135. package/dist-cli/chunks/reset-PKFZA4NC.js +4 -0
  136. package/dist-cli/chunks/resolve-target-AFKU3BRE.js +4 -0
  137. package/dist-cli/chunks/runtime-XHWWPOIN.js +4 -0
  138. package/dist-cli/chunks/{screenshot-command-DWEYPJE7.js → screenshot-command-JYUXDVSA.js} +3 -3
  139. package/dist-cli/chunks/{screenshot-layers-5GMBXLO7.js → screenshot-layers-OGRY6AA3.js} +2 -2
  140. package/dist-cli/chunks/{screenshots-capture-5KCI7IZD.js → screenshots-capture-QHDN65XS.js} +2 -2
  141. package/dist-cli/chunks/{serve-QNKTA2HR.js → serve-W4BKAG4J.js} +3 -3
  142. package/dist-cli/chunks/setup-WJPMPSAC.js +4 -0
  143. package/dist-cli/chunks/sim-client-UOQGFBPO.js +4 -0
  144. package/dist-cli/chunks/{skills-DOEALD3X.js → skills-OPPXOD63.js} +2 -2
  145. package/dist-cli/chunks/state-TDAN7BOM.js +14 -0
  146. package/dist-cli/chunks/{storage-E7WUWN3E.js → storage-CFB2YGLY.js} +2 -2
  147. package/dist-cli/chunks/store-4TEED4ZU.js +4 -0
  148. package/dist-cli/chunks/telemetry-S6N7CV6G.js +4 -0
  149. package/dist-cli/chunks/{timeline-IKNUGQ2A.js → timeline-ASOOVP4C.js} +2 -2
  150. package/dist-cli/chunks/{upgrade-VS3OKXE2.js → upgrade-6MVJISHG.js} +2 -2
  151. package/dist-cli/chunks/upload-CBNIRFEW.js +4 -0
  152. package/dist-cli/chunks/{version-F4XHNTBZ.js → version-5GS7CWRL.js} +2 -2
  153. package/dist-cli/chunks/{web-F72724QL.js → web-QRRMYMV4.js} +2 -2
  154. package/dist-cli/chunks/welcome-33FXMAMB.js +5 -0
  155. package/dist-cli/chunks/{what-happened-APK7YKOV.js → what-happened-GAZJGKXX.js} +2 -2
  156. package/dist-cli/chunks/ws-bridge-DIXUAPLQ.js +4 -0
  157. package/dist-lib/agent-daemon-client.cjs +1 -1
  158. package/dist-lib/agent-events.cjs +1 -1
  159. package/dist-lib/agent-identity.cjs +1 -1
  160. package/dist-lib/agent-sessions.cjs +1 -1
  161. package/dist-lib/attached-projects.cjs +1 -1
  162. package/dist-lib/auth/shared-session.cjs +1 -1
  163. package/dist-lib/backend-origin.cjs +1 -1
  164. package/dist-lib/beta.cjs +1 -1
  165. package/dist-lib/beta.mjs +1 -1
  166. package/dist-lib/bridge-constants.cjs +1 -1
  167. package/dist-lib/bridge-contract-input.cjs +336 -0
  168. package/dist-lib/bridge-contract-input.mjs +303 -0
  169. package/dist-lib/bridge-contract.cjs +29 -1
  170. package/dist-lib/bridge-contract.mjs +19 -0
  171. package/dist-lib/cli-constants.cjs +1 -1
  172. package/dist-lib/config.cjs +1 -1
  173. package/dist-lib/detox/index.cjs +35 -19
  174. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  175. package/dist-lib/home-paths.cjs +1 -1
  176. package/dist-lib/host/bridge-host.cjs +5 -1
  177. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  178. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  179. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  180. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  181. package/dist-lib/host/websocket-proxy.cjs +1 -1
  182. package/dist-lib/index.cjs +244 -594
  183. package/dist-lib/jump-to-source-babel.cjs +1 -1
  184. package/dist-lib/menu.cjs +1 -1
  185. package/dist-lib/menu.mjs +1 -1
  186. package/dist-lib/metro-production-bundle.cjs +1 -1
  187. package/dist-lib/metro-production-bundle.mjs +1 -1
  188. package/dist-lib/metro.cjs +1 -1
  189. package/dist-lib/profiles.cjs +1 -1
  190. package/dist-lib/public-brand.cjs +1 -1
  191. package/dist-lib/react-native-host-modules.cjs +1 -1
  192. package/dist-lib/react-native-host-modules.mjs +1 -1
  193. package/dist-lib/render-mode.cjs +1 -1
  194. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  195. package/dist-lib/sdk.cjs +303 -657
  196. package/dist-lib/sdk.mjs +301 -652
  197. package/dist-lib/skills.cjs +256 -339
  198. package/dist-lib/vite.cjs +1 -1
  199. package/package.json +10 -1
  200. package/skills/contrast/SKILL.md +3 -0
  201. package/skills/rnx-debug/SKILL.md +8 -0
  202. package/skills/rnx-test/SKILL.md +21 -0
  203. package/src/app-url.ts +40 -0
  204. package/src/bridge-contract-input.ts +359 -0
  205. package/src/bridge-contract.ts +121 -1
  206. package/src/host/bridge-host.ts +7 -12
  207. package/src/index.ts +7 -0
  208. package/src/sim-client.ts +24 -9
  209. package/dist-cli/chunks/chunk-2JFZ5Z7Q.js +0 -4
  210. package/dist-cli/chunks/chunk-4WFN4DFR.js +0 -5
  211. package/dist-cli/chunks/chunk-52ES4API.js +0 -38
  212. package/dist-cli/chunks/chunk-622E4JET.js +0 -767
  213. package/dist-cli/chunks/chunk-EFL2ASZO.js +0 -124
  214. package/dist-cli/chunks/chunk-IWPS3EKJ.js +0 -15
  215. package/dist-cli/chunks/chunk-MCHKBFUL.js +0 -4
  216. package/dist-cli/chunks/chunk-OSZ5HZSI.js +0 -24
  217. package/dist-cli/chunks/chunk-W3UIDI3W.js +0 -5
  218. package/dist-cli/chunks/chunk-XKRUNS7A.js +0 -32
  219. package/dist-cli/chunks/chunk-YE3M3YD4.js +0 -944
  220. package/dist-cli/chunks/chunk-ZCP4CRP6.js +0 -4
  221. package/dist-cli/chunks/chunk-ZGD7GZRI.js +0 -4
  222. package/dist-cli/chunks/chunk-ZGH5U4AJ.js +0 -27
  223. package/dist-cli/chunks/cli-version-ZM3PVKQ5.js +0 -4
  224. package/dist-cli/chunks/control-4QR43FXV.js +0 -4
  225. package/dist-cli/chunks/daemon-2U4CJ6AT.js +0 -4
  226. package/dist-cli/chunks/detox-RQ6FFSBS.js +0 -52
  227. package/dist-cli/chunks/drivers-OVCUPQTM.js +0 -4
  228. package/dist-cli/chunks/flow-ELTLKKZ3.js +0 -4
  229. package/dist-cli/chunks/help-CDEZAG2L.js +0 -4
  230. package/dist-cli/chunks/inspect-VVQRPJLS.js +0 -4
  231. package/dist-cli/chunks/install-desktop-YXSRKR35.js +0 -4
  232. package/dist-cli/chunks/privacy-MNRHREME.js +0 -4
  233. package/dist-cli/chunks/reset-R4E4W4YI.js +0 -4
  234. package/dist-cli/chunks/runtime-XRQZ7W34.js +0 -4
  235. package/dist-cli/chunks/setup-RNMM5GO5.js +0 -4
  236. package/dist-cli/chunks/state-3HH2IHIF.js +0 -14
  237. package/dist-cli/chunks/store-HUPZUCFG.js +0 -4
  238. package/dist-cli/chunks/telemetry-IJ53XR2Y.js +0 -4
  239. package/dist-cli/chunks/upload-A57NAAHF.js +0 -4
  240. package/dist-cli/chunks/welcome-B72RRMBW.js +0 -5
@@ -1,8 +1,4 @@
1
- // `sootsim describe` — dump the visible-UI tree with layout + style annotations.
2
- //
3
- // see packages/sootsim-engine/src/test-bridge.ts for the actual dumpTree impl
4
- // that powers this. the CLI-side job is just: optional preflight for in-flight
5
- // screen transitions, call dumpTree with the right flags, and pretty-print.
1
+ // `sootsim describe` — format the pruned visible semantic tree.
6
2
 
7
3
  import { maybeHint } from '../../hints'
8
4
  import { inspectDescribe, type DescribeDumpOptions } from './core'
@@ -34,18 +30,6 @@ export async function runDescribeSubcommand(opts: DescribeOptions): Promise<void
34
30
  const watchInterval = 1000
35
31
  const compact = args.includes('--compact')
36
32
  const hideXy = args.includes('--no-xy')
37
- // when set, strip rows annotated `(clipped:left|right|top|bottom)` from the
38
- // output. dumpTree marks anything that overflows the viewport so search
39
- // context is preserved, but the rows balloon the output on screens like
40
- // 3pc's profile (off-screen list items + edge-pulled chrome). this flag is
41
- // a client-side filter so we don't need a roundtrip to dumpTree.
42
- const hideClipped = args.includes('--no-clipped')
43
- // by default describe hides nodes that sit fully behind a modal/sheet/popover
44
- // scrim — they aren't reachable, and listing them as `(tap)` misleads agents
45
- // into tapping content that's actually occluded. --include-occluded surfaces
46
- // them annotated `(behind)`.
47
- const includeOccluded = args.includes('--include-occluded')
48
-
49
33
  const testIdLike = flagValue(args, '--testid-like')
50
34
  const onlyGlob = flagValue(args, '--only')
51
35
  const subtreeRoot = flagValue(args, '--subtree')
@@ -74,35 +58,17 @@ export async function runDescribeSubcommand(opts: DescribeOptions): Promise<void
74
58
  subtreeRoot: subtreeRoot || undefined,
75
59
  compact,
76
60
  hideXy,
77
- includeOccluded,
78
61
  // no terminal to fit, so nothing gets clipped on the way out
79
62
  fullText: jsonOut,
80
63
  }
81
64
  const result = await inspectDescribe(bridge, dumpOpts)
82
65
  const tree = result?.tree
83
- const shell = result?.shell
84
- const keyboard = result?.keyboard
85
66
 
86
67
  if (jsonOut) {
87
- printJson({ shell, tree: tree ?? '', keyboard })
68
+ printJson({ tree: tree ?? '' })
88
69
  return
89
70
  }
90
71
 
91
- // show shell state in header if available
92
- if (shell && typeof shell === 'object') {
93
- const shellParts = [
94
- shell.state ? `state=${shell.state}` : null,
95
- shell.activeApp ? `app=${shell.activeApp}` : null,
96
- shell.showSwitcher ? 'switcher' : null,
97
- shell.switcherPhase && shell.switcherPhase !== 'idle'
98
- ? `phase=${shell.switcherPhase}`
99
- : null,
100
- ].filter(Boolean)
101
- if (shellParts.length > 0) {
102
- console.log(` shell: ${shellParts.join(' ')}`)
103
- }
104
- }
105
-
106
72
  if (typeof tree === 'string' && tree.startsWith('__SUBTREE_NOT_FOUND__:')) {
107
73
  const missing = tree.slice('__SUBTREE_NOT_FOUND__:'.length)
108
74
  console.log(` subtree root not found: ${missing}`)
@@ -120,26 +86,7 @@ export async function runDescribeSubcommand(opts: DescribeOptions): Promise<void
120
86
  return
121
87
  }
122
88
 
123
- let rendered = tree
124
- let hiddenClippedCount = 0
125
- if (hideClipped && typeof rendered === 'string') {
126
- const lines = rendered.split('\n')
127
- const kept: string[] = []
128
- for (const line of lines) {
129
- if (line.includes('(clipped:')) {
130
- hiddenClippedCount += 1
131
- continue
132
- }
133
- kept.push(line)
134
- }
135
- rendered = kept.join('\n')
136
- }
137
- console.log(rendered)
138
- if (hiddenClippedCount > 0) {
139
- console.log(
140
- ` ${hiddenClippedCount} clipped row(s) hidden (omit --no-clipped to see)`,
141
- )
142
- }
89
+ console.log(tree)
143
90
 
144
91
  const anyFilterActive = filter || testIdLike || effectiveOnlyGlob || subtreeRoot
145
92
  const searchFilterActive = filter || testIdLike || effectiveOnlyGlob
@@ -157,26 +104,6 @@ export async function runDescribeSubcommand(opts: DescribeOptions): Promise<void
157
104
  maybeHint('describe-use-filters')
158
105
  }
159
106
  }
160
-
161
- // keyboard summary — only when visible. rendered as a footer so it
162
- // doesn't bury the tree on forms with non-trivial UI above the input.
163
- if (keyboard && keyboard.visible) {
164
- const spec = keyboard.spec
165
- const kbParts = [
166
- spec?.keyboardType ? `type=${spec.keyboardType}` : null,
167
- spec?.returnKeyType && spec.returnKeyType !== 'default'
168
- ? `return=${spec.returnKeyType}`
169
- : null,
170
- keyboard.mode !== 'letters' ? `mode=${keyboard.mode}` : null,
171
- keyboard.shifted ? 'shift' : null,
172
- keyboard.capsLock ? 'caps' : null,
173
- spec?.autoCapitalize && spec.autoCapitalize !== 'sentences'
174
- ? `autoCap=${spec.autoCapitalize}`
175
- : null,
176
- keyboard.accessoryBarId ? `accessory=${keyboard.accessoryBarId}` : null,
177
- ].filter(Boolean)
178
- console.log(`\n keyboard: ${kbParts.join(' ') || 'visible'}`)
179
- }
180
107
  }
181
108
 
182
109
  if (watch) {
@@ -1,5 +1,5 @@
1
1
  import { maybeHint } from '../../hints'
2
- import { inspectFind, rankInteractive, tapCommandForNode } from './core'
2
+ import { inspectFind, inspectNodeCount, rankInteractive, tapCommandForNode } from './core'
3
3
  import { printJson, wantsJson } from './shared'
4
4
  import type { WsBridge } from '../../ws-bridge'
5
5
 
@@ -78,11 +78,8 @@ export async function runFindSubcommand(opts: {
78
78
  } else if (Array.isArray(result)) {
79
79
  if (result.length === 0) {
80
80
  console.log(` no ${mode} nodes found`)
81
- const nodeCount = await bridge.send({
82
- type: 'evaluate',
83
- code: '(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()',
84
- })
85
- if (typeof nodeCount === 'number' && nodeCount < 10) {
81
+ const { nodes: nodeCount } = await inspectNodeCount(bridge)
82
+ if (nodeCount < 10) {
86
83
  maybeHint('app-still-loading', nodeCount)
87
84
  }
88
85
  } else if (mode === 'interactive-targets') {
@@ -25,7 +25,20 @@ export async function runGetLayoutSubcommand(opts: {
25
25
  const styling = args.includes('--styling')
26
26
  const filterIndex = args.indexOf('--filter')
27
27
  const filter = filterIndex >= 0 ? args[filterIndex + 1] : undefined
28
- const elements = await inspectGetLayout(bridge, { styling, filter })
28
+ const elements = await inspectGetLayout(bridge, { styling, filter }).catch(
29
+ (error: unknown) => {
30
+ if (
31
+ styling &&
32
+ error instanceof Error &&
33
+ error.message === 'unsupported RNX Cloud command type: evaluate'
34
+ ) {
35
+ throw new Error(
36
+ 'get layout --styling is unavailable in RNX Cloud; rerun without --styling or use a local sim',
37
+ )
38
+ }
39
+ throw error
40
+ },
41
+ )
29
42
  if (jsonOut) {
30
43
  printJson({ count: elements.length, elements })
31
44
  return
@@ -1,3 +1,4 @@
1
+ import { isSimSemanticTree } from './core'
1
2
  import type { WsBridge } from '../../ws-bridge'
2
3
 
3
4
  // read a --testid / --text flag from args. returns null when neither is
@@ -26,57 +27,50 @@ export function readTargetFlag(
26
27
  return null
27
28
  }
28
29
 
29
- export async function resolveTargetCoords(
30
- bridge: WsBridge,
31
- target: { mode: 'testid' | 'text'; value: string },
32
- ): Promise<{
30
+ export interface ResolvedTargetCoords {
33
31
  x: number
34
32
  y: number
35
- id?: string | null
36
33
  testID?: string | null
37
34
  text?: string | null
38
35
  type?: string | null
39
- } | null> {
40
- const arg = JSON.stringify(target.value)
41
- const findExpr =
42
- target.mode === 'testid'
43
- ? `(await t.findByTestId(${arg})) || (await t.findById(${arg}))`
44
- : `await t.findByText(${arg})`
45
- const result = await bridge.send({
46
- type: 'evaluate',
47
- code: `(async () => {
48
- const t = window.__sootsimTest
49
- if (!t) return null
50
- const n = ${findExpr}
51
- if (!n || !n.absolutePosition || !n.layout) return null
52
- const resolved =
53
- typeof n.nodeId === 'number' && typeof t.resolveTapTarget === 'function'
54
- ? await t.resolveTapTarget(n.nodeId)
55
- : null
56
- const cx =
57
- typeof resolved?.cx === 'number'
58
- ? resolved.cx
59
- : n.absolutePosition.x + (n.layout.width || 0) / 2
60
- const cy =
61
- typeof resolved?.cy === 'number'
62
- ? resolved.cy
63
- : n.absolutePosition.y + (n.layout.height || 0) / 2
64
- return {
65
- x: cx,
66
- y: cy,
67
- id: n.id ?? null,
68
- testID: n.testID ?? null,
69
- text: ${JSON.stringify(target.mode === 'text')} ? ${arg} : (n.text ?? n.accessibilityLabel ?? null),
70
- type: n.type ?? null,
71
- }
72
- })()`,
36
+ }
37
+
38
+ export async function resolveTargetCoords(
39
+ bridge: WsBridge,
40
+ target: { mode: 'testid' | 'text'; value: string },
41
+ ): Promise<ResolvedTargetCoords | null> {
42
+ const result: unknown = await bridge.send({
43
+ type: 'resolve',
44
+ selector:
45
+ target.mode === 'testid' ? { testID: target.value } : { text: target.value },
73
46
  })
74
- return (result ?? null) as {
75
- x: number
76
- y: number
77
- id?: string | null
78
- testID?: string | null
79
- text?: string | null
80
- type?: string | null
81
- } | null
47
+ if (result === null) return null
48
+ if (typeof result !== 'object') throw new Error('resolve returned an invalid result')
49
+ const match = Reflect.get(result, 'match')
50
+ const resolvedTarget = Reflect.get(result, 'target')
51
+ const semanticNodes = [match, resolvedTarget]
52
+ const point = Reflect.get(result, 'point')
53
+ const x =
54
+ point !== null && typeof point === 'object' ? Reflect.get(point, 'x') : undefined
55
+ const y =
56
+ point !== null && typeof point === 'object' ? Reflect.get(point, 'y') : undefined
57
+ if (
58
+ !isSimSemanticTree(semanticNodes) ||
59
+ typeof x !== 'number' ||
60
+ !Number.isFinite(x) ||
61
+ typeof y !== 'number' ||
62
+ !Number.isFinite(y)
63
+ ) {
64
+ throw new Error('resolve returned an invalid result')
65
+ }
66
+ const semanticMatch = semanticNodes[0]
67
+ if (!semanticMatch) throw new Error('resolve returned an invalid result')
68
+ return {
69
+ x,
70
+ y,
71
+ testID: semanticMatch.testID ?? null,
72
+ text:
73
+ semanticMatch.text ?? (target.mode === 'text' ? target.value : semanticMatch.label),
74
+ type: semanticMatch.type,
75
+ }
82
76
  }
@@ -11,14 +11,7 @@ import {
11
11
  type ParsedBridgeCliArgs,
12
12
  type WsBridge,
13
13
  } from '../../ws-bridge'
14
- import {
15
- getShellState,
16
- isShellCommandUnavailable,
17
- readyProbeHasContent,
18
- READY_NODE_STABLE_MS,
19
- WAIT_READY_PROBE,
20
- type ReadyProbe,
21
- } from './core'
14
+ import { getShellState, inspectWaitReady, isShellCommandUnavailable } from './core'
22
15
  import type { SootSimScreenTransitionWaitResult } from '@sootsim/globals'
23
16
 
24
17
  // shell-state helpers live in the transport-agnostic kernel module so the CLI
@@ -230,124 +223,36 @@ export interface ReloadReadyResult {
230
223
  errors: number
231
224
  }
232
225
 
233
- // drives the post-reload wait with short bridge-side probes. used by
234
- // `sootsim reload` (both the in-place hot-remount and the full-page reload
235
- // paths). primary ready signal is window.__sootsimExternalAppReady, set by
236
- // shell-events-bridge on the `sootsim:externalAppReady` event, plus visible
237
- // inspectable content (or a larger non-placeholder tree) and a brief stable
238
- // node count. a single long in-page evaluate can hold a stale shell-owned tree
239
- // snapshot until it returns; separate probes let the host process pending
240
- // shellTreeUpdate traffic between reads. bails early if the console picks up
241
- // errors after a grace period with the flag still unset — fatal bundle/eval
242
- // failures pile up errors fast and never emit ready, so waiting the full
243
- // budget just wastes wall time. falls back to the same content gate on timeout
244
- // so apps that never wire up the shell-events bridge don't hard-fail reload.
226
+ // post-reload readiness is the same engine-owned condition as `rnx wait ready`.
227
+ // keeping reload on that primitive prevents another polling implementation
228
+ // from drifting on loading text, live frames, or tree stability.
245
229
  export async function pollForReloadReady(
246
230
  bridge: WsBridge,
247
- opts: {
248
- timeoutMs?: number
249
- errorGraceMs?: number
250
- pollIntervalMs?: number
251
- } = {},
231
+ opts: { timeoutMs?: number } = {},
252
232
  ): Promise<ReloadReadyResult> {
253
233
  const timeoutMs = opts.timeoutMs ?? 10000
254
- const errorGraceMs = opts.errorGraceMs ?? 3000
255
- const pollIntervalMs = opts.pollIntervalMs ?? 200
256
- const start = Date.now()
257
- const deadline = start + timeoutMs
258
- let lastNodes = -1
259
- let nodeStableSince = start
260
- let lastExternalReady: unknown = null
261
- let lastExternalErrored = false
262
- let last: ReloadReadyResult = {
263
- ready: false,
264
- source: 'timeout',
265
- elapsedMs: 0,
266
- nodes: 0,
267
- targets: 0,
268
- liveFrameActive: false,
269
- liveFrameChannels: 0,
270
- liveFramePublishes: 0,
271
- flag: undefined,
272
- loadingText: '',
273
- externalReady: null,
274
- externalStatus: '',
275
- externalError: '',
276
- errors: 0,
277
- }
278
-
279
- while (Date.now() < deadline) {
280
- try {
281
- const probe = (await bridge.send({
282
- type: 'evaluate',
283
- code: WAIT_READY_PROBE,
284
- })) as Partial<ReadyProbe> | null
285
- const elapsedMs = Date.now() - start
286
- const nodes = Number(probe?.nodes) || 0
287
- const targets = Number(probe?.targets) || 0
288
- const liveFrameActive = probe?.liveFrameActive === true
289
- const liveFrameChannels = Number(probe?.liveFrameChannels) || 0
290
- const liveFramePublishes = Number(probe?.liveFramePublishes) || 0
291
- const errors = Number(probe?.errors) || 0
292
- const readyFlag = probe?.flag === true
293
- const externalReady = probe?.externalReady
294
- const loadingText =
295
- typeof probe?.loadingText === 'string' ? probe.loadingText.trim() : ''
296
- const externalStatus =
297
- typeof probe?.externalStatus === 'string' ? probe.externalStatus.trim() : ''
298
- const externalError =
299
- typeof probe?.externalError === 'string' ? probe.externalError.trim() : ''
300
- const externalErrored =
301
- typeof probe?.externalError === 'string' && externalError.length > 0
302
- lastExternalReady = externalReady
303
- lastExternalErrored = externalErrored
304
- if (nodes !== lastNodes) {
305
- lastNodes = nodes
306
- nodeStableSince = elapsedMs
307
- }
308
- last = {
309
- ready: false,
310
- source: 'timeout',
311
- elapsedMs,
312
- nodes,
313
- targets,
314
- liveFrameActive,
315
- liveFrameChannels,
316
- liveFramePublishes,
317
- flag: probe?.flag,
318
- loadingText,
319
- externalReady: typeof externalReady === 'boolean' ? externalReady : null,
320
- externalStatus,
321
- externalError,
322
- errors,
323
- }
324
- if (
325
- readyFlag &&
326
- externalReady !== false &&
327
- !externalErrored &&
328
- !loadingText &&
329
- readyProbeHasContent({ liveFrameActive, nodes, targets })
330
- ) {
331
- if (elapsedMs - nodeStableSince >= READY_NODE_STABLE_MS) {
332
- return { ...last, ready: true, source: 'flag' }
333
- }
334
- }
335
- if (elapsedMs >= errorGraceMs && errors > 0 && !readyFlag) {
336
- return { ...last, ready: false, source: 'error-bail' }
337
- }
338
- } catch {
339
- // transient bridge disconnect during full-page reload — keep polling.
340
- }
341
- await sleep(pollIntervalMs)
342
- }
343
-
344
- if (
345
- lastExternalReady !== false &&
346
- !lastExternalErrored &&
347
- !last.loadingText &&
348
- readyProbeHasContent(last)
349
- ) {
350
- return { ...last, ready: true, source: 'nodes-fallback' }
234
+ const status = await inspectWaitReady(bridge, timeoutMs)
235
+ const source = status.ready
236
+ ? status.flag === true
237
+ ? 'flag'
238
+ : 'nodes-fallback'
239
+ : status.errors > 0 && status.flag !== true
240
+ ? 'error-bail'
241
+ : 'timeout'
242
+ return {
243
+ ready: status.ready,
244
+ source,
245
+ elapsedMs: status.elapsedMs,
246
+ nodes: status.nodes,
247
+ targets: status.targets,
248
+ liveFrameActive: status.liveFrameActive,
249
+ liveFrameChannels: status.liveFrameChannels,
250
+ liveFramePublishes: status.liveFramePublishes,
251
+ flag: status.flag,
252
+ loadingText: status.loadingText,
253
+ externalReady: status.externalReady,
254
+ externalStatus: status.externalStatus,
255
+ externalError: status.externalError,
256
+ errors: status.errors,
351
257
  }
352
- return { ...last, ready: false, source: 'timeout', elapsedMs: Date.now() - start }
353
258
  }
@@ -1,9 +1,6 @@
1
- // `sootsim get tree` — raw node tree dump, default depth 5.
2
- //
3
- // goes through the merged test bridge (shell + tenant) rather than the raw
4
- // tree message, which only walks the tenant root.
1
+ // `sootsim get tree` — pruned structured semantic tree, default depth 5.
5
2
 
6
- import { inspectTree } from './core'
3
+ import { formatSemanticTree, inspectTree, isSimSemanticTree } from './core'
7
4
  import { printJson, wantsJson } from './shared'
8
5
  import type { WsBridge } from '../../ws-bridge'
9
6
 
@@ -13,20 +10,14 @@ export async function runTreeSubcommand(opts: {
13
10
  positional: string[]
14
11
  }): Promise<void> {
15
12
  const { bridge, args, positional } = opts
16
- // --boxes: structured nested rects ({ type, testID?, text?, x, y, w, h,
17
- // bg?, fg?, br?, children? }) in absolute device coords — for layout
18
- // tooling that needs real geometry, not the rendered text dump. deeper
19
- // default depth because geometry consumers want the whole tree.
13
+ // --boxes keeps the deeper default expected by geometry consumers. the
14
+ // semantic tree is structured in both modes.
20
15
  const boxes = args.includes('--boxes')
21
16
  const depth = positional[1] ? Number(positional[1]) : boxes ? 50 : 5
22
- const { tree } = await inspectTree(
23
- bridge,
24
- depth,
25
- boxes ? { format: 'boxes' } : undefined,
26
- )
17
+ const { tree } = await inspectTree(bridge, depth)
27
18
  if (wantsJson(args)) {
28
19
  printJson({ depth, tree: tree ?? null })
29
20
  return
30
21
  }
31
- console.log(typeof tree === 'string' ? tree : JSON.stringify(tree, null, 2))
22
+ console.log(isSimSemanticTree(tree) ? formatSemanticTree(tree) : '')
32
23
  }
@@ -6,8 +6,8 @@ import type { WsBridge } from '../../ws-bridge'
6
6
  // inspectable content. the persistent window flag
7
7
  // `__sootsimExternalAppReady` is necessary but not sufficient: shell-owned
8
8
  // canvas can expose a stable launch/loading tree before the app content lands.
9
- // the polling loop lives in inspect/core.ts (`inspectWaitReady`) so the CLI
10
- // and the agent share it; this handler just parses flags and reports.
9
+ // the engine owns the polling loop; this handler sends one request, then
10
+ // reports the typed result.
11
11
  export async function runWaitReadySubcommand(opts: {
12
12
  bridge: WsBridge
13
13
  args: string[]
@@ -2,8 +2,8 @@ import { inspectWaitSelector } from './core'
2
2
  import type { WsBridge } from '../../ws-bridge'
3
3
 
4
4
  // blocks until a node with the given testID is present and laid out, or — with
5
- // `--gone` — until it is absent. the polling logic lives in inspect/core.ts
6
- // (`inspectWaitSelector`); this handler parses args and reports.
5
+ // `--gone` — until it is absent. the engine owns the polling loop and this
6
+ // handler sends one request, then reports.
7
7
  export async function runWaitSelectorSubcommand(opts: {
8
8
  bridge: WsBridge
9
9
  args: string[]
@@ -38,12 +38,8 @@ export async function runWaitSelectorSubcommand(opts: {
38
38
  }
39
39
 
40
40
  if (found && node) {
41
- const loc = node.absolutePosition
42
- ? `@(${Math.round(node.absolutePosition.x)},${Math.round(node.absolutePosition.y)})`
43
- : ''
44
- const size = node.layout
45
- ? `${Math.round(node.layout.width)}x${Math.round(node.layout.height)}`
46
- : '?x?'
41
+ const loc = `@(${Math.round(node.geometry.x)},${Math.round(node.geometry.y)})`
42
+ const size = `${Math.round(node.geometry.width)}x${Math.round(node.geometry.height)}`
47
43
  console.log(` found #${testId} in ${elapsed}ms ${size} ${loc}`)
48
44
  } else {
49
45
  console.error(
@@ -45,6 +45,7 @@ import {
45
45
  filterLogEntries,
46
46
  inspectAccessibilityTree,
47
47
  inspectErrors,
48
+ inspectFind,
48
49
  inspectLogs,
49
50
  inspectRequests,
50
51
  inspectWarnings,
@@ -1060,8 +1061,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1060
1061
  // nothing). value-taking describe flags live in stripValueFlags below.
1061
1062
  '--compact',
1062
1063
  '--no-xy',
1063
- '--no-clipped',
1064
- '--include-occluded',
1065
1064
  ],
1066
1065
  stripValueFlags: [
1067
1066
  '--output',
@@ -1749,12 +1748,28 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1749
1748
  await runGetLayoutSubcommand({ bridge, args: effectiveArgs })
1750
1749
  break
1751
1750
  }
1752
- // use async for worker mode bridge
1753
- const layout = await bridge.send({
1754
- type: 'evaluate',
1755
- code: `(async () => await window.__sootsimTest.getLayout(${JSON.stringify(id)}))()`,
1756
- })
1757
- console.log(JSON.stringify(layout, null, 2))
1751
+ const found = await inspectFind(bridge, { testId: id })
1752
+ const node = found?.result
1753
+ if (node === null || typeof node !== 'object' || Array.isArray(node)) {
1754
+ console.log('null')
1755
+ break
1756
+ }
1757
+ const absolute = Reflect.get(node, 'absolutePosition')
1758
+ const size = Reflect.get(node, 'layout')
1759
+ console.log(
1760
+ JSON.stringify(
1761
+ absolute && size
1762
+ ? {
1763
+ x: Reflect.get(absolute, 'x'),
1764
+ y: Reflect.get(absolute, 'y'),
1765
+ width: Reflect.get(size, 'width'),
1766
+ height: Reflect.get(size, 'height'),
1767
+ }
1768
+ : null,
1769
+ null,
1770
+ 2,
1771
+ ),
1772
+ )
1758
1773
  break
1759
1774
  }
1760
1775
 
@@ -1906,14 +1921,12 @@ export async function runInspect(args: string[], opts: InspectOptions) {
1906
1921
  cx: resolved.x,
1907
1922
  cy: resolved.y,
1908
1923
  match: {
1909
- id: target.mode === 'testid' ? target.value : (resolved.id ?? null),
1910
1924
  testID:
1911
1925
  target.mode === 'testid' ? target.value : (resolved.testID ?? null),
1912
1926
  text: target.mode === 'text' ? target.value : (resolved.text ?? null),
1913
1927
  type: resolved.type ?? null,
1914
1928
  },
1915
1929
  target: {
1916
- id: resolved.id ?? null,
1917
1930
  testID: resolved.testID ?? null,
1918
1931
  text: resolved.text ?? null,
1919
1932
  type: resolved.type ?? null,
@@ -2684,7 +2697,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2684
2697
  let y = Number(positional[2])
2685
2698
  const target = readTargetFlag(args, positional)
2686
2699
  let resolvedTarget: {
2687
- id?: string | null
2688
2700
  testID?: string | null
2689
2701
  text?: string | null
2690
2702
  type?: string | null
@@ -2701,7 +2713,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
2701
2713
  x = resolved.x
2702
2714
  y = resolved.y
2703
2715
  resolvedTarget = {
2704
- id: resolved.id ?? null,
2705
2716
  testID: resolved.testID ?? null,
2706
2717
  text: resolved.text ?? null,
2707
2718
  type: resolved.type ?? null,
@@ -3382,7 +3393,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3382
3393
  // failures surface as console errors that pile up fast — bail early
3383
3394
  // in that case instead of waiting the full budget.
3384
3395
  const READY_TIMEOUT_MS = 10000
3385
- const ERROR_GRACE_MS = 3000
3386
3396
  let issuedReload = false
3387
3397
  let inPlaceReload = false
3388
3398
  try {
@@ -3432,7 +3442,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3432
3442
  if (inPlaceReload) {
3433
3443
  readyResult = await pollForReloadReady(bridge, {
3434
3444
  timeoutMs: READY_TIMEOUT_MS,
3435
- errorGraceMs: ERROR_GRACE_MS,
3436
3445
  })
3437
3446
  } else {
3438
3447
  // full page reload — wait for a fresh bridge before polling for ready.
@@ -3452,7 +3461,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3452
3461
  finalBridge = reconnected
3453
3462
  readyResult = await pollForReloadReady(reconnected, {
3454
3463
  timeoutMs: PAGE_RELOAD_TIMEOUT_MS,
3455
- errorGraceMs: ERROR_GRACE_MS,
3456
3464
  })
3457
3465
  } else {
3458
3466
  console.log(
@@ -3517,7 +3525,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3517
3525
 
3518
3526
  case 'storage-clear': {
3519
3527
  const READY_TIMEOUT_MS = 10000
3520
- const ERROR_GRACE_MS = 3000
3521
3528
  await clearConsole(bridge)
3522
3529
  const cleared = await bridge.send({
3523
3530
  type: 'evaluate',
@@ -3541,7 +3548,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
3541
3548
 
3542
3549
  const readyResult = await pollForReloadReady(bridge, {
3543
3550
  timeoutMs: READY_TIMEOUT_MS,
3544
- errorGraceMs: ERROR_GRACE_MS,
3545
3551
  })
3546
3552
 
3547
3553
  if (wantsJson(effectiveArgs)) {