@deeeed/metamask-harness 0.91.6 → 0.92.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 CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.92.0 - 2026-10-14
6
+
7
+ ### Changed
8
+
9
+ - Use the coordinated public recipe-engine release for immutable artifact closeout and engine-owned attempt publication manifests.
10
+ - Keep browser provenance checks on the engine finalization contract, with native browser lifetime conformance in the live release tier.
11
+
12
+ ### Fixed
13
+
14
+ - Extension Perps smoke binds document and native captures to its passing observations for live conformance. Existing `perps-home` callers remain supported, and `smoke` names the shared QA proof.
15
+ - Retain invocation-owned backend logs through engine closeout before the canonical artifact manifest is written.
16
+ - Finish successful Mobile dependency recovery with explicit install-baseline recording so a retry accepts the installed content.
17
+
18
+ ### Removed
19
+
20
+ - `MM_HARNESS_BIN` entrypoint delegation. Invoke a development checkout directly; Farmslot selects the provider package root. Public commands, arguments and executable identity are preserved.
21
+
22
+ ## 0.91.7 - 2026-10-13
23
+
24
+ ### Changed
25
+
26
+ - Use the coordinated Farmslot recipe closure for fresh task attempt directories, selected-package checks and declared output provenance. Reusing a retained `--artifacts-dir` refuses and preserves its evidence.
27
+
28
+ ### Fixed
29
+
30
+ - Render PR validation logs from the selected retained attempt, including when an older legacy report remains.
31
+
5
32
  ## 0.91.6 - 2026-10-13
6
33
 
7
34
  ### Fixed
package/README.md CHANGED
@@ -447,14 +447,13 @@ failure.
447
447
  - [QA](docs/QA.md) — clean-machine and human release checks.
448
448
  - [Contributing](docs/CONTRIBUTING.md) — ownership, layout, and change gates.
449
449
 
450
- For development, point the installed command at a source checkout:
450
+ For development, invoke the source checkout directly:
451
451
 
452
452
  ```bash
453
- export MM_HARNESS_BIN=/path/to/metamask-harness/bin/mm-harness
454
- mm-harness --version
453
+ /path/to/metamask-harness/bin/mm-harness --version
455
454
  ```
456
455
 
457
- Unset `MM_HARNESS_BIN` to return to the published installation.
456
+ Farmslot selects that same package through `recipe.provider.root.env`, configured as `MM_HARNESS_PACKAGE_ROOT`. Binary environment overrides do not redirect the public entrypoint.
458
457
 
459
458
 
460
459
  ### Workflow entry points and completion
package/bin/mm-harness CHANGED
@@ -29,43 +29,11 @@ done
29
29
  SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd -P)"
30
30
  RUNNER_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
31
31
 
32
- # Dev/prod switch (the single override point). MM_HARNESS_BIN, when set, is the
33
- # authoritative path to a dev checkout's bin/mm-harness with active pre-release
34
- # changes; unset resolves the installed/global mm-harness (prod). Handing the
35
- # invocation over here, before any dependency work, lets the dev checkout fully
36
- # own the run. The self-path guard prevents an exec loop when MM_HARNESS_BIN
37
- # already points at this script — including via a symlink (both sides are resolved
38
- # to their real paths before comparing).
39
- if [ -n "${MM_HARNESS_BIN:-}" ]; then
40
- self_real="$SCRIPT_DIR/${SOURCE##*/}"
41
- # Resolve MM_HARNESS_BIN through any symlink chain so a symlink-to-self is caught.
42
- mm_bin_src="$MM_HARNESS_BIN"
43
- while [ -L "$mm_bin_src" ]; do
44
- mm_bin_dir="$(cd "$(dirname "$mm_bin_src")" && pwd -P)"
45
- mm_bin_target="$(readlink "$mm_bin_src")"
46
- if [[ "$mm_bin_target" == /* ]]; then
47
- mm_bin_src="$mm_bin_target"
48
- else
49
- mm_bin_src="$mm_bin_dir/$mm_bin_target"
50
- fi
51
- done
52
- bin_real_dir="$(cd "$(dirname "$mm_bin_src")" 2>/dev/null && pwd -P || true)"
53
- bin_real="${bin_real_dir:+$bin_real_dir/${mm_bin_src##*/}}"
54
- if [ "$bin_real" != "$self_real" ]; then
55
- if [ ! -x "$MM_HARNESS_BIN" ]; then
56
- echo "mm-harness: MM_HARNESS_BIN is not an executable: $MM_HARNESS_BIN" >&2
57
- echo " Next: point MM_HARNESS_BIN at a checkout's bin/mm-harness, or unset it to use the global install" >&2
58
- exit 1
59
- fi
60
- exec "$MM_HARNESS_BIN" "$@"
61
- fi
62
- fi
63
-
64
32
  # Internal executable identity (not part of the public env surface): the CLI
65
33
  # embeds this in emitted recovery commands so they run verbatim even when
66
- # mm-harness is not on PATH (task-local installs). Set AFTER the MM_HARNESS_BIN
67
- # delegation above so the final executable entered always overwrites any
68
- # inherited/stale value with its own resolved self path.
34
+ # mm-harness is not on PATH (task-local installs). Set at the
35
+ # invocation entry so the executable always overwrites an inherited/stale
36
+ # value with its own resolved self path.
69
37
  export MM_HARNESS_EXECUTABLE="$SCRIPT_DIR/${SOURCE##*/}"
70
38
  export MM_HARNESS_INVOKED_AS="$INVOKED_AS"
71
39
 
@@ -11,7 +11,7 @@ import {
11
11
  supersededErrorCapture
12
12
  } from "@farmslot/recipe-runner/runtime/log-analysis";
13
13
  import { probeMetroPackager } from "@farmslot/recipe-runner/runtime/metro-probe";
14
- import { color, recipeRuntimePath, shellQuote } from "@farmslot/recipe-cli/harness";
14
+ import { recipeRuntimePath, shellQuote } from "@farmslot/recipe-cli/harness";
15
15
  import { resolveMobileToolPath } from "@farmslot/adapter-rn";
16
16
  import { mobileProductMarkers } from "./deps-markers.js";
17
17
  import { mobileMetroEnvCheck } from "./metro-env.js";
@@ -164,7 +164,7 @@ async function decideMobileReadiness(target, options = {}) {
164
164
  ...report.reasons,
165
165
  "Quick launch does not install dependencies."
166
166
  ],
167
- userAction: `cd ${shellQuote(resolved)} && ${depsInstallCommand(resolved)}`,
167
+ userAction: `cd ${shellQuote(resolved)} && ${depsInstallCommand(resolved)} && mm-harness runtime-decision --adapter mobile --target ${shellQuote(resolved)} --record-baseline`,
168
168
  actions: []
169
169
  };
170
170
  }
@@ -185,24 +185,10 @@ async function decideMobileReadiness(target, options = {}) {
185
185
  )
186
186
  };
187
187
  }
188
- function writeDepsNote() {
189
- const stream = process.stderr;
190
- const body = "No install baseline is recorded. Required package checks passed; timestamps alone do not establish dependency drift. Reusing the installed dependencies.";
191
- stream.write(
192
- `
193
- ${color("warn", "mm-harness note (deps):", { stream })} ${color("dim", body, { stream })}
194
-
195
- `
196
- );
197
- }
198
188
  async function computeMobileReadiness(resolved, options, fast) {
199
- const rawDeps = depsCheck(resolved, {
189
+ let deps = depsCheck(resolved, {
200
190
  productMarkers: mobileProductMarkers(options.platform)
201
191
  });
202
- let deps = rawDeps;
203
- if (rawDeps.status === "stale" && !rawDeps.hasBaseline) {
204
- deps = { installed: rawDeps.installed, status: "current", hasBaseline: false };
205
- }
206
192
  if (deps.status === "current") {
207
193
  const absent = missingRequiredDeps(resolved);
208
194
  if (absent.length > 0) {
@@ -320,7 +306,6 @@ async function computeMobileReadiness(resolved, options, fast) {
320
306
  actions: installActions(resolved)
321
307
  };
322
308
  }
323
- if (rawDeps.status === "stale" && !rawDeps.hasBaseline) writeDepsNote();
324
309
  if (metro.status === "down") {
325
310
  return {
326
311
  schemaVersion: 1,
@@ -40,18 +40,6 @@ async function createBackendProvider(context) {
40
40
  };
41
41
  const serviceLog = path.join(target, ".agent/terminal-backend/service.log");
42
42
  const logOffset = fs.existsSync(serviceLog) ? fs.statSync(serviceLog).size : 0;
43
- const output = path.resolve(target, String(context.options?.artifactsDir ?? context.project.artifactDir));
44
- const manifest = path.join(output, "artifact-manifest.json");
45
- const manifestIdentity = () => {
46
- try {
47
- const s = fs.statSync(manifest, { bigint: true });
48
- return [s.dev, s.ino, s.size, s.mtimeNs, s.ctimeNs].join(":");
49
- } catch (error) {
50
- if (error.code === "ENOENT") return void 0;
51
- throw error;
52
- }
53
- };
54
- const previousManifest = manifestIdentity();
55
43
  if (owner) {
56
44
  setEnv("BACKEND_OWNER_ID", owner);
57
45
  setEnv("BACKEND_LIFECYCLE_SCRIPT", lifecycle);
@@ -59,6 +47,19 @@ async function createBackendProvider(context) {
59
47
  const cleanup = async () => {
60
48
  if (owner) await main([...args("stop"), owner]);
61
49
  };
50
+ let finalized = false;
51
+ const finalize = async () => {
52
+ if (finalized) return;
53
+ finalized = true;
54
+ try {
55
+ await cleanup();
56
+ } finally {
57
+ for (const [key, value] of previous) {
58
+ if (value === void 0) delete process.env[key];
59
+ else process.env[key] = value;
60
+ }
61
+ }
62
+ };
62
63
  const logSource = () => ({ label: "NestJS and monitor", path: serviceLog });
63
64
  const hint = "Prepare the selected slot with the full profile.";
64
65
  const runtime = defineAdapter({
@@ -83,6 +84,20 @@ async function createBackendProvider(context) {
83
84
  readiness: { statusRuntime: true, captureProviders: [], readyIndicator: () => "OK" },
84
85
  logSources: () => [logSource()],
85
86
  appLogSource: logSource,
87
+ ...owner ? { observation: { performance: {
88
+ async start({ artifactsDir }) {
89
+ return {
90
+ onActionEvent() {
91
+ },
92
+ async finalize(observerManifestPath) {
93
+ await finalize();
94
+ if (!observerManifestPath || !fs.existsSync(serviceLog)) return;
95
+ await writeContainedArtifact(artifactsDir, "logs/backend.log", fs.readFileSync(serviceLog).subarray(logOffset), "Backend logs");
96
+ await indexArtifactManifest(observerManifestPath, [{ category: "log", label: "Backend and monitor logs", path: "logs/backend.log", type: "text" }]);
97
+ }
98
+ };
99
+ }
100
+ } } } : {},
86
101
  hints: { launch: hint, relaunch: hint, runtimeProbeRecovery: () => "Inspect the slot service.log and run farmslot doctor --conformance." },
87
102
  devServer: {
88
103
  label: "NestJS",
@@ -119,32 +134,9 @@ async function createBackendProvider(context) {
119
134
  }
120
135
  });
121
136
  if (executing) runtime.resolveSlotPorts();
122
- let finalized = false;
123
137
  return {
124
138
  runtime,
125
- ...owner ? {
126
- cancel: cleanup,
127
- async finalize() {
128
- if (finalized) return;
129
- finalized = true;
130
- try {
131
- try {
132
- await cleanup();
133
- } finally {
134
- const currentManifest = manifestIdentity();
135
- if (fs.existsSync(serviceLog) && currentManifest !== void 0 && currentManifest !== previousManifest) {
136
- await writeContainedArtifact(output, "logs/backend.log", fs.readFileSync(serviceLog).subarray(logOffset), "Backend logs");
137
- await indexArtifactManifest(manifest, [{ category: "log", label: "Backend and monitor logs", path: "logs/backend.log", type: "text" }]);
138
- }
139
- }
140
- } finally {
141
- for (const [key, value] of previous) {
142
- if (value === void 0) delete process.env[key];
143
- else process.env[key] = value;
144
- }
145
- }
146
- }
147
- } : {}
139
+ ...owner ? { cancel: cleanup, finalize } : {}
148
140
  };
149
141
  }
150
142
  export {
@@ -779,7 +779,7 @@ Common overrides:
779
779
  --adapter <{adapters}> Target adapter (auto-detected inside a checkout)
780
780
  --platform <ios|android> Mobile platform preference; use --adapter for the product adapter
781
781
  --target <path> Checkout path (default: cwd)
782
- --artifacts-dir <dir> Override evidence output (default: active task/artifacts, otherwise a checkout-local temp/recipe/runs/<run>)
782
+ --artifacts-dir <dir> Fresh evidence output (default: active task/artifacts/recipe-runs/<attempt>, otherwise checkout-local temp/recipe/runs/<run>); retained packages cannot be reused
783
783
  --funding-request <absolute-file> Original consented mutation request for external-mutation actions
784
784
  --funding-preflight <absolute-file> Eligible funding preflight bound to the request bytes
785
785
  --funding-release-proof <absolute-file> Exact release proof independently bound to funding eligibility
@@ -1343,7 +1343,7 @@ Example:
1343
1343
  where available) and prints the copy's executable. A task records that path,
1344
1344
  so \`npm i -g\` upgrading the global install never changes the harness a running
1345
1345
  task runs. Idempotent: the same install returns the same pin. A source checkout
1346
- (MM_HARNESS_BIN) or an existing pin is printed as is.
1346
+ invoked directly or an existing pin is printed as is.
1347
1347
 
1348
1348
  --json Machine-readable { version, source, executable, pinned, created }
1349
1349
 
@@ -260,9 +260,8 @@ function launchPass(launch, profile, state, remoteFlags) {
260
260
  );
261
261
  } else {
262
262
  const tierNote = tier === "quick" ? "quick relaunch, no native build" : tier;
263
- const devNote = process.env.MM_HARNESS_BIN ? ` ${color("dim", "[dev: MM_HARNESS_BIN]")}` : "";
264
263
  console.error(
265
- `${color("ok", "\u2713")} launch ${adapter}${platformTarget ? ` ${platformTarget}` : ""} \u2014 ${color("ok", profile.deviceLabel(launch))} \xB7 ${tierNote} \xB7 app + bridge ready${devNote}`
264
+ `${color("ok", "\u2713")} launch ${adapter}${platformTarget ? ` ${platformTarget}` : ""} \u2014 ${color("ok", profile.deviceLabel(launch))} \xB7 ${tierNote} \xB7 app + bridge ready`
266
265
  );
267
266
  }
268
267
  return EXIT.ok;
@@ -265,8 +265,8 @@ await createHarnessCli({
265
265
  "SETUP \u2014 tab-completion (zsh + bash), sourced from the bundled scripts:",
266
266
  " mm-harness completions install # print the lines to add to ~/.zshrc / ~/.bashrc",
267
267
  "",
268
- "DEV/PROD \u2014 the global npm install is prod; set MM_HARNESS_BIN to a dev checkout to override:",
269
- " MM_HARNESS_BIN=/path/to/checkout/bin/mm-harness # unset = the installed/global bin",
268
+ "DEVELOPMENT \u2014 invoke the source checkout directly; Farmslot selects its configured provider package root:",
269
+ " /path/to/checkout/bin/mm-harness --version",
270
270
  "",
271
271
  "See README.md for the workflow and docs/RECIPES.md for proof authoring."
272
272
  ],
@@ -1,5 +1,9 @@
1
1
  import fs from "node:fs";
2
+ import { createRequire } from "node:module";
2
3
  import path from "node:path";
4
+ const { readRecipeAttemptSelection } = createRequire(import.meta.url)(
5
+ "@farmslot/agent-runtime/scripts/retained-recipe-attempt.cjs"
6
+ );
3
7
  const PROSE_FILE = "pr-description.md";
4
8
  const BODY_FILE = "pr-body.md";
5
9
  const RECIPE_HEADING = "## **Validation Recipe**";
@@ -77,7 +81,9 @@ function renderPrBody(input) {
77
81
  throw new Error(`Missing ${path.relative(input.taskDir, prosePath)}: write the PR description there first.`);
78
82
  }
79
83
  const recipePath = path.join(artifacts, "recipe.json");
80
- const reportPath = path.join(artifacts, "recipe-run", "report.md");
84
+ const selected = readRecipeAttemptSelection(input.taskDir);
85
+ const reportRoot = selected?.relativeArtifactRoot ?? "recipe-run";
86
+ const reportPath = path.join(artifacts, reportRoot, "report.md");
81
87
  const workflowPath = path.join(artifacts, "workflow.mmd");
82
88
  const machine = [];
83
89
  let recipe = null;
@@ -91,7 +97,7 @@ function renderPrBody(input) {
91
97
  const hasReport = fs.existsSync(reportPath);
92
98
  machine.push([
93
99
  LOGS_HEADING,
94
- hasReport ? logsSection(reportPath, input.command) : "Not applicable: no recipe run report under `artifacts/recipe-run/`."
100
+ hasReport ? logsSection(reportPath, input.command) : `Not applicable: no recipe run report under \`artifacts/${reportRoot}/\`.`
95
101
  ]);
96
102
  const hasWorkflow = fs.existsSync(workflowPath);
97
103
  if (hasWorkflow) {
@@ -10,7 +10,7 @@ Callers scanned (2026-10-02):
10
10
 
11
11
  ## Resolution and environment
12
12
 
13
- - Farms resolve the binary with `HARNESS_BIN="${METAMASK_HARNESS_BIN:-${MM_HARNESS_BIN:-mm-harness}}"; command -v "$HARNESS_BIN"`. `MM_HARNESS_BIN` hands the whole invocation to another checkout's `bin/mm-harness`.
13
+ - Farms select the provider package through `recipe.provider.root.env`, configured as `MM_HARNESS_PACKAGE_ROOT`, and invoke its public `mm-harness` command. The entrypoint stays in the package invoked; inherited binary overrides cannot redirect it.
14
14
  - Static review runs `{{support}}/bin/mm-harness` with entry `dist/mm-harness-cli.js`, so the package layout (`bin/`, `dist/`) is part of the contract.
15
15
  - Hook environment: `RECIPE_SLOT_ID`, `RECIPE_RUNTIME_DIR` (default `temp/recipe/runtime`), `RECIPE_WALLET_FIXTURE`, `RECIPE_LIBRARY_PATH`, `MM_HARNESS_DOMAIN`, `IOS_SIMULATOR`/`ADB_SERIAL` (mobile slots), `RECIPE_HARNESS_ROOT=temp/recipe/harness` (Extension).
16
16
 
@@ -0,0 +1,63 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "MetaMask Extension Perps smoke observation",
4
+ "description": "Observe the populated Perps home and retain its document and native viewport. The caller establishes the network and opens Perps before this read-only proof.",
5
+ "workflow": {
6
+ "entry": "read-home",
7
+ "nodes": {
8
+ "read-home": {
9
+ "action": "metamask.perps.read_visible_state",
10
+ "surface": "home",
11
+ "minimum_market_count": 1,
12
+ "require_features": [
13
+ "balance",
14
+ "market-list"
15
+ ],
16
+ "intent": "Observe a populated Perps home after setup",
17
+ "next": "assert-home",
18
+ "forbid_test_ids": [
19
+ "perps-tutorial-skip-button"
20
+ ],
21
+ "max_items": 200
22
+ },
23
+ "assert-home": {
24
+ "action": "assert_output",
25
+ "source": "read-home",
26
+ "assert": {
27
+ "path": "$.surface",
28
+ "operator": "eq",
29
+ "value": "home"
30
+ },
31
+ "intent": "The observed surface is Perps home",
32
+ "next": "assert-markets"
33
+ },
34
+ "assert-markets": {
35
+ "action": "assert_output",
36
+ "source": "read-home",
37
+ "assert": {
38
+ "path": "$.marketCount",
39
+ "operator": "gte",
40
+ "value": 1
41
+ },
42
+ "intent": "Perps home contains market data rather than only a loading shell",
43
+ "next": "capture-document"
44
+ },
45
+ "capture-document": {
46
+ "action": "ui.capture_surface",
47
+ "path": "evidence/perps-smoke-document.png",
48
+ "next": "capture-window",
49
+ "intent": "Keep the observed Perps home document for visual review"
50
+ },
51
+ "capture-window": {
52
+ "action": "ui.screenshot",
53
+ "path": "screenshots/perps-smoke.png",
54
+ "next": "done",
55
+ "intent": "Keep the native Perps viewport after its market checks"
56
+ },
57
+ "done": {
58
+ "action": "end",
59
+ "status": "pass"
60
+ }
61
+ }
62
+ }
63
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "MetaMask Extension Perps smoke",
4
- "description": "Sets and verifies the configured Perps network, default testnet, before proof. Extension Perps smoke: verifies CDP, unlocks if needed, opens Perps, proves visible home with market data, and reads positions/orders. Requires approved wallet setup and completed onboarding gates; a visible tutorial is setup, not passing smoke.",
4
+ "description": "Sets and verifies the configured Perps network, default testnet, before proof. Verifies CDP, unlocks if needed, opens Perps, asserts visible home and market data, retains document and native captures, and reads positions/orders. Requires approved wallet setup and completed onboarding gates; a visible tutorial is setup, not passing smoke.",
5
5
  "paramsSchema": {
6
6
  "type": "object",
7
7
  "additionalProperties": false,
@@ -26,7 +26,7 @@
26
26
  "page": false,
27
27
  "positions": false,
28
28
  "orders": false,
29
- "next": "read-home",
29
+ "next": "observe-perps",
30
30
  "intent": "Verify the configured Perps network before proof; default testnet. Keep accounts and orders."
31
31
  },
32
32
  "status": {
@@ -67,55 +67,29 @@
67
67
  "action": "end",
68
68
  "status": "pass"
69
69
  },
70
- "read-home": {
71
- "action": "metamask.perps.read_visible_state",
72
- "surface": "home",
73
- "minimum_market_count": 1,
74
- "require_features": [
75
- "balance",
76
- "market-list"
77
- ],
78
- "intent": "Observe a populated Perps home after setup",
79
- "next": "assert-home",
80
- "forbid_test_ids": [
81
- "perps-tutorial-skip-button"
82
- ],
83
- "max_items": 200
84
- },
85
- "assert-home": {
86
- "action": "assert_output",
87
- "source": "read-home",
88
- "assert": {
89
- "path": "$.surface",
90
- "operator": "eq",
91
- "value": "home"
92
- },
70
+ "observe-perps": {
71
+ "action": "call",
72
+ "ref": "perps.smoke-observation",
93
73
  "proves": [
94
- "perps-home"
74
+ "perps-home",
75
+ "smoke"
95
76
  ],
96
- "intent": "The observed surface is Perps home",
97
- "next": "assert-markets"
98
- },
99
- "assert-markets": {
100
- "action": "assert_output",
101
- "source": "read-home",
102
- "assert": {
103
- "path": "$.marketCount",
104
- "operator": "gte",
105
- "value": 1
106
- },
107
- "proves": [
108
- "perps-home"
109
- ],
110
- "intent": "Perps home contains market data rather than only a loading shell",
111
- "next": "read-positions"
77
+ "next": "read-positions",
78
+ "intent": "Check the populated Perps home and retain its observed viewport"
112
79
  }
113
80
  }
114
81
  },
115
82
  "proofTargets": [
116
83
  {
117
84
  "id": "perps-home",
118
- "claim": "The unlocked Perps home has visible market data and no observed tutorial gate."
85
+ "claim": "The unlocked Perps home has visible market data and no observed tutorial gate.",
86
+ "proofMode": "state"
87
+ },
88
+ {
89
+ "id": "smoke",
90
+ "kind": "qa-check",
91
+ "claim": "The unlocked Perps home has visible market data and no observed tutorial gate.",
92
+ "proofMode": "state"
119
93
  }
120
94
  ]
121
95
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeeed/metamask-harness",
3
- "version": "0.91.6",
3
+ "version": "0.92.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mm-harness": "bin/mm-harness"
@@ -21,15 +21,15 @@
21
21
  "check:syntax": "find . -name '*.mjs' -print0 | xargs -0 -n1 node --check"
22
22
  },
23
23
  "dependencies": {
24
- "@farmslot/adapter-node": "0.1.14",
25
- "@farmslot/adapter-rn": "0.20.1",
26
- "@farmslot/adapter-sdk": "0.9.1",
27
- "@farmslot/adapter-web": "0.7.2",
28
- "@farmslot/agent-runtime": "0.18.1",
24
+ "@farmslot/adapter-node": "0.1.17",
25
+ "@farmslot/adapter-rn": "0.22.1",
26
+ "@farmslot/adapter-sdk": "0.12.0",
27
+ "@farmslot/adapter-web": "0.8.2",
28
+ "@farmslot/agent-runtime": "0.20.1",
29
29
  "@farmslot/handoff": "^0.3.1",
30
- "@farmslot/protocol": "0.40.0",
31
- "@farmslot/recipe-cli": "0.14.3",
32
- "@farmslot/recipe-runner": "0.31.0",
30
+ "@farmslot/protocol": "0.43.0",
31
+ "@farmslot/recipe-cli": "0.16.1",
32
+ "@farmslot/recipe-runner": "0.34.0",
33
33
  "agent-device": "0.19.3",
34
34
  "commander": "^12.0.0",
35
35
  "esbuild": "0.28.1",