@deeeed/metamask-harness 0.17.5 → 0.19.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 +1059 -0
- package/README.md +91 -140
- package/adapters/core/inject.sh +1 -6
- package/adapters/extension/console-tail.mjs +55 -24
- package/adapters/extension/ensure-browser.sh +6 -1
- package/adapters/extension/inject.mjs +7 -13
- package/adapters/extension/launch-browser.cjs +7 -1
- package/adapters/extension/launch-webpack.cjs +83 -0
- package/adapters/extension/launch.sh +8 -11
- package/adapters/extension/lib/chrome-args.cjs +8 -1
- package/adapters/extension/lib/macos-focus.cjs +32 -0
- package/adapters/extension/live.sh +12 -21
- package/adapters/extension/reattach.sh +1 -0
- package/adapters/extension/seed-fixture.sh +4 -12
- package/adapters/extension/sidepanel-toggle.sh +4 -1
- package/adapters/extension/stamp-runtime-title.cjs +58 -0
- package/adapters/extension/start-watch.sh +17 -4
- package/adapters/extension/stop-viewers.sh +1 -1
- package/adapters/extension/sync-webpack-dist.cjs +107 -0
- package/adapters/extension/verify.sh +2 -2
- package/adapters/manifest.json +53 -37
- package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +16 -0
- package/adapters/mobile/bridge-runtime/console-forwarder.cjs +1 -1
- package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +3 -1
- package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +2 -3
- package/adapters/mobile/cleanup.sh +16 -176
- package/adapters/mobile/inject.sh +91 -671
- package/adapters/mobile/launch-console-forwarder.cjs +39 -0
- package/adapters/mobile/open-device.sh +45 -7
- package/adapters/mobile/start-console-forwarder.sh +70 -0
- package/adapters/mobile/start-metro.sh +0 -41
- package/adapters/mobile/verify.sh +34 -83
- package/adapters/mobile/wait-for-bridge.sh +22 -8
- package/adapters/shared/harness-source-fingerprint.mjs +14 -12
- package/adapters/shared/resolve-slot-ports-core.mjs +17 -6
- package/adapters/shared/resolve-slot-ports.sh +17 -5
- package/adapters/shared/update-check-worker.mjs +43 -0
- package/bin/mm-harness +21 -2
- package/dist/adapters/core/surface.js +4 -1
- package/dist/adapters/extension/console-capture.js +95 -0
- package/dist/adapters/extension/product-config.js +110 -0
- package/dist/adapters/extension/runtime-decision.js +20 -2
- package/dist/adapters/extension/surface.js +22 -3
- package/dist/adapters/harness-freshness.js +49 -0
- package/dist/adapters/mobile/perps-env.js +43 -3
- package/dist/adapters/mobile/prepare.js +39 -7
- package/dist/adapters/mobile/surface.js +5 -2
- package/dist/adapters/resolve-slot-ports.js +2 -2
- package/dist/adapters/slot-ports.js +13 -16
- package/dist/adapters.js +56 -16
- package/dist/checkout-lock.js +27 -2
- package/dist/cli-color.js +19 -0
- package/dist/cli-commands.js +1 -1
- package/dist/cli.js +7 -18
- package/dist/command-contract.js +462 -0
- package/dist/command-journal.js +263 -0
- package/dist/commands/call.js +252 -57
- package/dist/commands/check.js +10 -4
- package/dist/commands/completion-candidates.js +17 -22
- package/dist/commands/device-target.js +27 -12
- package/dist/commands/doctor.js +106 -25
- package/dist/commands/fixtures.js +142 -35
- package/dist/commands/last.js +60 -0
- package/dist/commands/launch/extension.js +40 -17
- package/dist/commands/launch/index.js +207 -63
- package/dist/commands/launch/mobile.js +2 -0
- package/dist/commands/list-executables.js +187 -29
- package/dist/commands/logs.js +8 -6
- package/dist/commands/manifest.js +286 -35
- package/dist/commands/parse-args.js +68 -4
- package/dist/commands/provision.js +10 -4
- package/dist/commands/run-engine.js +772 -264
- package/dist/commands/run-report.js +12 -3
- package/dist/commands/run.js +378 -85
- package/dist/commands/shared.js +76 -4
- package/dist/commands/status-probe.js +4 -1
- package/dist/commands/status.js +2 -1
- package/dist/commands/stop.js +7 -2
- package/dist/commands/update.js +16 -28
- package/dist/completions-cache.js +1 -1
- package/dist/doctor.js +57 -10
- package/dist/harness.js +47 -137
- package/dist/heal-bounds.js +7 -2
- package/dist/json-stream.js +57 -0
- package/dist/live-adapter-contract.js +138 -32
- package/dist/manifest.js +161 -1
- package/dist/mm-harness-cli.js +146 -73
- package/dist/paths.js +2 -5
- package/dist/recipe-security.js +178 -0
- package/dist/run-diagnostics.js +261 -0
- package/dist/run-recording.js +1 -1
- package/dist/runner.js +140 -9
- package/docs/CONTRIBUTING.md +136 -0
- package/docs/QA.md +184 -0
- package/docs/RECIPES.md +122 -0
- package/docs/SECURITY.md +88 -0
- package/library/README.md +7 -3
- package/library/actions/core/perps/_controller.mjs +43 -56
- package/library/actions/core/perps/assert_orders.mjs +6 -7
- package/library/actions/core/perps/assert_positions.mjs +6 -7
- package/library/actions/core/perps/close_orders.mjs +2 -0
- package/library/actions/core/perps/close_positions.mjs +2 -0
- package/library/actions/core/perps/ensure_orders.mjs +4 -2
- package/library/actions/core/perps/ensure_positions.mjs +4 -2
- package/library/actions/core/perps/place_order.mjs +7 -3
- package/library/actions/core/perps/read_account.mjs +2 -2
- package/library/actions/core/perps/read_orders.mjs +2 -1
- package/library/actions/core/perps/read_positions.mjs +2 -1
- package/library/actions/core/wallet/list_accounts.mjs +95 -0
- package/library/actions/extension/perps/assert_orders.mjs +2 -1
- package/library/actions/extension/perps/assert_positions.mjs +2 -1
- package/library/actions/extension/perps/perps.mjs +43 -14
- package/library/actions/extension/platform/cdp.mjs +1 -0
- package/library/actions/extension/wallet/list_accounts.mjs +41 -0
- package/library/actions/mobile/perps/assert_orders.mjs +2 -1
- package/library/actions/mobile/perps/assert_positions.mjs +2 -1
- package/library/actions/mobile/perps/perps.mjs +40 -12
- package/library/actions/mobile/wallet/list_accounts.mjs +37 -0
- package/library/library.json +1 -1
- package/library/manifests/core.action-manifest.json +1214 -396
- package/library/manifests/extension.action-manifest.json +1635 -728
- package/library/manifests/mobile.action-manifest.json +1740 -727
- package/library/recipes/app/lifecycle.android-smoke.mobile.recipe.json +63 -81
- package/library/recipes/perps/clean-market-testnet.core.recipe.json +44 -0
- package/library/recipes/perps/clean-market-testnet.recipe.json +49 -0
- package/library/recipes/perps/lifecycle.recipe.json +136 -180
- package/library/recipes/perps/order-lifecycle.core.recipe.json +71 -67
- package/library/recipes/perps/performance.background-resume.mobile.recipe.json +51 -67
- package/library/recipes/perps/performance.cold-start.mobile.recipe.json +51 -67
- package/library/recipes/perps/performance.mobile.recipe.json +37 -51
- package/library/recipes/perps/performance.warm-start.mobile.recipe.json +44 -59
- package/library/recipes/perps/read-markets.core.recipe.json +29 -31
- package/library/recipes/perps/smoke.core.recipe.json +29 -32
- package/library/recipes/perps/smoke.extension.recipe.json +41 -44
- package/library/recipes/perps/smoke.mobile.recipe.json +42 -44
- package/library/recipes/perps/trading-lifecycle.core.recipe.json +69 -65
- package/library/recipes/runner/action-validation.extension.recipe.json +312 -398
- package/library/recipes/runner/action-validation.mobile.recipe.json +316 -402
- package/library/recipes/runner/smoke.core.recipe.json +25 -0
- package/library/recipes/runner/smoke.extension.recipe.json +23 -24
- package/library/recipes/runner/smoke.mobile.recipe.json +23 -24
- package/library/recipes/wallet/smoke.extension.recipe.json +40 -0
- package/library/recipes/wallet/smoke.mobile.recipe.json +40 -0
- package/package.json +12 -5
- package/scripts/completions.sh +8 -11
- package/scripts/validate-human-outcomes.mjs +169 -0
- package/adapters/mobile/overlay/app/dev-tools/AgenticService/AgentStepHud.tsx.patch +0 -185
- package/adapters/mobile/overlay/app/dev-tools/AgenticService/AgenticService.ts.patch +0 -1662
- package/adapters/mobile/overlay/compat/README.md +0 -28
- package/adapters/mobile/overlay/compat/rn81-message-event-source.patch +0 -42
- package/adapters/shared/resolve-farmslot-ports-core.mjs +0 -3
- package/adapters/shared/resolve-farmslot-ports.mjs +0 -5
- package/adapters/shared/resolve-farmslot-ports.sh +0 -7
- package/dist/adapters/extension/harness-freshness.js +0 -39
- package/dist/commands/flows.js +0 -62
- package/docs/ADAPTER-SURFACE.md +0 -119
- package/docs/CHEATSHEET.md +0 -61
- package/docs/CLI-SPEC.md +0 -1098
- package/docs/CODE-MAP.md +0 -62
- package/docs/DEBUG-HANDOVER.md +0 -36
- package/docs/MENTAL-MODEL.md +0 -295
- package/docs/UX-PRINCIPLES.md +0 -64
- package/docs/architecture.md +0 -398
- package/docs/live-adapter-contract.md +0 -188
- package/docs/package-boundaries.md +0 -47
- package/docs/perps-flow-catalog.md +0 -235
- package/docs/recipe-libraries.md +0 -301
- package/docs/runtime-file-conventions.md +0 -36
- package/library/flows/perps.flows.json +0 -64
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { detectAdapter } from "../harness.js";
|
|
3
3
|
import { assertAdapter, manifestPath } from "../paths.js";
|
|
4
|
+
import { explicitRecipeTrustOptions } from "../recipe-security.js";
|
|
4
5
|
import { ADAPTER_DETECT_NEXT } from "./shared.js";
|
|
5
6
|
import { EXIT } from "./shared.js";
|
|
6
7
|
class CliError extends Error {
|
|
@@ -19,12 +20,15 @@ function parseArgs(argv, command) {
|
|
|
19
20
|
const options = {};
|
|
20
21
|
const booleanOptions = /* @__PURE__ */ new Set([
|
|
21
22
|
"json",
|
|
23
|
+
"jsonStream",
|
|
22
24
|
"launchExistingDist",
|
|
23
25
|
"startWatch",
|
|
24
26
|
"record",
|
|
25
27
|
"plan",
|
|
26
28
|
"list",
|
|
29
|
+
"describe",
|
|
27
30
|
"raw",
|
|
31
|
+
"categories",
|
|
28
32
|
"fix",
|
|
29
33
|
"force",
|
|
30
34
|
"resolveOnly",
|
|
@@ -34,6 +38,7 @@ function parseArgs(argv, command) {
|
|
|
34
38
|
"allDevices",
|
|
35
39
|
"help"
|
|
36
40
|
]);
|
|
41
|
+
const repeatableOptions = /* @__PURE__ */ new Set(["library"]);
|
|
37
42
|
for (let i = 0; i < argv.length; i += 1) {
|
|
38
43
|
const arg = argv[i];
|
|
39
44
|
if (!arg.startsWith("--")) {
|
|
@@ -66,15 +71,56 @@ function parseArgs(argv, command) {
|
|
|
66
71
|
continue;
|
|
67
72
|
}
|
|
68
73
|
if (inlineValue !== void 0) {
|
|
69
|
-
options
|
|
74
|
+
assignOption(options, key, inlineValue, repeatableOptions);
|
|
70
75
|
continue;
|
|
71
76
|
}
|
|
72
77
|
if (i + 1 >= argv.length) throw usageError(`Missing value for ${arg}`);
|
|
73
|
-
options
|
|
78
|
+
assignOption(options, key, argv[i + 1], repeatableOptions);
|
|
74
79
|
i += 1;
|
|
75
80
|
}
|
|
76
81
|
return { positional, options, rawArgv: [...argv] };
|
|
77
82
|
}
|
|
83
|
+
function assignOption(options, key, value, repeatableOptions) {
|
|
84
|
+
if (!repeatableOptions.has(key)) {
|
|
85
|
+
options[key] = value;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const existing = options[key];
|
|
89
|
+
if (existing === void 0) {
|
|
90
|
+
options[key] = [value];
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!Array.isArray(existing)) throw usageError(`--${key} has conflicting values.`);
|
|
94
|
+
options[key] = [...existing, value];
|
|
95
|
+
}
|
|
96
|
+
function parseRecipeParamAssignments(values) {
|
|
97
|
+
const params = {};
|
|
98
|
+
for (const assignment of values) {
|
|
99
|
+
const separator = assignment.indexOf("=");
|
|
100
|
+
if (separator <= 0) {
|
|
101
|
+
throw usageError(`recipe parameter ${JSON.stringify(assignment)} must use key=value.`);
|
|
102
|
+
}
|
|
103
|
+
const key = assignment.slice(0, separator).trim();
|
|
104
|
+
if (!key) throw usageError(`recipe parameter ${JSON.stringify(assignment)} has an empty key.`);
|
|
105
|
+
if (Object.hasOwn(params, key)) {
|
|
106
|
+
throw usageError(`recipe parameter ${JSON.stringify(key)} was provided more than once.`);
|
|
107
|
+
}
|
|
108
|
+
const raw = assignment.slice(separator + 1);
|
|
109
|
+
let value;
|
|
110
|
+
try {
|
|
111
|
+
value = JSON.parse(raw);
|
|
112
|
+
} catch {
|
|
113
|
+
value = raw;
|
|
114
|
+
}
|
|
115
|
+
Object.defineProperty(params, key, {
|
|
116
|
+
value,
|
|
117
|
+
enumerable: true,
|
|
118
|
+
configurable: true,
|
|
119
|
+
writable: true
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return params;
|
|
123
|
+
}
|
|
78
124
|
function parseRecordVideoMode(value) {
|
|
79
125
|
if (value === void 0 || value === "" || value === "true") return "full-run";
|
|
80
126
|
if (value === "off" || value === "false") return false;
|
|
@@ -97,6 +143,14 @@ function optionString(options, key) {
|
|
|
97
143
|
if (typeof value !== "string") throw usageError(`--${key} requires a value.`);
|
|
98
144
|
return value;
|
|
99
145
|
}
|
|
146
|
+
function optionStrings(options, key) {
|
|
147
|
+
const value = options[key];
|
|
148
|
+
if (value === void 0) return void 0;
|
|
149
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
150
|
+
throw usageError(`--${key} requires a value.`);
|
|
151
|
+
}
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
100
154
|
function optionFlag(options, key) {
|
|
101
155
|
const value = options[key];
|
|
102
156
|
return value === true;
|
|
@@ -127,7 +181,7 @@ function adapterOption(options) {
|
|
|
127
181
|
return adapter;
|
|
128
182
|
}
|
|
129
183
|
function targetPath(options) {
|
|
130
|
-
return path.resolve(optionString(options, "target") ??
|
|
184
|
+
return path.resolve(optionString(options, "target") ?? process.cwd());
|
|
131
185
|
}
|
|
132
186
|
function actionManifestPathOption(options, adapter) {
|
|
133
187
|
const configured = optionString(options, "actionManifest");
|
|
@@ -140,13 +194,21 @@ function parsePort(value, errorMessage) {
|
|
|
140
194
|
}
|
|
141
195
|
function runtimeOptionsFromCli(options) {
|
|
142
196
|
const recordVideo = options.recordVideo;
|
|
197
|
+
const trust = explicitRecipeTrustOptions({
|
|
198
|
+
sourceTrust: optionString(options, "sourceTrust"),
|
|
199
|
+
sourceKind: optionString(options, "sourceKind"),
|
|
200
|
+
sourceName: optionString(options, "sourceName"),
|
|
201
|
+
sourceDigest: optionString(options, "sourceDigest"),
|
|
202
|
+
approvalDigest: optionString(options, "approvePlan")
|
|
203
|
+
});
|
|
143
204
|
return {
|
|
144
205
|
cdpPort: optionString(options, "cdpPort"),
|
|
145
206
|
watcherPort: optionString(options, "watcherPort") ?? optionString(options, "metroPort"),
|
|
146
207
|
launchExistingDist: optionFlag(options, "launchExistingDist"),
|
|
147
208
|
slot: optionString(options, "slot"),
|
|
148
209
|
validationRuntimeDir: optionString(options, "validationRuntimeDir"),
|
|
149
|
-
recordVideo: recordVideo === "full-run" ? "full-run" : false
|
|
210
|
+
recordVideo: recordVideo === "full-run" ? "full-run" : false,
|
|
211
|
+
...trust
|
|
150
212
|
};
|
|
151
213
|
}
|
|
152
214
|
function resolveAdapter(options) {
|
|
@@ -184,8 +246,10 @@ export {
|
|
|
184
246
|
isRecord,
|
|
185
247
|
optionFlag,
|
|
186
248
|
optionString,
|
|
249
|
+
optionStrings,
|
|
187
250
|
parseArgs,
|
|
188
251
|
parsePort,
|
|
252
|
+
parseRecipeParamAssignments,
|
|
189
253
|
requiredOption,
|
|
190
254
|
resolveAdapter,
|
|
191
255
|
runtimeOptionsFromCli,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { detectAdapter } from "../harness.js";
|
|
2
2
|
import { assertAdapter } from "../paths.js";
|
|
3
3
|
import { getAdapterSurface } from "../adapters/surface.js";
|
|
4
|
-
import { ADAPTER_DETECT_NEXT, usageOut } from "./shared.js";
|
|
4
|
+
import { ADAPTER_DETECT_NEXT, usageOut, writeInteractiveProgress } from "./shared.js";
|
|
5
5
|
import {
|
|
6
6
|
applyWatcherPortOption,
|
|
7
7
|
optionFlag,
|
|
@@ -25,9 +25,13 @@ async function handleProvision({ positional, options, rawArgv }) {
|
|
|
25
25
|
}
|
|
26
26
|
const surface = getAdapterSurface(adapter);
|
|
27
27
|
const rerunCommand = provisionRerunCommand(rawArgv, options, adapter, target);
|
|
28
|
+
const platform = optionString(options, "platform") ?? optionString(options, "devicePlatform") ?? (positional[0] === "runway" ? positional[1] : positional[0]) ?? "ios";
|
|
29
|
+
if (adapter === "mobile") {
|
|
30
|
+
writeInteractiveProgress(json, `\u2192 provision mobile ${platform} \u2014 resolving simulator and Runway artifact`);
|
|
31
|
+
}
|
|
28
32
|
const result = await surface.runwayProvision.run(target, {
|
|
29
33
|
json,
|
|
30
|
-
platform
|
|
34
|
+
platform,
|
|
31
35
|
branch: optionString(options, "branch"),
|
|
32
36
|
defaultBranch: optionString(options, "defaultBranch"),
|
|
33
37
|
run: optionString(options, "run"),
|
|
@@ -42,8 +46,10 @@ async function handleProvision({ positional, options, rawArgv }) {
|
|
|
42
46
|
resolveOnly: optionFlag(options, "resolveOnly"),
|
|
43
47
|
rerunCommand
|
|
44
48
|
});
|
|
49
|
+
const next = result.status === "pass" && adapter === "mobile" && result.resolveOnly !== true ? `mm-harness launch ${String(result.platform ?? platform)} --adapter mobile --target ${shellQuote(target)}` : void 0;
|
|
50
|
+
const output = next ? { ...result, next } : result;
|
|
45
51
|
if (json) {
|
|
46
|
-
console.log(JSON.stringify(
|
|
52
|
+
console.log(JSON.stringify(output, null, 2));
|
|
47
53
|
} else if (result.status === "pass") {
|
|
48
54
|
const cache = typeof result.cache === "object" && result.cache ? result.cache : void 0;
|
|
49
55
|
const simulator = typeof result.simulator === "object" && result.simulator ? result.simulator : void 0;
|
|
@@ -54,6 +60,7 @@ async function handleProvision({ positional, options, rawArgv }) {
|
|
|
54
60
|
const action = result.skipped ? "already provisioned" : "provisioned";
|
|
55
61
|
console.error(`\u2713 ${action} ${adapter} ${result.platform ?? ""} simulator=${simulator?.name ?? "unknown"} cache=${cache?.status ?? "unknown"}`);
|
|
56
62
|
}
|
|
63
|
+
if (next) console.error(` Next: ${next}`);
|
|
57
64
|
} else {
|
|
58
65
|
console.error(`\u2717 mm-harness provision: ${result.error?.message ?? "provision failed"}
|
|
59
66
|
Next: ${result.error?.userAction ?? rerunCommand}`);
|
|
@@ -92,7 +99,6 @@ function provisionPositionals(rawArgv) {
|
|
|
92
99
|
const valueFlags = /* @__PURE__ */ new Set([
|
|
93
100
|
"--adapter",
|
|
94
101
|
"--target",
|
|
95
|
-
"--project-root",
|
|
96
102
|
"--platform",
|
|
97
103
|
"--device-platform",
|
|
98
104
|
"--branch",
|