zig-mobile-runner 0.1.0

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 (225) hide show
  1. package/CHANGELOG.md +484 -0
  2. package/CONTRIBUTING.md +42 -0
  3. package/FEATURES.md +112 -0
  4. package/LICENSE +21 -0
  5. package/README.md +255 -0
  6. package/SECURITY.md +34 -0
  7. package/build.zig +38 -0
  8. package/build.zig.zon +7 -0
  9. package/clients/README.md +144 -0
  10. package/clients/go/README.md +24 -0
  11. package/clients/go/examples/fake-session/main.go +93 -0
  12. package/clients/go/go.mod +3 -0
  13. package/clients/go/zmr/client.go +432 -0
  14. package/clients/kotlin/README.md +35 -0
  15. package/clients/kotlin/build.gradle.kts +35 -0
  16. package/clients/kotlin/settings.gradle.kts +15 -0
  17. package/clients/kotlin/src/main/kotlin/dev/zmr/FakeSession.kt +86 -0
  18. package/clients/kotlin/src/main/kotlin/dev/zmr/ZmrClient.kt +67 -0
  19. package/clients/python/README.md +29 -0
  20. package/clients/python/examples/fake_session.py +48 -0
  21. package/clients/python/pyproject.toml +13 -0
  22. package/clients/python/zmr_client.py +202 -0
  23. package/clients/rust/Cargo.lock +107 -0
  24. package/clients/rust/Cargo.toml +10 -0
  25. package/clients/rust/README.md +19 -0
  26. package/clients/rust/examples/fake_session.rs +70 -0
  27. package/clients/rust/src/lib.rs +461 -0
  28. package/clients/swift/Package.swift +16 -0
  29. package/clients/swift/README.md +36 -0
  30. package/clients/swift/Sources/ZMRClient/ZMRClient.swift +114 -0
  31. package/clients/swift/Sources/ZMRFakeSession/main.swift +86 -0
  32. package/clients/typescript/README.md +34 -0
  33. package/clients/typescript/examples/fake-session.mjs +36 -0
  34. package/clients/typescript/index.d.ts +144 -0
  35. package/clients/typescript/index.mjs +192 -0
  36. package/clients/typescript/package.json +8 -0
  37. package/docs/adr/0001-agent-native-runner-boundary.md +31 -0
  38. package/docs/adr/0002-app-local-zmr-contract.md +39 -0
  39. package/docs/adr/0003-ios-simulator-xctest-shim.md +41 -0
  40. package/docs/adr/0004-benchmark-claims-and-baseline-collection.md +37 -0
  41. package/docs/adr/README.md +12 -0
  42. package/docs/ai-agents.md +156 -0
  43. package/docs/app-integration.md +316 -0
  44. package/docs/benchmarking.md +275 -0
  45. package/docs/client-installation.md +141 -0
  46. package/docs/clients.md +98 -0
  47. package/docs/config.md +175 -0
  48. package/docs/demo.md +259 -0
  49. package/docs/dsl.md +57 -0
  50. package/docs/install.md +233 -0
  51. package/docs/market-positioning.md +70 -0
  52. package/docs/npm.md +359 -0
  53. package/docs/protocol-fixtures/README.md +8 -0
  54. package/docs/protocol-fixtures/core-session.requests.jsonl +8 -0
  55. package/docs/protocol-fixtures/core-session.responses.jsonl +8 -0
  56. package/docs/protocol-versioning.md +65 -0
  57. package/docs/protocol.md +560 -0
  58. package/docs/publication.md +77 -0
  59. package/docs/release-audit.md +99 -0
  60. package/docs/release-candidate.md +111 -0
  61. package/docs/release-evidence.md +188 -0
  62. package/docs/release-notes-template.md +58 -0
  63. package/docs/roadmap.md +334 -0
  64. package/docs/scenario-authoring.md +88 -0
  65. package/docs/shipping.md +170 -0
  66. package/docs/trace-privacy.md +88 -0
  67. package/docs/troubleshooting.md +256 -0
  68. package/examples/android-app-auth-probe.json +89 -0
  69. package/examples/android-app-error-state.json +13 -0
  70. package/examples/android-app-login-smoke.json +192 -0
  71. package/examples/android-app-onboarding.json +12 -0
  72. package/examples/android-app-referral-deep-link.json +12 -0
  73. package/examples/android-shim-smoke.json +19 -0
  74. package/examples/demo-failure.json +12 -0
  75. package/examples/demo-fake.json +14 -0
  76. package/examples/ios-dev-client-open-link.json +26 -0
  77. package/examples/ios-dev-client-route-snapshot.json +24 -0
  78. package/examples/ios-shim-smoke.json +23 -0
  79. package/examples/ios-smoke.json +9 -0
  80. package/go.work +3 -0
  81. package/npm/agents.mjs +183 -0
  82. package/npm/app-config.mjs +95 -0
  83. package/npm/build-zmr.mjs +21 -0
  84. package/npm/commands.mjs +104 -0
  85. package/npm/generated-files.mjs +50 -0
  86. package/npm/index.mjs +75 -0
  87. package/npm/init-app.mjs +80 -0
  88. package/npm/package-scripts.mjs +72 -0
  89. package/npm/postinstall.mjs +21 -0
  90. package/npm/scaffold.mjs +179 -0
  91. package/npm/scenarios.mjs +93 -0
  92. package/npm/setup.mjs +69 -0
  93. package/npm/wizard.mjs +117 -0
  94. package/npm/zmr.mjs +23 -0
  95. package/package.json +114 -0
  96. package/prebuilds/darwin-arm64/zmr +0 -0
  97. package/prebuilds/darwin-x64/zmr +0 -0
  98. package/prebuilds/linux-arm64/zmr +0 -0
  99. package/prebuilds/linux-x64/zmr +0 -0
  100. package/schemas/README.md +26 -0
  101. package/schemas/action-result.schema.json +27 -0
  102. package/schemas/capabilities-output.schema.json +98 -0
  103. package/schemas/devices-output.schema.json +25 -0
  104. package/schemas/doctor-output.schema.json +51 -0
  105. package/schemas/explain-output.schema.json +51 -0
  106. package/schemas/import-output.schema.json +23 -0
  107. package/schemas/init-output.schema.json +71 -0
  108. package/schemas/json-rpc.schema.json +55 -0
  109. package/schemas/release-manifest.schema.json +43 -0
  110. package/schemas/release-readiness-output.schema.json +127 -0
  111. package/schemas/run-output.schema.json +43 -0
  112. package/schemas/scenario.schema.json +128 -0
  113. package/schemas/schemas-output.schema.json +26 -0
  114. package/schemas/semantic-snapshot.schema.json +116 -0
  115. package/schemas/snapshot.schema.json +60 -0
  116. package/schemas/trace-event.schema.json +14 -0
  117. package/schemas/trace-manifest.schema.json +59 -0
  118. package/schemas/validate-output.schema.json +42 -0
  119. package/schemas/version-output.schema.json +23 -0
  120. package/schemas/zmr-config.schema.json +75 -0
  121. package/scripts/android-emulator.sh +126 -0
  122. package/scripts/assert-ios-physical-ready.sh +213 -0
  123. package/scripts/benchmark-command.sh +307 -0
  124. package/scripts/benchmark.sh +359 -0
  125. package/scripts/benchmark_gate.py +117 -0
  126. package/scripts/benchmark_result_row.py +88 -0
  127. package/scripts/compare-benchmarks.py +288 -0
  128. package/scripts/create-android-demo-app.sh +342 -0
  129. package/scripts/create-ios-demo-app.sh +261 -0
  130. package/scripts/demo-android-real.sh +232 -0
  131. package/scripts/demo-ios-real.sh +270 -0
  132. package/scripts/demo.sh +464 -0
  133. package/scripts/device-matrix.sh +338 -0
  134. package/scripts/ensure-ios-shim-target.rb +237 -0
  135. package/scripts/install-android-shim.sh +281 -0
  136. package/scripts/install-ios-shim.sh +589 -0
  137. package/scripts/pilot-gate.sh +560 -0
  138. package/scripts/release-readiness.py +838 -0
  139. package/scripts/release-readiness.sh +91 -0
  140. package/scripts/run-android-pilot.sh +561 -0
  141. package/scripts/run-ios-pilot.sh +509 -0
  142. package/shims/android/README.md +21 -0
  143. package/shims/android/ZMRShimInstrumentedTest.java +152 -0
  144. package/shims/android/protocol.md +18 -0
  145. package/shims/ios/README.md +50 -0
  146. package/shims/ios/ZMRShim.swift +110 -0
  147. package/shims/ios/ZMRShimUITestCase.swift +475 -0
  148. package/shims/ios/protocol.md +74 -0
  149. package/skills/zmr-mobile-testing/SKILL.md +127 -0
  150. package/src/android.zig +344 -0
  151. package/src/android_device_info.zig +99 -0
  152. package/src/android_emulator.zig +154 -0
  153. package/src/android_screen_recording.zig +112 -0
  154. package/src/android_shell.zig +112 -0
  155. package/src/bundle.zig +124 -0
  156. package/src/bundle_redaction.zig +272 -0
  157. package/src/bundle_tar.zig +123 -0
  158. package/src/cli_devices.zig +97 -0
  159. package/src/cli_doctor.zig +114 -0
  160. package/src/cli_import.zig +70 -0
  161. package/src/cli_info.zig +39 -0
  162. package/src/cli_init.zig +72 -0
  163. package/src/cli_output.zig +467 -0
  164. package/src/cli_run.zig +259 -0
  165. package/src/cli_serve.zig +287 -0
  166. package/src/cli_trace.zig +111 -0
  167. package/src/cli_validate.zig +41 -0
  168. package/src/command.zig +211 -0
  169. package/src/config.zig +305 -0
  170. package/src/config_diagnostics.zig +212 -0
  171. package/src/config_paths.zig +49 -0
  172. package/src/device_registry.zig +37 -0
  173. package/src/doctor.zig +412 -0
  174. package/src/doctor_hints.zig +52 -0
  175. package/src/errors.zig +55 -0
  176. package/src/fake_device.zig +163 -0
  177. package/src/health.zig +28 -0
  178. package/src/importer.zig +343 -0
  179. package/src/importer_json.zig +100 -0
  180. package/src/importer_model.zig +103 -0
  181. package/src/ios.zig +399 -0
  182. package/src/ios_devices.zig +219 -0
  183. package/src/ios_lifecycle.zig +72 -0
  184. package/src/ios_shim.zig +242 -0
  185. package/src/ios_snapshot.zig +20 -0
  186. package/src/json_fields.zig +80 -0
  187. package/src/json_rpc.zig +150 -0
  188. package/src/json_rpc_methods.zig +318 -0
  189. package/src/json_rpc_observation.zig +31 -0
  190. package/src/json_rpc_params.zig +52 -0
  191. package/src/json_rpc_protocol.zig +110 -0
  192. package/src/json_rpc_trace.zig +73 -0
  193. package/src/main.zig +135 -0
  194. package/src/mcp.zig +234 -0
  195. package/src/mcp_protocol.zig +64 -0
  196. package/src/mcp_trace.zig +83 -0
  197. package/src/report.zig +346 -0
  198. package/src/report_html.zig +63 -0
  199. package/src/report_values.zig +27 -0
  200. package/src/run_options.zig +152 -0
  201. package/src/runner.zig +280 -0
  202. package/src/runner_actions.zig +109 -0
  203. package/src/runner_config.zig +6 -0
  204. package/src/runner_diagnostics.zig +268 -0
  205. package/src/runner_events.zig +170 -0
  206. package/src/runner_native.zig +88 -0
  207. package/src/runner_waits.zig +300 -0
  208. package/src/scaffold.zig +472 -0
  209. package/src/scenario.zig +346 -0
  210. package/src/scenario_fields.zig +50 -0
  211. package/src/schema_registry.zig +53 -0
  212. package/src/selector.zig +84 -0
  213. package/src/semantic.zig +171 -0
  214. package/src/trace.zig +315 -0
  215. package/src/trace_json.zig +340 -0
  216. package/src/trace_summary.zig +218 -0
  217. package/src/trace_summary_diagnostic.zig +202 -0
  218. package/src/types.zig +120 -0
  219. package/src/uiautomator.zig +164 -0
  220. package/src/validation.zig +187 -0
  221. package/src/version.zig +22 -0
  222. package/viewer/app.js +373 -0
  223. package/viewer/index.html +126 -0
  224. package/viewer/parser.js +233 -0
  225. package/viewer/styles.css +585 -0
package/docs/demo.md ADDED
@@ -0,0 +1,259 @@
1
+ # Demo
2
+
3
+ Run the local demo with no emulator, simulator, app, or credentials:
4
+
5
+ ```bash
6
+ ./scripts/demo.sh
7
+ ```
8
+
9
+ The script builds `zig-out/bin/zmr`, then runs:
10
+
11
+ - `zmr version`
12
+ - `zmr version --json`
13
+ - `zmr schemas --json`
14
+ - `zmr validate examples/demo-fake.json`
15
+ - `zmr validate examples/demo-failure.json`
16
+ - `zmr validate examples/android-app-onboarding.json`
17
+ - `zmr validate examples/android-app-referral-deep-link.json`
18
+ - `zmr validate examples/android-app-error-state.json`
19
+ - `zmr validate examples/android-shim-smoke.json`
20
+ - `zmr validate examples/ios-smoke.json`
21
+ - `zmr validate examples/ios-dev-client-open-link.json`
22
+ - `zmr validate examples/ios-dev-client-route-snapshot.json`
23
+ - `zmr validate examples/ios-shim-smoke.json`
24
+ - expected-failing `zmr validate --json` output that shows `fieldPath`, `line`,
25
+ and `column` for invalid scenarios covered by `schemas/validate-output.schema.json`
26
+ - `zmr doctor --adb ./tests/fake-adb.sh --xcrun ./tests/fake-xcrun.sh --ios-shim ./tests/fake-ios-shim.sh`
27
+ - `zmr doctor --json` output for a missing Android shim that includes a
28
+ remediation `hint`
29
+ - `zmr doctor --json` output that warns with stable setup `errorCode` values
30
+ when no Android devices, booted iOS simulators, or paired physical iOS
31
+ devices are ready
32
+ - expected-failing `zmr doctor --strict --json` output for the same no-device
33
+ setup, showing how CI can fail without parsing the diagnostics itself
34
+ - `zmr doctor --json --config traces/demo-doctor-config.json` output that
35
+ validates configured smoke scenario files, including an `ios-smoke-scenario` remediation
36
+ for a bad `ios.smokeScenario` and a `zmr validate on the configured Android
37
+ smoke scenario` hint for malformed scenario JSON
38
+ - `zmr doctor --json --config traces/demo-bad-config.json` output that reports
39
+ stable `errorCode` plus `fieldPath` for an invalid app-local config value
40
+ before device setup starts
41
+ - `zmr devices --adb ./tests/fake-adb.sh`
42
+ - `zmr devices --json --adb ./tests/fake-adb.sh`
43
+ - `zmr devices --platform ios --xcrun ./tests/fake-xcrun.sh`
44
+ - `zmr devices --json --platform ios --xcrun ./tests/fake-xcrun.sh`
45
+ - `zmr init --app --json --dir traces/demo-init-app --app-id com.example.demoapp`
46
+ followed by validation and strict config-driven doctor checks from that
47
+ generated app-local workspace
48
+ - `zmr import flow-yaml traces/demo-flow-yaml-flow.yaml --out traces/demo-imported-flow.json --json`
49
+ followed by validation of the generated native ZMR scenario
50
+ - `zmr run examples/demo-fake.json --trace-dir traces/demo-fake-android --json`
51
+ - `scripts/device-matrix.sh --matrix traces/demo-device-matrix.json --trace-root traces/demo-device-matrix`
52
+ - `zmr run examples/demo-failure.json --trace-dir traces/demo-failure --json`
53
+ - `zmr explain traces/demo-failure`
54
+ - `zmr explain traces/demo-failure --json`
55
+ - `zmr serve --transport stdio --trace-dir traces/demo-rpc-session`
56
+ - `node clients/typescript/examples/fake-session.mjs`
57
+ - `python3 clients/python/examples/fake_session.py`
58
+ - `swift run ZMRFakeSession` from `clients/swift`
59
+ - `gradle -p clients/kotlin runFakeSession`
60
+ - `go run ./clients/go/examples/fake-session --zmr ./zig-out/bin/zmr --adb ./tests/fake-adb.sh --trace-dir traces/demo-go-client`
61
+ - `cargo run --manifest-path clients/rust/Cargo.toml --example fake_session -- --zmr ./zig-out/bin/zmr --adb ./tests/fake-adb.sh --trace-dir traces/demo-rust-client`
62
+ - `zmr run examples/ios-smoke.json --platform ios --trace-dir traces/demo-fake-ios`
63
+
64
+ The fake Android flow exercises selector matching and wait/assert trace output.
65
+ The fake device-matrix flow exercises Android, iOS simulator, and physical iOS
66
+ matrix rows without requiring local hardware, producing `matrix.jsonl` and
67
+ `summary.json`.
68
+ The fake failure flow exercises failed trace diagnostics and the terminal
69
+ `zmr explain` summary.
70
+ The fake JSON-RPC flow exercises the agent protocol over stdio, live RPC trace
71
+ recording, `observe.snapshot`, and redacted `trace.export`.
72
+ Doctor output is intentionally structured for setup automation; `--json`
73
+ includes remediation `hint` values for missing or warning checks, and
74
+ `--config` validates app-local smoke scenario files. Add `--strict` when a
75
+ non-`ok` diagnostic should also make the command fail.
76
+ The TypeScript reference client flow exercises the same protocol through the
77
+ client API external agents would use.
78
+ The Python reference client flow verifies the same agent integration path with
79
+ only the Python standard library.
80
+ The Swift and Kotlin reference client flows verify host-side native-language
81
+ agent/test-harness integration for iOS and Android teams.
82
+ The fake Android shim flow exercises shim-backed hierarchy, wait, tap, type,
83
+ hide-keyboard, and snapshot handling.
84
+ The fake iOS flow exercises simulator lifecycle, deep-link opening, screenshot
85
+ artifact capture, log capture, and snapshot trace writing. The fake iOS shim
86
+ flow exercises shim-backed hierarchy, wait, tap, type, hide-keyboard, and
87
+ snapshot handling.
88
+
89
+ Load any generated `.zmrtrace` in `viewer/index.html` to inspect the replay
90
+ timeline, payloads, screenshot, UI tree, selected node details, and raw
91
+ artifacts side-by-side.
92
+
93
+ ## Real Android Pilot Demo
94
+
95
+ Run the Android pilot against a sample app test build:
96
+
97
+ ```bash
98
+ ./scripts/run-android-pilot.sh \
99
+ --app-root /path/to/mobile-app \
100
+ --device emulator-5554
101
+ ```
102
+
103
+ To force a known emulator state, direct `zmr run` supports `--android-avd`,
104
+ `--create-avd-if-missing`, `--avd-system-image`, `--avd-device`,
105
+ `--restore-snapshot`, `--reset-emulator`, and `--wait-emulator`. The pilot
106
+ wrapper accepts the same state controls while also building/installing the app.
107
+ Add `--screen-record` to keep a pilot-level MP4 under the trace root:
108
+
109
+ ```bash
110
+ ./scripts/run-android-pilot.sh \
111
+ --app-root /path/to/mobile-app \
112
+ --device emulator-5554 \
113
+ --avd Small_Phone \
114
+ --reset-emulator \
115
+ --restore-snapshot zmr-clean \
116
+ --screen-record
117
+ ```
118
+
119
+ The script builds `zmr` when needed, validates both sample scenarios, installs the debug test APK, starts the app's test Metro server, and runs:
120
+
121
+ - `examples/android-app-auth-probe.json`
122
+ - `examples/android-app-login-smoke.json`
123
+
124
+ For each single run it writes:
125
+
126
+ - `auth/report.html`
127
+ - `login-smoke/report.html`
128
+ - `auth.zmrtrace`
129
+ - `auth-redacted.zmrtrace`
130
+ - `login-smoke.zmrtrace`
131
+ - `login-smoke-redacted.zmrtrace`
132
+ - `screenrecord.mp4` when pilot `--screen-record`, `zmr run --screen-record`, or `.zmr/config.json` `artifacts.screenRecording` is enabled
133
+
134
+ Use the redacted bundles for demos outside a trusted local machine:
135
+
136
+ ```bash
137
+ open viewer/index.html
138
+ ```
139
+
140
+ Then load `auth-redacted.zmrtrace` or `login-smoke-redacted.zmrtrace`.
141
+
142
+ Inspect the command plan without touching the emulator:
143
+
144
+ ```bash
145
+ ./scripts/run-android-pilot.sh --dry-run --skip-emulator --skip-metro --app-root <android-app-root>
146
+ ```
147
+
148
+ Run repeated benchmark passes:
149
+
150
+ ```bash
151
+ ./scripts/run-android-pilot.sh \
152
+ --app-root <android-app-root> \
153
+ --device emulator-5554 \
154
+ --runs 20 \
155
+ --min-pass-rate 100 \
156
+ --max-failures 0
157
+ ```
158
+
159
+ `<trace-root>/metro.log` may contain sensitive app output from the sample app test environment. Do not publish raw Metro logs.
160
+
161
+ ## Real Android Demo APK
162
+
163
+ To generate a small public native Android app and matching smoke scenario:
164
+
165
+ ```bash
166
+ npx zmr-demo-android --out /tmp/zmr-android-demo --device emulator-5554 --avd <avd-name>
167
+ ```
168
+
169
+ The wrapper builds a signed debug APK with Android SDK command-line tools
170
+ only, boots the named AVD when the requested device is not ready, installs the
171
+ app, and runs the generated smoke scenario. To inspect or customize the
172
+ generated app before running manually:
173
+
174
+ ```bash
175
+ npx zmr-create-android-demo-app --out /tmp/zmr-android-demo
176
+ adb install -r /tmp/zmr-android-demo/build/app-debug.apk
177
+ zmr run /tmp/zmr-android-demo/.zmr/android-smoke.json \
178
+ --device emulator-5554 \
179
+ --app-id com.example.mobiletest \
180
+ --trace-dir /tmp/zmr-android-demo/traces/android-demo
181
+ ```
182
+
183
+ The scenario launches the app, waits for visible text, taps a button, types
184
+ text into a field, and captures a trace-backed snapshot.
185
+
186
+ ## Real iOS Simulator Demo
187
+
188
+ To generate a small public demo app with the ZMR XCTest shim already installed:
189
+
190
+ ```bash
191
+ npx zmr-demo-ios --out /tmp/zmr-ios-demo --device booted --cleanup-build-products
192
+ ```
193
+
194
+ That command creates the demo app, builds it, installs it on the requested
195
+ simulator, runs the plain iOS smoke and selector-grade shim smoke, then writes
196
+ reports and redacted `.zmrtrace` bundles. `--cleanup-build-products` removes
197
+ generated Xcode `DerivedData` after the pilot so repeated demo runs keep their
198
+ footprint small. When `--device booted` is used and no
199
+ simulator is running, the command boots an available iOS simulator first. If
200
+ the first available simulator fails to boot because CoreSimulator cannot start
201
+ `launchd_sim`, the script tries the next available iOS simulator before failing.
202
+
203
+ To inspect or customize the generated app before running the pilot manually:
204
+
205
+ ```bash
206
+ npx zmr-create-ios-demo-app --out /tmp/zmr-ios-demo
207
+ cd /tmp/zmr-ios-demo
208
+ xcodebuild -project ios/ZMRDemo.xcodeproj -scheme ZMRDemo -destination 'generic/platform=iOS Simulator' -derivedDataPath DerivedData build
209
+ ```
210
+
211
+ Then boot a simulator and run from the ZMR repo:
212
+
213
+ ```bash
214
+ scripts/run-ios-pilot.sh \
215
+ --app-root /tmp/zmr-ios-demo \
216
+ --app-path /tmp/zmr-ios-demo/DerivedData/Build/Products/Debug-iphonesimulator/ZMRDemo.app \
217
+ --app-id com.example.mobiletest \
218
+ --device booted \
219
+ --ios-shim /tmp/zmr-ios-demo/.zmr/ios-shim
220
+ ```
221
+
222
+ Build the app for an iOS simulator, boot a simulator, then run:
223
+
224
+ ```bash
225
+ ./scripts/run-ios-pilot.sh \
226
+ --app-root /path/to/mobile-app \
227
+ --app-path /path/to/mobile-app/build/Debug-iphonesimulator/Sample.app \
228
+ --app-id com.example.mobiletest \
229
+ --device booted \
230
+ --ios-shim /path/to/mobile-app/.zmr/ios-shim
231
+ ```
232
+
233
+ For each run it writes:
234
+
235
+ - `ios-smoke/report.html`
236
+ - `ios-smoke.zmrtrace`
237
+ - `ios-smoke-redacted.zmrtrace`
238
+ - `ios-shim-smoke/report.html` when `--ios-shim` is set
239
+ - `ios-shim-smoke.zmrtrace` when `--ios-shim` is set
240
+ - `ios-shim-smoke-redacted.zmrtrace` when `--ios-shim` is set
241
+
242
+ The iOS demo covers simulator install, launch/open-link, screenshot capture,
243
+ log capture, trace export, and viewer inspection. With `--ios-shim`, it also
244
+ runs `examples/ios-shim-smoke.json`, which exercises launch, waitVisible, tap,
245
+ selector-scoped typeText, hideKeyboard, and snapshot through the generated
246
+ XCTest/XCUIAutomation shim command.
247
+
248
+ When an iOS shim is configured, the pilot wrapper prewarms it before scenario
249
+ timing by sending `{"cmd":"appState"}`. That catches Xcode target wiring issues
250
+ early and keeps cold `build-for-testing` cost out of benchmark durations.
251
+ The same app-state check is used as an idempotent launch confirmation when the
252
+ app is already running but `simctl launch` reports a non-zero exit.
253
+
254
+ Simulator demos require a simulator-built `iphonesimulator` `.app`. A signed
255
+ device `.ipa` is for `--ios-device-type physical` only and is rejected early for
256
+ simulator pilots.
257
+
258
+ `clearState` on iOS is best-effort app uninstall by bundle id. Repeating it is
259
+ safe: a simulator where the app is already absent is treated as clean.
package/docs/dsl.md ADDED
@@ -0,0 +1,57 @@
1
+ # Scenario DSL
2
+
3
+ ZMR uses JSON as the V1 scenario DSL:
4
+
5
+ ```json
6
+ {
7
+ "name": "Login smoke",
8
+ "appId": "com.example.mobiletest",
9
+ "steps": [
10
+ { "action": "launch" },
11
+ { "action": "tap", "selector": { "resourceId": "email" } },
12
+ { "action": "typeText", "text": "user@example.com" },
13
+ { "action": "assertVisible", "selector": { "text": "Welcome" } }
14
+ ]
15
+ }
16
+ ```
17
+
18
+ ## Why JSON For V1
19
+
20
+ JSON is strict, deterministic, schema-validatable, and easy for agents to emit.
21
+
22
+ - It is strict and deterministic.
23
+ - It has mature schema validation.
24
+ - It is easy for AI agents and code generators to emit.
25
+ - It works cleanly across TypeScript, Python, Go, Rust, Zig, and CI tooling.
26
+ - It avoids hidden parser behavior while the protocol is still a developer
27
+ preview.
28
+
29
+ JSON is not the most pleasant hand-authored format for every team. That is why
30
+ ZMR keeps scenario files small, supports generated scenarios, and includes an
31
+ import path for a documented subset of mobile-flow YAML.
32
+
33
+ ## Authoring Recommendation
34
+
35
+ - Use JSON for committed `.zmr/*.json` scenarios.
36
+ - Use `zmr validate --json` before device runs.
37
+ - Generate JSON from higher-level tools when humans want a friendlier surface.
38
+ - Keep selectors stable and explicit: resource ids or accessibility identifiers
39
+ first, labels/content descriptions second, text third.
40
+
41
+ ## Human-Friendly Layer
42
+
43
+ JSON should stay the canonical machine contract. A friendlier authoring layer
44
+ can come later as a compiler to JSON, not as a second runtime format.
45
+
46
+ ## Roadmap
47
+
48
+ The likely production shape is:
49
+
50
+ 1. JSON remains the canonical machine contract.
51
+ 2. A friendlier authoring layer can compile to JSON.
52
+ 3. The compiler must preserve source locations so validation errors still point
53
+ to the human-authored file.
54
+ 4. The JSON Schema and protocol fixtures remain the compatibility boundary.
55
+
56
+ This keeps agents accurate while leaving room for nicer hand-authored test
57
+ files later.
@@ -0,0 +1,233 @@
1
+ # Install
2
+
3
+ ZMR is at present distributed as local release archives built by `scripts/build-release.sh`.
4
+
5
+ ## Build From Source
6
+
7
+ ```bash
8
+ git clone <repo-url> zig-mobile-runner
9
+ cd zig-mobile-runner
10
+ zig test src/main.zig -target aarch64-macos.15.0
11
+ zig build-exe src/main.zig -target aarch64-macos.15.0 -O ReleaseSafe -femit-bin=zig-out/bin/zmr
12
+ ./zig-out/bin/zmr version
13
+ ```
14
+
15
+ On this macOS 26 host, Zig `0.15.2` at present needs the explicit `aarch64-macos.15.0` target. Normal Zig environments can also use:
16
+
17
+ ```bash
18
+ zig build test
19
+ zig build
20
+ ```
21
+
22
+ ## Local Release Archive
23
+
24
+ ```bash
25
+ ./scripts/build-release.sh
26
+ tar -xzf dist/zmr-0.1.0-aarch64-macos.15.0.tar.gz -C /tmp
27
+ /tmp/zmr-0.1.0-aarch64-macos.15.0/zmr version
28
+ ```
29
+
30
+ Verify checksums:
31
+
32
+ ```bash
33
+ cd dist
34
+ shasum -a 256 -c SHA256SUMS
35
+ ```
36
+
37
+ Maintainers can run the stricter release verifier after building:
38
+
39
+ ```bash
40
+ ./scripts/verify-release-artifacts.sh
41
+ ```
42
+
43
+ It verifies each checksum entry and requires the archives, SBOM, notices,
44
+ Homebrew formula, and `RELEASE_MANIFEST.json` to be present in `SHA256SUMS`.
45
+ It also checks that manifest artifact sizes and SHA-256 digests match the files
46
+ in `dist/`.
47
+
48
+ Maintainers publishing macOS archives can sign and notarize them after building
49
+ and before uploading release assets:
50
+
51
+ ```bash
52
+ ./scripts/sign-macos-release.sh --identity "Developer ID Application: Example"
53
+ ./scripts/notarize-macos-release.sh --keychain-profile "zmr-notary"
54
+ ./scripts/verify-release-artifacts.sh
55
+ ```
56
+
57
+ The signing helper extracts each macOS tarball, signs the `zmr` binary with
58
+ hardened runtime, verifies the signature, rebuilds the tarball, refreshes the
59
+ Homebrew formula checksums, and regenerates `SHA256SUMS`. Use `--dry-run` to
60
+ inspect which archives would be signed.
61
+
62
+ The notarization helper packages each signed macOS archive for `xcrun
63
+ notarytool submit --wait`, writes JSON receipts under `dist/notarization/`,
64
+ refreshes `RELEASE_MANIFEST.json`, and regenerates `SHA256SUMS`. It accepts
65
+ either `--keychain-profile <profile>` or explicit `--apple-id`, `--team-id`,
66
+ and `--password` credentials.
67
+
68
+ Release metadata is written alongside the archives:
69
+
70
+ - `SBOM.spdx.json`: SPDX 2.3 software bill of materials for the release.
71
+ - `THIRD_PARTY_NOTICES.md`: dependency and license report.
72
+ - `homebrew/zmr.rb`: generated Homebrew formula with per-platform archive
73
+ URLs and SHA-256 checksums.
74
+ - `RELEASE_MANIFEST.json`: machine-readable release artifact inventory with
75
+ paths, types, sizes, and SHA-256 digests.
76
+ - `zig-mobile-runner-*.tgz`: npm package tarball when `npm run pack:npm` has
77
+ been run.
78
+ - `notarization/*.notary.json`: optional Apple notarization receipts when
79
+ `scripts/notarize-macos-release.sh` has been run.
80
+
81
+ All release metadata files and generated package tarballs are included in
82
+ `SHA256SUMS`.
83
+
84
+ ## npm Package
85
+
86
+ `npm run pack:npm` builds release archives, copies the platform binaries into
87
+ `prebuilds/`, writes `dist/zig-mobile-runner-*.tgz`, and refreshes
88
+ `RELEASE_MANIFEST.json` plus `SHA256SUMS` so the tarball is covered by the same
89
+ integrity checks as native archives. The tagged release workflow uploads that
90
+ tarball with the GitHub release assets, includes it in artifact attestation, and
91
+ runs:
92
+
93
+ ```bash
94
+ npm publish dist/zig-mobile-runner-*.tgz --provenance --access public
95
+ ```
96
+
97
+ The publish step is skipped unless `NPM_TOKEN` is configured for the repository.
98
+
99
+ ## Homebrew Formula
100
+
101
+ `scripts/build-release.sh` generates a formula under `dist/homebrew/zmr.rb`.
102
+ Tagged releases upload that file with the release assets. For a local release
103
+ build:
104
+
105
+ ```bash
106
+ brew install --build-from-source ./dist/homebrew/zmr.rb
107
+ zmr version
108
+ ```
109
+
110
+ For an external tap, copy the generated formula into the tap after confirming
111
+ the `url` values point at the final GitHub release asset location.
112
+
113
+ ## First Run
114
+
115
+ ```bash
116
+ zmr doctor
117
+ zmr init zmr-scenario.json --app-id com.example.mobiletest
118
+ zmr init --app --json --dir . --app-id com.example.mobiletest
119
+ zmr doctor --strict --json --config .zmr/config.json
120
+ zmr validate examples/demo-fake.json
121
+ ./scripts/demo.sh
122
+ ```
123
+
124
+ ## npm Install
125
+
126
+ Inside a mobile app repo:
127
+
128
+ ```bash
129
+ npm install --save-dev zig-mobile-runner
130
+ npx zmr-wizard --app-id com.example.mobiletest --package-json
131
+ npx zmr doctor --strict --json --config .zmr/config.json
132
+ npx zmr-device-matrix --matrix .zmr/device-matrix.json --trace-root traces/zmr-matrix
133
+ ```
134
+
135
+ The npm package exposes the app-facing CLI wrapper, setup wizard, benchmark
136
+ helpers, matrix runner, pilot gate, shim installers, public demo generators,
137
+ release-readiness checker, schemas, examples, reference clients, and the
138
+ packaged agent skill. Common app-local commands are:
139
+
140
+ ```bash
141
+ npx zmr-wizard --app-id com.example.mobiletest --android --ios --package-json
142
+ npx zmr-install-android-shim --app-root . --test-package com.example.mobiletest.test
143
+ npx zmr-install-ios-shim --app-root . --scheme SampleUITests --bundle-id com.example.mobiletest
144
+ npm run zmr:serve
145
+ npm run zmr:mcp
146
+ npx zmr-pilot-gate --android --ios --android-app-root . --android-app-id com.example.mobiletest --android-device emulator-5554 --ios-app-root . --ios-app-path ./build/Debug-iphonesimulator/Sample.app --ios-app-id com.example.mobiletest --ios-device booted --runs 20 --min-pass-rate 100 --max-failures 0 --evidence-out traces/zmr-pilots/evidence.jsonl
147
+ ```
148
+
149
+ See [docs/npm.md](npm.md) for the full npm binary list, binary resolution,
150
+ app-local `.zmr/` setup, and package publishing details.
151
+ See [config.md](config.md) for `.zmr/config.json` defaults and CLI override precedence.
152
+
153
+ ## App Codebase Integration
154
+
155
+ Use the runner from a separate checkout and point it at app build artifacts:
156
+
157
+ ```bash
158
+ /path/to/zig-mobile-runner/scripts/run-android-pilot.sh \
159
+ --app-root /path/to/mobile-app \
160
+ --app-id com.example.mobiletest \
161
+ --device emulator-5554
162
+
163
+ /path/to/zig-mobile-runner/scripts/run-ios-pilot.sh \
164
+ --app-root /path/to/mobile-app \
165
+ --app-path /path/to/mobile-app/build/Debug-iphonesimulator/Sample.app \
166
+ --app-id com.example.mobiletest \
167
+ --device booted
168
+ ```
169
+
170
+ See [app-integration.md](app-integration.md) for the expected app-side test surface.
171
+
172
+ ## Android Requirements
173
+
174
+ - Android SDK platform tools with `adb` on `PATH`.
175
+ - A booted emulator or connected device for real Android runs.
176
+ - Test app installed with the expected app id, for example `com.example.mobiletest`.
177
+
178
+ ## iOS Requirements
179
+
180
+ - Xcode command line tools with `xcrun` on `PATH`.
181
+ - A booted simulator for real simulator runs, or a paired physical device
182
+ identifier from `zmr devices --json --platform ios --ios-device-type physical`
183
+ for physical-device lifecycle and selector runs.
184
+ - `zmr doctor --json` reports simulator readiness as `ios-simulators` and
185
+ paired-device readiness as `ios-physical-devices`, so setup scripts can fail
186
+ fast before install or XCTest work starts.
187
+ - A simulator-built `iphonesimulator` `.app` for simulator launch/open-link
188
+ smoke scenarios. A signed device `.ipa` is not simulator-compatible; run it
189
+ with `--ios-device-type physical` and a real physical device identifier.
190
+ - Physical-device installs require a signed `.app` or `.ipa` accepted by
191
+ `xcrun devicectl`.
192
+ - Optional app-provided XCTest/XCUIAutomation shim command for hierarchy,
193
+ selector actions, and native selector waits. Pass it with `--ios-shim <path>`
194
+ or set `tools.iosShimPath` in `.zmr/config.json`.
195
+
196
+ To scaffold the shim command and XCTest source into an app repo:
197
+
198
+ ```bash
199
+ npx zmr-install-ios-shim \
200
+ --app-root . \
201
+ --scheme SampleUITests \
202
+ --test-target SampleUITests \
203
+ --workspace ios/Sample.xcworkspace \
204
+ --app-target SampleApp \
205
+ --derived-data-path ios/build/ZMRDerivedData \
206
+ --bundle-id com.example.mobiletest \
207
+ --patch-xcodeproj
208
+ ```
209
+
210
+ Run `.zmr/ensure-ios-shim-target.sh` to create/update the UI test target, add
211
+ the generated Swift files, configure `.zmr/ZMRShimUITests-Info.plist`, and write
212
+ a shared scheme. The helper uses the Ruby `xcodeproj` gem. For workspace input,
213
+ it resolves the referenced `.xcodeproj` automatically when there is one project,
214
+ or when exactly one project contains `--app-target`, or when `--bundle-id` disambiguates
215
+ matching app targets. Use `--project ios/Sample.xcodeproj`
216
+ instead of `--workspace` for still-ambiguous multi-project workspaces or
217
+ project-only apps.
218
+
219
+ The installer also patches or creates `.zmr/config.json` with
220
+ `tools.iosShimPath: "./.zmr/ios-shim"`, so `zmr run`, `zmr serve`, and
221
+ `zmr doctor` can discover the shim from app-local config without repeating the
222
+ flag on every command.
223
+
224
+ The generated `.zmr/ios-shim` caches `build-for-testing` output under
225
+ `.zmr/ios-shim-state/` and uses `test-without-building` for selector commands.
226
+ Set `ZMR_IOS_SHIM_FORCE_REBUILD=1` after app-side target changes, or
227
+ `ZMR_IOS_SHIM_ONESHOT=1` for the slower one-command-per-XCTest fallback when
228
+ debugging Xcode wiring.
229
+
230
+ For reliable real simulator and physical-device runs, execute ZMR from a normal
231
+ terminal or CI worker with access to Xcode, CoreSimulator, and device caches.
232
+ Restricted sandboxes can block Xcode log/cache access and make `xcodebuild` or
233
+ `simctl` report misleading setup errors.
@@ -0,0 +1,70 @@
1
+ # Market Positioning
2
+
3
+ ZMR is a developer-preview runner. It should compete by being the best local
4
+ mobile automation control plane for AI agents, not by pretending to be a mature
5
+ drop-in replacement for every existing runner on day one.
6
+
7
+ ## What The Market Rewards
8
+
9
+ The existing market rewards frameworks that feel easy to start, expose stable
10
+ selectors and waits, produce useful reports, and run well in CI. Some tools lean
11
+ on app internals, some use simple flow files, and some emphasize hosted device
12
+ coverage. ZMR should avoid copying those surfaces directly. Its opportunity is a
13
+ mobile-native control plane: device lifecycle, app install/launch/clear state,
14
+ accessibility trees, selector actions, logs, screenshots, trace bundles, and
15
+ physical-device workflows.
16
+
17
+ ## ZMR Position
18
+
19
+ ZMR should lead with:
20
+
21
+ - **Agent-native protocol:** structured snapshots and actions over JSON-RPC,
22
+ plus an MCP stdio server for agent runtimes.
23
+ - **Semantic mobile tree:** normalized roles, names, selectors, bounds, and
24
+ recommended actions so agents do not parse platform-specific hierarchy dumps.
25
+ - **Trace-first reliability:** every action produces evidence agents and humans
26
+ can inspect.
27
+ - **Small deterministic core:** Zig runner, explicit adapters, schema-validated
28
+ inputs, stable CLI JSON.
29
+ - **App-local setup:** `.zmr/` owns config, scenarios, shims, and private traces.
30
+ - **Language-neutral clients:** TypeScript, Python, Go, and Rust can all drive
31
+ the same protocol.
32
+
33
+ ## Where ZMR Is Already Strong
34
+
35
+ | Area | ZMR advantage |
36
+ | --- | --- |
37
+ | AI agent integration | First-class JSON-RPC, MCP tools, semantic snapshots, live trace events, schemas, agent guide, packaged skill |
38
+ | Failure diagnostics | Trace bundles, snapshot replay, UI tree, screenshots, logs, `zmr explain` |
39
+ | Language neutrality | Protocol clients across multiple languages |
40
+ | Local release discipline | Release gate, coverage gate, artifacts, SBOM, checksums, attestation |
41
+ | App-local privacy | `.zmr/` config and redacted trace export |
42
+ | Mobile focus versus browser engines | Native Android/iOS device lifecycle and accessibility semantics instead of CDP-only web primitives |
43
+
44
+ ## Where ZMR Must Catch Up
45
+
46
+ | Area | Gap |
47
+ | --- | --- |
48
+ | npm distribution | Tarball exists in GitHub release, registry publish still pending |
49
+ | Android proof | Public generic Android demo wrapper exists; repeated emulator proof and app-local pilots still need published release evidence |
50
+ | iOS scale | Simulator demo passes, but repeated-run evidence should be published |
51
+ | Physical iOS | Local lifecycle and selector support exist through `devicectl` plus the XCTest shim; screenshots use the shim, physical log capture still needs hardening |
52
+ | Cloud | Not supported yet |
53
+ | Human DSL | JSON is reliable for agents; a friendlier authoring layer should compile to JSON |
54
+ | Brand surface | README is now concise; a docs/landing site should follow after npm publish |
55
+
56
+ ## Website Recommendation
57
+
58
+ For `0.1.x`, GitHub README plus release assets are enough. After npm publish,
59
+ create a docs site with:
60
+
61
+ - homepage: value proposition, install, demo GIF/video, trace viewer screenshot
62
+ - docs: install, `.zmr/`, scenarios, JSON-RPC, clients, shims, privacy
63
+ - compare: honest capability matrix
64
+ - examples: Android app, iOS app, agent session
65
+ - releases: checksums, SBOM, artifact verification
66
+
67
+ Do not create a marketing-only site before the npm package and repeated device
68
+ evidence are in place. The strongest market fit is a clean first-run path that
69
+ actually works.
70
+