@deeeed/metamask-harness 0.46.0 → 0.47.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 (42) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +1 -1
  3. package/adapters/manifest.json +12 -4
  4. package/adapters/mobile/wait-for-bridge.cjs +550 -0
  5. package/adapters/mobile/wait-for-bridge.sh +11 -148
  6. package/bin/mm-harness +7 -2
  7. package/dist/adapters/mobile/prepare.js +26 -18
  8. package/dist/adapters/mobile/runtime-decision.js +1 -0
  9. package/dist/cli-commands.js +2 -0
  10. package/dist/command-contract.js +7 -0
  11. package/dist/commands/checklist.js +1 -0
  12. package/dist/commands/help.js +76 -0
  13. package/dist/commands/parse-args.js +2 -1
  14. package/dist/commands/recipe-quality.js +1 -1
  15. package/dist/commands/tutorial.js +46 -0
  16. package/dist/mm-harness-cli.js +45 -6
  17. package/docs/CONTRIBUTING.md +2 -0
  18. package/docs/QA.md +2 -2
  19. package/library/actions/mobile/perps/perps.mjs +1 -1
  20. package/package.json +2 -2
  21. package/scripts/site-contrast.mjs +6 -2
  22. package/site/assets/help-recipes.json +113 -0
  23. package/site/architecture.html +0 -497
  24. package/site/assets/metamask-fox.svg +0 -24
  25. package/site/assets/progress.mjs +0 -323
  26. package/site/assets/style.css +0 -1066
  27. package/site/cheatsheet.html +0 -307
  28. package/site/ecosystem.html +0 -162
  29. package/site/how-it-works.html +0 -692
  30. package/site/index.html +0 -184
  31. package/site/perps-advanced-orders-qa.html +0 -96
  32. package/site/perps.html +0 -265
  33. package/site/recipes.html +0 -423
  34. package/site/reviewers.html +0 -375
  35. package/site/tutorials/index.html +0 -181
  36. package/site/tutorials/v1.html +0 -212
  37. package/site/tutorials/v2.html +0 -207
  38. package/site/tutorials/v3.html +0 -258
  39. package/site/tutorials/v4.html +0 -196
  40. package/site/tutorials/v5.html +0 -164
  41. package/site/tutorials/v6.html +0 -166
  42. package/site/tutorials/v7.html +0 -185
@@ -1,692 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>How it works — proving a change with a recipe</title>
7
- <meta name="description" content="How a recipe proves a change on a real MetaMask build, checks itself before handoff, and stays behind as a regression guard. The full walkthrough, step by step.">
8
- <link rel="icon" href="assets/metamask-fox.svg" type="image/svg+xml">
9
- <link rel="stylesheet" href="assets/style.css?v=4">
10
- </head>
11
- <body data-progress-page="start">
12
- <a class="skip" href="#steps">Skip to the walkthrough</a>
13
-
14
- <header class="topbar">
15
- <div class="wrap topbar-inner">
16
- <a class="brand" href="index.html">
17
- <img class="brand-mark" src="assets/metamask-fox.svg" alt="" width="22" height="22">
18
- <span class="brand-name">recipes</span>
19
- </a>
20
- <nav class="nav" aria-label="Main">
21
- <a class="nav-cta" href="index.html#prompt">Quick start</a>
22
- <a href="how-it-works.html" aria-current="page">How it works</a>
23
- <a href="perps.html">Team / Perps</a>
24
- <a href="cheatsheet.html">Cheatsheet</a>
25
- <a href="architecture.html">Architecture</a>
26
- <a href="tutorials/index.html">Tutorials</a>
27
- </nav>
28
- </div>
29
- </header>
30
-
31
- <div class="progress-rail">
32
- <div class="wrap progress-inner">
33
- <div class="progress-track" role="progressbar" aria-label="Walkthrough progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
34
- <div class="progress-fill"></div>
35
- </div>
36
- <span class="progress-label">0/8 steps</span>
37
- <button type="button" class="progress-reset">Reset</button>
38
- </div>
39
- </div>
40
-
41
- <main>
42
- <section class="wrap hero">
43
- <span class="eyebrow">How it works</span>
44
- <h1>How a recipe earns trust.</h1>
45
- <p class="lede">
46
- A recipe is a graph of typed actions run against a real MetaMask build — Extension, Mobile, or
47
- Core. It runs while the change is being written, so the work is proven as it is made rather than
48
- hoped about and checked at the end. <code>mm-harness</code> is the runner. Everything below, in
49
- order.
50
- </p>
51
- <div class="hero-meta">
52
- <span>requires mm-harness 0.34+</span>
53
- <span>~20 minutes</span>
54
- <span>progress saves in this browser</span>
55
- </div>
56
- <p style="margin-top:.9rem;opacity:.7;font-size:.9rem;max-width:60ch">
57
- A proposal for how agents can code at MetaMask — offered for teams to try.
58
- </p>
59
- </section>
60
-
61
- <section class="wrap">
62
- <div class="note plain">
63
- <span class="note-title">Rather hand it to your agent?</span>
64
- <p style="margin-bottom:0">
65
- The <a href="index.html">front page</a> carries one prompt that goes further than this page:
66
- it sets up the harness and the skills, then drives a real ticket through one.
67
- </p>
68
- </div>
69
- </section>
70
-
71
- <section class="wrap">
72
- <h2 id="why">Why a recipe</h2>
73
- <p>
74
- <strong>Proof, as the change is made.</strong> The agent drives a real build, asserts what should
75
- be true, and leaves a trace: which actions ran, what they returned, how many times. On-device
76
- evidence, produced while the work is happening.
77
- </p>
78
- <p>
79
- <strong>Self-checked in the same context.</strong> Replaying a recipe needs no fresh session, no
80
- human, and no wait for CI. The agent does it mid-task, in the context it made the change in — so a
81
- broken step surfaces while it is still cheap to fix.
82
- </p>
83
- <p>
84
- <strong>Prevents regressions.</strong> The recipe outlives the change it was written for. Every
85
- later change has to pass it too, so the same bug cannot quietly come back: a one-time check becomes
86
- a permanent guard.
87
- </p>
88
- <p>
89
- <strong>Trust.</strong> Proven, self-checked, and still proving — so the change is trustworthy
90
- while it is being built, not hoped about and verified afterwards. Everything downstream, review
91
- included, inherits that.
92
- </p>
93
- </section>
94
-
95
- <section class="wrap">
96
- <h2 id="fit">How it fits your work</h2>
97
- <p>
98
- You use this through the skills. A <strong>skill</strong> is the interface — the packaged workflow
99
- an agent follows to fix a bug, build a feature, or review a pull request. The skill calls
100
- <code>mm-harness</code> underneath, and what the harness runs is a <strong>recipe</strong>: the
101
- executable proof that drives a real build, asserts, and leaves the evidence.
102
- </p>
103
- <p>You do not add proof to your work. Working through a skill is what produces it.</p>
104
-
105
- <p class="stack-caption">Top is how you interact; each layer calls the one below.</p>
106
- <div class="stack">
107
- <div class="layer layer-static">
108
- <span class="layer-n">1</span>
109
- <span class="layer-name">Skills</span>
110
- <span class="layer-sub">how you use it — fix a bug, build a feature, review a PR</span>
111
- </div>
112
- <div class="arrow" aria-hidden="true">↓</div>
113
- <div class="layer layer-static">
114
- <span class="layer-n">2</span>
115
- <span class="layer-name">mm-harness</span>
116
- <span class="layer-sub">what the skill calls underneath</span>
117
- </div>
118
- <div class="arrow" aria-hidden="true">↓</div>
119
- <div class="layer layer-static">
120
- <span class="layer-n">3</span>
121
- <span class="layer-name">Recipe</span>
122
- <span class="layer-sub">what the harness runs — on-device proof, kept as a regression guard</span>
123
- </div>
124
- </div>
125
-
126
- <p>
127
- So what you are adopting is not a testing tool. It is a way of working where the proof comes out
128
- of doing the work rather than out of a separate step afterwards.
129
- </p>
130
- <p>
131
- Skills come from two sources: the public <code>MetaMask/skills</code> repo, and the internal
132
- <code>Consensys/skills</code> overlay, which needs access to that org. Both are cloned locally and
133
- installed per checkout with <code>yarn skills</code>. You can drive the harness directly — the
134
- walkthrough below does, and uses no skill — but skills are the path day to day.
135
- <a href="architecture.html#stack">The full stack is on Architecture.</a>
136
- </p>
137
- </section>
138
-
139
- <section class="wrap">
140
- <h2 id="model">Two words</h2>
141
- <p>
142
- An <strong>action</strong> is one typed operation: unlock the wallet, press a button, read the
143
- account state. A <strong>recipe</strong> is a JSON graph of actions. The steps below follow
144
- <strong>discover → drive → prove</strong>, which is also the order you will work in from here on.
145
- <code>mm-harness</code> is the runner, and it implements a versioned recipe specification —
146
- <a href="architecture.html#spec">see Architecture</a>.
147
- </p>
148
-
149
- <div class="doctrine">
150
- <p>
151
- <span class="k">You never guess capabilities — you discover them.</span>
152
- <code>mm-harness actions</code> prints what this checkout can do, and that list is law. The tool
153
- refuses an invented action rather than improvising one, which is why its output is worth
154
- trusting.
155
- </p>
156
- </div>
157
- </section>
158
-
159
- <section class="wrap">
160
- <h2 id="steps">The walkthrough, step by step</h2>
161
- <p>Each piece on its own, from an empty terminal to an evidence bundle. Checkboxes persist in this browser, so you can close the tab and come back.</p>
162
-
163
- <ol class="steps">
164
-
165
- <li class="step" data-step="install">
166
- <div class="step-head">
167
- <input type="checkbox" class="step-check" id="c-install" aria-labelledby="t-install">
168
- <h3 class="step-title" id="t-install">Get the CLI</h3>
169
- </div>
170
- <p class="step-why">Both paths end with <code>mm-harness</code> on your PATH.</p>
171
-
172
- <div class="grid grid-2" style="margin:1.2rem 0">
173
- <div class="path-card">
174
- <div class="path-tag">Path A — from zero</div>
175
- <h4 style="margin:0 0 .5rem">No checkout yet</h4>
176
- <p style="font-size:.92rem;color:var(--text-dim)">
177
- Install below, then <code>mm-harness setup-base</code> clones the MetaMask product repos
178
- into one standard layout and runs each repo's own dependency install. Use
179
- <code>--dry-run</code> first to see the layout it would create.
180
- </p>
181
- <p style="margin-bottom:0"><span class="badge live">available now</span></p>
182
- </div>
183
- <div class="path-card">
184
- <div class="path-tag">Path B — you already have a checkout</div>
185
- <h4 style="margin:0 0 .5rem">Install and cd in</h4>
186
- <p style="font-size:.92rem;color:var(--text-dim)">
187
- Install globally, then work from inside the checkout. The product, ports, and runtime paths
188
- are detected from where you are standing; there is no config file to write.
189
- </p>
190
- <p style="margin-bottom:0"><span class="badge live">available now</span></p>
191
- </div>
192
- </div>
193
-
194
- <div class="cmd"><pre><code><span class="p">$ </span>npm i -g @deeeed/metamask-harness@latest
195
- <span class="p">$ </span>mm-harness --version</code></pre></div>
196
-
197
- <div class="out-label">Expected</div>
198
- <div class="out">0.34.x <span class="dim">— any 0.34 or newer</span></div>
199
-
200
- <p class="step-why">Everything from here runs inside a product checkout:</p>
201
- <div class="cmd"><pre><code><span class="p">$ </span>cd ~/dev/metamask/metamask-extension <span class="dim"># or metamask-mobile, or core</span></code></pre></div>
202
-
203
- <details class="fail">
204
- <summary>If it fails</summary>
205
- <div class="fail-body">
206
- <p>
207
- <strong><code>mm-harness: command not found</code></strong> — your global npm bin is not on
208
- PATH. <code>npm prefix -g</code> prints the global prefix; add its <code>bin</code>
209
- directory to your shell profile.
210
- </p>
211
- <p>
212
- <strong>Older than 0.34</strong> — a stale global install is the most common source of
213
- "the docs don't match my terminal". Run <code>mm-harness update</code>, or
214
- <code>update --check</code> to look without installing.
215
- </p>
216
- </div>
217
- </details>
218
- </li>
219
-
220
- <li class="step" data-step="doctor">
221
- <div class="step-head">
222
- <input type="checkbox" class="step-check" id="c-doctor" aria-labelledby="t-doctor">
223
- <h3 class="step-title" id="t-doctor">Run doctor — and learn to read the errors</h3>
224
- </div>
225
- <p class="step-why">
226
- A read-only readiness check that launches nothing and names the exact command that fixes each
227
- finding.
228
- </p>
229
-
230
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness doctor</code></pre></div>
231
-
232
- <div class="out-label">Expected — a checkout that needs one repair</div>
233
- <div class="out"><span class="ok">pass</span> extension bridge present manifest=…/extension.action-manifest.json
234
- harness: @deeeed/metamask-harness@0.34.x
235
- runtime: decision=install (deps-missing) deps=missing webpack=down
236
- Dependencies are not installed (no yarn install-state markers).
237
- runtime-context: temp/recipe/runtime/agentic-runtime.json (<span class="bad">absent</span> — run mm-harness doctor --fix)
238
- capture: <span class="ok">pass</span> (screenshots: capture-helper → cdp; video: capture-helper)
239
- <span class="hint">Next: mm-harness launch --adapter extension --target '…'</span></div>
240
-
241
- <div class="note">
242
- <span class="note-title">The habit the toolchain is built around</span>
243
- <p>
244
- Every failure names one next action. Above, the finding tells you to run
245
- <code>doctor --fix</code> and the <code>Next:</code> line says where to go once it passes.
246
- Read the message and do what it says — that is also what lets an agent recover on its own
247
- instead of guessing.
248
- </p>
249
- </div>
250
-
251
- <p class="step-why">Do what it said:</p>
252
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness doctor --fix</code></pre></div>
253
-
254
- <div class="out-label">Expected — the finding is gone</div>
255
- <div class="out"><span class="ok">pass</span> extension bridge present ready=true <span class="ok">fixed=[runtime-context]</span> failed=[]</div>
256
-
257
- <p class="step-why">
258
- <code>--fix</code> repairs runtime state the harness owns. It will not launch the app, invent
259
- credentials, or pick a wallet fixture; those are your decisions, so it stops and asks.
260
- </p>
261
-
262
- <details class="fail">
263
- <summary>If it fails</summary>
264
- <div class="fail-body">
265
- <p>
266
- <strong><code>deps=missing</code></strong> — run <code>yarn install</code> as usual for
267
- that repo. The harness does not manage your product repo's dependencies.
268
- </p>
269
- <p>
270
- <strong>A finding you do not understand</strong> — <code>mm-harness doctor --json</code>
271
- carries the same findings with structured detail, and is the form to paste to an agent or a
272
- bug report.
273
- </p>
274
- <p>
275
- <strong>Still failing after <code>--fix</code></strong> — <code>fixed=[…] failed=[…]</code>
276
- separates the two. Anything in <code>failed</code> needs a human decision; the finding says
277
- which.
278
- </p>
279
- </div>
280
- </details>
281
- </li>
282
-
283
- <li class="step" data-step="launch">
284
- <div class="step-head">
285
- <input type="checkbox" class="step-check" id="c-launch" aria-labelledby="t-launch">
286
- <h3 class="step-title" id="t-launch">Launch the app under harness control</h3>
287
- </div>
288
- <p class="step-why">
289
- Starts the app and its dev server, installing the runtime overlay first if missing. Platform is
290
- auto-detected. On iOS, pin one simulator UUID through provisioning and launch so duplicate device
291
- names cannot select different simulators.
292
- </p>
293
-
294
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness launch --verify <span class="dim"># extension — fullscreen by default</span>
295
- <span class="p">$ </span>xcrun simctl list devices available <span class="dim"># choose one iPhone UUID</span>
296
- <span class="p">$ </span>mm-harness provision runway ios --device '&lt;UUID&gt;' --force
297
- <span class="p">$ </span>xcrun simctl get_app_container '&lt;UUID&gt;' io.metamask.MetaMask app
298
- <span class="p">$ </span>mm-harness launch ios --device '&lt;UUID&gt;' --verify
299
- <span class="p">$ </span>mm-harness launch android --verify</code></pre></div>
300
-
301
- <p class="step-why">
302
- Quick relaunch is the default and reuses a healthy runtime. <code>--build</code> is the escape
303
- hatch that always clean-builds; reach for it only when native or bundler output changed.
304
- </p>
305
-
306
- <div class="out-label">Core is headless — and says so</div>
307
- <div class="out"><span class="bad">✗</span> mm-harness launch: core is headless; there is nothing to launch.
308
- <span class="hint">Next: mm-harness verify</span></div>
309
- <p class="step-why">
310
- In <code>core</code> there is no UI to launch, so you get the equivalent step instead of a
311
- silent failure. Run <code>mm-harness verify</code> and continue.
312
- </p>
313
-
314
- <details class="fail">
315
- <summary>If it fails</summary>
316
- <div class="fail-body">
317
- <p>
318
- <strong>Mobile: more than one device</strong> — the harness lists what it found rather than
319
- guessing. Re-run with <code>--device &lt;udid|serial&gt;</code>. Prefer the iOS UUID over a name,
320
- because Xcode can contain several simulators with the same display name.
321
- </p>
322
- <p>
323
- <strong>iOS app missing after provisioning</strong> — repeat the provision command with
324
- <code>--force</code> and the same UUID. Do not use <code>--preflight-mode</code>; it is an
325
- internal adapter flag, not a public <code>mm-harness launch</code> option.
326
- </p>
327
- <p>
328
- <strong>Stuck</strong> — <code>mm-harness logs</code> tails the dev server and app logs;
329
- <code>mm-harness status</code> shows the adapter, devices, and next command.
330
- </p>
331
- <p>
332
- <strong>Clean slate</strong> — <code>mm-harness stop</code> stops only what this checkout
333
- owns, so parallel checkouts are untouched. Stopping nothing is success.
334
- </p>
335
- </div>
336
- </details>
337
- </li>
338
-
339
- <li class="step" data-step="actions">
340
- <div class="step-head">
341
- <input type="checkbox" class="step-check" id="c-actions" aria-labelledby="t-actions">
342
- <h3 class="step-title" id="t-actions">Discover what this checkout can do</h3>
343
- </div>
344
- <p class="step-why">
345
- Prints every typed operation available here, with its fields. The set differs per product:
346
- Mobile has UI actions, Core is headless and has none.
347
- </p>
348
-
349
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness actions --categories</code></pre></div>
350
-
351
- <div class="out-label">Expected — a mobile checkout, with its own counts</div>
352
- <div class="out">analytics (4)
353
- assertion (4)
354
- control (4)
355
- deeplink (1)
356
- evidence (2)
357
- perps (11)
358
- runtime (4)
359
- ui (13)
360
- utility (1)
361
- wallet (6)</div>
362
-
363
- <p class="step-why">
364
- Categories and counts move with the release and the adapter. Read yours from the command; the
365
- shape is the point, not the numbers.
366
- </p>
367
-
368
- <p class="step-why">Then look inside a category, search, or inspect one action's fields:</p>
369
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness actions --category ui
370
- <span class="p">$ </span>mm-harness actions positions
371
- <span class="p">$ </span>mm-harness actions --action read_state</code></pre></div>
372
-
373
- <div class="doctrine">
374
- <p>
375
- <span class="k">The discovered list is law.</span> It is the capability boundary, not a
376
- subset of some larger API. Call something not on it and the harness refuses, pointing you back
377
- at discovery:
378
- </p>
379
- </div>
380
-
381
- <div class="out"><span class="bad">✗</span> call: unknown action "totally_made_up" for the extension adapter.
382
- <span class="hint">Next: mm-harness actions --adapter extension --json</span></div>
383
-
384
- <p class="step-why">
385
- That refusal is why the evidence is worth reading: a tool that invents an action when asked for
386
- something impossible would also produce a plausible-looking result, and you would have no way to
387
- tell. Add <code>--json</code> when feeding this to an agent.
388
- </p>
389
-
390
- <details class="fail">
391
- <summary>If it fails</summary>
392
- <div class="fail-body">
393
- <p>
394
- <strong>Fewer actions than expected</strong> — you are seeing only the bundled set. Team
395
- libraries add domain actions and must be declared: <a href="tutorials/v3.html">V3</a>.
396
- </p>
397
- <p>
398
- <strong>Wrong product detected</strong> — pass <code>--adapter mobile|extension|core</code>
399
- explicitly, and check you are inside the checkout you meant.
400
- </p>
401
- </div>
402
- </details>
403
- </li>
404
-
405
- <li class="step" data-step="call-read">
406
- <div class="step-head">
407
- <input type="checkbox" class="step-check" id="c-call-read" aria-labelledby="t-call-read">
408
- <h3 class="step-title" id="t-call-read">Drive it: read product state</h3>
409
- </div>
410
- <p class="step-why">
411
- <code>call</code> runs one action as a one-node recipe through the real engine — same execution
412
- path, trace, and evidence as a full run. Start with a read; reads cannot break anything.
413
- </p>
414
-
415
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness call read_state</code></pre></div>
416
-
417
- <div class="note blue">
418
- <span class="note-title">Core branch</span>
419
- <p>
420
- Core has no wallet UI. Exercise its live controller boundary instead:
421
- <code>mm-harness call read_positions mode=all</code>.
422
- </p>
423
- </div>
424
-
425
- <p class="step-why">
426
- Short names resolve when unambiguous: <code>read_state</code> finds
427
- <code>metamask.wallet.read_state</code>. An ambiguous one stops and lists the candidates.
428
- </p>
429
-
430
- <div class="out-label">Expected — shape of the result</div>
431
- <div class="out">call read_state: <span class="ok">pass</span>
432
- Result:
433
- {
434
- "action": "metamask.wallet.read_state",
435
- "state": {
436
- "selectedAccount": { "name": "Account 1", "address": "0x…" },
437
- "completedOnboarding": true
438
- },
439
- "redacted": true
440
- }</div>
441
-
442
- <p class="step-why">
443
- Note <code>"redacted": true</code> — wallet state passes through redaction before reaching an
444
- artifact, because these bundles get attached to pull requests.
445
- </p>
446
-
447
- <details class="fail">
448
- <summary>If it fails</summary>
449
- <div class="fail-body">
450
- <p>
451
- <strong>Runtime health check failed / CDP not reachable</strong> — the app is not running.
452
- Complete the launch step; <code>mm-harness status</code> confirms what is live.
453
- </p>
454
- <p>
455
- <strong>Mobile: more than one device</strong> — <code>call</code> fails fast and lists
456
- them. Re-run with <code>--device</code>.
457
- </p>
458
- <p>
459
- <strong><code>unknown action</code></strong> — not in this adapter's set.
460
- <code>mm-harness call --list</code> shows what <code>call</code> accepts here.
461
- </p>
462
- </div>
463
- </details>
464
- </li>
465
-
466
- <li class="step" data-step="call-ui">
467
- <div class="step-head">
468
- <input type="checkbox" class="step-check" id="c-call-ui" aria-labelledby="t-call-ui">
469
- <h3 class="step-title" id="t-call-ui">Drive it again: UI or headless Core</h3>
470
- </div>
471
- <p class="step-why">Keep the app visible for this one.</p>
472
-
473
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness call navigate page=perps</code></pre></div>
474
-
475
- <div class="note blue">
476
- <span class="note-title">Core branch</span>
477
- <p>
478
- Prove a second headless action instead:
479
- <code>mm-harness call command cmd="echo core-ready"</code>.
480
- </p>
481
- </div>
482
-
483
- <p class="step-why">
484
- Fields are passed as <code>key=value</code>, or <code>--arg k=v</code> for the same effect.
485
- </p>
486
-
487
- <div class="note blue">
488
- <span class="note-title">Semantic intent, not coordinates</span>
489
- <p>
490
- You asked for a <em>page</em>, not a pixel or a route. The adapter owns the mapping and
491
- verifies where it landed, so a drifted route fails loudly instead of quietly doing nothing —
492
- which is why these actions survive redesigns.
493
- <code>mm-harness actions --action navigate</code> lists accepted values.
494
- </p>
495
- </div>
496
-
497
- <p class="step-why">Others worth trying, if your adapter lists them:</p>
498
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness call press text="Account 1"
499
- <span class="p">$ </span>mm-harness call screenshot path=proof.png</code></pre></div>
500
-
501
- <details class="fail">
502
- <summary>If it fails</summary>
503
- <div class="fail-body">
504
- <p>
505
- <strong>Target not found</strong> — the element is not on screen. Actions do not hunt
506
- blindly; use <code>wait_for</code> when something needs to mount first.
507
- </p>
508
- <p>
509
- <strong>Core has no UI actions</strong> — correct, it is headless. Try
510
- <code>mm-harness call command cmd="echo hello"</code> there instead.
511
- </p>
512
- </div>
513
- </details>
514
- </li>
515
-
516
- <li class="step" data-step="run">
517
- <div class="step-head">
518
- <input type="checkbox" class="step-check" id="c-run" aria-labelledby="t-run">
519
- <h3 class="step-title" id="t-run">Prove it: run your first recipe</h3>
520
- </div>
521
- <p class="step-why">
522
- Everything so far was driving by hand. A recipe composes the same operations into a graph that
523
- runs identically every time and records what happened. Start with what ships:
524
- </p>
525
-
526
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness run --list</code></pre></div>
527
-
528
- <div class="out-label">Expected — an extension checkout</div>
529
- <div class="out">runnable recipes (extension)
530
- Inspect: mm-harness run &lt;recipe&gt; --describe
531
- perps.clean-market-testnet [metamask] variant=all params=market — Converge one Perps testnet market…
532
- perps.lifecycle [metamask] variant=all — Opens a small ETH testnet position, verifies it, closes it…
533
- perps.smoke [metamask] variant=extension — Non-mutating Perps domain smoke…
534
- runner.action-validation [metamask] variant=extension — Exercises every manifest-declared action…
535
- runner.smoke [metamask] variant=extension — Proves the runner executes manifest-declared actions…
536
- wallet.smoke [metamask] variant=extension — Fixture-backed proof that the wallet is reachable…</div>
537
- <p class="step-why">
538
- The bundled set grows between releases; yours is whatever this command prints, not what is
539
- printed here.
540
- </p>
541
-
542
- <p class="step-why">
543
- Read one first. <code>--describe</code> shows its parameters and every action it composes:
544
- </p>
545
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness run wallet.smoke --describe
546
- <span class="p">$ </span>mm-harness run wallet.smoke --plan</code></pre></div>
547
-
548
- <p class="step-why">
549
- <code>--plan</code> validates and prints the execution plan while touching nothing, exiting 5 if
550
- the recipe is invalid. Cheap check before the expensive one.
551
- </p>
552
-
553
- <p class="step-why">Now for real, with the evidence somewhere you chose:</p>
554
- <div class="cmd"><pre><code><span class="p">$ </span>mm-harness run wallet.smoke --artifacts-dir ./first-recipe-artifacts</code></pre></div>
555
-
556
- <div class="out-label">Expected</div>
557
- <div class="out"><span class="ok">PASS</span> recipe run [extension]
558
- summary:
559
- <span class="ok">PASS</span> status (app.status, 9ms): platform=extension
560
- <span class="ok">PASS</span> fixture (metamask.wallet.fixture_status, 17ms): path=temp/recipe/runtime/wallet-fixture.json
561
- <span class="ok">PASS</span> unlock (metamask.wallet.ensure_unlocked, 100ms): proof=extension-unlocked-state
562
- <span class="ok">PASS</span> state (metamask.wallet.read_state, 94ms): proof=extension-wallet-state
563
- <span class="ok">PASS</span> screenshot (ui.screenshot, 6.0s): path=screenshots/wallet-smoke.png
564
- <span class="ok">PASS</span> done (end, 0ms)
565
- artifacts (6):
566
- Human run report: ./first-recipe-artifacts/report.md
567
- Run summary: ./first-recipe-artifacts/summary.json
568
- Execution trace: ./first-recipe-artifacts/trace.json
569
- Executed recipe: ./first-recipe-artifacts/recipe.json
570
- <span class="dim">…</span></div>
571
-
572
- <div class="note">
573
- <span class="note-title">Wallet fixtures</span>
574
- <p>
575
- Recipes needing a signed-in wallet read one canonical fixture per checkout; the password comes
576
- <em>from</em> the fixture and is never typed. On a missing fixture,
577
- <code>mm-harness fixtures</code> shows its status and the safe next command.
578
- <code>fixtures init --dev</code> creates a disposable public test wallet that must never hold
579
- real funds.
580
- </p>
581
- </div>
582
-
583
- <details class="fail">
584
- <summary>If it fails</summary>
585
- <div class="fail-body">
586
- <p>
587
- <strong>Exit 5</strong> — validation or trust failure. The recipe is the problem, not your
588
- environment; nothing executed. The message names the invalid part.
589
- </p>
590
- <p>
591
- <strong>Exit 1</strong> — it ran and an action failed. A real result, not a tooling
592
- problem: find the first node in <code>trace.json</code> with <code>"ok": false</code>.
593
- </p>
594
- <p>
595
- <strong>Exit 3</strong> — infrastructure, not your recipe: the app or dev server fell over.
596
- Try <code>mm-harness doctor</code> then <code>mm-harness logs</code>.
597
- </p>
598
- <p>
599
- <strong>Lost track</strong> — <code>mm-harness last</code> prints the last significant
600
- command with its verdict and evidence paths.
601
- </p>
602
- </div>
603
- </details>
604
- </li>
605
-
606
- <li class="step" data-step="evidence">
607
- <div class="step-head">
608
- <input type="checkbox" class="step-check" id="c-evidence" aria-labelledby="t-evidence">
609
- <h3 class="step-title" id="t-evidence">Open the evidence bundle</h3>
610
- </div>
611
- <p class="step-why">The run left a directory behind. This is the part that beats clicking through by hand.</p>
612
-
613
- <div class="cmd"><pre><code><span class="p">$ </span>ls first-recipe-artifacts
614
- <span class="p">$ </span>cat first-recipe-artifacts/summary.json
615
- <span class="p">$ </span>open first-recipe-artifacts/screenshots</code></pre></div>
616
-
617
- <div class="table-scroll">
618
- <table>
619
- <thead><tr><th>File</th><th>What it answers</th></tr></thead>
620
- <tbody>
621
- <tr><td><code>summary.json</code></td><td>Did it pass? How many nodes, how long, which libraries were in play. The verdict.</td></tr>
622
- <tr><td><code>trace.json</code></td><td>What happened at every step: per-node verdict, timing, inputs, outputs. Counts come from here.</td></tr>
623
- <tr><td><code>recipe.json</code></td><td>The graph that actually executed, including each node's stated intent.</td></tr>
624
- <tr><td><code>report.md</code></td><td>The same story in one readable page — the thing to skim first.</td></tr>
625
- <tr><td><code>screenshots/</code></td><td>Visual evidence captured during the run.</td></tr>
626
- <tr><td><code>diagnostics.json</code></td><td>Warnings and errors the app emitted, kept deliberately separate from the verdict.</td></tr>
627
- </tbody>
628
- </table>
629
- </div>
630
-
631
- <p class="step-why">
632
- Read them in that order: <code>report.md</code>, then <code>summary.json</code> for the verdict,
633
- then <code>trace.json</code> when you want to know why. Cite numbers from
634
- <code>trace.json</code>, never from prose written around it.
635
- </p>
636
-
637
- <div class="btn-row" style="margin-top:1.2rem">
638
- <a class="btn btn-primary" href="reviewers.html">Read a bundle line by line →</a>
639
- </div>
640
-
641
- <details class="fail">
642
- <summary>If it fails</summary>
643
- <div class="fail-body">
644
- <p>
645
- <strong>Cannot find the directory</strong> — without <code>--artifacts-dir</code> it goes
646
- to a checkout-local run directory. <code>mm-harness last</code> prints the path.
647
- </p>
648
- <p>
649
- <strong>No screenshots</strong> — capture differs per platform;
650
- <code>mm-harness doctor</code> reports it on a <code>capture:</code> line. A degraded
651
- fallback still succeeds and records that it degraded in the artifact metadata.
652
- </p>
653
- </div>
654
- </details>
655
- </li>
656
-
657
- </ol>
658
- </section>
659
-
660
- <section class="wrap">
661
- <hr class="sep">
662
- <h2>Next</h2>
663
- <div class="grid grid-3">
664
- <div class="card">
665
- <h3>Recipe anatomy</h3>
666
- <p>The graph, the intents, the assertions, and the test of whether yours is worth keeping.</p>
667
- <p><a href="recipes.html">Read the anatomy →</a></p>
668
- </div>
669
- <div class="card">
670
- <h3>Your team's library</h3>
671
- <p>Install the skills, declare your library, prove discovery sees it.</p>
672
- <p><a href="tutorials/v3.html">Tutorial V3 →</a></p>
673
- </div>
674
- <div class="card">
675
- <h3>Reviewing someone's proof</h3>
676
- <p>A real bundle annotated, including a degraded capture that stayed honest about it.</p>
677
- <p><a href="reviewers.html">For reviewers →</a></p>
678
- </div>
679
- </div>
680
- </section>
681
- </main>
682
-
683
- <footer class="footer">
684
- <div class="wrap">
685
- <p>Internal getting-started guide for proving MetaMask changes with recipes. Not official MetaMask product documentation.</p>
686
- <p>Commands here are checked against the CLI's own <code>--help</code>. If one disagrees with your terminal, your terminal is right: run <code>mm-harness update</code>, then trust <code>--help</code>.</p>
687
- </div>
688
- </footer>
689
-
690
- <script type="module" src="assets/progress.mjs?v=4"></script>
691
- </body>
692
- </html>