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.
- package/CHANGELOG.md +162 -3
- package/FEATURES.md +50 -7
- package/README.md +133 -7
- package/build.zig.zon +3 -3
- package/clients/README.md +60 -3
- package/clients/go/README.md +12 -0
- package/clients/go/zmr/client.go +142 -0
- package/clients/kotlin/README.md +18 -1
- package/clients/kotlin/build.gradle.kts +1 -1
- package/clients/kotlin/src/main/kotlin/dev/zmr/ZmrClient.kt +76 -1
- package/clients/python/README.md +19 -0
- package/clients/python/pyproject.toml +1 -1
- package/clients/python/zmr_client.py +33 -0
- package/clients/rust/Cargo.lock +1 -1
- package/clients/rust/Cargo.toml +1 -1
- package/clients/rust/README.md +25 -1
- package/clients/rust/src/lib.rs +201 -0
- package/clients/swift/README.md +18 -0
- package/clients/swift/Sources/ZMRClient/ZMRClient.swift +82 -0
- package/clients/typescript/README.md +16 -0
- package/clients/typescript/index.d.ts +12 -0
- package/clients/typescript/index.mjs +16 -0
- package/clients/typescript/package.json +1 -1
- package/docs/agent-discovery.md +202 -0
- package/docs/ai-agents.md +87 -6
- package/docs/benchmarking.md +10 -3
- package/docs/clients.md +10 -6
- package/docs/demo.md +4 -0
- package/docs/expo-smoke.md +79 -0
- package/docs/install.md +3 -2
- package/docs/npm.md +58 -4
- package/docs/production-readiness.md +123 -0
- package/docs/protocol-fixtures/core-session.responses.jsonl +1 -1
- package/docs/protocol.md +215 -16
- package/docs/scenario-authoring.md +3 -0
- package/docs/troubleshooting.md +1 -1
- package/npm/agents.mjs +16 -0
- package/npm/build-zmr.mjs +1 -1
- package/npm/commands.mjs +9 -5
- package/npm/postinstall.mjs +28 -2
- package/npm/verify-publish.mjs +36 -0
- package/package.json +2 -1
- 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 +4 -0
- package/schemas/discover-output.schema.json +83 -0
- package/schemas/draft-output.schema.json +58 -0
- package/schemas/explore-output.schema.json +94 -0
- package/schemas/inspect-output.schema.json +88 -0
- package/schemas/run-output.schema.json +2 -0
- package/scripts/install-ios-shim.sh +79 -14
- package/scripts/release-readiness.py +43 -0
- package/scripts/run-android-pilot.sh +35 -9
- package/scripts/run-ios-pilot.sh +11 -4
- package/shims/ios/ZMRShim.swift +3 -0
- package/shims/ios/ZMRShimUITestCase.swift +41 -11
- package/skills/zmr-mobile-testing/SKILL.md +28 -3
- package/src/cli_discover.zig +239 -0
- package/src/cli_draft.zig +924 -0
- package/src/cli_explore.zig +136 -0
- package/src/cli_inspect.zig +310 -0
- package/src/cli_output.zig +26 -2
- package/src/cli_run.zig +28 -0
- package/src/cli_trace.zig +8 -0
- package/src/errors.zig +9 -0
- package/src/ios.zig +11 -4
- package/src/ios_lifecycle.zig +36 -0
- package/src/ios_shim.zig +42 -0
- package/src/json_rpc_methods.zig +85 -11
- package/src/json_rpc_params.zig +8 -0
- package/src/json_rpc_protocol.zig +1 -1
- package/src/json_rpc_trace.zig +112 -0
- package/src/main.zig +24 -2
- package/src/mcp.zig +209 -6
- package/src/mcp_protocol.zig +29 -1
- package/src/mcp_trace.zig +126 -4
- package/src/report.zig +186 -0
- package/src/runner.zig +26 -4
- package/src/runner_actions.zig +10 -0
- package/src/runner_diagnostics.zig +31 -1
- package/src/runner_events.zig +70 -7
- package/src/runner_native.zig +17 -1
- package/src/runner_waits.zig +82 -19
- package/src/scaffold.zig +28 -12
- package/src/scenario.zig +32 -4
- package/src/schema_registry.zig +4 -0
- package/src/version.zig +1 -1
|
@@ -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,
|
|
@@ -167,6 +167,10 @@ mkdir -p "$APP_ROOT"
|
|
|
167
167
|
APP_ROOT="$(cd "$APP_ROOT" && pwd)"
|
|
168
168
|
mkdir -p "$APP_ROOT/.zmr" "$APP_ROOT/.zmr/shims/ios"
|
|
169
169
|
rm -f "$APP_ROOT/.zmr/ios-shim-state/build-for-testing.ready"
|
|
170
|
+
rm -f "$APP_ROOT/.zmr/ios-shim-state/destination.id"
|
|
171
|
+
rm -f "$APP_ROOT/.zmr/ios-shim-state/xcodebuild.pid"
|
|
172
|
+
rm -f "$APP_ROOT/.zmr/ios-shim-state/xcodebuild.log"
|
|
173
|
+
rm -rf "$APP_ROOT/.zmr/ios-shim-state/server"
|
|
170
174
|
cp "$ROOT/shims/ios/ZMRShim.swift" "$APP_ROOT/.zmr/shims/ios/ZMRShim.swift"
|
|
171
175
|
cp "$ROOT/shims/ios/ZMRShimUITestCase.swift" "$APP_ROOT/.zmr/ZMRShimUITestCase.swift"
|
|
172
176
|
cp "$ROOT/scripts/ensure-ios-shim-target.rb" "$APP_ROOT/.zmr/ensure-ios-shim-target.rb"
|
|
@@ -216,6 +220,7 @@ STATE_DIR="$APP_ROOT/.zmr/ios-shim-state"
|
|
|
216
220
|
SERVER_DIR="\$STATE_DIR/server"
|
|
217
221
|
PID_FILE="\$STATE_DIR/xcodebuild.pid"
|
|
218
222
|
READY_FILE="\$SERVER_DIR/ready"
|
|
223
|
+
DESTINATION_ID_FILE="\$STATE_DIR/destination.id"
|
|
219
224
|
BUILD_READY_FILE="\$STATE_DIR/build-for-testing.ready"
|
|
220
225
|
LOG_FILE="\$STATE_DIR/xcodebuild.log"
|
|
221
226
|
STDIN_FILE="\$(mktemp)"
|
|
@@ -241,6 +246,52 @@ tail_log() {
|
|
|
241
246
|
fi
|
|
242
247
|
}
|
|
243
248
|
|
|
249
|
+
tail_log_path() {
|
|
250
|
+
local log_file="\$1"
|
|
251
|
+
if [[ -f "\$log_file" ]]; then
|
|
252
|
+
tail -120 "\$log_file" >&2
|
|
253
|
+
fi
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
run_xcodebuild_with_timeout() {
|
|
257
|
+
local label="\$1"
|
|
258
|
+
local timeout_seconds="\$2"
|
|
259
|
+
local log_file="\$3"
|
|
260
|
+
shift 3
|
|
261
|
+
|
|
262
|
+
local pid started_at next_progress progress_seconds elapsed
|
|
263
|
+
progress_seconds="\${ZMR_IOS_SHIM_PROGRESS_SECONDS:-30}"
|
|
264
|
+
"\$@" >"\$log_file" 2>&1 &
|
|
265
|
+
pid="\$!"
|
|
266
|
+
started_at="\$SECONDS"
|
|
267
|
+
next_progress=\$((started_at + progress_seconds))
|
|
268
|
+
|
|
269
|
+
while kill -0 "\$pid" 2>/dev/null; do
|
|
270
|
+
elapsed=\$((SECONDS - started_at))
|
|
271
|
+
if (( elapsed >= timeout_seconds )); then
|
|
272
|
+
echo "timed out waiting for \$label after \${timeout_seconds}s" >&2
|
|
273
|
+
kill -TERM "\$pid" 2>/dev/null || true
|
|
274
|
+
sleep 2
|
|
275
|
+
if kill -0 "\$pid" 2>/dev/null; then
|
|
276
|
+
kill -KILL "\$pid" 2>/dev/null || true
|
|
277
|
+
fi
|
|
278
|
+
wait "\$pid" 2>/dev/null || true
|
|
279
|
+
tail_log_path "\$log_file"
|
|
280
|
+
exit 1
|
|
281
|
+
fi
|
|
282
|
+
if (( SECONDS >= next_progress )); then
|
|
283
|
+
echo "still waiting for \$label after \${elapsed}s; log: \$log_file" >&2
|
|
284
|
+
next_progress=\$((SECONDS + progress_seconds))
|
|
285
|
+
fi
|
|
286
|
+
sleep 1
|
|
287
|
+
done
|
|
288
|
+
|
|
289
|
+
if ! wait "\$pid"; then
|
|
290
|
+
tail_log_path "\$log_file"
|
|
291
|
+
exit 1
|
|
292
|
+
fi
|
|
293
|
+
}
|
|
294
|
+
|
|
244
295
|
resolve_destination() {
|
|
245
296
|
local destination_id="$DEVICE"
|
|
246
297
|
if [[ "\$destination_id" == "booted" ]]; then
|
|
@@ -248,7 +299,20 @@ resolve_destination() {
|
|
|
248
299
|
echo "physical iOS shim requires an explicit --device id" >&2
|
|
249
300
|
exit 2
|
|
250
301
|
fi
|
|
302
|
+
if [[ -f "\$DESTINATION_ID_FILE" ]]; then
|
|
303
|
+
destination_id="\$(cat "\$DESTINATION_ID_FILE" 2>/dev/null || true)"
|
|
304
|
+
if [[ -n "\$destination_id" ]] && xcrun simctl list devices available | grep -F "\$destination_id" >/dev/null 2>&1; then
|
|
305
|
+
# Reuse the first resolved booted simulator so build-for-testing and
|
|
306
|
+
# test-without-building target the same simulator even if it shuts down
|
|
307
|
+
# while Xcode is compiling the shim target.
|
|
308
|
+
printf '%s' "\$destination_id"
|
|
309
|
+
return 0
|
|
310
|
+
fi
|
|
311
|
+
fi
|
|
251
312
|
destination_id="\$(xcrun simctl list devices booted | sed -n 's/.*(\([0-9A-Fa-f-][0-9A-Fa-f-]*\)) (Booted).*/\1/p' | head -n 1)"
|
|
313
|
+
if [[ -n "\$destination_id" ]]; then
|
|
314
|
+
printf '%s' "\$destination_id" > "\$DESTINATION_ID_FILE"
|
|
315
|
+
fi
|
|
252
316
|
fi
|
|
253
317
|
if [[ -z "\$destination_id" ]]; then
|
|
254
318
|
echo "no booted iOS simulator found" >&2
|
|
@@ -272,9 +336,13 @@ is_server_running() {
|
|
|
272
336
|
if [[ ! -f "\$PID_FILE" ]]; then
|
|
273
337
|
return 1
|
|
274
338
|
fi
|
|
275
|
-
local pid
|
|
339
|
+
local pid command
|
|
276
340
|
pid="\$(cat "\$PID_FILE" 2>/dev/null || true)"
|
|
277
|
-
[[ -
|
|
341
|
+
if [[ -z "\$pid" ]] || ! kill -0 "\$pid" 2>/dev/null; then
|
|
342
|
+
return 1
|
|
343
|
+
fi
|
|
344
|
+
command="\$(ps -p "\$pid" -o command= 2>/dev/null || true)"
|
|
345
|
+
[[ "\$command" == *xcodebuild* && "\$command" == *ZMRShimUITests* ]]
|
|
278
346
|
}
|
|
279
347
|
|
|
280
348
|
run_oneshot() {
|
|
@@ -332,18 +400,15 @@ build_for_testing() {
|
|
|
332
400
|
destination_id="\$(destination_spec)"
|
|
333
401
|
build_log="\$STATE_DIR/xcodebuild.build.log"
|
|
334
402
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
tail -120 "\$build_log" >&2
|
|
345
|
-
exit 1
|
|
346
|
-
fi
|
|
403
|
+
run_xcodebuild_with_timeout "iOS shim build-for-testing" "\${ZMR_IOS_SHIM_BUILD_TIMEOUT_SECONDS:-5400}" "\$build_log" \\
|
|
404
|
+
xcodebuild build-for-testing \\
|
|
405
|
+
"\${XCODEBUILD_ARGS[@]}" \\
|
|
406
|
+
-scheme "$SCHEME" \\
|
|
407
|
+
-configuration "$CONFIGURATION" \\
|
|
408
|
+
-destination "\$destination_id" \\
|
|
409
|
+
ZMR_SHIM_MODE="server" \\
|
|
410
|
+
ZMR_SHIM_SERVER_DIR="\$SERVER_DIR" \\
|
|
411
|
+
ZMR_APP_BUNDLE_ID="$BUNDLE_ID"
|
|
347
412
|
|
|
348
413
|
touch "\$BUILD_READY_FILE"
|
|
349
414
|
}
|
|
@@ -423,6 +423,38 @@ def benchmark_threshold_reason(row):
|
|
|
423
423
|
return "requires " + ", ".join(reasons)
|
|
424
424
|
|
|
425
425
|
|
|
426
|
+
agent_workflow_fields = (
|
|
427
|
+
"agentWorkflow",
|
|
428
|
+
"mcp",
|
|
429
|
+
"jsonRpc",
|
|
430
|
+
"semanticSnapshot",
|
|
431
|
+
"typedActions",
|
|
432
|
+
"traceEvents",
|
|
433
|
+
"traceExplain",
|
|
434
|
+
"traceExplore",
|
|
435
|
+
"traceDiscover",
|
|
436
|
+
"scenarioValidation",
|
|
437
|
+
"redactedExport",
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def agent_workflow_pass(row):
|
|
442
|
+
command = row.get("command")
|
|
443
|
+
if row.get("name") == "local release gate" and isinstance(command, str) and "release-gate.sh" in command:
|
|
444
|
+
return True
|
|
445
|
+
return all(row.get(field) is True for field in agent_workflow_fields)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def agent_workflow_reason(row):
|
|
449
|
+
command = row.get("command")
|
|
450
|
+
if row.get("name") == "local release gate" and (not isinstance(command, str) or "release-gate.sh" not in command):
|
|
451
|
+
return "requires release-gate.sh or structured agentWorkflow evidence"
|
|
452
|
+
missing = [field for field in agent_workflow_fields if row.get(field) is not True]
|
|
453
|
+
if missing:
|
|
454
|
+
return "requires release-gate.sh or structured agentWorkflow evidence: " + ", ".join(missing)
|
|
455
|
+
return "requires release-gate.sh or structured agentWorkflow evidence"
|
|
456
|
+
|
|
457
|
+
|
|
426
458
|
def row_satisfies(label, row):
|
|
427
459
|
if row.get("status") != "passed":
|
|
428
460
|
return False
|
|
@@ -436,6 +468,8 @@ def row_satisfies(label, row):
|
|
|
436
468
|
return physical_ios_device_value(row) is not None
|
|
437
469
|
if label == "competitive benchmark comparison":
|
|
438
470
|
return benchmark_thresholds_pass(row)
|
|
471
|
+
if label == "agent workflow smoke":
|
|
472
|
+
return agent_workflow_pass(row)
|
|
439
473
|
return True
|
|
440
474
|
|
|
441
475
|
|
|
@@ -485,6 +519,8 @@ def requirement_status(label, names):
|
|
|
485
519
|
reason = "requires concrete physical device identifier evidence"
|
|
486
520
|
elif label == "competitive benchmark comparison":
|
|
487
521
|
reason = benchmark_threshold_reason(row)
|
|
522
|
+
elif label == "agent workflow smoke":
|
|
523
|
+
reason = agent_workflow_reason(row)
|
|
488
524
|
return {
|
|
489
525
|
"name": label,
|
|
490
526
|
"status": "insufficient",
|
|
@@ -508,6 +544,7 @@ requirements = [
|
|
|
508
544
|
|
|
509
545
|
if target in ("production", "market-claim"):
|
|
510
546
|
requirements.extend([
|
|
547
|
+
("agent workflow smoke", ("agent workflow smoke", "local release gate")),
|
|
511
548
|
("physical iOS readiness", "physical iOS readiness"),
|
|
512
549
|
("Android hardware pilot", "Android hardware pilot"),
|
|
513
550
|
("iOS simulator hardware pilot", "iOS simulator hardware pilot"),
|
|
@@ -582,6 +619,7 @@ next_step_commands = {
|
|
|
582
619
|
"local release gate": ["./scripts/release-candidate.sh --mode local"],
|
|
583
620
|
"public Android demo": ["zmr-demo-android --runs 5"],
|
|
584
621
|
"public iOS simulator demo": ["zmr-demo-ios --runs 5"],
|
|
622
|
+
"agent workflow smoke": ["./scripts/release-gate.sh"],
|
|
585
623
|
"physical iOS readiness": [physical_ios_pilot_command(default_pilot_evidence)],
|
|
586
624
|
"Android hardware pilot": [grouped_simulator_pilot_command(default_pilot_evidence)],
|
|
587
625
|
"iOS simulator hardware pilot": [grouped_simulator_pilot_command(default_pilot_evidence)],
|
|
@@ -690,6 +728,11 @@ def append_grouped_next_steps(blocked_items):
|
|
|
690
728
|
append_next_step(next_steps, label, commands, present)
|
|
691
729
|
handled.update(present)
|
|
692
730
|
|
|
731
|
+
maybe_group(
|
|
732
|
+
["local release gate", "agent workflow smoke"],
|
|
733
|
+
"local release gate + agent workflow smoke",
|
|
734
|
+
["./scripts/release-candidate.sh --mode local"],
|
|
735
|
+
)
|
|
693
736
|
maybe_group(
|
|
694
737
|
["Android hardware pilot", "iOS simulator hardware pilot"],
|
|
695
738
|
"Android hardware pilot + iOS simulator hardware pilot",
|
|
@@ -171,6 +171,11 @@ run() {
|
|
|
171
171
|
fi
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
+
run_zmr_report() {
|
|
175
|
+
local trace_dir="$1"
|
|
176
|
+
run "$ZMR_BIN" report "$trace_dir" --out "$trace_dir/report.html" --junit "$trace_dir/junit.xml"
|
|
177
|
+
}
|
|
178
|
+
|
|
174
179
|
capture() {
|
|
175
180
|
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
176
181
|
echo ""
|
|
@@ -505,7 +510,7 @@ if [[ "$RUNS" -eq 1 ]]; then
|
|
|
505
510
|
SINGLE_TRACE="$TRACE_ROOT/scenario"
|
|
506
511
|
run rm -rf "$SINGLE_TRACE"
|
|
507
512
|
run_zmr_android_scenario "$SCENARIO" --device "$DEVICE" --app-id "$APP_ID" --trace-dir "$SINGLE_TRACE"
|
|
508
|
-
|
|
513
|
+
run_zmr_report "$SINGLE_TRACE"
|
|
509
514
|
run "$ZMR_BIN" export "$SINGLE_TRACE" --out "$TRACE_ROOT/scenario.zmrtrace"
|
|
510
515
|
run "$ZMR_BIN" export "$SINGLE_TRACE" --out "$TRACE_ROOT/scenario-redacted.zmrtrace" --redact
|
|
511
516
|
else
|
|
@@ -513,11 +518,11 @@ if [[ "$RUNS" -eq 1 ]]; then
|
|
|
513
518
|
LOGIN_TRACE="$TRACE_ROOT/login-smoke"
|
|
514
519
|
run rm -rf "$AUTH_TRACE" "$LOGIN_TRACE"
|
|
515
520
|
run_zmr_android_scenario examples/android-app-auth-probe.json --device "$DEVICE" --app-id "$APP_ID" --trace-dir "$AUTH_TRACE"
|
|
516
|
-
|
|
521
|
+
run_zmr_report "$AUTH_TRACE"
|
|
517
522
|
run "$ZMR_BIN" export "$AUTH_TRACE" --out "$TRACE_ROOT/auth.zmrtrace"
|
|
518
523
|
run "$ZMR_BIN" export "$AUTH_TRACE" --out "$TRACE_ROOT/auth-redacted.zmrtrace" --redact
|
|
519
524
|
run_zmr_android_scenario examples/android-app-login-smoke.json --device "$DEVICE" --app-id "$APP_ID" --trace-dir "$LOGIN_TRACE"
|
|
520
|
-
|
|
525
|
+
run_zmr_report "$LOGIN_TRACE"
|
|
521
526
|
run "$ZMR_BIN" export "$LOGIN_TRACE" --out "$TRACE_ROOT/login-smoke.zmrtrace"
|
|
522
527
|
run "$ZMR_BIN" export "$LOGIN_TRACE" --out "$TRACE_ROOT/login-smoke-redacted.zmrtrace" --redact
|
|
523
528
|
fi
|
|
@@ -531,12 +536,12 @@ else
|
|
|
531
536
|
fi
|
|
532
537
|
if [[ -n "$SCENARIO" ]]; then
|
|
533
538
|
run_android_benchmark --zmr "$SCENARIO" --device "$DEVICE" --app-id "$APP_ID" --runs "$RUNS" --trace-root "$TRACE_ROOT/bench-scenario" "${benchmark_gate_args[@]}"
|
|
534
|
-
|
|
539
|
+
run_zmr_report "$TRACE_ROOT/bench-scenario"
|
|
535
540
|
else
|
|
536
541
|
run_android_benchmark --zmr examples/android-app-auth-probe.json --device "$DEVICE" --app-id "$APP_ID" --runs "$RUNS" --trace-root "$TRACE_ROOT/bench-auth" "${benchmark_gate_args[@]}"
|
|
537
|
-
|
|
542
|
+
run_zmr_report "$TRACE_ROOT/bench-auth"
|
|
538
543
|
run_android_benchmark --zmr examples/android-app-login-smoke.json --device "$DEVICE" --app-id "$APP_ID" --runs "$RUNS" --trace-root "$TRACE_ROOT/bench-login-smoke" "${benchmark_gate_args[@]}"
|
|
539
|
-
|
|
544
|
+
run_zmr_report "$TRACE_ROOT/bench-login-smoke"
|
|
540
545
|
fi
|
|
541
546
|
fi
|
|
542
547
|
|
|
@@ -546,9 +551,30 @@ cat <<EOF
|
|
|
546
551
|
|
|
547
552
|
Android pilot complete.
|
|
548
553
|
Output directory: $TRACE_ROOT
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
554
|
+
EOF
|
|
555
|
+
|
|
556
|
+
if [[ "$RUNS" -eq 1 ]]; then
|
|
557
|
+
echo "Shareable bundles:"
|
|
558
|
+
if [[ -n "$SCENARIO" ]]; then
|
|
559
|
+
echo " $TRACE_ROOT/scenario-redacted.zmrtrace"
|
|
560
|
+
else
|
|
561
|
+
echo " $TRACE_ROOT/auth-redacted.zmrtrace"
|
|
562
|
+
echo " $TRACE_ROOT/login-smoke-redacted.zmrtrace"
|
|
563
|
+
fi
|
|
564
|
+
else
|
|
565
|
+
echo "Benchmark reports:"
|
|
566
|
+
if [[ -n "$SCENARIO" ]]; then
|
|
567
|
+
echo " $TRACE_ROOT/bench-scenario/report.html"
|
|
568
|
+
echo " $TRACE_ROOT/bench-scenario/junit.xml"
|
|
569
|
+
else
|
|
570
|
+
echo " $TRACE_ROOT/bench-auth/report.html"
|
|
571
|
+
echo " $TRACE_ROOT/bench-auth/junit.xml"
|
|
572
|
+
echo " $TRACE_ROOT/bench-login-smoke/report.html"
|
|
573
|
+
echo " $TRACE_ROOT/bench-login-smoke/junit.xml"
|
|
574
|
+
fi
|
|
575
|
+
fi
|
|
576
|
+
|
|
577
|
+
cat <<EOF
|
|
552
578
|
Viewer:
|
|
553
579
|
$ROOT/viewer/index.html
|
|
554
580
|
EOF
|