@swmansion/argent 0.32.0 → 0.32.1-next.1

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 (57) hide show
  1. package/bin/argent-android-devtools-0.3.0.apk +0 -0
  2. package/bin/darwin/ax-service +0 -0
  3. package/bin/darwin/tvos-ax-service +0 -0
  4. package/bin/darwin/tvos-hid-daemon +0 -0
  5. package/bin/network-inspector/network-inspector.jar +0 -0
  6. package/bin/tcp/ax-service +0 -0
  7. package/dist/cli-cmds.mjs +1 -1
  8. package/dist/installer.mjs +7 -7
  9. package/dist/mcp-server.mjs +1 -1
  10. package/dist/tool-args.generated.d.ts +178 -178
  11. package/dist/tool-server.cjs +1281 -1459
  12. package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
  13. package/dylibs/libKeyboardPatch.dylib +0 -0
  14. package/dylibs/libNativeDevtoolsIos.dylib +0 -0
  15. package/dylibs/tcp/libArgentInjectionBootstrap.dylib +0 -0
  16. package/dylibs/tcp/libKeyboardPatch.dylib +0 -0
  17. package/dylibs/tcp/libNativeDevtoolsIos.dylib +0 -0
  18. package/dylibs/tvos/libArgentInjectionBootstrap.dylib +0 -0
  19. package/dylibs/tvos/libKeyboardPatch.dylib +0 -0
  20. package/dylibs/tvos/libNativeDevtoolsIos.dylib +0 -0
  21. package/package.json +1 -1
  22. package/rules/argent.md +19 -183
  23. package/skills/argent-android-emulator-setup/SKILL.md +5 -13
  24. package/skills/argent-create-e2e/SKILL.md +1 -1
  25. package/skills/argent-create-e2e/references/e2e-yaml.md +12 -17
  26. package/skills/argent-create-e2e/references/live-authoring.md +25 -65
  27. package/skills/argent-create-e2e/references/reliability-and-recovery.md +8 -8
  28. package/skills/argent-device-interact/SKILL.md +65 -367
  29. package/skills/argent-device-interact/references/chromium.md +4 -19
  30. package/skills/argent-device-interact/references/foldables.md +8 -0
  31. package/skills/argent-device-interact/references/harmonyos.md +13 -50
  32. package/skills/argent-ios-device-interact/SKILL.md +0 -1
  33. package/skills/argent-ios-device-setup/SKILL.md +1 -1
  34. package/skills/argent-ios-simulator-setup/SKILL.md +3 -9
  35. package/skills/argent-lens/SKILL.md +20 -75
  36. package/skills/argent-metro-debugger/SKILL.md +35 -101
  37. package/skills/argent-native-profiler/SKILL.md +23 -92
  38. package/skills/argent-qa-e2e/SKILL.md +5 -5
  39. package/skills/argent-react-native-app-workflow/SKILL.md +34 -203
  40. package/skills/argent-react-native-optimization/SKILL.md +10 -26
  41. package/skills/argent-react-native-optimization/references/fix-reference.md +11 -11
  42. package/skills/argent-react-native-optimization/references/lint-rules.md +4 -5
  43. package/skills/argent-react-native-optimization/references/semantic-checklist.md +2 -2
  44. package/skills/argent-react-native-profiler/SKILL.md +46 -110
  45. package/skills/argent-screen-recording/SKILL.md +18 -37
  46. package/skills/argent-screenshot-diff/SKILL.md +8 -52
  47. package/skills/argent-settings-permissions/SKILL.md +15 -117
  48. package/skills/argent-test-ui-flow/SKILL.md +20 -90
  49. package/skills/argent-tv-interact/SKILL.md +9 -34
  50. package/skills/argent-tv-interact/references/vega.md +23 -0
  51. package/agents/argent-environment-inspector.md +0 -107
  52. package/agents/references/quality-control-checklist.md +0 -45
  53. package/skills/argent-device-interact/references/gesture-examples.md +0 -114
  54. package/skills/argent-device-interact/references/secrets.md +0 -23
  55. package/skills/argent-metro-debugger/references/failure-scenarios.md +0 -14
  56. package/skills/argent-metro-debugger/references/source-maps.md +0 -27
  57. package/skills/argent-react-native-profiler/references/diagnostic-tools.md +0 -101
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/argent",
3
- "version": "0.32.0",
3
+ "version": "0.32.1-next.1",
4
4
  "mcpName": "io.github.software-mansion/argent",
5
5
  "description": "MCP server for iOS Simulator and Android Emulator control",
6
6
  "license": "Apache-2.0",
package/rules/argent.md CHANGED
@@ -1,198 +1,34 @@
1
1
  ---
2
- description: Argent iOS Simulator and Android Emulator Agent, always-on guidance for methodology and tools for working with, interacting, testing and profiling mobile app work
2
+ description: Always-on Argent rules for driving, testing and profiling apps on simulators, emulators, phones, TVs and Chromium
3
3
  alwaysApply: true
4
4
  ---
5
5
 
6
- <description>
7
- If argent is installed and configured in this environment, its MCP tools are the preferred form of interaction with the application for iOS simulator, physical iPhone, Android emulator, Chromium (CDP) app, and Vega (Amazon Fire TV) device control; otherwise see `<availability_check>` below before attempting any argent workflow. A "Chromium (CDP) app" is any Chromium runtime exposing a Chrome DevTools Protocol endpoint: an Electron app, or any Chromium-family browser (Chrome/Brave/Edge) launched with `--remote-debugging-port`; all are driven through the same tool surface and tagged `platform: "chromium"`. A "Vega device" is a virtual device (VVD) or physical unit, driven by tv-remote (D-pad) and tagged `platform: "vega"`. Physical iPhones (iPads are not supported) appear in `list-devices` as iOS entries with kind `"device"`; they are driven over USB cable only, and the on-device runner's signing is auto-detected from the Mac's keychain (`ARGENT_IOS_TEAM_ID` overrides). Automation there is app-scoped: `launch-app` registers the target app before anything else can act. Read `argent-ios-device-setup` to get one connected and `argent-ios-device-interact` before interacting.
8
- Running MCP server and managing the Argent toolkit utilises `argent` command - if asked use `argent --help` for reference.
9
- To check current version of MCP server run `argent --version` command.
6
+ Argent - general rules:
10
7
 
11
- Use cases:
12
-
13
- - User mentions iOS simulator, Android emulator, device, or app interaction
14
- - The app user is working with is a mobile application which can be run in a simulator/emulator
15
- - Any tapping, swiping, typing, screenshotting, or inspecting a running app
16
- - Any code change that affects visible mobile UI, layout, styling, copy, navigation, or screen composition
17
- - Any request to execute manual QA, UI QA, or visual behavior validation for a mobile app
18
- - Running, debugging, or testing a React Native app (iOS, Android or Vega)
19
- - Profiling performance or diagnosing re-renders in a React Native app (iOS or Android)
20
- - Running, debugging, or testing a Chromium (CDP) app: an Electron app (boot with `boot-device` + `electronAppPath`) or a Chromium browser exposing CDP (auto-discovered on port `9222` / `ARGENT_CHROMIUM_PORTS`); on Chromium scroll with `gesture-scroll` and drag with `gesture-drag`; `gesture-swipe` is touch-only
21
- </description>
8
+ - do not derive tap coordinates from screenshot pixels; use inspection tools that give coordinates
9
+ - use the platform the user named; otherwise prefer a device `list-devices` shows already running, and don't default to iOS; in a single-platform project boot that platform.
10
+ - if tap fails twice, stop retrying and re-run a discovery tool
11
+ - Prefer mcp-tool calls over raw commands like `xcrun` or `adb`; use them as fallback.
12
+ - Interaction tools return screenshot and element tree automatically.
13
+ - prefer `launch-app` or `open-url` than tapping icons on home screen.
14
+ - If a task can require a saved e2e test, load `argent-create-e2e` (`argent-qa-e2e` for acceptance tests) before the first launch or in-app action; recording is not retroactive.
15
+ - Load the matching `argent-*` skill before React Native build/debug, profiling, a physical phone or a TV.
16
+ - Do not stop simulator servers when a task finishes: the next task reuses them. Call `stop-all-simulator-servers` when the user asks to clean up or ends the session, or when a skill tells you to recycle a device's services, with devices this session used. One tool-server is shared by every other agent, so unscoped call tears down their devices too. Never stop a Metro the user started unless they ask.
17
+ - Use the `await-ui-element` tool to block until the UI settles instead of polling using screenshot.
18
+ - The `argent` CLI manages the toolkit: `argent --help` lists commands, `argent --version` shows the installed version.
22
19
 
23
20
  <availability_check>
24
- <important>Run this check once per session, before the first argent tool call or `argent` command. Do not re-probe before later calls.</important>
25
-
21
+ Run this check once per session. Do not re-probe before later calls.
26
22
  Confirm argent is available:
27
23
 
28
- 1. Are `mcp__argent__*` tools in your tool list? If none are present, argent is not available.
29
- 2. If still unsure, run `command -v argent`. A non-zero exit means the CLI is not on PATH.
24
+ 1. Are `mcp__argent__*` tools in your tool list? If none, argent is not available.
25
+ 2. If unsure, run `command -v argent`. Non-zero exit = the CLI is not on PATH.
30
26
 
31
27
  If argent IS available, ignore the rest of this block and follow this rule normally.
32
28
 
33
- If argent is ABSENT, treat it as an expected state, not an error to retry. Do not call `mcp__argent__*` tools, do not run `argent` commands, and do not attempt any argent workflow. Tell the user once, and ask if you should continue without argent:
29
+ If argent is ABSENT, treat it as an expected state, not an error to retry. Do not call `mcp__argent__*` tools, do not run `argent` commands, do not attempt any argent workflow.
30
+ Tell the user once, and ask if you should continue without argent:
34
31
 
35
32
  > Argent isn't installed in this environment. To enable the mobile/Chromium tooling this repo is configured for, run `npx @swmansion/argent@latest init -y` (or `npm i -g @swmansion/argent@latest && argent init -y`).
36
- > </availability_check>
37
-
38
- <tapping_rule>
39
- <important>**Never** derive tap coordinates from screenshot pixels</important>
40
- Interaction tools (`gesture-tap`, `gesture-swipe`, `keyboard`, `button`, `launch-app`, `open-url`, `run-sequence`, `await-ui-element`, …) return the screen **after** the action: a screenshot AND the accessibility element tree (`--- Elements after action (describe) ---`, the same format `describe` prints, with normalized 0–1 frames). Take tap coordinates from that tree: the centre of the element's frame (`x + width/2`, `y + height/2`). You do not need a separate discovery call before a tap when the last result already lists the target.
41
-
42
- Call a discovery tool yourself only when you have no fresh tree for the current screen: before the first action on a screen you have not touched yet, after waiting for something to load without `await-ui-element`, or when the last tree did not list your target. Preferred tools are, in order:
43
-
44
- - `describe` - native app-level components and safely targetable foreground apps (iOS and Android).
45
- - `native-describe-screen` - accessibility screen description via injected native devtools (iOS only)
46
- - `debugger-component-tree` - react-native specific components
47
-
48
- `native-user-interactable-view-at-point` / `native-view-at-point` are follow-up diagnostics once you already have a candidate point (iOS only).
49
-
50
- If a **tap fails twice** at the same coordinates, **stop retrying** and re-run a discovery tool.
51
-
52
- If `describe` fails, **read the exact error before reacting**, follow the recovery guidance in `argent-device-interact` to choose the correct next action.
53
-
54
- Before starting to interact with the app, read the `argent-device-interact` skill first.
55
- </tapping_rule>
56
-
57
- <device_selection_rule>
58
- Before booting, running, or interacting with any app, call `list-devices` first - prefer running devices.
59
-
60
- Decision order:
61
-
62
- 1. **Explicit user intent** - choose the user named platform or device. Look for words "simulator" and "emulator".
63
- 2. **Prefer a running device.** iOS simulators - state `Booted` and Android devices - `state: "device"` come first in `list-devices`; Chromium (CDP) apps appear as `platform: "chromium"`, `state: "Running"`. A cabled physical iPhone (`platform: "ios"`, `kind: "device"`, `state: "connected"`) is listed first too, but it is not a running simulator: never pick it because it is there. Use it only when the user names the phone, a physical or real device, or hardware testing. With nothing else booted, boot a simulator or ask which target the user means.
64
- 3. **Single-platform project:** (per `argent-environment-inspector` flags `is_native_ios`/`is_native_android`, or RN with only one platform configured) → boot that platform.
65
- </device_selection_rule>
66
-
67
- <skill_reading_rule>
68
- <important>Always read relevant skills for guidance before executing argent-mcp tool - read skill_routing reference</important>
69
- </skill_reading_rule>
70
-
71
- <general_rules>
72
-
73
- - All simulator/emulator interactions go through argent MCP tools; never use `xcrun simctl`,
74
- raw `curl` to simulator ports, or the simulator-server binary directly.
75
- - Before calling any gesture tool for the first time, use ToolSearch to load its schema.
76
- - Interaction tools (`gesture-tap`, `gesture-swipe`, `gesture-pinch`, `gesture-rotate`, `gesture-custom`, `launch-app`, etc.) return a screenshot and the element tree automatically.
77
- Call `screenshot` or `describe` separately only for a baseline before any action or after a delay.
78
- - Always open apps with `launch-app` or `open-url`; never tap home screen icons.
79
- - If a task can require a saved e2e test, choose `argent-create-e2e` or `argent-qa-e2e` before the first launch or in-app action. Start the recorder before walking the path; recording is not retroactive.
80
- - Always use `run-sequence` when performing multiple sequential device actions where you don't need to observe the screen between steps. More in `argent-device-interact` skill.
81
- - Do not stop simulator servers when a task finishes: the next task reuses them, and stopping them makes its
82
- first device action start cold again. Call `stop-all-simulator-servers` when the user asks to clean up or
83
- ends the session, or when a skill tells you to recycle a device's services (e.g. before a QA proof pass).
84
- Always pass `devices: [...]` naming the devices this session used. One tool-server is shared by every other
85
- agent using this argent install, so an unscoped call tears down their devices too; reserve that form for a
86
- deliberate machine-wide cleanup.
87
- Never stop a Metro the user started unless they ask (`stop-metro`, specify the port if not 8081).
88
- - If tools provided by mcp-server are not sufficient and action can be done using `xcrun`, `adb`, or other commands, use the command. Examples: changing device options, performing a device action such as lock, shake, etc. Not on a physical iPhone.
89
- - When waiting for an action, do not call `screenshot` repeatedly without a proper wait mechanism. Use the `await-ui-element` tool to block until the UI settles (e.g. wait for an element to become `visible`/`hidden`, or to contain expected `text`) instead of polling.
90
- </general_rules>
91
-
92
- <react_native_detection>
93
- Project type is determined by the `argent-environment-inspector` subagent (see `subagents` section).
94
- When the subagent result is available, use its `is_react_native` field as the authoritative
95
- source; do not re-inspect files manually.
96
-
97
- If the subagent has not run yet and project type is unknown, run it first before proceeding. Always use subagents if available to run `gather-workspace-data` data tool, if possible do not run yourself.
98
-
99
- When `is_react_native` is true: load `argent-react-native-app-workflow` skill. Use `debugger-component-tree` for element discovery - if the responses are large or unhelpful, try `describe`.
100
- </react_native_detection>
101
-
102
- <skill_routing>
103
- Load the matching skill before starting work and executing tools from argent-mcp: skills contain the full step-by-step
104
- procedure and edge-case handling for each workflow.
105
-
106
- PLATFORM DETECTION
107
- If the user did not specify a platform, call `list-devices` first and pick the booted target; do not default to iOS. Vega (Amazon Fire TV) devices appear as `platform:"vega"`, when present load `argent-tv-interact`
108
-
109
- iOS SIMULATOR SETUP
110
- Skill: `argent-ios-simulator-setup`
111
- When: Beginning a task that involves the iOS simulator, no simulator booted yet, need UDID or simulator-server.
112
-
113
- ANDROID EMULATOR SETUP
114
- Skill: `argent-android-emulator-setup`
115
- When: Beginning a task that involves the Android emulator, no emulator running yet, need an adb serial, or about to install an APK.
116
-
117
- PHYSICAL iPHONE (USB)
118
- Skills: `argent-ios-device-setup` (cable, trust, signing), then `argent-ios-device-interact` (the app-scoped interaction contract)
119
- When: The user names a physical iPhone, a real device, or hardware, or the target `list-devices` iOS entry has kind `"device"`. Never for a simulator, and never because a cabled phone is listed first. On hardware every interaction starts with `launch-app`; `paste`, `settings-permissions`, `rotate`, `shake`, screen recording, `debugger-*`, `react-profiler-*`, `native-profiler-*` and `native-*` do not exist there.
120
- Prompt keywords: physical iPhone, real device, on my phone, USB, hardware
121
-
122
- TAPPING, SWIPING, TYPING, GESTURES, SCREENSHOTS, SCROLLING
123
- Skill: `argent-device-interact`
124
- When: Performing touch interactions, typing, pressing hardware buttons, launching/restarting apps, opening URLs, rotating or folding the device, taking standalone screenshots, or verifying a visible UI code change. Covers phone/tablet iOS and Android simulators and emulators plus Chromium (CDP) apps: for any TV target use the TV skill below, and for a physical iPhone use the entry above.
125
-
126
- APP PERMISSIONS (GRANT / DENY / RESET WITHOUT THE SETTINGS UI)
127
- Skill: `argent-settings-permissions`
128
- When: You must change an app runtime permission (camera, microphone, photos, contacts, notifications, calendar, location, location-always, media-library, motion, reminders) that the app itself can't flip: pre-authorize or deny it before the app asks, re-enable one the user already denied (iOS never re-prompts), or reset it so the first-run dialog reappears. Works on the iOS simulator and Android emulator/device. Do NOT use it when the app has an in-app toggle or is showing its own permission dialog; tap that instead (see `argent-device-interact`); nor for permissions/settings outside that list.
129
- Prompt keywords: permission, grant, deny, revoke, reset permission, privacy, camera access, location access, TCC
130
-
131
- TV INTERACTION (APPLE TV / ANDROID TV / FIRE TV)
132
- Skill: `argent-tv-interact`
133
- When: Any TV target: a `list-devices` entry with `runtimeKind: "tv"` (Apple TV simulator or Android TV emulator) or `platform:"vega"` / `kind:"vvd"` (Amazon Fire TV / VVD), or the user mentions Apple TV / tvOS / Android TV / leanback / Vega / Fire TV. A TV UI is focus-driven, not touch-driven: drive it with `describe` (read focus) + `tv-remote` (D-pad presses) + `keyboard` (type); `gesture-*` tools do NOT apply. Covers booting the target, app lifecycle, focus navigation, typing, screenshots, and (Vega) VVD lifecycle + Fast Refresh + JS-runtime debugging (evaluate, console logs, network inspector).
134
- Prompt keywords: apple tv, tvos, android tv, leanback, vega, fire tv, vvd, d-pad
135
- Saved artifacts: on Vega, a replayable path is `argent-create-e2e` and an acceptance-criteria regression test is `argent-qa-e2e`; both record D-pad navigation as `tool: tv-remote` steps. Apple TV and Android TV have no e2e support; report that limitation.
136
-
137
- SCREENSHOT DIFF & VISUAL REGRESSION
138
- Skill: `argent-screenshot-diff`
139
- When: Explicit visual regression, screenshot diff, compare screenshots, before/after visual comparison requests, or visible UI changes where stable pixel comparison would add useful evidence.
140
-
141
- SCREEN RECORDING (VIDEO CAPTURE)
142
- Skill: `argent-screen-recording`
143
- When: The user wants an mp4 of an interaction, animation, or bug reproduction. Use `argent-create-e2e` instead for a replayable sequence.
144
- Prompt keywords: record, recording, screen recording, video, capture video, clip, mp4
145
-
146
- RUNNING / BUILDING / DEBUGGING REACT NATIVE APP
147
- Skill: `argent-react-native-app-workflow`
148
- When: Project is react-native, starting Metro or running the iOS or Android app, build failures, pod issues, lost Metro connection, reading logs, reloading JS bundle, reinstalling app.
149
-
150
- JS EVALUATION, METRO CONNECTION, REACT NATIVE
151
- Skill: `argent-metro-debugger`
152
- When: evaluating expressions, inspecting React component tree at source level, finding element placement via `debugger-component-tree`.
153
-
154
- REACT APP & COMPONENT PROFILING
155
- Use skill: `argent-react-native-profiler`
156
- When: To measure performance of specific components, to find app-wide bottlenecks. Investigating re-renders or CPU hotspots, producing ranked performance reports.
157
-
158
- NATIVE PROFILING
159
- Use skill: `argent-native-profiler`
160
- When: Profiling native performance (CPU hotspots, UI hangs, memory leaks). iOS only today; Android on the roadmap. Useful as a reference for platform-specific investigation when running dual profiling via `argent-react-native-profiler`.
161
-
162
- PERFORMANCE OPTIMIZATION
163
- Use skill: `argent-react-native-optimization`
164
- When: App feels slow, user asks to optimize, reducing bundle size, improving startup time, fixing re-renders, optimizing lists/images/navigation, or any performance-related task. This is the entry-point skill for all performance work; it delegates to `argent-react-native-profiler` for measurement.
165
-
166
- INTERACTIVE UI TESTING (ONE-OFF, NOT SAVED)
167
- Skill: `argent-test-ui-flow`
168
- When: Running a one-off interact → screenshot → verify check with no saved regression artifact.
169
-
170
- RECORDING & REPLAYING E2E TESTS
171
- Use skill: `argent-create-e2e`
172
- When: Saving or replaying a repeatable path for profiling, A/B comparison, retry, or reuse. For acceptance-driven regression tests, use `argent-qa-e2e`.
173
- Prompt keywords: record e2e, replay e2e, run e2e, flow, repeat, test X times
174
-
175
- GENERATED QA REGRESSION TESTS
176
- Use skill: `argent-qa-e2e`
177
- When: Saving a test case, ticket, or acceptance criteria as a repeatable regression test. Requires stable evidence and two unchanged full passes. iOS, Android, Chromium, and Vega (D-pad navigation records as `tool: tv-remote` steps); not Apple TV or Android TV.
178
- Prompt keywords: QA test, regression test, test case, automate an e2e test, write an e2e test, generate a test
179
- Routing: one-off check → `argent-test-ui-flow`; saved path → `argent-create-e2e`; saved acceptance test → `argent-qa-e2e`.
180
-
181
- PROPOSING DESIGN VARIANTS FOR HUMAN SELECTION
182
- Use skill: `argent-lens`
183
- When: The user asks for design alternatives / options / A-B choices for a screen or component, or you have produced more than one candidate look for an element and want a human to pick before committing. Covers the build → navigate → screenshot → propose_variant loop and the single blocking await_user_selection call. (Gated behind the `argent-lens` flag, off by default; run `argent enable argent-lens` first.)
184
- Prompt keywords: variant, design option, alternative, A/B, "let me pick", "show me options"
185
- </skill_routing>
186
33
 
187
- <subagents>
188
- ENVIRONMENT INSPECTION AT SESSION START
189
- Use subagent: `argent-environment-inspector`
190
- When:
191
- - Environment context of the project is not yet known
192
- - No "Project Environment" section exists in project memory / `MEMORY.md` or you lack information about basic setup workflows
193
- - Need to determine build commands, startup scripts, metro port, platform support, or QA tooling
194
- If the subagent already ran this session (result in memory), use that context directly; do NOT re-run.
195
- Rules:
196
- - Run the `argent-environment-inspector` subagent if possible. Never call `gather-workspace-data` yourself - do only if subagent is not available.
197
- - The main agent is responsible for persisting the subagent's JSON result to project memory
198
- </subagents>
34
+ </availability_check>
@@ -5,26 +5,18 @@ description: Set up and connect to an Android emulator using argent MCP tools. U
5
5
 
6
6
  ## 1. Prerequisites
7
7
 
8
- - **Android SDK Platform Tools** on PATH: provides `adb`.
9
- - **Android Emulator** on PATH: needed to boot AVDs. If you will only use an already-running emulator or a physical device, adb alone is sufficient.
10
- - An AVD created via Android Studio or `avdmanager create avd`.
11
-
12
- Verify with `adb version` and `emulator -list-avds`.
8
+ The Android SDK (platform tools and emulator) and an AVD, created in Android Studio or with `avdmanager create avd`. If `list-devices` returns no Android devices and no `avds`, either no AVD exists or Argent can't find the SDK. Then run `argent config set android.sdkRoot <sdk-path>` and call `list-devices` again after a minute: a failed SDK lookup is cached that long. Exporting `ANDROID_HOME` in your shell doesn't reach the tool-server that is already running.
13
9
 
14
10
  ## 2. Setup
15
11
 
16
- 1. **Find a ready device**: call `list-devices`. Filter for entries with `platform: "android"`. Ready devices (`state: "device"`) come first. Pick the first `serial` (e.g. `emulator-5554`) unless the user specified one. If the result has a `hint` about the adb server, prefix every `adb` command that you run yourself, as the hint shows.
17
- 2. **Boot if needed**: if nothing Android is ready, call `boot-device` with `avdName: <name>` from the same call's `avds` list. The tool transparently picks hot vs cold boot: it probes the AVD's `default_boot` snapshot, restores it under a tight deadline when usable, and falls back to a full cold boot otherwise. Hot path is typically ~30s; cold path takes 2–10 min. On any stage failure the tool kills the emulator process it started so your next call starts from a clean state.
18
- 3. **Metro (for React Native)**: once a device is up, run `adb -s <serial> reverse tcp:8081 tcp:8081` so the device can reach Metro on your host. Repeat if the device restarts.
12
+ 1. **Find a ready device**: call `list-devices`. Filter for entries with `platform: "android"`. Ready devices (`state: "device"`) come first. If the user named a device, use it. Otherwise pick the first `kind: "emulator"` that fits the task. Take a physical phone (`kind: "device"`) only when the user asks for one. If the result has a `hint` about the adb server, prefix every `adb` command that you run yourself, as the hint shows.
13
+ 2. **Boot if needed**: if no such emulator is ready, call `boot-device` with `avdName: <name>` from the same call's `avds` list. `avds` doesn't mark TV images: for a TV task, pick the AVD by its name.
19
14
 
20
15
  ## 3. Using the device
21
16
 
22
- Pass the Android serial as `udid` to the unified interaction tools: `gesture-tap`, `gesture-swipe`, `describe`, `screenshot`, `launch-app`, `keyboard`, etc. Dispatch is automatic based on the id shape. See `argent-device-interact` for platform-neutral interaction tooling and the Android-specific gotchas section at the bottom of that skill.
17
+ Pass the Android serial as `udid` to the same interaction tools as on iOS. See `argent-device-interact` for interaction tooling and the Android notes at the bottom of that skill. If a React Native app can't reach Metro, see `argent-metro-debugger` §1.
23
18
 
24
19
  ## 4. Notes
25
20
 
26
- - **Android TV / leanback AVDs** boot through this exact flow (same `boot-device` + `avdName`), but they are **focus-driven, not touch-driven**; do not use `gesture-tap`/`gesture-swipe` on them. `list-devices` tags a leanback device with `runtimeKind: "tv"` (detected via the system feature list, not the serial: a TV AVD's serial looks just like a phone's). When you see `runtimeKind: "tv"`, drive it with the focus-driven tools (`describe` / `tv-remote` / `keyboard`) and the `argent-tv-interact` skill (it covers Android TV as well as Apple TV, including the full TV setup flow).
27
- - Serials are the adb device id. iOS UDIDs and Android serials are not interchangeable, but you do NOT need to tell the tools which platform: dispatch is automatic.
28
- - `describe` on Android returns a shallower tree than iOS (no accessibility-service equivalent), but covers most tap-target discovery.
29
- - `reinstall-app` on Android always installs with `-g` so first-launch runtime permissions are pre-granted.
21
+ - **Android TV / leanback AVDs** boot through this exact flow, but `list-devices` tags them `runtimeKind: "tv"` and they are focus-driven: use the `argent-tv-interact` skill, not the gesture tools.
30
22
  - To stop the emulator, run `adb -s <serial> emu kill` from a shell (clean shutdown). Never `pkill -9`/`kill -9` qemu: a hard kill leaves the userdata image dirty, after which cold boots can hang for many minutes doing recovery (runaway writes, `boot_completed` never flips). If an image gets into that state, boot once with `-wipe-data` to reset it.
@@ -13,7 +13,7 @@ For a saved QA test case, ticket, or acceptance criterion, load `argent-qa-e2e`
13
13
 
14
14
  - Before creating or changing an e2e test, read [Live authoring](references/live-authoring.md) completely.
15
15
  - When polishing, composing, or manually reviewing YAML, read [E2E YAML](references/e2e-yaml.md). For Vega, read its platform limits before recording remote or keyboard tools.
16
- - E2E tests run on physical iPhones (an iOS `list-devices` entry with kind `"device"`), but replay never auto-binds one, even when no simulator is booted: pass the phone's udid as `device` (CLI `--device`), and only a `connected` phone can run. `pinch`/`rotate` steps run there as two-finger gestures, in apps drawn in portrait. On hardware the runner tree is the `describe` tree: same ids and roles, no UIView hierarchy. See `argent-ios-device-interact` for the hardware contract.
16
+ - E2E tests run on physical iPhones (an iOS `list-devices` entry with kind `"device"`), but replay never auto-binds one, even when no simulator is booted: pass the phone's udid as `device` (CLI `--device`), and only a `connected` phone can run. `pinch`/`rotate` steps need the app drawn in portrait. On hardware the runner tree is the `describe` tree: same ids and roles, no UIView hierarchy. See `argent-ios-device-interact` for the hardware contract.
17
17
  - On capture warnings, raw coordinates, unavailable trees, mistimed transitions, overlays, or replay failures, read [Reliability and recovery](references/reliability-and-recovery.md).
18
18
 
19
19
  ## Non-negotiable rules
@@ -67,22 +67,22 @@ YAML selectors and live discovery use different screen projections:
67
67
 
68
68
  | Platform | Runner tree | `describe` / `await-ui-element` | Important difference |
69
69
  | -------- | --------------------------------------------------------- | ------------------------------- | ------------------------------------------------------ |
70
- | iOS | projected UIView hierarchy | accessibility tree | `native-full-hierarchy` is raw; nodes and roles differ |
70
+ | iOS sim | projected UIView hierarchy | accessibility tree | `native-full-hierarchy` is raw; nodes and roles differ |
71
71
  | Android | full accessibility hierarchy | trimmed interactables | Discovery can omit testID containers or merge nodes |
72
72
  | Chromium | filtered DOM nodes with id, label, value, click, or focus | shorter DOM walk | Projections and node limits differ (12,000 vs. 5,000) |
73
73
  | Vega | toolkit page source | same source | Same elements, different shape |
74
74
 
75
- On iOS, Android, and Chromium, an id absent from `describe` can still resolve in an e2e test. Verify it in a scratch fragment. Chromium exposes password fields to the runner as `[password]`; select them by id or role.
75
+ On an iOS simulator, Android, and Chromium, an id absent from `describe` can still resolve in an e2e test. Verify it in a scratch fragment. Chromium exposes password fields to the runner as `[password]`; select them by id or role.
76
76
 
77
- The recorder rechecks each successful `await-ui-element` against the runner tree. Follow any `message` warning and replay each conversion. On Vega, a mismatch usually means the screen changed. A `text` check can also select different elements from the same source. See [Live waits and checks](live-authoring.md#live-waits-and-checks).
77
+ For the recorder's cross-tree warning on a recorded wait, see [Live waits and checks](live-authoring.md#live-waits-and-checks). On Vega both read the same source, so a mismatch usually means the screen changed or a `text` check selected a different element.
78
78
 
79
- **On iOS, a `launch:` step also decides which app the runner reads.** A successful `launch:` pins later runner-tree reads to that app, so a read probes only that app instead of fanning out over every connected one to find the frontmost. A pinned read still refuses, naming the reason, when the app has no foreground presence left, when it stops answering after an earlier read got through, when its devtools connection dropped, or when the pinned id is a `com.apple.*` system app.
79
+ **On an iOS simulator, a `launch:` step also decides which app the runner reads.** A successful `launch:` pins later runner-tree reads to that app, so a read probes only that app instead of fanning out over every connected one to find the frontmost. A pinned read still refuses, naming the reason, when the app has no foreground presence left, when it stops answering after an earlier read got through, when its devtools connection dropped, or when the pinned id is a `com.apple.*` system app.
80
80
 
81
81
  Any raw `tool:` step ends the pin, because its effect on the screen is opaque to the runner, and reads auto-detect the frontmost app again until the next `launch:` re-pins. A tool that cannot change the foreground app leaves the launched id as an unpinned fallback, which takes the read only when auto-detection times out and the launched app vouches for itself with a probe of its own. `launch-app`, `restart-app`, `reinstall-app`, `open-url`, and `button` drop even that; `launch-app` and `restart-app` replace it with the app they just started, still unpinned. Nested `run:` fragments inherit both the pin and its clearing.
82
82
 
83
- So on iOS recording and replay can read different apps, not only different projections: recording has no run state and always auto-detects the frontmost connected app, while a replay read between a `launch:` and the next raw `tool:` step reads the launched app.
83
+ So on an iOS simulator, recording and replay can read different apps, not only different projections: recording has no run state and always auto-detects the frontmost connected app, while a replay read between a `launch:` and the next raw `tool:` step reads the launched app.
84
84
 
85
- **On iOS, never copy a `role` from `describe` into a YAML selector.** The runner derives iOS roles from the UIView class name and `describe` from accessibility traits, so a React Native `Pressable` (class `RCTView`) is `AXGroup` to the runner and `AXButton` to `describe`. Select on `id`/`text`, or confirm the role against the runner's own tree.
85
+ **On an iOS simulator, never copy a `role` from `describe` into a YAML selector.** The runner derives iOS roles from the UIView class name and `describe` from accessibility traits, so a React Native `Pressable` (class `RCTView`) is `AXGroup` to the runner and `AXButton` to `describe`. Select on `id`/`text`, or confirm the role against the runner's own tree.
86
86
 
87
87
  When several nodes match, the directive decides:
88
88
 
@@ -118,7 +118,7 @@ Directives stop the test on failure and skip later steps. The available directiv
118
118
  - iOS: unfolded, the UI is landscape. `swipe` and `scroll-to` directions and the reading order stay as the user sees the UI. Coordinates stay in the space of the `describe` frames.
119
119
  - iOS: a fold between two angles that are not `closed` or `open` can keep the current panel. The step passes, and the report names the panel. To change panels, fold to `closed` or `open`.
120
120
 
121
- Use the launch map for cross-platform tests. A bare launch applies everywhere and becomes an app path on Chromium. The map takes `native:`, `ios:`, `android:`, `vega:`, and `chromium:`. `native:` is one id shared by iOS, Android, and Vega, and a per-platform key overrides it for that platform. `chromium:` accepts a relative or absolute app path. `ios:` also accepts `{ app, args }`; a simulator passes `args` to the app at launch. A launch that declares no id for the run's platform is an error, not a cue to switch platforms. A run on a remote simulator uses the `ios:` id, or the `native:` id when the map has no `ios:` key, so no test needs a key for a remote run. On iOS, a successful launch also pins later tree reads to that app until the next raw `tool:` step, so read [The runner tree is not the discovery tree](#the-runner-tree-is-not-the-discovery-tree) when a read describes the wrong screen.
121
+ Use the launch map for cross-platform tests. A bare launch applies everywhere and becomes an app path on Chromium. The map takes `native:`, `ios:`, `android:`, `vega:`, and `chromium:`. `native:` is one id shared by iOS, Android, and Vega, and a per-platform key overrides it for that platform. `chromium:` accepts a relative or absolute app path. `ios:` also accepts `{ app, args }`; Argent passes `args` to the app at launch. A launch that declares no id for the run's platform is an error, not a cue to switch platforms. A run on a remote simulator uses the `ios:` id, or the `native:` id when the map has no `ios:` key, so no test needs a key for a remote run. On an iOS simulator, a successful launch also pins later tree reads to that app until the next raw `tool:` step, so read [The runner tree is not the discovery tree](#the-runner-tree-is-not-the-discovery-tree) when a read describes the wrong screen.
122
122
 
123
123
  ```yaml
124
124
  - launch: { native: com.acme.app, chromium: ../../app }
@@ -156,9 +156,9 @@ Only the direction presets carry OS-edge margins. A resolved `from` point is use
156
156
 
157
157
  On Chromium a swipe is a mouse drag (`gesture-drag`), so a `from` on an `<img>`, an `<a href>` or a `draggable="true"` node starts the browser's native drag-and-drop: the page gets `pointerdown` then `pointercancel` and sees no travel. On Vega, `swipe` fails upfront like the other touch directives.
158
158
 
159
- `type` presses Enter in a second `keyboard` call unless `submit: false`. A polished focus tap plus one text-only `keyboard` call usually needs `submit: false`. Store external values as `{{secret:NAME}}`. The runner uses the first source that defines the name: environment `ARGENT_SECRET_NAME`; project `.argent/secrets.env`; project `.env.local`, then `.env`; then `~/.argent/secrets.env`. Over a link with `forward-secrets` on, the same sources on the client's machine come first. The two `secrets.env` files accept the bare `NAME`, but the shared dotenv files expose only `ARGENT_SECRET_`-prefixed keys, so a bare `NAME=…` in `.env` or `.env.local` stays unresolved. The runner redacts every resolved value, so do not use a placeholder for content a report must show.
159
+ `type` presses Enter in a second `keyboard` call unless `submit: false`. A polished focus tap plus one text-only `keyboard` call usually needs `submit: false`. Store external values as `{{secret:NAME}}`; the runner resolves them from the same sources as the `keyboard` tool. The runner redacts every resolved value, so do not use a placeholder for content a report must show.
160
160
 
161
- A **selector-less gesture** (a coordinate `tap`/`long-press`/`swipe`, or a `pinch`/`rotate` with no `on:`) resolves no frame, so a tree source it cannot read does not fail it. It settles best effort, dispatches anyway, and the step **passes carrying a warning** that quotes the source's own error. That green says the gesture was sent, not that it landed: one aimed at a moving element can miss it entirely. Restore the tree source, usually by relaunching the app so the instrumentation loads. Accept the warning only where the app serves no tree at all, and put an explicit `wait:` before a gesture that follows a transition. The first such gesture proves the outage and later ones spend that verdict without paying the settle window again. A tree read that comes back, or a relaunch, retires that verdict, which only makes the next gesture pay a fresh window, and it warns again if the source is still down.
161
+ A **selector-less gesture** (a coordinate `tap`/`long-press`/`swipe`, or a `pinch`/`rotate` with no `on:`) resolves no frame, so a tree source it cannot read does not fail it. It settles best effort, dispatches anyway, and the step **passes carrying a warning** that quotes the source's own error. That green says the gesture was sent, not that it landed: one aimed at a moving element can miss it entirely. Restore the tree source, usually by relaunching the app so the instrumentation loads. Accept the warning only where the app serves no tree at all, and put an explicit `wait:` before a gesture that follows a transition: after the first such gesture, later ones skip the settle window until a tree read succeeds again or the app relaunches.
162
162
 
163
163
  ## Verification conditions
164
164
 
@@ -209,7 +209,7 @@ It **never fails a run.** Every outcome short of a clean settle passes with a wa
209
209
  - **a small part of it was still changing**: a spinner, caret, or progress dot moved through the hold. Too small to count as the screen moving, so the settle completed anyway.
210
210
  - **the screen was still for the last Nms**: the wait ran out mid-hold, so no settle was confirmed. It names the term that was short: a second agreeing interval, or the rest of `stableFor`. Raise this step's `timeout:`, because the wait was too short rather than the screen too busy.
211
211
  - **the tree stayed empty**: the screen rendered no accessible content: a canvas or video surface, or a screen that never arrived.
212
- - **settled on the UI tree alone**: no screenshot pair could be read, so presentation-layer animation was never waited out.
212
+ - **settled on the UI tree alone**: no screenshot pair could be read, so presentation-layer animation was never waited out. Inspect the capture path rather than the app's rendering.
213
213
  - **too few reads**: a settle needs three reads across two intervals and this step got fewer, so it ended with no evidence either way.
214
214
 
215
215
  Only a tree source this step could not read stops the run, as an errored step: one still failing when the wait ends, one that wedges after answering, one that answers with an empty tree it flags as degraded (an unattached Vega toolkit, an AX service asking to be relaunched), or one that never answers (raise `timeout` before suspecting the app). The run is then not ok and every later step is skipped. A single failed read is not that: the hold restarts from the next good read. The same outage stops no [selector-less gesture](#directives), which needs no frame and passes with its own warning instead.
@@ -241,8 +241,6 @@ A `run:` target is a YAML path resolved against the directory of the test file c
241
241
 
242
242
  ## Local scripts
243
243
 
244
- Use a local `.mjs` script only when the user requests one. Record it with `e2e-add-script` at the point where it must run.
245
-
246
244
  ```yaml
247
245
  - script: { path: ../../scripts/seed-order.mjs }
248
246
  - script: { path: ../../scripts/seed-order.mjs, timeout: 60000 }
@@ -250,13 +248,10 @@ Use a local `.mjs` script only when the user requests one. Record it with `e2e-a
250
248
 
251
249
  Use the map form shown above. A bare `script: scripts/seed.mjs` is invalid.
252
250
 
253
- - **`path`** is relative to the test file that contains the step. Include `.mjs` and match the file name's letter case.
254
- - **`timeout`** is optional and uses milliseconds. The default is 30000. The minimum is 100.
251
+ `path` is relative to the test file that contains the step. Include `.mjs` and match the file name's letter case. `timeout` is in milliseconds, as in `e2e-add-script`.
255
252
 
256
253
  Over a link (`argent link` or `ARGENT_TOOLS_URL`, also to 127.0.0.1), `e2e-add-script` refuses the call, and a replay rejects a test with a `script:` step. Record and replay a test with a script without a link.
257
254
 
258
- If a script fails, check its changes before you retry.
259
-
260
255
  ## Snapshots and CLI runs
261
256
 
262
257
  `argent e2e run <name> [--device <id>] [--platform ios|android|chromium|vega|ios-remote] [--update-baselines] [--output <dir>] [--json]` runs without an LLM and exits non-zero on failure.
@@ -267,7 +262,7 @@ Do not use a snapshot as the only proof of navigation, persistence, data, access
267
262
 
268
263
  Baselines live beside the test, under `.argent/e2e/__baselines__/<name>/` and are keyed by platform and full-capture geometry; `cropOn` also contributes its selector. A run on a remote simulator uses `ios` in the key, so it uses the same baseline as a local iOS run with the same capture geometry. Seed from a known-good state with `--update-baselines`. A test that a `tool: e2e-execute` step runs keeps its own baselines, and `--update-baselines` updates them too unless the step sets `updateBaselines` itself. A run on a remote simulator with `--update-baselines` rewrites the same baseline file that a local run uses, and its step reason says that a remote simulator wrote it. Inspect every baseline and require user review. Do not commit it yourself. Baseline creation or update is not a test pass. Never update a baseline only to make a diff pass. The default `maxMismatch` is 0.5 percent.
269
264
 
270
- Pin `--platform` and `--device` for iOS, Android, or Vega. For Chromium the device class is the window's own pixel size, which the app sets and no launch argument changes: pass `--platform chromium` and omit `--device` so the runner boots the declared app path instead of attaching to a running window of another size. A window sized from host or session state produces a key CI cannot reproduce, and the step fails for a missing baseline. The runner pins mobile status bars during visual runs. `--output <dir>` writes failed baseline, current, and diff images under `<dir>/<name>/` for CI artifact upload.
265
+ Pin `--platform` and `--device` for iOS, Android, or Vega. For Chromium the device class is the window's own pixel size, which the app sets and no launch argument changes: pass `--platform chromium` and omit `--device` so the runner boots the declared app path instead of attaching to a running window of another size. A window sized from host or session state produces a key CI cannot reproduce, and the step fails for a missing baseline. The runner pins mobile status bars during visual runs. `--output <dir>` writes failed snapshots' images and failed steps' screenshots under `<dir>/<name>/` for CI artifact upload.
271
266
 
272
267
  ## YAML safety
273
268