@deeeed/metamask-harness 0.14.5 → 0.14.7

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 (57) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/adapters/core/cleanup.sh +0 -0
  3. package/adapters/core/inject.sh +0 -0
  4. package/adapters/extension/cleanup.mjs +0 -0
  5. package/adapters/extension/ensure-browser.sh +0 -0
  6. package/adapters/extension/inject.mjs +0 -0
  7. package/adapters/extension/launch-browser.cjs +0 -0
  8. package/adapters/extension/launch.sh +0 -0
  9. package/adapters/extension/live.sh +0 -0
  10. package/adapters/extension/readiness.mjs +0 -0
  11. package/adapters/extension/reattach.sh +0 -0
  12. package/adapters/extension/refresh-build.sh +0 -0
  13. package/adapters/extension/seed-fixture.sh +0 -0
  14. package/adapters/extension/sidepanel-toggle.sh +0 -0
  15. package/adapters/extension/snapshot-dist.sh +0 -0
  16. package/adapters/extension/start-watch.sh +0 -0
  17. package/adapters/extension/stop-viewers.sh +0 -0
  18. package/adapters/extension/verify.sh +0 -0
  19. package/adapters/extension/wallet-fixture-state.cjs +0 -0
  20. package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +0 -0
  21. package/adapters/mobile/bridge-runtime/setup-wallet.sh +0 -0
  22. package/adapters/mobile/cleanup.sh +0 -0
  23. package/adapters/mobile/inject.sh +0 -0
  24. package/adapters/mobile/lib/metro-listener.sh +0 -0
  25. package/adapters/mobile/lib/tmux-viewer.sh +0 -0
  26. package/adapters/mobile/open-device.sh +0 -0
  27. package/adapters/mobile/prewarm-bundle.sh +0 -0
  28. package/adapters/mobile/start-metro.sh +0 -0
  29. package/adapters/mobile/stop-metro.sh +0 -0
  30. package/adapters/mobile/verify.sh +0 -0
  31. package/adapters/mobile/wait-for-bridge.sh +0 -0
  32. package/adapters/mobile/yarn-setup.sh +0 -0
  33. package/adapters/shared/activate-repo-node.sh +0 -0
  34. package/adapters/shared/activate-repo-ruby.sh +0 -0
  35. package/adapters/shared/cli-ux.sh +0 -0
  36. package/adapters/shared/ensure-runner-deps.sh +0 -0
  37. package/adapters/shared/harness-path.sh +0 -0
  38. package/adapters/shared/hash-helpers.sh +0 -0
  39. package/adapters/shared/json-field.sh +0 -0
  40. package/adapters/shared/open-log-window.sh +0 -0
  41. package/adapters/shared/reap-checkout-metros.sh +0 -0
  42. package/adapters/shared/resolve-farmslot-ports.mjs +0 -0
  43. package/adapters/shared/resolve-farmslot-ports.sh +0 -0
  44. package/adapters/shared/resolve-slot-ports.mjs +0 -0
  45. package/adapters/shared/resolve-slot-ports.sh +0 -0
  46. package/adapters/shared/sync-wallet-fixture.sh +0 -0
  47. package/adapters/shared/tmux-session.sh +0 -0
  48. package/adapters/shared/tmux-viewer.sh +0 -0
  49. package/dist/adapters/mobile/surface.js +2 -1
  50. package/dist/cli-commands.js +1 -1
  51. package/dist/commands/doctor.js +47 -7
  52. package/dist/commands/farmslot-ready.js +25 -0
  53. package/dist/commands/parse-args.js +1 -0
  54. package/dist/mm-harness-cli.js +4 -3
  55. package/package.json +2 -2
  56. package/scripts/completions.sh +0 -0
  57. package/scripts/install-completions.sh +0 -0
package/CHANGELOG.md CHANGED
@@ -1,6 +1,21 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.14.7 - 2026-07-10
4
+
5
+ ### Changed
6
+ - `doctor --print-ready` now implies the exit-coded live probe — Farmslot `health_check` hooks need only `--print-ready`, not `--expect-live --print-ready`.
7
+ - Mobile `--print-ready` uses bridge `walletState` (unlocked + live bridge), not React Navigation route names; mobile `ready_indicator` is `OK`.
8
+ - Removed `metamask-recipe` install symlinks from adapter inject paths (no compat aliases).
9
+ - `doctor --print-ready` rejects `--json` (stdout is reserved for the Farmslot indicator line).
10
+
11
+ ### Fixed
12
+ - Mobile `surface.runtimeStatus` infers Android from `ADB_SERIAL` / `ANDROID_SERIAL` when present.
13
+
14
+ ## 0.14.6 - 2026-07-10
15
+
16
+ ### Added
17
+ - `mm-harness doctor --print-ready` — Farmslot `health_check` mode: prints `health.ready_indicator` on stdout (`extension`/`mobile`: `OK`; `core`: `ready`).
18
+ - `doctor --expect-live` — exit-coded liveness gate without indicator output (prepare recovery and other pass/fail callers).
4
19
 
5
20
  ## 0.14.5 - 2026-07-10
6
21
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -12,7 +12,8 @@ const mobileSurface = {
12
12
  },
13
13
  async runtimeStatus(target) {
14
14
  const watcherPort = process.env.WATCHER_PORT ? parseInt(process.env.WATCHER_PORT, 10) : void 0;
15
- const report = await mobileRuntimeStatus(target, { watcherPort });
15
+ const platform = process.env.ADB_SERIAL || process.env.ANDROID_SERIAL ? "android" : "ios";
16
+ const report = await mobileRuntimeStatus(target, { watcherPort, platform });
16
17
  const runwayProvisioned = hasRunwayProvisionBaseline(target);
17
18
  const depsPending = runwayProvisioned && report.checks?.deps?.status !== "current";
18
19
  return {
@@ -16,7 +16,7 @@ const SPEC = {
16
16
  { name: "debug", aliases: ["devtools", "inspect"], desc: "Open DevTools UI", flags: ["--json", "--no-open"] },
17
17
  { name: "fixtures", desc: "Manage the canonical wallet fixture (sync/set/generate)", args: ["sync", "set", "generate"], flags: ["--fixture", "--out", "--adapter", "--target", "--device", "--json"] },
18
18
  { name: "actions", desc: "List runnable recipe actions", flags: ["--json"] },
19
- { name: "doctor", desc: "Check harness/orchestration health", flags: ["--json", "--target", "--adapter", "--runtime-dir", "--expect-live", "--cdp-port", "--device"] },
19
+ { name: "doctor", desc: "Check harness/orchestration health", flags: ["--json", "--target", "--adapter", "--runtime-dir", "--expect-live", "--print-ready", "--cdp-port", "--device"] },
20
20
  { name: "run", desc: "Execute a proof recipe (path or library name, e.g. run perps.smoke)", args: ["recipe.json|name"], flags: ["--list", "--device"] },
21
21
  { name: "recipe-quality", desc: "Build the recipe-quality artifact from compact JSON", args: ["build"], flags: ["--input", "--output", "--json"] },
22
22
  { name: "interactive", aliases: ["menu"], desc: "Interactive command menu" },
@@ -15,6 +15,7 @@ import {
15
15
  renderMobileDeviceList,
16
16
  renderMobileLiveBlock
17
17
  } from "./mobile-device-view.js";
18
+ import { farmslotReadyIndicator } from "./farmslot-ready.js";
18
19
  import { ADAPTER_DETECT_NEXT, EXIT, usageOut } from "./shared.js";
19
20
  import {
20
21
  actionManifestPathOption,
@@ -40,7 +41,8 @@ async function handleDoctor({ options }) {
40
41
  applyRuntimeDirOption(options);
41
42
  const target = targetPath(options);
42
43
  const json = optionFlag(options, "json");
43
- const expectLive = optionFlag(options, "expectLive");
44
+ const printReady = optionFlag(options, "printReady");
45
+ const expectLive = optionFlag(options, "expectLive") || printReady;
44
46
  const allDevices = optionFlag(options, "allDevices");
45
47
  const platformOption = optionString(options, "platform");
46
48
  const explicitAdapter = optionString(options, "adapter") ?? (platformOption === "ios" || platformOption === "android" ? "mobile" : platformOption);
@@ -49,6 +51,14 @@ async function handleDoctor({ options }) {
49
51
  return usageOut(json, "doctor", `could not detect the MetaMask repo type for ${target}`, ADAPTER_DETECT_NEXT);
50
52
  }
51
53
  assertAdapter(adapter);
54
+ if (printReady && json) {
55
+ return usageOut(
56
+ json,
57
+ "doctor",
58
+ "--print-ready owns stdout for Farmslot health_check; drop --json (use --expect-live --json for the doctor envelope)",
59
+ "mm-harness doctor --print-ready --adapter <adapter> --target <path>"
60
+ );
61
+ }
52
62
  const actionManifestPath = actionManifestPathOption(options, adapter);
53
63
  const manifest = loadActionManifest(adapter, optionString(options, "actionManifest"));
54
64
  const manifestValidation = await validateManifest(manifest);
@@ -80,7 +90,20 @@ async function handleDoctor({ options }) {
80
90
  const liveView = deviceView ? await mobileDeviceLiveView(target, deviceView) : null;
81
91
  const devices = liveView?.devicesWithLive ?? deviceView?.devices ?? [];
82
92
  const additionalReachableDevices = liveView?.additionalReachableDevices ?? [];
83
- if (expectLive) return emitExpectLive(adapter, target, runtime, result, orphanMetros, capture, devices, additionalReachableDevices, json);
93
+ if (expectLive) {
94
+ return emitExpectLive(
95
+ adapter,
96
+ target,
97
+ runtime,
98
+ result,
99
+ orphanMetros,
100
+ capture,
101
+ devices,
102
+ additionalReachableDevices,
103
+ json,
104
+ printReady
105
+ );
106
+ }
84
107
  if (json) console.log(JSON.stringify({ ...result, runtime, orphanMetros, capture, devices, additionalReachableDevices }, null, 2));
85
108
  else {
86
109
  const out = (style, text) => color(style, text, { stream: process.stdout });
@@ -119,8 +142,28 @@ async function handleDoctor({ options }) {
119
142
  }
120
143
  return result.status === "pass" ? 0 : 1;
121
144
  }
122
- function emitExpectLive(adapter, target, runtime, result, orphanMetros, capture, devices, additionalReachableDevices, json) {
145
+ function emitExpectLiveVerdict(adapter, target, runtime, verdict) {
146
+ const out = (style, text) => color(style, text, { stream: process.stderr });
147
+ const detail = runtime ? `${runtime.decision}${runtime.reasonCode ? ` (${runtime.reasonCode})` : ""}` : "runtime probe unavailable";
148
+ console.error(`${out("err", verdict)} ${out("bold", adapter)} ${detail} ${out("dim", target)}`);
149
+ for (const reason of runtime?.reasons ?? []) console.error(` ${out("dim", reason)}`);
150
+ console.error(` Next: ${getAdapterSurface(adapter).hints.relaunch}`);
151
+ }
152
+ function emitExpectLive(adapter, target, runtime, result, orphanMetros, capture, devices, additionalReachableDevices, json, printReady) {
123
153
  const live = runtime?.decision === "ready";
154
+ if (printReady) {
155
+ if (live) {
156
+ const indicator = farmslotReadyIndicator(adapter, devices);
157
+ if (indicator) {
158
+ console.log(indicator);
159
+ return EXIT.ok;
160
+ }
161
+ emitExpectLiveVerdict(adapter, target, runtime, "not-ready");
162
+ return EXIT.runtime;
163
+ }
164
+ emitExpectLiveVerdict(adapter, target, runtime, "not-live");
165
+ return EXIT.runtime;
166
+ }
124
167
  if (json) {
125
168
  console.log(JSON.stringify({ ...result, runtime, orphanMetros, capture, devices, additionalReachableDevices }, null, 2));
126
169
  return live ? EXIT.ok : EXIT.runtime;
@@ -130,10 +173,7 @@ function emitExpectLive(adapter, target, runtime, result, orphanMetros, capture,
130
173
  console.log(`${out("ok", "live")} ${out("bold", adapter)} runtime ready`);
131
174
  return EXIT.ok;
132
175
  }
133
- const detail = runtime ? `${runtime.decision}${runtime.reasonCode ? ` (${runtime.reasonCode})` : ""}` : "runtime probe unavailable";
134
- console.error(`${out("err", "not-live")} ${out("bold", adapter)} ${detail} ${out("dim", target)}`);
135
- for (const reason of runtime?.reasons ?? []) console.error(` ${out("dim", reason)}`);
136
- console.error(` Next: ${getAdapterSurface(adapter).hints.relaunch}`);
176
+ emitExpectLiveVerdict(adapter, target, runtime, "not-live");
137
177
  return EXIT.runtime;
138
178
  }
139
179
  function captureHelperHealth() {
@@ -0,0 +1,25 @@
1
+ function selectedDevice(devices) {
2
+ return devices.find((d) => d.selected) ?? devices[0];
3
+ }
4
+ function mobileWalletReady(device) {
5
+ if (device.liveState === "no-bridge" || device.liveState === "bridge-absent") return false;
6
+ return device.walletState === "unlocked";
7
+ }
8
+ function farmslotReadyIndicator(adapter, devices) {
9
+ switch (adapter) {
10
+ case "extension":
11
+ return "OK";
12
+ case "core":
13
+ return "ready";
14
+ case "mobile": {
15
+ const device = selectedDevice(devices);
16
+ if (!device) return "";
17
+ return mobileWalletReady(device) ? "OK" : "";
18
+ }
19
+ default:
20
+ return "";
21
+ }
22
+ }
23
+ export {
24
+ farmslotReadyIndicator
25
+ };
@@ -29,6 +29,7 @@ function parseArgs(argv, command) {
29
29
  "force",
30
30
  "resolveOnly",
31
31
  "expectLive",
32
+ "printReady",
32
33
  "fast",
33
34
  "allDevices",
34
35
  "help"
@@ -171,19 +171,20 @@ Example:
171
171
  sections so there is no hunting for files.
172
172
 
173
173
  --fix Repair the overlay/runtime-context WITHOUT launching (no fixture reseed); --json adds fixed[]/failed[]
174
- --expect-live Exit 0 iff the runtime is live (extension: watcher+CDP; mobile: Metro+bridge; core: deps), non-zero + teaching escape otherwise
174
+ --expect-live Exit-coded liveness gate only (human verdict on stderr). Use without --print-ready when callers need pass/fail without a Farmslot indicator line
175
+ --print-ready Farmslot health_check mode: implies --expect-live and prints health.ready_indicator on stdout (extension/mobile: OK; core: ready)
175
176
  --cdp-port <port> Extension CDP port for the liveness probe (env: CDP_PORT / RECIPE_CDP_PORT)
176
177
  --device <udid|serial|name> Mobile only: target this device (env: IOS_SIMULATOR / ADB_SERIAL). doctor reports the connected devices; it never gates on ambiguity.
177
178
  --all-devices Mobile only: show every connected device instead of the slot-scoped target
178
179
  --adapter <mobile|extension|core> Target adapter (auto-detected inside a checkout)
179
180
  --target <path> Checkout path (default: cwd)
180
181
  --runtime-dir <dir> Runtime dir containing agentic-runtime.json (relative to target)
181
- --json Machine-readable output
182
+ --json Machine-readable output (incompatible with --print-ready)
182
183
 
183
184
  Example:
184
185
  mm-harness doctor
185
186
  mm-harness doctor --fix --json
186
- mm-harness doctor --adapter extension --target /path/to/checkout --cdp-port 6662 --expect-live
187
+ mm-harness doctor --adapter extension --target /path/to/checkout --cdp-port 6662 --print-ready
187
188
  mm-harness doctor --adapter mobile --target /path/to/checkout`
188
189
  },
189
190
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeeed/metamask-harness",
3
- "version": "0.14.5",
3
+ "version": "0.14.7",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mm-harness": "bin/mm-harness"
@@ -70,4 +70,4 @@
70
70
  "url": "https://github.com/MetaMask/experimental-metamask-harness/issues"
71
71
  },
72
72
  "homepage": "https://github.com/MetaMask/experimental-metamask-harness#readme"
73
- }
73
+ }
File without changes
File without changes