Skip to content

Commit d0d3bd3

Browse files
authored
Merge branch 'Expensify:main' into feat/95355
2 parents 6fd6c22 + 4adc694 commit d0d3bd3

360 files changed

Lines changed: 12803 additions & 4219 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.

.claude/skills/agent-device/flows/README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,29 @@
33
## Directory layout
44

55
- `macros/` - reusable helpers for common setup/navigation actions that stop in a navigable state for further interactive work.
6+
- `macros/<platform>/` - platform-specific overrides of a `macros/` flow, for flows whose selectors differ per platform. See [Platform scoping](#platform-scoping).
67
- `tests/` - critical-scenario scripts for QA/perf verification that assert explicit outcomes (for example Sentry spans) and then stop.
78
- `lib/` - bash drive libraries for flows that need conditional steering the linear `.ad` format cannot express (snapshot classification, state-dependent branching). Each file documents its own contract; the caller always owns the session lifecycle (`open`/`close`/`record`). Source them from an orchestrator or run them standalone against an already-open session (for example `lib/sign-in-drive.sh --platform web --session <name> --email <email>`).
89

910
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/`).
1011

12+
## Platform scoping
13+
14+
Most flows are platform-neutral and live directly in `macros/`. A flow whose selectors genuinely differ per platform gets a copy per platform under `macros/<platform>/`, where `<platform>` is the value passed to `--platform`.
15+
16+
A caller driving platform `P` resolves a macro by name:
17+
18+
1. `macros/<P>/<name>.ad` when that file exists.
19+
2. `macros/<name>.ad` otherwise.
20+
21+
Split flows today: `sign-in.ad`, `send-message.ad`, `complete-onboarding.ad`. All three fill text inputs, whose accessibility shape differs between web and native. The unscoped copy of a split flow stays in `macros/` as the fallback for platforms that have no folder yet; it is not the contract for any platform that does have one. Everything else stays shared - split a flow only after confirming the divergence per platform with `agent-device is visible "<selector>"`.
22+
1123
## Agent decision loop (interactive)
1224

1325
Before manually navigating, use this human-in-the-loop loop:
1426

1527
1. `agent-device snapshot -i` - see current state.
16-
2. `grep -H '^# @' .claude/skills/agent-device/flows/macros/*.ad` - interactive catalog.
28+
2. `grep -H '^# @' .claude/skills/agent-device/flows/macros/*.ad .claude/skills/agent-device/flows/macros/<platform>/*.ad` - interactive catalog. Where both list the same name, the platform copy wins.
1729
3. For each candidate flow, run `agent-device is exists "<selector>"` per `@pre`. Keep flows where every `@pre` passes.
1830
4. Rank survivors by goal closeness and present top macro candidates to the user with a short "why this flow" note:
1931
- Prefer flows whose `@post` selectors literally match destination language from the user request (same `text`, `label`, or selector phrase).
@@ -69,6 +81,7 @@ agent-device replay <flow>.ad -e EMAIL=other@example.com
6981
- **No `open`, no `close`, no `context` header.** Caller owns lifecycle.
7082
- **No fixed `wait` calls.** `fill`/`press` resolve selectors with retry. Only add `wait <selector>` for real post-action blocks.
7183
- **Durable selectors.** Prefer `id=...` first, then `role=... label=...`, with `||` fallbacks. Avoid `@eN` refs.
84+
- **Confirm every selector on the platform it is written for.** `snapshot -i` prints display tags, which are not selector values - a node printed as `[text-field]` may only match `role="textbox"`. Check the exit code of `agent-device is visible "<selector>"` before committing a selector, and never carry one across platforms unchecked.
7285
- **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.
7386
- **Choose directory intentionally.** Put reusable setup/navigation steps in `flows/macros/`; put outcome verification scenarios in `flows/tests/`.
7487
- **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").
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
context platform=android
2+
# @desc Complete onboarding with minimal choices (skip work email, pick "Something else" purpose, enter generic name). Lands on Home.
3+
# @pre text="What’s your work email?"
4+
# @post text="Home"
5+
# @post role="button" label="Search"
6+
# @tag onboarding
7+
# @param FIRST_NAME First name to enter on onboarding profile step.
8+
# @param LAST_NAME Last name to enter on onboarding profile step.
9+
10+
press "id=\"onboardingPrivateEmailSkipButton\" || role=\"button\" label=\"Skip\" || label=\"Skip\""
11+
press "role=\"button\" label=\"Something else\" || label=\"Something else\""
12+
fill "role=\"textfield\" label=\"First name\" editable=true || label=\"First name\" editable=true" "${FIRST_NAME}"
13+
fill "role=\"textfield\" label=\"Last name\" editable=true || label=\"Last name\" editable=true" "${LAST_NAME}"
14+
press "role=\"button\" label=\"Continue\" || label=\"Continue\""
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
context platform=android
2+
# @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.
3+
# @pre label="Write something..." editable=true
4+
# @post label="Write something..." editable=true
5+
# @tag chat
6+
# @param MESSAGE Message text to send in the currently open chat.
7+
8+
is exists "label=\"Write something...\" editable=true"
9+
fill "label=\"Write something...\" editable=true" "${MESSAGE}"
10+
press "role=\"button\" label=\"Send\" || label=\"Send\""
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
context platform=android
2+
# @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.
3+
# @pre id="username"
4+
# @pre role="button" label="Continue"
5+
# @post role="button" label="Join" || role="button" label="Search"
6+
# @tag auth
7+
# @param EMAIL Login email. Use randomized alias format `agent-device-testing+<9digits>@gmail.com` to avoid account flagging.
8+
9+
fill "id=\"username\" || label=\"Phone or email\" editable=true" "${EMAIL}"
10+
press "role=\"button\" label=\"Continue\" || label=\"Continue\""
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
context platform=web
2+
# @desc Complete onboarding with minimal choices (skip work email, pick "Something else" purpose, enter generic name). Lands on Home.
3+
# @pre text="What’s your work email?"
4+
# @post text="Home"
5+
# @post role="button" label="Search"
6+
# @tag onboarding
7+
# @param FIRST_NAME First name to enter on onboarding profile step.
8+
# @param LAST_NAME Last name to enter on onboarding profile step.
9+
10+
press "role=\"button\" label=\"Skip\" || label=\"Skip\""
11+
press "role=\"button\" label=\"Something else\" || label=\"Something else\""
12+
fill "role=\"textbox\" label=\"First name\" || label=\"First name\"" "${FIRST_NAME}"
13+
fill "role=\"textbox\" label=\"Last name\" || label=\"Last name\"" "${LAST_NAME}"
14+
press "role=\"button\" label=\"Continue\" || label=\"Continue\""
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
context platform=web
2+
# @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.
3+
# @pre role="textbox" label="Write something..."
4+
# @post role="textbox" label="Write something..."
5+
# @tag chat
6+
# @param MESSAGE Message text to send in the currently open chat.
7+
8+
is exists "role=\"textbox\" label=\"Write something...\""
9+
fill "role=\"textbox\" label=\"Write something...\"" "${MESSAGE}"
10+
press "role=\"button\" label=\"Send\" || label=\"Send\""
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
context platform=web
2+
# @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.
3+
# @pre role="textbox" label="Phone or email"
4+
# @pre role="button" label="Continue"
5+
# @post text="Welcome!" || text="Home"
6+
# @post role="button" label="Join" || role="button" label="Search"
7+
# @tag auth
8+
# @param EMAIL Login email. Use randomized alias format `agent-device-testing+<9digits>@gmail.com` to avoid account flagging.
9+
10+
fill "role=\"textbox\" label=\"Phone or email\" || label=\"Phone or email\"" "${EMAIL}"
11+
press "role=\"button\" label=\"Continue\" || label=\"Continue\""

.github/workflows/authorChecklist.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
if: |
1717
github.actor != 'OSBotify'
1818
&& github.actor != 'imgbot[bot]'
19+
&& github.actor != 'melvin-bot[bot]'
1920
steps:
2021
- name: Checkout
2122
uses: useblacksmith/checkout@1c9394c220d293645707b625ba9d79685f093a8f # v1

CLAUDE.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,9 @@ React Compiler auto-memoizes object literals, callbacks, JSX, and derived values
225225

226226
**ALWAYS run these steps after making code changes, before committing:**
227227

228-
1. **Oxfmt**: Run `npm run fmt` on every file you modified. This is mandatory - CI will reject unformatted code.
229-
2. **ESLint**: Run `npm run lint-changed` to catch lint errors early.
230-
3. **TypeScript**: Run `npm run typecheck-tsgo` after changes that may affect typing (types, interfaces, or function signatures). It is ~10x faster and usually stricter than tsc. CI validates with `npm run typecheck` (tsc), which remains the required merge gate.
231-
4. **React Compiler**: If you added new React components/hooks or modified existing ones, run `npm run react-compiler-compliance-check check-changed` to verify they compile with React Compiler. This applies the same rules as CI, evaluated against BOTH the Babel and OXC compilers: new components/hooks must compile, existing compiled files must not regress, and changes must not introduce new memoization divergence (one compiler memoizing a file while the other does not). See `contributingGuides/REACT_COMPILER.md` for details and common fixes.
228+
1. **ESLint**: Run `npm run lint-changed` to catch lint errors early.
229+
2. **TypeScript**: Run `npm run typecheck-tsgo` after changes that may affect typing (types, interfaces, or function signatures). It is ~10x faster and usually stricter than tsc. CI validates with `npm run typecheck` (tsc), which remains the required merge gate.
230+
3. **React Compiler**: If you added new React components/hooks or modified existing ones, run `npm run react-compiler-compliance-check check-changed` to verify they compile with React Compiler. This applies the same rules as CI, evaluated against BOTH the Babel and OXC compilers: new components/hooks must compile, existing compiled files must not regress, and changes must not introduce new memoization divergence (one compiler memoizing a file while the other does not). See `contributingGuides/REACT_COMPILER.md` for details and common fixes.
232231

233232
### Testing
234233

@@ -357,6 +356,6 @@ Use the `/agent-device` skill to drive the App on iOS and Android (simulators or
357356

358357
### With Backend Services
359358

360-
- RESTful API communication
359+
- REST API communication
361360
- WebSocket connections via Pusher
362361
- Real-time synchronization

Mobile-Expensify

0 commit comments

Comments
 (0)