zeno-mobile-runner 0.2.16 → 0.2.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +20 -7
- package/FEATURES.md +29 -20
- package/README.md +73 -57
- package/SECURITY.md +11 -6
- package/clients/README.md +8 -7
- package/clients/go/README.md +2 -2
- package/clients/kotlin/README.md +2 -2
- package/clients/kotlin/build.gradle.kts +1 -1
- package/clients/python/README.md +2 -1
- package/clients/python/pyproject.toml +1 -1
- package/clients/rust/Cargo.lock +1 -1
- package/clients/rust/Cargo.toml +1 -1
- package/clients/rust/README.md +2 -2
- package/clients/swift/README.md +2 -2
- package/clients/typescript/README.md +2 -1
- package/clients/typescript/package.json +1 -1
- package/docs/adr/0001-agent-native-runner-boundary.md +1 -1
- package/docs/adr/README.md +7 -5
- package/docs/agent-discovery.md +15 -15
- package/docs/ai-agents.md +30 -20
- package/docs/app-integration.md +59 -27
- package/docs/benchmarking.md +16 -8
- package/docs/benchmarks/README.md +3 -1
- package/docs/benchmarks/benchmark-lab-v1.md +1 -1
- package/docs/client-installation.md +18 -9
- package/docs/clients.md +7 -6
- package/docs/config.md +29 -15
- package/docs/demo.md +14 -9
- package/docs/expo-smoke.md +12 -18
- package/docs/frameworks.md +30 -21
- package/docs/install.md +63 -13
- package/docs/npm.md +45 -27
- package/docs/production-readiness.md +32 -17
- package/docs/protocol-fixtures/core-session.responses.jsonl +1 -1
- package/docs/protocol-versioning.md +5 -3
- package/docs/protocol.md +33 -18
- package/docs/scenario-authoring.md +15 -8
- package/docs/support-matrix.md +38 -0
- package/docs/trace-privacy.md +5 -3
- package/docs/troubleshooting.md +17 -14
- package/npm/app-config.mjs +2 -0
- package/npm/commands.mjs +4 -4
- package/npm/scaffold.mjs +2 -2
- package/package.json +2 -2
- package/prebuilds/darwin-arm64/zmr +0 -0
- package/prebuilds/darwin-x64/zmr +0 -0
- package/prebuilds/linux-arm64/zmr +0 -0
- package/prebuilds/linux-x64/zmr +0 -0
- package/schemas/README.md +6 -3
- package/schemas/import-output.schema.json +1 -1
- package/schemas/scenario.schema.json +2 -0
- package/schemas/zmr-config.schema.json +2 -1
- package/scripts/public-metadata-guard.sh +101 -0
- package/shims/android/README.md +4 -3
- package/shims/android/protocol.md +3 -2
- package/shims/ios/README.md +5 -5
- package/shims/ios/protocol.md +2 -1
- package/skills/zmr-mobile-testing/SKILL.md +9 -8
- package/src/android_emulator.zig +54 -5
- package/src/cli_import.zig +15 -2
- package/src/cli_output.zig +2 -0
- package/src/cli_run.zig +8 -0
- package/src/config.zig +3 -0
- package/src/errors.zig +3 -0
- package/src/ios_devices.zig +100 -0
- package/src/main.zig +1 -1
- package/src/mcp_protocol.zig +12 -9
- package/src/run_options.zig +4 -0
- package/src/scaffold.zig +10 -8
- package/src/scenario.zig +43 -0
- package/src/selector.zig +53 -9
- package/src/trace_json.zig +4 -0
- package/src/validation.zig +5 -0
- package/src/version.zig +1 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Production Readiness
|
|
2
2
|
|
|
3
|
-
ZMR is a public developer preview. The npm package is live, release
|
|
4
|
-
are signed by GitHub release attestations, and
|
|
5
|
-
repeatable Android,
|
|
6
|
-
|
|
3
|
+
ZMR is currently a public developer preview. The npm package is live, release
|
|
4
|
+
artifacts are signed by GitHub release attestations, and app teams can collect
|
|
5
|
+
repeatable Android, iPhone simulator, iPad simulator, and physical iOS/iPadOS
|
|
6
|
+
evidence today. The product should not be described as production-stable until
|
|
7
|
+
the gates below are passing and remain part of the release routine.
|
|
7
8
|
|
|
8
9
|
## Current Release Standard
|
|
9
10
|
|
|
10
|
-
Every public release should satisfy:
|
|
11
|
+
Every public release should satisfy these checks before publishing artifacts:
|
|
11
12
|
|
|
12
13
|
- `bash tests/docs-readiness-test.sh`
|
|
13
14
|
- `bash tests/public-safety-test.sh`
|
|
@@ -18,14 +19,20 @@ Every public release should satisfy:
|
|
|
18
19
|
- `./scripts/verify-release-artifacts.sh --dist dist`
|
|
19
20
|
- at least one trace or benchmark report rendered with `zmr report --junit`,
|
|
20
21
|
or a pilot wrapper run that produced both `report.html` and `junit.xml`
|
|
21
|
-
- a fresh
|
|
22
|
+
- a fresh curl installer smoke:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
./install.sh --version 0.2.17 --dry-run
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- a fresh npm convenience smoke:
|
|
22
29
|
|
|
23
30
|
```bash
|
|
24
31
|
npm install --save-dev zeno-mobile-runner
|
|
25
32
|
npx zmr version --json
|
|
26
33
|
```
|
|
27
34
|
|
|
28
|
-
Tagged releases
|
|
35
|
+
Tagged releases should build release archives, generate
|
|
29
36
|
`RELEASE_MANIFEST.json`, publish GitHub artifact attestations, upload release
|
|
30
37
|
assets, and publish the npm tarball through trusted publishing after the npm
|
|
31
38
|
package is configured with the `release.yml` trusted publisher.
|
|
@@ -36,12 +43,17 @@ workflow artifact for 30 days in addition to GitHub release assets.
|
|
|
36
43
|
|
|
37
44
|
## Product Gates Before 1.0
|
|
38
45
|
|
|
46
|
+
These gates separate "usable preview" from "production-stable product claim."
|
|
47
|
+
|
|
39
48
|
| Area | Required evidence | Current status |
|
|
40
49
|
| --- | --- | --- |
|
|
41
50
|
| Android emulator | 20-run pilot gate with zero failures and trace/report artifacts | Supported by `zmr-pilot-gate` and demo app |
|
|
42
51
|
| Android physical device | 20-run pilot gate on a real connected device | Supported by ADB flow; app teams must collect evidence |
|
|
43
|
-
|
|
|
44
|
-
|
|
|
52
|
+
| iPhone simulator | 20-run pilot gate with XCTest shim selectors, screenshots, and reports | Supported by iOS demo and app-local shim |
|
|
53
|
+
| iPad simulator | 20-run pilot gate on an iPad simulator with tablet layout coverage | Same iOS simulator path; needs repeated public evidence before production-stable claims |
|
|
54
|
+
| iPhone physical device | 20-run pilot gate on a real trusted device | Supported for lifecycle and shim screenshots; needs repeated public evidence |
|
|
55
|
+
| iPad physical device | 20-run pilot gate on a real trusted iPad | Same iOS/iPadOS physical path; app teams must collect separate tablet evidence |
|
|
56
|
+
| tvOS / watchOS | Platform-specific lifecycle, shim, trace, and pilot evidence | Not supported in this preview |
|
|
45
57
|
| React Native | Public setup guidance plus selector-grade app evidence using stable labels or ids | Guidance exists; repeated public demo evidence is still needed |
|
|
46
58
|
| Expo | Public smoke, dev-client scaffold, and iOS/Android run evidence | Basic iOS smoke is documented; repeated matrix evidence is still needed |
|
|
47
59
|
| Flutter | Platform-level Android/iOS smoke using semantics, deep links, and screenshots | Supported at platform level; widget-tree claims are intentionally out of scope |
|
|
@@ -52,7 +64,8 @@ workflow artifact for 30 days in addition to GitHub release assets.
|
|
|
52
64
|
|
|
53
65
|
## Reliability Evidence
|
|
54
66
|
|
|
55
|
-
Use repeated app-local pilots before making app or device claims
|
|
67
|
+
Use repeated app-local pilots before making app or device claims. A single green
|
|
68
|
+
demo proves wiring; a 20-run pilot proves reliability for a target class:
|
|
56
69
|
|
|
57
70
|
```bash
|
|
58
71
|
zmr-pilot-gate \
|
|
@@ -81,13 +94,13 @@ zmr-release-readiness \
|
|
|
81
94
|
--json
|
|
82
95
|
```
|
|
83
96
|
|
|
84
|
-
Keep
|
|
85
|
-
|
|
97
|
+
Keep generated evidence in the app repository unless it is fully redacted and
|
|
98
|
+
safe to publish.
|
|
86
99
|
|
|
87
100
|
## Agentic Standard
|
|
88
101
|
|
|
89
|
-
ZMR
|
|
90
|
-
|
|
102
|
+
ZMR meets the agent-first bar when an external agent can work from structured
|
|
103
|
+
state instead of screenshots, terminal prose, or guessed coordinates:
|
|
91
104
|
|
|
92
105
|
- `zmr doctor --json` explains setup state and remediation.
|
|
93
106
|
- `zmr schemas --json` exposes machine-readable contracts.
|
|
@@ -105,7 +118,7 @@ screenscraping or guessing:
|
|
|
105
118
|
trace events, trace explanation, trace discovery/exploration, scenario
|
|
106
119
|
validation, and redacted export.
|
|
107
120
|
|
|
108
|
-
The safe discovery pattern
|
|
121
|
+
The safe discovery pattern remains external-agent-first: observe with
|
|
109
122
|
`semantic_snapshot`, choose one typed action, record successful steps into a
|
|
110
123
|
candidate scenario, validate it, rerun it deterministically, and require human
|
|
111
124
|
review before committing generated tests.
|
|
@@ -114,10 +127,12 @@ review before committing generated tests.
|
|
|
114
127
|
|
|
115
128
|
- Claim Android and iOS app-level support only for flows that pass local pilot
|
|
116
129
|
evidence on the target device class.
|
|
130
|
+
- Claim iPad support separately from iPhone support. The runner path is shared,
|
|
131
|
+
but tablet layouts and size classes can change UI trees and selector outcomes.
|
|
117
132
|
- Claim React Native and Expo support through app-level lifecycle, deep links,
|
|
118
133
|
accessibility labels, selectors, screenshots, traces, and reports.
|
|
119
134
|
- Claim Flutter support at the Android/iOS app level when the app exposes stable
|
|
120
135
|
semantics, labels, ids, or deep links.
|
|
121
136
|
- Do not claim Flutter widget-tree inspection, Dart state inspection, managed
|
|
122
|
-
device-farm coverage, or a built-in autonomous test writer until
|
|
123
|
-
features exist and have public evidence.
|
|
137
|
+
device-farm coverage, tvOS, watchOS, or a built-in autonomous test writer until
|
|
138
|
+
those features exist and have public evidence.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{"jsonrpc":"2.0","id":1,"result":{"name":"zmr","version":"0.2.
|
|
1
|
+
{"jsonrpc":"2.0","id":1,"result":{"name":"zmr","version":"0.2.17","protocolVersion":"2026-04-28","protocol":{"version":"2026-04-28","minimumCompatibleVersion":"2026-04-28","stability":"dev-preview","breakingChangePolicy":"version-and-changelog"},"platforms":["android","ios"],"platformSupport":{"android":{"status":"supported","deviceTypes":["emulator","physical"],"automation":["adb","uiautomator","android-shim"]},"ios":{"status":"supported","deviceTypes":["simulator","physical"],"automation":["simctl","devicectl","xctest-shim"],"physicalDevices":true}},"iosPreview":false,"transports":["stdio","tcp"],"methods":["runner.capabilities","device.list","session.create","session.close","app.install","app.launch","app.stop","app.openLink","app.clearState","observe.snapshot","observe.semanticSnapshot","ui.tap","ui.type","ui.eraseText","ui.hideKeyboard","ui.swipe","ui.pressBack","ui.scrollUntilVisible","wait.until","wait.any","wait.gone","assert.visible","assert.notVisible","assert.healthy","scenario.validate","trace.events","trace.explore","trace.discover","trace.explain","trace.export"]}}
|
|
2
2
|
{"jsonrpc":"2.0","id":2,"result":[{"serial":"fake-device-1","state":"device","ready":true}]}
|
|
3
3
|
{"jsonrpc":"2.0","id":3,"result":{"sessionId":"default"}}
|
|
4
4
|
{"jsonrpc":"2.0","id":4,"result":true}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Protocol Versioning
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use this page when changing scenario JSON, JSON-RPC, MCP-visible schemas, trace
|
|
4
|
+
schemas, or stable error codes. ZMR exposes two public automation surfaces:
|
|
4
5
|
|
|
5
6
|
- scenario JSON files consumed by `zmr run`
|
|
6
7
|
- JSON-RPC methods exposed by `zmr serve`
|
|
7
8
|
|
|
8
|
-
The current protocol version is a date string. Before `v1.0.0`, breaking
|
|
9
|
-
are allowed only when the protocol version and changelog are updated
|
|
9
|
+
The current protocol version is a date string. Before `v1.0.0`, breaking
|
|
10
|
+
changes are allowed only when the protocol version and changelog are updated
|
|
11
|
+
together.
|
|
10
12
|
`runner.capabilities` exposes this policy in machine-readable form:
|
|
11
13
|
|
|
12
14
|
```json
|
package/docs/protocol.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# ZMR JSON-RPC Protocol
|
|
2
2
|
|
|
3
|
-
ZMR exposes newline-delimited JSON-RPC 2.0 over stdio or localhost TCP
|
|
3
|
+
ZMR exposes newline-delimited JSON-RPC 2.0 over stdio or localhost TCP. This is
|
|
4
|
+
the contract used by reference clients, agent harnesses, and the MCP server
|
|
5
|
+
internals. Each request is one JSON object followed by `\n`; each response is
|
|
6
|
+
one JSON object followed by `\n`.
|
|
4
7
|
|
|
5
|
-
Current runner version: `0.2.
|
|
8
|
+
Current runner version: `0.2.17`.
|
|
6
9
|
|
|
7
10
|
Current protocol version: `2026-04-28`.
|
|
8
11
|
|
|
@@ -47,7 +50,7 @@ and protocol versions. The response is covered by
|
|
|
47
50
|
`schemas/inspect-output.schema.json`:
|
|
48
51
|
|
|
49
52
|
```json
|
|
50
|
-
{"ok":true,"status":"ready","schemaVersion":1,"runnerVersion":"0.2.
|
|
53
|
+
{"ok":true,"status":"ready","schemaVersion":1,"runnerVersion":"0.2.17","protocolVersion":"2026-04-28","dir":".","configPath":".zmr/config.json","configExists":true,"agentInstructionsPath":".zmr/AGENTS.md","agentInstructionsExists":true,"platforms":[{"name":"android","enabled":true,"defaultDevice":"emulator-5554","smokeScenario":".zmr/android-smoke.json","smokeScenarioExists":true,"traceDir":"traces/zmr-android"},{"name":"ios","enabled":true,"defaultDevice":"booted","smokeScenario":".zmr/ios-smoke.json","smokeScenarioExists":true,"traceDir":"traces/zmr-ios"}],"recommendedCommands":["zmr doctor --strict --json --config .zmr/config.json","zmr schemas --json","zmr validate --json .zmr/android-smoke.json","zmr validate --json .zmr/ios-smoke.json","zmr serve --transport stdio --config .zmr/config.json --trace-dir traces/zmr-agent","zmr mcp --config .zmr/config.json --trace-dir traces/zmr-agent"],"claimsPolicy":["verify runs with trace evidence before making readiness claims","do not claim Flutter widget-tree inspection"],"limitations":["inspect is read-only and does not launch devices","autonomous crawling is not shipped; generate or edit scenarios for human review"]}
|
|
51
54
|
```
|
|
52
55
|
|
|
53
56
|
`zmr discover --from-trace <trace-dir> --out <scenario.json> --validate --json`
|
|
@@ -60,7 +63,7 @@ invent credentials, or commit files. The response is covered by
|
|
|
60
63
|
`schemas/discover-output.schema.json`:
|
|
61
64
|
|
|
62
65
|
```json
|
|
63
|
-
{"ok":true,"mode":"discover","schemaVersion":1,"runnerVersion":"0.2.
|
|
66
|
+
{"ok":true,"mode":"discover","schemaVersion":1,"runnerVersion":"0.2.17","protocolVersion":"2026-04-28","out":".zmr/discovered/replay-smoke.json","traceDir":"traces/zmr-agent","sourceSnapshot":"traces/zmr-agent/artifacts/snapshot-2.json","name":"draft from login smoke","appId":"com.example.mobiletest","selectorCount":2,"stepCount":6,"replay":{"enabled":true,"eventCount":4,"stepCount":3,"skippedEventCount":1},"warnings":["draft requires human review before commit"],"validated":true,"validation":{"ok":true,"path":".zmr/discovered/replay-smoke.json","name":"draft from login smoke","appId":"com.example.mobiletest","stepCount":6},"nextCommands":["zmr validate --json .zmr/discovered/replay-smoke.json","zmr run .zmr/discovered/replay-smoke.json --json --trace-dir traces/zmr-agent"]}
|
|
64
67
|
```
|
|
65
68
|
|
|
66
69
|
`zmr explore --from-trace <trace-dir> --out <scenario.json> --goal <goal>
|
|
@@ -71,7 +74,7 @@ launch devices, crawl the app, invent missing actions, discover credentials, or
|
|
|
71
74
|
commit files. The response is covered by `schemas/explore-output.schema.json`:
|
|
72
75
|
|
|
73
76
|
```json
|
|
74
|
-
{"ok":true,"mode":"explore","schemaVersion":1,"runnerVersion":"0.2.
|
|
77
|
+
{"ok":true,"mode":"explore","schemaVersion":1,"runnerVersion":"0.2.17","protocolVersion":"2026-04-28","goal":"find a stable login smoke","autonomous":false,"reviewRequired":true,"guardrails":["writes from existing trace evidence only","does not crawl the app","does not discover credentials or secrets","requires human review before commit"],"out":".zmr/discovered/login-smoke.json","traceDir":"traces/zmr-agent","sourceSnapshot":"traces/zmr-agent/artifacts/snapshot-2.json","name":"draft from login smoke","appId":"com.example.mobiletest","selectorCount":2,"stepCount":6,"replay":{"enabled":true,"eventCount":4,"stepCount":3,"skippedEventCount":1},"warnings":["draft requires human review before commit"],"validated":true,"validation":{"ok":true,"path":".zmr/discovered/login-smoke.json","name":"draft from login smoke","appId":"com.example.mobiletest","stepCount":6},"nextCommands":["zmr validate --json .zmr/discovered/login-smoke.json","zmr run .zmr/discovered/login-smoke.json --json --trace-dir traces/zmr-agent"]}
|
|
75
78
|
```
|
|
76
79
|
|
|
77
80
|
`zmr draft --from-trace <trace-dir> --out <scenario.json> --json` is the lower
|
|
@@ -84,7 +87,7 @@ into fields, or commit files. The response is covered by
|
|
|
84
87
|
`schemas/draft-output.schema.json`:
|
|
85
88
|
|
|
86
89
|
```json
|
|
87
|
-
{"ok":true,"mode":"draft","schemaVersion":1,"runnerVersion":"0.2.
|
|
90
|
+
{"ok":true,"mode":"draft","schemaVersion":1,"runnerVersion":"0.2.17","protocolVersion":"2026-04-28","out":".zmr/discovered/surface-smoke.json","traceDir":"traces/zmr-agent","sourceSnapshot":"traces/zmr-agent/artifacts/snapshot-2.json","name":"draft from login smoke","appId":"com.example.mobiletest","selectorCount":2,"stepCount":4,"replay":{"enabled":false,"eventCount":0,"stepCount":0,"skippedEventCount":0},"warnings":["draft requires human review before commit"],"nextCommands":["zmr validate --json .zmr/discovered/surface-smoke.json","zmr run .zmr/discovered/surface-smoke.json --json --trace-dir traces/zmr-agent"]}
|
|
88
91
|
```
|
|
89
92
|
|
|
90
93
|
`zmr draft --include-actions` additionally parses `events.jsonl` and prepends
|
|
@@ -214,7 +217,7 @@ installers, setup scripts, and generated clients. The response is covered by
|
|
|
214
217
|
`schemas/version-output.schema.json`:
|
|
215
218
|
|
|
216
219
|
```json
|
|
217
|
-
{"name":"zmr","version":"0.2.
|
|
220
|
+
{"name":"zmr","version":"0.2.17","protocolVersion":"2026-04-28","minimumCompatibleProtocolVersion":"2026-04-28","stability":"dev-preview","breakingChangePolicy":"version-and-changelog"}
|
|
218
221
|
```
|
|
219
222
|
|
|
220
223
|
## Capabilities Output Contract
|
|
@@ -226,7 +229,7 @@ and method inventory for JSON-RPC clients. The result object is covered by
|
|
|
226
229
|
iOS simulator, or physical iOS workflows are available.
|
|
227
230
|
|
|
228
231
|
```json
|
|
229
|
-
{"name":"zmr","version":"0.2.
|
|
232
|
+
{"name":"zmr","version":"0.2.17","protocolVersion":"2026-04-28","protocol":{"version":"2026-04-28","minimumCompatibleVersion":"2026-04-28","stability":"dev-preview","breakingChangePolicy":"version-and-changelog"},"platforms":["android","ios"],"platformSupport":{"android":{"status":"supported","deviceTypes":["emulator","physical"],"automation":["adb","uiautomator","android-shim"]},"ios":{"status":"supported","deviceTypes":["simulator","physical"],"automation":["simctl","devicectl","xctest-shim"],"physicalDevices":true}},"iosPreview":false,"transports":["stdio","tcp"],"methods":["runner.capabilities","device.list","session.create","session.close","app.install","app.launch","app.stop","app.openLink","app.clearState","observe.snapshot","observe.semanticSnapshot","ui.tap","ui.type","ui.eraseText","ui.hideKeyboard","ui.swipe","ui.pressBack","ui.scrollUntilVisible","wait.until","wait.any","wait.gone","assert.visible","assert.notVisible","assert.healthy","scenario.validate","trace.events","trace.explore","trace.discover","trace.explain","trace.export"]}
|
|
230
233
|
```
|
|
231
234
|
|
|
232
235
|
## Doctor Output Contract
|
|
@@ -278,7 +281,7 @@ generated app-local file, direct paths for the config/scenario/matrix/agent
|
|
|
278
281
|
files, first-run commands, and the generated script names:
|
|
279
282
|
|
|
280
283
|
```json
|
|
281
|
-
{"ok":true,"mode":"app","dir":".","appId":"com.example.mobiletest","created":["./.zmr/config.json","./.zmr/android-smoke.json","./.zmr/ios-smoke.json","./.zmr/device-matrix.json","./.zmr/AGENTS.md"],"configPath":"./.zmr/config.json","androidScenarioPath":"./.zmr/android-smoke.json","iosScenarioPath":"./.zmr/ios-smoke.json","deviceMatrixPath":"./.zmr/device-matrix.json","agentInstructionsPath":"./.zmr/AGENTS.md","next":"zmr doctor --strict --json --config ./.zmr/config.json","nextCommands":["zmr doctor --strict --json --config ./.zmr/config.json","zmr schemas --json","zmr validate --json ./.zmr/android-smoke.json","zmr validate --json ./.zmr/ios-smoke.json"],"smokeCommands":["zmr run ./.zmr/android-smoke.json --device emulator-5554 --trace-dir ./traces/zmr-android","zmr run ./.zmr/ios-smoke.json --platform ios --device booted --trace-dir ./traces/zmr-ios"],"scriptCount":16,"scriptNames":["doctor","schemas","validate","android","androidReport","androidReliability","ios","iosReport","iosReliability","matrix","pilotGate","readiness","serve","mcp","explain","exportTrace"]}
|
|
284
|
+
{"ok":true,"mode":"app","dir":".","appId":"com.example.mobiletest","created":["./.zmr/config.json","./.zmr/android-smoke.json","./.zmr/ios-smoke.json","./.zmr/device-matrix.json","./.zmr/AGENTS.md"],"configPath":"./.zmr/config.json","androidScenarioPath":"./.zmr/android-smoke.json","iosScenarioPath":"./.zmr/ios-smoke.json","deviceMatrixPath":"./.zmr/device-matrix.json","agentInstructionsPath":"./.zmr/AGENTS.md","next":"zmr doctor --strict --json --config ./.zmr/config.json","nextCommands":["zmr doctor --strict --json --config ./.zmr/config.json","zmr schemas --json","zmr validate --json ./.zmr/android-smoke.json","zmr validate --json ./.zmr/ios-smoke.json"],"smokeCommands":["zmr run ./.zmr/android-smoke.json --device emulator-5554 --trace-dir ./traces/zmr-android --ensure-device","zmr run ./.zmr/ios-smoke.json --platform ios --device booted --trace-dir ./traces/zmr-ios --ensure-device"],"scriptCount":16,"scriptNames":["doctor","schemas","validate","android","androidReport","androidReliability","ios","iosReport","iosReliability","matrix","pilotGate","readiness","serve","mcp","explain","exportTrace"]}
|
|
282
285
|
```
|
|
283
286
|
|
|
284
287
|
Agents should read `agentInstructionsPath` for the app-local operating note and
|
|
@@ -299,8 +302,9 @@ Single-scenario mode reports the created scenario and next validation command:
|
|
|
299
302
|
## Import Output Contract
|
|
300
303
|
|
|
301
304
|
`zmr import flow-yaml <flow.yaml> --out .zmr/imported.json --json` converts a
|
|
302
|
-
supported subset of mobile-flow YAML into native ZMR scenario JSON.
|
|
303
|
-
|
|
305
|
+
supported subset of mobile-flow YAML into native ZMR scenario JSON. Keep the
|
|
306
|
+
generated JSON as the reviewed, deterministic scenario that agents and CI run.
|
|
307
|
+
The response is covered by `schemas/import-output.schema.json`:
|
|
304
308
|
|
|
305
309
|
```json
|
|
306
310
|
{"ok":true,"format":"flow-yaml","source":"flows/login.yaml","out":".zmr/login-smoke.json","name":"Imported login smoke","appId":"com.example.mobiletest","stepCount":10,"next":"zmr validate .zmr/login-smoke.json","nextCommands":["zmr validate --json .zmr/login-smoke.json","zmr run .zmr/login-smoke.json --json --trace-dir traces/zmr-run"]}
|
|
@@ -360,7 +364,7 @@ zmr serve --transport stdio --platform ios --ios-device-type physical --device <
|
|
|
360
364
|
zmr mcp --config .zmr/config.json --trace-dir traces/mcp-agent-session
|
|
361
365
|
```
|
|
362
366
|
|
|
363
|
-
`runner.capabilities` reports `platforms: ["android","ios"]`, `platformSupport.ios.status: "supported"`, and legacy `iosPreview: false`. Android supports emulators and connected devices. iOS simulators use `simctl` for discovery, install, launch, stop, clear-state-by-uninstall, deep links, screenshots, logs, and snapshots. Physical
|
|
367
|
+
`runner.capabilities` reports `platforms: ["android","ios"]`, `platformSupport.ios.status: "supported"`, and legacy `iosPreview: false`. Android supports emulators and connected devices. iOS and iPadOS simulators use `simctl` for discovery, install, launch, stop, clear-state-by-uninstall, deep links, screenshots, logs, and snapshots. Physical iPhone and iPad devices use `devicectl` for discovery, install, launch, deep-link launch, clear-state-by-uninstall, and best-effort stop. Selector-grade `ui.*` methods on iOS require a configured XCTest/XCUIAutomation shim command; without one they return `IosXCTestShimRequired`. With the shim configured, single-field `ui.tap`, selector-scoped `ui.type`, selector-scoped `ui.eraseText`, `wait.*`, and `assert.*` can execute directly through XCTest. Compound selectors continue to use the portable snapshot-matching fallback. iOS snapshot responses are bounded to common XCTest element families so traces stay usable on large apps. Physical iOS screenshot artifacts use the XCTest shim; physical-device log capture is intentionally limited in this release.
|
|
364
368
|
|
|
365
369
|
## Core Methods
|
|
366
370
|
|
|
@@ -433,7 +437,7 @@ Request:
|
|
|
433
437
|
Response:
|
|
434
438
|
|
|
435
439
|
```json
|
|
436
|
-
{"jsonrpc":"2.0","id":1,"result":{"name":"zmr","version":"0.2.
|
|
440
|
+
{"jsonrpc":"2.0","id":1,"result":{"name":"zmr","version":"0.2.17","protocolVersion":"2026-04-28","protocol":{"version":"2026-04-28","minimumCompatibleVersion":"2026-04-28","stability":"dev-preview","breakingChangePolicy":"version-and-changelog"},"platforms":["android","ios"],"platformSupport":{"android":{"status":"supported","deviceTypes":["emulator","physical"],"automation":["adb","uiautomator","android-shim"]},"ios":{"status":"supported","deviceTypes":["simulator","physical"],"automation":["simctl","devicectl","xctest-shim"],"physicalDevices":true}},"iosPreview":false,"transports":["stdio","tcp"],"methods":["runner.capabilities","device.list","session.create","session.close","app.install","app.launch","app.stop","app.openLink","app.clearState","observe.snapshot","observe.semanticSnapshot","ui.tap","ui.type","ui.eraseText","ui.hideKeyboard","ui.swipe","ui.pressBack","ui.scrollUntilVisible","wait.until","wait.any","wait.gone","assert.visible","assert.notVisible","assert.healthy","scenario.validate","trace.events","trace.explore","trace.discover","trace.explain","trace.export"]}}
|
|
437
441
|
```
|
|
438
442
|
|
|
439
443
|
### `trace.events`
|
|
@@ -515,7 +519,7 @@ Request:
|
|
|
515
519
|
Response:
|
|
516
520
|
|
|
517
521
|
```json
|
|
518
|
-
{"jsonrpc":"2.0","id":25,"result":{"ok":true,"mode":"discover","schemaVersion":1,"runnerVersion":"0.2.
|
|
522
|
+
{"jsonrpc":"2.0","id":25,"result":{"ok":true,"mode":"discover","schemaVersion":1,"runnerVersion":"0.2.17","protocolVersion":"2026-04-28","out":".zmr/discovered/agent-smoke.json","traceDir":"traces/agent-session","sourceSnapshot":"traces/agent-session/artifacts/snapshot-1.json","name":"agent smoke","appId":"com.example.mobiletest","selectorCount":1,"stepCount":4,"replay":{"enabled":true,"eventCount":2,"stepCount":1,"skippedEventCount":1},"warnings":["draft requires human review before commit"],"validated":true,"validation":{"ok":true,"path":".zmr/discovered/agent-smoke.json","name":"agent smoke","appId":"com.example.mobiletest","stepCount":4},"nextCommands":["zmr validate --json .zmr/discovered/agent-smoke.json","zmr run .zmr/discovered/agent-smoke.json --json --trace-dir traces/agent-session"]}}
|
|
519
523
|
```
|
|
520
524
|
|
|
521
525
|
Without `--trace-dir`, it returns `ok: false` with `traceDir: null`. Generated
|
|
@@ -538,7 +542,7 @@ Request:
|
|
|
538
542
|
Response:
|
|
539
543
|
|
|
540
544
|
```json
|
|
541
|
-
{"jsonrpc":"2.0","id":27,"result":{"ok":true,"mode":"explore","schemaVersion":1,"runnerVersion":"0.2.
|
|
545
|
+
{"jsonrpc":"2.0","id":27,"result":{"ok":true,"mode":"explore","schemaVersion":1,"runnerVersion":"0.2.17","protocolVersion":"2026-04-28","out":".zmr/discovered/agent-goal.json","traceDir":"traces/agent-session","sourceSnapshot":"traces/agent-session/artifacts/snapshot-1.json","name":"agent goal smoke","appId":"com.example.mobiletest","selectorCount":1,"stepCount":4,"replay":{"enabled":true,"eventCount":2,"stepCount":1,"skippedEventCount":1},"warnings":["draft requires human review before commit"],"validated":true,"validation":{"ok":true,"path":".zmr/discovered/agent-goal.json","name":"agent goal smoke","appId":"com.example.mobiletest","stepCount":4},"nextCommands":["zmr validate --json .zmr/discovered/agent-goal.json","zmr run .zmr/discovered/agent-goal.json --json --trace-dir traces/agent-session"],"goal":"find a stable login smoke","autonomous":false,"reviewRequired":true,"guardrails":["writes from existing trace evidence only","does not crawl the app","does not discover credentials or secrets","requires human review before commit"]}}
|
|
542
546
|
```
|
|
543
547
|
|
|
544
548
|
Without `--trace-dir`, it returns `ok: false` with `traceDir: null`.
|
|
@@ -719,12 +723,15 @@ Current stable public codes:
|
|
|
719
723
|
|
|
720
724
|
## Selectors
|
|
721
725
|
|
|
722
|
-
Selectors can combine fields.
|
|
726
|
+
Selectors must be non-empty and can combine fields. Unknown selector keys are
|
|
727
|
+
rejected by `zmr validate`, JSON-RPC, and MCP tool handling. All provided fields
|
|
728
|
+
must match the same visible node.
|
|
723
729
|
|
|
724
730
|
```json
|
|
725
731
|
{
|
|
726
732
|
"id": "email-login-submit-button",
|
|
727
733
|
"resourceId": "email-login-submit-button",
|
|
734
|
+
"stableId": "rid:email-login-submit-button:4",
|
|
728
735
|
"text": "Sign in",
|
|
729
736
|
"textContains": "Sign",
|
|
730
737
|
"contentDesc": "Account",
|
|
@@ -733,6 +740,11 @@ Selectors can combine fields. All provided fields must match the same visible no
|
|
|
733
740
|
}
|
|
734
741
|
```
|
|
735
742
|
|
|
743
|
+
Prefer app-owned `id`/`resourceId` values, accessibility identifiers, content
|
|
744
|
+
descriptions, labels, and stable text for committed scenarios. Use `stableId`
|
|
745
|
+
only as a fallback copied from the current `semantic_snapshot` when an agent
|
|
746
|
+
needs to act immediately and no stronger selector exists.
|
|
747
|
+
|
|
736
748
|
## Example
|
|
737
749
|
|
|
738
750
|
```json
|
|
@@ -744,7 +756,8 @@ Selectors can combine fields. All provided fields must match the same visible no
|
|
|
744
756
|
|
|
745
757
|
## Scenario-Only Flow Primitives
|
|
746
758
|
|
|
747
|
-
Scenario JSON supports additional orchestration primitives for agent-grade
|
|
759
|
+
Scenario JSON supports additional orchestration primitives for agent-grade
|
|
760
|
+
mobile flows:
|
|
748
761
|
|
|
749
762
|
- `waitAny`
|
|
750
763
|
- `waitNotVisible`
|
|
@@ -757,4 +770,6 @@ Scenario JSON supports additional orchestration primitives for agent-grade mobil
|
|
|
757
770
|
- `hideKeyboard`
|
|
758
771
|
- `"optional": true` on any step
|
|
759
772
|
|
|
760
|
-
These are intentionally explicit JSON structures instead of YAML conditionals,
|
|
773
|
+
These are intentionally explicit JSON structures instead of YAML conditionals,
|
|
774
|
+
so agents can generate, validate, and mutate flows without parsing a second
|
|
775
|
+
language.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Scenario Authoring
|
|
2
2
|
|
|
3
|
-
ZMR scenarios are JSON so agents
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
ZMR scenarios are JSON so agents, code generators, and CI scripts can create
|
|
4
|
+
and mutate them without learning another DSL. The parser is strict: validate
|
|
5
|
+
before a device run, keep flows explicit, and bias selectors toward app-owned
|
|
6
|
+
identifiers.
|
|
6
7
|
|
|
7
|
-
Scenarios can be written by hand
|
|
8
|
-
|
|
8
|
+
Scenarios can be written by hand or generated review-first from the trace of a
|
|
9
|
+
live session:
|
|
9
10
|
|
|
10
11
|
```mermaid
|
|
11
12
|
flowchart LR
|
|
@@ -19,17 +20,22 @@ flowchart LR
|
|
|
19
20
|
|
|
20
21
|
## Selector Strategy
|
|
21
22
|
|
|
22
|
-
Prefer selectors in this order:
|
|
23
|
+
Prefer selectors in this order for committed scenarios:
|
|
23
24
|
|
|
24
25
|
1. `id` or `resourceId` for app-owned controls.
|
|
25
26
|
2. `contentDesc` for intentional accessibility labels.
|
|
26
27
|
3. Exact `text` for stable product copy.
|
|
27
28
|
4. `textContains` only for headings, errors, or partial copy that is expected to
|
|
28
29
|
vary.
|
|
30
|
+
5. `stableId` only as a fallback copied from the current `semantic_snapshot`
|
|
31
|
+
when no app-owned selector exists.
|
|
29
32
|
|
|
30
33
|
Avoid selecting by text that includes user data, timestamps, counts, prices, or
|
|
31
34
|
network-provided content. Prefer app-owned resource ids or accessibility identifiers
|
|
32
35
|
over widening a selector until it matches unrelated nodes.
|
|
36
|
+
Treat `stableId` as a live-session fallback: it can unblock immediate agent
|
|
37
|
+
actions, but committed CI scenarios should prefer app-owned selectors because UI
|
|
38
|
+
tree shape and fallback IDs can change as layouts evolve.
|
|
33
39
|
|
|
34
40
|
## Waits And Assertions
|
|
35
41
|
|
|
@@ -81,7 +87,7 @@ The importer supports the common subset needed for smoke scenarios:
|
|
|
81
87
|
`hideKeyboard`, `assertVisible`, `assertNotVisible`, `assertHealthy`,
|
|
82
88
|
`openLink`, `back`,
|
|
83
89
|
`scrollUntilVisible`, `takeScreenshot`, and simple wait commands. Review the
|
|
84
|
-
generated JSON before committing it
|
|
90
|
+
generated JSON before committing it. Native `.zmr/*.json` scenarios remain the
|
|
85
91
|
runtime contract for agents and CI.
|
|
86
92
|
|
|
87
93
|
Use `setLocation` before location-dependent assertions to set simulator or
|
|
@@ -115,4 +121,5 @@ The example directory includes templates for common app flows:
|
|
|
115
121
|
|
|
116
122
|
Run `zmr validate --json <scenario.json>` before touching a device. Invalid
|
|
117
123
|
scenarios report `fieldPath`, `line`, and `column` when ZMR can identify the
|
|
118
|
-
source location.
|
|
124
|
+
source location. Unknown root, step, and selector fields are rejected so typos do
|
|
125
|
+
not silently change test intent.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Support Matrix
|
|
2
|
+
|
|
3
|
+
Use this page to decide what ZMR can claim today, what needs app-local proof,
|
|
4
|
+
and what is still outside the preview. ZMR is intended as an AI-agent-first
|
|
5
|
+
replacement path for mobile automation: agents observe UI state, choose typed
|
|
6
|
+
actions, validate generated scenarios, and export trace evidence that can replay
|
|
7
|
+
in CI without an LLM.
|
|
8
|
+
|
|
9
|
+
Support is claimed only when ZMR has lifecycle, observation, selector/action,
|
|
10
|
+
trace, and repeat-run evidence for the target class.
|
|
11
|
+
|
|
12
|
+
| Target | Status | Evidence standard | Notes |
|
|
13
|
+
| --- | --- | --- | --- |
|
|
14
|
+
| Android emulator | Supported | Public demo smoke plus 20-run pilot gate | ADB/UI Automator, optional Android shim, emulator lifecycle helpers |
|
|
15
|
+
| Android physical device | Supported, app-team evidence required | 20-run pilot gate on a connected device | Same ADB path; publish only redacted app-safe evidence |
|
|
16
|
+
| iPhone simulator | Supported | Public iOS simulator demo smoke plus shim traces | `simctl` lifecycle with app-local XCTest/XCUIAutomation shim for selector-grade actions |
|
|
17
|
+
| iPad simulator | Supported, evidence-needed | iPad simulator smoke plus 20-run pilot gate before production claims | Uses the same iOS simulator path; teams should verify tablet layouts and size-class branches |
|
|
18
|
+
| iPhone physical device | Supported, validate locally | 20-run pilot gate on a trusted device | `devicectl` lifecycle plus XCTest shim, subject to signing, Developer Mode, and Xcode availability |
|
|
19
|
+
| iPad physical device | Supported, evidence-needed | 20-run pilot gate on a trusted iPad before production claims | Uses the same physical iOS/iPadOS path; keep it a separate row because tablet UI can diverge |
|
|
20
|
+
| tvOS simulator/device | Not supported in this preview | Separate proof of concept, shim, destination, and trace evidence required | Reasonable Apple-platform research after iPad evidence, but not a 1.0 dependency |
|
|
21
|
+
| watchOS simulator/device | Not supported in this preview | Separate companion/pairing/lifecycle design and evidence required | Treat as customer-driven roadmap work, not a 1.0 dependency |
|
|
22
|
+
| Cloud device farms | Not included | Adapter and provider-specific evidence required | Current focus is local and self-managed devices |
|
|
23
|
+
|
|
24
|
+
## Evidence Policy
|
|
25
|
+
|
|
26
|
+
- Production-stable support requires a 20-run pilot gate with zero failures and
|
|
27
|
+
redacted trace/report artifacts.
|
|
28
|
+
- iPad evidence must stay separate from iPhone evidence. The runner path is
|
|
29
|
+
shared, but layouts, split views, and size-class behavior can produce
|
|
30
|
+
different UI trees and selector outcomes.
|
|
31
|
+
- App-owned selectors should come first: `resourceId`/`id`, accessibility
|
|
32
|
+
identifiers, content descriptions, accessibility labels, then stable visible
|
|
33
|
+
text.
|
|
34
|
+
- Use `stableId` only as a fallback copied from a current semantic snapshot. It
|
|
35
|
+
is useful for immediate agent actions; committed CI scenarios should prefer
|
|
36
|
+
app-owned identifiers.
|
|
37
|
+
- tvOS and watchOS should stay out of public support claims until their platform
|
|
38
|
+
lifecycles, shim protocols, and trace evidence exist.
|
package/docs/trace-privacy.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Trace Privacy
|
|
2
2
|
|
|
3
|
-
ZMR traces are debugging artifacts.
|
|
4
|
-
|
|
3
|
+
ZMR traces are product-debugging artifacts. Treat them as sensitive by default:
|
|
4
|
+
even a generic scenario can capture private UI state, logs, identifiers, or
|
|
5
|
+
typed inputs from the app under test.
|
|
5
6
|
|
|
6
7
|
```mermaid
|
|
7
8
|
flowchart LR
|
|
@@ -24,7 +25,8 @@ Raw trace directories may include:
|
|
|
24
25
|
|
|
25
26
|
## Sharing Rules
|
|
26
27
|
|
|
27
|
-
- Disable unnecessary raw artifacts in `.zmr/config.json
|
|
28
|
+
- Disable unnecessary raw artifacts in `.zmr/config.json` before collecting
|
|
29
|
+
traces that may leave a trusted machine:
|
|
28
30
|
|
|
29
31
|
```json
|
|
30
32
|
{
|
package/docs/troubleshooting.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Troubleshooting
|
|
2
2
|
|
|
3
|
-
Start with structured diagnostics
|
|
3
|
+
Start with structured diagnostics. They give humans, agents, and CI scripts the
|
|
4
|
+
same setup state, error codes, field paths, and remediation hints:
|
|
4
5
|
|
|
5
6
|
```bash
|
|
6
7
|
zmr doctor --json
|
|
@@ -13,25 +14,25 @@ zmr explain traces/zmr-android
|
|
|
13
14
|
`zmr doctor --json` is the first command to run when setup is unclear. It
|
|
14
15
|
reports Zig, ADB, Android device count, `xcrun`, iOS simulator state, physical
|
|
15
16
|
iOS device state, and configured Android/iOS shim command paths in a
|
|
16
|
-
machine-readable shape
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
machine-readable shape. Device readiness checks report `warning` when ADB sees
|
|
18
|
+
zero devices, `xcrun` sees zero booted iOS simulators, `devicectl` sees zero
|
|
19
|
+
paired physical iOS devices, or all listed physical devices are
|
|
20
|
+
disconnected/unavailable, with stable
|
|
20
21
|
`setup.android.no_devices`, `setup.ios.no_booted_simulators`,
|
|
21
22
|
`setup.ios.no_physical_devices`, and
|
|
22
23
|
`setup.ios.no_ready_physical_devices` error codes.
|
|
23
24
|
Missing tool and shim checks also include stable setup codes such as
|
|
24
25
|
`setup.adb.not_found` and `setup.android_shim.not_found`.
|
|
25
26
|
By default `doctor` exits zero after printing diagnostics so interactive setup
|
|
26
|
-
can keep going
|
|
27
|
+
can keep going. Add `--strict` when CI or install scripts should exit non-zero
|
|
27
28
|
for any warning or missing check.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
smoke scenario files from
|
|
31
|
-
`ios.smokeScenario` so app-local setup mistakes fail
|
|
32
|
-
starts. Config files with wrong types,
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
|
|
30
|
+
When run with `--config .zmr/config.json`, `doctor` first reports whether the
|
|
31
|
+
config file loaded, then validates configured smoke scenario files from
|
|
32
|
+
`android.smokeScenario` and `ios.smokeScenario` so app-local setup mistakes fail
|
|
33
|
+
before device orchestration starts. Config files with wrong types, unknown
|
|
34
|
+
fields such as misspelled `smokeScenario`, or empty strings where paths, app
|
|
35
|
+
ids, or script commands are required are reported as `config` warnings.
|
|
35
36
|
Those warnings include `fieldPath` in JSON mode when ZMR can identify the
|
|
36
37
|
invalid `.zmr/config.json` key, plus stable `errorCode` values for setup
|
|
37
38
|
automation.
|
|
@@ -109,6 +110,7 @@ zmr validate --json .zmr/android-smoke.json
|
|
|
109
110
|
The JSON output includes `errorCode`, `fieldPath`, `line`, and `column` when ZMR
|
|
110
111
|
can locate the source. Fix schema and selector mistakes there first; device
|
|
111
112
|
state debugging is slower and less reliable when the scenario itself is invalid.
|
|
113
|
+
Unknown root, step, and selector fields are rejected to catch typos early.
|
|
112
114
|
|
|
113
115
|
## Android Device Issues
|
|
114
116
|
|
|
@@ -234,7 +236,8 @@ with the `appState` command above.
|
|
|
234
236
|
|
|
235
237
|
## Trace And Failure Issues
|
|
236
238
|
|
|
237
|
-
When a run fails,
|
|
239
|
+
When a run fails, inspect the recorded failure before changing selectors or
|
|
240
|
+
rerunning:
|
|
238
241
|
|
|
239
242
|
```bash
|
|
240
243
|
zmr explain traces/zmr-android
|
package/npm/app-config.mjs
CHANGED
|
@@ -71,12 +71,14 @@ export function appConfig(appId, { android = true, ios = true, androidShim = "",
|
|
|
71
71
|
defaultDevice: "emulator-5554",
|
|
72
72
|
smokeScenario: ".zmr/android-smoke.json",
|
|
73
73
|
traceDir: "traces/zmr-android",
|
|
74
|
+
ensureDevice: true,
|
|
74
75
|
},
|
|
75
76
|
ios: {
|
|
76
77
|
enabled: ios,
|
|
77
78
|
defaultDevice: "booted",
|
|
78
79
|
smokeScenario: ".zmr/ios-smoke.json",
|
|
79
80
|
traceDir: "traces/zmr-ios",
|
|
81
|
+
ensureDevice: true,
|
|
80
82
|
},
|
|
81
83
|
artifacts: {
|
|
82
84
|
screenshots: true,
|
package/npm/commands.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export function smokeRunCommand({ platform, androidShim = "", iosShim = "" }) {
|
|
2
2
|
if (platform === "android") {
|
|
3
|
-
const args = ["zmr", "run", ".zmr/android-smoke.json", "--device", "emulator-5554", "--trace-dir", "traces/zmr-android"];
|
|
3
|
+
const args = ["zmr", "run", ".zmr/android-smoke.json", "--device", "emulator-5554", "--trace-dir", "traces/zmr-android", "--ensure-device"];
|
|
4
4
|
if (androidShim) args.push("--android-shim", androidShim);
|
|
5
5
|
return shellJoin(args);
|
|
6
6
|
}
|
|
7
7
|
if (platform === "ios") {
|
|
8
|
-
const args = ["zmr", "run", ".zmr/ios-smoke.json", "--platform", "ios", "--device", "booted", "--trace-dir", "traces/zmr-ios"];
|
|
8
|
+
const args = ["zmr", "run", ".zmr/ios-smoke.json", "--platform", "ios", "--device", "booted", "--trace-dir", "traces/zmr-ios", "--ensure-device"];
|
|
9
9
|
if (iosShim) args.push("--ios-shim", iosShim);
|
|
10
10
|
return shellJoin(args);
|
|
11
11
|
}
|
|
@@ -76,10 +76,10 @@ export function reliabilityCommand({ scenario, platform = "", device, appId, xcr
|
|
|
76
76
|
|
|
77
77
|
export function devClientRunCommand({ platform }) {
|
|
78
78
|
if (platform === "android") {
|
|
79
|
-
return "zmr run .zmr/android-dev-client-smoke.json --device emulator-5554 --trace-dir traces/zmr-android-dev-client";
|
|
79
|
+
return "zmr run .zmr/android-dev-client-smoke.json --device emulator-5554 --trace-dir traces/zmr-android-dev-client --ensure-device";
|
|
80
80
|
}
|
|
81
81
|
if (platform === "ios") {
|
|
82
|
-
return "zmr run .zmr/ios-dev-client-open-link.json --platform ios --device booted --trace-dir traces/zmr-ios-dev-client";
|
|
82
|
+
return "zmr run .zmr/ios-dev-client-open-link.json --platform ios --device booted --trace-dir traces/zmr-ios-dev-client --ensure-device";
|
|
83
83
|
}
|
|
84
84
|
throw new Error(`unsupported dev-client platform: ${platform}`);
|
|
85
85
|
}
|
package/npm/scaffold.mjs
CHANGED
|
@@ -139,12 +139,12 @@ export function appInitOutput(appRoot, appId, plan, { packageScripts = false } =
|
|
|
139
139
|
} else {
|
|
140
140
|
if (androidScenarioPath) {
|
|
141
141
|
smokeCommands.push(
|
|
142
|
-
`zmr run ${shellQuote(androidScenarioPath)} --device emulator-5554 --trace-dir ${shellQuote(pathJoin(appRoot, "traces", "zmr-android"))}`,
|
|
142
|
+
`zmr run ${shellQuote(androidScenarioPath)} --device emulator-5554 --trace-dir ${shellQuote(pathJoin(appRoot, "traces", "zmr-android"))} --ensure-device`,
|
|
143
143
|
);
|
|
144
144
|
}
|
|
145
145
|
if (iosScenarioPath) {
|
|
146
146
|
smokeCommands.push(
|
|
147
|
-
`zmr run ${shellQuote(iosScenarioPath)} --platform ios --device booted --trace-dir ${shellQuote(pathJoin(appRoot, "traces", "zmr-ios"))}`,
|
|
147
|
+
`zmr run ${shellQuote(iosScenarioPath)} --platform ios --device booted --trace-dir ${shellQuote(pathJoin(appRoot, "traces", "zmr-ios"))} --ensure-device`,
|
|
148
148
|
);
|
|
149
149
|
}
|
|
150
150
|
}
|