zeno-mobile-runner 0.1.3 → 0.2.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 (115) hide show
  1. package/CHANGELOG.md +192 -2
  2. package/FEATURES.md +50 -7
  3. package/README.md +168 -120
  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 +151 -22
  25. package/docs/ai-agents.md +99 -11
  26. package/docs/benchmarking.md +49 -3
  27. package/docs/benchmarks/2026-06-09-android-workflow.md +73 -0
  28. package/docs/benchmarks/2026-06-09-android-workflow.results.jsonl +20 -0
  29. package/docs/benchmarks/2026-06-09-framework-baseline-status.md +32 -0
  30. package/docs/benchmarks/2026-06-09-ios-appium-comparison.md +115 -0
  31. package/docs/benchmarks/2026-06-09-ios-appium-comparison.results.jsonl +40 -0
  32. package/docs/benchmarks/2026-06-09-ios-demo.md +90 -0
  33. package/docs/benchmarks/2026-06-09-ios-demo.results.jsonl +20 -0
  34. package/docs/benchmarks/2026-06-09-ios-maestro-comparison.md +128 -0
  35. package/docs/benchmarks/2026-06-09-ios-maestro-comparison.results.jsonl +40 -0
  36. package/docs/benchmarks/2026-06-09-ios-workflow-comparison.md +143 -0
  37. package/docs/benchmarks/2026-06-09-ios-workflow-comparison.results.jsonl +40 -0
  38. package/docs/benchmarks/2026-06-09-ios-xctest-floor.md +106 -0
  39. package/docs/benchmarks/2026-06-09-ios-xctest-floor.results.jsonl +40 -0
  40. package/docs/benchmarks/README.md +36 -0
  41. package/docs/benchmarks/benchmark-lab-v1.json +155 -0
  42. package/docs/benchmarks/benchmark-lab-v1.md +95 -0
  43. package/docs/clients.md +26 -6
  44. package/docs/demo.md +40 -1
  45. package/docs/expo-smoke.md +8 -8
  46. package/docs/frameworks.md +10 -0
  47. package/docs/install.md +3 -2
  48. package/docs/npm.md +100 -4
  49. package/docs/production-readiness.md +123 -0
  50. package/docs/protocol-fixtures/core-session.responses.jsonl +1 -1
  51. package/docs/protocol.md +215 -16
  52. package/docs/scenario-authoring.md +18 -0
  53. package/docs/trace-privacy.md +9 -0
  54. package/docs/troubleshooting.md +7 -1
  55. package/examples/android-workflow.json +79 -0
  56. package/examples/ios-shim-workflow.json +79 -0
  57. package/examples/react-native-expo-workflow.json +75 -0
  58. package/npm/agents.mjs +16 -0
  59. package/npm/commands.mjs +9 -5
  60. package/package.json +6 -1
  61. package/prebuilds/darwin-arm64/zmr +0 -0
  62. package/prebuilds/darwin-x64/zmr +0 -0
  63. package/prebuilds/linux-arm64/zmr +0 -0
  64. package/prebuilds/linux-x64/zmr +0 -0
  65. package/schemas/README.md +4 -0
  66. package/schemas/discover-output.schema.json +83 -0
  67. package/schemas/draft-output.schema.json +58 -0
  68. package/schemas/explore-output.schema.json +94 -0
  69. package/schemas/inspect-output.schema.json +88 -0
  70. package/schemas/run-output.schema.json +2 -0
  71. package/scripts/benchmark-lab.py +253 -0
  72. package/scripts/create-android-demo-app.sh +324 -29
  73. package/scripts/create-ios-demo-app.sh +174 -7
  74. package/scripts/create-react-native-expo-demo-app.sh +727 -0
  75. package/scripts/demo.sh +3 -0
  76. package/scripts/install-ios-shim.sh +2 -2
  77. package/scripts/release-readiness.py +43 -0
  78. package/scripts/run-android-pilot.sh +35 -9
  79. package/scripts/run-ios-pilot.sh +11 -4
  80. package/shims/ios/ZMRShim.swift +10 -0
  81. package/shims/ios/ZMRShimUITestCase.swift +42 -0
  82. package/shims/ios/protocol.md +1 -0
  83. package/skills/zmr-mobile-testing/SKILL.md +28 -3
  84. package/src/cli_discover.zig +239 -0
  85. package/src/cli_draft.zig +924 -0
  86. package/src/cli_explore.zig +136 -0
  87. package/src/cli_import.zig +31 -15
  88. package/src/cli_inspect.zig +310 -0
  89. package/src/cli_output.zig +26 -2
  90. package/src/cli_run.zig +28 -0
  91. package/src/cli_trace.zig +45 -15
  92. package/src/cli_validate.zig +12 -6
  93. package/src/errors.zig +9 -0
  94. package/src/ios.zig +49 -12
  95. package/src/ios_shim.zig +36 -2
  96. package/src/json_rpc_methods.zig +85 -11
  97. package/src/json_rpc_params.zig +8 -0
  98. package/src/json_rpc_protocol.zig +1 -1
  99. package/src/json_rpc_trace.zig +112 -0
  100. package/src/main.zig +27 -2
  101. package/src/mcp.zig +209 -6
  102. package/src/mcp_protocol.zig +29 -1
  103. package/src/mcp_trace.zig +126 -4
  104. package/src/report.zig +186 -0
  105. package/src/runner.zig +26 -4
  106. package/src/runner_actions.zig +10 -0
  107. package/src/runner_diagnostics.zig +31 -1
  108. package/src/runner_events.zig +70 -7
  109. package/src/runner_native.zig +17 -1
  110. package/src/runner_waits.zig +82 -19
  111. package/src/scaffold.zig +28 -12
  112. package/src/scenario.zig +32 -4
  113. package/src/schema_registry.zig +4 -0
  114. package/src/version.zig +1 -1
  115. package/viewer/app.js +23 -3
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "ZMR React Native Expo workflow demo",
3
+ "appId": "com.example.mobiletest",
4
+ "steps": [
5
+ { "action": "openLink", "url": "zenoexpodemo://benchmark" },
6
+ {
7
+ "action": "waitVisible",
8
+ "selector": { "text": "Zeno Expo Demo" },
9
+ "timeoutMs": 30000
10
+ },
11
+ {
12
+ "action": "tap",
13
+ "selector": { "contentDesc": "continue_button" }
14
+ },
15
+ {
16
+ "action": "waitVisible",
17
+ "selector": { "text": "Profile" },
18
+ "timeoutMs": 10000
19
+ },
20
+ {
21
+ "action": "typeText",
22
+ "selector": { "contentDesc": "profile_name_input" },
23
+ "text": "Riley"
24
+ },
25
+ {
26
+ "action": "typeText",
27
+ "selector": { "contentDesc": "profile_email_input" },
28
+ "text": "riley@example.test"
29
+ },
30
+ { "action": "hideKeyboard" },
31
+ {
32
+ "action": "tap",
33
+ "selector": { "contentDesc": "save_profile_button" }
34
+ },
35
+ {
36
+ "action": "waitVisible",
37
+ "selector": { "text": "Catalog" },
38
+ "timeoutMs": 10000
39
+ },
40
+ {
41
+ "action": "scrollUntilVisible",
42
+ "selector": { "contentDesc": "catalog_item_north_ridge_pack" },
43
+ "direction": "down",
44
+ "timeoutMs": 10000
45
+ },
46
+ {
47
+ "action": "tap",
48
+ "selector": { "contentDesc": "catalog_item_north_ridge_pack" }
49
+ },
50
+ {
51
+ "action": "waitVisible",
52
+ "selector": { "text": "North Ridge Pack" },
53
+ "timeoutMs": 10000
54
+ },
55
+ {
56
+ "action": "tap",
57
+ "selector": { "contentDesc": "detail_save_button" }
58
+ },
59
+ {
60
+ "action": "waitVisible",
61
+ "selector": { "text": "Saved North Ridge Pack" },
62
+ "timeoutMs": 10000
63
+ },
64
+ {
65
+ "action": "tap",
66
+ "selector": { "contentDesc": "review_button" }
67
+ },
68
+ {
69
+ "action": "assertVisible",
70
+ "selector": { "text": "Workflow complete" },
71
+ "timeoutMs": 10000
72
+ },
73
+ { "action": "snapshot" }
74
+ ]
75
+ }
package/npm/agents.mjs CHANGED
@@ -47,6 +47,7 @@ export function nextStepCommands(config, { android = true, ios = true, packageSc
47
47
  export function agentInstructions(appId, { android = true, ios = true, packageScripts = false, scripts = {} } = {}) {
48
48
  const command = (name, fallback) => scripts[name] ?? fallback;
49
49
  const appCommand = (scriptName, directCommand) => packageScripts ? `npm run ${scriptName}` : directCommand;
50
+ const inspectCommand = "zmr inspect --json --dir .";
50
51
  const doctorCommand = appCommand("zmr:doctor", command("doctor", "zmr doctor --strict --json --config .zmr/config.json"));
51
52
  const schemasCommand = appCommand("zmr:schemas", command("schemas", "zmr schemas --json"));
52
53
  const validateDirectCommand = command("validate", validateCommand({ android, ios }));
@@ -56,6 +57,7 @@ export function agentInstructions(appId, { android = true, ios = true, packageSc
56
57
  const explainCommand = appCommand("zmr:explain", command("explain", "zmr explain traces/zmr-agent --json"));
57
58
  const exportCommand = appCommand("zmr:export", command("exportTrace", "zmr export traces/zmr-agent --out traces/zmr-agent-redacted.zmrtrace --redact"));
58
59
  const setupChecks = [
60
+ inspectCommand,
59
61
  doctorCommand,
60
62
  schemasCommand,
61
63
  validateAppCommand,
@@ -119,6 +121,7 @@ export function agentInstructions(appId, { android = true, ios = true, packageSc
119
121
  const appSectionTitle = packageScripts ? "App Scripts" : "App Commands";
120
122
  const appSectionCommands = nextStepCommands({ scripts: nextStepScripts }, { android, ios, packageScripts })
121
123
  .map((step) => step.command);
124
+ appSectionCommands.unshift(inspectCommand);
122
125
  const releaseClaims = android && ios
123
126
  ? `\`\`\`bash
124
127
  ${readinessCommandText}
@@ -148,6 +151,19 @@ ${mcpCommand}
148
151
 
149
152
  Use \`semantic_snapshot\` before choosing tap or type actions. Prefer selectors from accessibility identifiers, resource ids, labels, or exact text before coordinates. Export redacted traces before sharing artifacts.
150
153
 
154
+ ## Discover From Trace
155
+
156
+ \`\`\`bash
157
+ zmr explore --from-trace traces/zmr-agent --out .zmr/discovered/login-smoke.json --goal "find a stable login smoke" --include-actions --validate --json
158
+ zmr discover --from-trace traces/zmr-agent --out .zmr/discovered/replay-smoke.json --include-actions --validate --json
159
+ zmr draft --from-trace traces/zmr-agent --out .zmr/discovered/surface-smoke.json --json
160
+ zmr validate --json .zmr/discovered/surface-smoke.json
161
+ zmr draft --from-trace traces/zmr-agent --out .zmr/discovered/replay-smoke.json --include-actions --json
162
+ zmr validate --json .zmr/discovered/replay-smoke.json
163
+ \`\`\`
164
+
165
+ Prefer \`zmr explore\` for CLI agent loops when the goal should travel with the generated candidate. Its JSON includes \`autonomous:false\`, \`reviewRequired:true\`, \`guardrails\`, replay coverage, validation, and deterministic next commands. Treat discover output as a lower-level reviewable starting point. It writes from trace evidence and validates the generated file when \`--validate\` is present, but it does not crawl, invent missing actions, discover credentials, or commit tests. Treat draft output as a reviewable starting point when using the lower-level split workflow. The default draft contains only \`launch\`, \`snapshot\`, and conservative \`assertVisible\` checks. Use \`--include-actions\` only when the trace came from a reviewed agent session; unsupported events are skipped with warnings instead of guessed. Do not commit a discovered or drafted scenario until a human has reviewed and rerun it.
166
+
151
167
  ## Failure Triage
152
168
 
153
169
  \`\`\`bash
package/npm/commands.mjs CHANGED
@@ -13,8 +13,8 @@ export function smokeRunCommand({ platform, androidShim = "", iosShim = "" }) {
13
13
  }
14
14
 
15
15
  export function smokeReportCommand({ platform }) {
16
- if (platform === "android") return "zmr report traces/zmr-android --out traces/zmr-android/report.html";
17
- if (platform === "ios") return "zmr report traces/zmr-ios --out traces/zmr-ios/report.html";
16
+ if (platform === "android") return reportCommand("zmr", "traces/zmr-android");
17
+ if (platform === "ios") return reportCommand("zmr", "traces/zmr-ios");
18
18
  throw new Error(`unsupported smoke report platform: ${platform}`);
19
19
  }
20
20
 
@@ -71,7 +71,7 @@ export function reliabilityCommand({ scenario, platform = "", device, appId, xcr
71
71
  "--max-p95-ms",
72
72
  String(maxP95Ms),
73
73
  );
74
- return `export ZMR_BIN="\${ZMR_BIN:-zmr}"; ${shellJoin(args)} && "$ZMR_BIN" report ${shellQuote(traceRoot)} --out ${shellQuote(`${traceRoot}/report.html`)}`;
74
+ return `export ZMR_BIN="\${ZMR_BIN:-zmr}"; ${shellJoin(args)} && ${reportCommand('"$ZMR_BIN"', traceRoot)}`;
75
75
  }
76
76
 
77
77
  export function devClientRunCommand({ platform }) {
@@ -85,11 +85,15 @@ export function devClientRunCommand({ platform }) {
85
85
  }
86
86
 
87
87
  export function devClientReportCommand({ platform }) {
88
- if (platform === "android") return "zmr report traces/zmr-android-dev-client --out traces/zmr-android-dev-client/report.html";
89
- if (platform === "ios") return "zmr report traces/zmr-ios-dev-client --out traces/zmr-ios-dev-client/report.html";
88
+ if (platform === "android") return reportCommand("zmr", "traces/zmr-android-dev-client");
89
+ if (platform === "ios") return reportCommand("zmr", "traces/zmr-ios-dev-client");
90
90
  throw new Error(`unsupported dev-client report platform: ${platform}`);
91
91
  }
92
92
 
93
+ function reportCommand(bin, traceRoot) {
94
+ return `${bin} report ${shellQuote(traceRoot)} --out ${shellQuote(`${traceRoot}/report.html`)} --junit ${shellQuote(`${traceRoot}/junit.xml`)}`;
95
+ }
96
+
93
97
  export function shellJoin(args) {
94
98
  return args.map((arg, index) => {
95
99
  if (index === 0 && /^[A-Za-z_][A-Za-z0-9_]*=/.test(arg)) return arg;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zeno-mobile-runner",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Agent-native mobile app test runner for React Native, Expo, Flutter, and native Android/iOS.",
5
5
  "main": "npm/index.mjs",
6
6
  "repository": {
@@ -16,6 +16,7 @@
16
16
  "zmr-init": "npm/init-app.mjs",
17
17
  "zmr-wizard": "npm/wizard.mjs",
18
18
  "zmr-benchmark": "scripts/benchmark.sh",
19
+ "zmr-benchmark-lab": "scripts/benchmark-lab.py",
19
20
  "zmr-benchmark-command": "scripts/benchmark-command.sh",
20
21
  "zmr-compare-benchmarks": "scripts/compare-benchmarks.py",
21
22
  "zmr-device-matrix": "scripts/device-matrix.sh",
@@ -26,6 +27,7 @@
26
27
  "zmr-install-ios-shim": "scripts/install-ios-shim.sh",
27
28
  "zmr-create-android-demo-app": "scripts/create-android-demo-app.sh",
28
29
  "zmr-create-ios-demo-app": "scripts/create-ios-demo-app.sh",
30
+ "zmr-create-react-native-expo-demo-app": "scripts/create-react-native-expo-demo-app.sh",
29
31
  "zmr-demo-android": "scripts/demo-android-real.sh",
30
32
  "zmr-demo-ios": "scripts/demo-ios-real.sh"
31
33
  },
@@ -63,9 +65,12 @@
63
65
  "shims/",
64
66
  "viewer/",
65
67
  "docs/",
68
+ "!docs/assets/",
66
69
  "scripts/",
67
70
  "!scripts/build-npm-package.sh",
68
71
  "!scripts/build-release.sh",
72
+ "!scripts/capture-screenshots.sh",
73
+ "!scripts/capture-viewer-shots.mjs",
69
74
  "!scripts/ci-gate.sh",
70
75
  "!scripts/coverage.sh",
71
76
  "!scripts/generate-homebrew-formula.mjs",
Binary file
Binary file
Binary file
Binary file
package/schemas/README.md CHANGED
@@ -19,6 +19,10 @@ This directory contains draft 2020-12 JSON Schemas for public ZMR file and proto
19
19
  - `capabilities-output.schema.json`: machine-readable `runner.capabilities` JSON-RPC result for protocol, platform support, transport, and method discovery
20
20
  - `explain-output.schema.json`: machine-readable `zmr explain --json` failure triage output for agents and CI
21
21
  - `run-output.schema.json`: machine-readable `zmr run --json` terminal run summary output
22
+ - `inspect-output.schema.json`: machine-readable `zmr inspect --json` app and agent handoff output
23
+ - `discover-output.schema.json`: machine-readable `zmr discover --json` trace-backed scenario discovery output with replay coverage metadata
24
+ - `explore-output.schema.json`: machine-readable `zmr explore --json` review-first trace exploration output with goal and guardrail metadata
25
+ - `draft-output.schema.json`: machine-readable `zmr draft --json` trace-backed scenario draft output with replay coverage metadata
22
26
  - `release-manifest.schema.json`: machine-readable `RELEASE_MANIFEST.json` emitted with release archives
23
27
  - `release-readiness-output.schema.json`: machine-readable `zmr-release-readiness --json` release evidence gate output
24
28
  - `schemas-output.schema.json`: machine-readable `zmr schemas --json` index of public schema names, paths, ids, and descriptions
@@ -0,0 +1,83 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://zmr.dev/schemas/discover-output.schema.json",
4
+ "title": "ZMR Discover Output",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "ok",
9
+ "mode",
10
+ "schemaVersion",
11
+ "runnerVersion",
12
+ "protocolVersion",
13
+ "out",
14
+ "traceDir",
15
+ "sourceSnapshot",
16
+ "name",
17
+ "appId",
18
+ "selectorCount",
19
+ "stepCount",
20
+ "replay",
21
+ "warnings",
22
+ "validated",
23
+ "validation",
24
+ "nextCommands"
25
+ ],
26
+ "properties": {
27
+ "ok": { "type": "boolean" },
28
+ "mode": { "const": "discover" },
29
+ "schemaVersion": { "const": 1 },
30
+ "runnerVersion": { "type": "string", "minLength": 1 },
31
+ "protocolVersion": { "type": "string", "minLength": 1 },
32
+ "out": { "type": "string", "minLength": 1 },
33
+ "traceDir": { "type": "string", "minLength": 1 },
34
+ "sourceSnapshot": { "type": "string", "minLength": 1 },
35
+ "name": { "type": "string", "minLength": 1 },
36
+ "appId": { "type": ["string", "null"] },
37
+ "selectorCount": { "type": "integer", "minimum": 0 },
38
+ "stepCount": { "type": "integer", "minimum": 2 },
39
+ "replay": {
40
+ "type": "object",
41
+ "additionalProperties": false,
42
+ "required": ["enabled", "eventCount", "stepCount", "skippedEventCount"],
43
+ "properties": {
44
+ "enabled": { "type": "boolean" },
45
+ "eventCount": { "type": "integer", "minimum": 0 },
46
+ "stepCount": { "type": "integer", "minimum": 0 },
47
+ "skippedEventCount": { "type": "integer", "minimum": 0 }
48
+ }
49
+ },
50
+ "warnings": {
51
+ "type": "array",
52
+ "items": { "type": "string" }
53
+ },
54
+ "validated": { "type": "boolean" },
55
+ "validation": {
56
+ "anyOf": [
57
+ { "type": "null" },
58
+ {
59
+ "type": "object",
60
+ "additionalProperties": false,
61
+ "required": ["ok", "path"],
62
+ "properties": {
63
+ "ok": { "type": "boolean" },
64
+ "path": { "type": "string", "minLength": 1 },
65
+ "name": { "type": "string", "minLength": 1 },
66
+ "appId": { "type": ["string", "null"] },
67
+ "stepCount": { "type": "integer", "minimum": 0 },
68
+ "errorCode": { "type": "string", "minLength": 1 },
69
+ "message": { "type": "string", "minLength": 1 },
70
+ "fieldPath": { "type": "string", "minLength": 1 },
71
+ "line": { "type": "integer", "minimum": 1 },
72
+ "column": { "type": "integer", "minimum": 1 }
73
+ }
74
+ }
75
+ ]
76
+ },
77
+ "nextCommands": {
78
+ "type": "array",
79
+ "minItems": 1,
80
+ "items": { "type": "string", "minLength": 1 }
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://zmr.dev/schemas/draft-output.schema.json",
4
+ "title": "ZMR Draft Output",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "ok",
9
+ "mode",
10
+ "schemaVersion",
11
+ "runnerVersion",
12
+ "protocolVersion",
13
+ "out",
14
+ "traceDir",
15
+ "sourceSnapshot",
16
+ "name",
17
+ "appId",
18
+ "selectorCount",
19
+ "stepCount",
20
+ "replay",
21
+ "warnings",
22
+ "nextCommands"
23
+ ],
24
+ "properties": {
25
+ "ok": { "type": "boolean" },
26
+ "mode": { "const": "draft" },
27
+ "schemaVersion": { "const": 1 },
28
+ "runnerVersion": { "type": "string", "minLength": 1 },
29
+ "protocolVersion": { "type": "string", "minLength": 1 },
30
+ "out": { "type": "string", "minLength": 1 },
31
+ "traceDir": { "type": "string", "minLength": 1 },
32
+ "sourceSnapshot": { "type": "string", "minLength": 1 },
33
+ "name": { "type": "string", "minLength": 1 },
34
+ "appId": { "type": ["string", "null"] },
35
+ "selectorCount": { "type": "integer", "minimum": 0 },
36
+ "stepCount": { "type": "integer", "minimum": 2 },
37
+ "replay": {
38
+ "type": "object",
39
+ "additionalProperties": false,
40
+ "required": ["enabled", "eventCount", "stepCount", "skippedEventCount"],
41
+ "properties": {
42
+ "enabled": { "type": "boolean" },
43
+ "eventCount": { "type": "integer", "minimum": 0 },
44
+ "stepCount": { "type": "integer", "minimum": 0 },
45
+ "skippedEventCount": { "type": "integer", "minimum": 0 }
46
+ }
47
+ },
48
+ "warnings": {
49
+ "type": "array",
50
+ "items": { "type": "string" }
51
+ },
52
+ "nextCommands": {
53
+ "type": "array",
54
+ "minItems": 1,
55
+ "items": { "type": "string", "minLength": 1 }
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,94 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://zmr.dev/schemas/explore-output.schema.json",
4
+ "title": "ZMR Explore Output",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "ok",
9
+ "mode",
10
+ "schemaVersion",
11
+ "runnerVersion",
12
+ "protocolVersion",
13
+ "autonomous",
14
+ "reviewRequired",
15
+ "guardrails",
16
+ "out",
17
+ "traceDir",
18
+ "sourceSnapshot",
19
+ "name",
20
+ "appId",
21
+ "selectorCount",
22
+ "stepCount",
23
+ "replay",
24
+ "warnings",
25
+ "validated",
26
+ "validation",
27
+ "nextCommands"
28
+ ],
29
+ "properties": {
30
+ "ok": { "type": "boolean" },
31
+ "mode": { "const": "explore" },
32
+ "schemaVersion": { "const": 1 },
33
+ "runnerVersion": { "type": "string", "minLength": 1 },
34
+ "protocolVersion": { "type": "string", "minLength": 1 },
35
+ "goal": { "type": "string", "minLength": 1 },
36
+ "autonomous": { "const": false },
37
+ "reviewRequired": { "const": true },
38
+ "guardrails": {
39
+ "type": "array",
40
+ "minItems": 1,
41
+ "items": { "type": "string", "minLength": 1 }
42
+ },
43
+ "out": { "type": "string", "minLength": 1 },
44
+ "traceDir": { "type": "string", "minLength": 1 },
45
+ "sourceSnapshot": { "type": "string", "minLength": 1 },
46
+ "name": { "type": "string", "minLength": 1 },
47
+ "appId": { "type": ["string", "null"] },
48
+ "selectorCount": { "type": "integer", "minimum": 0 },
49
+ "stepCount": { "type": "integer", "minimum": 2 },
50
+ "replay": {
51
+ "type": "object",
52
+ "additionalProperties": false,
53
+ "required": ["enabled", "eventCount", "stepCount", "skippedEventCount"],
54
+ "properties": {
55
+ "enabled": { "type": "boolean" },
56
+ "eventCount": { "type": "integer", "minimum": 0 },
57
+ "stepCount": { "type": "integer", "minimum": 0 },
58
+ "skippedEventCount": { "type": "integer", "minimum": 0 }
59
+ }
60
+ },
61
+ "warnings": {
62
+ "type": "array",
63
+ "items": { "type": "string" }
64
+ },
65
+ "validated": { "type": "boolean" },
66
+ "validation": {
67
+ "anyOf": [
68
+ { "type": "null" },
69
+ {
70
+ "type": "object",
71
+ "additionalProperties": false,
72
+ "required": ["ok", "path"],
73
+ "properties": {
74
+ "ok": { "type": "boolean" },
75
+ "path": { "type": "string", "minLength": 1 },
76
+ "name": { "type": "string", "minLength": 1 },
77
+ "appId": { "type": ["string", "null"] },
78
+ "stepCount": { "type": "integer", "minimum": 0 },
79
+ "errorCode": { "type": "string", "minLength": 1 },
80
+ "message": { "type": "string", "minLength": 1 },
81
+ "fieldPath": { "type": "string", "minLength": 1 },
82
+ "line": { "type": "integer", "minimum": 1 },
83
+ "column": { "type": "integer", "minimum": 1 }
84
+ }
85
+ }
86
+ ]
87
+ },
88
+ "nextCommands": {
89
+ "type": "array",
90
+ "minItems": 1,
91
+ "items": { "type": "string", "minLength": 1 }
92
+ }
93
+ }
94
+ }
@@ -0,0 +1,88 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://zmr.dev/schemas/inspect-output.schema.json",
4
+ "title": "ZMR Inspect Output",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "ok",
9
+ "status",
10
+ "schemaVersion",
11
+ "runnerVersion",
12
+ "protocolVersion",
13
+ "dir",
14
+ "configPath",
15
+ "configExists",
16
+ "agentInstructionsPath",
17
+ "agentInstructionsExists",
18
+ "platforms",
19
+ "recommendedCommands",
20
+ "claimsPolicy",
21
+ "limitations"
22
+ ],
23
+ "properties": {
24
+ "ok": { "type": "boolean" },
25
+ "status": { "enum": ["ready", "needs-setup"] },
26
+ "schemaVersion": { "const": 1 },
27
+ "runnerVersion": { "type": "string", "minLength": 1 },
28
+ "protocolVersion": { "type": "string", "minLength": 1 },
29
+ "dir": { "type": "string", "minLength": 1 },
30
+ "configPath": { "type": "string", "minLength": 1 },
31
+ "configExists": { "type": "boolean" },
32
+ "agentInstructionsPath": { "type": "string", "minLength": 1 },
33
+ "agentInstructionsExists": { "type": "boolean" },
34
+ "platforms": {
35
+ "type": "array",
36
+ "items": { "$ref": "#/$defs/platform" }
37
+ },
38
+ "recommendedCommands": {
39
+ "type": "array",
40
+ "items": { "type": "string", "minLength": 1 }
41
+ },
42
+ "claimsPolicy": {
43
+ "type": "array",
44
+ "items": { "type": "string", "minLength": 1 }
45
+ },
46
+ "limitations": {
47
+ "type": "array",
48
+ "items": { "type": "string", "minLength": 1 }
49
+ }
50
+ },
51
+ "$defs": {
52
+ "platform": {
53
+ "type": "object",
54
+ "additionalProperties": false,
55
+ "required": [
56
+ "name",
57
+ "enabled",
58
+ "defaultDevice",
59
+ "smokeScenario",
60
+ "smokeScenarioExists",
61
+ "traceDir"
62
+ ],
63
+ "properties": {
64
+ "name": { "enum": ["android", "ios"] },
65
+ "enabled": { "type": "boolean" },
66
+ "defaultDevice": {
67
+ "anyOf": [
68
+ { "type": "string", "minLength": 1 },
69
+ { "type": "null" }
70
+ ]
71
+ },
72
+ "smokeScenario": {
73
+ "anyOf": [
74
+ { "type": "string", "minLength": 1 },
75
+ { "type": "null" }
76
+ ]
77
+ },
78
+ "smokeScenarioExists": { "type": "boolean" },
79
+ "traceDir": {
80
+ "anyOf": [
81
+ { "type": "string", "minLength": 1 },
82
+ { "type": "null" }
83
+ ]
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
@@ -34,6 +34,8 @@
34
34
  "failedStepIndex": { "type": "integer", "minimum": 0 },
35
35
  "error": { "type": "string", "minLength": 1 },
36
36
  "reportPath": { "type": "string", "minLength": 1 },
37
+ "discovery": { "$ref": "https://zmr.dev/schemas/discover-output.schema.json" },
38
+ "discoveryError": { "type": "string", "minLength": 1 },
37
39
  "nextCommands": {
38
40
  "type": "array",
39
41
  "minItems": 1,