zeno-mobile-runner 0.1.2 → 0.1.8

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 (89) hide show
  1. package/CHANGELOG.md +162 -3
  2. package/FEATURES.md +50 -7
  3. package/README.md +133 -7
  4. package/build.zig.zon +3 -3
  5. package/clients/README.md +60 -3
  6. package/clients/go/README.md +12 -0
  7. package/clients/go/zmr/client.go +142 -0
  8. package/clients/kotlin/README.md +18 -1
  9. package/clients/kotlin/build.gradle.kts +1 -1
  10. package/clients/kotlin/src/main/kotlin/dev/zmr/ZmrClient.kt +76 -1
  11. package/clients/python/README.md +19 -0
  12. package/clients/python/pyproject.toml +1 -1
  13. package/clients/python/zmr_client.py +33 -0
  14. package/clients/rust/Cargo.lock +1 -1
  15. package/clients/rust/Cargo.toml +1 -1
  16. package/clients/rust/README.md +25 -1
  17. package/clients/rust/src/lib.rs +201 -0
  18. package/clients/swift/README.md +18 -0
  19. package/clients/swift/Sources/ZMRClient/ZMRClient.swift +82 -0
  20. package/clients/typescript/README.md +16 -0
  21. package/clients/typescript/index.d.ts +12 -0
  22. package/clients/typescript/index.mjs +16 -0
  23. package/clients/typescript/package.json +1 -1
  24. package/docs/agent-discovery.md +202 -0
  25. package/docs/ai-agents.md +87 -6
  26. package/docs/benchmarking.md +10 -3
  27. package/docs/clients.md +10 -6
  28. package/docs/demo.md +4 -0
  29. package/docs/expo-smoke.md +79 -0
  30. package/docs/install.md +3 -2
  31. package/docs/npm.md +58 -4
  32. package/docs/production-readiness.md +123 -0
  33. package/docs/protocol-fixtures/core-session.responses.jsonl +1 -1
  34. package/docs/protocol.md +215 -16
  35. package/docs/scenario-authoring.md +3 -0
  36. package/docs/troubleshooting.md +1 -1
  37. package/npm/agents.mjs +16 -0
  38. package/npm/build-zmr.mjs +1 -1
  39. package/npm/commands.mjs +9 -5
  40. package/npm/postinstall.mjs +28 -2
  41. package/npm/verify-publish.mjs +36 -0
  42. package/package.json +2 -1
  43. package/prebuilds/darwin-arm64/zmr +0 -0
  44. package/prebuilds/darwin-x64/zmr +0 -0
  45. package/prebuilds/linux-arm64/zmr +0 -0
  46. package/prebuilds/linux-x64/zmr +0 -0
  47. package/schemas/README.md +4 -0
  48. package/schemas/discover-output.schema.json +83 -0
  49. package/schemas/draft-output.schema.json +58 -0
  50. package/schemas/explore-output.schema.json +94 -0
  51. package/schemas/inspect-output.schema.json +88 -0
  52. package/schemas/run-output.schema.json +2 -0
  53. package/scripts/install-ios-shim.sh +79 -14
  54. package/scripts/release-readiness.py +43 -0
  55. package/scripts/run-android-pilot.sh +35 -9
  56. package/scripts/run-ios-pilot.sh +11 -4
  57. package/shims/ios/ZMRShim.swift +3 -0
  58. package/shims/ios/ZMRShimUITestCase.swift +41 -11
  59. package/skills/zmr-mobile-testing/SKILL.md +28 -3
  60. package/src/cli_discover.zig +239 -0
  61. package/src/cli_draft.zig +924 -0
  62. package/src/cli_explore.zig +136 -0
  63. package/src/cli_inspect.zig +310 -0
  64. package/src/cli_output.zig +26 -2
  65. package/src/cli_run.zig +28 -0
  66. package/src/cli_trace.zig +8 -0
  67. package/src/errors.zig +9 -0
  68. package/src/ios.zig +11 -4
  69. package/src/ios_lifecycle.zig +36 -0
  70. package/src/ios_shim.zig +42 -0
  71. package/src/json_rpc_methods.zig +85 -11
  72. package/src/json_rpc_params.zig +8 -0
  73. package/src/json_rpc_protocol.zig +1 -1
  74. package/src/json_rpc_trace.zig +112 -0
  75. package/src/main.zig +24 -2
  76. package/src/mcp.zig +209 -6
  77. package/src/mcp_protocol.zig +29 -1
  78. package/src/mcp_trace.zig +126 -4
  79. package/src/report.zig +186 -0
  80. package/src/runner.zig +26 -4
  81. package/src/runner_actions.zig +10 -0
  82. package/src/runner_diagnostics.zig +31 -1
  83. package/src/runner_events.zig +70 -7
  84. package/src/runner_native.zig +17 -1
  85. package/src/runner_waits.zig +82 -19
  86. package/src/scaffold.zig +28 -12
  87. package/src/scenario.zig +32 -4
  88. package/src/schema_registry.zig +4 -0
  89. package/src/version.zig +1 -1
@@ -0,0 +1,79 @@
1
+ # Expo Smoke Test
2
+
3
+ This is the quickest public smoke path for an Expo app. It proves that the npm
4
+ package installs, the wizard scaffolds a scenario, ZMR can launch an iOS app,
5
+ and the runner can produce screenshots, traces, HTML reports, JUnit XML, and
6
+ redacted trace bundles.
7
+
8
+ Run the flow below on a local iOS simulator before treating a specific app build
9
+ as validated.
10
+
11
+ ```bash
12
+ npx create-expo-app@latest /tmp/zmr-expo-smoke --template blank --yes
13
+ cd /tmp/zmr-expo-smoke
14
+ npm install --save-dev zeno-mobile-runner
15
+
16
+ npx zmr-wizard --yes --dir . \
17
+ --app-id com.example.zenoexposmoke \
18
+ --ios \
19
+ --package-json
20
+ ```
21
+
22
+ Boot a simulator, then build and launch the app:
23
+
24
+ ```bash
25
+ xcrun simctl boot <simulator-udid>
26
+ npx expo run:ios --device <simulator-name>
27
+ ```
28
+
29
+ Run the generated ZMR scenario:
30
+
31
+ ```bash
32
+ npx zmr run .zmr/ios-smoke.json \
33
+ --platform ios \
34
+ --device booted \
35
+ --trace-dir traces/zmr-ios \
36
+ --json
37
+
38
+ npx zmr report traces/zmr-ios --out traces/zmr-ios/report.html --junit traces/zmr-ios/junit.xml
39
+ npx zmr export traces/zmr-ios --out traces/zmr-ios-redacted.zmrtrace --redact
40
+ ```
41
+
42
+ Expected result shape:
43
+
44
+ ```json
45
+ {
46
+ "ok": true,
47
+ "status": "passed",
48
+ "scenario": "iOS smoke",
49
+ "appId": "com.example.zenoexposmoke",
50
+ "traceDir": "traces/zmr-ios",
51
+ "eventCount": 8,
52
+ "snapshotCount": 2,
53
+ "partialFailureCount": 0
54
+ }
55
+ ```
56
+
57
+ This smoke validates the platform-level loop: app launch, health check,
58
+ screenshot capture, trace collection, HTML/JUnit report generation, and
59
+ redacted export. For selector-grade React Native or Expo assertions on iOS, add
60
+ the XCTest shim described in [app integration](app-integration.md).
61
+
62
+ Android follows the same pattern with a connected emulator or device:
63
+
64
+ ```bash
65
+ npx zmr-wizard --yes --dir . \
66
+ --app-id com.example.zenoexposmoke \
67
+ --android \
68
+ --package-json
69
+
70
+ npx zmr run .zmr/android-smoke.json \
71
+ --platform android \
72
+ --device emulator-5554 \
73
+ --trace-dir traces/zmr-android \
74
+ --json
75
+ ```
76
+
77
+ Do not commit traces, screenshots, bundle identifiers, private app names, or
78
+ credentials from a real product app. Use `zmr export --redact`, and add
79
+ `--omit-screenshots` when visual artifacts may contain sensitive data.
package/docs/install.md CHANGED
@@ -54,8 +54,9 @@ zig build-exe src/main.zig -target aarch64-macos.15.0 -O ReleaseSafe -femit-bin=
54
54
  ./zig-out/bin/zmr version
55
55
  ```
56
56
 
57
- On macOS hosts where Zig can infer the target, `zig build test` and `zig build`
58
- are also valid.
57
+ On hosts where Zig can infer the target and locate the system SDK, `zig build`
58
+ can also build the binary. The explicit target form above is the supported
59
+ verification path used by CI and release gates.
59
60
 
60
61
  ## First Run Without A Device
61
62
 
package/docs/npm.md CHANGED
@@ -68,6 +68,8 @@ This creates:
68
68
  `.zmr/AGENTS.md` gives AI agents an app-local operating note with strict
69
69
  doctor/validate commands, schema discovery, direct `zmr run` smoke commands,
70
70
  JSON-RPC and MCP startup commands, selector guidance, the exact
71
+ `zmr discover --from-trace traces/zmr-agent --out .zmr/discovered/replay-smoke.json --include-actions --validate --json`
72
+ trace-to-test command,
71
73
  `zmr explain traces/zmr-agent --json` failure-triage command, the exact
72
74
  `zmr export traces/zmr-agent --out traces/zmr-agent-redacted.zmrtrace --redact`
73
75
  redacted trace export command.
@@ -91,12 +93,12 @@ Add app-local scripts:
91
93
  "zmr:schemas": "zmr schemas --json",
92
94
  "zmr:validate": "zmr validate --json .zmr/android-smoke.json && zmr validate --json .zmr/ios-smoke.json",
93
95
  "zmr:android": "zmr run .zmr/android-smoke.json --device emulator-5554 --trace-dir traces/zmr-android",
94
- "zmr:android:report": "zmr report traces/zmr-android --out traces/zmr-android/report.html",
95
- "zmr:android:reliability": "export ZMR_BIN=\"${ZMR_BIN:-zmr}\"; zmr-benchmark --zmr .zmr/android-smoke.json --device emulator-5554 --app-id com.example.mobiletest --runs 20 --trace-root traces/zmr-android-reliability --min-pass-rate 100 --max-failures 0 --max-p95-ms 30000 && \"$ZMR_BIN\" report traces/zmr-android-reliability --out traces/zmr-android-reliability/report.html",
96
+ "zmr:android:report": "zmr report traces/zmr-android --out traces/zmr-android/report.html --junit traces/zmr-android/junit.xml",
97
+ "zmr:android:reliability": "export ZMR_BIN=\"${ZMR_BIN:-zmr}\"; zmr-benchmark --zmr .zmr/android-smoke.json --device emulator-5554 --app-id com.example.mobiletest --runs 20 --trace-root traces/zmr-android-reliability --min-pass-rate 100 --max-failures 0 --max-p95-ms 30000 && \"$ZMR_BIN\" report traces/zmr-android-reliability --out traces/zmr-android-reliability/report.html --junit traces/zmr-android-reliability/junit.xml",
96
98
  "zmr:matrix": "ZMR_BIN=${ZMR_BIN:-zmr} zmr-device-matrix --matrix .zmr/device-matrix.json --trace-root traces/zmr-matrix --min-pass-rate 100 --max-failures 0",
97
99
  "zmr:ios": "zmr run .zmr/ios-smoke.json --platform ios --device booted --trace-dir traces/zmr-ios",
98
- "zmr:ios:report": "zmr report traces/zmr-ios --out traces/zmr-ios/report.html",
99
- "zmr:ios:reliability": "export ZMR_BIN=\"${ZMR_BIN:-zmr}\"; zmr-benchmark --zmr .zmr/ios-smoke.json --platform ios --device booted --app-id com.example.mobiletest --xcrun xcrun --runs 20 --trace-root traces/zmr-ios-reliability --min-pass-rate 100 --max-failures 0 --max-p95-ms 45000 && \"$ZMR_BIN\" report traces/zmr-ios-reliability --out traces/zmr-ios-reliability/report.html",
100
+ "zmr:ios:report": "zmr report traces/zmr-ios --out traces/zmr-ios/report.html --junit traces/zmr-ios/junit.xml",
101
+ "zmr:ios:reliability": "export ZMR_BIN=\"${ZMR_BIN:-zmr}\"; zmr-benchmark --zmr .zmr/ios-smoke.json --platform ios --device booted --app-id com.example.mobiletest --xcrun xcrun --runs 20 --trace-root traces/zmr-ios-reliability --min-pass-rate 100 --max-failures 0 --max-p95-ms 45000 && \"$ZMR_BIN\" report traces/zmr-ios-reliability --out traces/zmr-ios-reliability/report.html --junit traces/zmr-ios-reliability/junit.xml",
100
102
  "zmr:pilot": "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",
101
103
  "zmr:readiness": "zmr-release-readiness --evidence traces/zmr-pilots/evidence.jsonl --target production --json",
102
104
  "zmr:serve": "zmr serve --transport stdio --config .zmr/config.json --trace-dir traces/zmr-agent",
@@ -341,6 +343,58 @@ npm run pack:npm
341
343
 
342
344
  That command builds release binaries, copies them into `prebuilds/`, and runs `npm pack`.
343
345
 
346
+ Tagged GitHub releases publish through npm trusted publishing, not a long-lived
347
+ `NPM_TOKEN` secret. Configure the npm package trusted publisher before relying
348
+ on the tag workflow:
349
+
350
+ - Package: `zeno-mobile-runner`
351
+ - Provider: GitHub Actions
352
+ - Repository: `johnmikel/zeno-mobile-runner`
353
+ - Workflow file: `release.yml`
354
+
355
+ The release workflow already requests `id-token: write`, builds the npm tarball
356
+ from the tag, attests the generated release artifacts, uploads the GitHub
357
+ release assets, verifies exactly one local npm tarball exists under `./dist/`,
358
+ and then publishes that tarball with public access.
359
+
360
+ Trusted publishing requires a current npm runtime. The tag workflow uses Node
361
+ 24 so the npm CLI can exchange the GitHub Actions OIDC identity for publish
362
+ authorization.
363
+
364
+ ### Manual publish with passkey or 2FA
365
+
366
+ Use trusted publishing for normal tagged releases. If you need to publish a
367
+ verified local tarball manually, authenticate first:
368
+
369
+ ```bash
370
+ npm login --auth-type=web
371
+ npm whoami
372
+ ```
373
+
374
+ The browser/passkey step must finish before publishing. If `npm whoami` returns
375
+ `E401 Unauthorized`, the local machine is not authenticated and `npm publish`
376
+ will fail.
377
+
378
+ Build and verify the package before publishing:
379
+
380
+ ```bash
381
+ ./scripts/ci-gate.sh
382
+ npm pack --dry-run --json
383
+ npm run pack:npm
384
+ ```
385
+
386
+ Publish the generated tarball from `dist/`:
387
+
388
+ ```bash
389
+ npm publish ./dist/zeno-mobile-runner-<version>.tgz --access public
390
+ ```
391
+
392
+ If npm returns `E403` with a two-factor authentication message, the account or
393
+ organization requires either a current interactive 2FA challenge or a granular
394
+ automation token configured to bypass 2FA. For local passkey accounts, rerun
395
+ `npm login --auth-type=web`, complete the passkey challenge in the browser, and
396
+ confirm `npm whoami` before retrying the same `npm publish` command.
397
+
344
398
  ## Node API
345
399
 
346
400
  ```js
@@ -0,0 +1,123 @@
1
+ # Production Readiness
2
+
3
+ ZMR is a public developer preview. The npm package is live, release artifacts
4
+ are signed by GitHub release attestations, and local app teams can collect
5
+ repeatable Android, iOS simulator, and physical iOS evidence. ZMR should not be
6
+ called production-stable until the gates below are met and kept passing.
7
+
8
+ ## Current Release Standard
9
+
10
+ Every public release should satisfy:
11
+
12
+ - `bash tests/docs-readiness-test.sh`
13
+ - `bash tests/public-safety-test.sh`
14
+ - `npm test`
15
+ - `zig test src/test_harness.zig -target aarch64-macos.15.0`
16
+ - `./scripts/release-gate.sh`
17
+ - `npm run pack:npm`
18
+ - `./scripts/verify-release-artifacts.sh --dist dist`
19
+ - at least one trace or benchmark report rendered with `zmr report --junit`,
20
+ or a pilot wrapper run that produced both `report.html` and `junit.xml`
21
+ - a fresh npm install smoke:
22
+
23
+ ```bash
24
+ npm install --save-dev zeno-mobile-runner
25
+ npx zmr version --json
26
+ ```
27
+
28
+ Tagged releases are expected to build release archives, generate
29
+ `RELEASE_MANIFEST.json`, publish GitHub artifact attestations, upload release
30
+ assets, and publish the npm tarball through trusted publishing after the npm
31
+ package is configured with the `release.yml` trusted publisher.
32
+
33
+ CI runs retain `traces/`, `zig-cache/coverage/`, and `zig-out/bin/zmr` for 14
34
+ days when those files are produced. Tagged releases retain `dist/` as a
35
+ workflow artifact for 30 days in addition to GitHub release assets.
36
+
37
+ ## Product Gates Before 1.0
38
+
39
+ | Area | Required evidence | Current status |
40
+ | --- | --- | --- |
41
+ | Android emulator | 20-run pilot gate with zero failures and trace/report artifacts | Supported by `zmr-pilot-gate` and demo app |
42
+ | Android physical device | 20-run pilot gate on a real connected device | Supported by ADB flow; app teams must collect evidence |
43
+ | iOS simulator | 20-run pilot gate with XCTest shim selectors, screenshots, and reports | Supported by iOS demo and app-local shim |
44
+ | iOS physical device | 20-run pilot gate on a real trusted device | Supported for lifecycle and shim screenshots; needs repeated public evidence |
45
+ | 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
+ | Expo | Public smoke, dev-client scaffold, and iOS/Android run evidence | Basic iOS smoke is documented; repeated matrix evidence is still needed |
47
+ | Flutter | Platform-level Android/iOS smoke using semantics, deep links, and screenshots | Supported at platform level; widget-tree claims are intentionally out of scope |
48
+ | Agent workflows | MCP and JSON-RPC loop with semantic snapshots, typed actions, traces, redacted export, guarded trace exploration, and scenario validation | Supported and enforced by the `agent workflow smoke` readiness gate; `zmr explore` is review-first and trace-backed, and an unbounded autonomous crawler is not shipped |
49
+ | CI reporting | HTML reports plus JUnit XML artifacts from trace, benchmark, and pilot directories | Supported by `zmr report --junit` and pilot wrappers |
50
+ | Trace privacy | Redacted export path, denylist/allowlist controls, and public-safety tests | Supported and gated |
51
+ | Release supply chain | Trusted npm publish, GitHub artifact attestations, checksums, SBOM, and release manifest | Workflow is ready; npm trusted publisher must be configured in package settings |
52
+
53
+ ## Reliability Evidence
54
+
55
+ Use repeated app-local pilots before making app or device claims:
56
+
57
+ ```bash
58
+ zmr-pilot-gate \
59
+ --android \
60
+ --ios \
61
+ --android-app-root . \
62
+ --android-app-id com.example.mobiletest \
63
+ --android-device emulator-5554 \
64
+ --ios-app-root . \
65
+ --ios-app-path ./build/Debug-iphonesimulator/Sample.app \
66
+ --ios-app-id com.example.mobiletest \
67
+ --ios-device booted \
68
+ --ios-shim ./.zmr/ios-shim \
69
+ --runs 20 \
70
+ --min-pass-rate 100 \
71
+ --max-failures 0 \
72
+ --evidence-out traces/zmr-pilots/evidence.jsonl
73
+ ```
74
+
75
+ Then summarize readiness:
76
+
77
+ ```bash
78
+ zmr-release-readiness \
79
+ --evidence traces/zmr-pilots/evidence.jsonl \
80
+ --target production \
81
+ --json
82
+ ```
83
+
84
+ Keep the generated evidence in the app repository unless it is fully redacted
85
+ and safe to publish.
86
+
87
+ ## Agentic Standard
88
+
89
+ ZMR is agentic when an external agent can work from structured state instead of
90
+ screenscraping or guessing:
91
+
92
+ - `zmr doctor --json` explains setup state and remediation.
93
+ - `zmr schemas --json` exposes machine-readable contracts.
94
+ - `zmr validate --json` catches scenario mistakes before device runs.
95
+ - `zmr serve` exposes JSON-RPC for long-running sessions.
96
+ - `zmr mcp` exposes MCP tools for semantic snapshots, typed actions, and
97
+ assertion-grade checks.
98
+ - `zmr explain --json` summarizes failed traces.
99
+ - `zmr report --junit` emits CI-compatible test results from trace and
100
+ benchmark evidence.
101
+ - `zmr export --redact` produces shareable trace bundles.
102
+ - `zmr-release-readiness --target production` requires the `agent workflow
103
+ smoke` gate, satisfied by a passed `./scripts/release-gate.sh` row or
104
+ structured evidence for MCP, JSON-RPC, semantic snapshots, typed actions,
105
+ trace events, trace explanation, trace discovery/exploration, scenario
106
+ validation, and redacted export.
107
+
108
+ The safe discovery pattern is still external-agent-first: observe with
109
+ `semantic_snapshot`, choose one typed action, record successful steps into a
110
+ candidate scenario, validate it, rerun it deterministically, and require human
111
+ review before committing generated tests.
112
+
113
+ ## Claims Policy
114
+
115
+ - Claim Android and iOS app-level support only for flows that pass local pilot
116
+ evidence on the target device class.
117
+ - Claim React Native and Expo support through app-level lifecycle, deep links,
118
+ accessibility labels, selectors, screenshots, traces, and reports.
119
+ - Claim Flutter support at the Android/iOS app level when the app exposes stable
120
+ semantics, labels, ids, or deep links.
121
+ - Do not claim Flutter widget-tree inspection, Dart state inspection, managed
122
+ device-farm coverage, or a built-in autonomous test writer until those
123
+ features exist and have public evidence.
@@ -1,4 +1,4 @@
1
- {"jsonrpc":"2.0","id":1,"result":{"name":"zmr","version":"0.1.2","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","trace.events","trace.export"]}}
1
+ {"jsonrpc":"2.0","id":1,"result":{"name":"zmr","version":"0.1.8","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}