@deeeed/metamask-harness 0.18.0 → 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 +187 -0
- package/README.md +4 -7
- package/adapters/core/inject.sh +1 -6
- package/adapters/extension/inject.mjs +1 -4
- package/adapters/extension/verify.sh +1 -1
- package/adapters/mobile/inject.sh +5 -4
- package/adapters/mobile/verify.sh +15 -19
- package/adapters/shared/harness-source-fingerprint.mjs +14 -12
- package/dist/adapters/harness-freshness.js +49 -0
- package/dist/cli.js +0 -4
- package/dist/command-contract.js +51 -40
- package/dist/command-journal.js +50 -12
- package/dist/commands/call.js +95 -20
- package/dist/commands/check.js +1 -1
- package/dist/commands/completion-candidates.js +7 -19
- package/dist/commands/fixtures.js +50 -1
- package/dist/commands/last.js +9 -1
- package/dist/commands/launch/extension.js +2 -2
- package/dist/commands/launch/mobile.js +2 -0
- package/dist/commands/list-executables.js +56 -20
- package/dist/commands/manifest.js +28 -12
- package/dist/commands/parse-args.js +55 -3
- package/dist/commands/provision.js +0 -1
- package/dist/commands/run-engine.js +514 -336
- package/dist/commands/run.js +25 -37
- package/dist/commands/shared.js +1 -1
- package/dist/heal-bounds.js +5 -0
- package/dist/mm-harness-cli.js +22 -30
- package/dist/run-diagnostics.js +1 -1
- package/dist/run-recording.js +1 -1
- package/dist/runner.js +24 -2
- package/docs/CONTRIBUTING.md +2 -3
- package/docs/QA.md +0 -1
- package/docs/RECIPES.md +52 -91
- package/library/README.md +5 -5
- package/library/actions/core/perps/_controller.mjs +33 -1
- 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/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/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/library.json +1 -1
- package/library/manifests/core.action-manifest.json +1170 -413
- package/library/manifests/extension.action-manifest.json +1495 -641
- package/library/manifests/mobile.action-manifest.json +1704 -769
- 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 -405
- package/library/recipes/runner/action-validation.mobile.recipe.json +316 -409
- package/library/recipes/runner/smoke.core.recipe.json +18 -20
- 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 +33 -35
- package/library/recipes/wallet/smoke.mobile.recipe.json +33 -35
- package/package.json +3 -3
- package/scripts/completions.sh +1 -4
- package/dist/adapters/extension/harness-freshness.js +0 -39
- package/dist/commands/flows.js +0 -91
- package/library/flows/perps.flows.json +0 -64
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.19.0 - 2026-07-22
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Discover a task recipe's adjacent `recipe-library/` without extra flags.
|
|
10
|
+
- Recipe execution now accepts typed root `key=value` parameters, applies defaults, and resolves nested recipes through the same adapter-aware index.
|
|
11
|
+
- `run --list` and `run --describe` now expose parameter defaults, adapter variants, nested recipes, sources, and shadows.
|
|
12
|
+
- Runs now retain exact digest-keyed dependency recipes and `recipe-resolution.json`.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Made bare `mm-harness fixtures` report the current fixture status and next action instead of failing with an option dump.
|
|
17
|
+
- Simplified CLI usage failures and `run --help`; removed duplicate `--project-root`, `--record`, and logical-adapter `--platform` spellings while retaining `--platform ios|android`.
|
|
18
|
+
- Direct calls teach missing/invalid values, show declared defaults, omit routine library provenance, and reject implicit Perps assertion/mutation targets.
|
|
19
|
+
- Perps reads without a selector consistently return all live items across Extension, Mobile, and Core.
|
|
20
|
+
- `run` errors lead to recipe discovery instead of dumping every flag; help separates common overrides from managed integration controls.
|
|
21
|
+
- Declared team and task-library actions retain source provenance through the packaged adapter path.
|
|
22
|
+
- Validate every bundled recipe dependency graph during `yarn check` so missing or cyclic `call.ref` values fail before runtime.
|
|
23
|
+
- Require Farmslot protocol `^0.11.0` and recipe-harness `^0.9.0` for composable Recipe v1 execution.
|
|
24
|
+
- Discovery now exposes callable actions through `call --list` and executable recipes through `run --list`.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Deduplicate recipe-library output and reduce application failures to their actionable message while retaining full trace detail.
|
|
29
|
+
- `last` now shows the redacted command and evidence paths, including automatically resolved run/call artifact directories.
|
|
30
|
+
- `run --describe` reports the recipe's exact `$schema` URL instead of a fabricated nested version.
|
|
31
|
+
- `run --plan` rejects invalid parameters passed into nested recipes.
|
|
32
|
+
- Command journals redact sensitive keys inside standalone JSON arguments.
|
|
33
|
+
- Core Perps actions support the current Core `tsx` module export shape.
|
|
34
|
+
- Recipe delegation preserves upstream non-zero exit status and uses the public `mm-harness` name in recovery commands.
|
|
35
|
+
- Recipe discovery and repeated `--library` flags preserve every source in declared precedence order.
|
|
36
|
+
|
|
37
|
+
### Removed
|
|
38
|
+
|
|
39
|
+
- Removed redundant `--project-root`, bare `--record`, and logical-adapter uses of `run`/`call --platform`; use `--target`, `--record-video`, and `--adapter`.
|
|
40
|
+
- Removed flow catalogs, flow promotion, the `flows` command, and their completion surface; reusable graphs are composable Recipe v1 documents.
|
|
41
|
+
|
|
42
|
+
## 0.18.0 - 2026-07-20
|
|
43
|
+
|
|
5
44
|
### Added
|
|
6
45
|
|
|
7
46
|
- Recipe runs now preflight source provenance and action risk before runtime preparation; untrusted restricted plans require exact-digest approval.
|
|
@@ -98,11 +137,13 @@
|
|
|
98
137
|
- `checklist mark ... complete` now teaches the exact compact quality input, canonical builder command, and coverage artifact when a recipe activates those terminal requirements, instead of forcing agents to reverse-engineer the artifact validator.
|
|
99
138
|
|
|
100
139
|
### Added
|
|
140
|
+
|
|
101
141
|
- Checkout-scoped operation locking prevents concurrent launch, fixture mutation, and recipe execution in one repository while allowing other checkouts/slots to run independently; stale locks from exited processes are reclaimed.
|
|
102
142
|
- `doctor --fix` creates an ignored, checkout-scoped `agentic-runtime.json` when absent, with stable claimed local ports for ordinary standalone clones while preserving explicit or Farmslot-provided slot resources.
|
|
103
143
|
- `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.
|
|
104
144
|
|
|
105
145
|
### Fixed
|
|
146
|
+
|
|
106
147
|
- 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.
|
|
107
148
|
- `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.
|
|
108
149
|
- `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.
|
|
@@ -135,23 +176,27 @@
|
|
|
135
176
|
## 0.14.7 - 2026-07-10
|
|
136
177
|
|
|
137
178
|
### Changed
|
|
179
|
+
|
|
138
180
|
- `doctor --print-ready` now implies the exit-coded live probe — Farmslot `health_check` hooks need only `--print-ready`, not `--expect-live --print-ready`.
|
|
139
181
|
- Mobile `--print-ready` uses bridge `walletState` (unlocked + live bridge), not React Navigation route names; mobile `ready_indicator` is `OK`.
|
|
140
182
|
- Removed `metamask-recipe` install symlinks from adapter inject paths (no compat aliases).
|
|
141
183
|
- `doctor --print-ready` rejects `--json` (stdout is reserved for the Farmslot indicator line).
|
|
142
184
|
|
|
143
185
|
### Fixed
|
|
186
|
+
|
|
144
187
|
- Mobile `surface.runtimeStatus` infers Android from `ADB_SERIAL` / `ANDROID_SERIAL` when present.
|
|
145
188
|
|
|
146
189
|
## 0.14.6 - 2026-07-10
|
|
147
190
|
|
|
148
191
|
### Added
|
|
192
|
+
|
|
149
193
|
- `mm-harness doctor --print-ready` — Farmslot `health_check` mode: prints `health.ready_indicator` on stdout (`extension`/`mobile`: `OK`; `core`: `ready`).
|
|
150
194
|
- `doctor --expect-live` — exit-coded liveness gate without indicator output (prepare recovery and other pass/fail callers).
|
|
151
195
|
|
|
152
196
|
## 0.14.5 - 2026-07-10
|
|
153
197
|
|
|
154
198
|
### Fixed
|
|
199
|
+
|
|
155
200
|
- Extension `ensure-browser` closes disposable New Tab / blank / extensions pages after reopen, matching reattach/ensure-ready hygiene.
|
|
156
201
|
- Extension slot browser titles are stamped through one shared helper (`adapters/extension/lib/slot-title.cjs`) with a persistent `MutationObserver`, and re-applied after `ensureExtensionReady` open/prune/reopen so relaunch and recipe paths keep `<slot-id> — MetaMask` instead of a bare MetaMask window.
|
|
157
202
|
- Extension slot-title contract test is hermetic (local CDP/WebSocket stub + fake DOM); Playwright and CDP stamps share one function source so they cannot drift.
|
|
@@ -160,11 +205,13 @@
|
|
|
160
205
|
## 0.14.4 - 2026-07-09
|
|
161
206
|
|
|
162
207
|
### Fixed
|
|
208
|
+
|
|
163
209
|
- Include the new extension viewer cleanup scripts in the adapter manifest so published packages pass adapter-surface validation.
|
|
164
210
|
|
|
165
211
|
## 0.14.3 - 2026-07-09
|
|
166
212
|
|
|
167
213
|
### Fixed
|
|
214
|
+
|
|
168
215
|
- Extension `status` and `doctor` now accept a sidepanel-only live runtime, matching `run`/`call` health checks instead of requiring a fullscreen `home.html` tab after `launch --sidepanel`.
|
|
169
216
|
- Extension sidepanel launch waits longer for Chrome to expose the `sidepanel.html` CDP target, avoiding false failures after Chrome accepts the open request.
|
|
170
217
|
- Extension tmux viewers are opened only in the run-owned tmux session and are cleaned by `mm-harness stop`, preventing stale `webpack-*`/`console-*` windows from leaking across slots.
|
|
@@ -173,15 +220,18 @@
|
|
|
173
220
|
## 0.14.2 - 2026-07-09
|
|
174
221
|
|
|
175
222
|
### Fixed
|
|
223
|
+
|
|
176
224
|
- Require `@farmslot/recipe-harness` `^0.4.3` so runtime dependency readiness trusts install markers newer than an old recorded baseline and stops repeatedly prompting managed slots to reinstall fresh dependencies.
|
|
177
225
|
|
|
178
226
|
## 0.14.1 - 2026-07-09
|
|
179
227
|
|
|
180
228
|
### Added
|
|
229
|
+
|
|
181
230
|
- `mm-harness check diff` runs bounded repo-local validation for the active git diff, writing `validation-summary.json`/`.md` plus per-check logs. The fast profile runs changed-file ESLint, Prettier, and changed test files; `--profile full` also runs the repo typecheck when available. The default base follows the active PR base or repo remote HEAD before falling back to common branch names.
|
|
182
231
|
- `mm-harness run` writes a concise human report (`report.md`) and prints a colored step summary for every adapter, so successful Core/Mobile/Extension recipe runs are scannable without opening raw trace files.
|
|
183
232
|
|
|
184
233
|
### Fixed
|
|
234
|
+
|
|
185
235
|
- Mobile slot targeting now refuses a platform launch/run/call when `--platform ios|android` conflicts with the configured default target, preventing an iOS-pinned slot from silently stealing a shared Android device; `status` and `doctor` scope device lists to the configured target by default and `status` reports other reachable bridges as additional targets that can be driven with `--device`.
|
|
186
236
|
- Mobile `status` bases `Next:` on the configured default target only, avoids assigning an additional Android bridge to a same-platform selected device, and reports stale Android reverse ports when the selected device is not connected to the slot Metro.
|
|
187
237
|
- Mobile `doctor` now reports the same additional reachable targets as `status`, so diagnostics and the home view agree on which devices can be driven with `--device`.
|
|
@@ -198,11 +248,13 @@
|
|
|
198
248
|
## 0.14.0 - 2026-07-08
|
|
199
249
|
|
|
200
250
|
### Added
|
|
251
|
+
|
|
201
252
|
- `mm-harness call` accepts action fields as direct `key=value` shorthand in addition to repeated `--arg k=v`, so commands like `mm-harness call ui.navigate page=perps` now match the examples agents naturally write.
|
|
202
253
|
- Packaged recipes are grouped by domain under `library/recipes/<domain>/` and still resolve by dotted names (`perps.smoke`, `runner.smoke`) with legacy aliases for the former flat names.
|
|
203
254
|
- Packaged `perps.smoke` recipes for mobile, extension, and core provide an explicit non-mutating Perps domain smoke. The existing bare `smoke` alias remains a runner/transport smoke for compatibility.
|
|
204
255
|
|
|
205
256
|
### Fixed
|
|
257
|
+
|
|
206
258
|
- The top-level help SLOT banner now labels the slot dev-server port by adapter, so extension checkouts show `webpack :<port>` instead of the mobile-only `metro :<port>`.
|
|
207
259
|
- Hidden internal runtime commands remain executable through the installed `mm-harness` bin, fixing Extension verify warnings where `runtime-decision` returned `{}` because the wrapper blocked its own shipped helper.
|
|
208
260
|
- Extension launch/readiness now stamps the live home tab title with the Farmslot slot id after MetaMask has settled, so headed browser windows identify their owning slot.
|
|
@@ -215,11 +267,13 @@
|
|
|
215
267
|
## 0.13.0 - 2026-07-08
|
|
216
268
|
|
|
217
269
|
### Added
|
|
270
|
+
|
|
218
271
|
- Typed cdp-bridge failure codes (`NO_TARGET`, `CDP_TIMEOUT`, `WS_CLOSED`, `METRO_UNREACHABLE`): the bridge classifies a failure at its source and reports it three ways a caller can recover — an `ERROR[<CODE>]:` stderr marker, a code-specific exit status (10–13), and a `Next:` teaching line for the caller's actual situation. `bridge.mjs` attaches the code to the error it throws, and `app.hud` lifecycle-skip classification (`isMobileHudLifecycleSkip`) branches on the code first, keeping the substring needles only as a fallback for output from a bridge that predates the codes. The needle fallback is now case-insensitive, closing a gap where target-discovery's `Pinned Android device …` (capital A) missed a lowercase needle.
|
|
219
272
|
- Console-forwarder now expands object/array console arguments in `metro.log` from the Hermes-supplied inline `preview` (e.g. `{ symbol: "BTC", px: 42 }` instead of the literal `Object`), bounded one level deep and rendered synchronously so the stream never blocks; objects without a preview degrade to their description.
|
|
220
273
|
- `mm-harness call <action> --help` now renders the named action's own field schema (name, type, required, description, example — from the action manifest) above the generic call flags, instead of printing only the generic call help. Fuzzy short-name resolves like `call` (an ambiguous prefix shows every match); an unresolvable name falls back to the generic help plus a pointer to `mm-harness actions`. `run <recipe> --help` is unchanged (recipe-specific help is a separate, larger surface — recipes are not in the action manifest).
|
|
221
274
|
|
|
222
275
|
### Fixed
|
|
276
|
+
|
|
223
277
|
- Runner construction no longer fails with `Manifest action app.lifecycle has no registered adapter` when a manifest declaring `app.lifecycle` is used with a non-mobile adapter (e.g. `call --adapter core --action-manifest library/manifests/mobile.action-manifest.json`): lifecycle adapter registration is manifest-driven instead of gated on the mobile adapter. Executing the action outside a mobile run still fails explicitly at target resolution.
|
|
224
278
|
- Mobile run teardown always clears any HUD step left painted on-device, so a failed run no longer strands a FAIL banner for the next run. Best-effort and bounded: a down/transitioning bridge simply has nothing to clear and never masks the run's real outcome.
|
|
225
279
|
- start-metro quick-launch now applies the dev Sentry DSN remap (`MM_SENTRY_DSN` defaults to `MM_SENTRY_DSN_DEV` when unset) at both launch paths. The quick-launch runs `expo start` directly and bypasses `scripts/build.sh`, which normally performs this remap, so without it Sentry never initialized in quick-launched dev clients.
|
|
@@ -228,9 +282,11 @@
|
|
|
228
282
|
## 0.12.0 - 2026-07-08
|
|
229
283
|
|
|
230
284
|
### Added
|
|
285
|
+
|
|
231
286
|
- Mobile console-forwarder: restores the device console (incl. DevLogger) in `metro.log` on RN 0.79+/Bridgeless via persistent CDP streaming (`Runtime.consoleAPICalled`) — one session per device JS-runtime page (shared target-discovery ranking, never the native C++ page), buffer replay + persisted last-seen cursor (timestamp + same-stamp texts) deduping across reconnects/app reloads, auto-started by `start-metro`; opt out with `METAMASK_RECIPE_CONSOLE_FORWARD=0`. Grep `[console:` for device lines. Zero-dependency transport (built-in Node 22+ WebSocket, like the CDP bridge client). Yields to interactive React Native DevTools: a session evicted by another debugger with no bridge lock present backs off for 5 minutes instead of evicting the human every discovery tick. Idles at the slow poll cadence while Metro is down; flushes pending lines and dedupe state synchronously on SIGTERM/SIGINT.
|
|
232
287
|
|
|
233
288
|
### Fixed
|
|
289
|
+
|
|
234
290
|
- `app.hud` no longer aborts recipes on `CDP message timeout` / `WebSocket closed` during dev-client lifecycle transitions (0.11.0 regression that failed every warm-start run at `foreground-app`/`ensure-unlocked`). Skips are loud: the reason is written to stderr and recorded in the action result, so a masked real failure remains visible.
|
|
235
291
|
- cdp-bridge takes a runtime lock (`cdp-bridge.lock`) so the console-forwarder yields the single debugger slot during bridge commands — prevents mutual eviction and lost `Runtime.evaluate` replies. The forwarder honors the lock while the pid inside it is alive (`kill -0`), so long commands (wallet setup runs `CDP_TIMEOUT=120000`) are never evicted mid-flight while a crashed/killed bridge releases immediately; the bridge releases on SIGTERM/SIGINT, only unlinks a lock it still owns (last-writer-wins under overlap), and takes no lock for `--help`/unknown commands.
|
|
236
292
|
- `stop-metro` and mobile `cleanup` stop the console-forwarder (recorded pid + checkout-scoped sweep), so no orphan forwarder outlives Metro or fights a later one for the debugger slot.
|
|
@@ -239,14 +295,17 @@
|
|
|
239
295
|
## 0.11.0 - 2026-07-07
|
|
240
296
|
|
|
241
297
|
### Added
|
|
298
|
+
|
|
242
299
|
- Mobile recipes can now use the standard outer `app.lifecycle` action for deterministic performance start states without rebuilding (Android background/foreground/terminate/restart, iOS simulator launch/terminate/restart through the shared Farmslot lifecycle adapter).
|
|
243
300
|
- `fixtures set --device <serial|udid|name>` now pins mobile fixture sync to the requested device using the same targeting rules as `run`, `call`, and `doctor`.
|
|
244
301
|
- New lifecycle-controlled measured flows in the packaged library: `app.lifecycle.android-smoke`, `perps.performance.warm-start`, `perps.performance.background-resume`, `perps.performance.cold-start`; performance recipes now keep lifecycle/unlock in `setup[]`/`startState` so measured nodes carry only CUF timings.
|
|
245
302
|
|
|
246
303
|
### Changed
|
|
304
|
+
|
|
247
305
|
- `@farmslot/recipe-harness` dependency raised to `^0.4.0` (ships the `app.lifecycle` adapter — the `FARMSLOT_ROOT` local-source fallback is no longer needed at runtime).
|
|
248
306
|
|
|
249
307
|
### Fixed
|
|
308
|
+
|
|
250
309
|
- `launch ios --device <udid|name>` again accepts a shutdown simulator target: launch preserves the requested simulator identity and lets `open-device.sh` boot it instead of requiring it to appear in the booted-device list first.
|
|
251
310
|
- iOS UDID pins are exported as both `SIM_UDID` and simulator name where available, so downstream simulator tooling can use the stable name while preserving the exact pin.
|
|
252
311
|
- `metamask.wallet.ensure_unlocked` now waits for the pinned agentic bridge target, tolerates transient status drops during the unlocked stability check, and avoids the old full password-unlock fallback for brief bridge gaps.
|
|
@@ -258,17 +317,20 @@
|
|
|
258
317
|
## 0.10.0 - 2026-07-07
|
|
259
318
|
|
|
260
319
|
### Added
|
|
320
|
+
|
|
261
321
|
- **Canonical `perps.performance` measured flow** (`library/recipes/perps/performance.mobile.recipe.json`): unlock → open the Perps market list → read live state → open a market detail — one node per user-visible step with stable node names, so the per-node `duration`s in `trace.json` are the timings you monitor. Run pinned: `mm-harness run perps.performance --device <serial> --heal off`. Device-proven end-to-end on a physical Pixel.
|
|
262
322
|
- **`run <name>` resolves personal/team recipe libraries.** Previously only the packaged library was probed by name; custom recipes ran by path. Sources resolve in library-precedence order (personal > team shadow the packaged canonical — a same-named personal recipe wins), path-shaped args never probe libraries, and a miss teaches which sources were searched. Zero-flag default: `$FARMSLOT_HOME/recipe-library`.
|
|
263
323
|
- **Custom-library walkthrough** ("Your own measured flow" in `docs/recipe-libraries.md`): a peer engineer scaffolds a personal library, copies the canonical flow, retargets the nodes to their journey, and runs it by name. Every step is executed by the `perps.performance-recipe` contract test, so the doc cannot drift from reality.
|
|
264
324
|
- **`call` declared on mobile and extension manifests** (was core-only) with self-discovery metadata — personal `flows/` segments are now usable from mobile/extension recipes. Honest limitation documented: flows carry no adapter dimension in the protocol yet, so a cross-adapter `call` fails at live-run rather than plan time.
|
|
265
325
|
|
|
266
326
|
### Fixed
|
|
327
|
+
|
|
267
328
|
- **A `--device` pin wins target selection end-to-end on dual-platform slots.** Three independently sufficient holes let a pinned android run drive the iOS simulator (observed live): the discovery simulator filter ran before the android pin and the slot's ambient `IOS_SIMULATOR` captured the candidate set; pins were only enforced when more than one candidate existed (a single WRONG candidate was silently accepted); and the wallet actions' status-entry selectors checked the ambient simulator identity first while never matching serials against Metro device names. Fixed at every layer with live-repro contract cases; an unmatchable pin fails fast listing the Metro candidates.
|
|
268
329
|
|
|
269
330
|
## 0.9.1 - 2026-07-07
|
|
270
331
|
|
|
271
332
|
### Fixed
|
|
333
|
+
|
|
272
334
|
- **Metro survives the launching shell.** `start-metro.sh` spawned Metro without SIGHUP protection, so closing the launching tmux window/shell killed it, leaving a stale `metro.pid` and hanging every subsequent bridge/fixtures call. Metro now starts under `nohup` (argv spawn, no `bash -c` string interpolation), and a stale `metro.pid` naming a dead process is detected and cleaned before start.
|
|
273
335
|
- **`--device <adb serial>` reaches CDP target selection.** The runner's ambiguity gate resolved the serial, but target discovery compared it against Metro's `deviceName` ("Pixel 6 - 16 - API 36") — never a serial — so with an iOS simulator also attached, a recipe pinned to the physical Android device could silently drive the simulator. The serial is now mapped to the Metro identity via `adb -s <serial> shell getprop ro.product.model` with model-prefix matching (scoped to non-simulator targets); an unmatchable or ambiguous pin (two same-model devices) fails fast listing every Metro `/json/list` candidate instead of silently picking one. `--device <serial>` remains the only thing users pass.
|
|
274
336
|
- **Bridge commands always emit valid JSON.** `get-route` printed the literal string `undefined` when the route was transiently unavailable mid-navigation, so `bridgeCommand()` threw on parse and `waitForRoute()` aborted instead of polling. `get-route`/`navigate`/`go-back` now normalise a missing route to `null`, `bridgeCommand()` treats `''`/`undefined` stdout as not-settled-yet only for transient-legitimate commands, and `waitForRoute()` polls through `null` until timeout — the timeout error carries the expected route, last parsed route, last bridge reply and the device pin.
|
|
@@ -277,12 +339,14 @@
|
|
|
277
339
|
## 0.9.0 - 2026-07-07
|
|
278
340
|
|
|
279
341
|
### Added
|
|
342
|
+
|
|
280
343
|
- **`status` auto-probes live app state per device** — the `yarn a:status` successor. Static info prints instantly; within a strict 2s window each device line is enriched with `screen=` (active route via the `__AGENTIC__` bridge, Route objects normalised), `wallet=locked|unlocked|onboarding`, `account=<label> (0x1234…abcd)` and `fixture=READY|missing`. `--fast` skips all probes (guaranteed-instant for scripts); `--json` carries the enriched `devices[]` in one envelope. All RN targets attached to the checkout's Metro are probed and matched per device (exact id → exact name → platform-uniqueness → leftover 1:1), so android + ios side by side on one Metro both report. Honest degradation: `no-bridge` (nothing matched/answering) vs `bridge-absent` (target attached but the installed build predates `__AGENTIC__`, rendered with a rebuild hint) — surfacing pre-bridge builds required the target discovery probe to become three-state (agentic/responsive/unreachable) instead of silently dropping them.
|
|
281
344
|
- **Every action now carries self-discovery metadata.** `action_metadata` (description + example recipe node, derived from the real handler implementations) covers all official and custom actions across the mobile, extension and core manifests — previously `app.status`, `cdp.target` and all 16 `metamask.wallet.*`/`metamask.perps.*` actions were bare names to agents. A new contract guard enforces coverage (including example structure: `node.action` must match), and locks mobile ↔ extension action-set parity with an explicit platform-only allowlist.
|
|
282
345
|
|
|
283
346
|
## 0.8.0 - 2026-07-07
|
|
284
347
|
|
|
285
348
|
### Added
|
|
349
|
+
|
|
286
350
|
- **`run <name>` — the recipe positional resolves packaged-library recipe names.** An existing file path (absolute or cwd-relative) wins; otherwise the arg is a library recipe name, adapter-scoped first (`run smoke` on mobile → `library/recipes/runner/smoke.mobile.recipe.json`), then adapterless (`run perps.lifecycle` → `library/recipes/perps/lifecycle.recipe.json`), then the exact library filename. A miss teaches `RECIPE_NOT_FOUND` naming the library recipes available for the adapter — no more `$LIB`-style path prefixes in docs or demo scripts. A directory shadowing a library name never wins, and path-shaped args (containing a separator) never fall through to the library.
|
|
287
351
|
- **`--device <udid|serial|name>` — first-class mobile device targeting on `run`, `call`, and `doctor`.** Resolves against connected devices (adb + booted simulators; exact id first, then exact name with an ambiguity teaching error) and sets the same env `launch --device` does. Mobile `run`/`call` **without** `--device` while more than one targetable device is connected (across android + ios; android state `device`, iOS `Booted`) fail fast listing the devices and the `--device` hint, so a recipe never lands on the wrong device silently. `run --plan`/`--list` are exempt; extension/core teach. Errors honor `--json` with structured envelopes.
|
|
288
352
|
- **`status` gains `devices[]`** (additive): `{platform, id, name, state, selected}` for connected android devices and booted iOS simulators on mobile checkouts — the `yarn a:status` successor; `selected` reflects the current env pinning.
|
|
@@ -290,48 +354,58 @@
|
|
|
290
354
|
## 0.7.5 - 2026-07-07
|
|
291
355
|
|
|
292
356
|
### Fixed
|
|
357
|
+
|
|
293
358
|
- **`launch --verify` converges duplicate extension home tabs instead of failing prepare forever.** A second bare `home.html` tab can appear beside the operator's slot-titled one outside the harness's control (the extension opens its own tab after the build-freeze reload), and the live verify health gate requires exactly one home tab — but nothing in launch/verify ever collapsed duplicates (`ensureExtensionReady` was only reachable via the retired `ensure-ready` verb), so every preflight retry recounted two tabs and failed. `launch --verify` (extension, with a CDP port) now runs the convergence before the live verify phase.
|
|
294
359
|
- **Convergence keeps the operator's tab.** With multiple home tabs, `ensureExtensionReady` now prunes the extras keeping the preferred tab — attached (another client is driving it) over custom slot title (`<slot-id> — MetaMask`, how operators tell which agent owns a browser) over first listed — instead of closing all and reopening fresh, which discarded the slot title. The deterministic close-all + fresh-open remains as a one-shot fallback when the kept tab fails the health check, and a failed re-listing during the fallback reports `cdp-unreachable` instead of a stale tab count.
|
|
295
360
|
|
|
296
361
|
### Changed
|
|
362
|
+
|
|
297
363
|
- **`EnsureReadyAction` gains `pruned`** — extras were closed keeping the preferred tab; `reopened` now specifically means the pruned keeper failed the health check and one fresh tab was reopened.
|
|
298
364
|
|
|
299
365
|
## 0.7.4 - 2026-07-07
|
|
300
366
|
|
|
301
367
|
### Added
|
|
368
|
+
|
|
302
369
|
- **`fixtures generate`** — renders the extension wallet `fixture-state.json` from a wallet fixture by fronting `adapters/extension/wallet-fixture-state.cjs generate` (no reimplementation). Extension-only (mobile/core teach); requires `--fixture <wallet-fixture.json>` and `--out <fixture-state.json>`, with a `--json` machine envelope and teaching escapes on missing inputs or a non-extension adapter. This is the public surface farm packs call instead of reaching into the internal leaf, so the Extension pack's `setup/generate-fixture.cjs` resolver can be replaced by a one-line `mm-harness fixtures generate` hook.
|
|
303
370
|
- **`fixtures finalize`** — seeds account labels/selection into the **live** extension over CDP and validates import parity, by fronting `adapters/extension/wallet-fixture-state.cjs seed-cdp` (no reimplementation). Extension-only, post-launch (mobile/core teach); requires `--fixture`, `--state`, `--cdp-port`, `--extension-dir` (optional `--extension-id-file` / `--out`), with a pure `--json` envelope (leaf progress on stderr), the shared `LEAF_MISSING` pre-check, and teaching escapes on missing flags or a non-extension adapter. This is the public surface for the Extension pack's `setup/preflight.sh` account-label finalization, retiring its last `--resolve-script` reach-in into the internal leaf.
|
|
304
371
|
|
|
305
372
|
### Fixed
|
|
373
|
+
|
|
306
374
|
- **`fixtures generate` teaches on a missing leaf instead of leaking a node error.** When the `wallet-fixture-state.cjs` leaf is absent (a corrupt packed install), `generate` now pre-checks the leaf on disk and fails with a one-sentence teaching error plus a `Next:` reinstall command (and a clean `--json` `LEAF_MISSING` envelope), instead of surfacing node's opaque "Cannot find module".
|
|
307
375
|
- **Extension readiness no longer spawns a duplicate home tab on a transient CDP hiccup.** `ensureExtensionReady` treated any `/json/list` failure as an empty tab set, so a list that transiently failed mid-prepare (unlock → home rerender) looked like "no home tab" and opened a second one next to the healthy tab — the following health check then found two targets and failed prepare. `/json/list` now distinguishes "CDP answered: N targets" from "CDP unreachable" (retried a few times), returns `reasonCode: 'cdp-unreachable'` without touching any tab when the state is unknown, confirms a zero count with a second listing before opening, and converges over a few passes so a wrong action is corrected within the call instead of tripping the health check.
|
|
308
376
|
- **`readiness` no longer opens a duplicate home tab when the existing one is attached.** `findPageTarget` required `webSocketDebuggerUrl`, but Chrome omits that field for any target another client is attached to — during prepare the fixture finalizer / smoke recipe / CDP evals attach to the healthy home tab, so it listed without a wsUrl, looked absent, and `readiness` opened a second `home.html` that then tripped the exactly-one-home health gate. Page existence is now decided by URL in any attach state; the websocket only gates UI inspection (a present-but-attached tab is reported `pagePresent: true`, `pageInspected: false` and left alone instead of duplicated). URL matching also tolerates the `home.html#/` router rewrite and query suffixes. New additive report fields: `pagePresent`, `pageInspected`.
|
|
309
377
|
|
|
310
378
|
### Changed
|
|
379
|
+
|
|
311
380
|
- **`install --adapter core` is documented and contract-locked as the public core-runner install surface for farm packs.** It already fronts `adapters/core/inject.sh` and produces the runner delegate at `<harness>/core/runner/bin/mm-harness`; a new CLI-level contract test (`tests/contract/core-install-cli.test.sh`) pins the happy path, `--json` envelope purity, and the adapter-detection teaching escape. Packs call `mm-harness install --adapter core --target <repo>` (inheriting `RECIPE_HARNESS_ROOT` / `FARMSLOT_ROOT`) instead of cloning a runner checkout and invoking the internal leaf directly — no separate top-level command is minted.
|
|
312
381
|
- **`EnsureReadyResult` gains a machine-readable `action` field** (`none` | `opened` | `reopened` | `skipped`) stating the tab decision the call took, so a consumer distinguishes "opened one because a zero was confirmed" from "touched nothing because CDP state was unknown" straight from the JSON envelope.
|
|
313
382
|
|
|
314
383
|
## 0.7.3
|
|
315
384
|
|
|
316
385
|
### Fixed
|
|
386
|
+
|
|
317
387
|
- **`provision runway` gates its install-skip on artifact identity.** The baseline now records the installed artifact identity (run id, branch, digest) at install time and a skip preserves it; provisioning skips ONLY when the recorded identity matches the requested (or probe-resolved) run — a different or unknown installed app is reinstalled from the cache instead of being silently kept. Previously any installed MetaMask.app suppressed the install, so a stale binary could be served against a newer JS bundle.
|
|
318
388
|
- **Provision decisions are machine-readable**: the --json envelope carries `reason` (`identity-match` | `identity-mismatch` | `unknown-identity` | `fresh-install` | `forced`) and a skip envelope includes the matched artifact identity.
|
|
319
389
|
|
|
320
390
|
## 0.7.2
|
|
321
391
|
|
|
322
392
|
### Added
|
|
393
|
+
|
|
323
394
|
- **`recipe-quality build`** — the single worker surface for producing `recipe-quality.json`: fronts @farmslot/agent-runtime's canonical builder (no reimplementation), validates against @farmslot/protocol `RecipeQualityArtifact` before writing (invalid input writes nothing, exit 5 with a teaching escape naming the invalid field). New production dependency: `@farmslot/agent-runtime`.
|
|
324
395
|
|
|
325
396
|
### Changed
|
|
397
|
+
|
|
326
398
|
- `@farmslot/protocol` dependency raised to `^0.7.3` so one protocol version serves both the harness and the builder.
|
|
327
399
|
- The packed-install contract test now executes `recipe-quality build` from the published layout, guarding the new dependency's packaging path.
|
|
328
400
|
|
|
329
401
|
## 0.7.1
|
|
330
402
|
|
|
331
403
|
### Added
|
|
404
|
+
|
|
332
405
|
- **`doctor --expect-live`** — exit-coded runtime liveness for hooks and scripts: exit 0 only when the adapter runtime decision is `ready` (extension: watcher + CDP; mobile: metro + bridge; core: deps), non-zero with a teaching escape otherwise. Fails closed on every degraded path; reuses the doctor runtime probe, no duplicated checks.
|
|
333
406
|
|
|
334
407
|
### Fixed
|
|
408
|
+
|
|
335
409
|
- **Per-command `--help` documents every implemented flag** (`call/run --list`, `--library`, `--action-manifest`, `logs --window`, `actions --action`, `launch --url`, `doctor --runtime-dir`, `stop --adapter`) and tab-completion matches — the CLI self-teaches its own surface. A contract test guards help/implementation parity.
|
|
336
410
|
- **Injected runner shims resolve at run time** instead of a path baked at inject time: `MM_HARNESS_BIN` → global `mm-harness` on PATH → the recorded install-time path as last resort → teaching escape. A slot copied to or shared with another machine no longer points at a missing absolute path.
|
|
337
411
|
- Removed two parsed-but-unused `launch` flags (`--yes`, `--json-stream`).
|
|
@@ -343,6 +417,7 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
343
417
|
(0.6.3, below). One themed commit per item; full contract suite green (macOS).
|
|
344
418
|
|
|
345
419
|
### Added
|
|
420
|
+
|
|
346
421
|
- **`call --list` / `run --list`** — one scope-aware listing of everything invocable
|
|
347
422
|
for the detected adapter: the fuzzy short-name action universe (each action's full
|
|
348
423
|
name plus its unambiguous short name — what `call` accepts) and the runnable
|
|
@@ -356,6 +431,7 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
356
431
|
optional (absent binary → no row, never a doctor failure). Seam: `CAPTURE_HELPER_PATH`.
|
|
357
432
|
|
|
358
433
|
### Changed
|
|
434
|
+
|
|
359
435
|
- **`fixtures set` is never silent** — an upfront intent line the moment work begins,
|
|
360
436
|
plus the mobile setup-wallet leaf's own progress streamed live (heartbeat) during
|
|
361
437
|
the 20-40s wallet build; stdout stays a clean `--json` envelope.
|
|
@@ -376,6 +452,7 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
376
452
|
`FARMSLOT_ROOT` a back-compat alias for one release.
|
|
377
453
|
|
|
378
454
|
### Fixed
|
|
455
|
+
|
|
379
456
|
- **Extension `launch` teaches `yarn install --immutable` on missing/stale deps** —
|
|
380
457
|
a pre-watcher deps-freshness probe fails fast (teaching only, never auto-installs)
|
|
381
458
|
instead of letting webpack crash deep on stale `node_modules`; gated so a reusable
|
|
@@ -395,6 +472,7 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
395
472
|
- **Extension quick-tier webpack tail window** is regression-guarded (Metro parity).
|
|
396
473
|
|
|
397
474
|
### Internal
|
|
475
|
+
|
|
398
476
|
- Dependabot: no high/critical advisories remain (existing `resolutions` cover them).
|
|
399
477
|
- Boring-library swaps (pidtree, ajv) declined per the "delete hand-rolled code with a
|
|
400
478
|
bug history" bar: the ps/lsof process detection is contract-tested and working, and
|
|
@@ -411,14 +489,17 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
411
489
|
## 0.6.3
|
|
412
490
|
|
|
413
491
|
### Fixed
|
|
492
|
+
|
|
414
493
|
- **Extension `launch` reuses a healthy live runtime instead of always clean-building** — quick `launch` / `launch --sidepanel` on an extension slot now probes for a reusable runtime (webpack watcher LISTENing on `WATCHER_PORT` + CDP `/json/version` reachable on `CDP_PORT` + dist not stale). When all hold it REATTACHES: re-snapshots `dist/chrome` into the loaded runtime-dist and reloads the extension in place over CDP (service worker + pages), re-asserts the side panel, and applies `--url` — against the existing slot Chrome profile, with no watcher stop, webpack cache clear, or Chrome kill/relaunch. Reuse is best-effort: a failed probe (watcher down, CDP unreachable, stale dist) falls through to the clean path, and `--build` is the explicit escape that always clean-builds + relaunches a fresh runtime (no probe) to force-recover a broken slot.
|
|
415
494
|
|
|
416
495
|
## 0.6.2 - 2026-07-06
|
|
417
496
|
|
|
418
497
|
### Added
|
|
498
|
+
|
|
419
499
|
- **`-v` / `--version`** prints the mm-harness version.
|
|
420
500
|
|
|
421
501
|
### Fixed
|
|
502
|
+
|
|
422
503
|
- **`logs` now streams live and shows the file path** — it captured output via spawnSync (never shown for a `tail -F` that doesn't exit), so `logs`/`logs --full` looked dead. New spawnInherit hands the terminal to the follow; the resolved log path + `tail -f`/`less +F` hints print upfront so you can page it yourself. Honors the test override seam.
|
|
423
504
|
- **`debug` resolves the checkout's own port** (slot context → pool → formula) like launch/stop/doctor — bare `mm-harness debug` no longer 'fetch failed' against the wrong port.
|
|
424
505
|
|
|
@@ -427,10 +508,12 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
427
508
|
Fresh-install fixes found live on a published-0.6.0 install.
|
|
428
509
|
|
|
429
510
|
### Fixed
|
|
511
|
+
|
|
430
512
|
- **Mobile `launch` no longer dies on empty `METAMASK_BUILD_TYPE`** — the quick-launch runs `expo start` directly (bypassing scripts/build.sh, which passes the build type as an arg); the fixture `.js.env` shipped `METAMASK_BUILD_TYPE=""`, which Metro's transform rejects (`Invalid METAMASK_BUILD_TYPE`). start-metro now defaults to the main dev client when unset, so already-installed slots launch without re-syncing fixtures.
|
|
431
513
|
- **`doctor` no longer false-flags orphan Metros** — the detector matched any argv containing "metro" (caught the `tail -F metro.log` viewer) and reported the live, valid bundler as leaked. Now it matches only `expo start` bundlers and excludes the one serving the current port.
|
|
432
514
|
|
|
433
515
|
### Internal
|
|
516
|
+
|
|
434
517
|
- Reap-checkout-metros test hardened against a SIGTERM timing flake (polls for exit).
|
|
435
518
|
|
|
436
519
|
## 0.6.0 - 2026-07-06
|
|
@@ -440,6 +523,7 @@ fresh-slot validation wave — every fix proven live on untouched -2 slots and
|
|
|
440
523
|
independently cross-reviewed.
|
|
441
524
|
|
|
442
525
|
### Changed
|
|
526
|
+
|
|
443
527
|
- **CLI decomposition + dist-only publish** — `src/cli.ts` is parse+dispatch only;
|
|
444
528
|
handlers under `src/commands/<verb>.ts`; one commander parser; the npm tarball
|
|
445
529
|
ships compiled `dist/` without `src/` and `tsx` is a devDependency (plain-node,
|
|
@@ -449,6 +533,7 @@ independently cross-reviewed.
|
|
|
449
533
|
the same slot isolation launch has).
|
|
450
534
|
|
|
451
535
|
### Added
|
|
536
|
+
|
|
452
537
|
- **`stop` reaps leaked Metro bundlers by checkout** (port-agnostic, path-
|
|
453
538
|
boundary matched), `doctor` surfaces any orphan and teaches the reap.
|
|
454
539
|
- **`launch --url <dapp>`** (extension) opens the dapp in the main tab beside the
|
|
@@ -457,6 +542,7 @@ independently cross-reviewed.
|
|
|
457
542
|
- DX: run-mode + stale-`dist` warning in `bin`; overlay-delegation notice; docs/CODE-MAP.md.
|
|
458
543
|
|
|
459
544
|
### Fixed
|
|
545
|
+
|
|
460
546
|
- `launch` targets the slot's own simulator (never the `booted` alias) and boots it;
|
|
461
547
|
slot-port resolution layers rungs so a partial rung never nulls the port; provision
|
|
462
548
|
resolves the simulator from the pool and boots before install.
|
|
@@ -470,6 +556,7 @@ independently cross-reviewed.
|
|
|
470
556
|
Fresh-install hotfixes found in live validation of 0.5.0.
|
|
471
557
|
|
|
472
558
|
### Fixed
|
|
559
|
+
|
|
473
560
|
- **First launch on a provisioned slot targets the slot's own simulator** — the mobile resolution ladder now reads the `runway-provision.json` baseline (simulator name/udid, watcher port, slot id) when `agentic-runtime.json` doesn't exist yet, and boots that simulator. Previously a provisioned-but-unprepared slot degraded to the simctl `booted` alias, missed the installed dev client, and guessed the wrong Metro port.
|
|
474
561
|
- **`call` works from published installs** — library actions load harness helpers through a dist-preferring bridge instead of importing `src/index.ts` (node refuses to type-strip `.ts` under `node_modules`). The bridge is deliberately narrow (paths + run-recording) to avoid an import cycle through `adapters.ts`.
|
|
475
562
|
- **deps-not-ready guidance matches the caller's state** — on a checkout without node_modules the taught command now leads with `yarn install --immutable` (yarn cannot run scripts at all on a bare checkout), and always ends with the launch re-run.
|
|
@@ -477,19 +564,26 @@ Fresh-install hotfixes found in live validation of 0.5.0.
|
|
|
477
564
|
## Unreleased
|
|
478
565
|
|
|
479
566
|
### Fixed
|
|
567
|
+
|
|
480
568
|
- **`provision --json` adapter-detection failures emit the standard error envelope** — usage errors now match `doctor`/`launch` (envelope on stdout with `error.userAction`; stderr stays human-only). Previously `--json` callers got empty stdout.
|
|
481
569
|
|
|
482
570
|
### Changed
|
|
571
|
+
|
|
483
572
|
- **CLI decomposition** — `src/cli.ts` is parse+dispatch only; handlers live under `src/commands/<verb>.ts`; `provision` routes through `src/commands/provision.ts` (not overlay harness dispatch); launch composition splits under `src/commands/launch/`; commander owns per-command `--help` (no hand-rolled interception).
|
|
484
573
|
- **Published tarball is dist-only** — `files` no longer ships `src/`; `tsx` is a devDependency; `bin/mm-harness` and overlay leaves resolve `dist/*.js` (teaching error if a published install lacks `dist/`). Library actions keep importing `library/actions/harness-exports.mjs` (dist-preferring narrow bridge from 0.5.1); package exports remain for external consumers (`dist/index.js` published; `src/index.ts` when `--conditions=development` and dist is absent).
|
|
485
574
|
- **resolve-farmslot-ports is TypeScript-first** — pool/context/formula port resolution lives in self-contained `adapters/shared/resolve-farmslot-ports-core.mjs` (works from runner and injected overlay copies); `src/adapters/resolve-farmslot-ports.ts` re-exports it for `slot-ports.ts`. `resolve-farmslot-ports.mjs` is the node leaf; `resolve-farmslot-ports.sh` remains a thin bash-compat wrapper for sourced callers.
|
|
486
575
|
|
|
487
576
|
## 0.5.0 - 2026-07-05
|
|
577
|
+
|
|
488
578
|
Minor release: thin Runway provisioning (harness-owned slot provisioning with a shared artifact cache) plus compiled-dist packaging.
|
|
579
|
+
|
|
489
580
|
### Added
|
|
581
|
+
|
|
490
582
|
- **`mm-harness provision runway`** — provisions a mobile slot with exactly: resolve the latest Runway (expo-dev-build) artifact, download it ONCE into a shared machine cache (`~/.cache/metamask-harness/runway/<runId>/`, sha256+size integrity, corrupt entries re-downloaded, never a slot failure), create the simulator if missing, install the dev client on it. Zero yarn/deps/Metro — those stay dispatch-time (lazy, presence-authoritative readiness unchanged). `install --runway` is the overlay-path equivalent (covered by its own contract test). Baseline recorded so doctor reports provisioned-but-deps-pending as a normal state.
|
|
491
583
|
- **Compiled `dist/` for published installs** — the npm tarball ships esbuild-compiled JS; `npm i -g` installs run the dist entry (~0.21s cold vs ~0.37s tsx). Source checkouts without `dist/` keep the tsx dev path; `bin/mm-harness` prefers dist when present. Packaging contract test (pack → global install → dist entry runs).
|
|
584
|
+
|
|
492
585
|
### Changed
|
|
586
|
+
|
|
493
587
|
- Runway provisioning callers (farm installer, mobile-farm `runway` prepare profile) delegate to the harness; the profile no longer runs a deps phase and a contract test enforces that.
|
|
494
588
|
|
|
495
589
|
## 0.4.0 - 2026-07-04
|
|
@@ -497,6 +591,7 @@ Minor release: thin Runway provisioning (harness-owned slot provisioning with a
|
|
|
497
591
|
Minor release: the adapter-surface architecture plus the day's feature wave (0.3.6-0.3.9 shipped fixes as they were validated live; this cut marks the surface additions honestly).
|
|
498
592
|
|
|
499
593
|
### Added
|
|
594
|
+
|
|
500
595
|
- **AdapterSurface** — one per-platform surface behind a common interface (`src/adapters/surface.ts`: resolveSlotPorts, runtimeStatus, devServer, logSources, hints); doctor/launch/stop/logs/debug/fixtures are surface-backed, so no verb hand-rolls platform branching. Contract: `docs/ADAPTER-SURFACE.md` (never-branch rule, add-a-platform checklist, migration table).
|
|
501
596
|
- **Platform-adaptive `stop` on every adapter** — extension: kills this checkout's webpack watcher (pid file + orphan scan, slot-scoped) and closes its tail window; mobile: port-scoped Metro; core: headless teaching error. Idempotent, outcome-stating summaries.
|
|
502
597
|
- **Doctor reports live runtime state on every adapter** — mobile Metro, extension webpack (via the extension readiness decision), core deps-only — one uniform shape, adapter-scoped colored context rows.
|
|
@@ -504,20 +599,24 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
504
599
|
- **Context-aware examples and tier-visible flows** — `call` usage/help examples use the detected adapter's real manifest actions; `flows` prints a precedence legend decoding each source into personal > team > canonical.
|
|
505
600
|
|
|
506
601
|
### Changed
|
|
602
|
+
|
|
507
603
|
- **BREAKING (agent contract)**: `doctor --json` `runtime.metro` (string) is now `runtime.devServer` `{label, status}` and is absent for core.
|
|
508
604
|
|
|
509
605
|
### Feature wave recap (0.3.6-0.3.9)
|
|
606
|
+
|
|
510
607
|
- `mm-harness stop`; live-streamed mobile AND extension launches with upfront intent lines; presence-authoritative readiness (no setup-on-every-launch) with the dev-client running probe; slot-context-first device/port resolution; UTF-8 locale for pod spawns; DEV OVERRIDE banner + SLOT line + colored help; `mmdev-harness` completions; hermetic tmux-stubbed contract suite (now gating CI) + ESLint in `npm run check`; `docs/UX-PRINCIPLES.md` interaction contract.
|
|
511
608
|
|
|
512
609
|
## 0.3.9 - 2026-07-04
|
|
513
610
|
|
|
514
611
|
### Fixed
|
|
612
|
+
|
|
515
613
|
- **Readiness is presence-authoritative** — a no-baseline mtime-only stale verdict no longer re-runs `yarn setup` inside every launch (warning instead; fingerprint-verified drift still installs), the deps baseline is recorded after any successful setup, and the `ready` decision probes that the dev client is actually running on the target device before doing nothing (`launch` launches).
|
|
516
614
|
- **Slot-context-first resolution** — device/ports resolve from the checkout's `agentic-runtime.json` before pool/formula fallbacks, for mobile (simulator, Metro port) and extension (CDP + watcher ports, overwriting stale inherited env); naming formulas no longer hardcode pool prefixes.
|
|
517
615
|
- **UTF-8 locale for pod-triggering spawns** — CocoaPods no longer dies on multibyte podspecs under locale-less orchestrator environments.
|
|
518
616
|
- **Hermetic contract tests** — tmux/xcrun/adb are stubbed; the Metro log-window opens only in a run-owned session, never an unrelated attached one.
|
|
519
617
|
|
|
520
618
|
### Added
|
|
619
|
+
|
|
521
620
|
- **`mm-harness stop`** — stop the port-scoped Metro this checkout owns and close its log-tail window; idempotent; teaching error on extension/core.
|
|
522
621
|
- **Extension launch streams live** with an upfront intent line (ports named); mobile and extension long operations are never silent.
|
|
523
622
|
- **Doctor reports live runtime state per platform** (deps currency, Metro on the slot's resolved port, dev-client presence) with adapter-scoped, colored runtime-context rows.
|
|
@@ -525,6 +624,7 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
525
624
|
- **docs/UX-PRINCIPLES.md** — the CLI interaction contract (human surface rules; `--json` envelope purity is exempt and inviolable).
|
|
526
625
|
|
|
527
626
|
### Fixed
|
|
627
|
+
|
|
528
628
|
- **Mobile preflight no longer re-runs `yarn setup` on every launch** — the deps readiness decision escalated an mtime hint to `stale` and ran the FULL `yarn setup` (submodules + inpage bridge + jetify + pods) inside the launch phase on every invocation in orchestrated (farmslot) contexts. `depsCheck` reports `stale` for a no-baseline checkout whenever a manifest is newer than the install markers; the orchestrator's git phase refreshes tracked-file mtimes on every sync while its deps phase leaves `node_modules` untouched, so "manifest newer than markers" is normal and not proof of drift — yet it duplicated the orchestrator's deps work and turned a fast preflight into 15+ minutes (the behavior that also looked like a hang before 0.3.8's streaming). **Presence is now authoritative:** without a recorded baseline an mtime-only `stale` is trusted as `current` (with a one-line stderr warning), so a churned-but-present checkout launches with zero `yarn` in both tiers. Genuine drift is still caught by the recorded-baseline fingerprint. `mm-harness launch` (quick tier / no `--build`) also dropped `preflightMode` before deciding, so the fast contract never took effect; it is threaded through now.
|
|
529
629
|
- **Fast tier never installs; genuine gaps teach the orchestrator** — in the fast tier (quick launch / orchestrated), deps that genuinely need work (absent markers, an absent required package, a fingerprint drift, or Metro unable to resolve a module) return a teaching block naming the orchestrator deps/prepare phase (plus the standalone `yarn setup:expo` / `launch --build` remedies) instead of an implicit setup — deps are the orchestrator's contract. The standalone/full tier still installs.
|
|
530
630
|
- **Deps baseline recorded the instant a setup leaf succeeds** — `prepareMobile` records the deps fingerprint baseline immediately after any successful `yarn-setup`, unconditionally (previously only a later `record: true` re-decide did, gated on the original decision being `install` and on `RECIPE_UP_INSTALL_ATTEMPTED`). Genuine-drift detection is fingerprint-based and self-sustaining after one good install.
|
|
@@ -533,6 +633,7 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
533
633
|
- **Metro log-tail window no longer leaks into an unrelated tmux session** — running `start-metro` without an explicit session previously fell back to whichever tmux client was current or last attached. The viewer now opens a window only from `RECIPE_TMUX_SESSION` or the checkout runtime context and otherwise skips it; Metro still runs detached to the log. Extracted to `adapters/mobile/lib/tmux-viewer.sh` so the rule is unit-tested; contract tests stub tmux hermetically so no suite run can create a real window.
|
|
534
634
|
|
|
535
635
|
### Added
|
|
636
|
+
|
|
536
637
|
- **Adapter surface — one seam for per-platform behavior** — `src/adapters/surface.ts` defines `AdapterSurface` + a `getAdapterSurface(adapter)` registry that owns the behavior commands used to hand-roll with `if (adapter === …)` ladders (slot-port resolution, read-only runtime status, dev-server describe/stop, log sources, and platform-phrased Next: hints), with thin `mobile`/`extension`/`core` implementations that delegate to the existing readiness/port plumbing (re-homed to `src/adapters/slot-ports.ts`). `doctor`, `launch`, `stop`, `logs`, `debug`, and `fixtures` now resolve platform behavior through the surface instead of branching. This closes the platform-blind class of bug (a platform handled in one command but forgotten in another). Documented in `docs/ADAPTER-SURFACE.md`; enforces `docs/UX-PRINCIPLES.md` principle 1.
|
|
537
638
|
- **`doctor` reports a runtime section for every adapter** — the live runtime readiness line (decision + reasons, deps currency, dev server) now renders for extension (webpack watcher via `decideExtensionReadiness`) and core (deps-presence-only), not just mobile; the render is one uniform shape sourced from the surface.
|
|
538
639
|
- **`mm-harness stop` is adaptive per platform** — mobile stops its port-scoped Metro and closes the log-tail window; extension stops the checkout's webpack watcher (pid file + orphan ps-scan, slot-scoped) and closes its tail window; core teaches the headless path. All idempotent (nothing-to-stop is success), with a uniform summary and `--json` envelope.
|
|
@@ -544,6 +645,7 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
544
645
|
- **CLI help surface** — grouped/colored `mm-harness` help, a `DEV OVERRIDE ACTIVE` banner when `MM_HARNESS_BIN` is set, and a `SLOT` line when the checkout is a prepared slot; `mmdev-harness` completion alias.
|
|
545
646
|
|
|
546
647
|
### Changed
|
|
648
|
+
|
|
547
649
|
- **`doctor --json` runtime dev-server shape is normalized** — the mobile-only `runtime.metro` string is replaced by a platform-labelled `runtime.devServer: { label, status }` (`metro` for mobile, `webpack` for extension; absent for headless core), so agents read one shape across platforms.
|
|
548
650
|
- **`yarn check` runs ESLint** — flat-config ESLint (typescript-eslint recommended on `src/**/*.ts`, `@eslint/js` recommended on the `.mjs`/`.cjs` library) runs after typecheck and comment-hygiene. Dev-only (not in the published `files`); the baseline is zero-warning by config scoping.
|
|
549
651
|
- **Deps install uses a scoped `setup:expo` variant when native isn't wanted** — `adapters/mobile/yarn-setup.sh` gains `--mode full|expo`. `expo` runs `yarn setup:expo --no-build-ios --no-build-android` (JS deps + prebuild, no native — native builds come from `open-device.sh`, never doubled); the full `yarn setup` runs only for a native build (`launch --build`). This is also the standalone Metro-only remedy taught by the fast-tier deps block.
|
|
@@ -552,47 +654,56 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
552
654
|
## 0.3.8 - 2026-07-04
|
|
553
655
|
|
|
554
656
|
### Fixed
|
|
657
|
+
|
|
555
658
|
- **Mobile launch streams progress in `--json` mode** — mobile prepare leaves now run through `spawnScriptStreaming`, which tees the child's stdout+stderr to the parent's stderr live while stdout stays reserved for the JSON envelope. A multi-minute `mm-harness launch --json` is no longer silent (previously `spawnSync` buffered leaf output and suppressed it entirely under `--json`). Contract test asserts leaf progress reaches stderr, the envelope stays clean, and the streaming conversion preserves the exit-code contract.
|
|
556
659
|
|
|
557
660
|
## 0.3.7 - 2026-07-04
|
|
558
661
|
|
|
559
662
|
### Fixed
|
|
663
|
+
|
|
560
664
|
- **Overlay install manifest no longer advertises the retired `launch.sh`/`live.sh`** — mobile launch/live orchestration is in-process now (`mm-harness launch`), and `install_v1_runner_assets` deletes `scripts/launch.sh` and `scripts/live.sh` on both install paths. The product-owned/metadata-only manifest already advertised `verify` only, but the overlay manifest's `runtimeHelpers` still listed `launch: scripts/launch.sh` and `live: scripts/live.sh` — paths the same install had just removed, a manifest that pointed at nonexistent files. The overlay manifest now advertises `verify` only, matching the product-owned path. A new manifest-honesty contract check in `tests/contract/mobile-inject.test.sh` asserts every advertised `runtimeHelpers` path exists on disk and that `launch`/`live` are not advertised, for both the product-owned and a full overlay install, so this cannot recur in either mode.
|
|
561
665
|
|
|
562
666
|
## 0.3.6 - 2026-07-04
|
|
563
667
|
|
|
564
668
|
### Fixed
|
|
669
|
+
|
|
565
670
|
- **Install manifest carries target checkout identity (`targetRevision`)** — `adapters/mobile/inject.sh` stamps the target repo's `HEAD` (resolved once, up front, via `git rev-parse --verify HEAD`) and an explicit `installMode` into the mobile install manifest on both install paths (product-owned/metadata-only and overlay). Consumers (the farm recipe hook) can now gate their fast path on manifest identity matching the current checkout instead of manifest existence, closing the stale-manifest hole where a gitignored manifest survives a branch switch to a bridge-less checkout. Install now fails with teaching guidance when the target `HEAD` cannot be resolved (not-a-repo, unborn branch), instead of stamping an unusable `targetRevision`. Contract tests cover the identity stamp on both paths and the unborn-HEAD refusal.
|
|
566
671
|
|
|
567
672
|
## 0.3.5 - 2026-07-04
|
|
568
673
|
|
|
569
674
|
### Fixed
|
|
675
|
+
|
|
570
676
|
- **IMP-24b: shell leaves run even when packed without the exec bit** — `yarn pack` (used by `yarn npm publish`) strips the executable bit off shipped `*.sh` leaves to `644`, even though git stores `100755` and `npm pack` preserves `755`. The 0.3.4 fix (git `100755` + an `npm pack` tarball test) was therefore insufficient: the published `yarn`-packed tarball still shipped `644` leaves and a fresh `npm i -g` hit `EACCES` on the first leaf. `spawnScript` now invokes shell leaves through `bash <leaf>` instead of exec'ing them directly, so the leaf's file mode is irrelevant (node leaves were already interpreter-invoked via `process.execPath`). Env overlays (`FORCE_COLOR`/`RECIPE_RUNTIME_DIR`), arg passing, cwd, JSON envelope, and exit codes are unchanged. New contract test `tests/contract/leaf-644-runs.test.sh` forces the device leaves to mode `644` and drives them through the real `mm-harness` spawn path, asserting they still run — the regression the `npm pack` tarball test could not catch.
|
|
571
677
|
|
|
572
678
|
### Changed
|
|
679
|
+
|
|
573
680
|
- **Publish with `npm publish`, not `yarn npm publish`** — `npm publish` preserves the git `100755` mode on shipped `*.sh` leaves (defense-in-depth on top of the interpreter invocation above). Documented in `AGENTS.md`; git exec bits remain `100755`.
|
|
574
681
|
|
|
575
682
|
## 0.3.4 - 2026-07-04
|
|
576
683
|
|
|
577
684
|
### Fixed
|
|
685
|
+
|
|
578
686
|
- **IMP-24: published tarball stripped exec bits from shell leaves** — the harness execs `adapters/**/*.sh` leaves directly, but six shipped leaves (`adapters/mobile/lib/metro-listener.sh`, `adapters/shared/activate-repo-node.sh`, `cli-ux.sh`, `harness-path.sh`, `hash-helpers.sh`, `resolve-farmslot-ports.sh`) were committed without the git exec bit (mode `100644`), so npm packed them `644`. A fresh `npm i -g` then hit `EACCES` on the first leaf. All shipped `*.sh` are now stored `100755` in git, so the published tarball packs them executable. Added contract test `tests/contract/packaging-exec-bits.test.sh` — it runs `npm pack` to produce the actual `.tgz`, then asserts via `tar tzvf` that every shipped `*.sh` entry has owner-execute set; fails with the offending path(s) if any is `644`, so this cannot silently regress.
|
|
579
687
|
- **IMP-24: spawn failures are surfaced, not swallowed** — `spawnScript` returned on `result.error` (a leaf that is missing/`ENOENT` or not executable/`EACCES`) before its human-mode stderr forward, so a leaf that could not start produced a silent exit-1 (surfaced upstream as `MOBILE_PREPARE_FAILED`). The `result.error` branch now always writes a teaching diagnostic (`leaf could not start: <leaf> (<errno>)` + a `Next: reinstall mm-harness` hint) to stderr before returning. Covered by `tests/contract/spawn-error-surfaced.test.sh`.
|
|
580
688
|
|
|
581
689
|
## 0.3.3 - 2026-07-04
|
|
582
690
|
|
|
583
691
|
### Fixed
|
|
692
|
+
|
|
584
693
|
- **IMP-23: per-run mobile runtime dir (`RECIPE_RUNTIME_DIR`)** — every on-disk mobile runtime file (`metro.log`, `metro.pid`, `metro.tmux`, `bridge-status.log`, `wallet-fixture.json`) now resolves from the shared runtime-dir resolver that honors `RECIPE_RUNTIME_DIR` instead of the hard-coded `<target>/temp/recipe/runtime`. `RECIPE_RUNTIME_DIR` must be a non-empty relative path under the target checkout — absolute values are rejected at validation. Shell (`recipe_runtime_dir` in `harness-path.sh`, used by `start-metro.sh`, `wait-for-bridge.sh`, `prewarm-bundle.sh`, and `bridge-runtime/setup-wallet.sh`) and TS (`recipeRuntimePath` in `runtime-decision.ts`) resolve the same location, so a run pointed at an isolated subdir (e.g. `temp/recipe/runtime-8081`) writes and reads nothing under the default. Two harness jobs sharing one checkout each set `RECIPE_RUNTIME_DIR` to a distinct relative subdir for full runtime isolation.
|
|
585
694
|
- **IMP-23: port-scoped Metro guard** — the Metro detect/kill/restart helpers are extracted into `adapters/mobile/lib/metro-listener.sh` with an explicit invariant: discovery, inspection, and signalling key off the managed watcher-port only (`lsof -iTCP:<port> -sTCP:LISTEN`). A Metro listening on any other port is never selected, never has its cmdline read, and is never signalled, so a run managing one port cannot detect or kill a concurrent Metro on another port in the same checkout.
|
|
586
695
|
|
|
587
696
|
## 0.3.2 - 2026-07-04
|
|
588
697
|
|
|
589
698
|
### Fixed
|
|
699
|
+
|
|
590
700
|
- **IMP-21: FORCE_COLOR-safe pod install** — the mobile pod-triggering leaves (`yarn-setup.sh` running `yarn setup`, and `open-device.sh` running the native `yarn start:ios|android` build) now run with `FORCE_COLOR=0` / `NO_COLOR=1`. VisionCamera's podspec probes `node --print require.resolve('react-native-worklets-core')` and treats any output other than the exact string `undefined` as "found"; an inherited `FORCE_COLOR` made node emit a colorized `undefined`, enabling FrameProcessors and hard-failing on the missing worklets pod. Setup/native builds are now reliable from a `FORCE_COLOR` shell.
|
|
591
701
|
- **IMP-22: `--watcher-port` beats `.js.env WATCHER_PORT`** — `verify.sh` port resolution now honors an explicit `WATCHER_PORT` in the process env (which carries `mm-harness launch --watcher-port N`) over the target's `.js.env`. Precedence is flag > process env > `.js.env` > `8081` default, so a run can be pointed at an alternate Metro/CDP port without editing a shared slot's `.js.env`.
|
|
592
702
|
|
|
593
703
|
## 0.3.1 - 2026-07-03
|
|
594
704
|
|
|
595
705
|
### Fixed
|
|
706
|
+
|
|
596
707
|
- **Customization compose-by-ref**: recipes with `{action:"call",ref:"<lib>.<flow>"}` + `--library <lib>=<dir>` now pass pre-run schema validation AND execute at runtime. `validateRecipeAdapterAware` threads `externalFlowIds` into both `validateRecipeDocument` and `validateRecipeWithManifest`; library resolution also runs at `run` time.
|
|
597
708
|
- **IMP-14: stale metro.log guard** — if `metro.log` is older than the install markers (`node_modules/.yarn-state.yml`, `.yarn/install-state.gz`), it is treated as absent so a stale log cannot drive a false native-module-mismatch decision at launch.
|
|
598
709
|
- **IMP-15: stale overlay shim auto-repair (two modes)** — `ensureOverlay` detects (1) a `.runner-source` pointing to a nonexistent runner dir, and (2) a `.runner-source` whose dir exists but whose `bin/mm-harness` was removed. Both re-install automatically before launch.
|
|
@@ -602,9 +713,11 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
602
713
|
## 0.3.0 - 2026-07-03
|
|
603
714
|
|
|
604
715
|
### Changed
|
|
716
|
+
|
|
605
717
|
- Porcelain layer eliminated: the legacy `mm-recipe`/`mme-recipe`/`metamask-recipe` bins are gone; launch/logs/debug/fixtures compose the adapter scripts directly in TypeScript. Repository reorganized into `src/` (all TS), `adapters/` (per-platform runtime glue), `library/` (recipe/action/flow vocabulary).
|
|
606
718
|
|
|
607
719
|
### Fixed
|
|
720
|
+
|
|
608
721
|
- Extension `launch` opens the app directly (composes `live.sh`) instead of a retired command.
|
|
609
722
|
- Mobile `cleanup` resilient to a stale runner-source path.
|
|
610
723
|
- Core run teaches the correct next step when no account is set.
|
|
@@ -907,11 +1020,13 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
907
1020
|
- `checklist mark ... complete` now teaches the exact compact quality input, canonical builder command, and coverage artifact when a recipe activates those terminal requirements, instead of forcing agents to reverse-engineer the artifact validator.
|
|
908
1021
|
|
|
909
1022
|
### Added
|
|
1023
|
+
|
|
910
1024
|
- Checkout-scoped operation locking prevents concurrent launch, fixture mutation, and recipe execution in one repository while allowing other checkouts/slots to run independently; stale locks from exited processes are reclaimed.
|
|
911
1025
|
- `doctor --fix` creates an ignored, checkout-scoped `agentic-runtime.json` when absent, with stable claimed local ports for ordinary standalone clones while preserving explicit or Farmslot-provided slot resources.
|
|
912
1026
|
- `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.
|
|
913
1027
|
|
|
914
1028
|
### Fixed
|
|
1029
|
+
|
|
915
1030
|
- Missing checkout targets now return the structured usage envelope before lock acquisition in `run` and `doctor`; recovery bounds distinguish a consumed successful repair, adapter helpers preserve explicit runtime/device pins, checklist-only runtime resolution is lazy, and fixture finalization is time-bounded.
|
|
916
1031
|
- 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.
|
|
917
1032
|
- 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.
|
|
@@ -949,23 +1064,27 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
949
1064
|
## 0.14.7 - 2026-07-10
|
|
950
1065
|
|
|
951
1066
|
### Changed
|
|
1067
|
+
|
|
952
1068
|
- `doctor --print-ready` now implies the exit-coded live probe — Farmslot `health_check` hooks need only `--print-ready`, not `--expect-live --print-ready`.
|
|
953
1069
|
- Mobile `--print-ready` uses bridge `walletState` (unlocked + live bridge), not React Navigation route names; mobile `ready_indicator` is `OK`.
|
|
954
1070
|
- Removed `metamask-recipe` install symlinks from adapter inject paths (no compat aliases).
|
|
955
1071
|
- `doctor --print-ready` rejects `--json` (stdout is reserved for the Farmslot indicator line).
|
|
956
1072
|
|
|
957
1073
|
### Fixed
|
|
1074
|
+
|
|
958
1075
|
- Mobile `surface.runtimeStatus` infers Android from `ADB_SERIAL` / `ANDROID_SERIAL` when present.
|
|
959
1076
|
|
|
960
1077
|
## 0.14.6 - 2026-07-10
|
|
961
1078
|
|
|
962
1079
|
### Added
|
|
1080
|
+
|
|
963
1081
|
- `mm-harness doctor --print-ready` — Farmslot `health_check` mode: prints `health.ready_indicator` on stdout (`extension`/`mobile`: `OK`; `core`: `ready`).
|
|
964
1082
|
- `doctor --expect-live` — exit-coded liveness gate without indicator output (prepare recovery and other pass/fail callers).
|
|
965
1083
|
|
|
966
1084
|
## 0.14.5 - 2026-07-10
|
|
967
1085
|
|
|
968
1086
|
### Fixed
|
|
1087
|
+
|
|
969
1088
|
- Extension `ensure-browser` closes disposable New Tab / blank / extensions pages after reopen, matching reattach/ensure-ready hygiene.
|
|
970
1089
|
- Extension slot browser titles are stamped through one shared helper (`adapters/extension/lib/slot-title.cjs`) with a persistent `MutationObserver`, and re-applied after `ensureExtensionReady` open/prune/reopen so relaunch and recipe paths keep `<slot-id> — MetaMask` instead of a bare MetaMask window.
|
|
971
1090
|
- Extension slot-title contract test is hermetic (local CDP/WebSocket stub + fake DOM); Playwright and CDP stamps share one function source so they cannot drift.
|
|
@@ -974,11 +1093,13 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
974
1093
|
## 0.14.4 - 2026-07-09
|
|
975
1094
|
|
|
976
1095
|
### Fixed
|
|
1096
|
+
|
|
977
1097
|
- Include the new extension viewer cleanup scripts in the adapter manifest so published packages pass adapter-surface validation.
|
|
978
1098
|
|
|
979
1099
|
## 0.14.3 - 2026-07-09
|
|
980
1100
|
|
|
981
1101
|
### Fixed
|
|
1102
|
+
|
|
982
1103
|
- Extension `status` and `doctor` now accept a sidepanel-only live runtime, matching `run`/`call` health checks instead of requiring a fullscreen `home.html` tab after `launch --sidepanel`.
|
|
983
1104
|
- Extension sidepanel launch waits longer for Chrome to expose the `sidepanel.html` CDP target, avoiding false failures after Chrome accepts the open request.
|
|
984
1105
|
- Extension tmux viewers are opened only in the run-owned tmux session and are cleaned by `mm-harness stop`, preventing stale `webpack-*`/`console-*` windows from leaking across slots.
|
|
@@ -987,15 +1108,18 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
987
1108
|
## 0.14.2 - 2026-07-09
|
|
988
1109
|
|
|
989
1110
|
### Fixed
|
|
1111
|
+
|
|
990
1112
|
- Require `@farmslot/recipe-harness` `^0.4.3` so runtime dependency readiness trusts install markers newer than an old recorded baseline and stops repeatedly prompting managed slots to reinstall fresh dependencies.
|
|
991
1113
|
|
|
992
1114
|
## 0.14.1 - 2026-07-09
|
|
993
1115
|
|
|
994
1116
|
### Added
|
|
1117
|
+
|
|
995
1118
|
- `mm-harness check diff` runs bounded repo-local validation for the active git diff, writing `validation-summary.json`/`.md` plus per-check logs. The fast profile runs changed-file ESLint, Prettier, and changed test files; `--profile full` also runs the repo typecheck when available. The default base follows the active PR base or repo remote HEAD before falling back to common branch names.
|
|
996
1119
|
- `mm-harness run` writes a concise human report (`report.md`) and prints a colored step summary for every adapter, so successful Core/Mobile/Extension recipe runs are scannable without opening raw trace files.
|
|
997
1120
|
|
|
998
1121
|
### Fixed
|
|
1122
|
+
|
|
999
1123
|
- Mobile slot targeting now refuses a platform launch/run/call when `--platform ios|android` conflicts with the configured default target, preventing an iOS-pinned slot from silently stealing a shared Android device; `status` and `doctor` scope device lists to the configured target by default and `status` reports other reachable bridges as additional targets that can be driven with `--device`.
|
|
1000
1124
|
- Mobile `status` bases `Next:` on the configured default target only, avoids assigning an additional Android bridge to a same-platform selected device, and reports stale Android reverse ports when the selected device is not connected to the slot Metro.
|
|
1001
1125
|
- Mobile `doctor` now reports the same additional reachable targets as `status`, so diagnostics and the home view agree on which devices can be driven with `--device`.
|
|
@@ -1012,11 +1136,13 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1012
1136
|
## 0.14.0 - 2026-07-08
|
|
1013
1137
|
|
|
1014
1138
|
### Added
|
|
1139
|
+
|
|
1015
1140
|
- `mm-harness call` accepts action fields as direct `key=value` shorthand in addition to repeated `--arg k=v`, so commands like `mm-harness call ui.navigate page=perps` now match the examples agents naturally write.
|
|
1016
1141
|
- Packaged recipes are grouped by domain under `library/recipes/<domain>/` and still resolve by dotted names (`perps.smoke`, `runner.smoke`) with legacy aliases for the former flat names.
|
|
1017
1142
|
- Packaged `perps.smoke` recipes for mobile, extension, and core provide an explicit non-mutating Perps domain smoke. The existing bare `smoke` alias remains a runner/transport smoke for compatibility.
|
|
1018
1143
|
|
|
1019
1144
|
### Fixed
|
|
1145
|
+
|
|
1020
1146
|
- The top-level help SLOT banner now labels the slot dev-server port by adapter, so extension checkouts show `webpack :<port>` instead of the mobile-only `metro :<port>`.
|
|
1021
1147
|
- Hidden internal runtime commands remain executable through the installed `mm-harness` bin, fixing Extension verify warnings where `runtime-decision` returned `{}` because the wrapper blocked its own shipped helper.
|
|
1022
1148
|
- Extension launch/readiness now stamps the live home tab title with the Farmslot slot id after MetaMask has settled, so headed browser windows identify their owning slot.
|
|
@@ -1029,11 +1155,13 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1029
1155
|
## 0.13.0 - 2026-07-08
|
|
1030
1156
|
|
|
1031
1157
|
### Added
|
|
1158
|
+
|
|
1032
1159
|
- Typed cdp-bridge failure codes (`NO_TARGET`, `CDP_TIMEOUT`, `WS_CLOSED`, `METRO_UNREACHABLE`): the bridge classifies a failure at its source and reports it three ways a caller can recover — an `ERROR[<CODE>]:` stderr marker, a code-specific exit status (10–13), and a `Next:` teaching line for the caller's actual situation. `bridge.mjs` attaches the code to the error it throws, and `app.hud` lifecycle-skip classification (`isMobileHudLifecycleSkip`) branches on the code first, keeping the substring needles only as a fallback for output from a bridge that predates the codes. The needle fallback is now case-insensitive, closing a gap where target-discovery's `Pinned Android device …` (capital A) missed a lowercase needle.
|
|
1033
1160
|
- Console-forwarder now expands object/array console arguments in `metro.log` from the Hermes-supplied inline `preview` (e.g. `{ symbol: "BTC", px: 42 }` instead of the literal `Object`), bounded one level deep and rendered synchronously so the stream never blocks; objects without a preview degrade to their description.
|
|
1034
1161
|
- `mm-harness call <action> --help` now renders the named action's own field schema (name, type, required, description, example — from the action manifest) above the generic call flags, instead of printing only the generic call help. Fuzzy short-name resolves like `call` (an ambiguous prefix shows every match); an unresolvable name falls back to the generic help plus a pointer to `mm-harness actions`. `run <recipe> --help` is unchanged (recipe-specific help is a separate, larger surface — recipes are not in the action manifest).
|
|
1035
1162
|
|
|
1036
1163
|
### Fixed
|
|
1164
|
+
|
|
1037
1165
|
- Runner construction no longer fails with `Manifest action app.lifecycle has no registered adapter` when a manifest declaring `app.lifecycle` is used with a non-mobile adapter (e.g. `call --adapter core --action-manifest library/manifests/mobile.action-manifest.json`): lifecycle adapter registration is manifest-driven instead of gated on the mobile adapter. Executing the action outside a mobile run still fails explicitly at target resolution.
|
|
1038
1166
|
- Mobile run teardown always clears any HUD step left painted on-device, so a failed run no longer strands a FAIL banner for the next run. Best-effort and bounded: a down/transitioning bridge simply has nothing to clear and never masks the run's real outcome.
|
|
1039
1167
|
- start-metro quick-launch now applies the dev Sentry DSN remap (`MM_SENTRY_DSN` defaults to `MM_SENTRY_DSN_DEV` when unset) at both launch paths. The quick-launch runs `expo start` directly and bypasses `scripts/build.sh`, which normally performs this remap, so without it Sentry never initialized in quick-launched dev clients.
|
|
@@ -1042,9 +1170,11 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1042
1170
|
## 0.12.0 - 2026-07-08
|
|
1043
1171
|
|
|
1044
1172
|
### Added
|
|
1173
|
+
|
|
1045
1174
|
- Mobile console-forwarder: restores the device console (incl. DevLogger) in `metro.log` on RN 0.79+/Bridgeless via persistent CDP streaming (`Runtime.consoleAPICalled`) — one session per device JS-runtime page (shared target-discovery ranking, never the native C++ page), buffer replay + persisted last-seen cursor (timestamp + same-stamp texts) deduping across reconnects/app reloads, auto-started by `start-metro`; opt out with `METAMASK_RECIPE_CONSOLE_FORWARD=0`. Grep `[console:` for device lines. Zero-dependency transport (built-in Node 22+ WebSocket, like the CDP bridge client). Yields to interactive React Native DevTools: a session evicted by another debugger with no bridge lock present backs off for 5 minutes instead of evicting the human every discovery tick. Idles at the slow poll cadence while Metro is down; flushes pending lines and dedupe state synchronously on SIGTERM/SIGINT.
|
|
1046
1175
|
|
|
1047
1176
|
### Fixed
|
|
1177
|
+
|
|
1048
1178
|
- `app.hud` no longer aborts recipes on `CDP message timeout` / `WebSocket closed` during dev-client lifecycle transitions (0.11.0 regression that failed every warm-start run at `foreground-app`/`ensure-unlocked`). Skips are loud: the reason is written to stderr and recorded in the action result, so a masked real failure remains visible.
|
|
1049
1179
|
- cdp-bridge takes a runtime lock (`cdp-bridge.lock`) so the console-forwarder yields the single debugger slot during bridge commands — prevents mutual eviction and lost `Runtime.evaluate` replies. The forwarder honors the lock while the pid inside it is alive (`kill -0`), so long commands (wallet setup runs `CDP_TIMEOUT=120000`) are never evicted mid-flight while a crashed/killed bridge releases immediately; the bridge releases on SIGTERM/SIGINT, only unlinks a lock it still owns (last-writer-wins under overlap), and takes no lock for `--help`/unknown commands.
|
|
1050
1180
|
- `stop-metro` and mobile `cleanup` stop the console-forwarder (recorded pid + checkout-scoped sweep), so no orphan forwarder outlives Metro or fights a later one for the debugger slot.
|
|
@@ -1053,14 +1183,17 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1053
1183
|
## 0.11.0 - 2026-07-07
|
|
1054
1184
|
|
|
1055
1185
|
### Added
|
|
1186
|
+
|
|
1056
1187
|
- Mobile recipes can now use the standard outer `app.lifecycle` action for deterministic performance start states without rebuilding (Android background/foreground/terminate/restart, iOS simulator launch/terminate/restart through the shared Farmslot lifecycle adapter).
|
|
1057
1188
|
- `fixtures set --device <serial|udid|name>` now pins mobile fixture sync to the requested device using the same targeting rules as `run`, `call`, and `doctor`.
|
|
1058
1189
|
- New lifecycle-controlled measured flows in the packaged library: `app.lifecycle.android-smoke`, `perps.performance.warm-start`, `perps.performance.background-resume`, `perps.performance.cold-start`; performance recipes now keep lifecycle/unlock in `setup[]`/`startState` so measured nodes carry only CUF timings.
|
|
1059
1190
|
|
|
1060
1191
|
### Changed
|
|
1192
|
+
|
|
1061
1193
|
- `@farmslot/recipe-harness` dependency raised to `^0.4.0` (ships the `app.lifecycle` adapter — the `FARMSLOT_ROOT` local-source fallback is no longer needed at runtime).
|
|
1062
1194
|
|
|
1063
1195
|
### Fixed
|
|
1196
|
+
|
|
1064
1197
|
- `launch ios --device <udid|name>` again accepts a shutdown simulator target: launch preserves the requested simulator identity and lets `open-device.sh` boot it instead of requiring it to appear in the booted-device list first.
|
|
1065
1198
|
- iOS UDID pins are exported as both `SIM_UDID` and simulator name where available, so downstream simulator tooling can use the stable name while preserving the exact pin.
|
|
1066
1199
|
- `metamask.wallet.ensure_unlocked` now waits for the pinned agentic bridge target, tolerates transient status drops during the unlocked stability check, and avoids the old full password-unlock fallback for brief bridge gaps.
|
|
@@ -1072,17 +1205,20 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1072
1205
|
## 0.10.0 - 2026-07-07
|
|
1073
1206
|
|
|
1074
1207
|
### Added
|
|
1208
|
+
|
|
1075
1209
|
- **Canonical `perps.performance` measured flow** (`library/recipes/perps/performance.mobile.recipe.json`): unlock → open the Perps market list → read live state → open a market detail — one node per user-visible step with stable node names, so the per-node `duration`s in `trace.json` are the timings you monitor. Run pinned: `mm-harness run perps.performance --device <serial> --heal off`. Device-proven end-to-end on a physical Pixel.
|
|
1076
1210
|
- **`run <name>` resolves personal/team recipe libraries.** Previously only the packaged library was probed by name; custom recipes ran by path. Sources resolve in library-precedence order (personal > team shadow the packaged canonical — a same-named personal recipe wins), path-shaped args never probe libraries, and a miss teaches which sources were searched. Zero-flag default: `$FARMSLOT_HOME/recipe-library`.
|
|
1077
1211
|
- **Custom-library walkthrough** ("Your own measured flow" in `docs/recipe-libraries.md`): a peer engineer scaffolds a personal library, copies the canonical flow, retargets the nodes to their journey, and runs it by name. Every step is executed by the `perps.performance-recipe` contract test, so the doc cannot drift from reality.
|
|
1078
1212
|
- **`call` declared on mobile and extension manifests** (was core-only) with self-discovery metadata — personal `flows/` segments are now usable from mobile/extension recipes. Honest limitation documented: flows carry no adapter dimension in the protocol yet, so a cross-adapter `call` fails at live-run rather than plan time.
|
|
1079
1213
|
|
|
1080
1214
|
### Fixed
|
|
1215
|
+
|
|
1081
1216
|
- **A `--device` pin wins target selection end-to-end on dual-platform slots.** Three independently sufficient holes let a pinned android run drive the iOS simulator (observed live): the discovery simulator filter ran before the android pin and the slot's ambient `IOS_SIMULATOR` captured the candidate set; pins were only enforced when more than one candidate existed (a single WRONG candidate was silently accepted); and the wallet actions' status-entry selectors checked the ambient simulator identity first while never matching serials against Metro device names. Fixed at every layer with live-repro contract cases; an unmatchable pin fails fast listing the Metro candidates.
|
|
1082
1217
|
|
|
1083
1218
|
## 0.9.1 - 2026-07-07
|
|
1084
1219
|
|
|
1085
1220
|
### Fixed
|
|
1221
|
+
|
|
1086
1222
|
- **Metro survives the launching shell.** `start-metro.sh` spawned Metro without SIGHUP protection, so closing the launching tmux window/shell killed it, leaving a stale `metro.pid` and hanging every subsequent bridge/fixtures call. Metro now starts under `nohup` (argv spawn, no `bash -c` string interpolation), and a stale `metro.pid` naming a dead process is detected and cleaned before start.
|
|
1087
1223
|
- **`--device <adb serial>` reaches CDP target selection.** The runner's ambiguity gate resolved the serial, but target discovery compared it against Metro's `deviceName` ("Pixel 6 - 16 - API 36") — never a serial — so with an iOS simulator also attached, a recipe pinned to the physical Android device could silently drive the simulator. The serial is now mapped to the Metro identity via `adb -s <serial> shell getprop ro.product.model` with model-prefix matching (scoped to non-simulator targets); an unmatchable or ambiguous pin (two same-model devices) fails fast listing every Metro `/json/list` candidate instead of silently picking one. `--device <serial>` remains the only thing users pass.
|
|
1088
1224
|
- **Bridge commands always emit valid JSON.** `get-route` printed the literal string `undefined` when the route was transiently unavailable mid-navigation, so `bridgeCommand()` threw on parse and `waitForRoute()` aborted instead of polling. `get-route`/`navigate`/`go-back` now normalise a missing route to `null`, `bridgeCommand()` treats `''`/`undefined` stdout as not-settled-yet only for transient-legitimate commands, and `waitForRoute()` polls through `null` until timeout — the timeout error carries the expected route, last parsed route, last bridge reply and the device pin.
|
|
@@ -1091,12 +1227,14 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1091
1227
|
## 0.9.0 - 2026-07-07
|
|
1092
1228
|
|
|
1093
1229
|
### Added
|
|
1230
|
+
|
|
1094
1231
|
- **`status` auto-probes live app state per device** — the `yarn a:status` successor. Static info prints instantly; within a strict 2s window each device line is enriched with `screen=` (active route via the `__AGENTIC__` bridge, Route objects normalised), `wallet=locked|unlocked|onboarding`, `account=<label> (0x1234…abcd)` and `fixture=READY|missing`. `--fast` skips all probes (guaranteed-instant for scripts); `--json` carries the enriched `devices[]` in one envelope. All RN targets attached to the checkout's Metro are probed and matched per device (exact id → exact name → platform-uniqueness → leftover 1:1), so android + ios side by side on one Metro both report. Honest degradation: `no-bridge` (nothing matched/answering) vs `bridge-absent` (target attached but the installed build predates `__AGENTIC__`, rendered with a rebuild hint) — surfacing pre-bridge builds required the target discovery probe to become three-state (agentic/responsive/unreachable) instead of silently dropping them.
|
|
1095
1232
|
- **Every action now carries self-discovery metadata.** `action_metadata` (description + example recipe node, derived from the real handler implementations) covers all official and custom actions across the mobile, extension and core manifests — previously `app.status`, `cdp.target` and all 16 `metamask.wallet.*`/`metamask.perps.*` actions were bare names to agents. A new contract guard enforces coverage (including example structure: `node.action` must match), and locks mobile ↔ extension action-set parity with an explicit platform-only allowlist.
|
|
1096
1233
|
|
|
1097
1234
|
## 0.8.0 - 2026-07-07
|
|
1098
1235
|
|
|
1099
1236
|
### Added
|
|
1237
|
+
|
|
1100
1238
|
- **`run <name>` — the recipe positional resolves packaged-library recipe names.** An existing file path (absolute or cwd-relative) wins; otherwise the arg is a library recipe name, adapter-scoped first (`run smoke` on mobile → `library/recipes/runner/smoke.mobile.recipe.json`), then adapterless (`run perps.lifecycle` → `library/recipes/perps/lifecycle.recipe.json`), then the exact library filename. A miss teaches `RECIPE_NOT_FOUND` naming the library recipes available for the adapter — no more `$LIB`-style path prefixes in docs or demo scripts. A directory shadowing a library name never wins, and path-shaped args (containing a separator) never fall through to the library.
|
|
1101
1239
|
- **`--device <udid|serial|name>` — first-class mobile device targeting on `run`, `call`, and `doctor`.** Resolves against connected devices (adb + booted simulators; exact id first, then exact name with an ambiguity teaching error) and sets the same env `launch --device` does. Mobile `run`/`call` **without** `--device` while more than one targetable device is connected (across android + ios; android state `device`, iOS `Booted`) fail fast listing the devices and the `--device` hint, so a recipe never lands on the wrong device silently. `run --plan`/`--list` are exempt; extension/core teach. Errors honor `--json` with structured envelopes.
|
|
1102
1240
|
- **`status` gains `devices[]`** (additive): `{platform, id, name, state, selected}` for connected android devices and booted iOS simulators on mobile checkouts — the `yarn a:status` successor; `selected` reflects the current env pinning.
|
|
@@ -1104,48 +1242,58 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1104
1242
|
## 0.7.5 - 2026-07-07
|
|
1105
1243
|
|
|
1106
1244
|
### Fixed
|
|
1245
|
+
|
|
1107
1246
|
- **`launch --verify` converges duplicate extension home tabs instead of failing prepare forever.** A second bare `home.html` tab can appear beside the operator's slot-titled one outside the harness's control (the extension opens its own tab after the build-freeze reload), and the live verify health gate requires exactly one home tab — but nothing in launch/verify ever collapsed duplicates (`ensureExtensionReady` was only reachable via the retired `ensure-ready` verb), so every preflight retry recounted two tabs and failed. `launch --verify` (extension, with a CDP port) now runs the convergence before the live verify phase.
|
|
1108
1247
|
- **Convergence keeps the operator's tab.** With multiple home tabs, `ensureExtensionReady` now prunes the extras keeping the preferred tab — attached (another client is driving it) over custom slot title (`<slot-id> — MetaMask`, how operators tell which agent owns a browser) over first listed — instead of closing all and reopening fresh, which discarded the slot title. The deterministic close-all + fresh-open remains as a one-shot fallback when the kept tab fails the health check, and a failed re-listing during the fallback reports `cdp-unreachable` instead of a stale tab count.
|
|
1109
1248
|
|
|
1110
1249
|
### Changed
|
|
1250
|
+
|
|
1111
1251
|
- **`EnsureReadyAction` gains `pruned`** — extras were closed keeping the preferred tab; `reopened` now specifically means the pruned keeper failed the health check and one fresh tab was reopened.
|
|
1112
1252
|
|
|
1113
1253
|
## 0.7.4 - 2026-07-07
|
|
1114
1254
|
|
|
1115
1255
|
### Added
|
|
1256
|
+
|
|
1116
1257
|
- **`fixtures generate`** — renders the extension wallet `fixture-state.json` from a wallet fixture by fronting `adapters/extension/wallet-fixture-state.cjs generate` (no reimplementation). Extension-only (mobile/core teach); requires `--fixture <wallet-fixture.json>` and `--out <fixture-state.json>`, with a `--json` machine envelope and teaching escapes on missing inputs or a non-extension adapter. This is the public surface farm packs call instead of reaching into the internal leaf, so the Extension pack's `setup/generate-fixture.cjs` resolver can be replaced by a one-line `mm-harness fixtures generate` hook.
|
|
1117
1258
|
- **`fixtures finalize`** — seeds account labels/selection into the **live** extension over CDP and validates import parity, by fronting `adapters/extension/wallet-fixture-state.cjs seed-cdp` (no reimplementation). Extension-only, post-launch (mobile/core teach); requires `--fixture`, `--state`, `--cdp-port`, `--extension-dir` (optional `--extension-id-file` / `--out`), with a pure `--json` envelope (leaf progress on stderr), the shared `LEAF_MISSING` pre-check, and teaching escapes on missing flags or a non-extension adapter. This is the public surface for the Extension pack's `setup/preflight.sh` account-label finalization, retiring its last `--resolve-script` reach-in into the internal leaf.
|
|
1118
1259
|
|
|
1119
1260
|
### Fixed
|
|
1261
|
+
|
|
1120
1262
|
- **`fixtures generate` teaches on a missing leaf instead of leaking a node error.** When the `wallet-fixture-state.cjs` leaf is absent (a corrupt packed install), `generate` now pre-checks the leaf on disk and fails with a one-sentence teaching error plus a `Next:` reinstall command (and a clean `--json` `LEAF_MISSING` envelope), instead of surfacing node's opaque "Cannot find module".
|
|
1121
1263
|
- **Extension readiness no longer spawns a duplicate home tab on a transient CDP hiccup.** `ensureExtensionReady` treated any `/json/list` failure as an empty tab set, so a list that transiently failed mid-prepare (unlock → home rerender) looked like "no home tab" and opened a second one next to the healthy tab — the following health check then found two targets and failed prepare. `/json/list` now distinguishes "CDP answered: N targets" from "CDP unreachable" (retried a few times), returns `reasonCode: 'cdp-unreachable'` without touching any tab when the state is unknown, confirms a zero count with a second listing before opening, and converges over a few passes so a wrong action is corrected within the call instead of tripping the health check.
|
|
1122
1264
|
- **`readiness` no longer opens a duplicate home tab when the existing one is attached.** `findPageTarget` required `webSocketDebuggerUrl`, but Chrome omits that field for any target another client is attached to — during prepare the fixture finalizer / smoke recipe / CDP evals attach to the healthy home tab, so it listed without a wsUrl, looked absent, and `readiness` opened a second `home.html` that then tripped the exactly-one-home health gate. Page existence is now decided by URL in any attach state; the websocket only gates UI inspection (a present-but-attached tab is reported `pagePresent: true`, `pageInspected: false` and left alone instead of duplicated). URL matching also tolerates the `home.html#/` router rewrite and query suffixes. New additive report fields: `pagePresent`, `pageInspected`.
|
|
1123
1265
|
|
|
1124
1266
|
### Changed
|
|
1267
|
+
|
|
1125
1268
|
- **`install --adapter core` is documented and contract-locked as the public core-runner install surface for farm packs.** It already fronts `adapters/core/inject.sh` and produces the runner delegate at `<harness>/core/runner/bin/mm-harness`; a new CLI-level contract test (`tests/contract/core-install-cli.test.sh`) pins the happy path, `--json` envelope purity, and the adapter-detection teaching escape. Packs call `mm-harness install --adapter core --target <repo>` (inheriting `RECIPE_HARNESS_ROOT` / `FARMSLOT_ROOT`) instead of cloning a runner checkout and invoking the internal leaf directly — no separate top-level command is minted.
|
|
1126
1269
|
- **`EnsureReadyResult` gains a machine-readable `action` field** (`none` | `opened` | `reopened` | `skipped`) stating the tab decision the call took, so a consumer distinguishes "opened one because a zero was confirmed" from "touched nothing because CDP state was unknown" straight from the JSON envelope.
|
|
1127
1270
|
|
|
1128
1271
|
## 0.7.3
|
|
1129
1272
|
|
|
1130
1273
|
### Fixed
|
|
1274
|
+
|
|
1131
1275
|
- **`provision runway` gates its install-skip on artifact identity.** The baseline now records the installed artifact identity (run id, branch, digest) at install time and a skip preserves it; provisioning skips ONLY when the recorded identity matches the requested (or probe-resolved) run — a different or unknown installed app is reinstalled from the cache instead of being silently kept. Previously any installed MetaMask.app suppressed the install, so a stale binary could be served against a newer JS bundle.
|
|
1132
1276
|
- **Provision decisions are machine-readable**: the --json envelope carries `reason` (`identity-match` | `identity-mismatch` | `unknown-identity` | `fresh-install` | `forced`) and a skip envelope includes the matched artifact identity.
|
|
1133
1277
|
|
|
1134
1278
|
## 0.7.2
|
|
1135
1279
|
|
|
1136
1280
|
### Added
|
|
1281
|
+
|
|
1137
1282
|
- **`recipe-quality build`** — the single worker surface for producing `recipe-quality.json`: fronts @farmslot/agent-runtime's canonical builder (no reimplementation), validates against @farmslot/protocol `RecipeQualityArtifact` before writing (invalid input writes nothing, exit 5 with a teaching escape naming the invalid field). New production dependency: `@farmslot/agent-runtime`.
|
|
1138
1283
|
|
|
1139
1284
|
### Changed
|
|
1285
|
+
|
|
1140
1286
|
- `@farmslot/protocol` dependency raised to `^0.7.3` so one protocol version serves both the harness and the builder.
|
|
1141
1287
|
- The packed-install contract test now executes `recipe-quality build` from the published layout, guarding the new dependency's packaging path.
|
|
1142
1288
|
|
|
1143
1289
|
## 0.7.1
|
|
1144
1290
|
|
|
1145
1291
|
### Added
|
|
1292
|
+
|
|
1146
1293
|
- **`doctor --expect-live`** — exit-coded runtime liveness for hooks and scripts: exit 0 only when the adapter runtime decision is `ready` (extension: watcher + CDP; mobile: metro + bridge; core: deps), non-zero with a teaching escape otherwise. Fails closed on every degraded path; reuses the doctor runtime probe, no duplicated checks.
|
|
1147
1294
|
|
|
1148
1295
|
### Fixed
|
|
1296
|
+
|
|
1149
1297
|
- **Per-command `--help` documents every implemented flag** (`call/run --list`, `--library`, `--action-manifest`, `logs --window`, `actions --action`, `launch --url`, `doctor --runtime-dir`, `stop --adapter`) and tab-completion matches — the CLI self-teaches its own surface. A contract test guards help/implementation parity.
|
|
1150
1298
|
- **Injected runner shims resolve at run time** instead of a path baked at inject time: `MM_HARNESS_BIN` → global `mm-harness` on PATH → the recorded install-time path as last resort → teaching escape. A slot copied to or shared with another machine no longer points at a missing absolute path.
|
|
1151
1299
|
- Removed two parsed-but-unused `launch` flags (`--yes`, `--json-stream`).
|
|
@@ -1157,6 +1305,7 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
1157
1305
|
(0.6.3, below). One themed commit per item; full contract suite green (macOS).
|
|
1158
1306
|
|
|
1159
1307
|
### Added
|
|
1308
|
+
|
|
1160
1309
|
- **`call --list` / `run --list`** — one scope-aware listing of everything invocable
|
|
1161
1310
|
for the detected adapter: the fuzzy short-name action universe (each action's full
|
|
1162
1311
|
name plus its unambiguous short name — what `call` accepts) and the runnable
|
|
@@ -1170,6 +1319,7 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
1170
1319
|
optional (absent binary → no row, never a doctor failure). Seam: `CAPTURE_HELPER_PATH`.
|
|
1171
1320
|
|
|
1172
1321
|
### Changed
|
|
1322
|
+
|
|
1173
1323
|
- **`fixtures set` is never silent** — an upfront intent line the moment work begins,
|
|
1174
1324
|
plus the mobile setup-wallet leaf's own progress streamed live (heartbeat) during
|
|
1175
1325
|
the 20-40s wallet build; stdout stays a clean `--json` envelope.
|
|
@@ -1190,6 +1340,7 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
1190
1340
|
`FARMSLOT_ROOT` a back-compat alias for one release.
|
|
1191
1341
|
|
|
1192
1342
|
### Fixed
|
|
1343
|
+
|
|
1193
1344
|
- **Extension `launch` teaches `yarn install --immutable` on missing/stale deps** —
|
|
1194
1345
|
a pre-watcher deps-freshness probe fails fast (teaching only, never auto-installs)
|
|
1195
1346
|
instead of letting webpack crash deep on stale `node_modules`; gated so a reusable
|
|
@@ -1209,6 +1360,7 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
1209
1360
|
- **Extension quick-tier webpack tail window** is regression-guarded (Metro parity).
|
|
1210
1361
|
|
|
1211
1362
|
### Internal
|
|
1363
|
+
|
|
1212
1364
|
- Dependabot: no high/critical advisories remain (existing `resolutions` cover them).
|
|
1213
1365
|
- Boring-library swaps (pidtree, ajv) declined per the "delete hand-rolled code with a
|
|
1214
1366
|
bug history" bar: the ps/lsof process detection is contract-tested and working, and
|
|
@@ -1225,14 +1377,17 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
1225
1377
|
## 0.6.3
|
|
1226
1378
|
|
|
1227
1379
|
### Fixed
|
|
1380
|
+
|
|
1228
1381
|
- **Extension `launch` reuses a healthy live runtime instead of always clean-building** — quick `launch` / `launch --sidepanel` on an extension slot now probes for a reusable runtime (webpack watcher LISTENing on `WATCHER_PORT` + CDP `/json/version` reachable on `CDP_PORT` + dist not stale). When all hold it REATTACHES: re-snapshots `dist/chrome` into the loaded runtime-dist and reloads the extension in place over CDP (service worker + pages), re-asserts the side panel, and applies `--url` — against the existing slot Chrome profile, with no watcher stop, webpack cache clear, or Chrome kill/relaunch. Reuse is best-effort: a failed probe (watcher down, CDP unreachable, stale dist) falls through to the clean path, and `--build` is the explicit escape that always clean-builds + relaunches a fresh runtime (no probe) to force-recover a broken slot.
|
|
1229
1382
|
|
|
1230
1383
|
## 0.6.2 - 2026-07-06
|
|
1231
1384
|
|
|
1232
1385
|
### Added
|
|
1386
|
+
|
|
1233
1387
|
- **`-v` / `--version`** prints the mm-harness version.
|
|
1234
1388
|
|
|
1235
1389
|
### Fixed
|
|
1390
|
+
|
|
1236
1391
|
- **`logs` now streams live and shows the file path** — it captured output via spawnSync (never shown for a `tail -F` that doesn't exit), so `logs`/`logs --full` looked dead. New spawnInherit hands the terminal to the follow; the resolved log path + `tail -f`/`less +F` hints print upfront so you can page it yourself. Honors the test override seam.
|
|
1237
1392
|
- **`debug` resolves the checkout's own port** (slot context → pool → formula) like launch/stop/doctor — bare `mm-harness debug` no longer 'fetch failed' against the wrong port.
|
|
1238
1393
|
|
|
@@ -1241,10 +1396,12 @@ The "version people use": every remaining identified fix/improvement batched on
|
|
|
1241
1396
|
Fresh-install fixes found live on a published-0.6.0 install.
|
|
1242
1397
|
|
|
1243
1398
|
### Fixed
|
|
1399
|
+
|
|
1244
1400
|
- **Mobile `launch` no longer dies on empty `METAMASK_BUILD_TYPE`** — the quick-launch runs `expo start` directly (bypassing scripts/build.sh, which passes the build type as an arg); the fixture `.js.env` shipped `METAMASK_BUILD_TYPE=""`, which Metro's transform rejects (`Invalid METAMASK_BUILD_TYPE`). start-metro now defaults to the main dev client when unset, so already-installed slots launch without re-syncing fixtures.
|
|
1245
1401
|
- **`doctor` no longer false-flags orphan Metros** — the detector matched any argv containing "metro" (caught the `tail -F metro.log` viewer) and reported the live, valid bundler as leaked. Now it matches only `expo start` bundlers and excludes the one serving the current port.
|
|
1246
1402
|
|
|
1247
1403
|
### Internal
|
|
1404
|
+
|
|
1248
1405
|
- Reap-checkout-metros test hardened against a SIGTERM timing flake (polls for exit).
|
|
1249
1406
|
|
|
1250
1407
|
## 0.6.0 - 2026-07-06
|
|
@@ -1254,6 +1411,7 @@ fresh-slot validation wave — every fix proven live on untouched -2 slots and
|
|
|
1254
1411
|
independently cross-reviewed.
|
|
1255
1412
|
|
|
1256
1413
|
### Changed
|
|
1414
|
+
|
|
1257
1415
|
- **CLI decomposition + dist-only publish** — `src/cli.ts` is parse+dispatch only;
|
|
1258
1416
|
handlers under `src/commands/<verb>.ts`; one commander parser; the npm tarball
|
|
1259
1417
|
ships compiled `dist/` without `src/` and `tsx` is a devDependency (plain-node,
|
|
@@ -1263,6 +1421,7 @@ independently cross-reviewed.
|
|
|
1263
1421
|
the same slot isolation launch has).
|
|
1264
1422
|
|
|
1265
1423
|
### Added
|
|
1424
|
+
|
|
1266
1425
|
- **`stop` reaps leaked Metro bundlers by checkout** (port-agnostic, path-
|
|
1267
1426
|
boundary matched), `doctor` surfaces any orphan and teaches the reap.
|
|
1268
1427
|
- **`launch --url <dapp>`** (extension) opens the dapp in the main tab beside the
|
|
@@ -1271,6 +1430,7 @@ independently cross-reviewed.
|
|
|
1271
1430
|
- DX: run-mode + stale-`dist` warning in `bin`; overlay-delegation notice; docs/CODE-MAP.md.
|
|
1272
1431
|
|
|
1273
1432
|
### Fixed
|
|
1433
|
+
|
|
1274
1434
|
- `launch` targets the slot's own simulator (never the `booted` alias) and boots it;
|
|
1275
1435
|
slot-port resolution layers rungs so a partial rung never nulls the port; provision
|
|
1276
1436
|
resolves the simulator from the pool and boots before install.
|
|
@@ -1284,6 +1444,7 @@ independently cross-reviewed.
|
|
|
1284
1444
|
Fresh-install hotfixes found in live validation of 0.5.0.
|
|
1285
1445
|
|
|
1286
1446
|
### Fixed
|
|
1447
|
+
|
|
1287
1448
|
- **First launch on a provisioned slot targets the slot's own simulator** — the mobile resolution ladder now reads the `runway-provision.json` baseline (simulator name/udid, watcher port, slot id) when `agentic-runtime.json` doesn't exist yet, and boots that simulator. Previously a provisioned-but-unprepared slot degraded to the simctl `booted` alias, missed the installed dev client, and guessed the wrong Metro port.
|
|
1288
1449
|
- **`call` works from published installs** — library actions load harness helpers through a dist-preferring bridge instead of importing `src/index.ts` (node refuses to type-strip `.ts` under `node_modules`). The bridge is deliberately narrow (paths + run-recording) to avoid an import cycle through `adapters.ts`.
|
|
1289
1450
|
- **deps-not-ready guidance matches the caller's state** — on a checkout without node_modules the taught command now leads with `yarn install --immutable` (yarn cannot run scripts at all on a bare checkout), and always ends with the launch re-run.
|
|
@@ -1291,19 +1452,26 @@ Fresh-install hotfixes found in live validation of 0.5.0.
|
|
|
1291
1452
|
## Unreleased
|
|
1292
1453
|
|
|
1293
1454
|
### Fixed
|
|
1455
|
+
|
|
1294
1456
|
- **`provision --json` adapter-detection failures emit the standard error envelope** — usage errors now match `doctor`/`launch` (envelope on stdout with `error.userAction`; stderr stays human-only). Previously `--json` callers got empty stdout.
|
|
1295
1457
|
|
|
1296
1458
|
### Changed
|
|
1459
|
+
|
|
1297
1460
|
- **CLI decomposition** — `src/cli.ts` is parse+dispatch only; handlers live under `src/commands/<verb>.ts`; `provision` routes through `src/commands/provision.ts` (not overlay harness dispatch); launch composition splits under `src/commands/launch/`; commander owns per-command `--help` (no hand-rolled interception).
|
|
1298
1461
|
- **Published tarball is dist-only** — `files` no longer ships `src/`; `tsx` is a devDependency; `bin/mm-harness` and overlay leaves resolve `dist/*.js` (teaching error if a published install lacks `dist/`). Library actions keep importing `library/actions/harness-exports.mjs` (dist-preferring narrow bridge from 0.5.1); package exports remain for external consumers (`dist/index.js` published; `src/index.ts` when `--conditions=development` and dist is absent).
|
|
1299
1462
|
- **resolve-farmslot-ports is TypeScript-first** — pool/context/formula port resolution lives in self-contained `adapters/shared/resolve-farmslot-ports-core.mjs` (works from runner and injected overlay copies); `src/adapters/resolve-farmslot-ports.ts` re-exports it for `slot-ports.ts`. `resolve-farmslot-ports.mjs` is the node leaf; `resolve-farmslot-ports.sh` remains a thin bash-compat wrapper for sourced callers.
|
|
1300
1463
|
|
|
1301
1464
|
## 0.5.0 - 2026-07-05
|
|
1465
|
+
|
|
1302
1466
|
Minor release: thin Runway provisioning (harness-owned slot provisioning with a shared artifact cache) plus compiled-dist packaging.
|
|
1467
|
+
|
|
1303
1468
|
### Added
|
|
1469
|
+
|
|
1304
1470
|
- **`mm-harness provision runway`** — provisions a mobile slot with exactly: resolve the latest Runway (expo-dev-build) artifact, download it ONCE into a shared machine cache (`~/.cache/metamask-harness/runway/<runId>/`, sha256+size integrity, corrupt entries re-downloaded, never a slot failure), create the simulator if missing, install the dev client on it. Zero yarn/deps/Metro — those stay dispatch-time (lazy, presence-authoritative readiness unchanged). `install --runway` is the overlay-path equivalent (covered by its own contract test). Baseline recorded so doctor reports provisioned-but-deps-pending as a normal state.
|
|
1305
1471
|
- **Compiled `dist/` for published installs** — the npm tarball ships esbuild-compiled JS; `npm i -g` installs run the dist entry (~0.21s cold vs ~0.37s tsx). Source checkouts without `dist/` keep the tsx dev path; `bin/mm-harness` prefers dist when present. Packaging contract test (pack → global install → dist entry runs).
|
|
1472
|
+
|
|
1306
1473
|
### Changed
|
|
1474
|
+
|
|
1307
1475
|
- Runway provisioning callers (farm installer, mobile-farm `runway` prepare profile) delegate to the harness; the profile no longer runs a deps phase and a contract test enforces that.
|
|
1308
1476
|
|
|
1309
1477
|
## 0.4.0 - 2026-07-04
|
|
@@ -1311,6 +1479,7 @@ Minor release: thin Runway provisioning (harness-owned slot provisioning with a
|
|
|
1311
1479
|
Minor release: the adapter-surface architecture plus the day's feature wave (0.3.6-0.3.9 shipped fixes as they were validated live; this cut marks the surface additions honestly).
|
|
1312
1480
|
|
|
1313
1481
|
### Added
|
|
1482
|
+
|
|
1314
1483
|
- **AdapterSurface** — one per-platform surface behind a common interface (`src/adapters/surface.ts`: resolveSlotPorts, runtimeStatus, devServer, logSources, hints); doctor/launch/stop/logs/debug/fixtures are surface-backed, so no verb hand-rolls platform branching. Contract: `docs/ADAPTER-SURFACE.md` (never-branch rule, add-a-platform checklist, migration table).
|
|
1315
1484
|
- **Platform-adaptive `stop` on every adapter** — extension: kills this checkout's webpack watcher (pid file + orphan scan, slot-scoped) and closes its tail window; mobile: port-scoped Metro; core: headless teaching error. Idempotent, outcome-stating summaries.
|
|
1316
1485
|
- **Doctor reports live runtime state on every adapter** — mobile Metro, extension webpack (via the extension readiness decision), core deps-only — one uniform shape, adapter-scoped colored context rows.
|
|
@@ -1318,20 +1487,24 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1318
1487
|
- **Context-aware examples and tier-visible flows** — `call` usage/help examples use the detected adapter's real manifest actions; `flows` prints a precedence legend decoding each source into personal > team > canonical.
|
|
1319
1488
|
|
|
1320
1489
|
### Changed
|
|
1490
|
+
|
|
1321
1491
|
- **BREAKING (agent contract)**: `doctor --json` `runtime.metro` (string) is now `runtime.devServer` `{label, status}` and is absent for core.
|
|
1322
1492
|
|
|
1323
1493
|
### Feature wave recap (0.3.6-0.3.9)
|
|
1494
|
+
|
|
1324
1495
|
- `mm-harness stop`; live-streamed mobile AND extension launches with upfront intent lines; presence-authoritative readiness (no setup-on-every-launch) with the dev-client running probe; slot-context-first device/port resolution; UTF-8 locale for pod spawns; DEV OVERRIDE banner + SLOT line + colored help; `mmdev-harness` completions; hermetic tmux-stubbed contract suite (now gating CI) + ESLint in `npm run check`; `docs/UX-PRINCIPLES.md` interaction contract.
|
|
1325
1496
|
|
|
1326
1497
|
## 0.3.9 - 2026-07-04
|
|
1327
1498
|
|
|
1328
1499
|
### Fixed
|
|
1500
|
+
|
|
1329
1501
|
- **Readiness is presence-authoritative** — a no-baseline mtime-only stale verdict no longer re-runs `yarn setup` inside every launch (warning instead; fingerprint-verified drift still installs), the deps baseline is recorded after any successful setup, and the `ready` decision probes that the dev client is actually running on the target device before doing nothing (`launch` launches).
|
|
1330
1502
|
- **Slot-context-first resolution** — device/ports resolve from the checkout's `agentic-runtime.json` before pool/formula fallbacks, for mobile (simulator, Metro port) and extension (CDP + watcher ports, overwriting stale inherited env); naming formulas no longer hardcode pool prefixes.
|
|
1331
1503
|
- **UTF-8 locale for pod-triggering spawns** — CocoaPods no longer dies on multibyte podspecs under locale-less orchestrator environments.
|
|
1332
1504
|
- **Hermetic contract tests** — tmux/xcrun/adb are stubbed; the Metro log-window opens only in a run-owned session, never an unrelated attached one.
|
|
1333
1505
|
|
|
1334
1506
|
### Added
|
|
1507
|
+
|
|
1335
1508
|
- **`mm-harness stop`** — stop the port-scoped Metro this checkout owns and close its log-tail window; idempotent; teaching error on extension/core.
|
|
1336
1509
|
- **Extension launch streams live** with an upfront intent line (ports named); mobile and extension long operations are never silent.
|
|
1337
1510
|
- **Doctor reports live runtime state per platform** (deps currency, Metro on the slot's resolved port, dev-client presence) with adapter-scoped, colored runtime-context rows.
|
|
@@ -1339,6 +1512,7 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1339
1512
|
- **docs/UX-PRINCIPLES.md** — the CLI interaction contract (human surface rules; `--json` envelope purity is exempt and inviolable).
|
|
1340
1513
|
|
|
1341
1514
|
### Fixed
|
|
1515
|
+
|
|
1342
1516
|
- **Mobile preflight no longer re-runs `yarn setup` on every launch** — the deps readiness decision escalated an mtime hint to `stale` and ran the FULL `yarn setup` (submodules + inpage bridge + jetify + pods) inside the launch phase on every invocation in orchestrated (farmslot) contexts. `depsCheck` reports `stale` for a no-baseline checkout whenever a manifest is newer than the install markers; the orchestrator's git phase refreshes tracked-file mtimes on every sync while its deps phase leaves `node_modules` untouched, so "manifest newer than markers" is normal and not proof of drift — yet it duplicated the orchestrator's deps work and turned a fast preflight into 15+ minutes (the behavior that also looked like a hang before 0.3.8's streaming). **Presence is now authoritative:** without a recorded baseline an mtime-only `stale` is trusted as `current` (with a one-line stderr warning), so a churned-but-present checkout launches with zero `yarn` in both tiers. Genuine drift is still caught by the recorded-baseline fingerprint. `mm-harness launch` (quick tier / no `--build`) also dropped `preflightMode` before deciding, so the fast contract never took effect; it is threaded through now.
|
|
1343
1517
|
- **Fast tier never installs; genuine gaps teach the orchestrator** — in the fast tier (quick launch / orchestrated), deps that genuinely need work (absent markers, an absent required package, a fingerprint drift, or Metro unable to resolve a module) return a teaching block naming the orchestrator deps/prepare phase (plus the standalone `yarn setup:expo` / `launch --build` remedies) instead of an implicit setup — deps are the orchestrator's contract. The standalone/full tier still installs.
|
|
1344
1518
|
- **Deps baseline recorded the instant a setup leaf succeeds** — `prepareMobile` records the deps fingerprint baseline immediately after any successful `yarn-setup`, unconditionally (previously only a later `record: true` re-decide did, gated on the original decision being `install` and on `RECIPE_UP_INSTALL_ATTEMPTED`). Genuine-drift detection is fingerprint-based and self-sustaining after one good install.
|
|
@@ -1347,6 +1521,7 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1347
1521
|
- **Metro log-tail window no longer leaks into an unrelated tmux session** — running `start-metro` without an explicit session previously fell back to whichever tmux client was current or last attached. The viewer now opens a window only from `RECIPE_TMUX_SESSION` or the checkout runtime context and otherwise skips it; Metro still runs detached to the log. Extracted to `adapters/mobile/lib/tmux-viewer.sh` so the rule is unit-tested; contract tests stub tmux hermetically so no suite run can create a real window.
|
|
1348
1522
|
|
|
1349
1523
|
### Added
|
|
1524
|
+
|
|
1350
1525
|
- **Adapter surface — one seam for per-platform behavior** — `src/adapters/surface.ts` defines `AdapterSurface` + a `getAdapterSurface(adapter)` registry that owns the behavior commands used to hand-roll with `if (adapter === …)` ladders (slot-port resolution, read-only runtime status, dev-server describe/stop, log sources, and platform-phrased Next: hints), with thin `mobile`/`extension`/`core` implementations that delegate to the existing readiness/port plumbing (re-homed to `src/adapters/slot-ports.ts`). `doctor`, `launch`, `stop`, `logs`, `debug`, and `fixtures` now resolve platform behavior through the surface instead of branching. This closes the platform-blind class of bug (a platform handled in one command but forgotten in another). Documented in `docs/ADAPTER-SURFACE.md`; enforces `docs/UX-PRINCIPLES.md` principle 1.
|
|
1351
1526
|
- **`doctor` reports a runtime section for every adapter** — the live runtime readiness line (decision + reasons, deps currency, dev server) now renders for extension (webpack watcher via `decideExtensionReadiness`) and core (deps-presence-only), not just mobile; the render is one uniform shape sourced from the surface.
|
|
1352
1527
|
- **`mm-harness stop` is adaptive per platform** — mobile stops its port-scoped Metro and closes the log-tail window; extension stops the checkout's webpack watcher (pid file + orphan ps-scan, slot-scoped) and closes its tail window; core teaches the headless path. All idempotent (nothing-to-stop is success), with a uniform summary and `--json` envelope.
|
|
@@ -1358,6 +1533,7 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1358
1533
|
- **CLI help surface** — grouped/colored `mm-harness` help, a `DEV OVERRIDE ACTIVE` banner when `MM_HARNESS_BIN` is set, and a `SLOT` line when the checkout is a prepared slot; `mmdev-harness` completion alias.
|
|
1359
1534
|
|
|
1360
1535
|
### Changed
|
|
1536
|
+
|
|
1361
1537
|
- **`doctor --json` runtime dev-server shape is normalized** — the mobile-only `runtime.metro` string is replaced by a platform-labelled `runtime.devServer: { label, status }` (`metro` for mobile, `webpack` for extension; absent for headless core), so agents read one shape across platforms.
|
|
1362
1538
|
- **`yarn check` runs ESLint** — flat-config ESLint (typescript-eslint recommended on `src/**/*.ts`, `@eslint/js` recommended on the `.mjs`/`.cjs` library) runs after typecheck and comment-hygiene. Dev-only (not in the published `files`); the baseline is zero-warning by config scoping.
|
|
1363
1539
|
- **Deps install uses a scoped `setup:expo` variant when native isn't wanted** — `adapters/mobile/yarn-setup.sh` gains `--mode full|expo`. `expo` runs `yarn setup:expo --no-build-ios --no-build-android` (JS deps + prebuild, no native — native builds come from `open-device.sh`, never doubled); the full `yarn setup` runs only for a native build (`launch --build`). This is also the standalone Metro-only remedy taught by the fast-tier deps block.
|
|
@@ -1366,47 +1542,56 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1366
1542
|
## 0.3.8 - 2026-07-04
|
|
1367
1543
|
|
|
1368
1544
|
### Fixed
|
|
1545
|
+
|
|
1369
1546
|
- **Mobile launch streams progress in `--json` mode** — mobile prepare leaves now run through `spawnScriptStreaming`, which tees the child's stdout+stderr to the parent's stderr live while stdout stays reserved for the JSON envelope. A multi-minute `mm-harness launch --json` is no longer silent (previously `spawnSync` buffered leaf output and suppressed it entirely under `--json`). Contract test asserts leaf progress reaches stderr, the envelope stays clean, and the streaming conversion preserves the exit-code contract.
|
|
1370
1547
|
|
|
1371
1548
|
## 0.3.7 - 2026-07-04
|
|
1372
1549
|
|
|
1373
1550
|
### Fixed
|
|
1551
|
+
|
|
1374
1552
|
- **Overlay install manifest no longer advertises the retired `launch.sh`/`live.sh`** — mobile launch/live orchestration is in-process now (`mm-harness launch`), and `install_v1_runner_assets` deletes `scripts/launch.sh` and `scripts/live.sh` on both install paths. The product-owned/metadata-only manifest already advertised `verify` only, but the overlay manifest's `runtimeHelpers` still listed `launch: scripts/launch.sh` and `live: scripts/live.sh` — paths the same install had just removed, a manifest that pointed at nonexistent files. The overlay manifest now advertises `verify` only, matching the product-owned path. A new manifest-honesty contract check in `tests/contract/mobile-inject.test.sh` asserts every advertised `runtimeHelpers` path exists on disk and that `launch`/`live` are not advertised, for both the product-owned and a full overlay install, so this cannot recur in either mode.
|
|
1375
1553
|
|
|
1376
1554
|
## 0.3.6 - 2026-07-04
|
|
1377
1555
|
|
|
1378
1556
|
### Fixed
|
|
1557
|
+
|
|
1379
1558
|
- **Install manifest carries target checkout identity (`targetRevision`)** — `adapters/mobile/inject.sh` stamps the target repo's `HEAD` (resolved once, up front, via `git rev-parse --verify HEAD`) and an explicit `installMode` into the mobile install manifest on both install paths (product-owned/metadata-only and overlay). Consumers (the farm recipe hook) can now gate their fast path on manifest identity matching the current checkout instead of manifest existence, closing the stale-manifest hole where a gitignored manifest survives a branch switch to a bridge-less checkout. Install now fails with teaching guidance when the target `HEAD` cannot be resolved (not-a-repo, unborn branch), instead of stamping an unusable `targetRevision`. Contract tests cover the identity stamp on both paths and the unborn-HEAD refusal.
|
|
1380
1559
|
|
|
1381
1560
|
## 0.3.5 - 2026-07-04
|
|
1382
1561
|
|
|
1383
1562
|
### Fixed
|
|
1563
|
+
|
|
1384
1564
|
- **IMP-24b: shell leaves run even when packed without the exec bit** — `yarn pack` (used by `yarn npm publish`) strips the executable bit off shipped `*.sh` leaves to `644`, even though git stores `100755` and `npm pack` preserves `755`. The 0.3.4 fix (git `100755` + an `npm pack` tarball test) was therefore insufficient: the published `yarn`-packed tarball still shipped `644` leaves and a fresh `npm i -g` hit `EACCES` on the first leaf. `spawnScript` now invokes shell leaves through `bash <leaf>` instead of exec'ing them directly, so the leaf's file mode is irrelevant (node leaves were already interpreter-invoked via `process.execPath`). Env overlays (`FORCE_COLOR`/`RECIPE_RUNTIME_DIR`), arg passing, cwd, JSON envelope, and exit codes are unchanged. New contract test `tests/contract/leaf-644-runs.test.sh` forces the device leaves to mode `644` and drives them through the real `mm-harness` spawn path, asserting they still run — the regression the `npm pack` tarball test could not catch.
|
|
1385
1565
|
|
|
1386
1566
|
### Changed
|
|
1567
|
+
|
|
1387
1568
|
- **Publish with `npm publish`, not `yarn npm publish`** — `npm publish` preserves the git `100755` mode on shipped `*.sh` leaves (defense-in-depth on top of the interpreter invocation above). Documented in `AGENTS.md`; git exec bits remain `100755`.
|
|
1388
1569
|
|
|
1389
1570
|
## 0.3.4 - 2026-07-04
|
|
1390
1571
|
|
|
1391
1572
|
### Fixed
|
|
1573
|
+
|
|
1392
1574
|
- **IMP-24: published tarball stripped exec bits from shell leaves** — the harness execs `adapters/**/*.sh` leaves directly, but six shipped leaves (`adapters/mobile/lib/metro-listener.sh`, `adapters/shared/activate-repo-node.sh`, `cli-ux.sh`, `harness-path.sh`, `hash-helpers.sh`, `resolve-farmslot-ports.sh`) were committed without the git exec bit (mode `100644`), so npm packed them `644`. A fresh `npm i -g` then hit `EACCES` on the first leaf. All shipped `*.sh` are now stored `100755` in git, so the published tarball packs them executable. Added contract test `tests/contract/packaging-exec-bits.test.sh` — it runs `npm pack` to produce the actual `.tgz`, then asserts via `tar tzvf` that every shipped `*.sh` entry has owner-execute set; fails with the offending path(s) if any is `644`, so this cannot silently regress.
|
|
1393
1575
|
- **IMP-24: spawn failures are surfaced, not swallowed** — `spawnScript` returned on `result.error` (a leaf that is missing/`ENOENT` or not executable/`EACCES`) before its human-mode stderr forward, so a leaf that could not start produced a silent exit-1 (surfaced upstream as `MOBILE_PREPARE_FAILED`). The `result.error` branch now always writes a teaching diagnostic (`leaf could not start: <leaf> (<errno>)` + a `Next: reinstall mm-harness` hint) to stderr before returning. Covered by `tests/contract/spawn-error-surfaced.test.sh`.
|
|
1394
1576
|
|
|
1395
1577
|
## 0.3.3 - 2026-07-04
|
|
1396
1578
|
|
|
1397
1579
|
### Fixed
|
|
1580
|
+
|
|
1398
1581
|
- **IMP-23: per-run mobile runtime dir (`RECIPE_RUNTIME_DIR`)** — every on-disk mobile runtime file (`metro.log`, `metro.pid`, `metro.tmux`, `bridge-status.log`, `wallet-fixture.json`) now resolves from the shared runtime-dir resolver that honors `RECIPE_RUNTIME_DIR` instead of the hard-coded `<target>/temp/recipe/runtime`. `RECIPE_RUNTIME_DIR` must be a non-empty relative path under the target checkout — absolute values are rejected at validation. Shell (`recipe_runtime_dir` in `harness-path.sh`, used by `start-metro.sh`, `wait-for-bridge.sh`, `prewarm-bundle.sh`, and `bridge-runtime/setup-wallet.sh`) and TS (`recipeRuntimePath` in `runtime-decision.ts`) resolve the same location, so a run pointed at an isolated subdir (e.g. `temp/recipe/runtime-8081`) writes and reads nothing under the default. Two harness jobs sharing one checkout each set `RECIPE_RUNTIME_DIR` to a distinct relative subdir for full runtime isolation.
|
|
1399
1582
|
- **IMP-23: port-scoped Metro guard** — the Metro detect/kill/restart helpers are extracted into `adapters/mobile/lib/metro-listener.sh` with an explicit invariant: discovery, inspection, and signalling key off the managed watcher-port only (`lsof -iTCP:<port> -sTCP:LISTEN`). A Metro listening on any other port is never selected, never has its cmdline read, and is never signalled, so a run managing one port cannot detect or kill a concurrent Metro on another port in the same checkout.
|
|
1400
1583
|
|
|
1401
1584
|
## 0.3.2 - 2026-07-04
|
|
1402
1585
|
|
|
1403
1586
|
### Fixed
|
|
1587
|
+
|
|
1404
1588
|
- **IMP-21: FORCE_COLOR-safe pod install** — the mobile pod-triggering leaves (`yarn-setup.sh` running `yarn setup`, and `open-device.sh` running the native `yarn start:ios|android` build) now run with `FORCE_COLOR=0` / `NO_COLOR=1`. VisionCamera's podspec probes `node --print require.resolve('react-native-worklets-core')` and treats any output other than the exact string `undefined` as "found"; an inherited `FORCE_COLOR` made node emit a colorized `undefined`, enabling FrameProcessors and hard-failing on the missing worklets pod. Setup/native builds are now reliable from a `FORCE_COLOR` shell.
|
|
1405
1589
|
- **IMP-22: `--watcher-port` beats `.js.env WATCHER_PORT`** — `verify.sh` port resolution now honors an explicit `WATCHER_PORT` in the process env (which carries `mm-harness launch --watcher-port N`) over the target's `.js.env`. Precedence is flag > process env > `.js.env` > `8081` default, so a run can be pointed at an alternate Metro/CDP port without editing a shared slot's `.js.env`.
|
|
1406
1590
|
|
|
1407
1591
|
## 0.3.1 - 2026-07-03
|
|
1408
1592
|
|
|
1409
1593
|
### Fixed
|
|
1594
|
+
|
|
1410
1595
|
- **Customization compose-by-ref**: recipes with `{action:"call",ref:"<lib>.<flow>"}` + `--library <lib>=<dir>` now pass pre-run schema validation AND execute at runtime. `validateRecipeAdapterAware` threads `externalFlowIds` into both `validateRecipeDocument` and `validateRecipeWithManifest`; library resolution also runs at `run` time.
|
|
1411
1596
|
- **IMP-14: stale metro.log guard** — if `metro.log` is older than the install markers (`node_modules/.yarn-state.yml`, `.yarn/install-state.gz`), it is treated as absent so a stale log cannot drive a false native-module-mismatch decision at launch.
|
|
1412
1597
|
- **IMP-15: stale overlay shim auto-repair (two modes)** — `ensureOverlay` detects (1) a `.runner-source` pointing to a nonexistent runner dir, and (2) a `.runner-source` whose dir exists but whose `bin/mm-harness` was removed. Both re-install automatically before launch.
|
|
@@ -1416,9 +1601,11 @@ Minor release: the adapter-surface architecture plus the day's feature wave (0.3
|
|
|
1416
1601
|
## 0.3.0 - 2026-07-03
|
|
1417
1602
|
|
|
1418
1603
|
### Changed
|
|
1604
|
+
|
|
1419
1605
|
- Porcelain layer eliminated: the legacy `mm-recipe`/`mme-recipe`/`metamask-recipe` bins are gone; launch/logs/debug/fixtures compose the adapter scripts directly in TypeScript. Repository reorganized into `src/` (all TS), `adapters/` (per-platform runtime glue), `library/` (recipe/action/flow vocabulary).
|
|
1420
1606
|
|
|
1421
1607
|
### Fixed
|
|
1608
|
+
|
|
1422
1609
|
- Extension `launch` opens the app directly (composes `live.sh`) instead of a retired command.
|
|
1423
1610
|
- Mobile `cleanup` resilient to a stale runner-source path.
|
|
1424
1611
|
- Core run teaches the correct next step when no account is set.
|