@deeeed/metamask-harness 0.17.1 → 0.17.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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.17.2 - 2026-07-15
6
+
7
+ ### Fixed
8
+
9
+ - Passive update discovery now runs in a detached, once-daily registry probe, so fast commands populate the cache without adding latency or contaminating machine output.
10
+
11
+ ## 0.17.1 - 2026-07-15
12
+
5
13
  ### Fixed
6
14
 
7
15
  - Extension `debug` now uses Chrome's native DevTools command for the active slot target and opens directly on Console; `debug --worker` targets the service worker without creating a frontend browser tab.
@@ -20,8 +28,6 @@
20
28
  - Removed compatibility-only runtime-start fields, hidden `live` execution, removed-command handlers, undomained recipe aliases, flat/non-ESM action lookup, old port-resolver filenames, duplicate Extension launcher naming, obsolete fixture search locations, and the alternate Mobile product-source bridge. Mobile install now requires the current product-owned bridge and writes metadata only.
21
29
  - Removed the historical CLI migration/spec documents; current behavior is documented in the README, cheatsheet, architecture, and human QA checklist.
22
30
 
23
- ## 0.17.1 - 2026-07-14
24
-
25
31
  ### Fixed
26
32
 
27
33
  - Human recipe results now print an absolute-path artifact inventory and expand run-scoped application diagnostics inline; single-action calls show the same `CLEAN`/`REVIEW` diagnostics instead of requiring another query.
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ const [cacheFile, timeoutText, endpointOverride] = process.argv.slice(2);
6
+ const timeoutMs = Number.parseInt(timeoutText ?? '', 10);
7
+ const endpoint = endpointOverride
8
+ ?? 'https://registry.npmjs.org/-/package/%40deeeed%2Fmetamask-harness/dist-tags';
9
+
10
+ async function main() {
11
+ if (!cacheFile || !Number.isInteger(timeoutMs) || timeoutMs < 1) return;
12
+ const controller = new AbortController();
13
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
14
+ try {
15
+ const response = await fetch(endpoint, { signal: controller.signal });
16
+ if (!response.ok) return;
17
+ const data = await response.json();
18
+ if (!data || typeof data.latest !== 'string' || data.latest.length === 0) return;
19
+ let lastCheck = Date.now();
20
+ try {
21
+ const cached = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
22
+ if (typeof cached.lastCheck === 'number') lastCheck = cached.lastCheck;
23
+ } catch {
24
+ // The parent may have exited before creating the cache; recreate it below.
25
+ }
26
+ fs.mkdirSync(path.dirname(cacheFile), { recursive: true });
27
+ const temporary = `${cacheFile}.${process.pid}.tmp`;
28
+ fs.writeFileSync(temporary, JSON.stringify({ lastCheck, latest: data.latest }));
29
+ fs.renameSync(temporary, cacheFile);
30
+ } catch {
31
+ // Passive checks are intentionally silent; the explicit update command teaches failures.
32
+ } finally {
33
+ clearTimeout(timer);
34
+ }
35
+ }
36
+
37
+ await main();
@@ -1,4 +1,4 @@
1
- import { spawnSync } from "node:child_process";
1
+ import { spawn, spawnSync } from "node:child_process";
2
2
  import fs from "node:fs";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
@@ -6,7 +6,7 @@ import { runnerDir } from "../paths.js";
6
6
  import { EXIT, flag, parseFlags } from "./shared.js";
7
7
  const PACKAGE_NAME = "@deeeed/metamask-harness";
8
8
  const NUDGE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
9
- const NUDGE_FETCH_TIMEOUT_MS = 300;
9
+ const NUDGE_FETCH_TIMEOUT_MS = 2e3;
10
10
  function currentVersion() {
11
11
  try {
12
12
  const pkg = JSON.parse(fs.readFileSync(path.join(runnerDir, "package.json"), "utf8"));
@@ -56,24 +56,6 @@ function fetchLatest(timeoutMs) {
56
56
  if (!latest) return { error: { kind: "unreachable", message: "npm returned no dist-tag for latest" } };
57
57
  return { latest };
58
58
  }
59
- async function fetchLatestAsync(timeoutMs) {
60
- const controller = new AbortController();
61
- const timer = setTimeout(() => controller.abort(), timeoutMs);
62
- try {
63
- const url = `https://registry.npmjs.org/-/package/${encodeURIComponent(PACKAGE_NAME)}/dist-tags`;
64
- const res = await fetch(url, { signal: controller.signal });
65
- if (!res.ok) return { error: { kind: "unreachable", message: `registry returned HTTP ${res.status}` } };
66
- const data = await res.json();
67
- const latest = data["latest"];
68
- if (!latest) return { error: { kind: "unreachable", message: "npm registry returned no latest dist-tag" } };
69
- return { latest };
70
- } catch (err) {
71
- const msg = err.name === "AbortError" ? `registry fetch timed out after ${timeoutMs}ms` : err.message;
72
- return { error: { kind: "unreachable", message: msg } };
73
- } finally {
74
- clearTimeout(timer);
75
- }
76
- }
77
59
  function teachFailure(json, current, code, message, userAction) {
78
60
  if (json) {
79
61
  console.log(
@@ -211,23 +193,28 @@ function nudgeDisabled() {
211
193
  function nudgeLine(current, latest) {
212
194
  return isNewer(latest, current) ? `mm-harness ${current} \u2192 ${latest} available \xB7 run: mm-harness update` : null;
213
195
  }
214
- async function maybeNudge(now = Date.now()) {
196
+ function maybeNudge(now = Date.now()) {
215
197
  if (nudgeDisabled()) return;
216
198
  const file = cacheFile();
217
199
  const cache = readCache(file);
218
200
  const current = currentVersion();
219
- let latest = cache?.latest ?? "";
220
201
  process.once("exit", () => {
221
- const line = nudgeLine(current, latest);
202
+ const line = nudgeLine(current, cache?.latest ?? "");
222
203
  if (line) process.stderr.write(`${line}
223
204
  `);
224
205
  });
225
206
  if (!cache || now - cache.lastCheck >= NUDGE_INTERVAL_MS) {
226
- writeCache(file, { lastCheck: now, latest });
227
- const fetched = await fetchLatestAsync(NUDGE_FETCH_TIMEOUT_MS);
228
- if (fetched.latest) {
229
- latest = fetched.latest;
230
- writeCache(file, { lastCheck: now, latest });
207
+ writeCache(file, { lastCheck: now, latest: cache?.latest ?? "" });
208
+ const worker = path.join(runnerDir, "adapters", "shared", "update-check-worker.mjs");
209
+ if (!fs.existsSync(worker)) return;
210
+ try {
211
+ const child = spawn(
212
+ process.execPath,
213
+ [worker, file, String(NUDGE_FETCH_TIMEOUT_MS)],
214
+ { detached: true, stdio: "ignore" }
215
+ );
216
+ child.unref();
217
+ } catch {
231
218
  }
232
219
  }
233
220
  }
@@ -696,7 +696,7 @@ program.command("completions").description("Install/print bundled shell tab-comp
696
696
  });
697
697
  const NUDGE_SKIP = ["update", "completions", "completion-candidates"];
698
698
  if (rawArgv.length > 0 && !NUDGE_SKIP.includes(rawArgv[0])) {
699
- setImmediate(() => void maybeNudge());
699
+ maybeNudge();
700
700
  }
701
701
  function hasPassthroughHelp(argv) {
702
702
  const divider = argv.indexOf("--");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeeed/metamask-harness",
3
- "version": "0.17.1",
3
+ "version": "0.17.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mm-harness": "bin/mm-harness"