@deeeed/metamask-harness 0.48.0 → 0.49.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 (177) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/commands/help.js +17 -5
  3. package/dist/funding-execution-context.js +19 -4
  4. package/dist/metamask-action-validation.js +3 -2
  5. package/dist/mm-harness-cli.js +2 -1
  6. package/docs/RECIPES.md +2 -2
  7. package/library/actions/core/perps/_controller.mjs +14 -24
  8. package/library/actions/core/perps/assert_orders.mjs +3 -5
  9. package/library/actions/core/perps/assert_positions.mjs +3 -5
  10. package/library/actions/core/perps/close_orders.mjs +28 -4
  11. package/library/actions/core/perps/close_positions.mjs +53 -12
  12. package/library/actions/core/perps/edit_order.mjs +2 -0
  13. package/library/actions/core/perps/ensure_orders.mjs +3 -4
  14. package/library/actions/core/perps/ensure_positions.mjs +4 -5
  15. package/library/actions/core/perps/place_order.mjs +7 -14
  16. package/library/actions/core/perps/read_account.mjs +2 -0
  17. package/library/actions/core/perps/read_orders.mjs +2 -0
  18. package/library/actions/core/perps/read_positions.mjs +3 -1
  19. package/library/actions/core/perps/read_snapshot.mjs +3 -0
  20. package/library/actions/core/perps/start_state.mjs +3 -14
  21. package/library/actions/core/perps/teardown_state.mjs +3 -14
  22. package/library/actions/core/perps/update_position_tpsl.mjs +13 -19
  23. package/library/actions/core/wallet/list_accounts.mjs +3 -0
  24. package/library/actions/extension/analytics/consent.mjs +2 -0
  25. package/library/actions/extension/analytics/set_consent.mjs +2 -0
  26. package/library/actions/extension/assets/home-token-identity.mjs +1 -0
  27. package/library/actions/extension/assets/import_custom_token.mjs +2 -0
  28. package/library/actions/extension/assets/open_details.mjs +1 -0
  29. package/library/actions/extension/assets/prepare_send.mjs +1 -0
  30. package/library/actions/extension/assets/read_details.mjs +1 -0
  31. package/library/actions/extension/assets/read_visible_state.mjs +1 -0
  32. package/library/actions/extension/assets/review_send.mjs +1 -0
  33. package/library/actions/extension/assets/select_network_scope.mjs +1 -0
  34. package/library/actions/extension/assets/send.mjs +2 -0
  35. package/library/actions/extension/assets/set_custom_gas.mjs +1 -0
  36. package/library/actions/extension/assets/set_token_visibility.mjs +2 -0
  37. package/library/actions/extension/assets/verify_sorting.mjs +1 -0
  38. package/library/actions/extension/deeplink/open.mjs +1 -0
  39. package/library/actions/extension/networks/add_chainlist.mjs +2 -0
  40. package/library/actions/extension/networks/add_custom.mjs +2 -0
  41. package/library/actions/extension/networks/custom_network.mjs +2 -0
  42. package/library/actions/extension/networks/read_visible_state.mjs +1 -0
  43. package/library/actions/extension/networks/remove_custom.mjs +1 -0
  44. package/library/actions/extension/performance/_navigation-memory.mjs +2 -0
  45. package/library/actions/extension/performance/compare_idle_navigation_memory.mjs +2 -0
  46. package/library/actions/extension/performance/measure_detached_dom.mjs +2 -0
  47. package/library/actions/extension/performance/measure_navigation_memory.mjs +2 -0
  48. package/library/actions/extension/perps/assert_orders.mjs +1 -0
  49. package/library/actions/extension/perps/assert_positions.mjs +1 -0
  50. package/library/actions/extension/perps/assert_visible_consistency.mjs +2 -0
  51. package/library/actions/extension/perps/close_orders.mjs +4 -1
  52. package/library/actions/extension/perps/close_positions.mjs +1 -0
  53. package/library/actions/extension/perps/close_visible_position.mjs +159 -10
  54. package/library/actions/extension/perps/compare_provider_market.mjs +2 -0
  55. package/library/actions/extension/perps/edit_margin.mjs +2 -0
  56. package/library/actions/extension/perps/ensure_orders.mjs +1 -0
  57. package/library/actions/extension/perps/ensure_positions.mjs +1 -0
  58. package/library/actions/extension/perps/mutation-receipt.mjs +54 -3
  59. package/library/actions/extension/perps/open_balance_action.mjs +1 -0
  60. package/library/actions/extension/perps/open_position_action.mjs +1 -0
  61. package/library/actions/extension/perps/perps.mjs +401 -25
  62. package/library/actions/extension/perps/place_order.mjs +1 -0
  63. package/library/actions/extension/perps/read_eligibility.mjs +1 -0
  64. package/library/actions/extension/perps/read_funds_confirmation.mjs +2 -0
  65. package/library/actions/extension/perps/read_orders.mjs +1 -0
  66. package/library/actions/extension/perps/read_positions.mjs +1 -0
  67. package/library/actions/extension/perps/read_snapshot.mjs +2 -0
  68. package/library/actions/extension/perps/read_visible_state.mjs +2 -0
  69. package/library/actions/extension/perps/search_markets.mjs +1 -0
  70. package/library/actions/extension/perps/select_activity_filter.mjs +1 -0
  71. package/library/actions/extension/perps/select_market_filter.mjs +1 -0
  72. package/library/actions/extension/perps/set_market_favorite.mjs +1 -0
  73. package/library/actions/extension/perps/state.mjs +1 -0
  74. package/library/actions/extension/perps/update_position_tpsl.mjs +2 -0
  75. package/library/actions/extension/perps/visible-mutation-identity.mjs +2 -0
  76. package/library/actions/extension/platform/cdp.mjs +29 -2
  77. package/library/actions/extension/settings/set_basic_functionality.mjs +1 -0
  78. package/library/actions/extension/swap_bridge/quote-state.mjs +2 -0
  79. package/library/actions/extension/swap_bridge/read_visible_state.mjs +1 -0
  80. package/library/actions/extension/swap_bridge/select_assets.mjs +1 -0
  81. package/library/actions/extension/swap_bridge/set_amount.mjs +1 -0
  82. package/library/actions/extension/swap_bridge/set_max_amount.mjs +1 -0
  83. package/library/actions/extension/swap_bridge/set_slippage.mjs +1 -0
  84. package/library/actions/extension/ui/locators.mjs +1 -0
  85. package/library/actions/extension/ui/navigate.mjs +2 -0
  86. package/library/actions/extension/wallet/ensure_unlocked.mjs +2 -0
  87. package/library/actions/extension/wallet/import.mjs +2 -0
  88. package/library/actions/extension/wallet/list_accounts.mjs +1 -0
  89. package/library/actions/extension/wallet/lock.mjs +2 -0
  90. package/library/actions/extension/wallet/read_state.mjs +1 -0
  91. package/library/actions/extension/wallet/reset.mjs +2 -0
  92. package/library/actions/extension/wallet/secret-input.mjs +2 -0
  93. package/library/actions/extension/wallet/select_account.mjs +2 -0
  94. package/library/actions/extension/wallet/setup.mjs +1 -0
  95. package/library/actions/extension/wallet/state.mjs +2 -0
  96. package/library/actions/extension/wallet/visible-session.mjs +2 -0
  97. package/library/actions/mobile/analytics/consent-settings.mjs +1 -0
  98. package/library/actions/mobile/analytics/set_consent.mjs +1 -0
  99. package/library/actions/mobile/app/network-control.mjs +2 -0
  100. package/library/actions/mobile/app/network.mjs +1 -0
  101. package/library/actions/mobile/app/network_assert.mjs +1 -0
  102. package/library/actions/mobile/app/network_capture.mjs +1 -0
  103. package/library/actions/mobile/assets/import_custom_token.mjs +2 -0
  104. package/library/actions/mobile/assets/open_details.mjs +1 -0
  105. package/library/actions/mobile/assets/read_details.mjs +1 -0
  106. package/library/actions/mobile/assets/read_visible_state.mjs +1 -0
  107. package/library/actions/mobile/assets/set_token_visibility.mjs +2 -0
  108. package/library/actions/mobile/assets/verify_sorting.mjs +90 -7
  109. package/library/actions/mobile/deeplink/open.mjs +1 -0
  110. package/library/actions/mobile/networks/add_custom.mjs +1 -0
  111. package/library/actions/mobile/networks/network-management.mjs +1 -0
  112. package/library/actions/mobile/networks/read_visible_state.mjs +1 -0
  113. package/library/actions/mobile/networks/remove_custom.mjs +1 -0
  114. package/library/actions/mobile/perps/assert_orders.mjs +1 -0
  115. package/library/actions/mobile/perps/assert_positions.mjs +1 -0
  116. package/library/actions/mobile/perps/capture_performance.mjs +1 -0
  117. package/library/actions/mobile/perps/close_orders.mjs +1 -0
  118. package/library/actions/mobile/perps/close_positions.mjs +1 -0
  119. package/library/actions/mobile/perps/ensure_orders.mjs +1 -0
  120. package/library/actions/mobile/perps/ensure_positions.mjs +1 -0
  121. package/library/actions/mobile/perps/measure_homepage_visible.mjs +1 -0
  122. package/library/actions/mobile/perps/performance-capture.mjs +2 -0
  123. package/library/actions/mobile/perps/perps.mjs +6 -2
  124. package/library/actions/mobile/perps/place_order.mjs +1 -0
  125. package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +2 -0
  126. package/library/actions/mobile/perps/read-visible-state-loop.mjs +2 -0
  127. package/library/actions/mobile/perps/read_orders.mjs +1 -0
  128. package/library/actions/mobile/perps/read_positions.mjs +1 -0
  129. package/library/actions/mobile/perps/read_visible_state.mjs +1 -0
  130. package/library/actions/mobile/perps/search_markets.mjs +1 -0
  131. package/library/actions/mobile/perps/set_market_favorite.mjs +2 -0
  132. package/library/actions/mobile/platform/bridge.mjs +16 -4
  133. package/library/actions/mobile/platform/native-session-name.mjs +1 -0
  134. package/library/actions/mobile/platform/native-session.mjs +2 -0
  135. package/library/actions/mobile/platform/observe-ui.mjs +2 -0
  136. package/library/actions/mobile/platform/tool-paths.mjs +1 -0
  137. package/library/actions/mobile/swap_bridge/native-session.mjs +1 -0
  138. package/library/actions/mobile/swap_bridge/read_visible_state.mjs +1 -0
  139. package/library/actions/mobile/swap_bridge/select_assets.mjs +2 -0
  140. package/library/actions/mobile/swap_bridge/set_amount.mjs +1 -0
  141. package/library/actions/mobile/swap_bridge/set_max_amount.mjs +1 -0
  142. package/library/actions/mobile/swap_bridge/set_slippage.mjs +1 -0
  143. package/library/actions/mobile/swap_bridge/submit_transaction.mjs +2 -0
  144. package/library/actions/mobile/ui/locators.mjs +1 -0
  145. package/library/actions/mobile/ui/native-navigation.mjs +2 -0
  146. package/library/actions/mobile/ui/navigate.mjs +2 -0
  147. package/library/actions/mobile/wallet/ensure_unlocked.mjs +2 -0
  148. package/library/actions/mobile/wallet/home.mjs +1 -0
  149. package/library/actions/mobile/wallet/import.mjs +2 -0
  150. package/library/actions/mobile/wallet/list_accounts.mjs +1 -0
  151. package/library/actions/mobile/wallet/lock.mjs +1 -0
  152. package/library/actions/mobile/wallet/native-ui.mjs +2 -0
  153. package/library/actions/mobile/wallet/read_state.mjs +2 -0
  154. package/library/actions/mobile/wallet/reset-helper.mjs +1 -0
  155. package/library/actions/mobile/wallet/reset.mjs +1 -0
  156. package/library/actions/mobile/wallet/select_account.mjs +2 -0
  157. package/library/actions/mobile/wallet/setup.mjs +2 -0
  158. package/library/actions/shared/analytics/assert_events.mjs +3 -0
  159. package/library/actions/shared/analytics/consent.mjs +3 -0
  160. package/library/actions/shared/analytics/read_events.mjs +2 -0
  161. package/library/actions/shared/analytics/start_capture.mjs +3 -0
  162. package/library/actions/shared/app/network-artifact.mjs +2 -0
  163. package/library/actions/shared/app/network-assert.mjs +2 -0
  164. package/library/actions/shared/assets/visible-state.mjs +2 -0
  165. package/library/actions/shared/deeplink/url.mjs +3 -0
  166. package/library/actions/shared/networks/visible-state.mjs +2 -0
  167. package/library/actions/shared/perps/visible-state.mjs +2 -0
  168. package/library/actions/shared/swap-bridge/transaction.mjs +3 -0
  169. package/library/actions/shared/swap-bridge/visible-state.mjs +2 -0
  170. package/library/actions/shared/ui/locators.mjs +2 -0
  171. package/library/actions/shared/wallet/import-source.mjs +3 -0
  172. package/library/manifests/core.action-manifest.json +20 -0
  173. package/library/manifests/extension.action-manifest.json +2 -2
  174. package/library/manifests/mobile.action-manifest.json +3 -3
  175. package/library/recipes/mobile/app/{lifecycle.android-smoke.recipe.json → lifecycle-smoke.recipe.json} +12 -11
  176. package/package.json +1 -1
  177. package/site/assets/help-recipes.json +188 -35
@@ -12,9 +12,21 @@
12
12
  "title": "Freeze the proof target",
13
13
  "instruction": "Work inside one isolated MetaMask checkout. Name the exact product version and acceptance criteria, repair harness-owned state, then verify or launch that checkout.",
14
14
  "details": [
15
- "The tested build and current criteria are authoritative. A prior recipe pass is not current proof. Freeze source and installed dependencies during execution. Parallel workers need private dependency trees with matching manifests and lockfiles; installing through a shared node_modules symlink can change another run. Mobile catalog compatibility does not establish both iOS and Android runtime support; validate the selected transport.",
16
- "Launching Extension preserves its wallet profile. Applying a fixture or resetting that profile is a separate explicit action. A session helper proves only its declared postcondition, not the selected account, provider, network, or funding; verify those separately before trading. Use account-aware balances: Hyperliquid unified accounts can use spot collateral even when clearinghouseState reports zero margin.",
17
- "Choose state, visual, log, or performance evidence for each criterion before authoring the graph. A tool returning successfully proves only its own operation, not the task's claim."
15
+ "The tested build and current criteria are authoritative. A prior recipe pass is not current proof. Freeze source and installed dependencies during execution. Parallel workers need private dependency trees with matching manifests and lockfiles; installing through a shared node_modules symlink can change another run.",
16
+ "A session helper proves only its declared postcondition, not the selected account, provider, network, or funding; verify those separately before trading. Use account-aware balances: Hyperliquid unified accounts can use spot collateral even when clearinghouseState reports zero margin.",
17
+ "Choose state, visual, log, or performance evidence for each criterion before authoring the graph. A tool returning successfully proves only its own operation, not the task's claim.",
18
+ {
19
+ "text": "Mobile catalog compatibility does not establish both iOS and Android runtime support; validate the selected transport.",
20
+ "adapters": [
21
+ "mobile"
22
+ ]
23
+ },
24
+ {
25
+ "text": "Launching Extension preserves its wallet profile. Applying a fixture or resetting that profile is a separate explicit action.",
26
+ "adapters": [
27
+ "extension"
28
+ ]
29
+ }
18
30
  ],
19
31
  "commands": [
20
32
  "mm-harness doctor --fix",
@@ -26,15 +38,27 @@
26
38
  "title": "Discover the strongest starting point",
27
39
  "instruction": "Search the installed recipe and action catalogs, inspect exact schemas, and select the closest recipe before writing anything new.",
28
40
  "details": [
29
- "A bundled recipe, including a Core recipe, is strong composable vocabulary, not authority for every future product version. Core actions use isolated controllers: pass account/network into each action instead of adding a no-op initialization node.",
30
- "Prefer an existing recipe, then existing actions, then read-only CDP or controller inspection. Add shared vocabulary only after repeated need is proven.",
41
+ "A bundled recipe is strong composable vocabulary, not authority for every future product version.",
42
+ "Prefer an existing recipe, then existing actions, then read-only inspection. Add shared vocabulary only after repeated need is proven.",
31
43
  "Before declaring a capability unsupported, inspect both catalogs and the closest recipe's composition. A missing dedicated action may already be composed from UI actions. Read the returned schema, examples, and result_cases before authoring; do not treat guessed field names as empty capabilities.",
32
- "Register a team library with --library team=/path/to/library-root, the directory containing recipes/. Use discovered recipe names in call.ref; the library alias names its source, not a recipe-name prefix. Confirm --describe reports the intended source and platform variant, then plan the complete composition. Discovery alone does not prove that child actions or parameter contracts work on this adapter."
44
+ "Register a team library with --library team=/path/to/library-root, the directory containing recipes/. Use discovered recipe names in call.ref; the library alias names its source, not a recipe-name prefix. Confirm --describe reports the intended source and platform variant, then plan the complete composition. Discovery alone does not prove that child actions or parameter contracts work on this adapter.",
45
+ {
46
+ "text": "Core actions use isolated controllers: pass account/network into each action instead of adding a no-op initialization node.",
47
+ "adapters": [
48
+ "core"
49
+ ]
50
+ }
33
51
  ],
34
52
  "commands": [
35
53
  "mm-harness actions --json",
36
54
  "mm-harness actions --action app.status --json",
37
- "mm-harness actions --action ui.screenshot --json",
55
+ {
56
+ "text": "mm-harness actions --action ui.screenshot --json",
57
+ "adapters": [
58
+ "mobile",
59
+ "extension"
60
+ ]
61
+ },
38
62
  "mm-harness actions performance --json",
39
63
  "mm-harness run --list --json",
40
64
  "mm-harness run runner.smoke --describe --json"
@@ -50,42 +74,74 @@
50
74
  "CLI values are parsed as JSON when possible. For a numeric-looking string parameter, preserve JSON quotes, for example 'amount=\"15\"'; shell quoting 15 alone still produces a number.",
51
75
  "Do not parameterize away safety, assertions, cleanup, or the meaning of success. Never depend on hidden wallet, account, provider, network, page, port, or device state.",
52
76
  "A clean-market postcondition must check both sides. Keep side-specific open-state proof separate, and inspect the actual cancellation payload: filtering by side before canceling by symbol does not protect opposite-side orders. Map client receipt IDs to exchange IDs when they differ, checking account and market. Never infer ownership from any new order or widen cleanup to fix a failed assertion.",
53
- "Asset symbols and test IDs may repeat across networks. Require an unambiguous observed row, or use a contract that accepts network/token identity; never infer chain, funding or ownership from a symbol alone.",
77
+ {
78
+ "text": "Asset symbols and test IDs may repeat across networks. Require an unambiguous observed row, or use a contract that accepts network/token identity; never infer chain, funding or ownership from a symbol alone.",
79
+ "adapters": [
80
+ "mobile",
81
+ "extension"
82
+ ]
83
+ },
54
84
  "For catalog changes, verify membership and lifecycle flags as well as counts. A smaller list can hide valid delisted entries still needed by callers; distinguish unavailable trading metadata from missing historical identity.",
55
- "Defaults must agree across callers and children. Keep consent and environment-specific values required when no safe default exists; a missing required input is not recipe drift. The current runtime resolves referenced inputs before branching, so an unselected branch does not hide an undefined parameter. Venue-key registration needs explicit account/key-slot ownership too. Pass account and network explicitly to isolated Core actions rather than assuming a preceding node selected them."
85
+ "Defaults must agree across callers and children. Keep consent and environment-specific values required when no safe default exists; a missing required input is not recipe drift. The current runtime resolves referenced inputs before branching, so an unselected branch does not hide an undefined parameter. Venue-key registration needs explicit account/key-slot ownership too."
56
86
  ],
57
- "commands": []
87
+ "commands": [
88
+ "mm-harness run ./proof.recipe.json market=ETH --plan --json"
89
+ ]
58
90
  },
59
91
  {
60
92
  "id": "compose",
61
93
  "title": "Compose a readable graph",
62
94
  "instruction": "Use static call references for unchanged sub-journeys. Separate preparation, action, assertions, and evidence; add workflow.teardown when cleanup must run after success or failure.",
63
95
  "details": [
64
- "Starting conditions are ordinary nodes at the beginning of workflow, not a preconditions field. Use idempotent ensure actions and independently assert their postconditions. Reopening a route may preserve filters or search state; establish the required view explicitly before sampling, and validate composition after a different journey changes it.",
96
+ "Starting conditions are ordinary nodes at the beginning of workflow, not a preconditions field. Use idempotent ensure actions and independently assert their postconditions.",
65
97
  "Inspect existing state before creating or cleaning fixtures. Establish only prerequisites required by the claim; a history or display check may already have usable records and need no trade or cleanup. Record the selected records and verify they still satisfy the proof boundary.",
66
98
  "Match history-query ranges to the dates of existing visible records before declaring fixtures missing. Sample only sections needed for change detection; fetch one-time corroborating history once, and count background calls as well as graph nodes.",
67
99
  "Actions translate UI, CDP, or controller operations. Recipes compose them. Product code owns business rules. Teams own specialized journeys in their libraries; the harness retains shared capabilities and a small set of composable examples.",
68
100
  "Put identical cross-adapter graphs in recipes/shared/<domain>/ and platform variants in recipes/<adapter>/<domain>/. Both keep the same domain.recipe name; an adapter variant takes precedence. Keep platform differences in actions when the journey is identical. Verify discovery, execution, and callers before removing duplicates.",
69
- "Keep lifecycle transitions explicit. Check whether an observation tool activates or foregrounds the app; that behavior can invalidate a lifecycle claim even when the captured screen looks correct.",
70
- "On source-dev Mobile, app.lifecycle launch, foreground, and restart already wait for the selected bridge and route. Use runtime_ready_timeout_ms to bound readiness and require_process_continuity for warm-resume claims. settle_ms is an explicit dwell period, not readiness proof. Unlock before a visual proof if the app protects locked-screen capture; never bypass that protection.",
101
+ {
102
+ "text": "Keep lifecycle transitions explicit. Check whether an observation tool activates or foregrounds the app; that behavior can invalidate a lifecycle claim even when the captured screen looks correct.",
103
+ "adapters": [
104
+ "mobile",
105
+ "extension"
106
+ ]
107
+ },
108
+ {
109
+ "text": "On source-dev Mobile, app.lifecycle launch, foreground, and restart already wait for the selected bridge and route. Use runtime_ready_timeout_ms to bound readiness and require_process_continuity for warm-resume claims. settle_ms is an explicit dwell period, not readiness proof. Unlock before a visual proof if the app protects locked-screen capture; never bypass that protection.",
110
+ "adapters": [
111
+ "mobile"
112
+ ]
113
+ },
71
114
  "Measure executed nodes and elapsed time across nested calls, including setup and teardown. Include action-internal repetitions such as navigation cycles. Splitting a long graph into child files does not reduce work. Reuse a verified prerequisite within its valid scope, branch around already-satisfied setup, and keep broad coverage suites separate from the small journey a task needs.",
72
- "Inspect scripts invoked by command nodes before running them. A read or stream label does not rule out signing, order placement or cleanup. Count the script's operations and verify its actual assertions; callback counts do not establish transport identity. Use a distinct output path for repeated invocations so one phase cannot overwrite another's evidence.",
115
+ "Inspect scripts and controller methods before running them. A read, get or stream label does not rule out signing, order placement or collateral settlement. Apply the normal approvals to those effects. Count actual operations and verify assertions; callback counts do not establish transport identity. Use a distinct output path for repeated invocations so one phase cannot overwrite another's evidence.",
73
116
  "Merge branch endings when their resolved action inputs and assertions are identical. Preserve the scenario identity in parameters; keep distinct endings when required evidence differs. Compare the selected operation sequences before claiming fewer checks or faster execution.",
74
117
  "Use summary.total for executed node count and summary.durationMs for engine duration. Measure CLI wall time separately when assessing speed; preparation and closeout can dominate a short recipe. The trace includes child nodes and their enclosing call; summing both durations double-counts the child work.",
75
118
  "Keep repository builds, unit suites, and release bookkeeping outside reusable runtime journeys. Run them separately when required and report both results; a runtime pass does not imply package acceptance.",
76
- "Main and teardown graphs are disjoint. A cleanup node reached only through next may be skipped on failure. Capture the baseline in a completed read before mutation, guard restoration on that output, and restore only task-owned state. A missing or ambiguous baseline is unknown, not false. A failed mutation may have changed the product without returning output. Teardown cannot guarantee provider acceptance or survive a killed process."
119
+ "Main and teardown graphs are disjoint. A cleanup node reached only through next may be skipped on failure. Capture the baseline before mutation, guard restoration on that output, and restore only task-owned state. A missing or ambiguous baseline is unknown, not false. An interaction can complete after timeout or navigation away; check task-owned pending requests during cleanup. Teardown cannot guarantee provider acceptance or survive a killed process.",
120
+ {
121
+ "text": "Reopening a route may preserve filters or search state; establish the required view explicitly before sampling, and validate composition after a different journey changes it.",
122
+ "adapters": [
123
+ "mobile",
124
+ "extension"
125
+ ]
126
+ }
77
127
  ],
78
128
  "commands": []
79
129
  },
80
130
  {
81
131
  "id": "author",
82
132
  "title": "Build and prove one node at a time",
83
- "instruction": "Probe each unfamiliar action with call or a tiny action-to-end recipe. Use read-only CDP inspection only when declared actions cannot reveal the needed authoring detail, then consolidate the final proof from manifest-declared actions.",
133
+ "instruction": "Probe each unfamiliar action with call or a tiny action-to-end recipe. Use read-only inspection only when declared actions cannot reveal the needed authoring detail, then consolidate the final proof from manifest-declared actions.",
84
134
  "details": [
85
135
  "Plan after every structural change and preserve the first failing trace.",
86
136
  "A plan validates structure only. Probe a reused setup boundary against the current build with a short explicit timeout before a full journey; a bundled journey timeout is not a discovery budget.",
87
137
  "A later update cannot repair a failed initial-seed assertion. Preserve the initial sample and stop that wait instead of spending the remaining budget on a proof that cannot pass.",
88
- "A CDP observation can help find the current route or selector; it is not final evidence unless the recipe records an allowed action and assertion for that signal."
138
+ {
139
+ "text": "A CDP observation can help find the current route or selector; it is not final evidence unless the recipe records an allowed action and assertion for that signal.",
140
+ "adapters": [
141
+ "mobile",
142
+ "extension"
143
+ ]
144
+ }
89
145
  ],
90
146
  "commands": [
91
147
  "mm-harness call app.status --json",
@@ -101,7 +157,9 @@
101
157
  "Use either next or cases with default. call always uses next and a static ref; only call.params passes child inputs, and child output stays scoped under the call node.",
102
158
  "Graphs are acyclic. Put bounded polling inside actions, not backward edges. Each success path must prove its promised outcome. end.status supports pass, fail, or unknown; an unknown result is not proof of success."
103
159
  ],
104
- "commands": ["mm-harness actions --action switch --json"]
160
+ "commands": [
161
+ "mm-harness actions --action switch --json"
162
+ ]
105
163
  },
106
164
  {
107
165
  "id": "quality",
@@ -114,14 +172,39 @@
114
172
  "Graph: no unconditional pass, generic intent, hidden start state, or opaque node that collapses preparation, action, assertion, evidence, and teardown.",
115
173
  "Assertion modes such as require_unchanged must fail before any corrective action. Verify the negative path leaves the inspected state untouched; an assertion must not repair the behavior it is supposed to test.",
116
174
  "Reuse structured reads with assert_output instead of adding a new domain action for every comparison: source names the earlier node, and assert can select $.matchingCount with operator eq and the expected parameter. A status-report action can succeed while reporting missing prerequisites; assert required values before the dependent action. Checking three rows exist does not prove there are exactly three, or that they belong to this task.",
117
- "Evidence: inspect the recipe resolution, summary, trace, manifest, logs, and actual visual evidence. A filename or passing node is not visual proof. A container's presence does not prove its data loaded; tab content does not prove its selection indicator. Verify the values and visible state required by the claim.",
175
+ "Evidence: inspect the recipe resolution, summary, trace, manifest, logs, and actual artifacts. Verify the values and state required by the claim.",
118
176
  "For a change claim, compare the actual before/after values for the same subject. Two captures alone prove neither an update nor freshness. Preserve unchanged observations as unproven rather than retrying to obtain a pass.",
119
- "Match capture to the claim. Extension ui.capture_surface records the browser document through Chrome, including below-viewport document content but not hidden nested-scroll contents or native dialogs. Keep viewport assertions separate, inspect every image, and preserve failed captures rather than reconstructing them from HTML.",
120
- "Screenshots: establish the claimed state, capture it, and inspect the original file. If a displayed preview looks incomplete, verify stored pixels or local OCR before reporting a capture defect or changing code. Preserve genuine failed captures. Performance: define a measured window, exclude setup, and compare equivalent builds, devices, and lifecycle conditions; action duration alone is not app latency.",
177
+ {
178
+ "text": "Match capture to the claim. Extension ui.capture_surface records the browser document through Chrome, including below-viewport document content but not hidden nested-scroll contents or native dialogs. Keep viewport assertions separate, inspect every image, and preserve failed captures rather than reconstructing them from HTML.",
179
+ "adapters": [
180
+ "extension"
181
+ ]
182
+ },
183
+ {
184
+ "text": "Screenshots: establish the claimed state, capture it, and inspect the original file. If a displayed preview looks incomplete, verify stored pixels or local OCR before reporting a capture defect or changing code. Preserve genuine failed captures.",
185
+ "adapters": [
186
+ "mobile",
187
+ "extension"
188
+ ]
189
+ },
190
+ "Performance: define a measured window, exclude setup, and compare equivalent builds, devices, and lifecycle conditions; action duration alone is not app latency.",
121
191
  "Retain samples and declared limits when a measurement fails. For memory growth, compare an equal-duration idle control before attributing it to navigation; do not raise the budget to make the run pass.",
122
192
  "Analytics: verify the collection destination and existing consent before capture. Changing participation or marketing consent requires operator approval and restoration of the prior settings; a recipe's hardcoded opt-in is not permission. Missing collection prerequisites are not missing product events.",
123
193
  "Flake risk: wait on observable state instead of sleeping, keep device and runtime identity explicit, and never overwrite a prior run's artifacts.",
124
- "Mutation: require an independent state assertion and identity-bound receipt. Schedule authorized cleanup in teardown, verify its result, and report any residue. Testnet cleanup must not cancel another task's orders or close its positions."
194
+ "Mutation: require an independent state assertion and identity-bound receipt. Bind activity to that operation's accepted ID; an old row or nonzero count is insufficient. Opening and closing orders have different IDs. Schedule authorized cleanup in teardown, verify its result, and report any residue. Testnet cleanup must not cancel another task's orders or close its positions.",
195
+ {
196
+ "text": "An accepted order can fill before the UI updates. Preserve its receipt even when the expected resting-order assertion fails; one empty read does not prove cleanup. Check the read API's cache and freshness options before adding polling. Reconcile returned margin against the pre-placement balance. A successful close does not turn the original failed proof into a pass.",
197
+ "adapters": [
198
+ "extension"
199
+ ]
200
+ },
201
+ {
202
+ "text": "A filename or passing node is not visual proof. A container's presence does not prove its data loaded; tab content does not prove its selection indicator. Inspect the captured image and the values it needs to show.",
203
+ "adapters": [
204
+ "mobile",
205
+ "extension"
206
+ ]
207
+ }
125
208
  ],
126
209
  "commands": [
127
210
  "mm-harness run ./proof.recipe.json --artifacts-dir temp/recipe-proof --json",
@@ -135,22 +218,92 @@
135
218
  "instruction": "Treat saved recipes as starting points, not compatibility guarantees. A failure starts diagnosis, not an automatic task stop. Preserve it, compare the current app with the task's acceptance criteria, and distinguish recipe drift from a product, harness, fixture, or live-dependency failure before repairing anything.",
136
219
  "details": [
137
220
  "The graph and evidence contract can be deterministic while the product, provider, account, or network outcome is not. Honest external rejection remains a valid result, not a reason to seek a green retry.",
138
- "Trace the first failure through the exact action source and test the smallest causal explanation before filing or fixing a harness issue. Verify the visible screen as well as the route name; an old route identifier may now open a different screen. If a proposed fix outgrows the confirmed cause, preserve it separately and return to the minimal fix.",
139
- "For blocked runtime proof, retain the target identity, build/app state, and first failing command and error. Reconcile later status snapshots with that evidence; they cannot establish that an earlier device was absent. Cold XCTest infrastructure belongs in explicit setup: consult agent-device help prepare using the same package, device and state directory. A preparation health check does not prove native snapshot or interaction latency.",
140
- "A failed device-discovery probe is unknown availability, not proof that a simulator stopped. Inspect deviceDiscoveryErrors or DEVICE_DISCOVERY_FAILED and run its Next command before changing targets or restarting a runtime.",
141
- "An RPC failure is not necessarily a credential or network failure. Distinguish an HTTP rejection from JavaScript execution errors and circuit-breaker cooldowns. Check build capabilities separately from remote rollout flags; do not reset a wallet to repair an unclassified failure.",
142
- "For LavaMoat execution errors, inspect the effective bundled policy as well as the calling code. A nested method grant can change receiver binding. Reproduce the mechanism in isolation, then validate the owning product correction with LavaMoat still enabled; never replace fetch in the live worker to manufacture proof.",
143
- "Use LaunchDarkly for feature rollout. Do not add local flag overrides to unblock validation. Match compile-time capabilities to the intended product build; if its remote rollout excludes the feature, report that prerequisite or request targeting from its owner.",
144
- "For confirmed product-version drift, copy the closest recipe into the task and retain its working nodes. Adapt only the stale selector, route, input contract, or setup condition against current source and observed UI. Keep the task's acceptance criteria; do not rebuild a working journey or relax its proof to obtain a pass.",
145
- "Inspect selection before toggling; skip already-satisfied setup. Visibility and a matching locator do not prove click readiness: a menu can move between press and release. Require an uncovered, stable target within the action budget, click once, then assert the result. If it fails, inspect the actual pointer target before changing locators. No fixed sleeps or repeated clicks.",
146
- "Use test values distinct from the product's defaults so resets are observable. If an intentional transition reseeds a form, assert its documented reset contract using a recorded baseline; do not claim preservation because the chosen value happened to equal the default.",
147
- "A loaded form shell is not a settled quote. Recheck every required preview condition after polling expires; stopping the wait must never turn missing fields into success. Verify this with a real unavailable-preview case and retain the failure.",
148
- "After changing quote inputs, bind the returned quote to those inputs. A debounced request may leave the previous positive output and enabled CTA visible briefly; neither proves the new quote is ready. Inspect the capture too, and preserve stale/loading evidence instead of refreshing invisibly.",
149
- "Native trees may include controls covered by developer or system overlays. Verify the screenshot before changing a selector; move or dismiss an overlay only as explicit setup and restore it afterward. Gesture path and delta values are offsets from the resolved start, not absolute endpoints; inspect the resolved coordinates and assert the resulting state.",
221
+ "Trace the first failure through the exact action source and test the smallest causal explanation before filing or fixing a harness issue. Check the product runtime too: security shims can change standard JavaScript behavior. Compute expectations independently from the verified contract, not host defaults. If a proposed fix outgrows the confirmed cause, preserve it separately and return to the minimal fix.",
222
+ "For blocked runtime proof, retain the target identity, build/app state, and first failing command and error. Reconcile later status snapshots with that evidence; they cannot establish the earlier runtime state.",
223
+ {
224
+ "text": "A failed discovery probe or native snapshot does not establish a stopped app or unsupported platform. Name the failing observation path. Inspect deviceDiscoveryErrors or DEVICE_DISCOVERY_FAILED and its Next command before restarting. Another supported observer must preserve the required visible identity, selection and ordering assertions.",
225
+ "adapters": [
226
+ "mobile"
227
+ ]
228
+ },
229
+ "An RPC failure is not necessarily a credential or network failure. Distinguish HTTP rejection, JavaScript errors and circuit-breaker cooldowns.",
230
+ {
231
+ "text": "If Chrome blocks an unpacked extension with ERR_BLOCKED_BY_CLIENT, inspect its status in that slot's chrome://extensions page before retrying app readiness. unsupportedDeveloperExtension can mean Developer mode is off. Use normal setup controls in the isolated QA profile; do not disable browser security, bypass policy, reset the wallet or treat a blocked page as a product failure.",
232
+ "adapters": [
233
+ "extension"
234
+ ]
235
+ },
236
+ {
237
+ "text": "For LavaMoat execution errors, inspect the effective bundled policy as well as the calling code. A nested method grant can change receiver binding. Reproduce the mechanism in isolation, then validate the owning product correction with LavaMoat still enabled; never replace fetch in the live worker to manufacture proof.",
238
+ "adapters": [
239
+ "extension"
240
+ ]
241
+ },
242
+ {
243
+ "text": "Use LaunchDarkly for feature rollout. Do not add local flag overrides to unblock validation. Match compile-time capabilities to the intended product build; if its remote rollout excludes the feature, report that prerequisite or request targeting from its owner.",
244
+ "adapters": [
245
+ "mobile",
246
+ "extension"
247
+ ]
248
+ },
249
+ "For confirmed product-version drift, copy the closest recipe into the task and retain its working nodes. Adapt only the stale contract or setup condition against current source and observed behavior. Keep the task's acceptance criteria; do not rebuild a working journey or relax its proof to obtain a pass.",
250
+ {
251
+ "text": "Inspect selection before toggling; skip already-satisfied setup. Visibility and a matching locator do not prove click readiness: a menu can move between press and release. Require an uncovered, stable target within the action budget, click once, then assert the result. If it fails, inspect the actual pointer target before changing locators. No fixed sleeps or repeated clicks.",
252
+ "adapters": [
253
+ "mobile",
254
+ "extension"
255
+ ]
256
+ },
257
+ {
258
+ "text": "Use test values distinct from the product's defaults so resets are observable. If an intentional transition reseeds a form, assert its documented reset contract using a recorded baseline; do not claim preservation because the chosen value happened to equal the default.",
259
+ "adapters": [
260
+ "mobile",
261
+ "extension"
262
+ ]
263
+ },
264
+ {
265
+ "text": "A loaded form shell is not a settled quote. Recheck every required preview condition after polling expires; stopping the wait must never turn missing fields into success. Verify this with a real unavailable-preview case and retain the failure.",
266
+ "adapters": [
267
+ "mobile",
268
+ "extension"
269
+ ]
270
+ },
271
+ {
272
+ "text": "After changing quote inputs, bind the returned quote to those inputs. A debounced request may leave the previous positive output and enabled CTA visible briefly; neither proves the new quote is ready. Inspect the capture too, and preserve stale/loading evidence instead of refreshing invisibly.",
273
+ "adapters": [
274
+ "mobile",
275
+ "extension"
276
+ ]
277
+ },
278
+ {
279
+ "text": "Native trees may include controls covered by developer or system overlays. Verify the screenshot before changing a selector; move or dismiss an overlay only as explicit setup and restore it afterward. Gesture path and delta values are offsets from the resolved start, not absolute endpoints; inspect the resolved coordinates and assert the resulting state.",
280
+ "adapters": [
281
+ "mobile"
282
+ ]
283
+ },
150
284
  "Reconcile any earlier side effects before repeating a step; an unknown order or transaction outcome must not be resubmitted. Probe the repaired node with call or a small recipe, re-plan, then validate the full task-local recipe and affected callers. Continue the task when the repaired path is proven; report a blocker only when no supported, authorized path remains.",
151
285
  "Record the source recipe digest, tested product identity, repair, and fresh evidence. If the defect belongs to reusable harness code or bundled vocabulary, prepare a focused experimental-metamask-harness issue and open it when authorized. Put verified authoring lessons in version-matched harness help; keep task-specific evidence in the task and skills as thin workflow wrappers.",
152
286
  "Promote a repair only after it works on the tested version and current main, or declare and enforce its compatibility boundary.",
153
- "Authoring guide: https://farmslot.io/docs/guides/write-a-recipe/ ; canonical field and graph contract: https://farmslot.io/docs/reference/recipe-protocol-v1/"
287
+ "Authoring guide: https://farmslot.io/docs/guides/write-a-recipe/ ; canonical field and graph contract: https://farmslot.io/docs/reference/recipe-protocol-v1/",
288
+ {
289
+ "text": "Verify the visible screen as well as the route name; an old route identifier may now open a different screen.",
290
+ "adapters": [
291
+ "mobile",
292
+ "extension"
293
+ ]
294
+ },
295
+ {
296
+ "text": "Cold XCTest infrastructure belongs in explicit setup: consult agent-device help prepare using the same package, device and state directory. A preparation health check does not prove native snapshot or interaction latency.",
297
+ "adapters": [
298
+ "mobile"
299
+ ]
300
+ },
301
+ {
302
+ "text": "Successful RPC does not prove asset discovery: for empty balances, inspect the active asset controllers and compare compiled capabilities with remote rollout flags. Harness or skills updates do not synchronize slot build fixtures; correct stale build settings at their source and rebuild explicitly without resetting the wallet.",
303
+ "adapters": [
304
+ "extension"
305
+ ]
306
+ }
154
307
  ],
155
308
  "commands": []
156
309
  }