sootsim 0.1.169 → 0.1.170
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.
- package/README.md +66 -63
- package/detox/index.ts +3 -3
- package/dist-cli/bin.js +3 -3
- package/dist-cli/chunks/agent-3C2BKQKX.js +46 -0
- package/dist-cli/chunks/{agent-wrapper-Y5FQA3RL.js → agent-wrapper-OIKCYOXZ.js} +2 -2
- package/dist-cli/chunks/{app-fonts-FYVA4XV6.js → app-fonts-25O32NAP.js} +2 -2
- package/dist-cli/chunks/{assert-U64QBDM2.js → assert-ONEP4NQU.js} +2 -2
- package/dist-cli/chunks/beta-4E5USTEI.js +2 -0
- package/dist-cli/chunks/{camera-3GXBVIAM.js → camera-RORW4MAA.js} +2 -2
- package/dist-cli/chunks/{chunk-5C6BR24W.js → chunk-25RFZ6WP.js} +6 -6
- package/dist-cli/chunks/chunk-35GMFXVJ.js +2 -0
- package/dist-cli/chunks/{chunk-GLRFKYDV.js → chunk-3TM7DHWE.js} +2 -2
- package/dist-cli/chunks/{chunk-4F3BBP7B.js → chunk-4XVY5TUF.js} +2 -2
- package/dist-cli/chunks/{chunk-LZEL2RU3.js → chunk-5ZHUPPS5.js} +1 -1
- package/dist-cli/chunks/{chunk-GC4THE6K.js → chunk-6FAEORJ2.js} +2 -2
- package/dist-cli/chunks/{chunk-G2ZFDIPK.js → chunk-6TSXXN2W.js} +4 -4
- package/dist-cli/chunks/chunk-AJF3QF4K.js +1 -0
- package/dist-cli/chunks/{chunk-FIDPRJYH.js → chunk-AUCNBB6Q.js} +2 -2
- package/dist-cli/chunks/{chunk-SIB6I72P.js → chunk-BP3EGFER.js} +2 -2
- package/dist-cli/chunks/{chunk-OGLWXPVG.js → chunk-DAXME77O.js} +3 -3
- package/dist-cli/chunks/chunk-DGJTEFE7.js +13 -0
- package/dist-cli/chunks/chunk-DIRDEKRW.js +23 -0
- package/dist-cli/chunks/{chunk-3L4NRJ6C.js → chunk-DKTC53HV.js} +1 -1
- package/dist-cli/chunks/{chunk-KUUFY6FC.js → chunk-DWXC25XG.js} +1 -1
- package/dist-cli/chunks/{chunk-CR6DOLUD.js → chunk-E3FKMY5E.js} +1 -1
- package/dist-cli/chunks/chunk-ER4GBJRY.js +2 -0
- package/dist-cli/chunks/chunk-EX6V4ZV6.js +6 -0
- package/dist-cli/chunks/{chunk-VMYMPL6H.js → chunk-GQH3PD3W.js} +5 -5
- package/dist-cli/chunks/{chunk-MVOHANJG.js → chunk-GST4YSBO.js} +4 -4
- package/dist-cli/chunks/{chunk-BIWJE7CB.js → chunk-I4RV5I6V.js} +1 -1
- package/dist-cli/chunks/{chunk-Y6IDAARY.js → chunk-I5WXVKR6.js} +1 -1
- package/dist-cli/chunks/{chunk-HC72ILJK.js → chunk-IO7KAVFK.js} +2 -2
- package/dist-cli/chunks/{chunk-XEH4QGWB.js → chunk-LMX7UB5T.js} +2 -2
- package/dist-cli/chunks/{chunk-YADWU7OZ.js → chunk-N4YCSOCR.js} +2 -2
- package/dist-cli/chunks/{chunk-IODOTOOP.js → chunk-NI3L4A65.js} +2 -2
- package/dist-cli/chunks/{chunk-IACEJQIO.js → chunk-ODGEH6OW.js} +2 -2
- package/dist-cli/chunks/{chunk-DNA6VS6M.js → chunk-Q4NDYO2U.js} +1 -1
- package/dist-cli/chunks/{chunk-PV6MBKKE.js → chunk-QPRF3UYX.js} +2 -2
- package/dist-cli/chunks/{chunk-M2TMFGZH.js → chunk-QXJMXSQP.js} +1 -1
- package/dist-cli/chunks/chunk-RLKSLUNR.js +2 -0
- package/dist-cli/chunks/{chunk-WZG3YVJR.js → chunk-S244IT4W.js} +1 -1
- package/dist-cli/chunks/chunk-SDHOM6ZG.js +62 -0
- package/dist-cli/chunks/{chunk-B7BMSU7H.js → chunk-TXKOJ3P5.js} +1 -1
- package/dist-cli/chunks/{chunk-IBEMMV5E.js → chunk-UDMJSFSH.js} +8 -8
- package/dist-cli/chunks/{chunk-DQZEN256.js → chunk-ULV4PWN4.js} +1 -1
- package/dist-cli/chunks/{chunk-2TYEWVS4.js → chunk-V4HTQPMA.js} +1 -1
- package/dist-cli/chunks/chunk-VATHADSI.js +2 -0
- package/dist-cli/chunks/{chunk-5Q7IHJ7K.js → chunk-VUOCUCJ2.js} +2 -2
- package/dist-cli/chunks/{chunk-JDGLBW64.js → chunk-WN7R4GL4.js} +1 -1
- package/dist-cli/chunks/chunk-XOTJD6PU.js +118 -0
- package/dist-cli/chunks/chunk-XUNPVF5K.js +1 -0
- package/dist-cli/chunks/{chunk-KZIXAYN5.js → chunk-YMFSRCHL.js} +4 -4
- package/dist-cli/chunks/{chunk-X2HNVXNM.js → chunk-YV74D4MG.js} +2 -2
- package/dist-cli/chunks/{chunk-SNX3M4XD.js → chunk-YVTWSC5Y.js} +3 -3
- package/dist-cli/chunks/cli-version-EKKWCHRX.js +2 -0
- package/dist-cli/chunks/{compat-ORRWNXVT.js → compat-ZVZM5TML.js} +3 -3
- package/dist-cli/chunks/control-TWINYHMY.js +2 -0
- package/dist-cli/chunks/{cpu-profile-6PRSBZ2F.js → cpu-profile-RWGQTWLP.js} +2 -2
- package/dist-cli/chunks/daemon-AOSMNBD4.js +2 -0
- package/dist-cli/chunks/{debug-Q3J2X4WW.js → debug-R7PL3MHF.js} +5 -5
- package/dist-cli/chunks/{detox-DN57GMMJ.js → detox-UIJMKIGQ.js} +2 -2
- package/dist-cli/chunks/{device-IL5TPYGU.js → device-7SRVX2PU.js} +2 -2
- package/dist-cli/chunks/{diagnose-BW6QWP4F.js → diagnose-OXAKLLZT.js} +2 -2
- package/dist-cli/chunks/drivers-BPPG22VP.js +2 -0
- package/dist-cli/chunks/{electron-DGMSXQWG.js → electron-CTCH4VOL.js} +3 -3
- package/dist-cli/chunks/flow-KA2WCWDL.js +2 -0
- package/dist-cli/chunks/help-XBQIK2XY.js +2 -0
- package/dist-cli/chunks/{hints-TK3EHB4U.js → hints-P3ZIAP3Z.js} +2 -2
- package/dist-cli/chunks/home-paths-ZSCTLOYE.js +2 -0
- package/dist-cli/chunks/{inspect-NFWFGU4B.js → inspect-2ABU5WET.js} +24 -24
- package/dist-cli/chunks/{install-desktop-GB3JKSNX.js → install-desktop-4NOQ3YY4.js} +3 -3
- package/dist-cli/chunks/{keys-RAAHRIFH.js → keys-RPVEUNUC.js} +2 -2
- package/dist-cli/chunks/{login-KQ37GHDE.js → login-6D6DXBO3.js} +4 -4
- package/dist-cli/chunks/{logout-63SH2Y25.js → logout-T5OSWDTJ.js} +2 -2
- package/dist-cli/chunks/{maestro-24BT3MML.js → maestro-MKCHEOKA.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-EYD2K3QH.js +2 -0
- package/dist-cli/chunks/{preview-KQAOVN6R.js → preview-S52ZNGN2.js} +2 -2
- package/dist-cli/chunks/{profile-AN2B4NJT.js → profile-IG5F3LTL.js} +2 -2
- package/dist-cli/chunks/{react-ATGV35B4.js → react-275HCOFC.js} +2 -2
- package/dist-cli/chunks/{record-36662T3R.js → record-YT63SUHO.js} +4 -4
- package/dist-cli/chunks/runtime-WYZMDZAK.js +2 -0
- package/dist-cli/chunks/{screenshot-K4N5MPAT.js → screenshot-5AZ4MY3A.js} +4 -4
- package/dist-cli/chunks/{screenshot-mode-4QOJDLSH.js → screenshot-mode-4S4EX2XJ.js} +2 -2
- package/dist-cli/chunks/{screenshots-TB35YMSR.js → screenshots-UUJNZSG7.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-W6X33BZ4.js → screenshots-capture-I66JD3AD.js} +2 -2
- package/dist-cli/chunks/{server-L2PKDJZ2.js → serve-O46Q4WAD.js} +18 -17
- package/dist-cli/chunks/setup-C44N54O7.js +77 -0
- package/dist-cli/chunks/skills-PPVS4XOQ.js +40 -0
- package/dist-cli/chunks/{slides-TORKO36P.js → slides-ZWSZJZUY.js} +2 -2
- package/dist-cli/chunks/store-3SLGP5O3.js +2 -0
- package/dist-cli/chunks/telemetry-2XLLWARK.js +2 -0
- package/dist-cli/chunks/{test-5VCENVW3.js → test-362G4M5A.js} +3 -3
- package/dist-cli/chunks/{three-mode-ZVS2DSX6.js → three-mode-JNVTM2UT.js} +2 -2
- package/dist-cli/chunks/{timeline-TNC5OWLF.js → timeline-VKC6ULRK.js} +2 -2
- package/dist-cli/chunks/{upgrade-E7IO6A7Z.js → upgrade-SJPX4SPA.js} +2 -2
- package/dist-cli/chunks/upload-MXOBV6RT.js +2 -0
- package/dist-cli/chunks/version-4Z7AFNH3.js +4 -0
- package/dist-cli/chunks/web-WB2I2AWL.js +2 -0
- package/dist-cli/chunks/{what-happened-RMHZ7DGX.js → what-happened-KQCWMQJT.js} +3 -3
- package/dist-cli/chunks/{whoami-D53ANHR5.js → whoami-K76PXAD4.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +4 -5
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +3 -6
- package/dist-lib/beta.mjs +3 -5
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +4 -4
- package/dist-lib/dev-bundle-resolution.cjs +2 -9
- package/dist-lib/home-paths.cjs +59 -1
- package/dist-lib/host/bridge-host.cjs +67 -5
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2 -2
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +2 -2
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +5 -4
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +124 -8
- package/dist-lib/vite.cjs +2 -2
- package/package.json +2 -1
- package/scripts/dev-server-scanner.ts +3 -4
- package/scripts/postinstall.cjs +2 -2
- package/scripts/preuninstall.cjs +5 -7
- package/skills/soot.md +178 -0
- package/skills/sootsim-debug.md +384 -0
- package/skills/sootsim-setup.md +96 -0
- package/skills/sootsim-test.md +292 -0
- package/skills/sootsim-visual.md +122 -0
- package/src/agent-daemon-client.ts +4 -14
- package/src/beta.ts +3 -5
- package/src/dev-bundle-resolution.ts +1 -14
- package/src/home-paths.ts +77 -2
- package/src/host/agent-host.ts +1 -1
- package/src/host/bridge-host.ts +65 -6
- package/src/metro-plugin.ts +1 -1
- package/src/runtime-assets.ts +1 -1
- package/src/vite-plugin.ts +1 -0
- package/dist-cli/chunks/agent-V3GVCRPL.js +0 -46
- package/dist-cli/chunks/auto-bootstrap-YXDP3WKH.js +0 -2
- package/dist-cli/chunks/beta-FGSMZWLP.js +0 -2
- package/dist-cli/chunks/chunk-2IFWVIKM.js +0 -2
- package/dist-cli/chunks/chunk-3T36XLP3.js +0 -119
- package/dist-cli/chunks/chunk-5KY7TQ42.js +0 -5
- package/dist-cli/chunks/chunk-BQOMDL4K.js +0 -1
- package/dist-cli/chunks/chunk-FHMPJZKM.js +0 -7
- package/dist-cli/chunks/chunk-GQAWFQNN.js +0 -23
- package/dist-cli/chunks/chunk-HJTKKF7M.js +0 -13
- package/dist-cli/chunks/chunk-K4JAWKOY.js +0 -1
- package/dist-cli/chunks/chunk-NXGQS7IR.js +0 -2
- package/dist-cli/chunks/chunk-R2INPDGW.js +0 -1
- package/dist-cli/chunks/chunk-SLL5SZN4.js +0 -2
- package/dist-cli/chunks/chunk-XM66K64H.js +0 -79
- package/dist-cli/chunks/cli-version-3L6FFDIX.js +0 -2
- package/dist-cli/chunks/config-5IB6ONJ2.js +0 -45
- package/dist-cli/chunks/control-BM4V27OB.js +0 -2
- package/dist-cli/chunks/daemon-62MZT4G4.js +0 -67
- package/dist-cli/chunks/drivers-V6QDFZQD.js +0 -2
- package/dist-cli/chunks/flow-VBM6TU32.js +0 -2
- package/dist-cli/chunks/help-XWKNL743.js +0 -2
- package/dist-cli/chunks/home-paths-G23H3RO6.js +0 -2
- package/dist-cli/chunks/install-5YL7FITA.js +0 -2
- package/dist-cli/chunks/launch-DYFE4CAD.js +0 -16
- package/dist-cli/chunks/optional-demo-registry-JJXPB3UD.js +0 -2
- package/dist-cli/chunks/runtime-NRMC3U3D.js +0 -2
- package/dist-cli/chunks/runtime-delivery-RO6CTYPQ.js +0 -2
- package/dist-cli/chunks/setup-repo-AK6QOUE7.js +0 -2
- package/dist-cli/chunks/skills-KDSOWUOE.js +0 -10
- package/dist-cli/chunks/start-GH2AOUX6.js +0 -23
- package/dist-cli/chunks/store-JHW65VGQ.js +0 -2
- package/dist-cli/chunks/telemetry-SZLRXJXW.js +0 -2
- package/dist-cli/chunks/upload-KKEWETA5.js +0 -2
- package/dist-cli/chunks/version-37OD33SE.js +0 -4
- package/dist-cli/chunks/web-4JVMIBTB.js +0 -2
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sootsim-debug
|
|
3
|
+
description: Debug rendering, performance, and accessibility issues in your React Native app under sootsim
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# sootsim debug
|
|
7
|
+
|
|
8
|
+
the foundational skill for "something is wrong with my app in sootsim".
|
|
9
|
+
covers debugging, performance, and accessibility — three branches that
|
|
10
|
+
share the same CLI primitives, the same auto-settling contract, and the
|
|
11
|
+
same diff/snapshot workflow. start here for any rendering, interaction,
|
|
12
|
+
event-order, or correctness question. for pixel-level rendering fidelity
|
|
13
|
+
load `/sootsim-visual` instead.
|
|
14
|
+
|
|
15
|
+
> needs a connected, pinned sim. if `sootsim describe` errors, load
|
|
16
|
+
> `/sootsim-setup` first.
|
|
17
|
+
|
|
18
|
+
## route in
|
|
19
|
+
|
|
20
|
+
- "my app renders wrong / wrong props / wrong tree" → [debugging](#branch--debugging)
|
|
21
|
+
- "feels slow / drops frames / janks on scroll" → [performance](#branch--performance)
|
|
22
|
+
- "screen reader can't find this / wrong label / tap target too small" → [accessibility](#branch--accessibility)
|
|
23
|
+
- "I want to see what just happened" (ephemeral toast, async navigation,
|
|
24
|
+
fetch + alert sequence) → [the timeline](#the-timeline-what-happened)
|
|
25
|
+
- "I want pixel-level fidelity to iOS" → load `/sootsim-visual`
|
|
26
|
+
- "I want to author a test" → load `/sootsim-test`
|
|
27
|
+
|
|
28
|
+
## anti-patterns (apply to every branch)
|
|
29
|
+
|
|
30
|
+
- **`a1`/`a2`/`b0` style ids mean sootsim sims, never browser tabs.** when a user
|
|
31
|
+
says "look at a3", that's the `sootsim list` sim id. do not open chrome
|
|
32
|
+
MCP unless the user explicitly says "use chrome" — the canvas has no
|
|
33
|
+
DOM to inspect anyway.
|
|
34
|
+
- **the CLI auto-settles. don't add `sleep`.** every read waits up to
|
|
35
|
+
1800 ms for in-flight transitions to start; every write polls layout
|
|
36
|
+
hash until stable. if a read keeps racing its write, the fix is **never**
|
|
37
|
+
a blind `sleep` — it's `wait selector`, `wait ready`, `wait idle`, or
|
|
38
|
+
fixing the underlying animation-completion signal.
|
|
39
|
+
- **prefer `--testid` over text matching.** text drifts under i18n, copy
|
|
40
|
+
changes, and duplicate strings. add `testID` during implementation and
|
|
41
|
+
query against it.
|
|
42
|
+
- **pin a sim once.** if more than one is live, an unpinned command
|
|
43
|
+
hits the first and produces results from the wrong app. `sootsim use
|
|
44
|
+
<id>` at the start of the workflow.
|
|
45
|
+
- **`debug eval` is an escape hatch.** if a top-level command feels
|
|
46
|
+
broken or missing, file an issue — every agent after you benefits from
|
|
47
|
+
a better CLI, not a pile of ad-hoc scripts.
|
|
48
|
+
- **sweep `get errors` and `get requests` after every repro.** the
|
|
49
|
+
one-line summary tells you the count grew; you still have to *look at
|
|
50
|
+
them*. a "fixed" behavior with a new console error is not fixed.
|
|
51
|
+
- **"found a testID" is not done.** done is: reliable repro + identified
|
|
52
|
+
root cause (specific node + prop, or event + handler) + verified fix.
|
|
53
|
+
|
|
54
|
+
## the timeline ("what happened")
|
|
55
|
+
|
|
56
|
+
between two CLI calls, things happen invisibly — toasts flash, keyboards
|
|
57
|
+
open and close, screens push and pop, alerts fire and dismiss, async
|
|
58
|
+
fetches resolve. the timeline records them so you can ask "what
|
|
59
|
+
happened" instead of racing the UI with `find`.
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
sootsim timeline start # arm recording (cheap kinds default-on)
|
|
63
|
+
# reproduce the flow
|
|
64
|
+
sootsim what-happened # events since the last CLI call
|
|
65
|
+
sootsim what-happened --since 10s # absolute window
|
|
66
|
+
sootsim what-happened --kinds toast,fetch # filter to a few kinds
|
|
67
|
+
sootsim what-happened --summary # one-line counts
|
|
68
|
+
sootsim what-happened --flow # section events by screen/route
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
semantic kinds the timeline understands: `keyboard`, `screen`, `route`,
|
|
72
|
+
`alert`, `actionsheet`, `picker`, `notification`, `toast`, `scroll`,
|
|
73
|
+
`gesture`, `text-input`, `reanimated`, `animation`, `fetch`, `console`,
|
|
74
|
+
`app-launch`, `shell`. cheap kinds record by default; heavier kinds
|
|
75
|
+
(scroll, gesture, text-input, reanimated, animation) opt in via
|
|
76
|
+
`sootsim timeline start scroll,gesture,…`.
|
|
77
|
+
|
|
78
|
+
every other CLI command also prints a one-line footer for events since
|
|
79
|
+
the last call — that's the headline indicator. when the footer is empty,
|
|
80
|
+
there's nothing new to look at; when it says `since last: 1 error · 1
|
|
81
|
+
toast · 1 screen push`, run `sootsim what-happened` to see the detail.
|
|
82
|
+
|
|
83
|
+
> reach for the timeline first when the question involves *something
|
|
84
|
+
> that appeared briefly and disappeared*. it's faster than a screenshot
|
|
85
|
+
> and tells you the duration too.
|
|
86
|
+
|
|
87
|
+
## automatic settling — when you actually need a manual wait
|
|
88
|
+
|
|
89
|
+
every CLI command already participates in a two-phase settle. you only
|
|
90
|
+
need a manual wait when:
|
|
91
|
+
|
|
92
|
+
1. the CLI explicitly printed `⚠ auto-wait timed out after Nms — next
|
|
93
|
+
command may see mid-animation state` *and* your next read depends on
|
|
94
|
+
the animation finishing.
|
|
95
|
+
2. the transition is longer than ~1.2 s (full stack navigation,
|
|
96
|
+
crossfades, video first-frame, network-backed render).
|
|
97
|
+
3. you want `--strict` settle, which also requires animation flags to
|
|
98
|
+
clear — only safe for apps with no perpetual background animation
|
|
99
|
+
(no pulsing dots, no shimmer, no looping Lottie).
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
sootsim do settle 5 # wait up to 5s for layout stability
|
|
103
|
+
sootsim wait idle --max-ms 5000 # same thing under the `wait` verb
|
|
104
|
+
sootsim wait idle --strict # also require animation flags clear
|
|
105
|
+
sootsim do tap-id play --no-wait # skip auto-settle on one command
|
|
106
|
+
SOOTSIM_NO_AUTO_WAIT=1 sootsim ... # disable auto-settle for a lane
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## branch — debugging
|
|
110
|
+
|
|
111
|
+
the playbook for "wrong tree / wrong props / wrong handler":
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
sootsim describe # what's on screen now
|
|
115
|
+
sootsim get errors 5 # any console smoke?
|
|
116
|
+
sootsim find --testid <node> # locate the suspect
|
|
117
|
+
sootsim debug snapshot before
|
|
118
|
+
# reproduce
|
|
119
|
+
sootsim debug snapshot after
|
|
120
|
+
sootsim debug diff before after # structural diff: what changed?
|
|
121
|
+
sootsim what-happened # timeline events during the repro
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
reading `describe` output:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
[button] "Sign in" #loginButton @(0,347) 402x44 [bg:#006AFF fg:#fff] (tap)
|
|
128
|
+
<text> "Forgot?" @(341,287) 55x28 [fg:#666 fontSize:14]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
format: `[type] "text" #testID @(x,y) WxH [styles] (flags)`. coordinates
|
|
132
|
+
are points (CSS pixels), origin top-left, parent-relative.
|
|
133
|
+
|
|
134
|
+
for transitions, alerts, native UI, or anything spanning the shell ↔
|
|
135
|
+
tenant boundary, lean on the timeline before reaching for traces:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
sootsim timeline start
|
|
139
|
+
# reproduce the launch / dismiss / alert
|
|
140
|
+
sootsim what-happened --kinds shell,alert,screen,animation
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
you're done when:
|
|
144
|
+
|
|
145
|
+
1. repro is reliable (same input → same output)
|
|
146
|
+
2. root cause is identified (specific node + prop, or event + handler,
|
|
147
|
+
not "something in the navigation stack")
|
|
148
|
+
3. fix re-verified through the same `snapshot → reproduce → diff` loop
|
|
149
|
+
|
|
150
|
+
## branch — performance
|
|
151
|
+
|
|
152
|
+
```sh
|
|
153
|
+
sootsim debug perf start # arm capture (also clears prior frames)
|
|
154
|
+
# reproduce the slow interaction
|
|
155
|
+
sootsim debug perf stop # full report
|
|
156
|
+
sootsim debug perf stop --json # machine-readable summary
|
|
157
|
+
sootsim debug perf frames # per-frame ring breakdown
|
|
158
|
+
sootsim debug perf worst # the slowest frames first
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`debug perf` output:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
frames: 847
|
|
165
|
+
total: 14123ms
|
|
166
|
+
avg: 16.7ms
|
|
167
|
+
max: 42ms (⚠ dropped frames)
|
|
168
|
+
p95: 22.3ms
|
|
169
|
+
layout frames: 123
|
|
170
|
+
layout avg: 2.1ms
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
frame budget: target **8 ms / frame (120 fps)** — render <4 ms, layout
|
|
174
|
+
<2 ms, JS/react <2 ms. heavier paints can fall back to the 16 ms / 60 fps
|
|
175
|
+
budget. **p95 >20 ms is visible jank for a scrolling surface.**
|
|
176
|
+
|
|
177
|
+
profiling a whole flow:
|
|
178
|
+
|
|
179
|
+
```sh
|
|
180
|
+
sootsim flow flows/scroll-feed.yaml --profile # per-step + frame stats
|
|
181
|
+
sootsim cpu-profile --duration 5 --output /tmp/trace.cpuprofile # sampled CPU
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
common patterns → first probe:
|
|
185
|
+
|
|
186
|
+
| symptom | likely | next |
|
|
187
|
+
| --- | --- | --- |
|
|
188
|
+
| scroll jank | layout firing during scroll | `debug enable layout` + `debug recent layout 40` |
|
|
189
|
+
| anim stutter | `Animated.Value` on `width`/`height` | switch to `transform: [{ scale }]` or `translate` |
|
|
190
|
+
| first-tap lag | font / image still loading | `get requests` + `debug state image` |
|
|
191
|
+
| memory growth | live animation drivers not cleaned up | `debug state animations` |
|
|
192
|
+
| slow initial render | many text measurements | `debug recent text` on first paint |
|
|
193
|
+
|
|
194
|
+
debug channels that help, but cost 1–3 ms/frame on their own — enable
|
|
195
|
+
only what you're investigating:
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
sootsim debug enable layout,onlayout,render,animated
|
|
199
|
+
# reproduce
|
|
200
|
+
sootsim debug recent layout 20 # last 20 layout events
|
|
201
|
+
sootsim debug recent render 20 # last 20 draw passes
|
|
202
|
+
sootsim debug disable layout,onlayout,render,animated
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
you're done when: a p95 number for the interaction + named hot path +
|
|
206
|
+
remeasured (a fresh `perf start` between runs clears the buffer) and the
|
|
207
|
+
number moved.
|
|
208
|
+
|
|
209
|
+
watch out for:
|
|
210
|
+
|
|
211
|
+
- **dynamic format strings bust the text-measurement cache.** `${count}
|
|
212
|
+
messages` re-measures every change — render the number and the word as
|
|
213
|
+
separate `<Text>` nodes.
|
|
214
|
+
- **`--strict` settle hangs forever on perpetual animation.** anything
|
|
215
|
+
with a pulsing dot or looping Lottie will never go quiet under
|
|
216
|
+
`--strict`. use plain `wait idle` there.
|
|
217
|
+
- **p95 over a single run is noise.** take three runs minimum.
|
|
218
|
+
|
|
219
|
+
## branch — accessibility
|
|
220
|
+
|
|
221
|
+
```sh
|
|
222
|
+
sootsim get a11y # full a11y tree
|
|
223
|
+
sootsim get a11y --issues # only nodes with problems
|
|
224
|
+
sootsim describe --a11y # inline a11y info on every node
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
issue summary format:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
[input] "" role=none label=null ⚠ missing label
|
|
231
|
+
[button] "➜" @(340,280) 20x20 (tap) ⚠ touch target <44×44
|
|
232
|
+
<text> "Sign in" color=#777 bg=#888 ⚠ contrast 1.4:1 (need 4.5:1)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
finding offenders fast:
|
|
236
|
+
|
|
237
|
+
```sh
|
|
238
|
+
sootsim find --no-label # interactive nodes missing label
|
|
239
|
+
sootsim find --no-role # interactive nodes missing role
|
|
240
|
+
sootsim find --pressable --max-dim 44 # undersized tap targets
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
what gets checked:
|
|
244
|
+
|
|
245
|
+
- **missing labels** — interactive nodes without `accessibilityLabel`
|
|
246
|
+
- **missing roles** — `Pressable`/`Touchable` without `accessibilityRole`
|
|
247
|
+
- **missing hints** — complex interactions without `accessibilityHint`
|
|
248
|
+
- **touch target size** — tappable nodes with hitSlop-expanded rect <44×44
|
|
249
|
+
- **contrast** — text color vs detectable background
|
|
250
|
+
- **label / visible-text mismatch** — label that reads differently from
|
|
251
|
+
the text VoiceOver would fall back to (often a translation bug)
|
|
252
|
+
- **duplicate labels** — two reachable nodes with identical labels on
|
|
253
|
+
one screen ("Open" + "Open" leaves no way to disambiguate)
|
|
254
|
+
|
|
255
|
+
triage order:
|
|
256
|
+
|
|
257
|
+
- **P0** — interactive node with no label or no role (blocks screen
|
|
258
|
+
reader entirely)
|
|
259
|
+
- **P1** — tap target <44×44, duplicate labels
|
|
260
|
+
- **P2** — contrast, label/visible-text mismatch
|
|
261
|
+
|
|
262
|
+
fix → verify loop (the same shape as debugging):
|
|
263
|
+
|
|
264
|
+
```sh
|
|
265
|
+
sootsim get a11y --issues > before.txt
|
|
266
|
+
# apply the fix
|
|
267
|
+
sootsim get a11y --issues > after.txt
|
|
268
|
+
diff before.txt after.txt
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
fixing common cases:
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
// bad: icon button with no accessible name
|
|
275
|
+
<Pressable onPress={onBack}>
|
|
276
|
+
<ChevronLeftIcon />
|
|
277
|
+
</Pressable>
|
|
278
|
+
|
|
279
|
+
// good: labeled + roled + hinted + hitSlop'd
|
|
280
|
+
<Pressable
|
|
281
|
+
onPress={onBack}
|
|
282
|
+
accessibilityRole="button"
|
|
283
|
+
accessibilityLabel="Back"
|
|
284
|
+
accessibilityHint="Returns to the previous screen"
|
|
285
|
+
hitSlop={12} // bumps tap target to 44×44 minimum
|
|
286
|
+
>
|
|
287
|
+
<ChevronLeftIcon />
|
|
288
|
+
</Pressable>
|
|
289
|
+
|
|
290
|
+
// bad: text input with no programmatic label
|
|
291
|
+
<TextInput placeholder="Email" onChangeText={setEmail} />
|
|
292
|
+
|
|
293
|
+
// good: label survives even when placeholder is hidden
|
|
294
|
+
<TextInput
|
|
295
|
+
placeholder="Email"
|
|
296
|
+
accessibilityLabel="Email address"
|
|
297
|
+
onChangeText={setEmail}
|
|
298
|
+
/>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
watch out for:
|
|
302
|
+
|
|
303
|
+
- **placeholders are not labels.** they disappear after the user types.
|
|
304
|
+
- **hitSlop expands the a11y rect too.** rarely need to make the
|
|
305
|
+
rendered button bigger — `hitSlop={12}` is usually enough.
|
|
306
|
+
- **`accessibilityRole="image"` is not an `alt` tag.** pair it with
|
|
307
|
+
`accessibilityLabel` or VoiceOver reads "image" and nothing else.
|
|
308
|
+
- **`importantForAccessibility="no-hide-descendants"` hides an entire
|
|
309
|
+
subtree.** useful for decorative chrome, dangerous if you forget it.
|
|
310
|
+
|
|
311
|
+
run the screen reader on a real device at least once before shipping —
|
|
312
|
+
labels that read fine on paper often sound robotic ("delete_message_btn_v2"
|
|
313
|
+
type names sneak in).
|
|
314
|
+
|
|
315
|
+
## recovery — common failure modes
|
|
316
|
+
|
|
317
|
+
- **`describe` returns nothing** — no sim pinned, or the app isn't
|
|
318
|
+
loaded. load `/sootsim-setup` and re-confirm.
|
|
319
|
+
- **`find` returns multiple matches** — narrow with `--testid`,
|
|
320
|
+
`--visible`, or both.
|
|
321
|
+
- **`debug perf` reports zero frames** — you didn't run `perf start`
|
|
322
|
+
first, or the capture window closed before any frame committed.
|
|
323
|
+
- **`get a11y --issues` returns 100+ items** — sort by P0 first; fixing
|
|
324
|
+
one label often cascades to a parent's a11y subtree.
|
|
325
|
+
- **timeline footer keeps showing 1 error but `get errors` is empty** —
|
|
326
|
+
the footer reads "since last cursor advance"; `get errors` is absolute.
|
|
327
|
+
the error already scrolled out of the absolute ring buffer.
|
|
328
|
+
|
|
329
|
+
## reference
|
|
330
|
+
|
|
331
|
+
### finding and interacting
|
|
332
|
+
|
|
333
|
+
```sh
|
|
334
|
+
sootsim describe # all visible elements with styles
|
|
335
|
+
sootsim describe button # filter by text/role/label/testID
|
|
336
|
+
sootsim describe --testid foo # only the subtree under a testID
|
|
337
|
+
sootsim describe --verbose # include every style property
|
|
338
|
+
|
|
339
|
+
sootsim find "Sign in" # by text content
|
|
340
|
+
sootsim find --testid loginButton
|
|
341
|
+
sootsim find --role button
|
|
342
|
+
sootsim find --pressable
|
|
343
|
+
sootsim find --visible # only on-screen nodes
|
|
344
|
+
|
|
345
|
+
sootsim do tap-id loginButton # tap by testID (preferred)
|
|
346
|
+
sootsim do tap-text "Submit" # tap by text
|
|
347
|
+
sootsim do tap 196 400 # tap at coordinates
|
|
348
|
+
sootsim do type "hello world" # type into focused input
|
|
349
|
+
sootsim do type-into emailInput "a@b" # focus then type
|
|
350
|
+
sootsim do key return # special key (return, backspace, …)
|
|
351
|
+
sootsim do scroll feed-list 0 500 # scroll a testID by dx/dy
|
|
352
|
+
sootsim do swipe feed-list left # directional swipe
|
|
353
|
+
sootsim do long-press messageRow 800 # ms hold
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### errors and requests
|
|
357
|
+
|
|
358
|
+
```sh
|
|
359
|
+
sootsim get errors 5 # last 5 console errors
|
|
360
|
+
sootsim get warnings 5
|
|
361
|
+
sootsim get requests 5 # recent failed requests
|
|
362
|
+
sootsim logs --since 30s # recent console output
|
|
363
|
+
sootsim network --since 30s # recent network traffic
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### snapshots and diff
|
|
367
|
+
|
|
368
|
+
```sh
|
|
369
|
+
sootsim debug snapshot before
|
|
370
|
+
# interact
|
|
371
|
+
sootsim debug snapshot after
|
|
372
|
+
sootsim debug diff before after # added / removed / changed nodes
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### debug channels
|
|
376
|
+
|
|
377
|
+
useful: `animated`, `layout`, `onlayout`, `render`, `sheets`, `portals`,
|
|
378
|
+
`gesture`, `scroll`, `text`, `image`.
|
|
379
|
+
|
|
380
|
+
```sh
|
|
381
|
+
sootsim debug enable animated,layout,sheets,portals
|
|
382
|
+
sootsim debug recent layout 20 # last 20 events on the channel
|
|
383
|
+
sootsim debug disable animated,layout,sheets,portals
|
|
384
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sootsim-setup
|
|
3
|
+
description: Get sootsim connected to your React Native app — from `npm install sootsim` to a driveable sim
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# sootsim setup
|
|
7
|
+
|
|
8
|
+
you've installed sootsim into a React Native project and want to drive it
|
|
9
|
+
from the CLI. this skill takes you from zero to a connected, pinned sim
|
|
10
|
+
that every other sootsim skill assumes exists. if `sootsim describe` already
|
|
11
|
+
returns a tree, you're past this skill — load `/sootsim-debug` for
|
|
12
|
+
debugging or `/sootsim-test` for writing tests.
|
|
13
|
+
|
|
14
|
+
## anti-patterns (read first)
|
|
15
|
+
|
|
16
|
+
- **never `sootsim claim --force` a sim held by another CLI.** the lease
|
|
17
|
+
exists for a reason — forcing strands the other agent and corrupts the
|
|
18
|
+
bridge state. use `sootsim open --new` to start a fresh sim instead.
|
|
19
|
+
- **don't switch sims mid-investigation.** pin once with `sootsim use
|
|
20
|
+
<id>` and keep it pinned. an unpinned command hits the first sim,
|
|
21
|
+
which produces baffling results when more than one is live.
|
|
22
|
+
- **an empty `sootsim list` is not "broken sootsim"** — it usually means the
|
|
23
|
+
daemon is down, the dev server port is wrong, or the runtime is missing.
|
|
24
|
+
walk the recovery checklist before reinstalling.
|
|
25
|
+
|
|
26
|
+
## first move
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
sootsim setup # one-time — installs daemon, optional repo setup
|
|
30
|
+
sootsim open 8081 # load a metro/expo dev server
|
|
31
|
+
sootsim list # confirm exactly one sim is reachable
|
|
32
|
+
sootsim use <id> # pin it for the rest of the workflow
|
|
33
|
+
sootsim describe # smoke test — should print a render tree
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
if you do not know the port, run `sootsim open` with no target and pick from
|
|
37
|
+
the detected dev servers. for hosted or unusual targets, pass the URL
|
|
38
|
+
explicitly:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
sootsim open 8081 # load a metro dev server
|
|
42
|
+
sootsim open https://my-app.local # load a hosted bundle
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## you're done when
|
|
46
|
+
|
|
47
|
+
- `sootsim list` shows your sim and no orphans
|
|
48
|
+
- `sootsim describe` returns a render tree, not an error
|
|
49
|
+
- the same sim id appears in `sootsim describe`, `sootsim find`, and
|
|
50
|
+
every subsequent command
|
|
51
|
+
- `sootsim get errors 5` and `sootsim get requests 5` are quiet (or the
|
|
52
|
+
warnings are ones you understand)
|
|
53
|
+
|
|
54
|
+
## recovery — common failure modes
|
|
55
|
+
|
|
56
|
+
**`sootsim list` is empty.** walk this checklist in order:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
sootsim daemon status # is the bridge daemon up?
|
|
60
|
+
sootsim runtime list # is at least one engine runtime installed?
|
|
61
|
+
sootsim open <port> # does loading explicitly work?
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
if daemon is down: run `sootsim setup`, or `sootsim serve` in another shell for
|
|
65
|
+
a foreground bridge. if no runtime is installed, `sootsim open` installs it
|
|
66
|
+
before launching. if open errors with "port unreachable": confirm your dev
|
|
67
|
+
server is actually serving — the bundler has to be up before sootsim can
|
|
68
|
+
attach.
|
|
69
|
+
|
|
70
|
+
**two sims appear unexpectedly.** an earlier `sootsim claim` didn't
|
|
71
|
+
release on exit. close the orphan explicitly:
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
sootsim list # note the stale id
|
|
75
|
+
sootsim close <id> # release it cleanly
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**`sootsim open` errors with "no runtime".** the engine binary isn't installed.
|
|
79
|
+
Run `sootsim runtime install`, then retry `sootsim open <port>`.
|
|
80
|
+
|
|
81
|
+
**bridge disconnects mid-sim.** the WebSocket dropped (laptop slept,
|
|
82
|
+
network blip). re-pin: `sootsim use <id>`. the daemon retries reconnection
|
|
83
|
+
automatically; you usually just need to re-issue the command.
|
|
84
|
+
|
|
85
|
+
**"sim held by another CLI".** another agent or your own previous CLI
|
|
86
|
+
process has the lease. find it (`sootsim list`), close it (`sootsim close
|
|
87
|
+
<id>`), or start a clean sim (`sootsim open --new`) — do **not**
|
|
88
|
+
`sootsim claim --force`.
|
|
89
|
+
|
|
90
|
+
## related
|
|
91
|
+
|
|
92
|
+
- `/sootsim-debug` — once setup is good, this is where you debug
|
|
93
|
+
rendering, performance, and accessibility issues.
|
|
94
|
+
- `/sootsim-test` — write or run automated flows against the connected
|
|
95
|
+
sim.
|
|
96
|
+
- `/sootsim-visual` — pixel-level rendering comparisons.
|