@deeeed/metamask-harness 0.34.1 → 0.34.2

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/dist/runner.js CHANGED
@@ -1,4 +1,4 @@
1
- import { execSync } from "node:child_process";
1
+ import { execFileSync, execSync } from "node:child_process";
2
2
  import { OFFICIAL_RECIPE_ACTIONS } from "@farmslot/protocol";
3
3
  import { createMetaMaskAdapters, createMetaMaskUiTransport } from "./adapters.js";
4
4
  import { bridgeCommand } from "../library/actions/mobile/platform/bridge.mjs";
@@ -239,6 +239,8 @@ function isAutomaticHudProgress(action, node, nodeId) {
239
239
  function mobileSourceAwareLifecycleAdapters(adapter, lifecycle, readinessProbe = probeMobileLifecycleRuntime, sourceFreshness = {
240
240
  fingerprint: mobileSourceFingerprint,
241
241
  record: recordMobileSourceBaseline
242
+ }, processIdentity = {
243
+ readIosPid: readIosAppPid
242
244
  }) {
243
245
  if (adapter !== "mobile") return lifecycle;
244
246
  return lifecycle.map((entry) => ({
@@ -246,6 +248,8 @@ function mobileSourceAwareLifecycleAdapters(adapter, lifecycle, readinessProbe =
246
248
  async execute(node, context) {
247
249
  const command = node.command ?? node.event ?? node.state;
248
250
  const reloadsSource = command === "launch" || command === "foreground" || command === "restart";
251
+ const checksIosContinuity = command === "foreground" && !isAndroidLifecycle(node, context.env ?? {});
252
+ const processBefore = checksIosContinuity ? processIdentity.readIosPid(node, context) : void 0;
249
253
  const fingerprint = reloadsSource ? sourceFreshness.fingerprint(context.projectRoot) : void 0;
250
254
  const androidRestart = command === "restart" && isAndroidLifecycle(node, context.env ?? {});
251
255
  const initialNode = androidRestart ? { ...node, settle_ms: 0 } : node;
@@ -261,6 +265,25 @@ function mobileSourceAwareLifecycleAdapters(adapter, lifecycle, readinessProbe =
261
265
  if (reloadsSource) {
262
266
  await readinessProbe(node, context);
263
267
  }
268
+ if (checksIosContinuity) {
269
+ const processAfter = processIdentity.readIosPid(node, context);
270
+ const actualTransition = processBefore !== null && processBefore === processAfter ? "foreground_resume" : processAfter !== null ? "cold_relaunch" : "unknown";
271
+ const resultRecord = asRecord(result);
272
+ result = {
273
+ ...resultRecord,
274
+ output: {
275
+ ...asRecord(resultRecord.output),
276
+ actualTransition,
277
+ processBefore,
278
+ processAfter
279
+ }
280
+ };
281
+ if (node.require_process_continuity === true && actualTransition !== "foreground_resume") {
282
+ throw new Error(
283
+ `iOS foreground did not preserve the app process (actualTransition=${actualTransition}, before=${String(processBefore)}, after=${String(processAfter)}); this lifecycle sample is a cold relaunch, not a reconnect.`
284
+ );
285
+ }
286
+ }
264
287
  if (fingerprint !== void 0 && !sourceFreshness.record(context.projectRoot, fingerprint)) {
265
288
  throw new Error(
266
289
  "Mobile source changed while the app was reloading; the loaded-source baseline was not recorded. Next: retry app.lifecycle restart."
@@ -270,6 +293,26 @@ function mobileSourceAwareLifecycleAdapters(adapter, lifecycle, readinessProbe =
270
293
  }
271
294
  }));
272
295
  }
296
+ function readIosAppPid(node, context) {
297
+ const env = context.env ?? {};
298
+ const device = node.simulator ?? node.ios_simulator ?? env.SIM_UDID ?? env.IOS_SIMULATOR ?? process.env.SIM_UDID ?? process.env.IOS_SIMULATOR;
299
+ const bundleId = node.bundle_id ?? node.bundleId ?? env.IOS_BUNDLE_ID ?? process.env.IOS_BUNDLE_ID ?? "io.metamask.MetaMask";
300
+ if (typeof device !== "string" || typeof bundleId !== "string") return null;
301
+ try {
302
+ const output = execFileSync(
303
+ "xcrun",
304
+ ["simctl", "spawn", device, "launchctl", "list"],
305
+ { encoding: "utf8", timeout: 5e3 }
306
+ );
307
+ const labelPrefix = `UIKitApplication:${bundleId}[`;
308
+ const line = output.split("\n").find((candidate) => candidate.includes(labelPrefix));
309
+ if (!line) return null;
310
+ const pid = Number.parseInt(line.trim().split(/\s+/u)[0] ?? "", 10);
311
+ return Number.isInteger(pid) && pid > 0 ? pid : null;
312
+ } catch {
313
+ return null;
314
+ }
315
+ }
273
316
  function isAndroidLifecycle(node, env) {
274
317
  const platform = node.platform ?? env.PLATFORM ?? process.env.PLATFORM;
275
318
  if (platform === "android") return true;
@@ -299,10 +342,9 @@ function mergeAndroidRestartResults(initialResult, foregroundResult) {
299
342
  }
300
343
  async function probeMobileLifecycleRuntime(node, context) {
301
344
  const command = node.command ?? node.event ?? node.state;
302
- const defaultTimeoutMs = command === "restart" || command === "launch" ? 6e4 : 3e4;
303
- const timeoutMs = lifecycleReadinessTimeout(
304
- node.runtime_ready_timeout_ms,
305
- defaultTimeoutMs
345
+ const timeoutMs = resolveMobileLifecycleReadinessTimeout(
346
+ command,
347
+ node.runtime_ready_timeout_ms
306
348
  );
307
349
  const deadline = Date.now() + timeoutMs;
308
350
  let lastError;
@@ -328,8 +370,10 @@ async function probeMobileLifecycleRuntime(node, context) {
328
370
  `Mobile lifecycle ${String(command)} did not expose a usable pinned __AGENTIC__ runtime within ${timeoutMs}ms: ${lastError instanceof Error ? lastError.message : String(lastError)}`
329
371
  );
330
372
  }
331
- function lifecycleReadinessTimeout(value, fallback) {
332
- if (value === void 0) return fallback;
373
+ function resolveMobileLifecycleReadinessTimeout(command, value) {
374
+ if (value === void 0) {
375
+ return command === "launch" || command === "restart" || command === "foreground" ? 6e4 : 3e4;
376
+ }
333
377
  const timeout = Number(value);
334
378
  if (!Number.isInteger(timeout) || timeout < 1e3 || timeout > 12e4) {
335
379
  throw new Error(
@@ -364,5 +408,6 @@ export {
364
408
  createMetaMaskMobileRunner,
365
409
  createMetaMaskRunner,
366
410
  isAutomaticHudProgress,
367
- mobileSourceAwareLifecycleAdapters
411
+ mobileSourceAwareLifecycleAdapters,
412
+ resolveMobileLifecycleReadinessTimeout
368
413
  };
@@ -244,6 +244,7 @@ function persistExplicitDevicePin(target, device) {
244
244
  return;
245
245
  }
246
246
  const next = { ...existing };
247
+ next.platform = device.platform;
247
248
  if (device.platform === "ios") {
248
249
  const simulatorName = device.name ? device.name.replace(/_/gu, " ").trim() : device.id;
249
250
  next.simulator = simulatorName;
@@ -0,0 +1,4 @@
1
+ import { runAdapter } from '../platform/bridge.mjs';
2
+ import { measureHomepageVisible } from './perps.mjs';
3
+
4
+ runAdapter(measureHomepageVisible);