@deeeed/metamask-harness 0.78.0 → 0.80.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 (215) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +1 -1
  3. package/adapters/extension/ensure-browser.sh +2 -2
  4. package/adapters/extension/inject.mjs +0 -1
  5. package/adapters/extension/launch-browser.cjs +39 -613
  6. package/adapters/extension/readiness.mjs +2 -5
  7. package/adapters/extension/reattach.sh +2 -2
  8. package/adapters/extension/stamp-runtime-title.cjs +1 -1
  9. package/adapters/manifest.json +2 -34
  10. package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +57 -1358
  11. package/adapters/mobile/bridge-runtime/teaching.cjs +20 -0
  12. package/adapters/mobile/inject.sh +16 -0
  13. package/adapters/mobile/launch-console-forwarder.cjs +1 -2
  14. package/adapters/mobile/open-device.sh +2 -2
  15. package/adapters/mobile/reload-app.mjs +4 -4
  16. package/adapters/mobile/reset-app-data.sh +1 -1
  17. package/adapters/mobile/start-console-forwarder.sh +3 -2
  18. package/adapters/mobile/start-metro.sh +17 -12
  19. package/adapters/mobile/wait-for-bridge.cjs +2 -2
  20. package/adapters/shared/ensure-runner-deps.sh +2 -2
  21. package/adapters/shared/harness-source-fingerprint.mjs +13 -8
  22. package/adapters/shared/open-debug.mjs +2 -2
  23. package/adapters/shared/runner-deps-ready.mjs +1 -1
  24. package/adapters/shared/sync-wallet-fixture.sh +8 -5
  25. package/adapters/terminal/cleanup.mjs +2 -1
  26. package/adapters/terminal/inject.mjs +2 -1
  27. package/adapters/terminal/lib/cdp-client.mjs +1 -1
  28. package/bin/mm-harness +9 -28
  29. package/dist/adapters/checkout-files.js +16 -0
  30. package/dist/adapters/console-capture.js +14 -1
  31. package/dist/adapters/core/actions.js +4 -3
  32. package/dist/adapters/core/overlay.js +1 -1
  33. package/dist/adapters/core/readiness.js +28 -1
  34. package/dist/adapters/core/run.js +3 -3
  35. package/dist/adapters/core/surface.js +22 -5
  36. package/dist/adapters/extension/browser-pid.js +56 -0
  37. package/dist/adapters/extension/console-capture.js +1 -1
  38. package/dist/adapters/extension/doctor-checks.js +1 -1
  39. package/dist/adapters/extension/ensure-ready.js +5 -4
  40. package/dist/adapters/extension/extension-id.js +1 -1
  41. package/dist/adapters/extension/feature-flags.js +1 -1
  42. package/dist/adapters/extension/fixtures.js +1 -2
  43. package/dist/adapters/extension/launch.js +4 -5
  44. package/dist/adapters/extension/launched-browser.js +1 -2
  45. package/dist/adapters/extension/network-observer.js +1 -1
  46. package/dist/adapters/extension/overlay.js +1 -1
  47. package/dist/adapters/extension/product-config.js +1 -1
  48. package/dist/adapters/extension/readiness.js +1 -1
  49. package/dist/adapters/extension/reload.js +1 -1
  50. package/dist/adapters/extension/run.js +24 -10
  51. package/dist/adapters/extension/runtime-decision.js +3 -2
  52. package/dist/adapters/extension/runtime.js +9 -5
  53. package/dist/adapters/extension/surface.js +20 -5
  54. package/dist/adapters/extension/verify.js +2 -2
  55. package/dist/adapters/harness-freshness.js +2 -1
  56. package/dist/adapters/mobile/android-gfxinfo-performance.js +1 -3
  57. package/dist/adapters/mobile/app-identity.js +10 -0
  58. package/dist/adapters/mobile/doctor-checks.js +1 -1
  59. package/dist/adapters/mobile/fixtures.js +1 -1
  60. package/dist/adapters/mobile/launch.js +27 -28
  61. package/dist/adapters/mobile/lifecycle.js +1 -1
  62. package/dist/adapters/mobile/metro-env.js +9 -59
  63. package/dist/adapters/mobile/performance-observer.js +1 -1
  64. package/dist/adapters/mobile/prepare-target.js +1 -1
  65. package/dist/adapters/mobile/prepare.js +4 -5
  66. package/dist/adapters/mobile/provision.js +1 -1
  67. package/dist/adapters/mobile/readiness.js +1 -1
  68. package/dist/adapters/mobile/recording-target.js +15 -0
  69. package/dist/adapters/mobile/release-artifact-state.js +1 -1
  70. package/dist/adapters/mobile/reload.js +1 -1
  71. package/dist/adapters/mobile/run.js +9 -8
  72. package/dist/adapters/mobile/runtime-decision.js +5 -7
  73. package/dist/adapters/mobile/source-freshness.js +22 -126
  74. package/dist/adapters/mobile/surface.js +31 -6
  75. package/dist/adapters/mobile/ui.js +16 -5
  76. package/dist/adapters/mobile/verify.js +2 -3
  77. package/dist/adapters/performance/cdp-trace.js +1 -1
  78. package/dist/adapters/performance/device-platform.js +1 -1
  79. package/dist/adapters/registry.js +2 -14
  80. package/dist/adapters/slot-ports.js +1 -1
  81. package/dist/adapters/surface.js +1 -0
  82. package/dist/adapters/terminal/console-capture.js +1 -1
  83. package/dist/adapters/terminal/launch.js +1 -1
  84. package/dist/adapters/terminal/run.js +25 -2
  85. package/dist/adapters/terminal/surface.js +12 -4
  86. package/dist/adapters.js +8 -4
  87. package/dist/advisor-policy.js +1 -1
  88. package/dist/checkout-view.js +1 -2
  89. package/dist/cli.js +28 -15
  90. package/dist/command-contract.js +1 -26
  91. package/dist/commands/call.js +10 -24
  92. package/dist/commands/check.js +3 -4
  93. package/dist/commands/checklist.js +1 -1
  94. package/dist/commands/completion-candidates.js +2 -10
  95. package/dist/commands/config.js +2 -2
  96. package/dist/commands/core-readiness.js +12 -7
  97. package/dist/commands/debug.js +3 -3
  98. package/dist/commands/device-target.js +5 -5
  99. package/dist/commands/doctor.js +2 -14
  100. package/dist/commands/domain.js +2 -2
  101. package/dist/commands/ensure-ready.js +1 -7
  102. package/dist/commands/fixtures.js +5 -6
  103. package/dist/commands/help.js +3 -4
  104. package/dist/commands/launch/device.js +10 -17
  105. package/dist/commands/launch/extension.js +3 -9
  106. package/dist/commands/launch/mobile.js +1 -1
  107. package/dist/commands/list-executables.js +1 -3
  108. package/dist/commands/logs.js +3 -3
  109. package/dist/commands/manifest.js +1 -12
  110. package/dist/commands/mobile-device-view.js +4 -2
  111. package/dist/commands/overlay.js +110 -0
  112. package/dist/commands/pin.js +1 -1
  113. package/dist/commands/pr-body.js +2 -2
  114. package/dist/commands/prepare.js +6 -11
  115. package/dist/commands/provision.js +3 -12
  116. package/dist/commands/recipe-advice.js +1 -2
  117. package/dist/commands/recipe-quality.js +2 -3
  118. package/dist/commands/resolve-extension.js +1 -7
  119. package/dist/commands/review.js +4 -4
  120. package/dist/commands/run-engine.js +12 -51
  121. package/dist/commands/run.js +4 -25
  122. package/dist/commands/runtime-decision.js +1 -6
  123. package/dist/commands/runtime-health.js +1 -7
  124. package/dist/commands/runtime-launch.js +1 -13
  125. package/dist/commands/self-test.js +2 -6
  126. package/dist/commands/status-watch.js +1 -2
  127. package/dist/commands/status.js +2 -5
  128. package/dist/commands/task-init.js +2 -3
  129. package/dist/commands/tutorial.js +2 -2
  130. package/dist/commands/update.js +1 -1
  131. package/dist/completions-cache.js +1 -1
  132. package/dist/console-classifier.js +19 -0
  133. package/dist/discovery.js +1 -1
  134. package/dist/doctor.js +3 -4
  135. package/dist/funding-execution-context.js +15 -1
  136. package/dist/host.js +32 -0
  137. package/dist/index.js +1 -6
  138. package/dist/live-tsx.js +49 -0
  139. package/dist/mm-harness-cli.js +2 -4
  140. package/dist/network-observation.js +4 -4
  141. package/dist/paths.js +48 -78
  142. package/dist/performance-observation.js +2 -2
  143. package/dist/progress.js +1 -1
  144. package/dist/recipe-assistance-context.js +2 -4
  145. package/dist/recipe-security.js +2 -59
  146. package/dist/review/knowledge.js +3 -3
  147. package/dist/runner.js +5 -3
  148. package/dist/runtime-context.js +1 -1
  149. package/dist/task-view.js +3 -4
  150. package/docs/CONTRIBUTING.md +3 -3
  151. package/docs/cli-contract.md +2 -2
  152. package/docs/feature-guard.md +90 -0
  153. package/library/README.md +3 -1
  154. package/library/actions/core/perps/_controller.mjs +153 -130
  155. package/library/actions/core/perps/quote_fees.mjs +58 -0
  156. package/library/actions/core/wallet/_fixture-accounts.mjs +69 -0
  157. package/library/actions/core/wallet/list_accounts.mjs +14 -57
  158. package/library/actions/extension/feature_flags/state.mjs +1 -1
  159. package/library/actions/extension/platform/cdp.mjs +2 -8
  160. package/library/actions/harness-exports.mjs +1 -6
  161. package/library/actions/mobile/app/network-control.mjs +6 -8
  162. package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +1 -1
  163. package/library/actions/mobile/platform/bridge.mjs +8 -8
  164. package/library/actions/mobile/platform/native-session-name.mjs +21 -1
  165. package/library/actions/mobile/platform/native-session.mjs +3 -4
  166. package/library/actions/mobile/platform/observe-ui.mjs +12 -6
  167. package/library/actions/mobile/ui/native-navigation.mjs +4 -3
  168. package/library/actions/mobile/wallet/native-ui.mjs +3 -2
  169. package/library/actions/shared/analytics/_adapter.mjs +1 -1
  170. package/library/actions/shared/console-findings.mjs +1 -1
  171. package/library/actions/terminal/platform/runtime.mjs +2 -1
  172. package/library/manifests/core.action-manifest.json +83 -13
  173. package/package.json +8 -8
  174. package/adapters/extension/lib/slot-title.cjs +0 -292
  175. package/adapters/mobile/bridge-runtime/console-forwarder.cjs +0 -472
  176. package/adapters/mobile/bridge-runtime/lib/bridge-errors.cjs +0 -125
  177. package/adapters/mobile/bridge-runtime/lib/cdp-broker.cjs +0 -1055
  178. package/adapters/mobile/bridge-runtime/lib/cdp-eval.cjs +0 -110
  179. package/adapters/mobile/bridge-runtime/lib/config.cjs +0 -61
  180. package/adapters/mobile/bridge-runtime/lib/console-format.cjs +0 -53
  181. package/adapters/mobile/bridge-runtime/lib/devtools-proxy.cjs +0 -177
  182. package/adapters/mobile/bridge-runtime/lib/issue-capture.cjs +0 -446
  183. package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +0 -84
  184. package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +0 -403
  185. package/adapters/mobile/bridge-runtime/lib/ws-client.cjs +0 -116
  186. package/adapters/mobile/coalesce-metro-log.cjs +0 -24
  187. package/adapters/mobile/launch-metro.cjs +0 -77
  188. package/adapters/mobile/metro-config.cjs +0 -98
  189. package/adapters/mobile/metro-log-generation.cjs +0 -106
  190. package/dist/adapters/mobile/frame-metrics.js +0 -118
  191. package/dist/adapters/mobile/video-recorder.js +0 -289
  192. package/dist/artifact-files.js +0 -92
  193. package/dist/checkout-lock.js +0 -149
  194. package/dist/cli-color.js +0 -98
  195. package/dist/command-journal.js +0 -308
  196. package/dist/commands/last.js +0 -60
  197. package/dist/commands/launch/index.js +0 -109
  198. package/dist/commands/parse-args.js +0 -279
  199. package/dist/commands/reload.js +0 -41
  200. package/dist/commands/run-report.js +0 -241
  201. package/dist/commands/shared.js +0 -323
  202. package/dist/commands/stop.js +0 -60
  203. package/dist/devices.js +0 -100
  204. package/dist/execution-provenance.js +0 -332
  205. package/dist/harness.js +0 -451
  206. package/dist/heal-bounds.js +0 -137
  207. package/dist/json-stream.js +0 -60
  208. package/dist/leaf-invoke.js +0 -19
  209. package/dist/library-provenance.js +0 -33
  210. package/dist/live-adapter-contract.js +0 -380
  211. package/dist/recording-target.js +0 -120
  212. package/dist/run-diagnostics.js +0 -364
  213. package/dist/run-recording.js +0 -481
  214. package/dist/runtime-proof.js +0 -90
  215. package/library/actions/mobile/platform/tool-paths.mjs +0 -123
@@ -2,59 +2,23 @@ import fs from "node:fs";
2
2
  import { mkdtemp } from "node:fs/promises";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
- import { validateRuntimeProofPlan } from "../runtime-proof.js";
6
- import {
7
- ensureOverlay,
8
- newHealState,
9
- parseHeal,
10
- recipeRunning,
11
- checkHealBounds,
12
- conciseFailureForHuman
13
- } from "../heal-bounds.js";
14
5
  import { resolveActionManifest, validateManifest } from "../manifest.js";
15
6
  import { getAdapterSurface } from "../adapters/surface.js";
16
7
  import { extensionProductConfigBlock } from "../adapters/extension/product-config.js";
17
- import {
18
- importRecipeHarness,
19
- importRecipeProtocol,
20
- runnerDir,
21
- recipeRuntimePath
22
- } from "../paths.js";
23
- import { captureHelperSupportsRecordSessionSnapshots } from "../recording-target.js";
24
- import { startRecipeRecording, stopRecipeRecording } from "../run-recording.js";
8
+ import { importRecipeHarness, importRecipeProtocol, runnerDir } from "../paths.js";
25
9
  import {
26
10
  resolveMetaMaskParameterValue,
27
11
  validateMetaMaskActionInputs
28
12
  } from "../metamask-action-validation.js";
29
- import { gitLibraryProvenance } from "../library-provenance.js";
13
+ import { beginRunDiagnostics, captureExecutionProvenance, captureHelperSupportsRecordSessionSnapshots, executedBrowser, executionProvenanceDrift, finishRunDiagnostics, ProvenanceDriftError, recipeCdpPorts, recipeEnvName, startRecipeRecording, stopRecipeRecording, validateRuntimeProofPlan, writeExecutionProvenance, gitLibraryProvenance, recipeRuntimePath, ensureOverlay, newHealState, parseHeal, recipeRunning, checkHealBounds, conciseFailureForHuman, EXIT, actionManifestPathOption, optionString, optionFlag, optionStrings, isRecord, shellQuoteArg, targetPath, usageError } from "@farmslot/recipe-cli/harness";
30
14
  import { runnableLibraryRecipes } from "../discovery.js";
31
15
  import { recipeComposition } from "@farmslot/recipe-cli";
32
- import {
33
- captureExecutionProvenance,
34
- executionProvenanceDrift,
35
- ProvenanceDriftError,
36
- writeExecutionProvenance
37
- } from "../execution-provenance.js";
16
+ import { consoleClassifier } from "../console-classifier.js";
38
17
  import {
39
18
  authorizeTrustedMutationPlan,
40
19
  loadTrustedMutationBase
41
20
  } from "../funding-execution-context.js";
42
- import {
43
- beginRunDiagnostics,
44
- finishRunDiagnostics
45
- } from "../run-diagnostics.js";
46
- import { executedBrowser, recipeCdpPorts } from "./run-report.js";
47
- import { EXIT } from "./shared.js";
48
- import {
49
- actionManifestPathOption,
50
- optionString,
51
- optionFlag,
52
- optionStrings,
53
- isRecord,
54
- shellQuoteArg,
55
- targetPath,
56
- usageError
57
- } from "./parse-args.js";
21
+ const RUNNER_INCLUDES = ["src", "adapters", "library", "bin", "dist", "package.json"];
58
22
  async function runRecipe(adapter, recipe, artifactsDir, projectRoot, actionManifestPath, runtimeOptions = {}, preflightedExecution, effectsState = newHealState()) {
59
23
  const restoreRuntimeEnvironment = activateRecipeRuntimeEnvironment(
60
24
  adapter,
@@ -144,7 +108,7 @@ async function runRecipe(adapter, recipe, artifactsDir, projectRoot, actionManif
144
108
  if (executionError !== void 0) throw executionError;
145
109
  if (recordingError !== void 0) throw recordingError;
146
110
  if (!result) throw new Error("Recipe execution returned no result.");
147
- const finalized = await finishRunDiagnostics(diagnosticBaseline, result);
111
+ const finalized = await finishRunDiagnostics(diagnosticBaseline, result, consoleClassifier);
148
112
  persistRunEffects(
149
113
  finalized.summaryPath,
150
114
  finalized.artifactManifestPath,
@@ -219,7 +183,7 @@ async function resolveRecipeExecution(adapter, recipe, artifactsDir, projectRoot
219
183
  adapter,
220
184
  actionManifestPath,
221
185
  librarySources,
222
- process.env.METAMASK_RECIPE_LIVE_ADAPTER_DIR
186
+ process.env[recipeEnvName("LIVE_ADAPTER_DIR")]
223
187
  );
224
188
  const { createMetaMaskRunner } = await import("../runner.js");
225
189
  const recipeDocument = runtimeRecipeDocument(recipe, absoluteRecipePath);
@@ -258,7 +222,7 @@ async function resolveRecipeExecution(adapter, recipe, artifactsDir, projectRoot
258
222
  env: {
259
223
  ...recipeProcessEnvironment(),
260
224
  ...recipeRunEnv(adapter, runtimeOptions),
261
- METAMASK_RECIPE_ACTION_SOURCE_MAP: actionSourceMap(actionSources)
225
+ [recipeEnvName("ACTION_SOURCE_MAP")]: actionSourceMap(actionSources)
262
226
  },
263
227
  recordVideo: useFramedExtensionRecording ? false : recordVideo,
264
228
  ...trust,
@@ -285,7 +249,8 @@ async function resolveRecipeExecution(adapter, recipe, artifactsDir, projectRoot
285
249
  recipeRuntimePath(projectRoot, "operations"),
286
250
  recipeRuntimePath(projectRoot, "lock-members")
287
251
  ],
288
- helperPaths: commandHelperPaths(recipeDocument ?? recipe, projectRoot)
252
+ helperPaths: commandHelperPaths(recipeDocument ?? recipe, projectRoot),
253
+ runnerIncludes: RUNNER_INCLUDES
289
254
  };
290
255
  const startProvenance = await captureExecutionProvenance(
291
256
  provenanceInput,
@@ -444,8 +409,7 @@ const RUN_ENV_KEYS = [
444
409
  "CDP_PORT",
445
410
  "RECIPE_CDP_PORT",
446
411
  "WATCHER_PORT",
447
- "METRO_PORT",
448
- "METAMASK_RECIPE_EXTENSION_AUTOLAUNCH"
412
+ "METRO_PORT"
449
413
  ];
450
414
  function activateRecipeRuntimeEnvironment(adapter, projectRoot, runtimeOptions) {
451
415
  const surface = getAdapterSurface(adapter);
@@ -467,10 +431,7 @@ function activateRecipeRuntimeEnvironment(adapter, projectRoot, runtimeOptions)
467
431
  process.env.WATCHER_PORT = runtimeOptions.watcherPort;
468
432
  process.env.METRO_PORT = runtimeOptions.watcherPort;
469
433
  }
470
- if (runtimeOptions.launchExistingDist) {
471
- process.env.METAMASK_RECIPE_EXTENSION_AUTOLAUNCH = "1";
472
- }
473
- surface.run?.activateEnv?.(projectRoot);
434
+ surface.run?.activateEnv?.(projectRoot, runtimeOptions);
474
435
  return () => {
475
436
  for (const [key, value] of Object.entries(previousEnv)) restoreEnv(key, value);
476
437
  };
@@ -493,7 +454,7 @@ function recipeRunEnv(adapter, runtimeOptions = {}) {
493
454
  FARMSLOT_SLOT_ID: runtimeOptions.slot ?? process.env.FARMSLOT_SLOT_ID,
494
455
  SLOT_ID: runtimeOptions.slot ?? process.env.SLOT_ID,
495
456
  PLATFORM: process.env.PLATFORM,
496
- MM_HARNESS_EXPLICIT_PLATFORM: process.env.MM_HARNESS_EXPLICIT_PLATFORM
457
+ RECIPE_RN_EXPLICIT_PLATFORM: process.env.RECIPE_RN_EXPLICIT_PLATFORM
497
458
  };
498
459
  const childEnv = getAdapterSurface(adapter).run?.childEnv;
499
460
  return childEnv ? childEnv(base) : base;
@@ -1,20 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { importRecipeHarness, walletFixturePath } from "../paths.js";
4
- import { color } from "../cli-color.js";
5
- import { recipeRunning } from "../heal-bounds.js";
6
- import { checkoutBusyOut, EXIT, usageOut, writeInteractiveProgress } from "./shared.js";
7
- import {
8
- optionFlag,
9
- optionString,
10
- resolveAdapter,
11
- runtimeOptionsFromCli,
12
- isRecord,
13
- parseRecipeParamAssignments,
14
- shellQuote,
15
- targetPath,
16
- usageError
17
- } from "./parse-args.js";
4
+ import { formatRunDiagnosticsForHuman, indexProductProvenanceArtifact, ProvenanceDriftError, readRunDiagnosticsDocument, recipeRunOptionsFromCli, recipeTrustFailure, writeRunReport, color, acquireCheckoutLock, JsonStreamWriter, recordCommandEvidence, recipeRunning, checkoutBusyOut, EXIT, usageOut, writeInteractiveProgress, optionFlag, optionString, resolveAdapter, isRecord, parseRecipeParamAssignments, shellQuote, targetPath, usageError } from "@farmslot/recipe-cli/harness";
18
5
  import {
19
6
  countRecipeNodes,
20
7
  emitHealViolation,
@@ -28,16 +15,7 @@ import {
28
15
  import { handleDescribeRecipe, handleListExecutables } from "./list-executables.js";
29
16
  import { applyDeviceTargeting } from "./device-target.js";
30
17
  import { getAdapterSurface } from "../adapters/surface.js";
31
- import {
32
- indexProductProvenanceArtifact,
33
- writeRunReport
34
- } from "./run-report.js";
35
- import { acquireCheckoutLock } from "../checkout-lock.js";
36
- import { JsonStreamWriter } from "../json-stream.js";
37
- import { formatRunDiagnosticsForHuman, readRunDiagnosticsDocument } from "../run-diagnostics.js";
38
- import { recipeTrustFailure } from "../recipe-security.js";
39
- import { ProvenanceDriftError } from "../execution-provenance.js";
40
- import { recordCommandEvidence } from "../command-journal.js";
18
+ import { fundingOptionsFromCli } from "../funding-execution-context.js";
41
19
  import { actionLibraryContextArgs, resolveActionCapabilityMatrix } from "./manifest.js";
42
20
  import { missingActionCapabilities } from "@farmslot/recipe-cli";
43
21
  import {
@@ -266,7 +244,8 @@ async function handleRunInner({ positional, options }, stream) {
266
244
  let networkObservation;
267
245
  let performanceObservation;
268
246
  const runtimeOptions = {
269
- ...runtimeOptionsFromCli(options),
247
+ ...recipeRunOptionsFromCli(adapter, options),
248
+ ...fundingOptionsFromCli(options),
270
249
  params,
271
250
  ...librarySources ? { librarySources } : {},
272
251
  stdoutIsMachineContract: machine,
@@ -1,10 +1,5 @@
1
+ import { adapterOption, applyRuntimeDirOption, optionFlag, targetPath } from "@farmslot/recipe-cli/harness";
1
2
  import { getAdapterSurface } from "../adapters/surface.js";
2
- import {
3
- adapterOption,
4
- applyRuntimeDirOption,
5
- optionFlag,
6
- targetPath
7
- } from "./parse-args.js";
8
3
  async function handleRuntimeDecision({ options }) {
9
4
  applyRuntimeDirOption(options);
10
5
  const adapter = adapterOption(options);
@@ -1,10 +1,4 @@
1
- import {
2
- adapterOption,
3
- optionFlag,
4
- optionString,
5
- parsePort,
6
- targetPath
7
- } from "./parse-args.js";
1
+ import { adapterOption, optionFlag, optionString, parsePort, targetPath } from "@farmslot/recipe-cli/harness";
8
2
  async function handleRuntimeHealth({ options }) {
9
3
  const adapter = adapterOption(options);
10
4
  if (adapter !== "extension") throw new Error("runtime-health currently applies to the extension adapter.");
@@ -1,5 +1,4 @@
1
- import { checkoutBusyOut, spawnScriptStreaming } from "./shared.js";
2
- import { acquireCheckoutLock } from "../checkout-lock.js";
1
+ import { acquireCheckoutLock, recipeHarnessPath, checkoutBusyOut, spawnScriptStreaming, adapterOption, isRecord, optionFlag, optionString, parsePort, shellQuote, targetPath, usageError } from "@farmslot/recipe-cli/harness";
3
2
  import fs from "node:fs";
4
3
  import path from "node:path";
5
4
  import {
@@ -10,19 +9,8 @@ import {
10
9
  clearMobileReleaseArtifactState,
11
10
  writeMobileReleaseArtifactState
12
11
  } from "../adapters/mobile/release-artifact-state.js";
13
- import { recipeHarnessPath } from "../paths.js";
14
12
  import { extensionDepsBlock } from "./launch/extension.js";
15
13
  import { isExtensionDistStale } from "../adapters/extension/runtime-decision.js";
16
- import {
17
- adapterOption,
18
- isRecord,
19
- optionFlag,
20
- optionString,
21
- parsePort,
22
- shellQuote,
23
- targetPath,
24
- usageError
25
- } from "./parse-args.js";
26
14
  import { FeatureFlagSpecError, parseRemoteFlagSpec } from "../feature-flags.js";
27
15
  async function handleRuntimeLaunch(args) {
28
16
  const target = targetPath(args.options);
@@ -1,13 +1,9 @@
1
+ import { optionFlag, optionString, requiredOption } from "@farmslot/recipe-cli/harness";
1
2
  import { mkdtemp } from "node:fs/promises";
2
3
  import os from "node:os";
3
4
  import path from "node:path";
4
5
  import { loadActionManifest, validateManifest } from "../manifest.js";
5
6
  import { recipePath, runnerDir } from "../paths.js";
6
- import {
7
- optionFlag,
8
- optionString,
9
- requiredOption
10
- } from "./parse-args.js";
11
7
  import { runRecipe } from "./run-engine.js";
12
8
  async function handleSelfTest({ options }) {
13
9
  const result = await runSelfTest(options);
@@ -28,7 +24,7 @@ async function runSelfTest(options) {
28
24
  const smokeRecipe = recipePath(`${adapter}/runner/smoke.recipe.json`);
29
25
  const artifactsDir = path.join(root, adapter);
30
26
  const result = await runRecipe(adapter, smokeRecipe, artifactsDir, runnerDir, void 0, {
31
- skipExtensionRuntimePrepare: true
27
+ platform: { skipExtensionRuntimePrepare: true }
32
28
  });
33
29
  runs.push({ adapter, manifestValidation: manifestValidation.summary, artifactsDir, result });
34
30
  }
@@ -1,14 +1,13 @@
1
1
  import os from "node:os";
2
2
  import path from "node:path";
3
3
  import { isTerminalWorkerSignalStatus } from "@farmslot/protocol";
4
- import { color } from "../cli-color.js";
4
+ import { color, EXIT } from "@farmslot/recipe-cli/harness";
5
5
  import {
6
6
  CHECKLIST_LABEL_LIMIT,
7
7
  collectTaskView,
8
8
  findTaskDir,
9
9
  TASK_SILENT_AFTER_MS
10
10
  } from "../task-view.js";
11
- import { EXIT } from "./shared.js";
12
11
  const REFRESH_MS = 2e3;
13
12
  const CLEAR_SCREEN = "\x1B[2J\x1B[H";
14
13
  const HIDE_CURSOR = "\x1B[?25l";
@@ -1,18 +1,15 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { featureFlagReport } from "../feature-flags.js";
4
- import { color } from "../cli-color.js";
4
+ import { color, detectAdapter, adapterDetectNext, EXIT, usageOut, optionFlag, optionString, targetPath } from "@farmslot/recipe-cli/harness";
5
5
  import { collectCheckoutView, renderCheckoutView } from "../checkout-view.js";
6
- import { detectAdapter } from "../harness.js";
7
6
  import { assertAdapter } from "../paths.js";
8
7
  import { getAdapterSurface } from "../adapters/surface.js";
9
8
  import {
10
9
  applyDeviceTargeting
11
10
  } from "./device-target.js";
12
- import { ADAPTER_DETECT_NEXT, EXIT, usageOut } from "./shared.js";
13
11
  import { handleStatusTaskView, renderAcceptanceLines } from "./status-watch.js";
14
12
  import { collectTaskView, findTaskDir } from "../task-view.js";
15
- import { optionFlag, optionString, targetPath } from "./parse-args.js";
16
13
  async function handleStatus({ options }) {
17
14
  const target = targetPath(options);
18
15
  const json = optionFlag(options, "json");
@@ -29,7 +26,7 @@ async function handleStatus({ options }) {
29
26
  const allDevices = optionFlag(options, "allDevices");
30
27
  const adapter = detectAdapter(target);
31
28
  if (!adapter) {
32
- return usageOut(json, "status", `could not detect the MetaMask repo type for ${target}`, ADAPTER_DETECT_NEXT);
29
+ return usageOut(json, "status", `could not detect the MetaMask repo type for ${target}`, adapterDetectNext());
33
30
  }
34
31
  assertAdapter(adapter);
35
32
  const view = collectCheckoutView(target, adapter);
@@ -1,8 +1,7 @@
1
+ import { harnessExecutable, detectAdapter, EXIT } from "@farmslot/recipe-cli/harness";
1
2
  import { spawnSync } from "node:child_process";
2
3
  import { createRequire } from "node:module";
3
- import { detectAdapter } from "../harness.js";
4
- import { harnessExecutable } from "../paths.js";
5
- import { EXIT } from "./shared.js";
4
+ import "../adapters/surface.js";
6
5
  const require2 = createRequire(import.meta.url);
7
6
  const USAGE = "mm-harness task init <task-dir> --flow f --template id --title t [options]";
8
7
  function hasOption(argv, name) {
@@ -1,5 +1,5 @@
1
+ import { parseArgs } from "@farmslot/recipe-cli/harness";
1
2
  import { spawnSync } from "node:child_process";
2
- import { parseArgs } from "./parse-args.js";
3
3
  const PROTECTED_TUTORIAL_URL = "https://glowing-chainsaw-gwzrn8k.pages.github.io/recipes.html#agent-method";
4
4
  function recipeTutorialUrl(runMode = process.env.MM_HARNESS_RUN_MODE) {
5
5
  if (runMode === "src") {
@@ -13,7 +13,7 @@ function openUrl(url) {
13
13
  return result.status === 0;
14
14
  }
15
15
  function handleTutorial(argv, context) {
16
- const parsed = parseArgs(argv, "tutorial");
16
+ const parsed = parseArgs(argv);
17
17
  const url = recipeTutorialUrl();
18
18
  const noOpen = parsed.options.noOpen === true;
19
19
  const opened = noOpen ? false : (context.open ?? openUrl)(url);
@@ -1,9 +1,9 @@
1
+ import { EXIT, flag, parseFlags } from "@farmslot/recipe-cli/harness";
1
2
  import { spawn, spawnSync } from "node:child_process";
2
3
  import fs from "node:fs";
3
4
  import os from "node:os";
4
5
  import path from "node:path";
5
6
  import { runnerDir } from "../paths.js";
6
- import { EXIT, flag, parseFlags } from "./shared.js";
7
7
  const PACKAGE_NAME = "@deeeed/metamask-harness";
8
8
  const NUDGE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
9
9
  const NUDGE_FETCH_TIMEOUT_MS = 2e3;
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { recipeRuntimePath } from "./paths.js";
3
+ import { recipeRuntimePath } from "@farmslot/recipe-cli/harness";
4
4
  const COMPLETION_CACHE_VERSION = 2;
5
5
  const COMPLETION_CACHE_TTL_MS = 6e4;
6
6
  function completionCachePath(projectRoot) {
@@ -0,0 +1,19 @@
1
+ import {
2
+ allowlistMatch,
3
+ classifyConsoleRecord,
4
+ consoleRecords,
5
+ libraryRootsFromEnv,
6
+ loadConsoleAllowlist,
7
+ messageSignature
8
+ } from "../library/actions/shared/console-findings.mjs";
9
+ const consoleClassifier = {
10
+ records: (text) => consoleRecords(text),
11
+ classify: (record) => classifyConsoleRecord(record),
12
+ signature: (message) => messageSignature(message),
13
+ loadAllowlist: (libraryRoots) => loadConsoleAllowlist([...libraryRoots]),
14
+ match: (event, allowlist) => allowlistMatch(event, allowlist),
15
+ libraryRoots: () => libraryRootsFromEnv()
16
+ };
17
+ export {
18
+ consoleClassifier
19
+ };
package/dist/discovery.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { assessRecipe } from "@farmslot/recipe-cli";
2
2
  import {
3
3
  loadRecipeLibraries
4
- } from "@farmslot/recipe-harness";
4
+ } from "@farmslot/recipe-runner";
5
5
  import { resolveActionManifest } from "./manifest.js";
6
6
  async function runnableLibraryRecipes(adapter, sources) {
7
7
  const resolution = await loadRecipeLibraries(sources, { adapter });
package/dist/doctor.js CHANGED
@@ -1,11 +1,10 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { color } from "./cli-color.js";
3
+ import { color, harnessExecutable, recipeHarnessRoot, recipeRuntimeDir, readRuntimeContextField, resolveRuntimeContextPath } from "@farmslot/recipe-cli/harness";
4
4
  import { normalizeFeatureFlagRecord } from "./feature-flags.js";
5
5
  import { getAdapterSurface } from "./adapters/surface.js";
6
- import { readRuntimeContextField, resolveRuntimeContextPath } from "./harness.js";
7
6
  import { isPin } from "./harness-pin.js";
8
- import { harnessExecutable, readJson, recipeHarnessRoot, recipeRuntimeDir, runnerDir } from "./paths.js";
7
+ import { readJson, runnerDir } from "./paths.js";
9
8
  function requiredDoctorCheckSummary(checks) {
10
9
  const required = checks.filter((check) => check.required);
11
10
  const failed = required.filter((check) => check.status === "fail").map((check) => check.id);
@@ -224,7 +223,7 @@ function runnerProvenance(actionManifestPath) {
224
223
  invokedPath,
225
224
  executablePath,
226
225
  actionManifestPath,
227
- harnessPackage: "@farmslot/recipe-harness"
226
+ harnessPackage: "@farmslot/recipe-runner"
228
227
  };
229
228
  }
230
229
  function readJsonObject(file) {
@@ -1,10 +1,10 @@
1
+ import { optionString, recipeRuntimeDir } from "@farmslot/recipe-cli/harness";
1
2
  import { createHash } from "node:crypto";
2
3
  import { constants as fsConstants } from "node:fs";
3
4
  import { chmod, lstat, mkdir, open, readFile, readdir, realpath } from "node:fs/promises";
4
5
  import os from "node:os";
5
6
  import path from "node:path";
6
7
  import { digestRecipeDocument } from "@farmslot/protocol";
7
- import { recipeRuntimeDir } from "./paths.js";
8
8
  const SHA256 = /^[a-f0-9]{64}$/u;
9
9
  const INTEGER = /^(0|[1-9][0-9]{0,39})$/u;
10
10
  const IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
@@ -255,6 +255,18 @@ async function trustedMutationForAction(base, recipe, selectedIdentitySha256) {
255
255
  trustedActionContexts.add(trusted);
256
256
  return trusted;
257
257
  }
258
+ function fundingOptionsFromCli(options) {
259
+ return {
260
+ fundingRequest: optionString(options, "fundingRequest"),
261
+ fundingPreflight: optionString(options, "fundingPreflight"),
262
+ fundingReleaseProof: optionString(options, "fundingReleaseProof"),
263
+ fundingBalanceProof: optionString(options, "fundingBalanceProof")
264
+ };
265
+ }
266
+ function trustedMutationContextExtras(context) {
267
+ const trusted = context.trustedMutation;
268
+ return trusted ? { trustedMutation: serializeTrustedMutationContext(trusted) } : void 0;
269
+ }
258
270
  function serializeTrustedMutationContext(value) {
259
271
  if (!isRecord(value) || !trustedActionContexts.has(value)) {
260
272
  throw new Error("Live adapter refused an untrusted mutation context.");
@@ -1431,8 +1443,10 @@ function deepFreeze(value) {
1431
1443
  }
1432
1444
  export {
1433
1445
  authorizeTrustedMutationPlan,
1446
+ fundingOptionsFromCli,
1434
1447
  loadTrustedMutationBase,
1435
1448
  selectedIdentityFromWalletImport,
1436
1449
  serializeTrustedMutationContext,
1450
+ trustedMutationContextExtras,
1437
1451
  trustedMutationForAction
1438
1452
  };
package/dist/host.js ADDED
@@ -0,0 +1,32 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { configureHarnessAdapters, configureHarnessHost } from "@farmslot/recipe-cli/harness";
4
+ import { adapterRegistry } from "./adapters/registry.js";
5
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
6
+ configureHarnessHost({
7
+ name: "mm-harness",
8
+ product: "MetaMask",
9
+ envPrefix: "MM_HARNESS",
10
+ recipeEnvPrefix: "METAMASK_RECIPE",
11
+ packageName: "@deeeed/metamask-harness",
12
+ packageRoot,
13
+ bin: "bin/mm-harness",
14
+ journaledCommands: [
15
+ "prepare",
16
+ "call",
17
+ "check",
18
+ "checklist",
19
+ "cleanup",
20
+ "doctor",
21
+ "fixtures",
22
+ "install",
23
+ "launch",
24
+ "runtime-launch",
25
+ "provision",
26
+ "recipe-quality",
27
+ "run",
28
+ "stop",
29
+ "verify"
30
+ ]
31
+ });
32
+ configureHarnessAdapters(adapterRegistry);
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import "./host.js";
1
2
  import { createDoctorReport } from "./doctor.js";
2
3
  import { loadActionManifest, validateManifest } from "./manifest.js";
3
4
  import { createMetaMaskExtensionRunner, createMetaMaskMobileRunner, createMetaMaskRunner } from "./runner.js";
@@ -5,13 +6,9 @@ import {
5
6
  extensionIdPath,
6
7
  importRecipeHarnessRuntimeBrowserExtension,
7
8
  importRecipeHarnessRuntimeCdp,
8
- recipeHarnessPath,
9
9
  walletFixturePath
10
10
  } from "./paths.js";
11
- import { captureActiveRecipeRecordingSnapshot } from "./run-recording.js";
12
- import { validateRuntimeProof } from "./runtime-proof.js";
13
11
  export {
14
- captureActiveRecipeRecordingSnapshot,
15
12
  createDoctorReport,
16
13
  createMetaMaskExtensionRunner,
17
14
  createMetaMaskMobileRunner,
@@ -20,8 +17,6 @@ export {
20
17
  importRecipeHarnessRuntimeBrowserExtension,
21
18
  importRecipeHarnessRuntimeCdp,
22
19
  loadActionManifest,
23
- recipeHarnessPath,
24
20
  validateManifest,
25
- validateRuntimeProof,
26
21
  walletFixturePath
27
22
  };
@@ -0,0 +1,49 @@
1
+ import { accessSync, constants, existsSync, readFileSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import path from "node:path";
4
+ const requireFromHarness = createRequire(import.meta.url);
5
+ function harnessTsxBin() {
6
+ try {
7
+ const manifest = requireFromHarness.resolve("tsx/package.json");
8
+ const { bin } = JSON.parse(readFileSync(manifest, "utf8"));
9
+ const relative = typeof bin === "string" ? bin : bin?.tsx;
10
+ return relative ? path.join(path.dirname(manifest), relative) : void 0;
11
+ } catch {
12
+ return void 0;
13
+ }
14
+ }
15
+ function liveTsxCandidates() {
16
+ const bin = harnessTsxBin();
17
+ return bin ? [bin] : [];
18
+ }
19
+ function isExecutable(file) {
20
+ try {
21
+ accessSync(file, constants.X_OK);
22
+ return true;
23
+ } catch {
24
+ return false;
25
+ }
26
+ }
27
+ function resolveOverride(override, projectRoot) {
28
+ if (!override.includes("/")) {
29
+ return (process.env.PATH ?? "").split(path.delimiter).map((dir) => path.join(path.resolve(projectRoot, dir || "."), override)).find(isExecutable);
30
+ }
31
+ const bin = path.resolve(projectRoot, override);
32
+ return isExecutable(bin) ? bin : void 0;
33
+ }
34
+ function resolveLiveTsx(projectRoot) {
35
+ const override = process.env.TSX_BIN;
36
+ if (override) {
37
+ const bin = resolveOverride(override, path.resolve(projectRoot));
38
+ return bin ? { bin, source: "TSX_BIN" } : null;
39
+ }
40
+ const target = path.join(path.resolve(projectRoot), "node_modules/.bin/tsx");
41
+ if (existsSync(target)) return { bin: target, source: "target" };
42
+ const harness = harnessTsxBin();
43
+ return harness && existsSync(harness) ? { bin: harness, source: "harness" } : null;
44
+ }
45
+ export {
46
+ harnessTsxBin,
47
+ liveTsxCandidates,
48
+ resolveLiveTsx
49
+ };
@@ -1,11 +1,10 @@
1
+ import "./host.js";
1
2
  import { spawnSync } from "node:child_process";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
5
  import { fileURLToPath } from "node:url";
5
6
  import { Command } from "commander";
6
- import { color } from "./cli-color.js";
7
- import { withCommandJournal } from "./command-journal.js";
8
- import { JsonStreamWriter } from "./json-stream.js";
7
+ import { color, withCommandJournal, JsonStreamWriter, detectAdapter } from "@farmslot/recipe-cli/harness";
9
8
  import { handleUpdate, maybeNudge } from "./commands/update.js";
10
9
  import { handlePin } from "./commands/pin.js";
11
10
  import { handleCallHelp } from "./commands/call.js";
@@ -13,7 +12,6 @@ import { handleHelp } from "./commands/help.js";
13
12
  import { handleTutorial } from "./commands/tutorial.js";
14
13
  import { handleSetupBase } from "./commands/setup-base.js";
15
14
  import { getAdapterSurface } from "./adapters/surface.js";
16
- import { detectAdapter } from "./harness.js";
17
15
  import { configPath, hydrateLibraryPathEnv, readConfig } from "./review/knowledge.js";
18
16
  import {
19
17
  PUBLIC_COMMAND_CONTRACTS,
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
- import brokerModule from "../adapters/mobile/bridge-runtime/lib/cdp-broker.cjs";
3
- import configModule from "../adapters/mobile/bridge-runtime/lib/config.cjs";
2
+ import brokerModule from "@farmslot/recipe-runner/cdp-broker";
3
+ import configModule from "@farmslot/adapter-rn/bridge-runtime/lib/config.cjs";
4
4
  import {
5
5
  createExtensionNetworkObserver
6
6
  } from "./adapters/extension/network-observer.js";
@@ -8,7 +8,7 @@ import { getAdapterSurface } from "./adapters/surface.js";
8
8
  import {
9
9
  indexArtifactManifest,
10
10
  writeContainedArtifact
11
- } from "./artifact-files.js";
11
+ } from "@farmslot/recipe-cli/harness";
12
12
  const AUTO_CAPTURE_ID = "run-network";
13
13
  const AUTO_ARTIFACT_PATH = "network/run-summary.json";
14
14
  const { brokerSocketPath, createBrokerClient } = brokerModule;
@@ -179,7 +179,7 @@ function selectMobileBrokerTarget(value, env) {
179
179
  }
180
180
  function mobileTargetPin(env) {
181
181
  const platform = String(
182
- env.MM_HARNESS_EXPLICIT_PLATFORM ?? env.RECIPE_HARNESS_PLATFORM ?? ""
182
+ env.RECIPE_RN_EXPLICIT_PLATFORM ?? env.RECIPE_HARNESS_PLATFORM ?? ""
183
183
  ).toLowerCase();
184
184
  return String(
185
185
  platform === "android" ? env.ANDROID_TARGET_DEVICE_NAME ?? env.ANDROID_DEVICE ?? "" : platform === "ios" ? env.IOS_SIMULATOR ?? "" : env.IOS_SIMULATOR ?? env.ANDROID_TARGET_DEVICE_NAME ?? env.ANDROID_DEVICE ?? ""