@deeeed/metamask-harness 0.92.10 → 0.92.12
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 +16 -0
- package/adapters/mobile/lib/idb-companion.sh +68 -0
- package/adapters/mobile/stop-metro.sh +11 -1
- package/dist/commands/help.js +13 -5
- package/dist/provider.js +15 -1
- package/package.json +1 -1
- package/site/assets/help-recipes.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Refresh Terminal contract goldens for the shipped console-error window, capture-provider metadata and engine evidence inventories.
|
|
8
|
+
|
|
9
|
+
## 0.92.12 - 2026-10-16
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Stop checkout-owned idb companions with the selected simulator identity, even when Metro and the simulator are already stopped; preserve other devices, checkouts and reused process IDs.
|
|
14
|
+
|
|
15
|
+
## 0.92.11 - 2026-10-16
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Supply the existing platform-specific recipe quality guide to Farmslot quality help, with canonical recipe commands and unchanged opt-in advice.
|
|
20
|
+
|
|
5
21
|
## 0.92.10 - 2026-10-16
|
|
6
22
|
|
|
7
23
|
### Changed
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stop only companions bound to this checkout and its selected simulator.
|
|
3
|
+
|
|
4
|
+
_idb_companion_identity() {
|
|
5
|
+
ps -p "$1" -o pid=,pgid=,lstart=,comm= 2>/dev/null
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
# 1 is foreign; 2 is unknown and must not authorize a signal.
|
|
9
|
+
_idb_companion_owned() {
|
|
10
|
+
local repo="$1" udid="$2" pid="$3" identity="$4" current cwd args
|
|
11
|
+
current="$(_idb_companion_identity "$pid")"
|
|
12
|
+
[ -n "$current" ] && [ "$current" = "$identity" ] || return 2
|
|
13
|
+
case "$current" in *'/idb_companion'|*' idb_companion') ;; *) return 1 ;; esac
|
|
14
|
+
cwd="$(lsof -a -p "$pid" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p')"
|
|
15
|
+
[ -n "$cwd" ] || return 2
|
|
16
|
+
case "$cwd" in "$repo"|"$repo/"*) ;; *) return 1 ;; esac
|
|
17
|
+
[ -n "$udid" ] || return 2
|
|
18
|
+
args="$(ps -p "$pid" -o args= 2>/dev/null)" || return 2
|
|
19
|
+
case " $args " in *" --udid $udid "*|*" --udid=$udid "*) ;; *) return 1 ;; esac
|
|
20
|
+
[ "$(_idb_companion_identity "$pid")" = "$identity" ] || return 2
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
stop_checkout_idb_companions() {
|
|
24
|
+
local repo="$1" udid="${2:-}" pids pid identity status signal current attempt stopped
|
|
25
|
+
if pids="$(pgrep -u "$(id -u)" -x idb_companion 2>/dev/null)"; then :
|
|
26
|
+
else
|
|
27
|
+
status=$?
|
|
28
|
+
[ "$status" -eq 1 ] && return 0
|
|
29
|
+
printf 'Could not inspect idb companions. Next: mm-harness status --target "%s"\n' "$repo" >&2
|
|
30
|
+
return 1
|
|
31
|
+
fi
|
|
32
|
+
for pid in $pids; do
|
|
33
|
+
case "$pid" in ''|*[!0-9]*) return 1 ;; esac
|
|
34
|
+
[ "$pid" -gt 0 ] || return 1
|
|
35
|
+
identity="$(_idb_companion_identity "$pid")"
|
|
36
|
+
if [ -z "$identity" ] && ! kill -0 "$pid" 2>/dev/null; then continue; fi
|
|
37
|
+
if _idb_companion_owned "$repo" "$udid" "$pid" "$identity"; then :
|
|
38
|
+
else
|
|
39
|
+
status=$?
|
|
40
|
+
[ "$status" -eq 1 ] && continue
|
|
41
|
+
printf 'Companion ownership is unknown. Next: mm-harness status --target "%s"\n' "$repo" >&2
|
|
42
|
+
return 1
|
|
43
|
+
fi
|
|
44
|
+
stopped=false
|
|
45
|
+
for signal in TERM KILL; do
|
|
46
|
+
if ! _idb_companion_owned "$repo" "$udid" "$pid" "$identity"; then
|
|
47
|
+
printf 'Companion ownership changed. Next: mm-harness status --target "%s"\n' "$repo" >&2
|
|
48
|
+
return 1
|
|
49
|
+
fi
|
|
50
|
+
kill -"$signal" "$pid" 2>/dev/null || true
|
|
51
|
+
for attempt in $(seq 1 20); do
|
|
52
|
+
current="$(_idb_companion_identity "$pid")"
|
|
53
|
+
if [ -z "$current" ] && ! kill -0 "$pid" 2>/dev/null; then stopped=true; break; fi
|
|
54
|
+
if [ "$current" != "$identity" ]; then
|
|
55
|
+
printf 'Companion identity changed during stop. Next: mm-harness status --target "%s"\n' "$repo" >&2
|
|
56
|
+
return 1
|
|
57
|
+
fi
|
|
58
|
+
sleep 0.1
|
|
59
|
+
done
|
|
60
|
+
[ "$stopped" = true ] && break
|
|
61
|
+
done
|
|
62
|
+
if [ "$stopped" != true ]; then
|
|
63
|
+
printf 'Companion %s did not stop. Next: mm-harness status --target "%s"\n' "$pid" "$repo" >&2
|
|
64
|
+
return 1
|
|
65
|
+
fi
|
|
66
|
+
printf 'Stopped checkout idb companion %s\n' "$pid" >&2
|
|
67
|
+
done
|
|
68
|
+
}
|
|
@@ -32,11 +32,12 @@ if ! command -v recipe_runtime_dir >/dev/null 2>&1; then
|
|
|
32
32
|
exit 1
|
|
33
33
|
fi
|
|
34
34
|
|
|
35
|
+
. "$MOBILE_STOP_DIR/../shared/resolve-slot-ports.sh"
|
|
36
|
+
|
|
35
37
|
# No explicit port: resolve the checkout's own (slot context first, then the
|
|
36
38
|
# pool/formula fallbacks) so we stop THIS slot's Metro, not the 8081 default.
|
|
37
39
|
if [ -z "$PORT" ]; then
|
|
38
40
|
# shellcheck disable=SC1091
|
|
39
|
-
. "$MOBILE_STOP_DIR/../shared/resolve-slot-ports.sh"
|
|
40
41
|
resolved_port="$(resolve_mobile_runtime_ports "$TARGET" 2>/dev/null | sed -n 's/^WATCHER_PORT=//p' | head -1 || true)"
|
|
41
42
|
PORT="${resolved_port:-8081}"
|
|
42
43
|
fi
|
|
@@ -56,6 +57,15 @@ else
|
|
|
56
57
|
printf 'Metro not running on port %s — nothing to stop\n' "$PORT" >&2
|
|
57
58
|
fi
|
|
58
59
|
|
|
60
|
+
# Companion cleanup retains the selected device and checkout boundary.
|
|
61
|
+
. "$MOBILE_STOP_DIR/lib/idb-companion.sh"
|
|
62
|
+
companion_udid="${SIM_UDID:-}"
|
|
63
|
+
if [ -z "$companion_udid" ]; then
|
|
64
|
+
mobile_identity="$(resolve_mobile_runtime_ports "$TARGET" 2>/dev/null || true)"
|
|
65
|
+
companion_udid="$(printf '%s\n' "$mobile_identity" | sed -n 's/^SIM_UDID=//p' | head -1)"
|
|
66
|
+
fi
|
|
67
|
+
stop_checkout_idb_companions "$TARGET" "$companion_udid" || exit 1
|
|
68
|
+
|
|
59
69
|
# The stop decision is made; everything below is best-effort cleanup (pid file,
|
|
60
70
|
# leaked-bundler sweep, tmux window). None of it may fail the command — the
|
|
61
71
|
# idempotent-stop contract is already satisfied. Drop set -e for the tail so an
|
package/dist/commands/help.js
CHANGED
|
@@ -49,6 +49,17 @@ function recipeHelpPayload(topic, harnessVersion, adapter, target) {
|
|
|
49
49
|
safety: topic.safety
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
+
function recipeHelpSectionLines(topic, adapter, sectionId) {
|
|
53
|
+
const paint = (style, text) => color(style, text, { stream: process.stdout });
|
|
54
|
+
const lines = [];
|
|
55
|
+
for (const [index, section] of scopedSections(topic, adapter).entries()) {
|
|
56
|
+
if (sectionId && section.id !== sectionId) continue;
|
|
57
|
+
lines.push("", paint("label", `${index + 1}. ${section.title}`), ` ${section.instruction}`);
|
|
58
|
+
for (const detail of section.details) lines.push(` - ${detail}`);
|
|
59
|
+
for (const command of section.commands) lines.push(` $ ${paint("cmd", command)}`);
|
|
60
|
+
}
|
|
61
|
+
return lines;
|
|
62
|
+
}
|
|
52
63
|
function renderRecipeHelp(topic, harnessVersion, adapter) {
|
|
53
64
|
const paint = (style, text) => color(style, text, { stream: process.stdout });
|
|
54
65
|
const lines = [
|
|
@@ -60,11 +71,7 @@ function renderRecipeHelp(topic, harnessVersion, adapter) {
|
|
|
60
71
|
`Visual tutorial: ${paint("cmd", "mm-harness tutorial")}`
|
|
61
72
|
];
|
|
62
73
|
if (adapter === "unscoped") lines.push(paint("warn", `No MetaMask checkout detected. Next: ${unscopedNext()}.`));
|
|
63
|
-
|
|
64
|
-
lines.push("", paint("label", `${index + 1}. ${section.title}`), ` ${section.instruction}`);
|
|
65
|
-
for (const detail of section.details) lines.push(` - ${detail}`);
|
|
66
|
-
for (const command of section.commands) lines.push(` $ ${paint("cmd", command)}`);
|
|
67
|
-
}
|
|
74
|
+
lines.push(...recipeHelpSectionLines(topic, adapter));
|
|
68
75
|
lines.push("", `${paint("warn", "Safety:")} ${topic.safety}`);
|
|
69
76
|
return `${lines.join("\n")}
|
|
70
77
|
`;
|
|
@@ -88,5 +95,6 @@ export {
|
|
|
88
95
|
handleHelp,
|
|
89
96
|
loadRecipeHelp,
|
|
90
97
|
recipeHelpPayload,
|
|
98
|
+
recipeHelpSectionLines,
|
|
91
99
|
renderRecipeHelp
|
|
92
100
|
};
|
package/dist/provider.js
CHANGED
|
@@ -16,6 +16,8 @@ import { abortRunMainnetOrders, cancelRunMainnetOrders } from "./adapters/perps-
|
|
|
16
16
|
import { adapterRegistry } from "./adapters/registry.js";
|
|
17
17
|
import { getAdapterSurface } from "./adapters/surface.js";
|
|
18
18
|
import { applyDeviceTargeting } from "./commands/device-target.js";
|
|
19
|
+
import { loadRecipeHelp, recipeHelpSectionLines } from "./commands/help.js";
|
|
20
|
+
import { runnerDir } from "./paths.js";
|
|
19
21
|
import { metaMaskEngine } from "./engine.js";
|
|
20
22
|
import { providerHost } from "./host.js";
|
|
21
23
|
import { configureProviderReadiness, doctorOptions } from "./provider-doctor.js";
|
|
@@ -70,7 +72,19 @@ async function createProvider(context) {
|
|
|
70
72
|
return {
|
|
71
73
|
runtime,
|
|
72
74
|
engine: metaMaskEngine,
|
|
73
|
-
commandOptions: {
|
|
75
|
+
commandOptions: {
|
|
76
|
+
...helperCommandOptions,
|
|
77
|
+
recipeQuality: {
|
|
78
|
+
...helperCommandOptions.recipeQuality,
|
|
79
|
+
get guidance() {
|
|
80
|
+
return recipeHelpSectionLines(loadRecipeHelp(runnerDir), adapter, "quality").join("\n");
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
status: statusOptions,
|
|
84
|
+
stop: stopOptions,
|
|
85
|
+
doctor: doctorOptions,
|
|
86
|
+
logs: createLogsOptions(runtime)
|
|
87
|
+
},
|
|
74
88
|
...executes ? {
|
|
75
89
|
async cancel() {
|
|
76
90
|
await abortRunMainnetOrders(context.target.value);
|
package/package.json
CHANGED
|
@@ -216,7 +216,7 @@
|
|
|
216
216
|
"extension"
|
|
217
217
|
]
|
|
218
218
|
},
|
|
219
|
-
"Verdict: pass when every named claim ran an executable path with an assertion and consistent evidence; warn when the supported claims pass but non-blocking gaps remain; fail when a named claim has no executable path or assertion, the graph can pass unconditionally, required evidence is missing or contradictory, or the relevant path did not run. A visual claim cannot pass without a settled capture. Write only the compact {verdict, reasons} to artifacts/recipe-quality-input.json and build the artifact with
|
|
219
|
+
"Verdict: pass when every named claim ran an executable path with an assertion and consistent evidence; warn when the supported claims pass but non-blocking gaps remain; fail when a named claim has no executable path or assertion, the graph can pass unconditionally, required evidence is missing or contradictory, or the relevant path did not run. A visual claim cannot pass without a settled capture. Write only the compact {verdict, reasons} to artifacts/recipe-quality-input.json and build the artifact with farmslot recipe quality build; never hand-author it.",
|
|
220
220
|
"Independent critique, when one is requested: the verdict with one evidence-backed sentence, uncovered or weak proof targets, graph, composition, adapter and reuse findings, evidence mismatches and flake risks, and the three highest-value concrete edits.",
|
|
221
221
|
{
|
|
222
222
|
"text": "State the simulator or device, build type and app state. Unlock through a fixture or a documented primitive; keep account, balance, network, permissions and feature flags deterministic; use existing page objects, test ids and fixtures; capture only after ui.wait_for, a route assertion or a state assertion; teardown must not leak balances, pending transactions, selected network, permissions or onboarding state into the next run.",
|
|
@@ -239,9 +239,9 @@
|
|
|
239
239
|
"Use fixtures that make the intended and incorrect outcomes differ. For changing geometry or values, declare the observation window and compare the same entity and inputs; do not select only favorable samples. Promote trace, screenshots, video and provenance as one immutable package, and inspect replacement image bytes again."
|
|
240
240
|
],
|
|
241
241
|
"commands": [
|
|
242
|
-
"
|
|
243
|
-
"
|
|
244
|
-
"
|
|
242
|
+
"farmslot recipe run ./proof.recipe.json --artifacts-dir temp/recipe-proof --json",
|
|
243
|
+
"farmslot recipe status --json",
|
|
244
|
+
"farmslot recipe quality build --input recipe-quality-input.json --output recipe-quality.json --json"
|
|
245
245
|
]
|
|
246
246
|
},
|
|
247
247
|
{
|