@deeeed/metamask-harness 0.79.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 (210) hide show
  1. package/CHANGELOG.md +47 -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/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/bin/mm-harness +9 -28
  26. package/dist/adapters/checkout-files.js +16 -0
  27. package/dist/adapters/console-capture.js +14 -1
  28. package/dist/adapters/core/actions.js +4 -3
  29. package/dist/adapters/core/overlay.js +1 -1
  30. package/dist/adapters/core/readiness.js +28 -1
  31. package/dist/adapters/core/run.js +2 -2
  32. package/dist/adapters/core/surface.js +16 -1
  33. package/dist/adapters/extension/browser-pid.js +56 -0
  34. package/dist/adapters/extension/console-capture.js +1 -1
  35. package/dist/adapters/extension/doctor-checks.js +1 -1
  36. package/dist/adapters/extension/ensure-ready.js +5 -4
  37. package/dist/adapters/extension/extension-id.js +1 -1
  38. package/dist/adapters/extension/feature-flags.js +1 -1
  39. package/dist/adapters/extension/fixtures.js +1 -2
  40. package/dist/adapters/extension/launch.js +4 -5
  41. package/dist/adapters/extension/launched-browser.js +1 -2
  42. package/dist/adapters/extension/network-observer.js +1 -1
  43. package/dist/adapters/extension/overlay.js +1 -1
  44. package/dist/adapters/extension/product-config.js +1 -1
  45. package/dist/adapters/extension/readiness.js +1 -1
  46. package/dist/adapters/extension/reload.js +1 -1
  47. package/dist/adapters/extension/run.js +24 -10
  48. package/dist/adapters/extension/runtime-decision.js +2 -1
  49. package/dist/adapters/extension/runtime.js +9 -5
  50. package/dist/adapters/extension/surface.js +15 -2
  51. package/dist/adapters/extension/verify.js +2 -2
  52. package/dist/adapters/harness-freshness.js +2 -1
  53. package/dist/adapters/mobile/android-gfxinfo-performance.js +1 -3
  54. package/dist/adapters/mobile/app-identity.js +10 -0
  55. package/dist/adapters/mobile/doctor-checks.js +1 -1
  56. package/dist/adapters/mobile/fixtures.js +1 -1
  57. package/dist/adapters/mobile/launch.js +27 -28
  58. package/dist/adapters/mobile/lifecycle.js +1 -1
  59. package/dist/adapters/mobile/metro-env.js +9 -59
  60. package/dist/adapters/mobile/performance-observer.js +1 -1
  61. package/dist/adapters/mobile/prepare-target.js +1 -1
  62. package/dist/adapters/mobile/prepare.js +3 -4
  63. package/dist/adapters/mobile/provision.js +1 -1
  64. package/dist/adapters/mobile/readiness.js +1 -1
  65. package/dist/adapters/mobile/recording-target.js +15 -0
  66. package/dist/adapters/mobile/release-artifact-state.js +1 -1
  67. package/dist/adapters/mobile/reload.js +1 -1
  68. package/dist/adapters/mobile/run.js +8 -7
  69. package/dist/adapters/mobile/runtime-decision.js +2 -4
  70. package/dist/adapters/mobile/source-freshness.js +22 -126
  71. package/dist/adapters/mobile/surface.js +26 -3
  72. package/dist/adapters/mobile/ui.js +16 -5
  73. package/dist/adapters/mobile/verify.js +2 -3
  74. package/dist/adapters/performance/cdp-trace.js +1 -1
  75. package/dist/adapters/performance/device-platform.js +1 -1
  76. package/dist/adapters/slot-ports.js +1 -1
  77. package/dist/adapters/surface.js +1 -0
  78. package/dist/adapters/terminal/console-capture.js +1 -1
  79. package/dist/adapters/terminal/launch.js +1 -1
  80. package/dist/adapters/terminal/run.js +25 -2
  81. package/dist/adapters/terminal/surface.js +7 -1
  82. package/dist/adapters.js +8 -4
  83. package/dist/advisor-policy.js +1 -1
  84. package/dist/checkout-view.js +1 -2
  85. package/dist/cli.js +28 -15
  86. package/dist/command-contract.js +1 -26
  87. package/dist/commands/call.js +10 -24
  88. package/dist/commands/check.js +3 -4
  89. package/dist/commands/checklist.js +1 -1
  90. package/dist/commands/completion-candidates.js +2 -10
  91. package/dist/commands/config.js +2 -2
  92. package/dist/commands/core-readiness.js +12 -7
  93. package/dist/commands/debug.js +3 -3
  94. package/dist/commands/device-target.js +5 -5
  95. package/dist/commands/doctor.js +2 -14
  96. package/dist/commands/domain.js +2 -2
  97. package/dist/commands/ensure-ready.js +1 -7
  98. package/dist/commands/fixtures.js +5 -6
  99. package/dist/commands/help.js +3 -4
  100. package/dist/commands/launch/device.js +10 -17
  101. package/dist/commands/launch/extension.js +2 -8
  102. package/dist/commands/launch/mobile.js +1 -1
  103. package/dist/commands/list-executables.js +1 -3
  104. package/dist/commands/logs.js +3 -3
  105. package/dist/commands/manifest.js +1 -12
  106. package/dist/commands/mobile-device-view.js +4 -2
  107. package/dist/commands/overlay.js +110 -0
  108. package/dist/commands/pin.js +1 -1
  109. package/dist/commands/pr-body.js +2 -2
  110. package/dist/commands/prepare.js +4 -9
  111. package/dist/commands/provision.js +3 -12
  112. package/dist/commands/recipe-advice.js +1 -2
  113. package/dist/commands/recipe-quality.js +2 -3
  114. package/dist/commands/resolve-extension.js +1 -7
  115. package/dist/commands/review.js +4 -4
  116. package/dist/commands/run-engine.js +12 -51
  117. package/dist/commands/run.js +4 -25
  118. package/dist/commands/runtime-decision.js +1 -6
  119. package/dist/commands/runtime-health.js +1 -7
  120. package/dist/commands/runtime-launch.js +1 -13
  121. package/dist/commands/self-test.js +2 -6
  122. package/dist/commands/status-watch.js +1 -2
  123. package/dist/commands/status.js +2 -5
  124. package/dist/commands/task-init.js +2 -3
  125. package/dist/commands/tutorial.js +2 -2
  126. package/dist/commands/update.js +1 -1
  127. package/dist/completions-cache.js +1 -1
  128. package/dist/console-classifier.js +19 -0
  129. package/dist/doctor.js +2 -3
  130. package/dist/funding-execution-context.js +15 -1
  131. package/dist/host.js +32 -0
  132. package/dist/index.js +1 -6
  133. package/dist/live-tsx.js +49 -0
  134. package/dist/mm-harness-cli.js +2 -4
  135. package/dist/network-observation.js +4 -4
  136. package/dist/paths.js +34 -64
  137. package/dist/performance-observation.js +2 -2
  138. package/dist/progress.js +1 -1
  139. package/dist/recipe-assistance-context.js +1 -3
  140. package/dist/recipe-security.js +2 -59
  141. package/dist/review/knowledge.js +2 -2
  142. package/dist/runner.js +5 -3
  143. package/dist/runtime-context.js +1 -1
  144. package/dist/task-view.js +2 -3
  145. package/docs/CONTRIBUTING.md +1 -1
  146. package/docs/cli-contract.md +2 -2
  147. package/docs/feature-guard.md +90 -0
  148. package/library/README.md +3 -1
  149. package/library/actions/core/perps/_controller.mjs +153 -130
  150. package/library/actions/core/perps/quote_fees.mjs +58 -0
  151. package/library/actions/core/wallet/_fixture-accounts.mjs +69 -0
  152. package/library/actions/core/wallet/list_accounts.mjs +14 -57
  153. package/library/actions/extension/feature_flags/state.mjs +1 -1
  154. package/library/actions/extension/platform/cdp.mjs +2 -8
  155. package/library/actions/harness-exports.mjs +1 -6
  156. package/library/actions/mobile/app/network-control.mjs +6 -8
  157. package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +1 -1
  158. package/library/actions/mobile/platform/bridge.mjs +8 -8
  159. package/library/actions/mobile/platform/native-session-name.mjs +21 -1
  160. package/library/actions/mobile/platform/native-session.mjs +3 -4
  161. package/library/actions/mobile/platform/observe-ui.mjs +12 -6
  162. package/library/actions/mobile/ui/native-navigation.mjs +4 -3
  163. package/library/actions/mobile/wallet/native-ui.mjs +3 -2
  164. package/library/actions/shared/analytics/_adapter.mjs +1 -1
  165. package/library/actions/shared/console-findings.mjs +1 -1
  166. package/library/actions/terminal/platform/runtime.mjs +2 -1
  167. package/library/manifests/core.action-manifest.json +83 -13
  168. package/package.json +8 -9
  169. package/adapters/extension/lib/slot-title.cjs +0 -292
  170. package/adapters/mobile/bridge-runtime/console-forwarder.cjs +0 -472
  171. package/adapters/mobile/bridge-runtime/lib/bridge-errors.cjs +0 -125
  172. package/adapters/mobile/bridge-runtime/lib/cdp-broker.cjs +0 -1055
  173. package/adapters/mobile/bridge-runtime/lib/cdp-eval.cjs +0 -110
  174. package/adapters/mobile/bridge-runtime/lib/config.cjs +0 -61
  175. package/adapters/mobile/bridge-runtime/lib/console-format.cjs +0 -53
  176. package/adapters/mobile/bridge-runtime/lib/devtools-proxy.cjs +0 -177
  177. package/adapters/mobile/bridge-runtime/lib/issue-capture.cjs +0 -446
  178. package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +0 -84
  179. package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +0 -403
  180. package/adapters/mobile/bridge-runtime/lib/ws-client.cjs +0 -116
  181. package/adapters/mobile/coalesce-metro-log.cjs +0 -24
  182. package/adapters/mobile/launch-metro.cjs +0 -77
  183. package/adapters/mobile/metro-config.cjs +0 -98
  184. package/adapters/mobile/metro-log-generation.cjs +0 -106
  185. package/dist/adapters/mobile/frame-metrics.js +0 -118
  186. package/dist/adapters/mobile/video-recorder.js +0 -289
  187. package/dist/artifact-files.js +0 -92
  188. package/dist/checkout-lock.js +0 -149
  189. package/dist/cli-color.js +0 -98
  190. package/dist/command-journal.js +0 -308
  191. package/dist/commands/last.js +0 -60
  192. package/dist/commands/launch/index.js +0 -109
  193. package/dist/commands/parse-args.js +0 -279
  194. package/dist/commands/reload.js +0 -41
  195. package/dist/commands/run-report.js +0 -241
  196. package/dist/commands/shared.js +0 -323
  197. package/dist/commands/stop.js +0 -60
  198. package/dist/devices.js +0 -100
  199. package/dist/execution-provenance.js +0 -332
  200. package/dist/harness.js +0 -451
  201. package/dist/heal-bounds.js +0 -137
  202. package/dist/json-stream.js +0 -60
  203. package/dist/leaf-invoke.js +0 -19
  204. package/dist/library-provenance.js +0 -33
  205. package/dist/live-adapter-contract.js +0 -380
  206. package/dist/recording-target.js +0 -120
  207. package/dist/run-diagnostics.js +0 -364
  208. package/dist/run-recording.js +0 -481
  209. package/dist/runtime-proof.js +0 -90
  210. package/library/actions/mobile/platform/tool-paths.mjs +0 -123
@@ -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");
@@ -2,9 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { resolveActionManifest } from "../manifest.js";
4
4
  import { importRecipeProtocol } from "../paths.js";
5
- import { color } from "../cli-color.js";
6
- import { EXIT } from "./shared.js";
7
- import { optionFlag, optionString, optionStrings, resolveAdapter, shellQuoteArg } from "./parse-args.js";
5
+ import { color, EXIT, optionFlag, optionString, optionStrings, resolveAdapter, shellQuoteArg } from "@farmslot/recipe-cli/harness";
8
6
  import { actionDomain, describeManifestActions, renderHumanActionCatalog } from "./manifest.js";
9
7
  import { shortActionNames } from "@farmslot/recipe-cli";
10
8
  import {
@@ -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,22 +1,11 @@
1
1
  import { resolveActionManifest } from "../manifest.js";
2
- import { color } from "../cli-color.js";
3
- import { EXIT } from "./shared.js";
4
- import {
5
- isRecord,
6
- optionFlag,
7
- optionString,
8
- optionStrings,
9
- resolveAdapter,
10
- shellQuoteArg
11
- } from "./parse-args.js";
2
+ import { closest, color, isSensitiveKey, redactStructuredValue, EXIT, isRecord, optionFlag, optionString, optionStrings, resolveAdapter, shellQuoteArg } from "@farmslot/recipe-cli/harness";
12
3
  import { resolveMetaMaskLibrarySources } from "./run-engine.js";
13
- import { isSensitiveKey, redactStructuredValue } from "../command-journal.js";
14
4
  import {
15
5
  OFFICIAL_RECIPE_ACTIONS,
16
6
  officialRecipeActionCapabilities
17
7
  } from "@farmslot/protocol";
18
8
  import { metaMaskActionExecutionCapabilities } from "../recipe-security.js";
19
- import { closest } from "../command-contract.js";
20
9
  import {
21
10
  actionCapabilityMatrix,
22
11
  actionCategory,
@@ -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]");
@@ -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";