@deeeed/metamask-harness 0.20.0 → 0.21.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.
@@ -1,30 +1,14 @@
1
1
  {
2
- "runner_protocol_version": 1,
3
- "action_registry_version": 1,
4
- "supported_official_actions": [
5
- "command",
6
- "wait",
7
- "assert_file",
8
- "assert_json",
9
- "assert_exit_code",
10
- "assert_output",
11
- "watch_logs",
12
- "index_artifacts",
13
- "end",
14
- "call",
15
- "switch",
16
- "app.status"
17
- ],
18
- "action_metadata": {
2
+ "$schema": "https://farmslot.io/schemas/action-manifest-v1.schema.json",
3
+ "actions": {
19
4
  "command": {
20
5
  "description": "Run a shell command from the project root.",
21
6
  "examples": [
22
7
  {
23
- "node": {
24
- "action": "command",
25
- "cmd": "pwd",
26
- "intent": "Run a shell command from the project root"
27
- }
8
+ "action": "command",
9
+ "cmd": "pwd",
10
+ "intent": "Prepare the project state needed for this proof.",
11
+ "next": "done"
28
12
  }
29
13
  ],
30
14
  "schema": {
@@ -53,11 +37,10 @@
53
37
  "description": "Base wait action.",
54
38
  "examples": [
55
39
  {
56
- "node": {
57
- "action": "wait",
58
- "duration_ms": 1,
59
- "intent": "Base wait action"
60
- }
40
+ "action": "wait",
41
+ "duration_ms": 1,
42
+ "intent": "Allow the requested asynchronous state to settle.",
43
+ "next": "done"
61
44
  }
62
45
  ],
63
46
  "schema": {
@@ -73,153 +56,15 @@
73
56
  "additionalProperties": false
74
57
  }
75
58
  },
76
- "switch": {
77
- "description": "Choose a graph branch when one resolved string equals another.",
78
- "examples": [
79
- {
80
- "node": {
81
- "action": "switch",
82
- "value": "{{params.mode}}",
83
- "equals": "background_resume",
84
- "cases": { "match": "background" },
85
- "default": "warm",
86
- "intent": "Choose the requested lifecycle preparation path"
87
- }
88
- }
89
- ],
90
- "schema": {
91
- "type": "object",
92
- "properties": {
93
- "value": { "type": "string" },
94
- "equals": { "type": "string" }
95
- },
96
- "required": ["value", "equals"],
97
- "additionalProperties": false
98
- },
99
- "result_cases": ["match"]
100
- },
101
- "watch_logs": {
102
- "description": "Base log assertion/capture action.",
103
- "examples": [
104
- {
105
- "node": {
106
- "action": "watch_logs",
107
- "path": "logs/app.log",
108
- "intent": "Base log assertion/capture action"
109
- }
110
- }
111
- ],
112
- "schema": {
113
- "type": "object",
114
- "properties": {
115
- "path": {
116
- "type": "string"
117
- },
118
- "contains": {
119
- "type": "string"
120
- },
121
- "scope": {
122
- "type": "string",
123
- "enum": [
124
- "run",
125
- "file"
126
- ]
127
- }
128
- },
129
- "required": [
130
- "path"
131
- ],
132
- "additionalProperties": false
133
- }
134
- },
135
- "index_artifacts": {
136
- "description": "Index extra recipe-authored artifacts that already exist on disk.",
137
- "examples": [
138
- {
139
- "node": {
140
- "action": "index_artifacts",
141
- "artifacts": [
142
- {
143
- "path": "reports/result.json",
144
- "type": "report",
145
- "category": "validation",
146
- "label": "Validation report"
147
- }
148
- ],
149
- "intent": "Register a pre-existing report artifact"
150
- }
151
- }
152
- ],
153
- "schema": {
154
- "type": "object",
155
- "properties": {
156
- "artifacts": {
157
- "type": "array",
158
- "items": {
159
- "type": [
160
- "string",
161
- "object"
162
- ],
163
- "properties": {
164
- "path": {
165
- "type": "string"
166
- },
167
- "type": {
168
- "type": "string"
169
- },
170
- "label": {
171
- "type": "string"
172
- },
173
- "nodeId": {
174
- "type": "string"
175
- },
176
- "mimeType": {
177
- "type": "string"
178
- },
179
- "category": {
180
- "type": "string"
181
- },
182
- "proofTarget": {
183
- "type": "string"
184
- },
185
- "covers": {
186
- "type": "array",
187
- "items": {
188
- "type": "string"
189
- }
190
- }
191
- },
192
- "additionalProperties": false
193
- }
194
- }
195
- },
196
- "required": [
197
- "artifacts"
198
- ],
199
- "additionalProperties": false
200
- }
201
- },
202
- "end": {
203
- "description": "Base terminal action.",
204
- "examples": [
205
- {
206
- "node": {
207
- "action": "end",
208
- "status": "pass"
209
- }
210
- }
211
- ]
212
- },
213
59
  "assert_file": {
214
60
  "description": "Assert that a project file exists and optionally contains text.",
215
61
  "examples": [
216
62
  {
217
- "node": {
218
- "action": "assert_file",
219
- "path": "reports/result.txt",
220
- "contains": "ok",
221
- "intent": "Assert that a project file exists and optionally contains text"
222
- }
63
+ "action": "assert_file",
64
+ "path": "reports/result.txt",
65
+ "contains": "ok",
66
+ "intent": "Confirm the requested project file state.",
67
+ "next": "done"
223
68
  }
224
69
  ],
225
70
  "schema": {
@@ -242,16 +87,15 @@
242
87
  "description": "Assert a JSON file value with a JSONPath-style selector.",
243
88
  "examples": [
244
89
  {
245
- "node": {
246
- "action": "assert_json",
247
- "path": "reports/result.json",
248
- "assert": {
249
- "path": "$.status",
250
- "operator": "eq",
251
- "value": "ok"
252
- },
253
- "intent": "Assert a JSON file value with a JSONPath-style selector"
254
- }
90
+ "action": "assert_json",
91
+ "path": "reports/result.json",
92
+ "assert": {
93
+ "path": "$.status",
94
+ "operator": "eq",
95
+ "value": "ok"
96
+ },
97
+ "intent": "Confirm the recorded data satisfies the requested condition.",
98
+ "next": "done"
255
99
  }
256
100
  ],
257
101
  "schema": {
@@ -321,12 +165,11 @@
321
165
  "description": "Assert the exit code captured from a command node output.",
322
166
  "examples": [
323
167
  {
324
- "node": {
325
- "action": "assert_exit_code",
326
- "source": "run-tests",
327
- "expected": 0,
328
- "intent": "Assert the exit code captured from a command node output"
329
- }
168
+ "action": "assert_exit_code",
169
+ "source": "run-tests",
170
+ "expected": 0,
171
+ "intent": "Confirm the project command completed with the expected result.",
172
+ "next": "done"
330
173
  }
331
174
  ],
332
175
  "schema": {
@@ -349,13 +192,12 @@
349
192
  "description": "Assert stdout or stderr captured from a command node output.",
350
193
  "examples": [
351
194
  {
352
- "node": {
353
- "action": "assert_output",
354
- "source": "run-tests",
355
- "stream": "stdout",
356
- "contains": "PASS",
357
- "intent": "Assert stdout or stderr captured from a command node output"
358
- }
195
+ "action": "assert_output",
196
+ "source": "run-tests",
197
+ "stream": "stdout",
198
+ "contains": "PASS",
199
+ "intent": "Confirm the recorded output satisfies the requested condition.",
200
+ "next": "done"
359
201
  }
360
202
  ],
361
203
  "schema": {
@@ -429,40 +271,175 @@
429
271
  "additionalProperties": false
430
272
  }
431
273
  },
432
- "app.status": {
433
- "description": "Report the core checkout shape and headless compatibility mode for the perps controller.",
274
+ "watch_logs": {
275
+ "description": "Base log assertion/capture action.",
434
276
  "examples": [
435
277
  {
436
- "node": {
437
- "action": "app.status",
438
- "intent": "Report the resolved core checkout status",
439
- "next": "done"
278
+ "action": "watch_logs",
279
+ "path": "logs/app.log",
280
+ "intent": "Observe the runtime behavior needed for this proof.",
281
+ "next": "done"
282
+ }
283
+ ],
284
+ "schema": {
285
+ "type": "object",
286
+ "properties": {
287
+ "path": {
288
+ "type": "string"
289
+ },
290
+ "contains": {
291
+ "type": "string"
292
+ },
293
+ "scope": {
294
+ "type": "string",
295
+ "enum": [
296
+ "run",
297
+ "file"
298
+ ]
440
299
  }
300
+ },
301
+ "required": [
302
+ "path"
303
+ ],
304
+ "additionalProperties": false
305
+ }
306
+ },
307
+ "index_artifacts": {
308
+ "description": "Index extra recipe-authored artifacts that already exist on disk.",
309
+ "examples": [
310
+ {
311
+ "action": "index_artifacts",
312
+ "artifacts": [
313
+ {
314
+ "path": "reports/result.json",
315
+ "type": "report",
316
+ "category": "validation",
317
+ "label": "Validation report"
318
+ }
319
+ ],
320
+ "intent": "Preserve generated evidence in the review package.",
321
+ "next": "done"
441
322
  }
442
323
  ],
443
324
  "schema": {
444
325
  "type": "object",
445
- "properties": {},
326
+ "properties": {
327
+ "artifacts": {
328
+ "type": "array",
329
+ "items": {
330
+ "type": [
331
+ "string",
332
+ "object"
333
+ ],
334
+ "properties": {
335
+ "path": {
336
+ "type": "string"
337
+ },
338
+ "type": {
339
+ "type": "string"
340
+ },
341
+ "label": {
342
+ "type": "string"
343
+ },
344
+ "nodeId": {
345
+ "type": "string"
346
+ },
347
+ "mimeType": {
348
+ "type": "string"
349
+ },
350
+ "category": {
351
+ "type": "string"
352
+ },
353
+ "proofTarget": {
354
+ "type": "string"
355
+ },
356
+ "covers": {
357
+ "type": "array",
358
+ "items": {
359
+ "type": "string"
360
+ }
361
+ }
362
+ },
363
+ "additionalProperties": false
364
+ }
365
+ }
366
+ },
367
+ "required": [
368
+ "artifacts"
369
+ ],
446
370
  "additionalProperties": false
447
371
  }
448
372
  },
373
+ "end": {
374
+ "description": "Base terminal action.",
375
+ "examples": [
376
+ {
377
+ "action": "end",
378
+ "status": "pass"
379
+ }
380
+ ]
381
+ },
449
382
  "call": {
450
383
  "description": "Invoke a named recipe by ref and run its steps inline.",
451
384
  "examples": [
452
385
  {
453
- "node": {
454
- "action": "call",
455
- "ref": "shared/setup",
456
- "intent": "Run a shared recipe"
457
- }
386
+ "action": "call",
387
+ "ref": "shared/setup",
388
+ "intent": "Run a shared recipe",
389
+ "next": "done"
458
390
  }
459
391
  ]
460
- }
461
- },
462
- "custom_actions": [
463
- {
464
- "name": "metamask.wallet.list_accounts",
465
- "owner": "metamask",
392
+ },
393
+ "switch": {
394
+ "description": "Choose a graph branch when one resolved string equals another.",
395
+ "examples": [
396
+ {
397
+ "action": "switch",
398
+ "value": "{{params.mode}}",
399
+ "equals": "background_resume",
400
+ "cases": {
401
+ "match": "background"
402
+ },
403
+ "default": "warm",
404
+ "intent": "Choose the graph path matching the observed state."
405
+ }
406
+ ],
407
+ "schema": {
408
+ "type": "object",
409
+ "properties": {
410
+ "value": {
411
+ "type": "string"
412
+ },
413
+ "equals": {
414
+ "type": "string"
415
+ }
416
+ },
417
+ "required": [
418
+ "value",
419
+ "equals"
420
+ ],
421
+ "additionalProperties": false
422
+ },
423
+ "result_cases": [
424
+ "match"
425
+ ]
426
+ },
427
+ "app.status": {
428
+ "description": "Report the core checkout shape and headless compatibility mode for the perps controller.",
429
+ "examples": [
430
+ {
431
+ "action": "app.status",
432
+ "intent": "Record the resolved application state before continuing.",
433
+ "next": "done"
434
+ }
435
+ ],
436
+ "schema": {
437
+ "type": "object",
438
+ "properties": {},
439
+ "additionalProperties": false
440
+ }
441
+ },
442
+ "metamask.wallet.list_accounts": {
466
443
  "description": "List redacted headless fixture accounts available to Core controller actions.",
467
444
  "schema": {
468
445
  "type": "object",
@@ -492,20 +469,14 @@
492
469
  },
493
470
  "examples": [
494
471
  {
495
- "description": "List configured Core accounts",
496
- "node": {
497
- "action": "metamask.wallet.list_accounts",
498
- "intent": "Discover the accounts available to headless controller actions"
499
- }
472
+ "action": "metamask.wallet.list_accounts",
473
+ "intent": "Discover the accounts available to headless controller actions",
474
+ "next": "done"
500
475
  }
501
476
  ],
502
- "proof_effect": "Records the redacted addresses derived from the same wallet fixture used by headless controller actions.",
503
- "safety_notes": "Read-only fixture metadata; must never return private keys, mnemonics, passwords, or vault data.",
504
477
  "execution_capabilities": []
505
478
  },
506
- {
507
- "name": "metamask.perps.read_positions",
508
- "owner": "metamask",
479
+ "metamask.perps.read_positions": {
509
480
  "description": "core Read live Perps positions directly from the Perps controller; without a selector, return all live positions.",
510
481
  "schema": {
511
482
  "type": "object",
@@ -607,21 +578,15 @@
607
578
  },
608
579
  "examples": [
609
580
  {
610
- "description": "Read every live position for the configured account",
611
- "node": {
612
- "action": "metamask.perps.read_positions",
613
- "mode": "all",
614
- "intent": "Read Perps positions from the headless controller"
615
- }
581
+ "action": "metamask.perps.read_positions",
582
+ "mode": "all",
583
+ "intent": "Read Perps positions from the headless controller",
584
+ "next": "done"
616
585
  }
617
586
  ],
618
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or controller output.",
619
- "safety_notes": "Read-only HyperLiquid query on the explicitly selected network; must not inject controller/UI state to fabricate proof.",
620
587
  "execution_capabilities": []
621
588
  },
622
- {
623
- "name": "metamask.perps.read_orders",
624
- "owner": "metamask",
589
+ "metamask.perps.read_orders": {
625
590
  "description": "core Read live Perps open orders directly from the Perps controller; without a selector, return all live orders.",
626
591
  "schema": {
627
592
  "type": "object",
@@ -723,21 +688,15 @@
723
688
  },
724
689
  "examples": [
725
690
  {
726
- "description": "Read every live open order for the configured account",
727
- "node": {
728
- "action": "metamask.perps.read_orders",
729
- "mode": "all",
730
- "intent": "Read Perps open orders from the headless controller"
731
- }
691
+ "action": "metamask.perps.read_orders",
692
+ "mode": "all",
693
+ "intent": "Read Perps open orders from the headless controller",
694
+ "next": "done"
732
695
  }
733
696
  ],
734
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or controller output.",
735
- "safety_notes": "Read-only HyperLiquid query on the explicitly selected network; must not inject controller/UI state to fabricate proof.",
736
697
  "execution_capabilities": []
737
698
  },
738
- {
739
- "name": "metamask.perps.read_account",
740
- "owner": "metamask",
699
+ "metamask.perps.read_account": {
741
700
  "description": "core Read live Perps account state (balances, margin) directly from the perps controller (HyperLiquid testnet, HTTP read-only).",
742
701
  "schema": {
743
702
  "type": "object",
@@ -754,20 +713,14 @@
754
713
  },
755
714
  "examples": [
756
715
  {
757
- "description": "Read account state for the configured account",
758
- "node": {
759
- "action": "metamask.perps.read_account",
760
- "intent": "Read Perps account state from the headless controller"
761
- }
716
+ "action": "metamask.perps.read_account",
717
+ "intent": "Read Perps account state from the headless controller",
718
+ "next": "done"
762
719
  }
763
720
  ],
764
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or controller output.",
765
- "safety_notes": "Read-only HyperLiquid testnet HTTP query; must not inject controller/UI state to fabricate proof.",
766
721
  "execution_capabilities": []
767
722
  },
768
- {
769
- "name": "metamask.perps.place_order",
770
- "owner": "metamask",
723
+ "metamask.perps.place_order": {
771
724
  "description": "core Place a real Perps order on HyperLiquid testnet by driving the headless perps controller placeOrder() through the full signing/provider path. Testnet only Supports market (default) and resting limit orders (order_type=limit with price/offset_pct).",
772
725
  "schema": {
773
726
  "type": "object",
@@ -886,40 +839,32 @@
886
839
  },
887
840
  "examples": [
888
841
  {
889
- "description": "Place a small BTC long market order on testnet",
890
- "node": {
891
- "action": "metamask.perps.place_order",
892
- "market": "BTC",
893
- "side": "long",
894
- "notional": "11",
895
- "leverage": 2,
896
- "intent": "Place the requested Perps order via the headless controller"
897
- }
842
+ "action": "metamask.perps.place_order",
843
+ "market": "BTC",
844
+ "side": "long",
845
+ "notional": "11",
846
+ "leverage": 2,
847
+ "intent": "Place the requested Perps order via the headless controller",
848
+ "next": "done"
898
849
  },
899
850
  {
900
- "description": "Place a resting BTC limit BUY 30%% below mid on testnet (does not fill)",
901
- "node": {
902
- "action": "metamask.perps.place_order",
903
- "market": "BTC",
904
- "side": "long",
905
- "order_type": "limit",
906
- "offset_pct": -30,
907
- "notional": "11",
908
- "leverage": 2,
909
- "intent": "Place a resting Perps limit order via the headless controller"
910
- }
851
+ "action": "metamask.perps.place_order",
852
+ "market": "BTC",
853
+ "side": "long",
854
+ "order_type": "limit",
855
+ "offset_pct": -30,
856
+ "notional": "11",
857
+ "leverage": 2,
858
+ "intent": "Place a resting Perps limit order via the headless controller",
859
+ "next": "done"
911
860
  }
912
861
  ],
913
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or controller output (order id, opened position).",
914
- "safety_notes": "Submits a REAL signed order to HyperLiquid testnet; must not mock the signer/provider or inject controller state to fabricate proof.",
915
862
  "execution_capabilities": [
916
863
  "app-mutation",
917
864
  "external-mutation"
918
865
  ]
919
866
  },
920
- {
921
- "name": "metamask.perps.close_positions",
922
- "owner": "metamask",
867
+ "metamask.perps.close_positions": {
923
868
  "description": "core Close selected live Perps positions on HyperLiquid testnet by driving the headless perps controller closePosition() through the full signing/provider path. Testnet only.",
924
869
  "schema": {
925
870
  "type": "object",
@@ -1012,24 +957,18 @@
1012
957
  },
1013
958
  "examples": [
1014
959
  {
1015
- "description": "Close the BTC position on testnet",
1016
- "node": {
1017
- "action": "metamask.perps.close_positions",
1018
- "market": "BTC",
1019
- "intent": "Close selected Perps positions via the headless controller"
1020
- }
960
+ "action": "metamask.perps.close_positions",
961
+ "market": "BTC",
962
+ "intent": "Close selected Perps positions via the headless controller",
963
+ "next": "done"
1021
964
  }
1022
965
  ],
1023
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or controller output (positions absent after close).",
1024
- "safety_notes": "Submits REAL signed close orders to HyperLiquid testnet; must not mock the signer/provider or inject controller state to fabricate proof.",
1025
966
  "execution_capabilities": [
1026
967
  "app-mutation",
1027
968
  "external-mutation"
1028
969
  ]
1029
970
  },
1030
- {
1031
- "name": "metamask.perps.assert_positions",
1032
- "owner": "metamask",
971
+ "metamask.perps.assert_positions": {
1033
972
  "description": "core Assert live Perps positions are present or absent for an explicit market selection or mode=all.",
1034
973
  "schema": {
1035
974
  "type": "object",
@@ -1145,22 +1084,16 @@
1145
1084
  },
1146
1085
  "examples": [
1147
1086
  {
1148
- "description": "Assert BTC position is open",
1149
- "node": {
1150
- "action": "metamask.perps.assert_positions",
1151
- "state": "open",
1152
- "market": "BTC",
1153
- "intent": "Assert the expected Perps position state via the headless controller"
1154
- }
1087
+ "action": "metamask.perps.assert_positions",
1088
+ "state": "open",
1089
+ "market": "BTC",
1090
+ "intent": "Assert the expected Perps position state via the headless controller",
1091
+ "next": "done"
1155
1092
  }
1156
1093
  ],
1157
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or controller output.",
1158
- "safety_notes": "Read-only HyperLiquid query on the explicitly selected network; must not inject controller state to fabricate proof.",
1159
1094
  "execution_capabilities": []
1160
1095
  },
1161
- {
1162
- "name": "metamask.perps.ensure_positions",
1163
- "owner": "metamask",
1096
+ "metamask.perps.ensure_positions": {
1164
1097
  "description": "core Higher-level wrapper that reads selected positions, places or closes via the headless controller as needed, then asserts the final position state. Testnet only.",
1165
1098
  "schema": {
1166
1099
  "type": "object",
@@ -1284,36 +1217,28 @@
1284
1217
  },
1285
1218
  "examples": [
1286
1219
  {
1287
- "description": "Ensure no BTC position before the proof window",
1288
- "node": {
1289
- "action": "metamask.perps.ensure_positions",
1290
- "state": "none",
1291
- "market": "BTC",
1292
- "intent": "Converge Perps positions to the requested state via the headless controller"
1293
- }
1220
+ "action": "metamask.perps.ensure_positions",
1221
+ "state": "none",
1222
+ "market": "BTC",
1223
+ "intent": "Converge Perps positions to the requested state via the headless controller",
1224
+ "next": "done"
1294
1225
  },
1295
1226
  {
1296
- "description": "Ensure one ETH long position exists",
1297
- "node": {
1298
- "action": "metamask.perps.ensure_positions",
1299
- "market": "ETH",
1300
- "side": "long",
1301
- "state": "open",
1302
- "notional": "10",
1303
- "intent": "Converge ETH positions to one explicit testnet precondition"
1304
- }
1227
+ "action": "metamask.perps.ensure_positions",
1228
+ "market": "ETH",
1229
+ "side": "long",
1230
+ "state": "open",
1231
+ "notional": "10",
1232
+ "intent": "Converge ETH positions to one explicit testnet precondition",
1233
+ "next": "done"
1305
1234
  }
1306
1235
  ],
1307
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or controller output.",
1308
- "safety_notes": "May submit REAL signed orders to HyperLiquid testnet; must not mock the signer/provider or inject controller state to fabricate proof.",
1309
1236
  "execution_capabilities": [
1310
1237
  "app-mutation",
1311
1238
  "external-mutation"
1312
1239
  ]
1313
1240
  },
1314
- {
1315
- "name": "metamask.perps.close_orders",
1316
- "owner": "metamask",
1241
+ "metamask.perps.close_orders": {
1317
1242
  "description": "core Default to testnet for Perps mutations; mainnet is read-only unless explicitly requested. Cancel selected live Perps open orders. Use selector/mode params to cancel matching symbols or all orders.",
1318
1243
  "schema": {
1319
1244
  "type": "object",
@@ -1402,32 +1327,24 @@
1402
1327
  },
1403
1328
  "examples": [
1404
1329
  {
1405
- "description": "Cancel every open order",
1406
- "node": {
1407
- "action": "metamask.perps.close_orders",
1408
- "mode": "all",
1409
- "intent": "Cancel selected Perps orders before continuing"
1410
- }
1330
+ "action": "metamask.perps.close_orders",
1331
+ "mode": "all",
1332
+ "intent": "Cancel selected Perps orders before continuing",
1333
+ "next": "done"
1411
1334
  },
1412
1335
  {
1413
- "description": "Cancel BTC orders only",
1414
- "node": {
1415
- "action": "metamask.perps.close_orders",
1416
- "market": "BTC",
1417
- "intent": "Cancel selected Perps orders before continuing"
1418
- }
1336
+ "action": "metamask.perps.close_orders",
1337
+ "market": "BTC",
1338
+ "intent": "Cancel selected Perps orders before continuing",
1339
+ "next": "done"
1419
1340
  }
1420
1341
  ],
1421
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or target runtime output.",
1422
- "safety_notes": "Must not inject mid-recipe UI/app state to fabricate proof.",
1423
1342
  "execution_capabilities": [
1424
1343
  "app-mutation",
1425
1344
  "external-mutation"
1426
1345
  ]
1427
1346
  },
1428
- {
1429
- "name": "metamask.perps.assert_orders",
1430
- "owner": "metamask",
1347
+ "metamask.perps.assert_orders": {
1431
1348
  "description": "core Assert live Perps open orders are present or absent for an explicit market selection or mode=all.",
1432
1349
  "schema": {
1433
1350
  "type": "object",
@@ -1539,22 +1456,16 @@
1539
1456
  },
1540
1457
  "examples": [
1541
1458
  {
1542
- "description": "Assert no BTC open orders",
1543
- "node": {
1544
- "action": "metamask.perps.assert_orders",
1545
- "state": "none",
1546
- "market": "BTC",
1547
- "intent": "Assert the expected Perps open order state"
1548
- }
1459
+ "action": "metamask.perps.assert_orders",
1460
+ "state": "none",
1461
+ "market": "BTC",
1462
+ "intent": "Assert the expected Perps open order state",
1463
+ "next": "done"
1549
1464
  }
1550
1465
  ],
1551
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or target runtime output.",
1552
- "safety_notes": "Read-only HyperLiquid query on the explicitly selected network; must not inject mid-recipe state to fabricate proof.",
1553
1466
  "execution_capabilities": []
1554
1467
  },
1555
- {
1556
- "name": "metamask.perps.ensure_orders",
1557
- "owner": "metamask",
1468
+ "metamask.perps.ensure_orders": {
1558
1469
  "description": "core Default to testnet for Perps mutations; mainnet is read-only unless explicitly requested.Higher-level wrapper that reads selected orders, cancels when needed, then asserts final order state.",
1559
1470
  "schema": {
1560
1471
  "type": "object",
@@ -1675,37 +1586,29 @@
1675
1586
  },
1676
1587
  "examples": [
1677
1588
  {
1678
- "description": "Ensure no open orders before proof window",
1679
- "node": {
1680
- "action": "metamask.perps.ensure_orders",
1681
- "state": "none",
1682
- "mode": "all",
1683
- "intent": "Converge Perps orders to the requested state"
1684
- }
1589
+ "action": "metamask.perps.ensure_orders",
1590
+ "state": "none",
1591
+ "mode": "all",
1592
+ "intent": "Converge Perps orders to the requested state",
1593
+ "next": "done"
1685
1594
  },
1686
1595
  {
1687
- "description": "Ensure one resting ETH short order exists",
1688
- "node": {
1689
- "action": "metamask.perps.ensure_orders",
1690
- "market": "ETH",
1691
- "side": "short",
1692
- "state": "open",
1693
- "notional": "10",
1694
- "leverage": 2,
1695
- "intent": "Converge ETH open orders to one explicit testnet precondition"
1696
- }
1596
+ "action": "metamask.perps.ensure_orders",
1597
+ "market": "ETH",
1598
+ "side": "short",
1599
+ "state": "open",
1600
+ "notional": "10",
1601
+ "leverage": 2,
1602
+ "intent": "Converge ETH open orders to one explicit testnet precondition",
1603
+ "next": "done"
1697
1604
  }
1698
1605
  ],
1699
- "proof_effect": "E2E validation must record this action in trace.json; live-proof actions include liveAdapter/proofPath or target runtime output.",
1700
- "safety_notes": "Must not inject mid-recipe UI/app state to fabricate proof.",
1701
1606
  "execution_capabilities": [
1702
1607
  "app-mutation",
1703
1608
  "external-mutation"
1704
1609
  ]
1705
1610
  },
1706
- {
1707
- "name": "metamask.perps.start_state",
1708
- "owner": "metamask",
1611
+ "metamask.perps.start_state": {
1709
1612
  "description": "core Default to testnet for Perps mutations; mainnet is read-only unless explicitly requested.Recommended configurable Perps start state that composes reusable domain operations before the proof window. Headless: converges POSITION and ORDER baselines on testnet via the controller; no navigation/page/HUD.",
1710
1613
  "schema": {
1711
1614
  "type": "object",
@@ -1993,48 +1896,40 @@
1993
1896
  },
1994
1897
  "examples": [
1995
1898
  {
1996
- "description": "Clean BTC testnet market state",
1997
- "node": {
1998
- "action": "metamask.perps.start_state",
1999
- "profile": "clean_market_testnet",
2000
- "market": "BTC",
2001
- "positions": {
2002
- "state": "none"
2003
- },
2004
- "orders": {
2005
- "state": "none"
2006
- },
2007
- "intent": "Prepare the Perps start state for the proof",
2008
- "network": "testnet"
2009
- }
1899
+ "action": "metamask.perps.start_state",
1900
+ "profile": "clean_market_testnet",
1901
+ "market": "BTC",
1902
+ "positions": {
1903
+ "state": "none"
1904
+ },
1905
+ "orders": {
1906
+ "state": "none"
1907
+ },
1908
+ "intent": "Prepare the Perps start state for the proof",
1909
+ "network": "testnet",
1910
+ "next": "done"
2010
1911
  },
2011
1912
  {
2012
- "description": "Start with an open ETH long position",
2013
- "node": {
2014
- "action": "metamask.perps.start_state",
2015
- "profile": "open_position_testnet",
2016
- "market": "ETH",
2017
- "side": "long",
2018
- "positions": {
2019
- "state": "open",
2020
- "notional": "10",
2021
- "leverage": 2
2022
- },
2023
- "intent": "Prepare the Perps start state for the proof",
2024
- "network": "testnet"
2025
- }
1913
+ "action": "metamask.perps.start_state",
1914
+ "profile": "open_position_testnet",
1915
+ "market": "ETH",
1916
+ "side": "long",
1917
+ "positions": {
1918
+ "state": "open",
1919
+ "notional": "10",
1920
+ "leverage": 2
1921
+ },
1922
+ "intent": "Prepare the Perps start state for the proof",
1923
+ "network": "testnet",
1924
+ "next": "done"
2026
1925
  }
2027
1926
  ],
2028
- "proof_effect": "Runs in setup/teardown phase and must be visible in trace.json; proof videos can keep this as trace-only setup.",
2029
- "safety_notes": "Composes supported app/API paths and must not mutate React/Redux/MobX/DOM/local storage to fabricate proof.",
2030
1927
  "execution_capabilities": [
2031
1928
  "app-mutation",
2032
1929
  "external-mutation"
2033
1930
  ]
2034
1931
  },
2035
- {
2036
- "name": "metamask.perps.teardown_state",
2037
- "owner": "metamask",
1932
+ "metamask.perps.teardown_state": {
2038
1933
  "description": "core Recommended configurable Perps teardown state that restores the selected environment after proof. Headless: converges POSITION and ORDER baselines on testnet via the controller; no navigation/page/HUD.",
2039
1934
  "schema": {
2040
1935
  "type": "object",
@@ -2322,108 +2217,28 @@
2322
2217
  },
2323
2218
  "examples": [
2324
2219
  {
2325
- "description": "Return BTC test account to clean state",
2326
- "node": {
2327
- "action": "metamask.perps.teardown_state",
2328
- "market": "BTC",
2329
- "positions": {
2330
- "state": "none"
2331
- },
2332
- "orders": {
2333
- "state": "none"
2334
- },
2335
- "intent": "Restore Perps state after the proof"
2336
- }
2220
+ "action": "metamask.perps.teardown_state",
2221
+ "market": "BTC",
2222
+ "positions": {
2223
+ "state": "none"
2224
+ },
2225
+ "orders": {
2226
+ "state": "none"
2227
+ },
2228
+ "intent": "Restore Perps state after the proof",
2229
+ "next": "done"
2337
2230
  },
2338
2231
  {
2339
- "description": "Teardown only state created by selected market",
2340
- "node": {
2341
- "action": "metamask.perps.teardown_state",
2342
- "market": "BTC",
2343
- "intent": "Restore Perps state after the proof"
2344
- }
2232
+ "action": "metamask.perps.teardown_state",
2233
+ "market": "BTC",
2234
+ "intent": "Restore Perps state after the proof",
2235
+ "next": "done"
2345
2236
  }
2346
2237
  ],
2347
- "proof_effect": "Runs in setup/teardown phase and must be visible in trace.json; proof videos can keep this as trace-only setup.",
2348
- "safety_notes": "Composes supported app/API paths and must not mutate React/Redux/MobX/DOM/local storage to fabricate proof.",
2349
2238
  "execution_capabilities": [
2350
2239
  "app-mutation",
2351
2240
  "external-mutation"
2352
2241
  ]
2353
2242
  }
2354
- ],
2355
- "native_bindings": [
2356
- {
2357
- "action": "command",
2358
- "implementation": "@farmslot/recipe-harness/adapters/core"
2359
- },
2360
- {
2361
- "action": "wait",
2362
- "implementation": "@farmslot/recipe-harness/adapters/core"
2363
- },
2364
- {
2365
- "action": "assert_file",
2366
- "implementation": "@farmslot/recipe-harness/adapters/core"
2367
- },
2368
- {
2369
- "action": "assert_json",
2370
- "implementation": "@farmslot/recipe-harness/adapters/core"
2371
- },
2372
- {
2373
- "action": "assert_exit_code",
2374
- "implementation": "@farmslot/recipe-harness/adapters/core"
2375
- },
2376
- {
2377
- "action": "assert_output",
2378
- "implementation": "@farmslot/recipe-harness/adapters/core"
2379
- },
2380
- {
2381
- "action": "watch_logs",
2382
- "implementation": "@farmslot/recipe-harness/adapters/core"
2383
- },
2384
- {
2385
- "action": "index_artifacts",
2386
- "implementation": "@farmslot/recipe-harness/adapters/core"
2387
- },
2388
- {
2389
- "action": "end",
2390
- "implementation": "@farmslot/recipe-harness/adapters/core"
2391
- },
2392
- {
2393
- "action": "app.status",
2394
- "implementation": "@metamask/recipe-runner/platform-status"
2395
- },
2396
- {
2397
- "action": "metamask.wallet.list_accounts",
2398
- "implementation": "@metamask/recipe-runner/core/wallet"
2399
- },
2400
- {
2401
- "action": "metamask.perps.read_positions",
2402
- "implementation": "@metamask/recipe-runner/core/perps"
2403
- },
2404
- {
2405
- "action": "metamask.perps.read_orders",
2406
- "implementation": "@metamask/recipe-runner/core/perps"
2407
- },
2408
- {
2409
- "action": "metamask.perps.read_account",
2410
- "implementation": "@metamask/recipe-runner/core/perps"
2411
- },
2412
- {
2413
- "action": "metamask.perps.place_order",
2414
- "implementation": "@metamask/recipe-runner/core/perps"
2415
- },
2416
- {
2417
- "action": "metamask.perps.close_positions",
2418
- "implementation": "@metamask/recipe-runner/core/perps"
2419
- },
2420
- {
2421
- "action": "metamask.perps.assert_positions",
2422
- "implementation": "@metamask/recipe-runner/core/perps"
2423
- },
2424
- {
2425
- "action": "metamask.perps.ensure_positions",
2426
- "implementation": "@metamask/recipe-runner/core/perps"
2427
- }
2428
- ]
2243
+ }
2429
2244
  }