@deeeed/metamask-harness 0.17.3 → 0.17.5
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 +6 -96
- package/README.md +136 -96
- package/adapters/extension/console-tail.mjs +24 -51
- package/adapters/extension/ensure-browser.sh +7 -1
- package/adapters/extension/inject.mjs +15 -5
- package/adapters/extension/launch-browser.cjs +4 -3
- package/adapters/extension/launch.sh +11 -8
- package/adapters/extension/lib/chrome-args.cjs +24 -0
- package/adapters/extension/live.sh +1 -2
- package/adapters/extension/reattach.sh +0 -1
- package/adapters/extension/seed-fixture.sh +12 -4
- package/adapters/extension/sidepanel-toggle.sh +1 -4
- package/adapters/extension/start-watch.sh +4 -17
- package/adapters/extension/stop-viewers.sh +1 -1
- package/adapters/extension/verify.sh +1 -1
- package/adapters/manifest.json +45 -53
- package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +0 -16
- package/adapters/mobile/bridge-runtime/console-forwarder.cjs +1 -1
- package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +1 -3
- package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +3 -2
- package/adapters/mobile/cleanup.sh +176 -16
- package/adapters/mobile/inject.sh +671 -90
- package/adapters/mobile/overlay/app/dev-tools/AgenticService/AgentStepHud.tsx.patch +185 -0
- package/adapters/mobile/overlay/app/dev-tools/AgenticService/AgenticService.ts.patch +1662 -0
- package/adapters/mobile/overlay/compat/README.md +28 -0
- package/adapters/mobile/overlay/compat/rn81-message-event-source.patch +42 -0
- package/adapters/mobile/start-metro.sh +41 -0
- package/adapters/mobile/verify.sh +61 -4
- package/adapters/mobile/wait-for-bridge.sh +8 -22
- package/adapters/shared/harness-source-fingerprint.mjs +49 -0
- package/adapters/shared/install-repo-deps.sh +1 -5
- package/adapters/shared/open-debug.mjs +184 -103
- package/adapters/shared/resolve-farmslot-ports-core.mjs +3 -0
- package/adapters/shared/resolve-farmslot-ports.mjs +5 -0
- package/adapters/shared/resolve-farmslot-ports.sh +7 -0
- package/adapters/shared/resolve-slot-ports-core.mjs +6 -0
- package/adapters/shared/resolve-slot-ports.sh +7 -2
- package/bin/mm-harness +0 -7
- package/dist/adapters/extension/harness-freshness.js +39 -0
- package/dist/adapters/extension/runtime-decision.js +4 -73
- package/dist/adapters/extension/surface.js +2 -3
- package/dist/adapters/mobile/perps-env.js +3 -43
- package/dist/adapters/mobile/prepare.js +7 -22
- package/dist/adapters/mobile/source-freshness.js +26 -41
- package/dist/adapters/mobile/surface.js +1 -1
- package/dist/adapters/resolve-slot-ports.js +2 -0
- package/dist/adapters/slot-ports.js +0 -16
- package/dist/adapters.js +5 -12
- package/dist/cli-commands.js +1 -1
- package/dist/cli.js +12 -6
- package/dist/commands/call.js +22 -56
- package/dist/commands/check.js +3 -9
- package/dist/commands/checklist.js +4 -1
- package/dist/commands/debug.js +31 -38
- package/dist/commands/device-target.js +12 -27
- package/dist/commands/doctor.js +23 -77
- package/dist/commands/fixtures.js +17 -27
- package/dist/commands/launch/extension.js +2 -0
- package/dist/commands/launch/index.js +59 -167
- package/dist/commands/logs.js +6 -8
- package/dist/commands/manifest.js +25 -151
- package/dist/commands/parse-args.js +0 -2
- package/dist/commands/provision.js +3 -10
- package/dist/commands/run-engine.js +69 -71
- package/dist/commands/run-report.js +3 -12
- package/dist/commands/run.js +35 -245
- package/dist/commands/shared.js +3 -55
- package/dist/commands/status-probe.js +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/stop.js +2 -7
- package/dist/commands/update.js +28 -16
- package/dist/doctor.js +4 -1
- package/dist/harness.js +134 -43
- package/dist/heal-bounds.js +1 -1
- package/dist/live-adapter-contract.js +20 -6
- package/dist/mm-harness-cli.js +48 -123
- package/dist/paths.js +5 -2
- package/dist/runner.js +2 -37
- package/dist/runtime-context.js +8 -26
- package/docs/ADAPTER-SURFACE.md +112 -19
- package/docs/CHEATSHEET.md +52 -39
- package/docs/CLI-SPEC.md +1098 -0
- package/docs/CODE-MAP.md +1 -1
- package/docs/DEBUG-HANDOVER.md +36 -0
- package/docs/MENTAL-MODEL.md +295 -0
- package/docs/UX-PRINCIPLES.md +1 -3
- package/docs/architecture.md +375 -65
- package/docs/live-adapter-contract.md +2 -4
- package/docs/recipe-libraries.md +275 -45
- package/library/README.md +0 -4
- package/library/actions/core/perps/_controller.mjs +55 -10
- package/library/actions/mobile/platform/bridge.mjs +1 -5
- package/library/manifests/core.action-manifest.json +7 -7
- package/library/manifests/mobile.action-manifest.json +3 -28
- package/package.json +1 -4
- package/adapters/extension/launch-webpack.cjs +0 -83
- package/adapters/extension/stamp-runtime-title.cjs +0 -49
- package/adapters/extension/sync-webpack-dist.cjs +0 -105
- package/adapters/mobile/launch-console-forwarder.cjs +0 -39
- package/adapters/mobile/start-console-forwarder.sh +0 -70
- package/adapters/shared/update-check-worker.mjs +0 -35
- package/dist/adapters/extension/console-capture.js +0 -93
- package/dist/command-contract.js +0 -441
- package/dist/command-journal.js +0 -225
- package/dist/commands/last.js +0 -52
- package/dist/json-stream.js +0 -57
- package/dist/run-diagnostics.js +0 -261
- package/docs/CLI-ERGONOMICS-AUDIT.md +0 -32
- package/docs/CLI-ERGONOMICS-HUMAN-QA.md +0 -64
- package/docs/VIDEO-DEMO-VALIDATION.md +0 -74
- package/library/recipes/runner/smoke.core.recipe.json +0 -27
- package/library/recipes/wallet/smoke.extension.recipe.json +0 -42
- package/library/recipes/wallet/smoke.mobile.recipe.json +0 -42
- package/scripts/validate-human-outcomes.mjs +0 -169
package/CHANGELOG.md
CHANGED
|
@@ -2,99 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
-
## 0.17.
|
|
6
|
-
|
|
7
|
-
### Added
|
|
8
|
-
|
|
9
|
-
- Added a real-checkout human-outcome gate covering live readiness, runtime verification, debugger target resolution, smoke evidence, and unchanged tracked product source across Extension, Mobile, and Core.
|
|
10
|
-
- Added generic Core runner smoke and fixture-backed wallet smoke recipes so the reusable examples are not tied to Perps.
|
|
11
|
-
- Added nine-slot isolation coverage for platform ports, runtime files, logs, and headless Core behavior.
|
|
12
|
-
|
|
13
|
-
### Changed
|
|
14
|
-
|
|
15
|
-
- `doctor` now reports CDP or simulator/ADB screenshot fallback when `capture-helper` is absent or unhealthy, while identifying video as unavailable separately.
|
|
16
|
-
- Action, flow, and recipe discovery/documentation now use one concise scope model; the default recipe-library and adapter-surface references were reduced to current behavior.
|
|
17
|
-
- Fixture discovery now uses one canonical checkout path instead of legacy fallback locations.
|
|
18
|
-
|
|
19
|
-
### Fixed
|
|
20
|
-
|
|
21
|
-
- Mobile launch now waits for two consecutive platform-matched agentic bridge snapshots, preventing a transient startup route from being reported ready before an immediate verify.
|
|
22
|
-
- `verify --json` keeps stdout to one machine-readable JSON document even when the platform harness must first be installed.
|
|
23
|
-
- Mobile install metadata safely preserves checkout paths containing shell-significant characters.
|
|
24
|
-
- Cleanup discovery no longer advertises a removed compatibility flag, and Core recovery guidance now points to the canonical wallet fixture.
|
|
25
|
-
- Mobile console forwarding now uses canonical checkout paths, readiness rejects impossible one-poll stability checks, and Extension debug handles malformed WebSocket frames without crashing.
|
|
26
|
-
- Extension watch refreshes remove stale runtime files, delay file replacement until transfer completion, allow slower console attachment, and stop the detached webpack process group.
|
|
27
|
-
|
|
28
|
-
## 0.17.2 - 2026-07-15
|
|
29
|
-
|
|
30
|
-
### Fixed
|
|
31
|
-
|
|
32
|
-
- Passive update discovery now runs in a detached, once-daily registry probe, so fast commands populate the cache without adding latency or contaminating machine output.
|
|
33
|
-
|
|
34
|
-
## 0.17.1 - 2026-07-15
|
|
35
|
-
|
|
36
|
-
### Fixed
|
|
37
|
-
|
|
38
|
-
- Extension `debug` now uses Chrome's native DevTools command for the active slot target and opens directly on Console; `debug --worker` targets the service worker without creating a frontend browser tab.
|
|
39
|
-
- Extension webpack watchers now launch in their own process group, so they remain alive for incremental rebuilds after the initial `launch --build` command exits.
|
|
40
|
-
- Successful Extension watch rebuilds now update the isolated loaded runtime in place, so a normal refresh of the current fullscreen or sidepanel UI shows source edits without another harness build or relaunch.
|
|
41
|
-
- Extension slot titles are stamped into the isolated runtime after snapshots and successful rebuilds, preserving the slot identifier across an operator's normal browser refresh without changing product source.
|
|
42
|
-
- Extension sidepanel opening no longer waits for the harness-owned user-gesture button to pass visual actionability checks; occluded wallet loading surfaces cannot block the trusted click.
|
|
43
|
-
- Human recipe results now print an absolute-path artifact inventory and expand run-scoped application diagnostics inline; single-action calls show the same `CLEAN`/`REVIEW` diagnostics instead of requiring another query.
|
|
44
|
-
- Extension console collection now starts after every successful public launch path, including quick reattach, and persists as one checkout-scoped process until `stop`. MetaMask UI/service-worker events and dapp-page events are routed to separate `extension-console.log` and `dapp-console.log` files; bare `logs` defaults to MetaMask while `--source dapp` and `--source webpack` remain explicit.
|
|
45
|
-
- Mobile CDP-forwarded app events now write to `app-console.log`, so `logs --source app` and run diagnostics are no longer mixed with Metro bundler output; warm and cold launches start a process-group-detached collector only after bridge readiness so capture remains live after the launch command exits.
|
|
46
|
-
- Extension `debug` now opens Chrome's local DevTools frontend inside the exact slot-owned profile, targets the MetaMask extension page rather than the dapp, and verifies the debugging connection before reporting success.
|
|
47
|
-
- Mobile fixture application now fails immediately when the checkout fixture is absent, rejects the misplaced `fixtures set --dev` flag with the correct initialization command, and never prints a success message after failure.
|
|
48
|
-
|
|
49
|
-
### Changed
|
|
50
|
-
|
|
51
|
-
- Current documentation now teaches the auto-detected workflow and verified human outcomes only: launch, incremental refresh, target-specific debugging/logs, fixture setup, capability discovery, and proof evidence.
|
|
52
|
-
- Mobile fixture setup now requires the current multichain account-tree path, and Core signing requires the canonical checkout wallet fixture.
|
|
53
|
-
|
|
54
|
-
### Removed
|
|
55
|
-
|
|
56
|
-
- Removed compatibility-only runtime-start fields, hidden `live` execution, removed-command handlers, undomained recipe aliases, flat/non-ESM action lookup, old port-resolver filenames, duplicate Extension launcher naming, obsolete fixture search locations, and the alternate Mobile product-source bridge. Mobile install now requires the current product-owned bridge and writes metadata only.
|
|
57
|
-
- Removed the historical CLI migration/spec documents; current behavior is documented in the README, cheatsheet, architecture, and human QA checklist.
|
|
58
|
-
|
|
59
|
-
## 0.17.0 - 2026-07-14
|
|
60
|
-
|
|
61
|
-
### Added
|
|
62
|
-
|
|
63
|
-
- Command-specific JSON failures now preserve a structured `userAction` across device targeting, action calls, recipe validation/execution, checks, and dev-server stop. Successful install/verify/cleanup, provision, and stop transitions add `next` only when one truthful follow-up exists; discovery and terminal evidence results remain quiet.
|
|
64
|
-
- `run` and `launch` now implement the documented `--json-stream` contract: line-flushed JSONL phase/progress events, per-node recipe status, compact evidence paths, and one terminal `complete` event. Stream mode keeps stdout machine-clean and takes precedence when combined with `--json`; existing `--json` output is unchanged.
|
|
65
|
-
- Interactive Mobile launch, Runway provisioning, and recipe execution now print contextual intent before their first potentially slow readiness or validation probe. The new lines are suppressed for `--json` and non-TTY stdout.
|
|
66
|
-
- `last --json` reads an atomic, mode-`0600`, per-checkout resumability journal for significant runtime/proof commands, including redacted args, verdict, evidence paths, and timestamps. Interrupted commands remain `running`; discovery commands do not overwrite the record.
|
|
67
|
-
- `actions <query>` now searches action names, categories, fields, and descriptions with typo tolerance, while single-action detail includes compact related-action names.
|
|
68
|
-
|
|
69
|
-
### Changed
|
|
70
|
-
|
|
71
|
-
- Action categories now group protocol primitives into useful `assertion`, `control`, `evidence`, and `runtime` domains instead of exposing one category per unnamespaced action.
|
|
72
|
-
- Public commands now reject unknown commands/options, missing values and positionals, invalid enums, and excess positionals before dispatch. Human errors include valid command-local options, a closest match when available, and a runnable example; `--json` returns stable `CLI_*` codes with `error.message` and `error.userAction`.
|
|
73
|
-
- `docs/CLI-ERGONOMICS-AUDIT.md` is generated from the public command contract so every command remains covered by the shared bad-flag and JSON usage-error policy as the surface evolves.
|
|
74
|
-
|
|
75
|
-
## 0.16.0 - 2026-07-14
|
|
76
|
-
|
|
77
|
-
### Added
|
|
78
|
-
|
|
79
|
-
- Mobile and Extension recipe runs now write bounded, redacted, non-blocking side findings to `diagnostics.json`: Mobile combines its in-app issue buffer with run-scoped log bytes, while Extension owns a CDP console subscription for the run. Core remains N/A because it is headless.
|
|
80
|
-
- `actions --categories` now lists compact category counts, and `actions --category <name>` returns a bounded action/schema view so agents can discover capabilities without loading the complete adapter catalog.
|
|
81
|
-
|
|
82
|
-
## 0.15.2 - 2026-07-13
|
|
83
|
-
|
|
84
|
-
### Fixed
|
|
85
|
-
|
|
86
|
-
- Mobile `ui.press text=<visible text>` now invokes the app bridge's text-content press path, while `test_id`, `testID`, and `selector` continue to use exact testID matching; ambiguous target combinations fail before bridge execution.
|
|
87
|
-
|
|
88
|
-
## 0.15.1 - 2026-07-13
|
|
89
|
-
|
|
90
|
-
### Fixed
|
|
91
|
-
|
|
92
|
-
- `doctor --fix` recovery `nextActions` (numbered fixture choices, overlay install, runtime-context retry) now embed the resolved `--adapter` and absolute `--target`, shell-quoted, so each command works verbatim from any cwd. They are also prefixed with the resolved `bin/mm-harness` executable path, so they work in task-local installs where `mm-harness` is not on PATH.
|
|
93
|
-
|
|
94
|
-
## 0.15.0 - 2026-07-13
|
|
5
|
+
## 0.17.5 - 2026-07-16
|
|
95
6
|
|
|
96
7
|
### Changed
|
|
97
8
|
|
|
9
|
+
- Mobile proof preflight now waits for the requested platform's bridge target after an automatic source-change restart; a bridge transition fails with a typed `MOBILE_BRIDGE_NOT_READY` result instead of letting the recipe race into `NO_TARGET`.
|
|
10
|
+
- Extension proof recovery now gives the checkout-owned runtime-dist synchronizer a short bounded handoff window after reattach, avoiding a false stale-runtime failure while still surfacing a real unhealthy build.
|
|
98
11
|
- Extension `status` and `doctor` now report the webpack dev server as `up` only when a target-owned watcher is alive; historical successful build logs no longer imply liveness after `stop`.
|
|
99
12
|
- Mobile overlay freshness no longer reports `pass` when every checkable runner overlay file is absent from the target; missing or drifted files are classified before the empty-overlay success case.
|
|
100
13
|
- Mobile live verification now compares AgenticService/HUD freshness against the canonical `app/dev-tools/AgenticService` runner and product paths instead of skipping the check through the obsolete `app/core/AgenticService` layout.
|
|
@@ -116,6 +29,8 @@
|
|
|
116
29
|
- Public Extension `stop` now tears down the checkout-owned watcher, Chrome/CDP profile processes, viewer tails/windows, and stale runtime PID/lock markers; explicit `--port` overrides only the watcher port and no longer hides the runtime-context CDP owner.
|
|
117
30
|
- Tmux log viewers now require an explicit `RECIPE_TMUX_SESSION` or checkout `agentic-runtime.json` session; merely running from another tmux session never creates, sweeps, or marker-closes windows there, while stale markers are discarded and file logs remain available.
|
|
118
31
|
- Extension `run`/`call --heal auto` now rebuild or reload before proof when source, `dist/chrome`, and the loaded runtime snapshot are out of sync; healing-off runs stop before execution with the exact `launch --build --verify` recovery command.
|
|
32
|
+
- Extension slots now launch with `--remote-allow-origins=http://127.0.0.1:<cdpPort>` (scoped to the slot's own debug origin, never `*`) so the local DevTools frontend can attach; without it Chrome 403s every browser DevTools WebSocket on the debug port. The debug-port flag trio (address + port + allow-origins) is declared once in a shared `chrome-args.cjs` and consumed by both the fresh launcher and the reopen path, so the origin allow-list can never drift away from the port.
|
|
33
|
+
- Extension `launch` now refreshes a slot's injected harness overlay from the runner whenever they diverge: `inject` stamps a source fingerprint into the slot manifest and each launch re-injects on mismatch (or when never installed). A runner change — e.g. a launcher flag — reaches every slot on the next launch instead of silently running a stale injected copy.
|
|
119
34
|
- Extension launch, readiness, reattach, actions, and screenshots preserve the operator's keyboard focus by default while retaining a headed, isolated CDP browser; macOS app launch uses Launch Services in the background, and explicit window focus remains available with `MM_HARNESS_FOCUS_BROWSER=1`.
|
|
120
35
|
- `mm-harness check diff --fix` now repairs only changed files with the checkout's direct ESLint and oxfmt/Prettier binaries, then runs the normal bounded validation, so agents do not need to guess repository lint scripts.
|
|
121
36
|
- Recipe-run infra healing now performs the adapter's runtime recovery before retrying instead of only recording a recovery label and immediately rerunning the recipe.
|
|
@@ -130,12 +45,7 @@
|
|
|
130
45
|
- `fixtures init --from <path>|--dev` initializes the canonical checkout wallet fixture explicitly; `--dev` is a disposable public test wallet and is never suitable for real funds.
|
|
131
46
|
|
|
132
47
|
### Fixed
|
|
133
|
-
-
|
|
134
|
-
- Checkout contention now uses one bounded JSON contract across `call`, `launch`, `doctor --fix`, `fixtures`, and `run`: exit 4 with `SANDBOX_BUSY` and an actionable lock path.
|
|
135
|
-
- Extension loaded-snapshot checks now use size/mtime comparison instead of full checksums, fall back to an in-process comparison when `rsync` is unavailable, and report comparison failures without forcing a misleading relaunch.
|
|
136
|
-
- Mobile Perps environment repair now publishes `.js.env` atomically without following destination symlinks, and Mobile source preflight returns an actionable `MOBILE_SOURCE_UNAVAILABLE` error for non-Git targets.
|
|
137
|
-
- Mobile no longer translates the Extension-only `visible=true` wait alias into an unsupported enum; `call --arg` accepts quoted JSON strings for numeric-looking string values.
|
|
138
|
-
- Timed streaming leaves now settle as soon as a SIGTERM-terminated direct child exits, reap SIGTERM-ignoring descendants, and forward Ctrl+C/SIGTERM to detached child trees before the harness exits.
|
|
48
|
+
- Extension `debug` now opens a working, offline DevTools console attached to the running slot's extension page: it launches the locally-served bundled DevTools frontend in its own window inside the slot's Chromium instead of Chrome's hosted `chrome-devtools-frontend.appspot.com` URL, which Chrome's WebSocket origin check rejected (the console showed "Debugging connection was closed"). A slot launched before this change fails a pre-open origin probe and reports the exact relaunch command instead of opening a dead console.
|
|
139
49
|
- `doctor --fix` now schema-validates, quarantines, and recreates malformed, semantically invalid, or cross-adapter-contaminated checkout runtime context without touching product data; wallet-fixture recovery commands use `--force` only for invalid or incomplete existing fixtures, while a missing fixture retains the safe unforced initialization command.
|
|
140
50
|
- `logs --source app` now resolves the adapter-owned application console (`extension-console.log` on Extension and the CDP-forwarded `metro.log` on Mobile); an absent console returns `APP_LOG_UNAVAILABLE` instead of falling back to a dev-server log or reporting a usage error.
|
|
141
51
|
- Doctor JSON now retains runtime probe failures, marks every diagnostic check as required or optional, derives its status from required checks, and reports runtime readiness separately.
|
package/README.md
CHANGED
|
@@ -1,137 +1,177 @@
|
|
|
1
|
-
# mm-harness
|
|
1
|
+
# MetaMask Recipe Runner — `mm-harness`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Extension, and Core. Run it inside a checkout; the product is auto-detected.
|
|
3
|
+
Architecture: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
**`mm-harness` is built for the agent but easy for the human to use and
|
|
6
|
+
understand.** It is the MetaMask recipe harness: one front door to launch the app,
|
|
7
|
+
prove behavior with recipes, and manage the per-checkout runtime overlay. It is a
|
|
8
|
+
thin MetaMask adapter over the generic `@farmslot/recipe-harness` engine — the
|
|
9
|
+
runner never re-implements graph execution, it binds to it. The agent gets full
|
|
10
|
+
depth (explicit flags, `--json`, ports, build tiers); the human gets short
|
|
11
|
+
commands, positional targets, good defaults, completions, and teaching
|
|
12
|
+
help/errors. Run it from inside a MetaMask Mobile/Extension/Core checkout and the
|
|
13
|
+
platform is auto-detected.
|
|
7
14
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
```
|
|
16
|
+
DAILY LOOP launch · logs · debug · fixtures what a teammate runs many times a day
|
|
17
|
+
DISCOVER actions · call · flows compose recipes from the vocabulary + flow library
|
|
18
|
+
PROVE run · doctor run recipes, check readiness
|
|
19
|
+
RUNTIME OVERLAY install · verify · cleanup manage the per-checkout runtime overlay
|
|
20
|
+
```
|
|
14
21
|
|
|
15
|
-
One
|
|
22
|
+
**One bin, no per-platform binaries.** `mm-harness` is the only command. Grammar:
|
|
23
|
+
`mm-harness <command> [target] [flags]` — the human types the bare command
|
|
24
|
+
(platform auto-detected) or a positional target (`mm-harness launch ios`); depth
|
|
25
|
+
lives in FLAGS with good defaults, never in extra command names. It ships shell
|
|
26
|
+
completions (zsh + bash) for commands, targets, and flags.
|
|
16
27
|
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
28
|
+
Naming: **"harness" is the tool** (`mm-harness`) and the generic engine package
|
|
29
|
+
(`@farmslot/recipe-harness`); the files it installs into a checkout are the
|
|
30
|
+
**runtime overlay**. Read [MENTAL-MODEL.md](docs/MENTAL-MODEL.md) first (the
|
|
31
|
+
before→after map), then [CLI-SPEC.md](docs/CLI-SPEC.md) for the full contract.
|
|
20
32
|
|
|
21
|
-
|
|
33
|
+
One package, two responsibilities:
|
|
22
34
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
mm-harness --version
|
|
26
|
-
mm-harness doctor
|
|
27
|
-
```
|
|
35
|
+
- **Recipe layer:** manifests, recipes, Mobile/Extension adapters, proof output.
|
|
36
|
+
- **Runtime layer:** start/reuse Metro or Chrome, seed fixtures, wait for readiness.
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
Farmslot and skills are wrappers around this CLI; they should not copy runner
|
|
39
|
+
logic.
|
|
30
40
|
|
|
31
|
-
##
|
|
41
|
+
## Quick start
|
|
32
42
|
|
|
33
|
-
|
|
43
|
+
Run from inside a MetaMask checkout (platform auto-detected):
|
|
34
44
|
|
|
35
45
|
```bash
|
|
36
|
-
#
|
|
37
|
-
mm-harness launch
|
|
38
|
-
mm-harness launch --sidepanel # open the sidepanel surface
|
|
39
|
-
|
|
40
|
-
# Mobile
|
|
41
|
-
mm-harness launch ios
|
|
42
|
-
mm-harness launch android
|
|
43
|
-
|
|
44
|
-
# Any product
|
|
45
|
-
mm-harness status
|
|
46
|
-
mm-harness logs
|
|
47
|
-
mm-harness debug
|
|
48
|
-
mm-harness fixtures set
|
|
49
|
-
```
|
|
46
|
+
# 1) Launch the app (installs the runtime overlay on first use, boots Metro/build)
|
|
47
|
+
mm-harness launch ios # mobile: ios | android; extension: just `launch`
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
sidepanel to see them. Use `launch --build` only when a clean rebuild is needed.
|
|
49
|
+
# 2) Run a recipe and write evidence
|
|
50
|
+
mm-harness run recipe.json --adapter mobile --artifacts-dir /tmp/recipe-artifacts --json
|
|
51
|
+
```
|
|
55
52
|
|
|
56
|
-
`
|
|
57
|
-
|
|
53
|
+
Outputs: `summary.json`, `trace.json`, screenshots, logs, and an artifact
|
|
54
|
+
manifest.
|
|
58
55
|
|
|
59
|
-
|
|
56
|
+
## Mental model
|
|
60
57
|
|
|
61
|
-
```
|
|
62
|
-
mm-harness
|
|
63
|
-
mm-harness
|
|
64
|
-
mm-harness logs --source webpack # Extension compiler
|
|
65
|
-
mm-harness logs --source app # Mobile app events
|
|
66
|
-
mm-harness logs --source metro # Mobile bundler
|
|
58
|
+
```text
|
|
59
|
+
mm-harness launch # runtime/orchestration: the app is ready
|
|
60
|
+
mm-harness run # runner/proof: actions execute and evidence is saved
|
|
67
61
|
```
|
|
68
62
|
|
|
69
|
-
|
|
63
|
+
Do not mix those layers. library/ = what recipes ARE (recipes, actions,
|
|
64
|
+
manifests — the content). src/ = what EXECUTES them (TypeScript CLI/engine glue,
|
|
65
|
+
typed adapters). adapters/ = what CONTROLS the app and its instances (start,
|
|
66
|
+
windows, wallet state, health, ports, parallel).
|
|
67
|
+
|
|
68
|
+
## Useful commands
|
|
70
69
|
|
|
71
70
|
```bash
|
|
72
|
-
|
|
73
|
-
mm-harness actions --action
|
|
74
|
-
mm-harness
|
|
75
|
-
mm-harness
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
mm-harness
|
|
71
|
+
# Capabilities (compose recipes from the vocabulary + flow library)
|
|
72
|
+
mm-harness actions --adapter mobile --json # the action vocabulary
|
|
73
|
+
mm-harness actions --adapter mobile --raw # raw action-manifest dump
|
|
74
|
+
mm-harness call unlock --adapter extension # run one action via the real engine path
|
|
75
|
+
mm-harness flows --json # reusable library flows, with provenance
|
|
76
|
+
|
|
77
|
+
# Readiness + proof
|
|
78
|
+
mm-harness doctor # read-only readiness check (no launch)
|
|
79
|
+
mm-harness doctor --fix # heal the overlay without launching
|
|
80
|
+
mm-harness run recipe.json --plan --adapter mobile # validate + plan, touch nothing
|
|
81
|
+
|
|
82
|
+
# Daily loop (run from inside a checkout)
|
|
83
|
+
mm-harness launch ios # launch (mobile: ios | android)
|
|
84
|
+
mm-harness logs # tail Metro/webpack + app logs
|
|
85
|
+
mm-harness debug # open the debug console
|
|
86
|
+
mm-harness fixtures sync # sync fixtures; `fixtures set` seeds the wallet
|
|
87
|
+
|
|
88
|
+
# Keep the install current
|
|
89
|
+
mm-harness update # upgrade to the published latest (prints old → new)
|
|
90
|
+
mm-harness update --check --json # report only — { current, latest, updateAvailable }
|
|
80
91
|
```
|
|
81
92
|
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
### Human validation rule
|
|
94
|
+
|
|
95
|
+
An exit code or `--json` result is not sufficient for a UI/debug command. After
|
|
96
|
+
`launch --verify`, confirm the debugger is visibly connected to the current
|
|
97
|
+
slot's app/profile. Repeat this check on every slot/platform that will be used
|
|
98
|
+
before release.
|
|
99
|
+
|
|
100
|
+
A passive once-a-day nudge prints one `stderr` line when a newer version is
|
|
101
|
+
published (`mm-harness <cur> → <latest> available · run: mm-harness update`). It
|
|
102
|
+
never blocks and never auto-updates. Silence it with `MM_HARNESS_NO_UPDATE_CHECK=1`
|
|
103
|
+
(auto-off in CI).
|
|
104
|
+
|
|
105
|
+
Set `RECIPE_LOG_UI=compact|full|quiet` (default `compact`) and `RECIPE_LOG_EVENTS=10`
|
|
106
|
+
to tune the compact log view during launch and Metro/webpack startup.
|
|
107
|
+
|
|
108
|
+
## Layout
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
bin/ the mm-harness entrypoint
|
|
112
|
+
src/ what EXECUTES recipes: TypeScript CLI/engine glue +
|
|
113
|
+
typed per-adapter logic (src/adapters/)
|
|
114
|
+
adapters/ what CONTROLS the app and its instances: launch/live/
|
|
115
|
+
watch/windows/wallet state/health/inject/cleanup per
|
|
116
|
+
platform, shared glue, porcelain, overlay payload +
|
|
117
|
+
manifest.json
|
|
118
|
+
library/ what recipes ARE: recipes/ (recipe JSONs), actions/
|
|
119
|
+
(per-platform implementations), manifests/ (capability)
|
|
120
|
+
scripts/ dev tooling (yarn check, local farmslot link, e2e
|
|
121
|
+
validation, adapter-surface-doctor)
|
|
122
|
+
docs/ details when this README is not enough
|
|
123
|
+
```
|
|
84
124
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
applicable, screenshots/logs, and `artifact-manifest.json`. Core is headless, so
|
|
88
|
-
browser/device diagnostics do not apply.
|
|
125
|
+
Defaults for installed harness/runtime paths live in
|
|
126
|
+
`adapters/shared/path-defaults.json`.
|
|
89
127
|
|
|
90
|
-
|
|
91
|
-
side-effecting command.
|
|
128
|
+
## Runtime-readiness ownership
|
|
92
129
|
|
|
93
|
-
|
|
130
|
+
Generic readiness mechanics live in `@farmslot/recipe-harness` (0.3+):
|
|
94
131
|
|
|
95
|
-
|
|
132
|
+
- `@farmslot/recipe-harness/runtime/deps-readiness` — install fingerprint + baseline
|
|
133
|
+
- `@farmslot/recipe-harness/runtime/log-analysis` — bundle-log boundaries, unresolved-module scoping
|
|
134
|
+
- `@farmslot/recipe-harness/runtime/metro-probe` — Metro `/status` reachability
|
|
96
135
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
mm-harness
|
|
100
|
-
|
|
136
|
+
This repo adds **MetaMask adapters only**: `adapters/mobile/deps-markers.ts`,
|
|
137
|
+
`adapters/mobile/runtime-decision.ts`, `adapters/extension/runtime-decision.ts`,
|
|
138
|
+
and shell launch in `adapters/porcelain/mm-recipe` / `adapters/porcelain/mme-recipe`. Do not re-copy harness
|
|
139
|
+
primitives into `adapters/shared/`. CI installs harness from npm — publish
|
|
140
|
+
`@farmslot/recipe-harness` before bumping the dependency here.
|
|
101
141
|
|
|
102
|
-
|
|
103
|
-
its own acceptance criteria. See [recipe libraries](docs/recipe-libraries.md).
|
|
142
|
+
## Dev/prod harness (`MM_HARNESS_BIN`)
|
|
104
143
|
|
|
105
|
-
|
|
144
|
+
The global npm install owns the `mm-harness` on `PATH` — that is the **prod**
|
|
145
|
+
harness. To run a **dev** checkout with active pre-release changes alongside it,
|
|
146
|
+
set `MM_HARNESS_BIN` to that checkout's `bin/mm-harness`:
|
|
106
147
|
|
|
107
148
|
```bash
|
|
108
|
-
mm-harness
|
|
109
|
-
|
|
110
|
-
mm-harness verify # verify the installed runtime overlay
|
|
111
|
-
mm-harness cleanup # remove the runtime overlay
|
|
149
|
+
export MM_HARNESS_BIN=/path/to/checkout/bin/mm-harness # dev: this checkout owns the run
|
|
150
|
+
unset MM_HARNESS_BIN # prod: the installed/global bin
|
|
112
151
|
```
|
|
113
152
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
153
|
+
`MM_HARNESS_BIN` is the single override point: when set, the entrypoint hands the
|
|
154
|
+
whole invocation to that path before doing any dependency work; when unset it
|
|
155
|
+
resolves the installed bin. A dev checkout is never installed globally, so there is
|
|
156
|
+
no `PATH` collision — dev is reached only through `MM_HARNESS_BIN` (or a shell
|
|
157
|
+
alias). A per-farm environment can export it so the dev farm dispatches through the
|
|
158
|
+
dev harness while the prod farm leaves it unset.
|
|
117
159
|
|
|
118
|
-
##
|
|
119
|
-
|
|
120
|
-
Use a source checkout without replacing the global install:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
export MM_HARNESS_BIN=/path/to/metamask-harness/bin/mm-harness
|
|
124
|
-
mm-harness --version
|
|
125
|
-
```
|
|
160
|
+
## Runtime notes
|
|
126
161
|
|
|
127
|
-
|
|
162
|
+
- `tmux` is recommended for long-lived Metro/webpack processes; standalone use
|
|
163
|
+
falls back to detached `nohup` where possible.
|
|
164
|
+
- Mobile may inject a local development bridge/HUD into older checkouts. Do not
|
|
165
|
+
commit those product patches.
|
|
166
|
+
- Extension does not patch product source; it drives `dist/chrome` through Chrome
|
|
167
|
+
CDP.
|
|
128
168
|
|
|
129
|
-
Validate changes
|
|
169
|
+
## Validate changes
|
|
130
170
|
|
|
131
171
|
```bash
|
|
132
172
|
yarn check
|
|
173
|
+
bash -n bin/mm-harness adapters/porcelain/{metamask-recipe,mm-recipe,mme-recipe} adapters/{mobile,extension,core}/*.sh
|
|
174
|
+
node --check adapters/extension/inject.mjs adapters/extension/cleanup.mjs adapters/extension/readiness.mjs adapters/extension/launch-browser.cjs adapters/shared/open-debug.mjs adapters/shared/cli-home.mjs adapters/shared/log-tui.mjs adapters/shared/progress.mjs adapters/shared/recipe-paths.mjs scripts/check.mjs
|
|
133
175
|
```
|
|
134
176
|
|
|
135
|
-
|
|
136
|
-
and [human QA](docs/CLI-ERGONOMICS-HUMAN-QA.md). Maintainers also have the
|
|
137
|
-
[architecture](docs/architecture.md) and [video gate](docs/VIDEO-DEMO-VALIDATION.md).
|
|
177
|
+
More detail: [Architecture](docs/architecture.md), [Package boundaries](docs/package-boundaries.md), [Runtime file conventions](docs/runtime-file-conventions.md).
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// the tab shows live extension logs (the equivalent of the Metro/webpack tabs).
|
|
9
9
|
//
|
|
10
10
|
// Usage:
|
|
11
|
-
// console-tail.mjs --cdp-port <port> [--
|
|
11
|
+
// console-tail.mjs --cdp-port <port> [--log <file>]
|
|
12
12
|
//
|
|
13
13
|
// Resilience: MV3 service workers cycle on idle and UI pages open/close, so we
|
|
14
14
|
// re-poll /json/list every ~2s and (re)attach to any extension target that is
|
|
@@ -19,10 +19,9 @@
|
|
|
19
19
|
'use strict';
|
|
20
20
|
|
|
21
21
|
import { appendFileSync } from 'node:fs';
|
|
22
|
-
import path from 'node:path';
|
|
23
22
|
|
|
24
23
|
function parseArgs(argv) {
|
|
25
|
-
const args = { cdpPort: null,
|
|
24
|
+
const args = { cdpPort: null, log: null };
|
|
26
25
|
for (let i = 0; i < argv.length; i += 1) {
|
|
27
26
|
const arg = argv[i];
|
|
28
27
|
switch (arg) {
|
|
@@ -30,16 +29,12 @@ function parseArgs(argv) {
|
|
|
30
29
|
args.cdpPort = argv[++i];
|
|
31
30
|
break;
|
|
32
31
|
case '--log':
|
|
33
|
-
|
|
34
|
-
args.extensionLog = argv[++i];
|
|
35
|
-
break;
|
|
36
|
-
case '--dapp-log':
|
|
37
|
-
args.dappLog = argv[++i];
|
|
32
|
+
args.log = argv[++i];
|
|
38
33
|
break;
|
|
39
34
|
case '-h':
|
|
40
35
|
case '--help':
|
|
41
36
|
process.stdout.write(
|
|
42
|
-
'Usage: console-tail.mjs --cdp-port <port> [--
|
|
37
|
+
'Usage: console-tail.mjs --cdp-port <port> [--log <file>]\n',
|
|
43
38
|
);
|
|
44
39
|
process.exit(0);
|
|
45
40
|
break;
|
|
@@ -56,9 +51,6 @@ if (!Number.isInteger(cdpPort) || cdpPort <= 0) {
|
|
|
56
51
|
throw new Error('console-tail requires a numeric --cdp-port.');
|
|
57
52
|
}
|
|
58
53
|
const HOST = `127.0.0.1:${cdpPort}`;
|
|
59
|
-
if (args.extensionLog && !args.dappLog) {
|
|
60
|
-
args.dappLog = path.join(path.dirname(path.resolve(args.extensionLog)), 'dapp-console.log');
|
|
61
|
-
}
|
|
62
54
|
|
|
63
55
|
if (typeof WebSocket === 'undefined') {
|
|
64
56
|
throw new Error('console-tail requires Node 22+ with a global WebSocket.');
|
|
@@ -73,9 +65,9 @@ const cooldown = new Map();
|
|
|
73
65
|
// Writes formatted console-event strings (never raw HTTP response bodies) to
|
|
74
66
|
// stdout and optionally to a caller-supplied log file. The source is the local
|
|
75
67
|
// Chrome CDP WebSocket (127.0.0.1:<cdpPort>) — a trusted-local endpoint.
|
|
76
|
-
function out(line
|
|
68
|
+
function out(line) {
|
|
77
69
|
process.stdout.write(`${line}\n`);
|
|
78
|
-
if (
|
|
70
|
+
if (args.log) appendFileSync(args.log, `${line}\n`);
|
|
79
71
|
}
|
|
80
72
|
|
|
81
73
|
function stamp() {
|
|
@@ -103,22 +95,6 @@ function isExtensionTarget(target) {
|
|
|
103
95
|
return String(target.url || '').startsWith('chrome-extension://');
|
|
104
96
|
}
|
|
105
97
|
|
|
106
|
-
function isDappTarget(target) {
|
|
107
|
-
if (!target || !target.webSocketDebuggerUrl || target.type !== 'page') return false;
|
|
108
|
-
try {
|
|
109
|
-
const url = new URL(String(target?.url || ''));
|
|
110
|
-
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
111
|
-
} catch {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function targetStream(target) {
|
|
117
|
-
if (isExtensionTarget(target)) return { kind: 'extension', log: args.extensionLog };
|
|
118
|
-
if (isDappTarget(target)) return { kind: 'dapp', log: args.dappLog };
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
98
|
function previewArg(arg) {
|
|
123
99
|
if (!arg || typeof arg !== 'object') return String(arg);
|
|
124
100
|
if ('value' in arg && arg.value !== undefined) {
|
|
@@ -132,29 +108,29 @@ function previewArg(arg) {
|
|
|
132
108
|
return arg.subtype || arg.type || '?';
|
|
133
109
|
}
|
|
134
110
|
|
|
135
|
-
function emitConsole(label, params
|
|
111
|
+
function emitConsole(label, params) {
|
|
136
112
|
const level = String(params.type || 'log').toUpperCase();
|
|
137
113
|
const text = (params.args || []).map(previewArg).join(' ');
|
|
138
|
-
out(`${stamp()} [${label}] ${level} ${text}
|
|
114
|
+
out(`${stamp()} [${label}] ${level} ${text}`);
|
|
139
115
|
}
|
|
140
116
|
|
|
141
|
-
function emitException(label, params
|
|
117
|
+
function emitException(label, params) {
|
|
142
118
|
const d = params.exceptionDetails || {};
|
|
143
119
|
const text =
|
|
144
120
|
d.exception?.description ||
|
|
145
121
|
d.exception?.value ||
|
|
146
122
|
d.text ||
|
|
147
123
|
'uncaught exception';
|
|
148
|
-
out(`${stamp()} [${label}] EXCEPTION ${text}
|
|
124
|
+
out(`${stamp()} [${label}] EXCEPTION ${text}`);
|
|
149
125
|
}
|
|
150
126
|
|
|
151
|
-
function emitLogEntry(label, params
|
|
127
|
+
function emitLogEntry(label, params) {
|
|
152
128
|
const e = params.entry || {};
|
|
153
129
|
const level = String(e.level || 'log').toUpperCase();
|
|
154
|
-
out(`${stamp()} [${label}] ${level} ${e.text || ''}
|
|
130
|
+
out(`${stamp()} [${label}] ${level} ${e.text || ''}`);
|
|
155
131
|
}
|
|
156
132
|
|
|
157
|
-
function handleMessage(label,
|
|
133
|
+
function handleMessage(label, data) {
|
|
158
134
|
let message;
|
|
159
135
|
try {
|
|
160
136
|
message = JSON.parse(data);
|
|
@@ -165,13 +141,13 @@ function handleMessage(label, destination, data) {
|
|
|
165
141
|
if (message.id != null) return; // command ack, not an event
|
|
166
142
|
switch (message.method) {
|
|
167
143
|
case 'Runtime.consoleAPICalled':
|
|
168
|
-
emitConsole(label, message.params || {}
|
|
144
|
+
emitConsole(label, message.params || {});
|
|
169
145
|
break;
|
|
170
146
|
case 'Runtime.exceptionThrown':
|
|
171
|
-
emitException(label, message.params || {}
|
|
147
|
+
emitException(label, message.params || {});
|
|
172
148
|
break;
|
|
173
149
|
case 'Log.entryAdded':
|
|
174
|
-
emitLogEntry(label, message.params || {}
|
|
150
|
+
emitLogEntry(label, message.params || {});
|
|
175
151
|
break;
|
|
176
152
|
default:
|
|
177
153
|
break;
|
|
@@ -179,11 +155,9 @@ function handleMessage(label, destination, data) {
|
|
|
179
155
|
}
|
|
180
156
|
|
|
181
157
|
function attach(target) {
|
|
182
|
-
const
|
|
183
|
-
if (!stream) return;
|
|
184
|
-
const label = `${stream.kind}:${shortLabel(target)}`;
|
|
158
|
+
const label = shortLabel(target);
|
|
185
159
|
const ws = new WebSocket(target.webSocketDebuggerUrl);
|
|
186
|
-
const entry = { ws, label,
|
|
160
|
+
const entry = { ws, label, opened: false };
|
|
187
161
|
attached.set(target.id, entry);
|
|
188
162
|
|
|
189
163
|
ws.addEventListener('open', () => {
|
|
@@ -192,16 +166,16 @@ function attach(target) {
|
|
|
192
166
|
for (const method of ['Runtime.enable', 'Log.enable']) {
|
|
193
167
|
ws.send(JSON.stringify({ id: ++id, method, params: {} }));
|
|
194
168
|
}
|
|
195
|
-
out(`${stamp()} [${label}] [attached]
|
|
169
|
+
out(`${stamp()} [${label}] [attached]`);
|
|
196
170
|
});
|
|
197
171
|
ws.addEventListener('message', (event) => {
|
|
198
|
-
handleMessage(label,
|
|
172
|
+
handleMessage(label, typeof event.data === 'string' ? event.data : '');
|
|
199
173
|
});
|
|
200
174
|
const drop = () => {
|
|
201
175
|
if (attached.get(target.id) !== entry) return;
|
|
202
176
|
attached.delete(target.id);
|
|
203
177
|
if (entry.opened) {
|
|
204
|
-
out(`${stamp()} [${label}] [reconnect] target detached; will re-attach
|
|
178
|
+
out(`${stamp()} [${label}] [reconnect] target detached; will re-attach`);
|
|
205
179
|
} else {
|
|
206
180
|
// Never connected (target gone / not debuggable yet): back off so a dead
|
|
207
181
|
// target is not retried — and logged — on every 2s poll.
|
|
@@ -222,9 +196,8 @@ async function poll() {
|
|
|
222
196
|
// CDP not reachable this tick (browser starting/restarting); retry next poll.
|
|
223
197
|
return;
|
|
224
198
|
}
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
if (!targetStream(target)) continue;
|
|
199
|
+
for (const target of Array.isArray(targets) ? targets : []) {
|
|
200
|
+
if (!isExtensionTarget(target)) continue;
|
|
228
201
|
if (attached.has(target.id)) continue;
|
|
229
202
|
const until = cooldown.get(target.id);
|
|
230
203
|
if (until !== undefined) {
|
|
@@ -253,6 +226,6 @@ function shutdown() {
|
|
|
253
226
|
process.on('SIGINT', shutdown);
|
|
254
227
|
process.on('SIGTERM', shutdown);
|
|
255
228
|
|
|
256
|
-
out(`${stamp()} [console-tail] streaming extension
|
|
229
|
+
out(`${stamp()} [console-tail] streaming extension console via cdp ${cdpPort}`);
|
|
257
230
|
await poll();
|
|
258
231
|
setInterval(poll, 2000);
|
|
@@ -277,6 +277,7 @@ const fs = require('fs');
|
|
|
277
277
|
const http = require('http');
|
|
278
278
|
const { execSync, execFileSync } = require('child_process');
|
|
279
279
|
let chromium; try { chromium = require('@playwright/test').chromium; } catch { chromium = require('playwright').chromium; }
|
|
280
|
+
const { remoteDebuggingArgs } = require(path.join('${SCRIPT_DIR}', 'lib/chrome-args.cjs'));
|
|
280
281
|
|
|
281
282
|
const SLOT_ID = '${SLOT_ID}';
|
|
282
283
|
const AGENT_DIR = '${AGENT_DIR}';
|
|
@@ -309,7 +310,12 @@ const resumeWebpack = () => {
|
|
|
309
310
|
'--no-default-browser-check',
|
|
310
311
|
'--window-size=420,800',
|
|
311
312
|
];
|
|
312
|
-
|
|
313
|
+
// Debug-port trio (address + port + scoped allow-origins) from the shared module
|
|
314
|
+
// so the DevTools origin allow-list can never drift away from the port; without
|
|
315
|
+
// it Chrome 403s every browser DevTools WebSocket and mm-harness debug can't attach.
|
|
316
|
+
if (CDP_PORT) {
|
|
317
|
+
args.push(...remoteDebuggingArgs(CDP_PORT));
|
|
318
|
+
}
|
|
313
319
|
|
|
314
320
|
const chromiumApp = path.dirname(path.dirname(path.dirname(chromium.executablePath())));
|
|
315
321
|
execFileSync('open', ['-g', '-n', '-a', chromiumApp, '--args', ...args], { stdio: 'ignore' });
|