Repository navigation
Track Maestro flow compatibility for replay --maestro #558
Copy link
Copy link
Closed as not planned
Labels
backlogLower priority / backlogLower priority / backlogenhancementNew feature or requestNew feature or request
Description
Problem
replay --maestro and test --maestro are compatibility paths for running common Maestro YAML flows through Agent Device replay and test execution. This issue tracks the supported subset and the remaining compatibility work so we do not imply full Maestro parity accidentally.
Reference docs:
- Maestro Flows overview: https://docs.maestro.dev/maestro-flows
- Maestro commands index: https://docs.maestro.dev/reference/commands-available
- Maestro selectors: https://docs.maestro.dev/reference/selectors
Architecture status
- Keep Maestro parsing and command mapping isolated in
src/compat/maestro. - Keep Maestro runtime compatibility shims isolated in
src/daemon/handlers/session-replay-maestro-runtime.ts. - Route CLI
--maestrothrough generic replay/test backend plumbing. - Emit replayable
SessionAction[]from the compat layer. - Keep lower-level iOS support explicit and opt-in for compatibility-only behavior, such as non-hittable selector taps.
- Reject unsupported commands/fields with precise command names and line numbers.
- Document the supported subset in CLI help.
- Cover the test-app Maestro fixture with parser/runtime tests.
Public app research
Sampled public Maestro suites:
- Bluesky: https://github.com/bluesky-social/social-app/tree/8e8dc7561f82dbd92c86d2f8c7a1366a8bb85eba/__e2e__
- react-native-reanimated-carousel: https://github.com/dohooo/react-native-reanimated-carousel/tree/fec99d770c52f5e55402af1c6b3a5c36d68cc7b1/e2e
- Stripe Terminal React Native: https://github.com/stripe/stripe-terminal-react-native/tree/c8e4deff06305dcbc920f036dbfce4edd2666ee7/maestro/e2e
- MentraOS: https://github.com/Mentra-Community/MentraOS/tree/9fd693b1000972a79491f3378db1c27cadd5c6b8/mobile/.maestro
Test suite execution
-
agent-device test --maestro <path-or-glob>...runs Maestro compatibility flows through the replay test suite runner. -
test --maestro --shard-all <n>runs the full runnable suite on each selected device. -
test --maestro --shard-split <n>distributes runnable suite entries across selected devices. -
test --maestro --device <id,id>accepts comma-separated explicit shard devices. - Sharded test runs can select connected or booted devices when an explicit device list is omitted.
- Sharded test runs scope sessions, request IDs, and artifacts per shard.
- Sharded test results and JUnit output include shard/device metadata for disambiguation.
- Replay test flows receive native shard/device variables:
AD_DEVICE_ID,AD_SHARD_INDEX, andAD_SHARD_COUNT.
Compatibility triage
Easy mappings should translate Maestro syntax to existing Agent Device commands without adding new runtime semantics. Runtime shims are acceptable only when scoped to Maestro compatibility and covered by parser/runtime tests.
Easy next mappings
-
setAirplaneModetrue/false ->settings airplane on|off. -
setLocation->settings location set <latitude> <longitude>. -
setOrientation->rotate <orientation>. -
setPermissionsfor supported targets ->settings permission grant|deny|reset <target>. -
killApp->close <appId>where Maestro provides or config supplies the app id. -
pasteTextwith a string payload ->type <text>if we accept text-entry equivalence instead of clipboard semantics. -
startRecording/stopRecording->record start|stopwhen Maestro options map cleanly. -
assertTrueonly for literal boolean expressions (true/false), if useful; broader JavaScript expressions stay deferred. -
launchApp.arguments/launchArguments-> simulator launch arguments.
Sampled syntax still deferred as feature work
-
repeat.while: requires replay runtime conditionals. -
runFlow.when.trueand full expression predicates: requires expression evaluation policy. -
evalScript: requires a broader sandboxing and side-effect model. -
eraseText: requires a neutral clear-field capability; emptyfillis intentionally unsupported. -
copyTextFrom: requires element text extraction into a variable/output model. -
toggleAirplaneMode: requires reading current state or accepting nondeterministic toggle semantics; prefersetAirplaneModefirst. -
launchApp.permissions: requires launch-time permission mapping before app open. -
launchApp.clearKeychain: true, clear-state command, and clear-keychain command: require neutral keychain/reset capabilities. - Relationship selectors such as
index,childOf,above,below,containsChild, and related variants.
Runtime compatibility shims now supported
-
scrollUntilVisible: polls withwait/ fuzzy text lookup and scroll probes. -
runFlow.when.visible. -
runFlow.when.notVisible. -
runScriptfile/env with a minimal compatibility sandbox forhttp.post,json, andoutputvariables. -
tapOn.optional: best-effort skip after the tap retry window. -
tapOn.pointpercentage coordinates against the current screen snapshot frame. - iOS non-hittable selector tap fallback for Maestro-style hidden/1x1 RN E2E controls, behind an explicit replay-only flag.
Supported flow shape and composition
- YAML config document + command document separated by
---. - Command-only YAML list.
-
appId. -
envmetadata parsing. -
${VAR}interpolation for string fields used by supported commands. -
${output.KEY}interpolation after supportedrunScriptoutput assignment. -
onFlowStart. -
onFlowComplete. -
runFlowscalar file form. -
runFlow.file. -
runFlow.env. -
runFlow.commands. -
runFlow.when.platform. -
runFlow.when.visible. -
runFlow.when.notVisible. -
runFlow.when.true/ expression predicates. - Full JavaScript expression interpolation.
Supported commands
-
launchApp. -
launchApp.appId. -
launchApp.stopAppasopen --relaunch. -
launchApp.clearState: falseandlaunchApp.clearKeychain: falseas tolerated no-op compatibility. -
launchApp.arguments/launchArguments. -
launchApp.clearState: truefor Android/iOS simulator app reset. -
launchApp.clearKeychain: true. -
launchApp.permissions. -
tapOnshorthand text selector. -
tapOn.id. -
tapOn.text. -
tapOn.enabled. -
tapOn.selected. -
tapOn.pointabsolute"x,y". -
tapOn.pointpercentage"x%,y%"against the screen frame. -
tapOn.repeat. -
tapOn.delay. -
tapOn.optional. -
tapOn.retryTapIfNoChange. -
tapOn.waitToSettleTimeoutMs. - point-within-element semantics.
-
doubleTapOn. -
longPressOn. -
inputTextstring value. -
inputText: { text, label }. - random input commands.
-
openLink. -
assertVisible. -
assertNotVisible. -
extendedWaitUntil.visible. -
extendedWaitUntil.notVisible. -
extendedWaitUntil.timeout. -
takeScreenshot. -
hideKeyboard. -
pressKey.back. -
pressKey.enter/pressKey.return. -
pressKey.home. -
back. -
waitForAnimationToEnd. -
waitForAnimationToEnd.timeout. -
stopApp. -
scrollscalar command. -
scrollUntilVisible. -
swipeabsolute coordinates. -
swipepercentage coordinates. -
swipe.direction. -
repeat.times. -
repeat.timesfrom${VAR}. -
repeat.while. -
eraseText. -
pasteText. -
copyTextFrom. -
runScriptfile/env withhttp.post,json, andoutput. -
evalScript. -
retry. -
toggleAirplaneMode. -
setAirplaneMode. -
setLocation. -
setOrientation. -
setPermissions. -
addMedia. -
clearStatecommand. -
clearKeychaincommand. -
killApp. -
travel. -
assertTrue. -
assertScreenshot. -
startRecording. -
stopRecording. - AI commands.
Selector support
- shorthand text.
-
id. -
text. -
enabled. -
selected. - absolute
point. - percentage
pointagainst the screen frame. -
index. -
cssfor web. -
checked. -
focused. -
traits. -
above. -
below. -
leftOf. -
rightOf. -
containsChild. -
childOf. -
containsDescendants. - dimension matchers.
- Maestro-compatible regex semantics for
text/id.
Known semantic gaps
-
extendedWaitUntil.notVisiblecurrently translates towait <timeout>thenis hidden, not a polling hidden wait. -
assertNotVisibleis not a polling assertion. -
runScriptis intentionally minimal and does not provide full Maestro JavaScript globals,require,process, arbitrary async APIs, orevalScript. - Device-state commands, clear-state command, and keychain reset need neutral Agent Device capabilities before mapping Maestro syntax.
- Relationship selectors such as
indexandchildOfare rejected instead of silently ignored.
Acceptance criteria
-
agent-device replay --maestro <flow.yaml>reports unsupported Maestro commands with precise command names and line numbers. -
agent-device test --maestro <path-or-glob>...runs Maestro compatibility flows through the replay test suite runner. -
agent-device test --maestrosupports--shard-all <n>and--shard-split <n>across selected devices. - Supported commands have parser unit tests.
- Runtime shims have replay runtime tests.
- The local test-app Maestro suite exercises supported compatibility syntax.
- CLI help describes the supported Maestro subset and links users to this issue for missing commands.
- The parser does not silently ignore unsupported Maestro fields that affect behavior.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
backlogLower priority / backlogLower priority / backlogenhancementNew feature or requestNew feature or request
Activity
thymikee commentedon May 22, 2026
Matrix update for PR #581:
Supported in this PR:
scrollUntilVisiblewith direction preserved as Maestro scroll direction (UPscrolls up,DOWNscrolls down).runFlow.when.visible/runFlow.when.notVisible, including nested Maestro runtime shims. Runtime errors from the condition check now propagate; only predicate misses skip the block.runScriptfile/env compatibility withhttp.post,json, andoutputvariables. This executes during flow parsing, can make network requests, and is not a security sandbox or native.adcommand.launchApp.clearStatefor iOS simulators.launchApp.arguments/launchArgumentsfor Apple-platform app launches only. Android launch arguments now fail loudly instead of being silently dropped.Deferred/unsupported after this cleanup:
setPermissions,setLocation,setOrientation,setAirplaneMode, recording commands, broadassertTrue, etc.).evalScript,runFlow.when.true, expression predicates, relationship selectors,repeat.while, clear-keychain support, and neutral clear-field/text-copy capabilities.thymikee commentedon Jul 20, 2026
Retiring this pre-overhaul umbrella as superseded. ADR 0015 is the compatibility contract, the generated conformance oracle is the parity record, and actionable gaps use focused issues. Unsupported syntax remains explicit and fails loudly; this closure does not claim full Maestro parity.