@farmslot/adapter-rn 0.15.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.
- package/CHANGELOG.md +117 -0
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/bin/farmslot-adapter-rn.mjs +10 -0
- package/dist/agent-device-ui-transport.d.ts +88 -0
- package/dist/agent-device-ui-transport.d.ts.map +1 -0
- package/dist/agent-device-ui-transport.js +1148 -0
- package/dist/agent-device-ui-transport.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +169 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -0
- package/dist/doctor.d.ts +17 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +125 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +2 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +5 -0
- package/dist/json.js.map +1 -0
- package/dist/metro-recipe-bridge-transport.d.ts +12 -0
- package/dist/metro-recipe-bridge-transport.d.ts.map +1 -0
- package/dist/metro-recipe-bridge-transport.js +63 -0
- package/dist/metro-recipe-bridge-transport.js.map +1 -0
- package/dist/redaction.d.ts +3 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/redaction.js +57 -0
- package/dist/redaction.js.map +1 -0
- package/dist/runner.d.ts +20 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +270 -0
- package/dist/runner.js.map +1 -0
- package/dist/scaffold.d.ts +14 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +82 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/simctl-video-recorder.d.ts +6 -0
- package/dist/simctl-video-recorder.d.ts.map +1 -0
- package/dist/simctl-video-recorder.js +160 -0
- package/dist/simctl-video-recorder.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/package.json +81 -0
- package/templates/scripts/agentic/recipe/README.md +15 -0
- package/templates/scripts/agentic/recipe/action-manifest.json +547 -0
- package/templates/scripts/agentic/recipe/action-manifest.with-bridge.json +599 -0
- package/templates/scripts/agentic/recipe/recipes/expo.config.recipe.json +37 -0
- package/templates/scripts/agentic/validate-recipe.sh +64 -0
- package/templates/src/farmslot/RecipeBridgeProvider.tsx +127 -0
- package/templates/src/farmslot/RecipeHud.tsx +138 -0
- package/templates/src/farmslot/index.ts +11 -0
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://farmslot.io/schemas/action-manifest-v1.schema.json",
|
|
3
|
+
"actions": {
|
|
4
|
+
"end": {
|
|
5
|
+
"description": "Finish recipe execution with an explicit status.",
|
|
6
|
+
"examples": [
|
|
7
|
+
{
|
|
8
|
+
"action": "end",
|
|
9
|
+
"status": "pass"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
"command": {
|
|
14
|
+
"description": "Run a project-local command during setup, diagnostics, or headless proof. Prefer UI actions only when the recipe must prove visible interaction.",
|
|
15
|
+
"schema": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"cmd": {
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"timeout_ms": {
|
|
22
|
+
"type": "integer"
|
|
23
|
+
},
|
|
24
|
+
"cwd": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
},
|
|
27
|
+
"allow_failure": {
|
|
28
|
+
"type": "boolean"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"required": ["cmd"],
|
|
32
|
+
"additionalProperties": false
|
|
33
|
+
},
|
|
34
|
+
"examples": [
|
|
35
|
+
{
|
|
36
|
+
"action": "command",
|
|
37
|
+
"intent": "Prepare the project state needed for this proof.",
|
|
38
|
+
"cmd": "true",
|
|
39
|
+
"next": "done"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"app.status": {
|
|
44
|
+
"description": "Query the dev-only Farmslot Expo bridge to confirm the app is reachable.",
|
|
45
|
+
"schema": {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"properties": {
|
|
48
|
+
"timeout_ms": {
|
|
49
|
+
"type": "integer"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"additionalProperties": false
|
|
53
|
+
},
|
|
54
|
+
"examples": [
|
|
55
|
+
{
|
|
56
|
+
"action": "app.status",
|
|
57
|
+
"intent": "Record the resolved application state before continuing.",
|
|
58
|
+
"next": "done"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
"app.hud": {
|
|
63
|
+
"description": "Display one concise human intent line from the current recipe node.",
|
|
64
|
+
"schema": {
|
|
65
|
+
"type": "object",
|
|
66
|
+
"properties": {
|
|
67
|
+
"clear": {
|
|
68
|
+
"type": "boolean"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"additionalProperties": false
|
|
72
|
+
},
|
|
73
|
+
"examples": [
|
|
74
|
+
{
|
|
75
|
+
"action": "app.hud",
|
|
76
|
+
"intent": "Show the current goal to the supervising human.",
|
|
77
|
+
"next": "done"
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
"app.trace": {
|
|
82
|
+
"description": "Emit a lightweight bridge trace event for recipe timeline observability.",
|
|
83
|
+
"schema": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"additionalProperties": false
|
|
86
|
+
},
|
|
87
|
+
"examples": [
|
|
88
|
+
{
|
|
89
|
+
"action": "app.trace",
|
|
90
|
+
"intent": "Record the requested runtime timeline evidence.",
|
|
91
|
+
"next": "done"
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
"ui.press": {
|
|
96
|
+
"description": "Press a native accessibility target on the assigned simulator or device.",
|
|
97
|
+
"schema": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"properties": {
|
|
100
|
+
"test_id": {
|
|
101
|
+
"type": "string"
|
|
102
|
+
},
|
|
103
|
+
"text": {
|
|
104
|
+
"type": "string"
|
|
105
|
+
},
|
|
106
|
+
"selector": {
|
|
107
|
+
"type": "string"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"additionalProperties": false
|
|
111
|
+
},
|
|
112
|
+
"examples": [
|
|
113
|
+
{
|
|
114
|
+
"action": "ui.press",
|
|
115
|
+
"intent": "Activate the requested visible control.",
|
|
116
|
+
"test_id": "example-control",
|
|
117
|
+
"next": "done"
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
"ui.key_press": {
|
|
122
|
+
"description": "Send Back through native navigation, or Escape, Enter, or Return to the visible native keyboard, then wait for the resulting UI transition. Keyboard actions fail when no visible keyboard accepts them.",
|
|
123
|
+
"adapters": ["android", "ios"],
|
|
124
|
+
"schema": {
|
|
125
|
+
"type": "object",
|
|
126
|
+
"properties": {
|
|
127
|
+
"key": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"enum": ["Back", "Escape", "Enter", "Return"]
|
|
130
|
+
},
|
|
131
|
+
"settle": {
|
|
132
|
+
"type": "boolean"
|
|
133
|
+
},
|
|
134
|
+
"timeout_ms": {
|
|
135
|
+
"type": "integer",
|
|
136
|
+
"minimum": 1
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"required": ["key"],
|
|
140
|
+
"additionalProperties": false
|
|
141
|
+
},
|
|
142
|
+
"examples": [
|
|
143
|
+
{
|
|
144
|
+
"action": "ui.key_press",
|
|
145
|
+
"intent": "Continue the requested keyboard interaction.",
|
|
146
|
+
"key": "Enter",
|
|
147
|
+
"next": "done"
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
},
|
|
151
|
+
"ui.set_input": {
|
|
152
|
+
"description": "Set text on a native input. Android recipes must provide test_id so the replacement can be verified from the native snapshot. Values remain part of retained recipe artifacts, so recipes must not contain secrets.",
|
|
153
|
+
"schema": {
|
|
154
|
+
"type": "object",
|
|
155
|
+
"properties": {
|
|
156
|
+
"test_id": {
|
|
157
|
+
"type": "string"
|
|
158
|
+
},
|
|
159
|
+
"value": {
|
|
160
|
+
"type": "string"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"additionalProperties": false
|
|
164
|
+
},
|
|
165
|
+
"examples": [
|
|
166
|
+
{
|
|
167
|
+
"action": "ui.set_input",
|
|
168
|
+
"intent": "Provide the requested value in the visible form.",
|
|
169
|
+
"test_id": "example-input",
|
|
170
|
+
"value": "example",
|
|
171
|
+
"next": "done"
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
"ui.scroll": {
|
|
176
|
+
"description": "Scroll the assigned native simulator or device and wait for stability.",
|
|
177
|
+
"schema": {
|
|
178
|
+
"type": "object",
|
|
179
|
+
"additionalProperties": false
|
|
180
|
+
},
|
|
181
|
+
"examples": [
|
|
182
|
+
{
|
|
183
|
+
"action": "ui.scroll",
|
|
184
|
+
"intent": "Expose the requested content for visible review.",
|
|
185
|
+
"next": "done"
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
"ui.swipe": {
|
|
190
|
+
"description": "Swipe from a test-id target or explicit screen coordinates in one cardinal direction.",
|
|
191
|
+
"adapters": ["android", "ios"],
|
|
192
|
+
"schema": {
|
|
193
|
+
"type": "object",
|
|
194
|
+
"properties": {
|
|
195
|
+
"target": {
|
|
196
|
+
"type": ["string", "object"],
|
|
197
|
+
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
|
|
198
|
+
"required": ["x", "y"],
|
|
199
|
+
"additionalProperties": false
|
|
200
|
+
},
|
|
201
|
+
"direction": { "type": "string", "enum": ["up", "down", "left", "right"] },
|
|
202
|
+
"distance": { "type": "number", "minimum": 1 },
|
|
203
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
204
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
205
|
+
"settle": { "type": "boolean" }
|
|
206
|
+
},
|
|
207
|
+
"required": ["target", "direction", "distance", "duration_ms"],
|
|
208
|
+
"additionalProperties": false
|
|
209
|
+
},
|
|
210
|
+
"examples": [
|
|
211
|
+
{
|
|
212
|
+
"action": "ui.swipe",
|
|
213
|
+
"intent": "Swipe the requested visible surface.",
|
|
214
|
+
"target": "example-scrollable",
|
|
215
|
+
"direction": "up",
|
|
216
|
+
"distance": 240,
|
|
217
|
+
"duration_ms": 300,
|
|
218
|
+
"next": "done"
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
"ui.pan": {
|
|
223
|
+
"description": "Stream a continuous pointer path from a test-id target or explicit screen coordinates. Native adapters accept one path point or delta.",
|
|
224
|
+
"adapters": ["android", "ios"],
|
|
225
|
+
"schema": {
|
|
226
|
+
"type": "object",
|
|
227
|
+
"properties": {
|
|
228
|
+
"target": {
|
|
229
|
+
"type": ["string", "object"],
|
|
230
|
+
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
|
|
231
|
+
"required": ["x", "y"],
|
|
232
|
+
"additionalProperties": false
|
|
233
|
+
},
|
|
234
|
+
"path": {
|
|
235
|
+
"type": "array",
|
|
236
|
+
"minItems": 1,
|
|
237
|
+
"items": {
|
|
238
|
+
"type": "object",
|
|
239
|
+
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
|
|
240
|
+
"required": ["x", "y"],
|
|
241
|
+
"additionalProperties": false
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
"delta": {
|
|
245
|
+
"type": "object",
|
|
246
|
+
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
|
|
247
|
+
"required": ["x", "y"],
|
|
248
|
+
"additionalProperties": false
|
|
249
|
+
},
|
|
250
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
251
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
252
|
+
"settle": { "type": "boolean" }
|
|
253
|
+
},
|
|
254
|
+
"required": ["target", "duration_ms"],
|
|
255
|
+
"additionalProperties": false
|
|
256
|
+
},
|
|
257
|
+
"adapter_schemas": {
|
|
258
|
+
"android": {
|
|
259
|
+
"type": "object",
|
|
260
|
+
"properties": {
|
|
261
|
+
"path": {
|
|
262
|
+
"type": "array",
|
|
263
|
+
"maxItems": 1,
|
|
264
|
+
"items": { "type": "object", "additionalProperties": true }
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
"additionalProperties": true
|
|
268
|
+
},
|
|
269
|
+
"ios": {
|
|
270
|
+
"type": "object",
|
|
271
|
+
"properties": {
|
|
272
|
+
"path": {
|
|
273
|
+
"type": "array",
|
|
274
|
+
"maxItems": 1,
|
|
275
|
+
"items": { "type": "object", "additionalProperties": true }
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
"additionalProperties": true
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
"examples": [
|
|
282
|
+
{
|
|
283
|
+
"action": "ui.pan",
|
|
284
|
+
"intent": "Pan through the requested pointer path.",
|
|
285
|
+
"target": "example-surface",
|
|
286
|
+
"path": [{ "x": 80, "y": 20 }],
|
|
287
|
+
"duration_ms": 400,
|
|
288
|
+
"next": "done"
|
|
289
|
+
}
|
|
290
|
+
]
|
|
291
|
+
},
|
|
292
|
+
"ui.drag": {
|
|
293
|
+
"description": "Drag a grabbable test-id target or explicit screen coordinate. Native adapters accept one path point or delta.",
|
|
294
|
+
"adapters": ["android", "ios"],
|
|
295
|
+
"schema": {
|
|
296
|
+
"type": "object",
|
|
297
|
+
"properties": {
|
|
298
|
+
"target": {
|
|
299
|
+
"type": ["string", "object"],
|
|
300
|
+
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
|
|
301
|
+
"required": ["x", "y"],
|
|
302
|
+
"additionalProperties": false
|
|
303
|
+
},
|
|
304
|
+
"path": {
|
|
305
|
+
"type": "array",
|
|
306
|
+
"minItems": 1,
|
|
307
|
+
"items": {
|
|
308
|
+
"type": "object",
|
|
309
|
+
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
|
|
310
|
+
"required": ["x", "y"],
|
|
311
|
+
"additionalProperties": false
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
"delta": {
|
|
315
|
+
"type": "object",
|
|
316
|
+
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
|
|
317
|
+
"required": ["x", "y"],
|
|
318
|
+
"additionalProperties": false
|
|
319
|
+
},
|
|
320
|
+
"duration_ms": { "type": "integer", "minimum": 1 },
|
|
321
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
322
|
+
"settle": { "type": "boolean" }
|
|
323
|
+
},
|
|
324
|
+
"required": ["target", "duration_ms"],
|
|
325
|
+
"additionalProperties": false
|
|
326
|
+
},
|
|
327
|
+
"adapter_schemas": {
|
|
328
|
+
"android": {
|
|
329
|
+
"type": "object",
|
|
330
|
+
"properties": {
|
|
331
|
+
"path": {
|
|
332
|
+
"type": "array",
|
|
333
|
+
"maxItems": 1,
|
|
334
|
+
"items": { "type": "object", "additionalProperties": true }
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
"additionalProperties": true
|
|
338
|
+
},
|
|
339
|
+
"ios": {
|
|
340
|
+
"type": "object",
|
|
341
|
+
"properties": {
|
|
342
|
+
"path": {
|
|
343
|
+
"type": "array",
|
|
344
|
+
"maxItems": 1,
|
|
345
|
+
"items": { "type": "object", "additionalProperties": true }
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
"additionalProperties": true
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
"examples": [
|
|
352
|
+
{
|
|
353
|
+
"action": "ui.drag",
|
|
354
|
+
"intent": "Drag the requested control to a new value.",
|
|
355
|
+
"target": "example-slider",
|
|
356
|
+
"delta": { "x": 120, "y": 0 },
|
|
357
|
+
"duration_ms": 500,
|
|
358
|
+
"next": "done"
|
|
359
|
+
}
|
|
360
|
+
]
|
|
361
|
+
},
|
|
362
|
+
"ui.long_press": {
|
|
363
|
+
"description": "Hold a test-id target or explicit screen coordinate for a bounded duration.",
|
|
364
|
+
"adapters": ["android", "ios"],
|
|
365
|
+
"schema": {
|
|
366
|
+
"type": "object",
|
|
367
|
+
"properties": {
|
|
368
|
+
"target": {
|
|
369
|
+
"type": ["string", "object"],
|
|
370
|
+
"properties": { "x": { "type": "number" }, "y": { "type": "number" } },
|
|
371
|
+
"required": ["x", "y"],
|
|
372
|
+
"additionalProperties": false
|
|
373
|
+
},
|
|
374
|
+
"hold_ms": { "type": "integer", "minimum": 1 },
|
|
375
|
+
"timeout_ms": { "type": "integer", "minimum": 1 },
|
|
376
|
+
"settle": { "type": "boolean" }
|
|
377
|
+
},
|
|
378
|
+
"required": ["target", "hold_ms"],
|
|
379
|
+
"additionalProperties": false
|
|
380
|
+
},
|
|
381
|
+
"examples": [
|
|
382
|
+
{
|
|
383
|
+
"action": "ui.long_press",
|
|
384
|
+
"intent": "Hold the requested visible control.",
|
|
385
|
+
"target": "example-control",
|
|
386
|
+
"hold_ms": 700,
|
|
387
|
+
"next": "done"
|
|
388
|
+
}
|
|
389
|
+
]
|
|
390
|
+
},
|
|
391
|
+
"ui.wait_for": {
|
|
392
|
+
"description": "Wait for native accessibility content and UI stability.",
|
|
393
|
+
"schema": {
|
|
394
|
+
"type": "object",
|
|
395
|
+
"properties": {
|
|
396
|
+
"text_contains": {
|
|
397
|
+
"type": "array",
|
|
398
|
+
"items": {
|
|
399
|
+
"type": "string"
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
"timeout_ms": {
|
|
403
|
+
"type": "integer"
|
|
404
|
+
},
|
|
405
|
+
"text": {
|
|
406
|
+
"type": "string"
|
|
407
|
+
},
|
|
408
|
+
"target": {
|
|
409
|
+
"type": "string"
|
|
410
|
+
},
|
|
411
|
+
"test_id": {
|
|
412
|
+
"type": "string"
|
|
413
|
+
},
|
|
414
|
+
"visible": {
|
|
415
|
+
"type": "boolean"
|
|
416
|
+
},
|
|
417
|
+
"event": {
|
|
418
|
+
"type": "string"
|
|
419
|
+
},
|
|
420
|
+
"selector": {
|
|
421
|
+
"type": "string"
|
|
422
|
+
},
|
|
423
|
+
"expected": {
|
|
424
|
+
"type": "string"
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
"additionalProperties": false
|
|
428
|
+
},
|
|
429
|
+
"examples": [
|
|
430
|
+
{
|
|
431
|
+
"action": "ui.wait_for",
|
|
432
|
+
"intent": "Confirm the requested application state is visible.",
|
|
433
|
+
"test_id": "example-control",
|
|
434
|
+
"visible": true,
|
|
435
|
+
"next": "done"
|
|
436
|
+
}
|
|
437
|
+
]
|
|
438
|
+
},
|
|
439
|
+
"ui.screenshot": {
|
|
440
|
+
"description": "Capture the assigned native simulator or device into the artifact package.",
|
|
441
|
+
"schema": {
|
|
442
|
+
"type": "object",
|
|
443
|
+
"properties": {
|
|
444
|
+
"path": {
|
|
445
|
+
"type": "string"
|
|
446
|
+
},
|
|
447
|
+
"label": {
|
|
448
|
+
"type": "string"
|
|
449
|
+
},
|
|
450
|
+
"claims": {
|
|
451
|
+
"type": "object",
|
|
452
|
+
"properties": {
|
|
453
|
+
"must_show": {
|
|
454
|
+
"type": "array",
|
|
455
|
+
"items": {
|
|
456
|
+
"type": "string"
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
"must_not_show": {
|
|
460
|
+
"type": "array",
|
|
461
|
+
"items": {
|
|
462
|
+
"type": "string"
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
"additionalProperties": false
|
|
467
|
+
},
|
|
468
|
+
"covers": {
|
|
469
|
+
"type": "array",
|
|
470
|
+
"items": {
|
|
471
|
+
"type": "string"
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
"note": {
|
|
475
|
+
"type": "string"
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
"additionalProperties": false
|
|
479
|
+
},
|
|
480
|
+
"examples": [
|
|
481
|
+
{
|
|
482
|
+
"action": "ui.screenshot",
|
|
483
|
+
"intent": "Preserve the visible application state as review evidence.",
|
|
484
|
+
"label": "example-state",
|
|
485
|
+
"next": "done"
|
|
486
|
+
}
|
|
487
|
+
]
|
|
488
|
+
},
|
|
489
|
+
"ui.capture_surface": {
|
|
490
|
+
"description": "Capture the full current scrollable screen as one PNG. This action is opt-in; ui.screenshot remains viewport-only.",
|
|
491
|
+
"schema": {
|
|
492
|
+
"type": "object",
|
|
493
|
+
"properties": {
|
|
494
|
+
"path": { "type": "string" },
|
|
495
|
+
"label": { "type": "string" },
|
|
496
|
+
"surface_test_id": { "type": "string" },
|
|
497
|
+
"until_test_id": { "type": "string" },
|
|
498
|
+
"max_scrolls": { "type": "integer" },
|
|
499
|
+
"restore_position": { "type": "boolean" }
|
|
500
|
+
},
|
|
501
|
+
"additionalProperties": false
|
|
502
|
+
},
|
|
503
|
+
"examples": [
|
|
504
|
+
{
|
|
505
|
+
"action": "ui.capture_surface",
|
|
506
|
+
"intent": "Preserve the complete scrollable context for human review.",
|
|
507
|
+
"path": "screenshots/full-screen.png",
|
|
508
|
+
"surface_test_id": "screen-scroll-surface",
|
|
509
|
+
"until_test_id": "screen-bottom",
|
|
510
|
+
"next": "done"
|
|
511
|
+
}
|
|
512
|
+
]
|
|
513
|
+
},
|
|
514
|
+
"assert_output": {
|
|
515
|
+
"description": "assert_output action.",
|
|
516
|
+
"schema": {
|
|
517
|
+
"type": "object",
|
|
518
|
+
"properties": {
|
|
519
|
+
"source": {
|
|
520
|
+
"type": "string"
|
|
521
|
+
},
|
|
522
|
+
"stream": {
|
|
523
|
+
"type": "string"
|
|
524
|
+
},
|
|
525
|
+
"contains": {
|
|
526
|
+
"type": "string"
|
|
527
|
+
},
|
|
528
|
+
"match": {
|
|
529
|
+
"type": "string"
|
|
530
|
+
},
|
|
531
|
+
"assert": {
|
|
532
|
+
"type": "object",
|
|
533
|
+
"additionalProperties": true
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
"required": ["source"],
|
|
537
|
+
"additionalProperties": false
|
|
538
|
+
},
|
|
539
|
+
"examples": [
|
|
540
|
+
{
|
|
541
|
+
"action": "assert_output",
|
|
542
|
+
"intent": "Confirm the recorded output satisfies the requested condition.",
|
|
543
|
+
"source": "command",
|
|
544
|
+
"contains": "ready",
|
|
545
|
+
"next": "done"
|
|
546
|
+
}
|
|
547
|
+
]
|
|
548
|
+
},
|
|
549
|
+
"wait": {
|
|
550
|
+
"description": "Pause briefly for asynchronous setup work. Keep waits short and prefer deterministic assertions.",
|
|
551
|
+
"schema": {
|
|
552
|
+
"type": "object",
|
|
553
|
+
"properties": {
|
|
554
|
+
"duration_ms": {
|
|
555
|
+
"type": "integer"
|
|
556
|
+
}
|
|
557
|
+
},
|
|
558
|
+
"required": ["duration_ms"],
|
|
559
|
+
"additionalProperties": false
|
|
560
|
+
},
|
|
561
|
+
"examples": [
|
|
562
|
+
{
|
|
563
|
+
"action": "wait",
|
|
564
|
+
"intent": "Allow the requested asynchronous state to settle.",
|
|
565
|
+
"duration_ms": 1,
|
|
566
|
+
"next": "done"
|
|
567
|
+
}
|
|
568
|
+
]
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
"observers": [
|
|
572
|
+
{
|
|
573
|
+
"ref": "ui.screen",
|
|
574
|
+
"default_for": [
|
|
575
|
+
"ui.press",
|
|
576
|
+
"ui.set_input",
|
|
577
|
+
"ui.scroll",
|
|
578
|
+
"ui.swipe",
|
|
579
|
+
"ui.pan",
|
|
580
|
+
"ui.drag",
|
|
581
|
+
"ui.long_press",
|
|
582
|
+
"ui.wait_for"
|
|
583
|
+
]
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
"ref": "ui.visible",
|
|
587
|
+
"default_for": [
|
|
588
|
+
"ui.press",
|
|
589
|
+
"ui.set_input",
|
|
590
|
+
"ui.scroll",
|
|
591
|
+
"ui.swipe",
|
|
592
|
+
"ui.pan",
|
|
593
|
+
"ui.drag",
|
|
594
|
+
"ui.long_press",
|
|
595
|
+
"ui.wait_for"
|
|
596
|
+
]
|
|
597
|
+
}
|
|
598
|
+
]
|
|
599
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
|
|
3
|
+
"title": "Expo configuration smoke",
|
|
4
|
+
"description": "Verifies the Expo project can run a Farmslot Recipe Protocol v1 artifact-producing configuration check.",
|
|
5
|
+
"proofTargets": [
|
|
6
|
+
{
|
|
7
|
+
"id": "expo-config",
|
|
8
|
+
"claim": "The Expo project can execute a Farmslot recipe runner and expose public config without secrets."
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"workflow": {
|
|
12
|
+
"entry": "expo-config",
|
|
13
|
+
"nodes": {
|
|
14
|
+
"expo-config": {
|
|
15
|
+
"action": "command",
|
|
16
|
+
"intent": "Read Expo public config through the project package manager",
|
|
17
|
+
"cmd": "yarn expo config --type public --json",
|
|
18
|
+
"timeout_ms": 120000,
|
|
19
|
+
"next": "assert-config",
|
|
20
|
+
"proves": ["expo-config"]
|
|
21
|
+
},
|
|
22
|
+
"assert-config": {
|
|
23
|
+
"action": "assert_output",
|
|
24
|
+
"intent": "Confirm the Expo public config contains a slug field",
|
|
25
|
+
"source": "expo-config",
|
|
26
|
+
"stream": "stdout",
|
|
27
|
+
"contains": "\"slug\"",
|
|
28
|
+
"next": "done",
|
|
29
|
+
"proves": ["expo-config"]
|
|
30
|
+
},
|
|
31
|
+
"done": {
|
|
32
|
+
"action": "end",
|
|
33
|
+
"status": "pass"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
APP_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
|
6
|
+
|
|
7
|
+
RECIPE_PATH="scripts/agentic/recipe/recipes/expo.config.recipe.json"
|
|
8
|
+
ARTIFACTS_DIR=""
|
|
9
|
+
DRY_RUN=0
|
|
10
|
+
|
|
11
|
+
value_from_equals() {
|
|
12
|
+
local option="$1"
|
|
13
|
+
local value="${option#*=}"
|
|
14
|
+
if [[ -z "${value}" ]]; then
|
|
15
|
+
echo "ERROR: ${option%%=*} requires a value." >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
printf '%s' "${value}"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
require_value() {
|
|
22
|
+
local option="$1"
|
|
23
|
+
local value="${2:-}"
|
|
24
|
+
if [[ -z "${value}" || "${value}" == --* ]]; then
|
|
25
|
+
echo "ERROR: ${option} requires a value." >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
printf '%s' "${value}"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
while [[ "$#" -gt 0 ]]; do
|
|
32
|
+
case "$1" in
|
|
33
|
+
--recipe)
|
|
34
|
+
RECIPE_PATH="$(require_value "$1" "${2:-}")"; shift 2 ;;
|
|
35
|
+
--recipe=*)
|
|
36
|
+
RECIPE_PATH="$(value_from_equals "$1")"; shift ;;
|
|
37
|
+
--artifacts-dir)
|
|
38
|
+
ARTIFACTS_DIR="$(require_value "$1" "${2:-}")"; shift 2 ;;
|
|
39
|
+
--artifacts-dir=*)
|
|
40
|
+
ARTIFACTS_DIR="$(value_from_equals "$1")"; shift ;;
|
|
41
|
+
--dry-run)
|
|
42
|
+
DRY_RUN=1; shift ;;
|
|
43
|
+
--runtime-dir|--platform|--metro-port|--simulator|--adb-serial)
|
|
44
|
+
require_value "$1" "${2:-}" >/dev/null; shift 2 ;;
|
|
45
|
+
--runtime-dir=*|--platform=*|--metro-port=*|--simulator=*|--adb-serial=*)
|
|
46
|
+
shift ;;
|
|
47
|
+
*)
|
|
48
|
+
echo "ERROR: unknown recipe validation option '$1'." >&2
|
|
49
|
+
exit 1 ;;
|
|
50
|
+
esac
|
|
51
|
+
done
|
|
52
|
+
|
|
53
|
+
if [[ -z "${ARTIFACTS_DIR}" ]]; then
|
|
54
|
+
echo "ERROR: --artifacts-dir is required." >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
ARGS=(farmslot-adapter-rn run "${RECIPE_PATH}" --artifacts-dir "${ARTIFACTS_DIR}")
|
|
59
|
+
if [[ "${DRY_RUN}" -eq 1 ]]; then
|
|
60
|
+
ARGS+=(--dry-run)
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
cd "${APP_DIR}"
|
|
64
|
+
yarn "${ARGS[@]}"
|