@deeeed/metamask-harness 0.17.5 → 0.19.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.
Files changed (169) hide show
  1. package/CHANGELOG.md +1059 -0
  2. package/README.md +91 -140
  3. package/adapters/core/inject.sh +1 -6
  4. package/adapters/extension/console-tail.mjs +55 -24
  5. package/adapters/extension/ensure-browser.sh +6 -1
  6. package/adapters/extension/inject.mjs +7 -13
  7. package/adapters/extension/launch-browser.cjs +7 -1
  8. package/adapters/extension/launch-webpack.cjs +83 -0
  9. package/adapters/extension/launch.sh +8 -11
  10. package/adapters/extension/lib/chrome-args.cjs +8 -1
  11. package/adapters/extension/lib/macos-focus.cjs +32 -0
  12. package/adapters/extension/live.sh +12 -21
  13. package/adapters/extension/reattach.sh +1 -0
  14. package/adapters/extension/seed-fixture.sh +4 -12
  15. package/adapters/extension/sidepanel-toggle.sh +4 -1
  16. package/adapters/extension/stamp-runtime-title.cjs +58 -0
  17. package/adapters/extension/start-watch.sh +17 -4
  18. package/adapters/extension/stop-viewers.sh +1 -1
  19. package/adapters/extension/sync-webpack-dist.cjs +107 -0
  20. package/adapters/extension/verify.sh +2 -2
  21. package/adapters/manifest.json +53 -37
  22. package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +16 -0
  23. package/adapters/mobile/bridge-runtime/console-forwarder.cjs +1 -1
  24. package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +3 -1
  25. package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +2 -3
  26. package/adapters/mobile/cleanup.sh +16 -176
  27. package/adapters/mobile/inject.sh +91 -671
  28. package/adapters/mobile/launch-console-forwarder.cjs +39 -0
  29. package/adapters/mobile/open-device.sh +45 -7
  30. package/adapters/mobile/start-console-forwarder.sh +70 -0
  31. package/adapters/mobile/start-metro.sh +0 -41
  32. package/adapters/mobile/verify.sh +34 -83
  33. package/adapters/mobile/wait-for-bridge.sh +22 -8
  34. package/adapters/shared/harness-source-fingerprint.mjs +14 -12
  35. package/adapters/shared/resolve-slot-ports-core.mjs +17 -6
  36. package/adapters/shared/resolve-slot-ports.sh +17 -5
  37. package/adapters/shared/update-check-worker.mjs +43 -0
  38. package/bin/mm-harness +21 -2
  39. package/dist/adapters/core/surface.js +4 -1
  40. package/dist/adapters/extension/console-capture.js +95 -0
  41. package/dist/adapters/extension/product-config.js +110 -0
  42. package/dist/adapters/extension/runtime-decision.js +20 -2
  43. package/dist/adapters/extension/surface.js +22 -3
  44. package/dist/adapters/harness-freshness.js +49 -0
  45. package/dist/adapters/mobile/perps-env.js +43 -3
  46. package/dist/adapters/mobile/prepare.js +39 -7
  47. package/dist/adapters/mobile/surface.js +5 -2
  48. package/dist/adapters/resolve-slot-ports.js +2 -2
  49. package/dist/adapters/slot-ports.js +13 -16
  50. package/dist/adapters.js +56 -16
  51. package/dist/checkout-lock.js +27 -2
  52. package/dist/cli-color.js +19 -0
  53. package/dist/cli-commands.js +1 -1
  54. package/dist/cli.js +7 -18
  55. package/dist/command-contract.js +462 -0
  56. package/dist/command-journal.js +263 -0
  57. package/dist/commands/call.js +252 -57
  58. package/dist/commands/check.js +10 -4
  59. package/dist/commands/completion-candidates.js +17 -22
  60. package/dist/commands/device-target.js +27 -12
  61. package/dist/commands/doctor.js +106 -25
  62. package/dist/commands/fixtures.js +142 -35
  63. package/dist/commands/last.js +60 -0
  64. package/dist/commands/launch/extension.js +40 -17
  65. package/dist/commands/launch/index.js +207 -63
  66. package/dist/commands/launch/mobile.js +2 -0
  67. package/dist/commands/list-executables.js +187 -29
  68. package/dist/commands/logs.js +8 -6
  69. package/dist/commands/manifest.js +286 -35
  70. package/dist/commands/parse-args.js +68 -4
  71. package/dist/commands/provision.js +10 -4
  72. package/dist/commands/run-engine.js +772 -264
  73. package/dist/commands/run-report.js +12 -3
  74. package/dist/commands/run.js +378 -85
  75. package/dist/commands/shared.js +76 -4
  76. package/dist/commands/status-probe.js +4 -1
  77. package/dist/commands/status.js +2 -1
  78. package/dist/commands/stop.js +7 -2
  79. package/dist/commands/update.js +16 -28
  80. package/dist/completions-cache.js +1 -1
  81. package/dist/doctor.js +57 -10
  82. package/dist/harness.js +47 -137
  83. package/dist/heal-bounds.js +7 -2
  84. package/dist/json-stream.js +57 -0
  85. package/dist/live-adapter-contract.js +138 -32
  86. package/dist/manifest.js +161 -1
  87. package/dist/mm-harness-cli.js +146 -73
  88. package/dist/paths.js +2 -5
  89. package/dist/recipe-security.js +178 -0
  90. package/dist/run-diagnostics.js +261 -0
  91. package/dist/run-recording.js +1 -1
  92. package/dist/runner.js +140 -9
  93. package/docs/CONTRIBUTING.md +136 -0
  94. package/docs/QA.md +184 -0
  95. package/docs/RECIPES.md +122 -0
  96. package/docs/SECURITY.md +88 -0
  97. package/library/README.md +7 -3
  98. package/library/actions/core/perps/_controller.mjs +43 -56
  99. package/library/actions/core/perps/assert_orders.mjs +6 -7
  100. package/library/actions/core/perps/assert_positions.mjs +6 -7
  101. package/library/actions/core/perps/close_orders.mjs +2 -0
  102. package/library/actions/core/perps/close_positions.mjs +2 -0
  103. package/library/actions/core/perps/ensure_orders.mjs +4 -2
  104. package/library/actions/core/perps/ensure_positions.mjs +4 -2
  105. package/library/actions/core/perps/place_order.mjs +7 -3
  106. package/library/actions/core/perps/read_account.mjs +2 -2
  107. package/library/actions/core/perps/read_orders.mjs +2 -1
  108. package/library/actions/core/perps/read_positions.mjs +2 -1
  109. package/library/actions/core/wallet/list_accounts.mjs +95 -0
  110. package/library/actions/extension/perps/assert_orders.mjs +2 -1
  111. package/library/actions/extension/perps/assert_positions.mjs +2 -1
  112. package/library/actions/extension/perps/perps.mjs +43 -14
  113. package/library/actions/extension/platform/cdp.mjs +1 -0
  114. package/library/actions/extension/wallet/list_accounts.mjs +41 -0
  115. package/library/actions/mobile/perps/assert_orders.mjs +2 -1
  116. package/library/actions/mobile/perps/assert_positions.mjs +2 -1
  117. package/library/actions/mobile/perps/perps.mjs +40 -12
  118. package/library/actions/mobile/wallet/list_accounts.mjs +37 -0
  119. package/library/library.json +1 -1
  120. package/library/manifests/core.action-manifest.json +1214 -396
  121. package/library/manifests/extension.action-manifest.json +1635 -728
  122. package/library/manifests/mobile.action-manifest.json +1740 -727
  123. package/library/recipes/app/lifecycle.android-smoke.mobile.recipe.json +63 -81
  124. package/library/recipes/perps/clean-market-testnet.core.recipe.json +44 -0
  125. package/library/recipes/perps/clean-market-testnet.recipe.json +49 -0
  126. package/library/recipes/perps/lifecycle.recipe.json +136 -180
  127. package/library/recipes/perps/order-lifecycle.core.recipe.json +71 -67
  128. package/library/recipes/perps/performance.background-resume.mobile.recipe.json +51 -67
  129. package/library/recipes/perps/performance.cold-start.mobile.recipe.json +51 -67
  130. package/library/recipes/perps/performance.mobile.recipe.json +37 -51
  131. package/library/recipes/perps/performance.warm-start.mobile.recipe.json +44 -59
  132. package/library/recipes/perps/read-markets.core.recipe.json +29 -31
  133. package/library/recipes/perps/smoke.core.recipe.json +29 -32
  134. package/library/recipes/perps/smoke.extension.recipe.json +41 -44
  135. package/library/recipes/perps/smoke.mobile.recipe.json +42 -44
  136. package/library/recipes/perps/trading-lifecycle.core.recipe.json +69 -65
  137. package/library/recipes/runner/action-validation.extension.recipe.json +312 -398
  138. package/library/recipes/runner/action-validation.mobile.recipe.json +316 -402
  139. package/library/recipes/runner/smoke.core.recipe.json +25 -0
  140. package/library/recipes/runner/smoke.extension.recipe.json +23 -24
  141. package/library/recipes/runner/smoke.mobile.recipe.json +23 -24
  142. package/library/recipes/wallet/smoke.extension.recipe.json +40 -0
  143. package/library/recipes/wallet/smoke.mobile.recipe.json +40 -0
  144. package/package.json +12 -5
  145. package/scripts/completions.sh +8 -11
  146. package/scripts/validate-human-outcomes.mjs +169 -0
  147. package/adapters/mobile/overlay/app/dev-tools/AgenticService/AgentStepHud.tsx.patch +0 -185
  148. package/adapters/mobile/overlay/app/dev-tools/AgenticService/AgenticService.ts.patch +0 -1662
  149. package/adapters/mobile/overlay/compat/README.md +0 -28
  150. package/adapters/mobile/overlay/compat/rn81-message-event-source.patch +0 -42
  151. package/adapters/shared/resolve-farmslot-ports-core.mjs +0 -3
  152. package/adapters/shared/resolve-farmslot-ports.mjs +0 -5
  153. package/adapters/shared/resolve-farmslot-ports.sh +0 -7
  154. package/dist/adapters/extension/harness-freshness.js +0 -39
  155. package/dist/commands/flows.js +0 -62
  156. package/docs/ADAPTER-SURFACE.md +0 -119
  157. package/docs/CHEATSHEET.md +0 -61
  158. package/docs/CLI-SPEC.md +0 -1098
  159. package/docs/CODE-MAP.md +0 -62
  160. package/docs/DEBUG-HANDOVER.md +0 -36
  161. package/docs/MENTAL-MODEL.md +0 -295
  162. package/docs/UX-PRINCIPLES.md +0 -64
  163. package/docs/architecture.md +0 -398
  164. package/docs/live-adapter-contract.md +0 -188
  165. package/docs/package-boundaries.md +0 -47
  166. package/docs/perps-flow-catalog.md +0 -235
  167. package/docs/recipe-libraries.md +0 -301
  168. package/docs/runtime-file-conventions.md +0 -36
  169. package/library/flows/perps.flows.json +0 -64
@@ -0,0 +1,136 @@
1
+ # Contributing
2
+
3
+ Keep `mm-harness` thin: put each change in the layer that owns it and validate
4
+ both the machine contract and the visible human result.
5
+
6
+ ## Ownership
7
+
8
+ ```text
9
+ bin/mm-harness
10
+ -> src/ typed CLI and product decisions
11
+ -> @farmslot/recipe-harness generic execution, UI transports, evidence
12
+ -> @farmslot/protocol schemas
13
+ -> adapters/ focused host/browser/device leaves
14
+ -> library/ MetaMask actions and recipes
15
+ -> MetaMask checkout product under test
16
+ ```
17
+
18
+ | Layer | Owns |
19
+ |---|---|
20
+ | `@farmslot/protocol` | recipe and evidence schemas |
21
+ | `@farmslot/recipe-harness` | generic execution, recovery, traces, artifacts, `ui.*` |
22
+ | `mm-harness` | MetaMask runtime control, diagnostics, durable domain actions |
23
+ | skills/checklists | task workflow and proof expectations |
24
+ | product checkout | app behavior and explicit debug hooks |
25
+
26
+ Generic bootstrap, trust, receipts, and recovery belong upstream. MetaMask
27
+ platform behavior and risk classification belong here. Ticket assertions stay
28
+ task-local.
29
+
30
+ ## Repository map
31
+
32
+ | Path | Responsibility |
33
+ |---|---|
34
+ | `bin/mm-harness` | only public executable |
35
+ | `src/commands/` | command behavior |
36
+ | `src/adapters/` | typed platform decisions and `AdapterSurface` |
37
+ | `adapters/<platform>/` | focused shell/Node host operations |
38
+ | `adapters/<platform>/inject*` | assemble the checkout overlay from shipped adapter/library files |
39
+ | `library/actions/` | executable MetaMask action adapters |
40
+ | `library/recipes/` | reusable parameterized behavior and proofs |
41
+ | `library/manifests/` | declared capability surface |
42
+ | `scripts/` | build/validation tooling and shipped completion/human-QA helpers |
43
+
44
+ All TypeScript lives under `src/`. Use `.mjs` for direct no-build Node leaves,
45
+ `.cjs` only for required CommonJS contexts, and shell only for host/device
46
+ commands. Decisions belong in TypeScript; a leaf performs one operation and
47
+ exits.
48
+
49
+ ## Adapter surface
50
+
51
+ Commands resolve shared platform behavior through
52
+ `src/adapters/surface.ts`. Extend `AdapterSurface` only when all platforms need
53
+ the concept, implement all three adapters, and let Core report headless/N/A
54
+ explicitly. Do not add command-local platform ladders for surface-owned behavior.
55
+
56
+ Each checkout owns:
57
+
58
+ ```text
59
+ temp/recipe/runtime/ ports, processes, fixture, logs, runtime identity
60
+ temp/recipe/harness/ installed runtime overlay
61
+ ```
62
+
63
+ Profiles, devices, ports, watchers, and evidence paths must resolve from that
64
+ checkout so slots remain isolated.
65
+
66
+ ## Actions and adapters
67
+
68
+ Official `ui.*` behavior comes from the generic runtime. MetaMask-specific
69
+ actions are manifest-declared modules under:
70
+
71
+ ```text
72
+ library/actions/<platform>/<domain>/<name>.mjs
73
+ library/actions/shared/<domain>/<name>.mjs
74
+ ```
75
+
76
+ Configured libraries use the same structure. An adapter receives a JSON input
77
+ path, writes JSON to its `outputPath` or stdout, returns redacted trace-safe
78
+ output, and performs only the declared operation. It must not execute another
79
+ recipe graph.
80
+
81
+ The input path is argv 1 and `METAMASK_RECIPE_ADAPTER_INPUT`. Its document is:
82
+
83
+ ```json
84
+ {
85
+ "schemaVersion": 1,
86
+ "platform": "mobile|extension|core",
87
+ "action": "metamask.example.action",
88
+ "node": {},
89
+ "context": {
90
+ "nodeId": "step-id",
91
+ "projectRoot": "/path/to/checkout",
92
+ "artifactsDir": "/path/to/run/artifacts"
93
+ },
94
+ "outputPath": "/temporary/output.json"
95
+ }
96
+ ```
97
+
98
+ Write JSON to `outputPath` (also `METAMASK_RECIPE_ADAPTER_OUTPUT`) or stdout.
99
+ Write evidence under `context.artifactsDir` and return relative artifact paths.
100
+ `METAMASK_RECIPE_LIVE_ADAPTER_DIR` is the explicit task-local implementation
101
+ root; configured libraries are the durable sharing mechanism.
102
+
103
+ Add a bundled action only when it is reusable, typed, stable, reduces inference
104
+ or risk, and has a real postcondition. Otherwise use a team library or task-local
105
+ recipe. Follow [Recipes](RECIPES.md) and [Security](SECURITY.md).
106
+
107
+ ## CLI contract
108
+
109
+ - Human mode is contextual, colored only in a TTY, and teaches one exact next
110
+ action on failure.
111
+ - `--json` stdout is one stable document with no decoration.
112
+ - Long work acknowledges intent before blocking and streams child output.
113
+ - Lifecycle commands are checkout-scoped and idempotent.
114
+ - `doctor` is read-only; `doctor --fix` repairs without launching.
115
+ - No command may fabricate platform support or readiness.
116
+
117
+ When adding a command, register its behavior and human metadata, then add a
118
+ contract test. When a flag reaches a host leaf, both the typed composer and leaf
119
+ parser must accept it. Before renaming or removing a public flag, injected file,
120
+ or wrapper, verify real callers and retain compatibility only when one exists.
121
+
122
+ ## Change gates
123
+
124
+ ```bash
125
+ yarn test:unit
126
+ yarn test:coverage
127
+ yarn check
128
+ bash tests/contract/run.sh
129
+ ```
130
+
131
+ Runtime changes also require real affected-platform QA and a packed installation
132
+ test. Update `CHANGELOG.md` under `Unreleased` for user-visible behavior.
133
+
134
+ Docs describe only current behavior. History belongs in the changelog and Git;
135
+ do not add handovers, audits, speculative roadmaps, or duplicate command guides
136
+ under `docs/`.
package/docs/QA.md ADDED
@@ -0,0 +1,184 @@
1
+ # QA
2
+
3
+ Validate the installed candidate as a human would use it. Use disposable
4
+ profiles and an unfunded fixture; preserve existing product source and active
5
+ processes.
6
+
7
+ ## Candidate and provenance
8
+
9
+ ```bash
10
+ export CANDIDATE=/path/to/mm-harness-candidate.tgz
11
+ export QA_HOME="$(mktemp -d "$HOME/mmh-qa.XXXXXX")"
12
+ export QA_PREFIX="$QA_HOME/npm"
13
+ HOME="$QA_HOME" npm install -g --prefix "$QA_PREFIX" "$CANDIDATE"
14
+ export PATH="$QA_PREFIX/bin:$PATH"
15
+ mm-harness --version
16
+ ```
17
+
18
+ - [ ] The executable and dependencies resolve inside the isolated prefix.
19
+ - [ ] No dependency is a symlink or resolves through a local Farmslot checkout.
20
+ - [ ] Record the tarball SHA-256 and product SHAs.
21
+ - [ ] Product trees start and finish without tracked changes.
22
+
23
+ ## Common
24
+
25
+ Run inside each Extension, Mobile, and Core checkout:
26
+
27
+ ```bash
28
+ mm-harness doctor
29
+ mm-harness doctor --json
30
+ mm-harness status
31
+ mm-harness actions
32
+ mm-harness run --list
33
+ mm-harness run runner.smoke --describe
34
+ mm-harness run runner.smoke --plan
35
+ mm-harness run runner.smoke
36
+ mm-harness last --json
37
+ ```
38
+
39
+ - [ ] Product, checkout, slot, ports, and next action are correct.
40
+ - [ ] Human output is concise and evidence paths are absolute.
41
+ - [ ] JSON output is one parseable document without color or prose on stdout.
42
+ - [ ] `run` chooses a checkout-local artifact directory; an explicit
43
+ `--artifacts-dir` still wins.
44
+ - [ ] Reports, trace, diagnostics, executed recipe, and manifest exist and agree.
45
+ - [ ] `last --json` reconstructs the run without re-executing it.
46
+
47
+ Recovery checks:
48
+
49
+ ```bash
50
+ mm-harness actions --wat
51
+ mm-harness run missing.recipe --describe
52
+ mm-harness doctor --fix
53
+ mm-harness verify
54
+ ```
55
+
56
+ - [ ] Bad input fails before runtime work with a stable code and one exact next
57
+ action.
58
+ - [ ] `doctor --fix` is idempotent and does not choose a fixture or launch.
59
+ - [ ] With `capture-helper` absent, Extension reports CDP screenshots and Mobile
60
+ reports `simctl`/ADB screenshots; video is honestly unavailable.
61
+
62
+ Run the bounded multi-platform preflight when all three checkouts are available:
63
+
64
+ ```bash
65
+ yarn qa:human \
66
+ --extension /path/to/metamask-extension \
67
+ --mobile /path/to/metamask-mobile \
68
+ --core /path/to/metamask-core \
69
+ --artifacts-dir temp/human-qa
70
+ ```
71
+
72
+ It supplements the visible checks below; it does not replace them.
73
+
74
+ ## Extension
75
+
76
+ Fresh MetaMask Extension needs its normal product configuration and
77
+ checkout-pinned Chromium. Follow the product files; do not invent values:
78
+
79
+ ```bash
80
+ cd /path/to/metamask-extension
81
+ cp .metamaskrc.dist .metamaskrc
82
+ ${EDITOR:-vi} .metamaskrc
83
+ yarn playwright install chromium
84
+ mm-harness launch --verify
85
+ mm-harness fixtures set
86
+ mm-harness run wallet.smoke
87
+ mm-harness logs --source extension
88
+ mm-harness logs --source dapp
89
+ mm-harness logs --source webpack
90
+ mm-harness debug
91
+ ```
92
+
93
+ - [ ] Missing/placeholder Infura configuration returns
94
+ `EXTENSION_PRODUCT_CONFIG_REQUIRED` before build or browser startup.
95
+ - [ ] Missing Chromium returns `EXTENSION_BROWSER_REQUIRED` without using system
96
+ Chrome.
97
+ - [ ] Launch uses the checkout-owned profile, opens one MetaMask surface, avoids
98
+ keychain prompts, and preserves keyboard focus by default.
99
+ - [ ] A second launch reuses the watcher/profile without duplicate tabs.
100
+ - [ ] Two source edits rebuild incrementally; refresh shows each change; revert
101
+ restores a clean tree.
102
+ - [ ] Log sources are distinct.
103
+ - [ ] `debug` opens connected DevTools for the active Extension surface;
104
+ `location.href` returns its `chrome-extension://` URL and remains connected.
105
+
106
+ ## Mobile
107
+
108
+ ```bash
109
+ cd /path/to/metamask-mobile
110
+ mm-harness provision runway ios
111
+ mm-harness launch ios --verify
112
+ mm-harness fixtures set
113
+ mm-harness call metamask.wallet.ensure_unlocked
114
+ mm-harness run wallet.smoke
115
+ mm-harness logs --source app
116
+ mm-harness logs --source metro
117
+ mm-harness debug
118
+ ```
119
+
120
+ - [ ] Simulator opens only when absent and does not steal focus by default.
121
+ - [ ] A second launch reuses the running simulator and Metro.
122
+ - [ ] Fixture setup and unlock show the intended redacted account without
123
+ mnemonic/private-key output.
124
+ - [ ] Status matches verified product routes: `Login`/`LockScreen` are locked;
125
+ `WalletView` is unlocked.
126
+ - [ ] App and Metro logs are separate.
127
+ - [ ] A JS edit rebuilds through Metro and appears after reload without a native
128
+ rebuild; revert restores a clean tree.
129
+
130
+ When Android/ADB is available, repeat with:
131
+
132
+ ```bash
133
+ mm-harness launch android --device <serial> --verify
134
+ ```
135
+
136
+ ## Core
137
+
138
+ ```bash
139
+ cd /path/to/metamask-core
140
+ mm-harness doctor
141
+ mm-harness call metamask.wallet.list_accounts scope=selected
142
+ mm-harness run runner.smoke
143
+ mm-harness logs
144
+ mm-harness debug
145
+ ```
146
+
147
+ - [ ] Doctor reports a headless controller surface and no capture requirement.
148
+ - [ ] Account output is fixture-backed and redacted.
149
+ - [ ] Smoke writes the complete evidence package without launching an app.
150
+ - [ ] Logs/debug fail with truthful headless teaching errors.
151
+
152
+ ## Trust and evidence
153
+
154
+ - [ ] An untrusted restricted plan fails with `RECIPE_TRUST_REQUIRED` and no
155
+ side effect.
156
+ - [ ] A wrong/stale digest fails with `RECIPE_APPROVAL_MISMATCH`.
157
+ - [ ] Only the unchanged, reviewed plan executes with its exact approval digest.
158
+ - [ ] Human output, JSON, reports, traces, diagnostics, and screenshots contain
159
+ no mnemonic, private key, seed, bearer token, or API credential.
160
+ - [ ] Diagnostics contain only events observed in the proof window.
161
+ - [ ] Screenshot provenance identifies capture-helper, CDP, simctl, or ADB
162
+ accurately.
163
+
164
+ ## Automated and release gates
165
+
166
+ ```bash
167
+ yarn check
168
+ bash tests/contract/run.sh
169
+ ```
170
+
171
+ Before release:
172
+
173
+ - [ ] Focused unit tests and full contract suite pass.
174
+ - [ ] Packed isolated installation passes the critical Extension, Mobile, and
175
+ Core scenarios.
176
+ - [ ] Independent review approves the exact final diff.
177
+ - [ ] Known limits are explicit: Extension requires product Infura setup;
178
+ Mobile requires its normal dev-client/device setup; video requires optional
179
+ `capture-helper`; the harness never invents funded fixtures.
180
+ - [ ] Existing Farmslot slots remain compatible.
181
+
182
+ When a slot manager is available, repeat `runner.smoke` in one existing managed
183
+ checkout per product and verify its profile/device, ports, processes, and fixture
184
+ remain isolated.
@@ -0,0 +1,122 @@
1
+ # Recipes
2
+
3
+ Use the smallest durable layer that proves the task:
4
+
5
+ 1. call an existing action;
6
+ 2. compose existing recipes;
7
+ 3. write a task-local recipe;
8
+ 4. use a verified controller or CDP path when no stable action exists.
9
+
10
+ Discover before authoring:
11
+
12
+ ```bash
13
+ mm-harness actions <intent>
14
+ mm-harness actions --action <name>
15
+ mm-harness run --list
16
+ mm-harness run <name> --describe
17
+ ```
18
+
19
+ Discovery reports parameters, selected adapter variant, nested recipes, source,
20
+ and shadows. Use `--json` for exact metadata.
21
+
22
+ ## Author and run
23
+
24
+ An action performs one typed operation. A recipe owns a reusable graph or a
25
+ task proof and may call other recipes.
26
+
27
+ ```json
28
+ {
29
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
30
+ "title": "Wallet readiness",
31
+ "description": "Proves the running wallet is reachable and unlocked.",
32
+ "paramsSchema": {
33
+ "type": "object",
34
+ "properties": {
35
+ "account": { "type": "string", "default": "Account 1" }
36
+ },
37
+ "additionalProperties": false
38
+ },
39
+ "workflow": {
40
+ "entry": "unlock",
41
+ "nodes": {
42
+ "unlock": {
43
+ "action": "metamask.wallet.ensure_unlocked",
44
+ "intent": "Make the fixture-backed wallet ready for use",
45
+ "next": "done"
46
+ },
47
+ "done": { "action": "end", "status": "pass" }
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ Defaults are applied before validation. Root values use `key=value`; a nested
54
+ recipe call uses `action: "call"`, `ref`, and `params`.
55
+
56
+ ```bash
57
+ mm-harness run recipe.json account="Account 2" --plan
58
+ mm-harness run recipe.json account="Account 2"
59
+ ```
60
+
61
+ Rules:
62
+
63
+ - Validate with `--plan` before side effects.
64
+ - Use real product paths; never mutate hidden state to fabricate proof.
65
+ - Prove preparation with an independent read/assert or visible UI postcondition.
66
+ - Keep ticket-specific claims in task-local recipes.
67
+ - Parameterize repeated behavior instead of multiplying names.
68
+ - Keep secrets out of recipes, libraries, and evidence.
69
+
70
+ The protocol is authoritative:
71
+ <https://farmslot.io/docs/reference/recipe-protocol-v1>.
72
+
73
+ ## Share a library
74
+
75
+ ```text
76
+ team-recipes/
77
+ library.json
78
+ manifests/extension.action-manifest.json
79
+ actions/extension/wallet/ensure_ready.mjs
80
+ recipes/onboarding/smoke.extension.recipe.json
81
+ ```
82
+
83
+ ```json
84
+ {
85
+ "kind": "recipe-library",
86
+ "schema_version": 1,
87
+ "name": "wallet-team",
88
+ "owner": "wallet-team"
89
+ }
90
+ ```
91
+
92
+ ```bash
93
+ export RECIPE_LIBRARY_PATH="wallet=$HOME/shared-library/wallet-team"
94
+ mm-harness run --list
95
+ mm-harness run onboarding.smoke --describe
96
+ mm-harness run onboarding.smoke --plan
97
+ ```
98
+
99
+ Use `--library wallet=/path/to/library` for one command. Resolution follows the
100
+ explicit library order, then bundled MetaMask. Adapter-specific variants are
101
+ selected deterministically. Every run records the root recipe, exact resolved
102
+ dependency documents, their digests, call edges, selected sources, and shadows.
103
+
104
+ ## Direct product access
105
+
106
+ The bundled library is intentionally small. A task may use a verified controller
107
+ or CDP path when that is clearer than adding a permanent wrapper. Confirm the
108
+ current source path, mutation risk, preconditions, independent postcondition,
109
+ and redaction. Do not infer route or controller names from memory. Repeated team
110
+ behavior belongs in a reviewed team recipe; only broadly reusable stable
111
+ capabilities belong in the bundled library.
112
+
113
+ Mobile and Extension share vocabulary where the product supports it. Core is
114
+ headless and must not fabricate UI state. Inspect the current surface:
115
+
116
+ ```bash
117
+ mm-harness actions --category wallet --json
118
+ mm-harness actions --category perps --json
119
+ mm-harness run --list --json
120
+ ```
121
+
122
+ See [Security](SECURITY.md) before enabling custom executable actions.
@@ -0,0 +1,88 @@
1
+ # Security
2
+
3
+ `mm-harness` executes product code, recipes, and optional custom adapters with
4
+ the current user's authority. It is a proof tool, not an OS sandbox.
5
+
6
+ ## Trust boundary
7
+
8
+ - Bundled actions and recipes are trusted package content.
9
+ - A configured library cannot declare itself trusted.
10
+ - Untrusted plans that request restricted capabilities stop before runtime
11
+ preparation or side effects with `RECIPE_TRUST_REQUIRED`.
12
+ - The failure reports blocked nodes, capabilities, source provenance, and one
13
+ exact approval command.
14
+ - Approval is bound to the resolved plan, implementation bundle, project root,
15
+ artifact directory, and execution environment.
16
+ - Changed code or inputs produce `RECIPE_APPROVAL_MISMATCH`; an old digest does
17
+ not authorize a new plan.
18
+
19
+ Never construct an approval from memory. Inspect the plan and use the exact
20
+ `userAction` emitted by the failed run. Review custom libraries like application
21
+ code because approved code retains the user's filesystem, process, and network
22
+ permissions.
23
+
24
+ ## Product-state integrity
25
+
26
+ Proof must come from supported UI, controller, or API paths. Never write DOM,
27
+ React/Redux/MobX state, controller internals, or storage merely to manufacture
28
+ the claimed result.
29
+
30
+ Fixture setup is allowed before the proof window when it is explicit in the
31
+ trace. Mutating setup must finish with a real read/assert or visible UI
32
+ postcondition.
33
+
34
+ ## Wallet fixtures
35
+
36
+ Each checkout has one canonical fixture:
37
+
38
+ ```text
39
+ temp/recipe/runtime/wallet-fixture.json
40
+ ```
41
+
42
+ Initialize it explicitly from an approved fixture or choose the disposable
43
+ `--dev` option shown in the [README](../README.md). Never fund a dev fixture.
44
+
45
+ - Never commit a fixture containing a mnemonic or private key.
46
+ - Never print, paste, or record mnemonic/private-key material.
47
+ - Use funded fixtures only in the intended isolated environment.
48
+ - `fixtures set` reads the password from the fixture; do not put it on the
49
+ command line.
50
+ - Human and JSON outputs may identify redacted accounts but must not expose
51
+ secret material.
52
+
53
+ ## Evidence and journals
54
+
55
+ Recipe output may include application logs, screenshots, traces, and custom
56
+ action results. Before sharing it:
57
+
58
+ - verify the artifact manifest contains only intended files;
59
+ - search human output, JSON, traces, diagnostics, and reports for credentials;
60
+ - confirm screenshots use the declared provider and show no sensitive UI;
61
+ - keep task-local artifacts out of source control unless intentionally reviewed.
62
+
63
+ `mm-harness last --json` stores a redacted resumability record. It is not a
64
+ secret store.
65
+
66
+ ## Runtime isolation
67
+
68
+ Extension uses a checkout-owned Chrome profile and CDP port. Mobile resolves a
69
+ checkout-owned simulator/device and Metro port. Core is headless. Parallel
70
+ checkouts must not share profiles, runtime directories, process markers, or
71
+ evidence directories.
72
+
73
+ On macOS, Extension Chromium uses a mock keychain so an isolated test profile
74
+ does not touch the operator's login keychain. Product configuration and wallet
75
+ fixtures remain user-owned; the harness detects missing prerequisites but never
76
+ invents them.
77
+
78
+ ## Release checks
79
+
80
+ Security-sensitive changes require:
81
+
82
+ 1. trust-boundary tests proving rejection occurs before side effects;
83
+ 2. exact-digest success and stale-digest rejection;
84
+ 3. redaction tests for arguments, results, journals, and evidence;
85
+ 4. packed-install provenance with no local links;
86
+ 5. independent review of the exact diff.
87
+
88
+ Use [QA](QA.md) for the runnable checklist.
package/library/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Recipe library
2
2
 
3
+ - An **action** performs one typed operation.
4
+ - A **recipe** is a parameterized, composable graph that may call actions and
5
+ other recipes.
6
+
3
7
  - `actions/<adapter>/<group>/<name>.mjs` — executable action modules.
4
8
  **Importing an action module RUNS it**: each ends with `runAdapter(main)` at top
5
9
  level, which reads the live-adapter input path from the environment and executes.
@@ -9,6 +13,6 @@
9
13
  - Actions load harness helpers ONLY through `actions/harness-exports.mjs` (the
10
14
  dist-preferring bridge) — never deep-import `src/` (published installs have no
11
15
  src/, and the entrypoint would close an import cycle through adapters.ts).
12
- - `recipes/` — runnable smoke/validation recipes (`mm-harness run <file>`).
13
- - Flow resolution order is personal > team > canonical; shadowing is recorded in
14
- summary.json (never silent).
16
+ - `recipes/` — runnable recipes (`mm-harness run <name-or-file>`).
17
+ - Recipe resolution is explicit library order, then bundled MetaMask; selected
18
+ variants and shadows are recorded in run evidence.