@deeeed/metamask-harness 0.79.0 → 0.81.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 (252) hide show
  1. package/CHANGELOG.md +73 -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 +16 -64
  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/harness-source-fingerprint.mjs +13 -8
  21. package/adapters/shared/open-debug.mjs +2 -2
  22. package/adapters/shared/sync-wallet-fixture.sh +8 -5
  23. package/adapters/terminal/cleanup.mjs +2 -1
  24. package/adapters/terminal/inject.mjs +2 -1
  25. package/adapters/terminal/launch.mjs +17 -13
  26. package/adapters/terminal/lib/mainnet-guard.mjs +9 -0
  27. package/adapters/terminal/lib/readiness.mjs +20 -12
  28. package/adapters/terminal/policy.mjs +35 -0
  29. package/adapters/terminal/verify.mjs +10 -3
  30. package/adapters/terminal/wallet-host.mjs +43 -225
  31. package/bin/mm-harness +9 -28
  32. package/dist/adapters/checkout-files.js +16 -0
  33. package/dist/adapters/console-capture.js +14 -1
  34. package/dist/adapters/core/actions.js +8 -4
  35. package/dist/adapters/core/overlay.js +1 -1
  36. package/dist/adapters/core/readiness.js +28 -1
  37. package/dist/adapters/core/run.js +2 -2
  38. package/dist/adapters/core/surface.js +16 -1
  39. package/dist/adapters/extension/actions.js +6 -2
  40. package/dist/adapters/extension/browser-pid.js +56 -0
  41. package/dist/adapters/extension/console-capture.js +1 -1
  42. package/dist/adapters/extension/doctor-checks.js +1 -1
  43. package/dist/adapters/extension/ensure-ready.js +5 -4
  44. package/dist/adapters/extension/extension-id.js +1 -1
  45. package/dist/adapters/extension/feature-flags.js +1 -1
  46. package/dist/adapters/extension/fixtures.js +1 -2
  47. package/dist/adapters/extension/launch.js +4 -5
  48. package/dist/adapters/extension/launched-browser.js +1 -2
  49. package/dist/adapters/extension/network-observer.js +14 -1
  50. package/dist/adapters/extension/overlay.js +1 -1
  51. package/dist/adapters/extension/product-config.js +1 -1
  52. package/dist/adapters/extension/readiness.js +1 -1
  53. package/dist/adapters/extension/reload.js +1 -1
  54. package/dist/adapters/extension/run.js +135 -14
  55. package/dist/adapters/extension/runtime-decision.js +2 -1
  56. package/dist/adapters/extension/runtime.js +9 -5
  57. package/dist/adapters/extension/surface.js +15 -2
  58. package/dist/adapters/extension/verify.js +2 -2
  59. package/dist/adapters/harness-freshness.js +2 -1
  60. package/dist/adapters/mobile/actions.js +4 -1
  61. package/dist/adapters/mobile/android-gfxinfo-performance.js +1 -3
  62. package/dist/adapters/mobile/app-identity.js +10 -0
  63. package/dist/adapters/mobile/doctor-checks.js +1 -1
  64. package/dist/adapters/mobile/fixtures.js +1 -1
  65. package/dist/adapters/mobile/launch.js +27 -28
  66. package/dist/adapters/mobile/lifecycle.js +1 -1
  67. package/dist/adapters/mobile/metro-env.js +9 -59
  68. package/dist/adapters/mobile/network-observer.js +68 -0
  69. package/dist/adapters/mobile/performance-observer.js +2 -4
  70. package/dist/adapters/mobile/prepare-target.js +1 -1
  71. package/dist/adapters/mobile/prepare.js +3 -4
  72. package/dist/adapters/mobile/provision.js +1 -1
  73. package/dist/adapters/mobile/readiness.js +1 -1
  74. package/dist/adapters/mobile/recording-target.js +15 -0
  75. package/dist/adapters/mobile/release-artifact-state.js +1 -1
  76. package/dist/adapters/mobile/reload.js +1 -1
  77. package/dist/adapters/mobile/run.js +39 -15
  78. package/dist/adapters/mobile/runtime-decision.js +2 -4
  79. package/dist/adapters/mobile/source-freshness.js +22 -126
  80. package/dist/adapters/mobile/surface.js +26 -3
  81. package/dist/adapters/mobile/ui.js +16 -5
  82. package/dist/adapters/mobile/verify.js +2 -3
  83. package/dist/adapters/performance/cdp-trace.js +1 -1
  84. package/dist/adapters/performance/device-platform.js +1 -1
  85. package/dist/adapters/perps-order-inputs.js +36 -0
  86. package/dist/adapters/proof-failure.js +11 -0
  87. package/dist/adapters/slot-ports.js +1 -1
  88. package/dist/adapters/surface.js +1 -0
  89. package/dist/adapters/terminal/actions.js +4 -1
  90. package/dist/adapters/terminal/console-capture.js +1 -1
  91. package/dist/adapters/terminal/doctor-checks.js +2 -0
  92. package/dist/adapters/terminal/launch.js +4 -1
  93. package/dist/adapters/terminal/overlay.js +8 -1
  94. package/dist/adapters/terminal/run.js +33 -5
  95. package/dist/adapters/terminal/surface.js +9 -1
  96. package/dist/adapters.js +27 -7
  97. package/dist/advisor-policy.js +1 -1
  98. package/dist/checkout-view.js +1 -2
  99. package/dist/cli.js +59 -21
  100. package/dist/command-contract.js +1 -26
  101. package/dist/commands/check.js +33 -10
  102. package/dist/commands/checklist.js +1 -1
  103. package/dist/commands/completion-candidates.js +6 -14
  104. package/dist/commands/config.js +2 -2
  105. package/dist/commands/core-readiness.js +12 -7
  106. package/dist/commands/debug.js +3 -3
  107. package/dist/commands/device-target.js +5 -5
  108. package/dist/commands/doctor.js +2 -14
  109. package/dist/commands/domain.js +2 -2
  110. package/dist/commands/ensure-ready.js +1 -7
  111. package/dist/commands/fixtures.js +5 -6
  112. package/dist/commands/help.js +3 -4
  113. package/dist/commands/launch/device.js +10 -17
  114. package/dist/commands/launch/extension.js +2 -8
  115. package/dist/commands/launch/mobile.js +1 -1
  116. package/dist/commands/logs.js +3 -3
  117. package/dist/commands/mobile-device-view.js +4 -2
  118. package/dist/commands/overlay.js +110 -0
  119. package/dist/commands/pin.js +1 -1
  120. package/dist/commands/pr-body.js +2 -2
  121. package/dist/commands/prepare.js +4 -9
  122. package/dist/commands/provision.js +3 -12
  123. package/dist/commands/recipe-advice.js +1 -2
  124. package/dist/commands/recipe-quality.js +2 -3
  125. package/dist/commands/resolve-extension.js +1 -7
  126. package/dist/commands/review.js +4 -4
  127. package/dist/commands/runtime-decision.js +1 -6
  128. package/dist/commands/runtime-health.js +1 -7
  129. package/dist/commands/runtime-launch.js +1 -13
  130. package/dist/commands/self-test.js +5 -8
  131. package/dist/commands/status-watch.js +1 -2
  132. package/dist/commands/status.js +2 -5
  133. package/dist/commands/task-init.js +2 -3
  134. package/dist/commands/tutorial.js +2 -2
  135. package/dist/commands/update.js +1 -1
  136. package/dist/completions-cache.js +1 -1
  137. package/dist/console-classifier.js +19 -0
  138. package/dist/doctor.js +2 -3
  139. package/dist/engine.js +57 -0
  140. package/dist/funding-execution-context.js +96 -1
  141. package/dist/host.js +32 -0
  142. package/dist/index.js +1 -6
  143. package/dist/live-tsx.js +49 -0
  144. package/dist/mm-harness-cli.js +4 -6
  145. package/dist/paths.js +34 -64
  146. package/dist/performance-observation.js +3 -5
  147. package/dist/progress.js +1 -1
  148. package/dist/recipe-assistance-context.js +6 -9
  149. package/dist/recipe-security.js +2 -59
  150. package/dist/review/knowledge.js +2 -2
  151. package/dist/runner.js +7 -4
  152. package/dist/runtime-context.js +1 -1
  153. package/dist/task-view.js +2 -3
  154. package/docs/CONTRIBUTING.md +5 -3
  155. package/docs/RECIPES.md +31 -3
  156. package/docs/cli-contract.md +2 -2
  157. package/docs/feature-guard.md +90 -0
  158. package/library/README.md +3 -1
  159. package/library/actions/core/perps/_controller.mjs +153 -134
  160. package/library/actions/core/perps/_rewards.mjs +186 -0
  161. package/library/actions/core/perps/close_positions.mjs +1 -1
  162. package/library/actions/core/perps/place_order.mjs +167 -45
  163. package/library/actions/core/perps/quote_fees.mjs +61 -0
  164. package/library/actions/core/wallet/list_accounts.mjs +14 -57
  165. package/library/actions/extension/feature_flags/state.mjs +1 -1
  166. package/library/actions/extension/perps/close_visible_position.mjs +5 -0
  167. package/library/actions/extension/perps/edit_margin.mjs +4 -0
  168. package/library/actions/extension/perps/mutation-receipt.mjs +95 -3
  169. package/library/actions/extension/perps/perps.mjs +320 -3
  170. package/library/actions/extension/perps/place_order.mjs +3 -1
  171. package/library/actions/extension/perps/update_position_tpsl.mjs +4 -0
  172. package/library/actions/extension/platform/cdp.mjs +73 -11
  173. package/library/actions/harness-exports.mjs +1 -6
  174. package/library/actions/mobile/app/network-control.mjs +6 -8
  175. package/library/actions/mobile/perps/perps.mjs +216 -11
  176. package/library/actions/mobile/perps/place_order.mjs +3 -1
  177. package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +1 -1
  178. package/library/actions/mobile/platform/bridge.mjs +8 -8
  179. package/library/actions/mobile/platform/native-session-name.mjs +21 -1
  180. package/library/actions/mobile/platform/native-session.mjs +3 -4
  181. package/library/actions/mobile/platform/observe-ui.mjs +12 -6
  182. package/library/actions/mobile/ui/native-navigation.mjs +4 -3
  183. package/library/actions/mobile/wallet/native-ui.mjs +3 -2
  184. package/library/actions/shared/analytics/_adapter.mjs +1 -1
  185. package/library/actions/shared/console-findings.mjs +1 -1
  186. package/library/actions/shared/perps/order-policy.mjs +177 -0
  187. package/library/actions/shared/wallet/fixture-accounts.mjs +84 -0
  188. package/library/actions/terminal/app/launch.mjs +3 -2
  189. package/library/actions/terminal/platform/hud.mjs +2 -1
  190. package/library/actions/terminal/platform/page.mjs +2 -1
  191. package/library/actions/terminal/platform/runtime.mjs +2 -1
  192. package/library/actions/terminal/wallet/_signature-log.mjs +40 -161
  193. package/library/actions/terminal/wallet/assert_signatures.mjs +6 -12
  194. package/library/actions/terminal/wallet/read_signatures.mjs +10 -9
  195. package/library/manifests/core.action-manifest.json +87 -13
  196. package/library/manifests/extension.action-manifest.json +4 -0
  197. package/library/manifests/mobile.action-manifest.json +12 -0
  198. package/package.json +8 -9
  199. package/site/assets/help-recipes.json +1 -0
  200. package/adapters/extension/lib/slot-title.cjs +0 -292
  201. package/adapters/mobile/bridge-runtime/console-forwarder.cjs +0 -472
  202. package/adapters/mobile/bridge-runtime/lib/bridge-errors.cjs +0 -125
  203. package/adapters/mobile/bridge-runtime/lib/cdp-broker.cjs +0 -1055
  204. package/adapters/mobile/bridge-runtime/lib/cdp-eval.cjs +0 -110
  205. package/adapters/mobile/bridge-runtime/lib/config.cjs +0 -61
  206. package/adapters/mobile/bridge-runtime/lib/console-format.cjs +0 -53
  207. package/adapters/mobile/bridge-runtime/lib/devtools-proxy.cjs +0 -177
  208. package/adapters/mobile/bridge-runtime/lib/issue-capture.cjs +0 -446
  209. package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +0 -84
  210. package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +0 -403
  211. package/adapters/mobile/bridge-runtime/lib/ws-client.cjs +0 -116
  212. package/adapters/mobile/coalesce-metro-log.cjs +0 -24
  213. package/adapters/mobile/launch-metro.cjs +0 -77
  214. package/adapters/mobile/metro-config.cjs +0 -98
  215. package/adapters/mobile/metro-log-generation.cjs +0 -106
  216. package/adapters/terminal/lib/origin.mjs +0 -30
  217. package/adapters/terminal/lib/page-script.mjs +0 -246
  218. package/adapters/terminal/lib/strict-wallet.mjs +0 -138
  219. package/dist/adapters/mobile/frame-metrics.js +0 -118
  220. package/dist/adapters/mobile/video-recorder.js +0 -289
  221. package/dist/artifact-files.js +0 -92
  222. package/dist/checkout-lock.js +0 -149
  223. package/dist/cli-color.js +0 -98
  224. package/dist/command-journal.js +0 -308
  225. package/dist/commands/call.js +0 -685
  226. package/dist/commands/last.js +0 -60
  227. package/dist/commands/launch/index.js +0 -109
  228. package/dist/commands/list-executables.js +0 -247
  229. package/dist/commands/manifest.js +0 -488
  230. package/dist/commands/parse-args.js +0 -279
  231. package/dist/commands/reload.js +0 -41
  232. package/dist/commands/run-engine.js +0 -1340
  233. package/dist/commands/run-report.js +0 -241
  234. package/dist/commands/run.js +0 -751
  235. package/dist/commands/shared.js +0 -323
  236. package/dist/commands/stop.js +0 -60
  237. package/dist/devices.js +0 -100
  238. package/dist/discovery.js +0 -15
  239. package/dist/execution-provenance.js +0 -332
  240. package/dist/harness.js +0 -451
  241. package/dist/heal-bounds.js +0 -137
  242. package/dist/json-stream.js +0 -60
  243. package/dist/leaf-invoke.js +0 -19
  244. package/dist/library-provenance.js +0 -33
  245. package/dist/live-adapter-contract.js +0 -380
  246. package/dist/metamask-action-validation.js +0 -68
  247. package/dist/network-observation.js +0 -290
  248. package/dist/recording-target.js +0 -120
  249. package/dist/run-diagnostics.js +0 -364
  250. package/dist/run-recording.js +0 -481
  251. package/dist/runtime-proof.js +0 -90
  252. package/library/actions/mobile/platform/tool-paths.mjs +0 -123
@@ -1,15 +1,8 @@
1
1
  import { execFileSync } from "node:child_process";
2
2
  import fs from "node:fs";
3
- import { color, colorHumanMessage } from "../../cli-color.js";
4
- import { handleHarness } from "../../harness.js";
5
- import { recipeRuntimePath, walletFixturePath } from "../../paths.js";
3
+ import { color, colorHumanMessage, recipeRuntimePath, handleHarness, EXIT, flag, str, checkHealBounds, ensureOverlay, newHealState } from "@farmslot/recipe-cli/harness";
4
+ import { walletFixturePath } from "../../paths.js";
6
5
  import { getAdapterSurface } from "../../adapters/surface.js";
7
- import { EXIT, flag, str } from "../shared.js";
8
- import {
9
- checkHealBounds,
10
- ensureOverlay,
11
- newHealState
12
- } from "../../heal-bounds.js";
13
6
  import {
14
7
  FeatureFlagSpecError,
15
8
  fixtureFeatureFlags,
@@ -131,7 +124,7 @@ async function runDeviceLaunch(context, profile) {
131
124
  if (heal === "off") {
132
125
  return launch.fail(state, {
133
126
  code: "LAUNCH_FAILED",
134
- message: `launch ${adapter}${launch.mobileTarget ? ` ${launch.mobileTarget}` : ""} failed (healing off)`,
127
+ message: `launch ${adapter}${launch.platformTarget ? ` ${launch.platformTarget}` : ""} failed (healing off)`,
135
128
  recoverable: false,
136
129
  exitCode: EXIT.infra
137
130
  });
@@ -166,7 +159,7 @@ async function runDeviceLaunch(context, profile) {
166
159
  if (retryReadinessFailure) return launch.fail(state, retryReadinessFailure);
167
160
  return launch.fail(state, {
168
161
  code: "SAME_RECOVERY_TWICE",
169
- message: `launch ${adapter}${launch.mobileTarget ? ` ${launch.mobileTarget}` : ""} failed again after ${recovery.code} recovery \u2014 refusing to loop.`,
162
+ message: `launch ${adapter}${launch.platformTarget ? ` ${launch.platformTarget}` : ""} failed again after ${recovery.code} recovery \u2014 refusing to loop.`,
170
163
  recoverable: false,
171
164
  exitCode: EXIT.bounded,
172
165
  originalError: attempt.output.trim() || void 0
@@ -231,7 +224,7 @@ async function settleLaunch(launch, profile, state, sidepanelRecoveryAllowed, pr
231
224
  return launchPass(launch, profile, state, proven.flags);
232
225
  }
233
226
  function launchPass(launch, profile, state, remoteFlags) {
234
- const { adapter, mobileTarget, target, stream, tier } = launch;
227
+ const { adapter, platformTarget, target, stream, tier } = launch;
235
228
  if (stream.enabled) {
236
229
  for (const mutation of state.mutations) stream.mutation(mutation);
237
230
  for (const recovery of state.recovered) stream.recovery(recovery);
@@ -269,13 +262,13 @@ function launchPass(launch, profile, state, remoteFlags) {
269
262
  const tierNote = tier === "quick" ? "quick relaunch, no native build" : tier;
270
263
  const devNote = process.env.MM_HARNESS_BIN ? ` ${color("dim", "[dev: MM_HARNESS_BIN]")}` : "";
271
264
  console.error(
272
- `${color("ok", "\u2713")} launch ${adapter}${mobileTarget ? ` ${mobileTarget}` : ""} \u2014 ${color("ok", profile.deviceLabel(launch))} \xB7 ${tierNote} \xB7 app + bridge ready${devNote}`
265
+ `${color("ok", "\u2713")} launch ${adapter}${platformTarget ? ` ${platformTarget}` : ""} \u2014 ${color("ok", profile.deviceLabel(launch))} \xB7 ${tierNote} \xB7 app + bridge ready${devNote}`
273
266
  );
274
267
  }
275
268
  return EXIT.ok;
276
269
  }
277
270
  function launchFail(launch, profile, state, failure) {
278
- const { adapter, mobileTarget, target, stream, tier } = launch;
271
+ const { adapter, platformTarget, target, stream, tier } = launch;
279
272
  const userAction = failure.userAction ?? `mm-harness doctor --fix --adapter ${adapter} --target ${shellQuote(target)} --json`;
280
273
  if (stream.enabled) {
281
274
  for (const mutation of state.mutations) stream.mutation(mutation);
@@ -289,7 +282,7 @@ function launchFail(launch, profile, state, failure) {
289
282
  });
290
283
  stream.complete("fail", failure.exitCode, {
291
284
  adapter,
292
- platform: mobileTarget ?? null,
285
+ platform: platformTarget ?? null,
293
286
  tier,
294
287
  recovered: state.recovered,
295
288
  mutations: state.mutations,
@@ -304,7 +297,7 @@ function launchFail(launch, profile, state, failure) {
304
297
  schemaVersion: 1,
305
298
  command: "launch",
306
299
  adapter,
307
- platform: mobileTarget ?? null,
300
+ platform: platformTarget ?? null,
308
301
  tier,
309
302
  status: "fail",
310
303
  phase: state.attemptedRecoveries.length ? "recover" : "launch",
@@ -328,7 +321,7 @@ function launchFail(launch, profile, state, failure) {
328
321
  );
329
322
  } else {
330
323
  console.error(colorHumanMessage(
331
- `\u2717 launch ${adapter}${mobileTarget ? ` ${mobileTarget}` : ""} failed
324
+ `\u2717 launch ${adapter}${platformTarget ? ` ${platformTarget}` : ""} failed
332
325
  ${failure.message}` + (failure.originalError ? `
333
326
  --- original failure ---
334
327
  ${failure.originalError}` : "") + `
@@ -7,13 +7,8 @@ import {
7
7
  depsCheck,
8
8
  recordDepsBaseline
9
9
  } from "@farmslot/recipe-runner/runtime/deps-readiness";
10
- import { colorHumanMessage } from "../../cli-color.js";
11
- import {
12
- importRecipeHarnessRuntimeCdp,
13
- recipeHarnessPath,
14
- recipeRuntimeDir,
15
- runnerDir
16
- } from "../../paths.js";
10
+ import { colorHumanMessage, recipeHarnessPath, recipeRuntimeDir, EXIT, spawnScriptStreaming } from "@farmslot/recipe-cli/harness";
11
+ import { importRecipeHarnessRuntimeCdp, runnerDir } from "../../paths.js";
17
12
  import { extensionIdFromKey } from "../../adapters/extension/extension-id.js";
18
13
  import {
19
14
  EXTENSION_PRODUCT_CONFIG_FINGERPRINT_FILENAME,
@@ -29,7 +24,6 @@ import {
29
24
  import { checkExtensionRuntimeHealth } from "../../adapters/extension/runtime.js";
30
25
  import { ensureHarnessFresh } from "../../adapters/harness-freshness.js";
31
26
  import { isExtensionWatcherLive, stopExtensionWatcher } from "../../adapters/slot-ports.js";
32
- import { EXIT, spawnScriptStreaming } from "../shared.js";
33
27
  import { readExtensionPinnedFlags } from "../../adapters/extension/feature-flags.js";
34
28
  import { sameFeatureFlags } from "../../feature-flags.js";
35
29
  const { CdpSession } = await importRecipeHarnessRuntimeCdp();
@@ -1,3 +1,4 @@
1
+ import { EXIT } from "@farmslot/recipe-cli/harness";
1
2
  import { prepareMobile } from "../../adapters/mobile/prepare.js";
2
3
  import {
3
4
  mobileSourceCheck,
@@ -7,7 +8,6 @@ import { ensureHarnessFresh } from "../../adapters/harness-freshness.js";
7
8
  import { pinMobileFeatureFlags } from "../../adapters/mobile/feature-flags.js";
8
9
  import { toRemoteFlagSpec } from "../../feature-flags.js";
9
10
  import { clearMobileReleaseArtifactState } from "../../adapters/mobile/release-artifact-state.js";
10
- import { EXIT } from "../shared.js";
11
11
  async function launchMobile(target, mobileTarget, tier, json, restartApp = false, clearMetro = false, remoteFlags) {
12
12
  clearMobileReleaseArtifactState(target);
13
13
  await ensureHarnessFresh(target, "mobile");
@@ -1,16 +1,16 @@
1
+ import { adapterDetectNext, EXIT, flag, parseFlags, resolveFlagsAdapter, spawnInherit, spawnScript, str, targetOf, usageOut } from "@farmslot/recipe-cli/harness";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import { runnerDir } from "../paths.js";
4
5
  import { getAdapterSurface } from "../adapters/surface.js";
5
- import { ADAPTER_DETECT_NEXT, EXIT, flag, parseFlags, resolveAdapter, spawnInherit, spawnScript, str, targetOf, usageOut } from "./shared.js";
6
6
  const LOGS_BOOLEANS = /* @__PURE__ */ new Set(["full", "json", "window"]);
7
7
  async function handleLogs(argv) {
8
8
  const { options } = parseFlags(argv, LOGS_BOOLEANS);
9
9
  const json = flag(options, "json");
10
10
  const target = targetOf(options);
11
- const adapter = resolveAdapter(options, target);
11
+ const adapter = resolveFlagsAdapter(options, target);
12
12
  if (!adapter) {
13
- return usageOut(json, "logs", `could not detect the MetaMask repo type for ${target}`, ADAPTER_DETECT_NEXT);
13
+ return usageOut(json, "logs", `could not detect the MetaMask repo type for ${target}`, adapterDetectNext());
14
14
  }
15
15
  const surface = getAdapterSurface(adapter);
16
16
  if (surface.headless) {
@@ -1,6 +1,8 @@
1
1
  import { execFileSync } from "node:child_process";
2
- import { resolveMobileToolPath } from "../../library/actions/mobile/platform/tool-paths.mjs";
3
- import { listConnectedDevices } from "../devices.js";
2
+ import {
3
+ listConnectedDevices,
4
+ resolveMobileToolPath
5
+ } from "@farmslot/adapter-rn";
4
6
  import { renderDeviceList, scopedDevices } from "./device-target.js";
5
7
  import { probeMobileLiveState } from "./status-probe.js";
6
8
  function mobileDeviceView(allDevices) {
@@ -0,0 +1,110 @@
1
+ import {
2
+ argValue,
3
+ hasArg,
4
+ shellQuoteArg
5
+ } from "@farmslot/recipe-cli/harness";
6
+ import { getAdapterSurface } from "../adapters/surface.js";
7
+ const USAGE = `mm-harness \u2014 install and validate the MetaMask recipe runtime in a checkout.
8
+
9
+ Run it from inside a MetaMask checkout; the platform (mobile | extension | core | terminal)
10
+ is auto-detected from the repo. Pass --platform only to override.
11
+
12
+ Commands (one copy-pasteable example each):
13
+ install Install the recipe harness runtime overlay into the checkout.
14
+ mm-harness install
15
+ verify Check the harness/runtime is present and healthy (no app launch).
16
+ mm-harness verify
17
+ cleanup Remove the installed harness overlay and restore the checkout.
18
+ mm-harness cleanup
19
+
20
+ Options:
21
+ --platform <mobile|extension|core|terminal> Override auto-detection (alias: --adapter).
22
+ --target <repo> Checkout to operate on (default: current dir).
23
+ --json Machine-readable summary for agents/scripts.
24
+ -- <args> Forward the rest verbatim to the underlying
25
+ script, e.g. -- --platform ios --preflight-mode fast
26
+ (mobile) or -- --cdp-port 6665 (extension).
27
+
28
+ Examples:
29
+ mm-harness install # inside a checkout, auto-detected
30
+ mm-harness verify --platform extension
31
+ mm-harness cleanup --target ../metamask-mobile
32
+
33
+ core supports install, verify, and cleanup (headless; no live).`;
34
+ const overlayCommandOptions = {
35
+ usage: USAGE,
36
+ install: ({ adapter, target, forward, json }) => hasArg(forward, "--runway") ? handleRunwayInstall(adapter, target, forward, json) : void 0
37
+ };
38
+ async function handleRunwayInstall(adapter, target, forward, json) {
39
+ const rerunCommand = runwayInstallRerunCommand(adapter, target, forward, json);
40
+ const surface = getAdapterSurface(adapter);
41
+ const runtimeDir = argValue(forward, "--runtime-dir");
42
+ const watcherPort = argValue(forward, "--watcher-port");
43
+ const result = await surface.runwayProvision.run(target, {
44
+ json,
45
+ platform: argValue(forward, "--platform") ?? "ios",
46
+ branch: argValue(forward, "--branch"),
47
+ defaultBranch: argValue(forward, "--default-branch"),
48
+ run: argValue(forward, "--run"),
49
+ cacheRoot: argValue(forward, "--cache-root"),
50
+ simulator: argValue(forward, "--simulator") ?? argValue(forward, "--device"),
51
+ runtime: argValue(forward, "--runtime"),
52
+ deviceType: argValue(forward, "--device-type"),
53
+ slot: argValue(forward, "--slot"),
54
+ watcherPort,
55
+ runtimeDir,
56
+ force: hasArg(forward, "--force"),
57
+ resolveOnly: hasArg(forward, "--resolve-only"),
58
+ rerunCommand
59
+ });
60
+ const provisionedSimulator = typeof result.simulator === "object" && result.simulator ? result.simulator : void 0;
61
+ const provisionedDevice = typeof provisionedSimulator?.udid === "string" ? provisionedSimulator.udid : typeof provisionedSimulator?.name === "string" ? provisionedSimulator.name : void 0;
62
+ const next = result.status === "pass" && surface.runwayProvision.launchNext && result.resolveOnly !== true ? `mm-harness launch ${String(result.platform ?? "ios")} --adapter ${adapter} --target ${shellQuoteArg(target)}` + (provisionedDevice ? ` --device ${shellQuoteArg(provisionedDevice)}` : "") : void 0;
63
+ const output = next ? { ...result, next } : result;
64
+ if (json) {
65
+ console.log(JSON.stringify(output, null, 2));
66
+ } else if (result.status === "pass") {
67
+ const cache = typeof result.cache === "object" && result.cache ? result.cache : void 0;
68
+ const simulator = provisionedSimulator;
69
+ const artifact = typeof result.artifact === "object" && result.artifact ? result.artifact : void 0;
70
+ if (result.resolveOnly) {
71
+ console.error(`\u2713 resolved Runway app for ${adapter} ${result.platform ?? ""} run=${artifact?.runId ?? "unknown"} revision=${artifact?.revision ?? "unknown"} artifact=${artifact?.artifactName ?? "unknown"}`);
72
+ } else {
73
+ const action = result.skipped ? "already provisioned" : "installed Runway app";
74
+ console.error(`\u2713 ${action} for ${adapter} ${result.platform ?? ""} simulator=${simulator?.name ?? "unknown"} udid=${simulator?.udid ?? "unknown"} cache=${cache?.status ?? "skip"}`);
75
+ }
76
+ if (next) console.error(` Next: ${next}`);
77
+ } else {
78
+ console.error(`\u2717 mm-harness install --runway: ${result.error?.message ?? "runway install failed"}
79
+ Next: ${result.error?.userAction ?? rerunCommand}`);
80
+ }
81
+ return result.exitCode;
82
+ }
83
+ function runwayInstallRerunCommand(adapter, target, forward, json) {
84
+ const parts = ["mm-harness", "install", "--runway", "--adapter", adapter, "--target", shellQuoteArg(target)];
85
+ const valueFlags = [
86
+ "--platform",
87
+ "--branch",
88
+ "--default-branch",
89
+ "--run",
90
+ "--cache-root",
91
+ "--simulator",
92
+ "--device",
93
+ "--slot",
94
+ "--watcher-port",
95
+ "--runtime-dir",
96
+ "--runtime",
97
+ "--device-type"
98
+ ];
99
+ for (const flag of valueFlags) {
100
+ const value = argValue(forward, flag);
101
+ if (value) parts.push(flag, shellQuoteArg(value));
102
+ }
103
+ if (hasArg(forward, "--force")) parts.push("--force");
104
+ if (hasArg(forward, "--resolve-only")) parts.push("--resolve-only");
105
+ if (json) parts.push("--json");
106
+ return parts.join(" ");
107
+ }
108
+ export {
109
+ overlayCommandOptions
110
+ };
@@ -1,3 +1,4 @@
1
+ import { EXIT } from "@farmslot/recipe-cli/harness";
1
2
  import { spawnSync } from "node:child_process";
2
3
  import crypto from "node:crypto";
3
4
  import fs from "node:fs";
@@ -6,7 +7,6 @@ import os from "node:os";
6
7
  import path from "node:path";
7
8
  import { isPin, PIN_MARKER } from "../harness-pin.js";
8
9
  import { runnerDir } from "../paths.js";
9
- import { EXIT } from "./shared.js";
10
10
  const PACKAGE_NAME = "@deeeed/metamask-harness";
11
11
  const STALE_STAGING_MS = 30 * 60 * 1e3;
12
12
  const RUNNER_STATE = /* @__PURE__ */ new Set([".omc", ".omx"]);
@@ -1,10 +1,10 @@
1
+ import { optionFlag, optionString, parseArgs, usageError } from "@farmslot/recipe-cli/harness";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import { BODY_FILE, renderPrBody } from "../pr-body/render.js";
4
- import { optionFlag, optionString, parseArgs, usageError } from "./parse-args.js";
5
5
  const USAGE = "Usage: mm-harness pr-body render <task-dir> [--command <text>] [--out <file>] [--json]";
6
6
  async function handlePrBody(argv) {
7
- const parsed = parseArgs(argv, "pr-body");
7
+ const parsed = parseArgs(argv);
8
8
  const [action, taskArg] = parsed.positional;
9
9
  if (action !== "render" || !taskArg) throw usageError(USAGE);
10
10
  const taskDir = path.resolve(taskArg);
@@ -1,5 +1,4 @@
1
- import { acquireCheckoutLock, trackCheckoutChild } from "../checkout-lock.js";
2
- import { recordCommandStage } from "../command-journal.js";
1
+ import { acquireCheckoutLock, trackCheckoutChild, recordCommandStage, color, stripAnsi, harnessExecutable, recipeRuntimeDir, detectAdapter, optionFlag, optionString, parseArgs, targetPath, usageError, EXIT } from "@farmslot/recipe-cli/harness";
3
2
  import { spawn } from "node:child_process";
4
3
  import { OperationOutputTail } from "@farmslot/recipe-runner/runtime/operation";
5
4
  import fs from "node:fs";
@@ -7,14 +6,10 @@ import path from "node:path";
7
6
  import {
8
7
  READINESS_RECORD
9
8
  } from "@farmslot/protocol";
10
- import { color, stripAnsi } from "../cli-color.js";
11
9
  import { runnerProvenance } from "../doctor.js";
12
- import { detectAdapter } from "../harness.js";
13
10
  import { adapterRegistry } from "../adapters/registry.js";
14
11
  import { getAdapterSurface } from "../adapters/surface.js";
15
- import { harnessExecutable, PREPARE_PROGRESS_ARTIFACT, recipeRuntimeDir } from "../paths.js";
16
- import { optionFlag, optionString, parseArgs, targetPath, usageError } from "./parse-args.js";
17
- import { EXIT } from "./shared.js";
12
+ import { PREPARE_PROGRESS_ARTIFACT } from "../paths.js";
18
13
  import { formatDuration } from "./status-watch.js";
19
14
  import { FeatureFlagSpecError, parseRemoteFlagSpec } from "../feature-flags.js";
20
15
  const USAGE = "mm-harness prepare [--target <checkout>] [--platform mobile|extension|core] [--mobile-platform ios|android] [--clear-metro] [--artifacts-dir <dir>] [--json]";
@@ -282,7 +277,7 @@ function resolvePlatform(requested, target) {
282
277
  );
283
278
  }
284
279
  async function handlePrepare(argv) {
285
- const { options } = parseArgs(argv, "prepare");
280
+ const { options } = parseArgs(argv);
286
281
  const target = targetPath(options);
287
282
  if (!fs.existsSync(target)) return handlePrepareLocked(argv);
288
283
  const lock = acquireCheckoutLock(target, "prepare");
@@ -298,7 +293,7 @@ async function handlePrepare(argv) {
298
293
  }
299
294
  }
300
295
  async function handlePrepareLocked(argv) {
301
- const { options } = parseArgs(argv, "prepare");
296
+ const { options } = parseArgs(argv);
302
297
  const json = optionFlag(options, "json");
303
298
  const target = targetPath(options);
304
299
  const surface = resolvePlatform(optionString(options, "platform"), target);
@@ -1,27 +1,18 @@
1
- import { detectAdapter } from "../harness.js";
1
+ import { detectAdapter, adapterDetectNext, usageOut, applyWatcherPortOption, optionFlag, optionString, shellQuote, shellQuoteArg, targetPath } from "@farmslot/recipe-cli/harness";
2
2
  import { assertAdapter } from "../paths.js";
3
3
  import { getAdapterSurface } from "../adapters/surface.js";
4
- import { ADAPTER_DETECT_NEXT, usageOut } from "./shared.js";
5
- import {
6
- applyWatcherPortOption,
7
- optionFlag,
8
- optionString,
9
- shellQuote,
10
- shellQuoteArg,
11
- targetPath
12
- } from "./parse-args.js";
13
4
  async function handleProvision({ positional, options, rawArgv }) {
14
5
  applyWatcherPortOption(options);
15
6
  const json = optionFlag(options, "json");
16
7
  const target = targetPath(options);
17
8
  const adapter = optionString(options, "adapter") ?? detectAdapter(target);
18
9
  if (!adapter) {
19
- return usageOut(json, "provision", `could not detect the MetaMask repo type for ${target}`, ADAPTER_DETECT_NEXT);
10
+ return usageOut(json, "provision", `could not detect the MetaMask repo type for ${target}`, adapterDetectNext());
20
11
  }
21
12
  try {
22
13
  assertAdapter(adapter);
23
14
  } catch (error) {
24
- return usageOut(json, "provision", error instanceof Error ? error.message : String(error), ADAPTER_DETECT_NEXT);
15
+ return usageOut(json, "provision", error instanceof Error ? error.message : String(error), adapterDetectNext());
25
16
  }
26
17
  const surface = getAdapterSurface(adapter);
27
18
  const rerunCommand = provisionRerunCommand(rawArgv, options, adapter, target);
@@ -1,10 +1,9 @@
1
+ import { CliError, isRecord, optionFlag, optionString, usageError, EXIT } from "@farmslot/recipe-cli/harness";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import { adviseRecipe } from "../recipe-assistance.js";
4
5
  import { resolveAdvisorPolicy } from "../advisor-policy.js";
5
6
  import { RECIPE_ADVICE_RUBRIC, RECIPE_PLANNING_RUBRIC } from "../recipe-assistance-rubric.js";
6
- import { CliError, isRecord, optionFlag, optionString, usageError } from "./parse-args.js";
7
- import { EXIT } from "./shared.js";
8
7
  async function handleRecipeAdvice(options, mode = "review") {
9
8
  try {
10
9
  return await runRecipeAdvice(options, mode);
@@ -1,10 +1,9 @@
1
+ import { EXIT, usageOut, optionFlag, optionString, parseArgs } from "@farmslot/recipe-cli/harness";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import {
4
5
  buildRecipeQualityArtifact
5
6
  } from "@farmslot/agent-runtime";
6
- import { EXIT, usageOut } from "./shared.js";
7
- import { optionFlag, optionString, parseArgs } from "./parse-args.js";
8
7
  const BUILD_USAGE = "mm-harness recipe-quality build --input <compact.json> --output <path> [--json]";
9
8
  const SHORTHAND_USAGE = "mm-harness recipe-quality build --input <compact.json> --output <path> [--json]\n Shorthand: mm-harness recipe-quality --input <compact.json> --output <path> [--json]\n Note: apply the quality bar from mm-harness help, then build its compact verdict here.";
10
9
  function errorMessage(error) {
@@ -34,7 +33,7 @@ function invalidOut(json, message, source) {
34
33
  return EXIT.validation;
35
34
  }
36
35
  async function handleRecipeQuality(argv) {
37
- const { positional, options } = parseArgs(argv, "recipe-quality");
36
+ const { positional, options } = parseArgs(argv);
38
37
  const json = optionFlag(options, "json");
39
38
  const action = positional[0];
40
39
  if (action === "advise" || action === "plan" || action === "advisor-status") {
@@ -1,11 +1,5 @@
1
+ import { adapterOption, optionFlag, optionString, parsePort, targetPath } from "@farmslot/recipe-cli/harness";
1
2
  import { resolveExtensionId } from "../adapters/extension/extension-id.js";
2
- import {
3
- adapterOption,
4
- optionFlag,
5
- optionString,
6
- parsePort,
7
- targetPath
8
- } from "./parse-args.js";
9
3
  async function handleResolveExtension({ options }) {
10
4
  const adapter = adapterOption(options);
11
5
  if (adapter !== "extension") throw new Error("resolve-extension currently applies to the extension adapter.");
@@ -1,6 +1,6 @@
1
+ import { detectAdapter, optionFlag, optionString, parseArgs, targetPath, usageError } from "@farmslot/recipe-cli/harness";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
- import { detectAdapter } from "../harness.js";
4
4
  import { runnerDir } from "../paths.js";
5
5
  import {
6
6
  configPath,
@@ -15,7 +15,7 @@ import {
15
15
  resolveReference,
16
16
  defaultBaseRef
17
17
  } from "../review/knowledge.js";
18
- import { optionFlag, optionString, parseArgs, targetPath, usageError } from "./parse-args.js";
18
+ import "../adapters/surface.js";
19
19
  const EXIT_OK = 0;
20
20
  let cachedHarnessVersion;
21
21
  function harnessVersion() {
@@ -54,7 +54,7 @@ function resolveReviewContext(options, { fetch = true } = {}) {
54
54
  return context;
55
55
  }
56
56
  function handleHelpReview(argv, harnessVersion2) {
57
- const parsed = parseArgs(argv, "help");
57
+ const parsed = parseArgs(argv);
58
58
  const context = resolveReviewContext(parsed.options, { fetch: false });
59
59
  const input = {
60
60
  adapter: context.adapter,
@@ -73,7 +73,7 @@ function handleHelpReview(argv, harnessVersion2) {
73
73
  return EXIT_OK;
74
74
  }
75
75
  async function handleReview(argv, version = harnessVersion()) {
76
- const parsed = parseArgs(argv, "review");
76
+ const parsed = parseArgs(argv);
77
77
  const subcommand = parsed.positional[0];
78
78
  if (subcommand !== "checklist") {
79
79
  throw usageError("Usage: mm-harness review checklist [--domain <name>] [--since <sha>] [--base <ref>] [--out <file>] [--json]");
@@ -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,14 +1,10 @@
1
+ import { optionFlag, optionString, requiredOption, runRecipe } 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
- import { runRecipe } from "./run-engine.js";
7
+ import { metaMaskEngine } from "../engine.js";
12
8
  async function handleSelfTest({ options }) {
13
9
  const result = await runSelfTest(options);
14
10
  if (optionFlag(options, "json")) console.log(JSON.stringify(result, null, 2));
@@ -27,8 +23,9 @@ async function runSelfTest(options) {
27
23
  const manifestValidation = await validateManifest(manifest);
28
24
  const smokeRecipe = recipePath(`${adapter}/runner/smoke.recipe.json`);
29
25
  const artifactsDir = path.join(root, adapter);
30
- const result = await runRecipe(adapter, smokeRecipe, artifactsDir, runnerDir, void 0, {
31
- skipExtensionRuntimePrepare: true
26
+ const result = await runRecipe(metaMaskEngine, adapter, smokeRecipe, artifactsDir, runnerDir, void 0, {
27
+ cli: { adapter },
28
+ platform: { skipExtensionRuntimePrepare: true }
32
29
  });
33
30
  runs.push({ adapter, manifestValidation: manifestValidation.summary, artifactsDir, result });
34
31
  }
@@ -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) {