@deeeed/metamask-harness 0.83.0 → 0.85.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.
- package/CHANGELOG.md +62 -0
- package/README.md +8 -1
- package/adapters/extension/console-tail.mjs +11 -7
- package/adapters/extension/ensure-browser.sh +17 -18
- package/adapters/manifest.json +14 -110
- package/adapters/mobile/start-console-forwarder.sh +8 -0
- package/adapters/shared/resolve-slot-ports-core.mjs +48 -6
- package/adapters/shared/session-lock.mjs +43 -0
- package/adapters/web-dapp/metamask-signer.mjs +212 -0
- package/dist/adapters/extension/actions.js +5 -0
- package/dist/adapters/extension/console-capture.js +18 -0
- package/dist/adapters/extension/fixtures.js +2 -0
- package/dist/adapters/extension/overlay.js +5 -4
- package/dist/adapters/extension/run.js +4 -2
- package/dist/adapters/extension/runtime.js +73 -18
- package/dist/adapters/mobile/devices.js +5 -1
- package/dist/adapters/mobile/launch.js +19 -2
- package/dist/adapters/mobile/provision.js +4 -2
- package/dist/adapters/mobile/run.js +3 -2
- package/dist/adapters/mobile/surface.js +1 -2
- package/dist/adapters/mobile/verify.js +15 -7
- package/dist/adapters/plugin-surface.js +14 -42
- package/dist/adapters/session-lock.js +23 -0
- package/dist/adapters/web-dapp/actions.js +7 -5
- package/dist/adapters/web-dapp/console-capture.js +2 -20
- package/dist/adapters/web-dapp/run.js +25 -24
- package/dist/adapters/web-dapp/surface.js +32 -108
- package/dist/adapters.js +5 -3
- package/dist/command-contract.js +1351 -643
- package/dist/commands/check.js +5 -7
- package/dist/commands/debug.js +2 -2
- package/dist/commands/doctor.js +3 -4
- package/dist/commands/domain.js +4 -3
- package/dist/commands/fixtures.js +3 -3
- package/dist/commands/help.js +6 -5
- package/dist/commands/launch/device.js +1 -1
- package/dist/commands/launch/extension.js +9 -7
- package/dist/commands/logs.js +2 -2
- package/dist/commands/prepare.js +4 -4
- package/dist/commands/provision.js +2 -2
- package/dist/commands/review.js +8 -10
- package/dist/commands/runtime-launch.js +2 -0
- package/dist/commands/status.js +4 -2
- package/dist/commands/task-init.js +2 -3
- package/dist/console-classifier.js +3 -2
- package/dist/doctor.js +11 -4
- package/dist/mm-harness-cli.js +241 -1210
- package/dist/paths.js +9 -4
- package/dist/recipe-security.js +1 -1
- package/dist/review/knowledge.js +10 -2
- package/dist/runner.js +18 -3
- package/docs/CONTRIBUTING.md +14 -4
- package/docs/RECIPES.md +14 -1
- package/docs/cli-contract.md +8 -7
- package/docs/feature-guard.md +1 -1
- package/library/actions/extension/app/assert_no_console_errors.mjs +95 -0
- package/library/actions/extension/platform/cdp.mjs +26 -0
- package/library/actions/mobile/app/assert_no_console_errors.mjs +129 -0
- package/library/actions/shared/console-assert.mjs +174 -0
- package/library/actions/shared/console-collector.mjs +11 -4
- package/library/actions/shared/console-findings.mjs +108 -7
- package/library/actions/web-dapp/app/assert_no_console_errors.mjs +10 -54
- package/library/actions/web-dapp/app/launch.mjs +1 -1
- package/library/actions/web-dapp/platform/adapter-web-lib.mjs +18 -0
- package/library/actions/web-dapp/platform/hud.mjs +3 -10
- package/library/actions/web-dapp/platform/page.mjs +63 -18
- package/library/actions/web-dapp/platform/runtime.mjs +30 -179
- package/library/diagnostics/console-allowlist.json +13 -0
- package/library/manifests/extension.action-manifest.json +36 -0
- package/library/manifests/mobile.action-manifest.json +36 -0
- package/library/manifests/web-dapp.action-manifest.json +1 -1
- package/library/recipes/core/health/check.recipe.json +40 -0
- package/library/recipes/extension/health/check.recipe.json +71 -0
- package/library/recipes/mobile/health/check.recipe.json +71 -0
- package/package.json +9 -9
- package/scripts/completions.sh +1 -1
- package/site/assets/help-recipes.json +2 -1
- package/adapters/web-dapp/cleanup.mjs +0 -69
- package/adapters/web-dapp/inject.mjs +0 -75
- package/adapters/web-dapp/launch.mjs +0 -631
- package/adapters/web-dapp/lib/blocked-hosts.mjs +0 -24
- package/adapters/web-dapp/lib/cdp-client.mjs +0 -84
- package/adapters/web-dapp/lib/display.mjs +0 -115
- package/adapters/web-dapp/lib/hud.mjs +0 -148
- package/adapters/web-dapp/lib/policy-fence.mjs +0 -119
- package/adapters/web-dapp/lib/policy.mjs +0 -84
- package/adapters/web-dapp/lib/processes.mjs +0 -187
- package/adapters/web-dapp/lib/readiness.mjs +0 -272
- package/adapters/web-dapp/stop.mjs +0 -38
- package/adapters/web-dapp/verify.mjs +0 -51
- package/adapters/web-dapp/wallet-host.mjs +0 -520
- package/dist/adapters/web-dapp/doctor-checks.js +0 -33
- package/dist/adapters/web-dapp/launch.js +0 -87
- package/dist/adapters/web-dapp/overlay.js +0 -21
- package/dist/adapters/web-dapp/readiness.js +0 -10
- package/dist/adapters/web-dapp/stop.js +0 -20
- package/dist/cli.js +0 -202
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { POLICY_ENV, webDappPolicy } from "../../../adapters/web-dapp/lib/policy.mjs";
|
|
2
|
-
const webDappReadiness = {
|
|
3
|
-
compatibilityMode: (target) => process.env[POLICY_ENV] && webDappPolicy().checkout.matches(target) ? "slot browser over CDP (website; no product bridge)" : "unsupported/no bridge",
|
|
4
|
-
liveChecks: async (target) => (await import("./doctor-checks.js")).webDappDoctorChecks(target),
|
|
5
|
-
// Screenshots come from the slot browser over CDP.
|
|
6
|
-
captureProviders: ["cdp"]
|
|
7
|
-
};
|
|
8
|
-
export {
|
|
9
|
-
webDappReadiness
|
|
10
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { runnerDir } from "../../paths.js";
|
|
4
|
-
import { webDappAdapterId } from "../../../adapters/web-dapp/lib/policy.mjs";
|
|
5
|
-
function stopWebDappBrowserSync(target) {
|
|
6
|
-
const args = [path.join(runnerDir, "adapters", "web-dapp", "stop.mjs"), "--target", path.resolve(target)];
|
|
7
|
-
const cdpPort = process.env.RECIPE_CDP_PORT ?? process.env.CDP_PORT;
|
|
8
|
-
if (cdpPort) args.push("--cdp-port", cdpPort);
|
|
9
|
-
const result = spawnSync(process.execPath, args, { encoding: "utf8" });
|
|
10
|
-
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
11
|
-
const status = result.status ?? 1;
|
|
12
|
-
return {
|
|
13
|
-
status,
|
|
14
|
-
summary: status === 0 ? `${webDappAdapterId()} browser and wallet host stopped` : `${webDappAdapterId()} browser stop failed`,
|
|
15
|
-
output
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
export {
|
|
19
|
-
stopWebDappBrowserSync
|
|
20
|
-
};
|
package/dist/cli.js
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import "./host.js";
|
|
2
|
-
import "./adapters/surface.js";
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import {
|
|
5
|
-
detectAdapter,
|
|
6
|
-
handleActions,
|
|
7
|
-
handleCall,
|
|
8
|
-
handleHarness,
|
|
9
|
-
handleLast,
|
|
10
|
-
handleLaunch,
|
|
11
|
-
handleReload,
|
|
12
|
-
handleRun,
|
|
13
|
-
handleStop,
|
|
14
|
-
parseArgs,
|
|
15
|
-
targetPath
|
|
16
|
-
} from "@farmslot/recipe-cli/harness";
|
|
17
|
-
import { stopProjectCollector } from "../library/actions/shared/analytics/collector.mjs";
|
|
18
|
-
import { loadSelectedAdapter } from "./adapters/plugin-surface.js";
|
|
19
|
-
import { adapterRegistry } from "./adapters/registry.js";
|
|
20
|
-
import { applyDeviceTargeting } from "./commands/device-target.js";
|
|
21
|
-
import { metaMaskEngine } from "./engine.js";
|
|
22
|
-
import { walletFixturePath } from "./paths.js";
|
|
23
|
-
import { handleDoctor } from "./commands/doctor.js";
|
|
24
|
-
import { handleProvision } from "./commands/provision.js";
|
|
25
|
-
import { handleRuntimeHealth } from "./commands/runtime-health.js";
|
|
26
|
-
import { handleRuntimeLaunch } from "./commands/runtime-launch.js";
|
|
27
|
-
import { handleRuntimeDecision } from "./commands/runtime-decision.js";
|
|
28
|
-
import { handleResolveExtension } from "./commands/resolve-extension.js";
|
|
29
|
-
import { handleEnsureReady } from "./commands/ensure-ready.js";
|
|
30
|
-
import { handleSelfTest } from "./commands/self-test.js";
|
|
31
|
-
import { handleCompletionCandidates, invalidateCompletionCache } from "./commands/completion-candidates.js";
|
|
32
|
-
import { handleLogs } from "./commands/logs.js";
|
|
33
|
-
import { handleDebug } from "./commands/debug.js";
|
|
34
|
-
import { handleFixtures } from "./commands/fixtures.js";
|
|
35
|
-
import { handleRecipeQuality } from "./commands/recipe-quality.js";
|
|
36
|
-
import { handleStatus } from "./commands/status.js";
|
|
37
|
-
import { handleCheck } from "./commands/check.js";
|
|
38
|
-
import { handleChecklist } from "./commands/checklist.js";
|
|
39
|
-
import { handleExecutionTemplate } from "./commands/execution-template.js";
|
|
40
|
-
import { handlePrepare } from "./commands/prepare.js";
|
|
41
|
-
import { handleTaskInit } from "./commands/task-init.js";
|
|
42
|
-
import { handleReview } from "./commands/review.js";
|
|
43
|
-
import { handleDomain } from "./commands/domain.js";
|
|
44
|
-
import { handleConfig } from "./commands/config.js";
|
|
45
|
-
import { handlePrBody } from "./commands/pr-body.js";
|
|
46
|
-
import { overlayCommandOptions } from "./commands/overlay.js";
|
|
47
|
-
const stopOptions = {
|
|
48
|
-
companions: async (target) => {
|
|
49
|
-
const collector = await stopProjectCollector(target);
|
|
50
|
-
return collector.stopped && collector.pid !== null ? [{ label: "analytics collector", pid: collector.pid }] : [];
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
const targetDevice = (command, adapter, options) => applyDeviceTargeting(command, adapter, options, { gate: true, rerun: "" });
|
|
54
|
-
const runOptions = {
|
|
55
|
-
engine: metaMaskEngine,
|
|
56
|
-
targetDevice,
|
|
57
|
-
plan: {
|
|
58
|
-
// The wallet fixture `fixtures set` seeds.
|
|
59
|
-
steps: (target) => [{
|
|
60
|
-
step: "fixture.file",
|
|
61
|
-
confidence: "static",
|
|
62
|
-
status: "ok",
|
|
63
|
-
detail: fs.existsSync(walletFixturePath(target)) ? `present: ${walletFixturePath(target)}` : `absent: ${walletFixturePath(target)} (fixtures set to seed)`
|
|
64
|
-
}],
|
|
65
|
-
launchDetail: "would launch/attach the app + heal transport (Metro/Chrome/CDP) before executing"
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
const callOptions = {
|
|
69
|
-
engine: metaMaskEngine,
|
|
70
|
-
targetDevice,
|
|
71
|
-
// A wallet action makes the most useful first example.
|
|
72
|
-
exampleAction: (names) => names.find((name) => /wallet|unlock/u.test(name))
|
|
73
|
-
};
|
|
74
|
-
const COMMANDS = {
|
|
75
|
-
actions: (parsed) => handleActions(parsed, { catalog: metaMaskEngine }),
|
|
76
|
-
doctor: handleDoctor,
|
|
77
|
-
"runtime-health": handleRuntimeHealth,
|
|
78
|
-
"runtime-decision": handleRuntimeDecision,
|
|
79
|
-
"runtime-launch": handleRuntimeLaunch,
|
|
80
|
-
"resolve-extension": handleResolveExtension,
|
|
81
|
-
"ensure-ready": handleEnsureReady,
|
|
82
|
-
"self-test": handleSelfTest
|
|
83
|
-
};
|
|
84
|
-
const OVERLAY_COMMANDS = ["install", "verify", "cleanup"];
|
|
85
|
-
function usage() {
|
|
86
|
-
console.error(`mm-harness \u2014 the MetaMask recipe harness: launch the app, prove behavior, manage the runtime overlay.
|
|
87
|
-
Run it from inside a MetaMask checkout; the platform (mobile | extension | core | terminal) is auto-detected.
|
|
88
|
-
Grammar: mm-harness <command> [target] [flags] (target is a positional: ios | android | extension; flags add agent depth)
|
|
89
|
-
|
|
90
|
-
DAILY LOOP \u2014 what a teammate runs many times a day:
|
|
91
|
-
launch Launch the app incl. Metro/build, surface auto-detected. Mobile: ios|android required.
|
|
92
|
-
mm-harness launch ios # quick relaunch (add --build | --verify)
|
|
93
|
-
logs Tail Metro/webpack + app logs.
|
|
94
|
-
mm-harness logs
|
|
95
|
-
debug Open the debug console (extension DevTools / mobile RN).
|
|
96
|
-
mm-harness debug
|
|
97
|
-
reload Reload the connected Mobile or Extension runtime.
|
|
98
|
-
mm-harness reload
|
|
99
|
-
fixtures Sync files, set/reset the wallet, generate fixture-state, or finalize labels over CDP.
|
|
100
|
-
mm-harness fixtures sync # or: set | reset | generate --fixture <f> --out <o> | finalize \u2026
|
|
101
|
-
|
|
102
|
-
PROVE \u2014 run recipes and inspect capabilities:
|
|
103
|
-
run Run a recipe and write evidence (summary/trace/artifacts).
|
|
104
|
-
mm-harness run recipe.json
|
|
105
|
-
doctor Readiness check for a checkout (no app launch).
|
|
106
|
-
mm-harness doctor
|
|
107
|
-
check Run bounded repo-local checks for an active diff.
|
|
108
|
-
mm-harness check diff --profile fast --artifacts-dir artifacts/validation
|
|
109
|
-
actions Describe the actions a manifest declares.
|
|
110
|
-
mm-harness actions --adapter mobile
|
|
111
|
-
RUNTIME OVERLAY \u2014 install/verify/clean the per-checkout runtime overlay:
|
|
112
|
-
provision Install the cached Runway mobile dev client (artifact cache + sim install).
|
|
113
|
-
mm-harness provision runway ios --adapter mobile
|
|
114
|
-
install Install the runtime overlay into the checkout.
|
|
115
|
-
mm-harness install # inside a checkout, auto-detected
|
|
116
|
-
verify Check the overlay/runtime is present and healthy (no launch).
|
|
117
|
-
mm-harness verify
|
|
118
|
-
cleanup Remove the installed overlay and restore the checkout.
|
|
119
|
-
mm-harness cleanup
|
|
120
|
-
|
|
121
|
-
ADVANCED \u2014 internal runtime probes (rarely typed by hand):
|
|
122
|
-
runtime-health runtime-decision runtime-launch
|
|
123
|
-
resolve-extension ensure-ready self-test
|
|
124
|
-
(e.g. mm-harness runtime-decision --adapter extension --target <repo> --json)
|
|
125
|
-
|
|
126
|
-
ONE bin: mm-harness is the only command. No per-platform binaries \u2014 platform is
|
|
127
|
-
auto-detected, the positional target forces it (mm-harness launch ios), and
|
|
128
|
-
platform-specific needs are FLAGS on the same command (e.g. --sidebar, --full-build).
|
|
129
|
-
Human happy path = the bare command; agents add depth via flags (--json, --target, ports).
|
|
130
|
-
See README.md for the workflow and docs/RECIPES.md for proof authoring.
|
|
131
|
-
`);
|
|
132
|
-
}
|
|
133
|
-
async function main(argv) {
|
|
134
|
-
const command = argv[0];
|
|
135
|
-
if (!command || command === "-h" || command === "--help") {
|
|
136
|
-
usage();
|
|
137
|
-
return command ? 0 : 2;
|
|
138
|
-
}
|
|
139
|
-
const refused = await loadSelectedAdapter(command, argv.slice(1));
|
|
140
|
-
if (refused !== void 0) return refused;
|
|
141
|
-
if (command === "status" || command === "health" || command === "home") {
|
|
142
|
-
return handleStatus(parseArgs(argv.slice(1)));
|
|
143
|
-
}
|
|
144
|
-
if (command === "run") return handleRun(argv.slice(1), runOptions);
|
|
145
|
-
if (command === "call") return handleCall(argv.slice(1), callOptions);
|
|
146
|
-
if (command === "completion-candidates") return handleCompletionCandidates(argv.slice(1));
|
|
147
|
-
if (command === "provision") return handleProvision(parseArgs(argv.slice(1)));
|
|
148
|
-
if (OVERLAY_COMMANDS.includes(command)) {
|
|
149
|
-
if (command === "verify" && process.env.MM_HARNESS_SKIP_OVERLAY_ENSURE !== "1") {
|
|
150
|
-
try {
|
|
151
|
-
const { options } = parseArgs(argv.slice(1));
|
|
152
|
-
const target = targetPath(options);
|
|
153
|
-
const adapterRaw = (typeof options["adapter"] === "string" ? options["adapter"] : void 0) ?? (typeof options["platform"] === "string" ? options["platform"] : void 0) ?? detectAdapter(target);
|
|
154
|
-
if (adapterRaw && adapterRegistry.has(adapterRaw)) {
|
|
155
|
-
await handleHarness(["install", "--platform", adapterRaw, "--target", target, "--quiet"]);
|
|
156
|
-
}
|
|
157
|
-
} catch {
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
const code = await handleHarness(argv, overlayCommandOptions);
|
|
161
|
-
if (code === 0 && command === "install") {
|
|
162
|
-
try {
|
|
163
|
-
invalidateCompletionCache(targetPath(parseArgs(argv.slice(1)).options));
|
|
164
|
-
} catch {
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return code;
|
|
168
|
-
}
|
|
169
|
-
if (command === "launch") return handleLaunch(argv.slice(1));
|
|
170
|
-
if (command === "stop") return handleStop(argv.slice(1), stopOptions);
|
|
171
|
-
if (command === "logs") return handleLogs(argv.slice(1));
|
|
172
|
-
if (command === "debug") return handleDebug(argv.slice(1));
|
|
173
|
-
if (command === "reload") return handleReload(argv.slice(1));
|
|
174
|
-
if (command === "fixtures") return handleFixtures(argv.slice(1));
|
|
175
|
-
if (command === "recipe-quality") return handleRecipeQuality(argv.slice(1));
|
|
176
|
-
if (command === "check") return handleCheck(argv.slice(1));
|
|
177
|
-
if (command === "checklist") return handleChecklist(argv.slice(1));
|
|
178
|
-
if (command === "execution-template") return handleExecutionTemplate(argv.slice(1));
|
|
179
|
-
if (command === "task") return handleTaskInit(argv.slice(1));
|
|
180
|
-
if (command === "prepare") return handlePrepare(argv.slice(1));
|
|
181
|
-
if (command === "last") return handleLast(parseArgs(argv.slice(1)));
|
|
182
|
-
if (command === "review") return handleReview(argv.slice(1));
|
|
183
|
-
if (command === "domain") return handleDomain(argv.slice(1));
|
|
184
|
-
if (command === "config") return handleConfig(argv.slice(1));
|
|
185
|
-
if (command === "pr-body") return handlePrBody(argv.slice(1));
|
|
186
|
-
const handler = COMMANDS[command];
|
|
187
|
-
if (!handler) throw new Error(`Unknown command: ${command}`);
|
|
188
|
-
return handler(parseArgs(argv.slice(1), command === "runtime-decision" ? { recordIsFlag: true } : {}));
|
|
189
|
-
}
|
|
190
|
-
if (!globalThis.__MM_HARNESS_WRAPPER__) {
|
|
191
|
-
try {
|
|
192
|
-
process.exit(await main(process.argv.slice(2)));
|
|
193
|
-
} catch (error) {
|
|
194
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
195
|
-
process.exit(
|
|
196
|
-
error !== null && typeof error === "object" && "exitCode" in error && typeof error.exitCode === "number" ? error.exitCode : 1
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
export {
|
|
201
|
-
main
|
|
202
|
-
};
|