Skip to content

Commit 5d94c63

Browse files
committed
Merge remote-tracking branch 'upstream/main' into jakubstec/domains/security-groups-add-search
2 parents 1f4f725 + cab0b7b commit 5d94c63

471 files changed

Lines changed: 8437 additions & 3947 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,98 @@
11
---
22
name: agent-device
33
description: Drive iOS and Android devices for the Expensify App - testing, debugging, performance profiling, bug reproduction, and feature verification. Use when the developer needs to interact with the mobile app on a device.
4-
allowed-tools: Bash(agent-device *) Bash(npm root *)
4+
allowed-tools: Bash(agent-device *) Bash(npm root *) Bash(scripts/is-hybrid-app.sh)
55
---
66

77
# agent-device
88

9-
## Pre-flight
9+
## Pre-flight (auto)
1010

11-
<!-- The line below compares the installed `agent-device --version` to the required minimum 0.13.0 -->
11+
These checks evaluate at skill load. If any line shows `FAIL`, stop and surface the fix before running any device command.
1212

13-
`agent-device` version check: !`R=0.13.0; V=$(agent-device --version 2>/dev/null); [ -n "$V" ] && [ "$(printf '%s\n%s\n' "$R" "$V" | sort -V | head -1)" = "$R" ] && echo "OK ($V)" || echo "FAIL (need v$R+, got: ${V:-not installed})"`
13+
`agent-device` version: !`R=0.13.0; V=$(agent-device --version 2>/dev/null); [ -n "$V" ] && [ "$(printf '%s\n%s\n' "$R" "$V" | sort -V | head -1)" = "$R" ] && echo "OK ($V)" || echo "FAIL (need v$R+, got: ${V:-not installed}). Fix: npm install -g agent-device@latest"`
1414

15-
> If the version check above shows `FAIL`, **STOP** and instruct the developer: `npm install -g agent-device@latest`.
15+
Bundled CLI skills dir: !`D="$(npm root -g)/agent-device/skills/agent-device"; test -s "$D/SKILL.md" && echo "OK ($D)" || echo "FAIL (missing $D/SKILL.md). Fix: npm install -g agent-device@latest"`
1616

17-
Canonical skill reference path (read these files directly for device automation guidance - bootstrap, exploration, verification, debugging): !`echo "$(npm root -g)/agent-device/skills/agent-device"`
17+
HybridApp mode: !`M=$(scripts/is-hybrid-app.sh 2>/dev/null | tail -1); [ "$M" = "true" ] && echo "OK (HybridApp)" || echo "FAIL (got: ${M:-unknown}). This skill only supports the HybridApp build - ensure the Mobile-Expensify submodule is present."`
1818

19-
## Dev prerequisites
19+
## Bring-up
2020

21-
Default assumption: dev build from this repo. Before `open <app>`, both must be true:
21+
Run this sequence the first time the user asks for device interaction in a session, before any `open` / `snapshot` / `replay`.
2222

23-
1. **Metro dev server** running: `npm run start` (background).
24-
2. **Dev build installed** on target: `npm run ios` or `npm run android` from the repo root.
23+
### 1. Platform
2524

26-
Skip these only when the developer explicitly targets a non-dev build (e.g., standalone/prod artifact, or a pre-installed release build).
25+
If the user prompt names `ios` or `android` explicitly, use it. Otherwise ask. Only iOS and Android are supported; reject other platforms.
26+
27+
### 2. Bundle ID
28+
29+
HybridApp dev builds only (the pre-flight gate enforces this).
30+
31+
| Platform | Bundle ID | Build script |
32+
| --------- | ------------------------------- | ----------------- |
33+
| `ios` | `com.expensify.expensifylite` | `npm run ios` |
34+
| `android` | `org.me.mobiexpensifyg.dev` | `npm run android` |
35+
36+
### 3. Confirm dev build is installed
37+
38+
```bash
39+
agent-device apps --user-installed --platform <p> --json
40+
```
41+
42+
If the resolved bundle ID is missing from the list, **STOP** and instruct the developer to run the matching build script from the table. HybridApp mobile builds **must** be initiated from `Mobile-Expensify/` (per project CLAUDE.md).
43+
44+
### 4. Metro
45+
46+
```bash
47+
agent-device metro prepare --public-base-url http://localhost:8081 --port 8081 --kind react-native
48+
```
49+
50+
If `metro prepare` fails, **STOP** and surface the error verbatim.
51+
52+
### 5. Pick a target device
53+
54+
```bash
55+
agent-device devices --platform <p> --json
56+
```
57+
58+
- Prefer the first device with `booted=true`.
59+
- If none are booted, choose the default target device (usually the first listed), then continue to step 6 to detect and clear any stale session bound to that device before opening.
60+
- If multiple are booted, ask the user which.
61+
62+
Capture the device name and (for iOS) the simulator UDID, or (for Android) the serial.
63+
64+
### 6. Session reuse vs reset
65+
66+
```bash
67+
agent-device session list --json
68+
```
69+
70+
For each entry whose `device_udid` (iOS) or `serial` (Android) matches the chosen device:
71+
72+
- If the session was created earlier in the **current** Claude invocation, reuse it silently.
73+
- Otherwise prompt: `reuse` (continue with the existing session) or `reset` (force-close it).
74+
- To reset: `agent-device close --shutdown --session <name>`. `--shutdown` also frees the simulator.
75+
76+
### 7. Open
77+
78+
```bash
79+
agent-device open <bundle-id> --platform <p> --device "<name>"
80+
```
81+
82+
If `open` errors with "app not installed", revisit step 3.
83+
84+
### 8. Sanity
85+
86+
```bash
87+
agent-device snapshot -i
88+
```
89+
90+
Confirm the app rendered. From here, follow the [Agent decision loop](flows/README.md) for repeatable flows or drive interactively.
91+
92+
### Canonical skill references
93+
94+
Read these files directly for device automation guidance (bootstrap, exploration, verification, debugging): !`echo "$(npm root -g)/agent-device/skills/agent-device"`
2795

2896
## Flows
2997

30-
Repeatable steps (sign-in, onboarding, etc.) are captured as composable `.ad` snippets under [`flows/`](flows/README.md). Before manually tapping through a screen, follow the **Agent decision loop** in [`flows/README.md`](flows/README.md) - it covers discovery, `@pre` filtering, replay, and `@post` verification.
98+
Repeatable steps (sign-in, onboarding, etc.) are captured as composable `.ad` snippets under [`flows/`](flows/README.md). For interactive usage, propose and run only `flows/macros/` helpers. `flows/tests/` belongs to a separate QA workflow and must not be proposed by this skill; QA/perf runs execute them via `agent-device test <path>`.
Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,34 @@
11
# Flows
22

3-
Composable `.ad` snippets - bounded units of work. A flow may span one or multiple screens as long as it represents a coherent, reusable action with clear start (`@pre`) and completion (`@post`) checkpoints. Each flow advertises machine-matchable metadata (`@pre`, `@post`, `@tag`) via `# @`-prefixed comment headers, so an agent can pick the right one from a snapshot.
3+
## Directory layout
44

5-
## Agent decision loop
5+
- `macros/` - reusable helpers for common setup/navigation actions that stop in a navigable state for further interactive work.
6+
- `tests/` - critical-scenario scripts for QA/perf verification that assert explicit outcomes (for example Sentry spans) and then stop.
7+
8+
Composable `.ad` snippets - bounded units of work. A flow may span one or multiple screens as long as it represents a coherent, reusable action with clear start (`@pre`) and completion (`@post`) checkpoints. Each flow advertises machine-matchable metadata (`@pre`, `@post`, `@tag`, `@param`) via `# @`-prefixed comment headers, while flow type is derived from location (`flows/macros/` or `flows/tests/`).
9+
10+
## Agent decision loop (interactive)
611

712
Before manually navigating, use this human-in-the-loop loop:
813

914
1. `agent-device snapshot -i` - see current state.
10-
2. `grep -H '^# @' .claude/skills/agent-device/flows/*.ad` - full catalog in one read.
15+
2. `grep -H '^# @' .claude/skills/agent-device/flows/macros/*.ad` - interactive catalog.
1116
3. For each candidate flow, run `agent-device is exists "<selector>"` per `@pre`. Keep flows where every `@pre` passes.
12-
4. Rank survivors by goal closeness (`@post` overlap with the requested destination when present) and present top candidates to the user with a short "why this flow" note.
17+
4. Rank survivors by goal closeness and present top macro candidates to the user with a short "why this flow" note:
18+
- Prefer flows whose `@post` selectors literally match destination language from the user request (same `text`, `label`, or selector phrase).
1319
5. Wait for user selection before replaying. **Auto-run is allowed only when there is exactly one survivor and it is an unambiguous match for an explicit user request.**
14-
6. `agent-device replay <path>`.
15-
7. If the flow declares `@post`, verify each `@post` with `is exists`. On success, re-enter the loop only if the user's stated goal is not complete; otherwise stop and report completion. On failure, propose peer flow/manual fallback options and ask before continuing. If no `@post` is declared (utility flow), rely on explicit user confirmation or the next snapshot before continuing.
20+
- Only propose flows from `flows/macros/` in interactive usage.
21+
6. Scan selected flow `# @param` headers. Ask the user for any missing parameter values, then build explicit CLI args (`-e KEY=VALUE`) for replay.
22+
7. `agent-device replay <path> -e KEY=VALUE ...`.
23+
8. If the flow declares `@post`, verify each `@post` with `is exists`. On success, re-enter the loop only if the user's stated goal is not complete; otherwise stop and report completion. On failure, propose peer flow/manual fallback options and ask before continuing. If no `@post` is declared (utility flow), rely on explicit user confirmation or the next snapshot before continuing.
24+
25+
## QA workflow (separate)
26+
27+
`flows/tests/` is reserved for dedicated QA automation and should not be offered to users as part of the interactive helper loop above. Run these flows with the dedicated test runner:
28+
29+
```bash
30+
agent-device test .claude/skills/agent-device/flows/tests/<name>.ad -e KEY=VALUE ...
31+
```
1632

1733
## Metadata header spec
1834

@@ -24,21 +40,22 @@ Each flow starts with `# @key value` comment lines. The `.ad` parser treats `#`
2440
| `@pre` | 1..N | Selector that must resolve in the current snapshot. Multiple lines are ANDed. |
2541
| `@post` | 0..N | Selector expected after replay. Multiple lines are ANDed. Used for chaining + success. |
2642
| `@tag` | 0..N | Free-form category (`auth`, `onboarding`, ...) or scoped (`sentry-<spanName>`). |
43+
| `@param` | 0..N | Runtime input contract: `@param KEY description.` Use with `${KEY}` in flow body. |
2744

2845
Selector syntax matches the body: `id="..."`, `role="..." label="..."`, `text="..."`, `||` for fallbacks.
2946

3047
## Parametrization (`agent-device` v0.13.0+)
3148

32-
Lift body literals to named variables via `env` + `${VAR}` interpolation so values can be overridden at runtime without editing the file.
49+
Declare runtime inputs via metadata (`@param`) and reference them in the body with `${VAR}` interpolation. Values are supplied by caller arguments (`-e`) or shell imports (`AD_VAR_*`) - never by in-file `env` directives.
3350

34-
| Construct | Where | Purpose |
35-
| ------------------ | -------------------- | -------------------------------------------------------------------------------- |
36-
| `env KEY=VALUE` | Header (after `# @`) | File-level default. Quote values with spaces or `||` chains: `env KEY="a || b"`. |
37-
| `${KEY}` | Body | Interpolation point. Resolves at replay time. |
38-
| `${KEY:-fallback}` | Body | Use `fallback` if `KEY` is unset. |
39-
| `\${KEY}` | Body | Literal `${KEY}` (escape). |
51+
| Construct | Where | Purpose |
52+
| ------------------ | ------------------------ | -------------------------------------------------------------------------------- |
53+
| `# @param KEY ...` | Metadata header comments | Declares expected input and documents meaning for the agent/user handoff. |
54+
| `${KEY}` | Body | Interpolation point. Resolves at replay time. |
55+
| `${KEY:-fallback}` | Body | Use `fallback` if `KEY` is unset. |
56+
| `\${KEY}` | Body | Literal `${KEY}` (escape). |
4057

41-
Resolution precedence (high to low): CLI `-e KEY=VALUE` (repeatable) > shell `AD_KEY=...` (auto-imported, prefix stripped) > file `env` > built-ins (`AD_PLATFORM`, `AD_SESSION`, `AD_FILENAME`, `AD_DEVICE`, `AD_ARTIFACTS`). Unresolved `${X}` errors with `file:line`.
58+
Resolution precedence (high to low): CLI `-e KEY=VALUE` (repeatable) > shell `AD_VAR_KEY=...` (auto-imported as `KEY`) > built-ins (`AD_PLATFORM`, `AD_SESSION`, `AD_FILENAME`, `AD_DEVICE`, `AD_ARTIFACTS`). Unresolved `${X}` errors with `file:line`.
4259

4360
Override at runtime without editing the file:
4461

@@ -52,30 +69,33 @@ agent-device replay <flow>.ad -e EMAIL=other@example.com
5269
- **No fixed `wait` calls.** `fill`/`press` resolve selectors with retry. Only add `wait <selector>` for real post-action blocks.
5370
- **Durable selectors.** Prefer `id=...` first, then `role=... label=...`, with `||` fallbacks. Avoid `@eN` refs.
5471
- **Every flow declares `@desc` and `@pre`.** Add `@post` for outcome-bearing flows; utility flows (for example `go-back`) may omit it. Add `@tag` when applicable.
72+
- **Choose directory intentionally.** Put reusable setup/navigation steps in `flows/macros/`; put outcome verification scenarios in `flows/tests/`.
5573
- **Keep scope coherent, not artificially tiny.** Flows can span multiple screens when that sequence is the reusable intent (for example "create and submit manual expense").
5674
- **Peers share `@pre` and differ on `@post`.** One flow per narrow outcome is better than a mega-flow with conditional branches.
57-
- **Use `env` for substituted values.** If a literal is interpolated into the body, declare a matching `env` default and reference it as `${VAR}`.
75+
- **Use `@param` for substituted values.** If a literal is interpolated into the body, declare `# @param KEY description.` and reference it as `${KEY}`.
76+
- **Do not use `env` directives in repo flows.** Runtime values must come from `-e KEY=VALUE` (preferred) or `AD_VAR_KEY=...`.
77+
- **Use inline defaults sparingly.** Optional tuning values can use `${KEY:-fallback}` in the body; required values should have no fallback and must be provided by caller input.
5878

5979
## Recording a new flow
6080

6181
1. Drive the target screen manually.
6282
2. Start a session with `--save-script`:
6383
```bash
64-
agent-device open <app> --save-script .claude/skills/agent-device/flows/<name>.ad
84+
agent-device open <app> --save-script .claude/skills/agent-device/flows/<kind>/<name>.ad
6585
```
6686
3. Perform the steps.
6787
4. `agent-device close` - flushes the `.ad`.
6888
5. Edit the generated file:
6989
- Delete the `context` line, leading `open ... --relaunch`, trailing `close`, and eyeballing `wait`s.
70-
- Add `@desc`, `@pre`, optional `@post`, and `@tag` headers.
90+
- Move file to `flows/macros/` or `flows/tests/`, then add `@desc`, `@pre`, optional `@post`, optional `@tag`, and any needed `@param` headers.
7191
6. Verify: pre-check from a matching state, replay, post-check.
7292

7393
## Maintenance
7494

7595
Heal selector drift in place:
7696

7797
```bash
78-
agent-device replay -u .claude/skills/agent-device/flows/<name>.ad
98+
agent-device replay -u .claude/skills/agent-device/flows/<kind>/<name>.ad
7999
```
80100

81-
Re-verify `@pre`/`@post` still hold, then commit. Note: `replay -u` is rejected when the script declares `env` directives (rewrite would drop them); strip the `env` block manually before healing, then re-add it.
101+
Re-verify `@pre`/`@post` still hold, then commit. Note: `replay -u` can rewrite interpolated lines to concrete selectors/values; review diffs and restore `${KEY}` placeholders where needed. Keep runtime inputs in `@param` + `-e`/`AD_VAR_*`; do not reintroduce in-file `env` directives.

.claude/skills/agent-device/flows/complete-onboarding.ad renamed to .claude/skills/agent-device/flows/macros/complete-onboarding.ad

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
# @post text="Home"
44
# @post role="button" label="Search"
55
# @tag onboarding
6-
env FIRST_NAME=Agent
7-
env LAST_NAME=Device
6+
# @param FIRST_NAME First name to enter on onboarding profile step.
7+
# @param LAST_NAME Last name to enter on onboarding profile step.
88

99
press "id=\"onboardingPrivateEmailSkipButton\" || role=\"button\" label=\"Skip\" || label=\"Skip\""
1010
press "role=\"button\" label=\"Something else\" || label=\"Something else\""
File renamed without changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# @desc Send a chat message from inside an already-open chat. Reusable helper for setting up state in other flows. Does not navigate or open a chat - assumes the composer is visible. For the QA scenario that exercises the ManualSendMessage Sentry span, see flows/tests/send-message.ad.
2+
# @pre label="Write something..." editable=true
3+
# @post label="Write something..." editable=true
4+
# @tag chat
5+
# @param MESSAGE Message text to send in the currently open chat.
6+
7+
is exists "label=\"Write something...\" editable=true"
8+
fill "label=\"Write something...\" editable=true" "${MESSAGE}"
9+
press "role=\"button\" label=\"Send\" || label=\"Send\""
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# @desc Sign in with the shared agent-device test account. Supports both new-account and returning-account outcomes. Caller MUST randomize EMAIL via `-e EMAIL=agent-device-testing+<9digits>@gmail.com` to avoid account flagging.
22
# @pre role="textfield" label="Phone or email"
33
# @pre role="button" label="Continue"
4-
# @post text="Welcome || Home"
5-
# @post role="button" label="Join || Search"
4+
# @post text="Welcome" || text="Home"
5+
# @post role="button" label="Join" || role="button" label="Search"
66
# @tag auth
7-
env EMAIL=agent-device-testing@gmail.com
7+
# @param EMAIL Login email. Use randomized alias format `agent-device-testing+<9digits>@gmail.com` to avoid account flagging.
88

99
fill "id=\"username\" || role=\"textfield\" label=\"Phone or email\" editable=true || label=\"Phone or email\" editable=true" "${EMAIL}"
1010
press "role=\"button\" label=\"Continue\" || label=\"Continue\""

.claude/skills/agent-device/flows/create-expense-manual.ad renamed to .claude/skills/agent-device/flows/tests/create-expense-manual.ad

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
# @tag sentry-ManualConfirmationListReady
1313
# @tag sentry-ManualConfirmationReceiptLoad
1414
# @tag sentry-ManualGeolocationWait
15-
env AMOUNT=22
16-
env CURRENCY=PLN
17-
env MERCHANT="Test Coffee"
15+
# @param AMOUNT Whole-number amount to type into the Manual amount input (for example `22`).
16+
# @param CURRENCY Currency symbol used by the submit CTA selector (for example `PLN` or `USD`).
17+
# @param MERCHANT Merchant name to populate before submit.
1818

1919
press "role=\"button\" label=\"Open actions menu\""
2020
press "role=\"button\" label=\"Create expense\" || label=\"Create expense\""

.claude/skills/agent-device/flows/open-create-expense.ad renamed to .claude/skills/agent-device/flows/tests/open-create-expense.ad

File renamed without changes.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# @desc From the Inbox tab, open a chat/report matching TARGET_CHAT in the LHN, with fallback to the first available chat row. Triggers the ManualOpenReport Sentry span (LHN row press -> report screen mounted with composer visible). Assumes the user is signed in with at least one chat in the Inbox.
22
# @pre text="Inbox"
3-
# @pre text="Navigates to a chat"
3+
# @pre role="button" label="Search"
44
# @post role="textview" label="Write something..."
55
# @tag chat
66
# @tag navigation
77
# @tag perf
88
# @tag sentry-ManualOpenReport
9-
env TARGET_CHAT="Navigates to a chat"
9+
# @param TARGET_CHAT Visible report/chat title to open from Inbox LHN.
1010

1111
find "Inbox" "click"
1212
find "${TARGET_CHAT}" "click"

.claude/skills/agent-device/flows/open-search-router.ad renamed to .claude/skills/agent-device/flows/tests/open-search-router.ad

File renamed without changes.

0 commit comments

Comments
 (0)