@deeeed/metamask-harness 0.13.0 → 0.14.1

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 (66) hide show
  1. package/CHANGELOG.md +43 -4
  2. package/adapters/extension/inject.mjs +1 -0
  3. package/adapters/extension/launch-browser.cjs +15 -3
  4. package/adapters/extension/lib/extension-id.cjs +36 -0
  5. package/adapters/extension/live.sh +5 -3
  6. package/adapters/extension/readiness.mjs +48 -0
  7. package/adapters/extension/reattach.sh +163 -55
  8. package/adapters/extension/sidepanel-toggle.sh +96 -24
  9. package/adapters/extension/verify.sh +15 -4
  10. package/adapters/extension/wallet-fixture-state.cjs +6 -11
  11. package/adapters/mobile/open-device.sh +32 -5
  12. package/adapters/mobile/start-metro.sh +15 -1
  13. package/adapters/mobile/verify.sh +50 -13
  14. package/adapters/shared/log-tui.mjs +7 -3
  15. package/adapters/shared/resolve-slot-ports-core.mjs +14 -4
  16. package/dist/adapters/core/surface.js +1 -0
  17. package/dist/adapters/extension/runtime.js +14 -5
  18. package/dist/adapters/extension/surface.js +1 -0
  19. package/dist/adapters/mobile/provision.js +49 -4
  20. package/dist/adapters/mobile/surface.js +1 -0
  21. package/dist/adapters/slot-ports.js +11 -4
  22. package/dist/cli-commands.js +5 -4
  23. package/dist/cli.js +4 -0
  24. package/dist/commands/call.js +79 -6
  25. package/dist/commands/check.js +326 -0
  26. package/dist/commands/core-readiness.js +75 -0
  27. package/dist/commands/device-target.js +123 -13
  28. package/dist/commands/doctor.js +30 -18
  29. package/dist/commands/fixtures.js +2 -1
  30. package/dist/commands/launch/extension.js +105 -9
  31. package/dist/commands/launch/index.js +116 -15
  32. package/dist/commands/mobile-device-view.js +140 -0
  33. package/dist/commands/parse-args.js +4 -1
  34. package/dist/commands/recipe-quality.js +6 -2
  35. package/dist/commands/run-engine.js +90 -5
  36. package/dist/commands/run-report.js +115 -0
  37. package/dist/commands/run.js +115 -8
  38. package/dist/commands/self-test.js +1 -1
  39. package/dist/commands/shared.js +2 -1
  40. package/dist/commands/status-probe.js +9 -3
  41. package/dist/commands/status.js +45 -50
  42. package/dist/live-adapter-contract.js +5 -1
  43. package/dist/mm-harness-cli.js +68 -27
  44. package/dist/recipe-files.js +14 -0
  45. package/docs/CLI-SPEC.md +25 -0
  46. package/docs/architecture.md +2 -2
  47. package/docs/live-adapter-contract.md +1 -1
  48. package/docs/recipe-libraries.md +21 -18
  49. package/library/actions/extension/platform/cdp.mjs +7 -4
  50. package/library/recipes/{app-lifecycle-android-smoke.mobile.recipe.json → app/lifecycle.android-smoke.mobile.recipe.json} +1 -1
  51. package/library/recipes/{perps-performance.mobile.recipe.json → perps/performance.mobile.recipe.json} +1 -1
  52. package/library/recipes/perps/smoke.core.recipe.json +39 -0
  53. package/library/recipes/perps/smoke.extension.recipe.json +51 -0
  54. package/library/recipes/perps/smoke.mobile.recipe.json +51 -0
  55. package/library/recipes/{action-validation.extension.recipe.json → runner/action-validation.extension.recipe.json} +7 -7
  56. package/library/recipes/{action-validation.mobile.recipe.json → runner/action-validation.mobile.recipe.json} +7 -7
  57. package/package.json +1 -1
  58. /package/library/recipes/{perps-lifecycle.recipe.json → perps/lifecycle.recipe.json} +0 -0
  59. /package/library/recipes/{order-lifecycle.core.recipe.json → perps/order-lifecycle.core.recipe.json} +0 -0
  60. /package/library/recipes/{perps-performance-background-resume.mobile.recipe.json → perps/performance.background-resume.mobile.recipe.json} +0 -0
  61. /package/library/recipes/{perps-performance-cold-start.mobile.recipe.json → perps/performance.cold-start.mobile.recipe.json} +0 -0
  62. /package/library/recipes/{perps-performance-warm-start.mobile.recipe.json → perps/performance.warm-start.mobile.recipe.json} +0 -0
  63. /package/library/recipes/{read-markets.core.recipe.json → perps/read-markets.core.recipe.json} +0 -0
  64. /package/library/recipes/{trading-lifecycle.core.recipe.json → perps/trading-lifecycle.core.recipe.json} +0 -0
  65. /package/library/recipes/{smoke.extension.recipe.json → runner/smoke.extension.recipe.json} +0 -0
  66. /package/library/recipes/{smoke.mobile.recipe.json → runner/smoke.mobile.recipe.json} +0 -0
package/docs/CLI-SPEC.md CHANGED
@@ -54,6 +54,7 @@ Name `metamask-recipe` → **REMOVE** (becomes `mm-harness`; no alias). Capabili
54
54
  | `resolve-extension` | Resolve the extension id | extension | advanced | **KEEP-INTERNAL** — internal plumbing; called inside `launch`/`launch --verify` |
55
55
  | `ensure-ready` | Ensure extension ready (close home tabs) | extension | advanced | **KEEP-INTERNAL** — becomes internal function inside `launch`/`verify` self-healing path |
56
56
  | `run` | Run a recipe, write evidence | all | PROVE | ROUTES-NOW |
57
+ | `check diff` | Run bounded repo-local validation for the active git diff | all | PROVE | ROUTES-NOW |
57
58
  | `self-test` | Package-wiring smoke (no device) | mobile+extension | advanced | **KEEP-INTERNAL** — CI smoke test; callable via `package.json` scripts; hidden from `--help` |
58
59
  | `flows` | List/promote library flows | all | DISCOVER | ROUTES-NOW |
59
60
  | `harness install\|verify\|cleanup\|live` | Runtime overlay lifecycle | all (core: no live) | OVERLAY | ROUTES-NOW (`harness` prefix → top-level); `live` **REMOVE** — dissolved into `launch --verify` |
@@ -437,6 +438,30 @@ Readiness check for a checkout without launching the app. Doctor is the single p
437
438
 
438
439
  ---
439
440
 
441
+ ## `check diff` (REAL → bounded local validation)
442
+
443
+ **Synopsis:** `mm-harness check diff [flags]`
444
+
445
+ Runs bounded validation against the target checkout's active git diff. This is
446
+ for local PR readiness loops and agent templates; it does not launch an app or
447
+ run a recipe.
448
+
449
+ | Flag | Values | Default | Purpose |
450
+ | --- | --- | --- | --- |
451
+ | `--target <repo>` | path | cwd | MetaMask checkout to inspect |
452
+ | `--adapter <adapter>` / `--platform <adapter>` | mobile\|extension\|core | auto-detect | Adapter label for the report |
453
+ | `--base <ref>` | git ref | GitHub PR base, then remote HEAD, then `origin/develop`/`origin/main`/local fallback | Diff base |
454
+ | `--profile <profile>` | `fast`\|`full` | `fast` | `fast` runs changed-file ESLint/Prettier/Jest; `full` also runs repo typecheck when available |
455
+ | `--artifacts-dir <dir>` | path | `temp/recipe/check-diff/<timestamp>` | Writes summary and per-check logs |
456
+ | `--json` | bool | false | Print the summary envelope to stdout |
457
+
458
+ **Artifacts:** `validation-summary.json`, `validation-summary.md`, and one log
459
+ per executed check.
460
+
461
+ **Exit:** 0 pass · 2 bad args / not a git checkout · 5 validation failure.
462
+
463
+ ---
464
+
440
465
  ## `--device <id>` — first-class mobile device targeting (REAL)
441
466
 
442
467
  `--device` is the uniform mobile device selector on `run`, `call`, `doctor`, and `fixtures`. Pass the **adb serial** for Android (from `adb devices`) or the **UDID / simulator name** for iOS. The harness resolves the adb serial to the Metro CDP target identity internally — users never need to know or set `ANDROID_DEVICE='Pixel 6 - 16 - API 36'`.
@@ -216,7 +216,7 @@ describes **how an agent should work**, it belongs in skills.
216
216
  | `adapters/extension/` | Runner-owned Extension launch/live/watch/windows/wallet-state/readiness helpers (orchestration) and verify (recipe) copied into installed harnesses. |
217
217
  | `adapters/shared/path-defaults.json` | Single source for default `recipeHarnessRoot` and `recipeRuntimeDir`. |
218
218
  | `adapters/shared/harness-path.sh`, `src/paths.ts` | Shell and TypeScript accessors for those defaults plus validation. |
219
- | `library/recipes/` | Reusable smoke/action-validation recipes only. Task-specific proof recipes stay task-local. |
219
+ | `library/recipes/` | Reusable smoke/runner.action-validation recipes only. Task-specific proof recipes stay task-local. |
220
220
  | `library/library.json`, `library/flows/` | Canonical recipe library: minimal, stable flows recipes can `call`. Personal/team libraries shadow it by default — see [Recipe Libraries](recipe-libraries.md). |
221
221
  | `docs/` | Runner architecture, contracts, and operational conventions. |
222
222
 
@@ -377,7 +377,7 @@ TypeScript or a focused `.mjs` adapter and keep shell as the launcher.
377
377
  5. Use official `ui.*` actions and screenshot claims for visible acceptance
378
378
  criteria; do not add task-specific `metamask.*` actions for exact copy,
379
379
  styling, ticket IDs, or one-off selectors.
380
- 6. Update smoke/action-validation recipes only when the capability is reusable.
380
+ 6. Update smoke/runner.action-validation recipes only when the capability is reusable.
381
381
 
382
382
  ## Standalone use first; farm later
383
383
 
@@ -85,7 +85,7 @@ domain capability useful across many tasks, such as `metamask.perps.start_state`
85
85
  `metamask.perps.place_order`, `metamask.perps.close_positions`, or
86
86
  `metamask.perps.assert_positions`.
87
87
 
88
- `ui.scroll` is part of the current executable contract and action-validation must
88
+ `ui.scroll` is part of the current executable contract and runner.action-validation must
89
89
  prove both normal scrolling and `scroll_into_view` before screenshot capture.
90
90
  `ui.gesture` is intentionally not advertised yet; drag/swipe proof must wait
91
91
  until the shared runtime and this runner expose and validate that action on both
@@ -101,19 +101,20 @@ each user-visible step takes. The runner has no benchmark verb: timings are just
101
101
  the per-node `duration`s in a passing run's `trace.json`, so a flow is comparable
102
102
  across runs only when you pin the run (same device, healing off) and keep the node
103
103
  graph stable. The repo ships one canonical example,
104
- `library/recipes/perps-performance.mobile.recipe.json` — unlock → open the Perps
104
+ `library/recipes/perps/performance.mobile.recipe.json` — unlock → open the Perps
105
105
  market list → read live state → open a market detail. This walkthrough copies it
106
106
  into a library of your own and retargets it to your journey. A peer engineer can
107
- follow it verbatim; the same steps run as the `perps-performance-recipe` contract
107
+ follow it verbatim; the same steps run as the `perps.performance-recipe` contract
108
108
  test.
109
109
 
110
110
  ### 1. Scaffold a personal library
111
111
 
112
112
  A library is a directory with a `library.json` marker. Keep reusable `flows/`
113
- (referenced via `call`) beside a `recipes/` folder for the full flows you run:
113
+ (referenced via `call`) beside a domain-grouped `recipes/` folder for the full
114
+ flows you run:
114
115
 
115
116
  ```bash
116
- mkdir -p ~/my-recipes/flows ~/my-recipes/recipes
117
+ mkdir -p ~/my-recipes/flows ~/my-recipes/recipes/my-perps
117
118
  cat > ~/my-recipes/library.json <<'JSON'
118
119
  { "kind": "recipe-library", "schema_version": 1, "name": "mydev", "owner": "mydev" }
119
120
  JSON
@@ -130,8 +131,8 @@ it works headlessly (CI, a scratch checkout) and so the path is unambiguous.
130
131
  Copy it out of your runner checkout's `library/recipes/`:
131
132
 
132
133
  ```bash
133
- cp library/recipes/perps-performance.mobile.recipe.json \
134
- ~/my-recipes/recipes/my-perps-performance.mobile.recipe.json
134
+ cp library/recipes/perps/performance.mobile.recipe.json \
135
+ ~/my-recipes/recipes/my-perps/performance.mobile.recipe.json
135
136
  ```
136
137
 
137
138
  ### 3. Edit the nodes to your journey
@@ -211,33 +212,35 @@ field on flow catalog entries — not yet in the protocol.
211
212
 
212
213
  ### 4. Run it and read the timings
213
214
 
214
- Validate statically **by name** first — `run` probes each library source's `recipes/`
215
- directory in precedence order (personal → team → canonical), so `my-perps-performance`
216
- resolves from `~/my-recipes/recipes/` without you spelling out the path:
215
+ Validate statically **by name** first — `run` probes each library source's
216
+ `recipes/` directory in precedence order (personal → team → canonical), so
217
+ `my-perps.performance` resolves from
218
+ `~/my-recipes/recipes/my-perps/performance.mobile.recipe.json` without you
219
+ spelling out the path:
217
220
 
218
221
  ```bash
219
222
  # Static validation by NAME — resolves from the personal library via --library.
220
- mm-harness run my-perps-performance \
223
+ mm-harness run my-perps.performance \
221
224
  --library mydev=~/my-recipes --plan --adapter mobile
222
225
 
223
226
  # Zero-flag personal-library: when ~/my-recipes is placed at
224
227
  # $FARMSLOT_HOME/recipe-library (default ~/.farmslot/recipe-library), the runner
225
228
  # discovers it automatically and run-by-name works without --library:
226
- mm-harness run my-perps-performance --plan --adapter mobile
229
+ mm-harness run my-perps.performance --plan --adapter mobile
227
230
 
228
231
  # Pinned live run — same device, healing OFF, so durations are comparable.
229
- mm-harness run my-perps-performance \
232
+ mm-harness run my-perps.performance \
230
233
  --library mydev=~/my-recipes \
231
234
  --adapter mobile --device <serial> --heal off --artifacts-dir artifacts
232
235
 
233
236
  # Canonical start-state variants — same installed app, no rebuild.
234
- mm-harness run app-lifecycle-android-smoke \
237
+ mm-harness run app.lifecycle.android-smoke \
235
238
  --adapter mobile --device <serial> --heal off --artifacts-dir artifacts/lifecycle-smoke
236
- mm-harness run perps-performance-warm-start \
239
+ mm-harness run perps.performance.warm-start \
237
240
  --adapter mobile --device <serial> --heal off --artifacts-dir artifacts/warm
238
- mm-harness run perps-performance-background-resume \
241
+ mm-harness run perps.performance.background-resume \
239
242
  --adapter mobile --device <serial> --heal off --artifacts-dir artifacts/background
240
- mm-harness run perps-performance-cold-start \
243
+ mm-harness run perps.performance.cold-start \
241
244
  --adapter mobile --device <serial> --heal off --artifacts-dir artifacts/cold
242
245
 
243
246
  # Per-node durations to diff across runs (trace.json is an array of entries, or
@@ -249,7 +252,7 @@ node -e 'const t=require("./artifacts/trace.json"); \
249
252
  A miss with `--library` names the sources that were searched, so you can tell at a
250
253
  glance whether a typo or a missing library entry caused the failure.
251
254
 
252
- Run `app-lifecycle-android-smoke` first when validating a new Android slot; it
255
+ Run `app.lifecycle.android-smoke` first when validating a new Android slot; it
253
256
  isolates lifecycle control from wallet setup and Perps navigation. The start-state
254
257
  variants use the standard outer `app.lifecycle` action. Every
255
258
  variant begins with `app.status` so `trace.json` records an idempotent start
@@ -294,5 +297,5 @@ mm-harness run my-perps-with-segment --plan --adapter mobile \
294
297
  ```
295
298
 
296
299
  That resolution — unresolved without the source, `pass` with it — is what the
297
- `perps-performance-recipe` contract test asserts, alongside the canonical recipe
300
+ `perps.performance-recipe` contract test asserts, alongside the canonical recipe
298
301
  resolving by name and the personal mobile copy planning by path and basename.
@@ -46,14 +46,17 @@ function cdpPort(input) {
46
46
  return port;
47
47
  }
48
48
 
49
- function extensionTarget(targets, extensionId = null) {
50
- return (Array.isArray(targets) ? targets : []).find((target) => {
49
+ export function extensionTarget(targets, extensionId = null) {
50
+ const candidates = (Array.isArray(targets) ? targets : []).filter((target) => {
51
51
  if (target?.type !== 'page') return false;
52
52
  if (!String(target?.url ?? '').startsWith('chrome-extension://')) return false;
53
- if (!String(target.url).includes('/home.html')) return false;
53
+ if (!String(target.url).includes('/home.html') && !String(target.url).includes('/sidepanel.html')) return false;
54
54
  if (extensionId && extensionIdFromTarget(target) !== extensionId) return false;
55
55
  return Boolean(target.webSocketDebuggerUrl);
56
- }) ?? null;
56
+ });
57
+ return candidates.find((target) => String(target.url).includes('/home.html')) ??
58
+ candidates.find((target) => String(target.url).includes('/sidepanel.html')) ??
59
+ null;
57
60
  }
58
61
 
59
62
 
@@ -68,7 +68,7 @@
68
68
  },
69
69
  "screenshot-after": {
70
70
  "action": "ui.screenshot",
71
- "path": "screenshots/app-lifecycle-android-smoke.png",
71
+ "path": "screenshots/app.lifecycle.android-smoke.png",
72
72
  "intent": "Capture the app after Android lifecycle foreground",
73
73
  "detail": "Visual proof that the selected device is displaying the relaunched app.",
74
74
  "flow": "evidence",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "title": "MetaMask Mobile Perps performance flow",
4
- "description": "Canonical measured flow for MetaMask Mobile Perps: setup unlocks the wallet, startState records the stable status, then the measured workflow opens the Perps market list, reads live state, and opens a market detail. Timings live in trace.json as each node's duration; there is no built-in benchmark verb. Run pinned so numbers are comparable: `mm-harness run perps-performance --device <serial> --heal off`. Optional testnet order placement is intentionally omitted because a live order would make the flow destructive and non-repeatable; add metamask.perps.place_order + close in a personal copy when you want to measure the trade path.",
4
+ "description": "Canonical measured flow for MetaMask Mobile Perps: setup unlocks the wallet, startState records the stable status, then the measured workflow opens the Perps market list, reads live state, and opens a market detail. Timings live in trace.json as each node's duration; there is no built-in benchmark verb. Run pinned so numbers are comparable: `mm-harness run perps.performance --device <serial> --heal off`. Optional testnet order placement is intentionally omitted because a live order would make the flow destructive and non-repeatable; add metamask.perps.place_order + close in a personal copy when you want to measure the trade path.",
5
5
  "startState": {
6
6
  "action": "app.status",
7
7
  "intent": "Record the stable run start status after wallet setup",
@@ -0,0 +1,39 @@
1
+ {
2
+ "schema_version": 1,
3
+ "title": "MetaMask core Perps smoke",
4
+ "description": "Non-mutating Perps domain smoke for the headless core adapter: instantiates the Perps controller and reads live positions, orders, and account state.",
5
+ "validate": {
6
+ "workflow": {
7
+ "entry": "status",
8
+ "nodes": {
9
+ "status": {
10
+ "action": "app.status",
11
+ "next": "read-positions",
12
+ "intent": "Resolve the core checkout and report headless compatibility mode"
13
+ },
14
+ "read-positions": {
15
+ "action": "metamask.perps.read_positions",
16
+ "mode": "all",
17
+ "next": "read-orders",
18
+ "intent": "Read live Perps positions from the headless controller"
19
+ },
20
+ "read-orders": {
21
+ "action": "metamask.perps.read_orders",
22
+ "mode": "all",
23
+ "next": "read-account",
24
+ "intent": "Read live Perps open orders from the headless controller"
25
+ },
26
+ "read-account": {
27
+ "action": "metamask.perps.read_account",
28
+ "next": "done",
29
+ "intent": "Read live Perps account state from the headless controller"
30
+ },
31
+ "done": {
32
+ "action": "end",
33
+ "status": "pass",
34
+ "intent": "Finish the core Perps smoke"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "schema_version": 1,
3
+ "title": "MetaMask Extension Perps smoke",
4
+ "description": "Non-mutating Perps domain smoke for MetaMask Extension: verifies CDP, unlocks if needed, opens the Perps page, and reads live Perps positions and orders.",
5
+ "validate": {
6
+ "workflow": {
7
+ "entry": "status",
8
+ "nodes": {
9
+ "status": {
10
+ "action": "app.status",
11
+ "next": "cdp",
12
+ "intent": "Resolve the Extension checkout and adapter status before Perps proof"
13
+ },
14
+ "cdp": {
15
+ "action": "cdp.target",
16
+ "required": true,
17
+ "timeout_ms": 15000,
18
+ "next": "ensure-unlocked",
19
+ "intent": "Confirm the Extension CDP runtime is reachable"
20
+ },
21
+ "ensure-unlocked": {
22
+ "action": "metamask.wallet.ensure_unlocked",
23
+ "timeout_ms": 45000,
24
+ "next": "open-perps",
25
+ "intent": "Ensure the wallet is unlocked before opening Perps"
26
+ },
27
+ "open-perps": {
28
+ "action": "ui.navigate",
29
+ "page": "perps",
30
+ "next": "read-positions",
31
+ "intent": "Open the Perps page through the stable page alias"
32
+ },
33
+ "read-positions": {
34
+ "action": "metamask.perps.read_positions",
35
+ "next": "read-orders",
36
+ "intent": "Read live Perps positions without mutating account state"
37
+ },
38
+ "read-orders": {
39
+ "action": "metamask.perps.read_orders",
40
+ "next": "done",
41
+ "intent": "Read live Perps open orders without mutating account state"
42
+ },
43
+ "done": {
44
+ "action": "end",
45
+ "status": "pass",
46
+ "intent": "Finish the Extension Perps smoke"
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "schema_version": 1,
3
+ "title": "MetaMask Mobile Perps smoke",
4
+ "description": "Non-mutating Perps domain smoke for MetaMask Mobile: verifies the live bridge, unlocks if needed, opens the Perps market list, and reads live Perps positions and orders.",
5
+ "validate": {
6
+ "workflow": {
7
+ "entry": "status",
8
+ "nodes": {
9
+ "status": {
10
+ "action": "app.status",
11
+ "next": "cdp",
12
+ "intent": "Resolve the Mobile checkout and adapter status before Perps proof"
13
+ },
14
+ "cdp": {
15
+ "action": "cdp.target",
16
+ "required": true,
17
+ "timeout_ms": 15000,
18
+ "next": "ensure-unlocked",
19
+ "intent": "Confirm the React Native debug bridge is reachable"
20
+ },
21
+ "ensure-unlocked": {
22
+ "action": "metamask.wallet.ensure_unlocked",
23
+ "timeout_ms": 45000,
24
+ "next": "open-perps",
25
+ "intent": "Ensure the wallet is unlocked before opening Perps"
26
+ },
27
+ "open-perps": {
28
+ "action": "ui.navigate",
29
+ "page": "perps",
30
+ "next": "read-positions",
31
+ "intent": "Open the Perps market list through the stable page alias"
32
+ },
33
+ "read-positions": {
34
+ "action": "metamask.perps.read_positions",
35
+ "next": "read-orders",
36
+ "intent": "Read live Perps positions without mutating account state"
37
+ },
38
+ "read-orders": {
39
+ "action": "metamask.perps.read_orders",
40
+ "next": "done",
41
+ "intent": "Read live Perps open orders without mutating account state"
42
+ },
43
+ "done": {
44
+ "action": "end",
45
+ "status": "pass",
46
+ "intent": "Finish the Mobile Perps smoke"
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
@@ -8,9 +8,9 @@
8
8
  "nodes": {
9
9
  "prepare-files": {
10
10
  "action": "command",
11
- "cmd": "mkdir -p temp/recipe-action-validation && printf 'E2E_ACTION_VALIDATION extension\\n' > temp/recipe-action-validation/probe.txt && printf '{\"platform\":\"extension\",\"ok\":true}\n' > temp/recipe-action-validation/probe.json && printf 'extension log E2E_ACTION_VALIDATION\\n' > temp/recipe-action-validation/validation.log && echo E2E_ACTION_VALIDATION extension",
11
+ "cmd": "mkdir -p temp/recipe-runner.action-validation && printf 'E2E_ACTION_VALIDATION extension\\n' > temp/recipe-runner.action-validation/probe.txt && printf '{\"platform\":\"extension\",\"ok\":true}\n' > temp/recipe-runner.action-validation/probe.json && printf 'extension log E2E_ACTION_VALIDATION\\n' > temp/recipe-runner.action-validation/validation.log && echo E2E_ACTION_VALIDATION extension",
12
12
  "next": "assert-command-exit",
13
- "intent": "Prepare action-validation probe files",
13
+ "intent": "Prepare runner.action-validation probe files",
14
14
  "detail": "Create local files used to prove command/assert/log/artifact actions.",
15
15
  "flow": "setup"
16
16
  },
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "assert-file": {
37
37
  "action": "assert_file",
38
- "path": "temp/recipe-action-validation/probe.txt",
38
+ "path": "temp/recipe-runner.action-validation/probe.txt",
39
39
  "contains": "E2E_ACTION_VALIDATION extension",
40
40
  "next": "assert-json",
41
41
  "intent": "Verify file assertions work",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "assert-json": {
46
46
  "action": "assert_json",
47
- "path": "temp/recipe-action-validation/probe.json",
47
+ "path": "temp/recipe-runner.action-validation/probe.json",
48
48
  "assert": {
49
49
  "path": "$.platform",
50
50
  "operator": "eq",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "watch-logs": {
59
59
  "action": "watch_logs",
60
- "path": "temp/recipe-action-validation/validation.log",
60
+ "path": "temp/recipe-runner.action-validation/validation.log",
61
61
  "contains": "E2E_ACTION_VALIDATION",
62
62
  "next": "index-artifacts",
63
63
  "intent": "Verify log watching works",
@@ -68,7 +68,7 @@
68
68
  "action": "index_artifacts",
69
69
  "artifacts": [
70
70
  {
71
- "path": "temp/recipe-action-validation/probe.txt",
71
+ "path": "temp/recipe-runner.action-validation/probe.txt",
72
72
  "type": "log",
73
73
  "category": "debug",
74
74
  "label": "Extension action validation probe"
@@ -173,7 +173,7 @@
173
173
  },
174
174
  "ui-screenshot-perps": {
175
175
  "action": "ui.screenshot",
176
- "path": "screenshots/extension-perps-action-validation.png",
176
+ "path": "screenshots/extension-perps-runner.action-validation.png",
177
177
  "timeout_ms": 5000,
178
178
  "next": "wallet-navigate-perps",
179
179
  "intent": "Capture Perps visual proof",
@@ -8,9 +8,9 @@
8
8
  "nodes": {
9
9
  "prepare-files": {
10
10
  "action": "command",
11
- "cmd": "mkdir -p temp/recipe-action-validation && printf 'E2E_ACTION_VALIDATION mobile\\n' > temp/recipe-action-validation/probe.txt && printf '{\"platform\":\"mobile\",\"ok\":true}\n' > temp/recipe-action-validation/probe.json && printf 'mobile log E2E_ACTION_VALIDATION\\n' > temp/recipe-action-validation/validation.log && echo E2E_ACTION_VALIDATION mobile",
11
+ "cmd": "mkdir -p temp/recipe-runner.action-validation && printf 'E2E_ACTION_VALIDATION mobile\\n' > temp/recipe-runner.action-validation/probe.txt && printf '{\"platform\":\"mobile\",\"ok\":true}\n' > temp/recipe-runner.action-validation/probe.json && printf 'mobile log E2E_ACTION_VALIDATION\\n' > temp/recipe-runner.action-validation/validation.log && echo E2E_ACTION_VALIDATION mobile",
12
12
  "next": "assert-command-exit",
13
- "intent": "Prepare action-validation probe files",
13
+ "intent": "Prepare runner.action-validation probe files",
14
14
  "detail": "Create local files used to prove command/assert/log/artifact actions.",
15
15
  "flow": "setup"
16
16
  },
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "assert-file": {
37
37
  "action": "assert_file",
38
- "path": "temp/recipe-action-validation/probe.txt",
38
+ "path": "temp/recipe-runner.action-validation/probe.txt",
39
39
  "contains": "E2E_ACTION_VALIDATION mobile",
40
40
  "next": "assert-json",
41
41
  "intent": "Verify file assertions work",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "assert-json": {
46
46
  "action": "assert_json",
47
- "path": "temp/recipe-action-validation/probe.json",
47
+ "path": "temp/recipe-runner.action-validation/probe.json",
48
48
  "assert": {
49
49
  "path": "$.platform",
50
50
  "operator": "eq",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "watch-logs": {
59
59
  "action": "watch_logs",
60
- "path": "temp/recipe-action-validation/validation.log",
60
+ "path": "temp/recipe-runner.action-validation/validation.log",
61
61
  "contains": "E2E_ACTION_VALIDATION",
62
62
  "next": "index-artifacts",
63
63
  "intent": "Verify log watching works",
@@ -68,7 +68,7 @@
68
68
  "action": "index_artifacts",
69
69
  "artifacts": [
70
70
  {
71
- "path": "temp/recipe-action-validation/probe.txt",
71
+ "path": "temp/recipe-runner.action-validation/probe.txt",
72
72
  "type": "log",
73
73
  "category": "debug",
74
74
  "label": "Mobile action validation probe"
@@ -174,7 +174,7 @@
174
174
  },
175
175
  "ui-screenshot-wallet": {
176
176
  "action": "ui.screenshot",
177
- "path": "screenshots/mobile-wallet-action-validation.png",
177
+ "path": "screenshots/mobile-wallet-runner.action-validation.png",
178
178
  "next": "wallet-navigate-perps",
179
179
  "intent": "Capture wallet visual proof",
180
180
  "detail": "Save a screenshot artifact after generic UI actions.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeeed/metamask-harness",
3
- "version": "0.13.0",
3
+ "version": "0.14.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mm-harness": "bin/mm-harness"