@deeeed/metamask-harness 0.79.0 → 0.81.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.
Files changed (252) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +1 -1
  3. package/adapters/extension/ensure-browser.sh +2 -2
  4. package/adapters/extension/inject.mjs +0 -1
  5. package/adapters/extension/launch-browser.cjs +39 -613
  6. package/adapters/extension/readiness.mjs +2 -5
  7. package/adapters/extension/reattach.sh +2 -2
  8. package/adapters/extension/stamp-runtime-title.cjs +1 -1
  9. package/adapters/manifest.json +16 -64
  10. package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +57 -1358
  11. package/adapters/mobile/bridge-runtime/teaching.cjs +20 -0
  12. package/adapters/mobile/inject.sh +16 -0
  13. package/adapters/mobile/launch-console-forwarder.cjs +1 -2
  14. package/adapters/mobile/open-device.sh +2 -2
  15. package/adapters/mobile/reload-app.mjs +4 -4
  16. package/adapters/mobile/reset-app-data.sh +1 -1
  17. package/adapters/mobile/start-console-forwarder.sh +3 -2
  18. package/adapters/mobile/start-metro.sh +17 -12
  19. package/adapters/mobile/wait-for-bridge.cjs +2 -2
  20. package/adapters/shared/harness-source-fingerprint.mjs +13 -8
  21. package/adapters/shared/open-debug.mjs +2 -2
  22. package/adapters/shared/sync-wallet-fixture.sh +8 -5
  23. package/adapters/terminal/cleanup.mjs +2 -1
  24. package/adapters/terminal/inject.mjs +2 -1
  25. package/adapters/terminal/launch.mjs +17 -13
  26. package/adapters/terminal/lib/mainnet-guard.mjs +9 -0
  27. package/adapters/terminal/lib/readiness.mjs +20 -12
  28. package/adapters/terminal/policy.mjs +35 -0
  29. package/adapters/terminal/verify.mjs +10 -3
  30. package/adapters/terminal/wallet-host.mjs +43 -225
  31. package/bin/mm-harness +9 -28
  32. package/dist/adapters/checkout-files.js +16 -0
  33. package/dist/adapters/console-capture.js +14 -1
  34. package/dist/adapters/core/actions.js +8 -4
  35. package/dist/adapters/core/overlay.js +1 -1
  36. package/dist/adapters/core/readiness.js +28 -1
  37. package/dist/adapters/core/run.js +2 -2
  38. package/dist/adapters/core/surface.js +16 -1
  39. package/dist/adapters/extension/actions.js +6 -2
  40. package/dist/adapters/extension/browser-pid.js +56 -0
  41. package/dist/adapters/extension/console-capture.js +1 -1
  42. package/dist/adapters/extension/doctor-checks.js +1 -1
  43. package/dist/adapters/extension/ensure-ready.js +5 -4
  44. package/dist/adapters/extension/extension-id.js +1 -1
  45. package/dist/adapters/extension/feature-flags.js +1 -1
  46. package/dist/adapters/extension/fixtures.js +1 -2
  47. package/dist/adapters/extension/launch.js +4 -5
  48. package/dist/adapters/extension/launched-browser.js +1 -2
  49. package/dist/adapters/extension/network-observer.js +14 -1
  50. package/dist/adapters/extension/overlay.js +1 -1
  51. package/dist/adapters/extension/product-config.js +1 -1
  52. package/dist/adapters/extension/readiness.js +1 -1
  53. package/dist/adapters/extension/reload.js +1 -1
  54. package/dist/adapters/extension/run.js +135 -14
  55. package/dist/adapters/extension/runtime-decision.js +2 -1
  56. package/dist/adapters/extension/runtime.js +9 -5
  57. package/dist/adapters/extension/surface.js +15 -2
  58. package/dist/adapters/extension/verify.js +2 -2
  59. package/dist/adapters/harness-freshness.js +2 -1
  60. package/dist/adapters/mobile/actions.js +4 -1
  61. package/dist/adapters/mobile/android-gfxinfo-performance.js +1 -3
  62. package/dist/adapters/mobile/app-identity.js +10 -0
  63. package/dist/adapters/mobile/doctor-checks.js +1 -1
  64. package/dist/adapters/mobile/fixtures.js +1 -1
  65. package/dist/adapters/mobile/launch.js +27 -28
  66. package/dist/adapters/mobile/lifecycle.js +1 -1
  67. package/dist/adapters/mobile/metro-env.js +9 -59
  68. package/dist/adapters/mobile/network-observer.js +68 -0
  69. package/dist/adapters/mobile/performance-observer.js +2 -4
  70. package/dist/adapters/mobile/prepare-target.js +1 -1
  71. package/dist/adapters/mobile/prepare.js +3 -4
  72. package/dist/adapters/mobile/provision.js +1 -1
  73. package/dist/adapters/mobile/readiness.js +1 -1
  74. package/dist/adapters/mobile/recording-target.js +15 -0
  75. package/dist/adapters/mobile/release-artifact-state.js +1 -1
  76. package/dist/adapters/mobile/reload.js +1 -1
  77. package/dist/adapters/mobile/run.js +39 -15
  78. package/dist/adapters/mobile/runtime-decision.js +2 -4
  79. package/dist/adapters/mobile/source-freshness.js +22 -126
  80. package/dist/adapters/mobile/surface.js +26 -3
  81. package/dist/adapters/mobile/ui.js +16 -5
  82. package/dist/adapters/mobile/verify.js +2 -3
  83. package/dist/adapters/performance/cdp-trace.js +1 -1
  84. package/dist/adapters/performance/device-platform.js +1 -1
  85. package/dist/adapters/perps-order-inputs.js +36 -0
  86. package/dist/adapters/proof-failure.js +11 -0
  87. package/dist/adapters/slot-ports.js +1 -1
  88. package/dist/adapters/surface.js +1 -0
  89. package/dist/adapters/terminal/actions.js +4 -1
  90. package/dist/adapters/terminal/console-capture.js +1 -1
  91. package/dist/adapters/terminal/doctor-checks.js +2 -0
  92. package/dist/adapters/terminal/launch.js +4 -1
  93. package/dist/adapters/terminal/overlay.js +8 -1
  94. package/dist/adapters/terminal/run.js +33 -5
  95. package/dist/adapters/terminal/surface.js +9 -1
  96. package/dist/adapters.js +27 -7
  97. package/dist/advisor-policy.js +1 -1
  98. package/dist/checkout-view.js +1 -2
  99. package/dist/cli.js +59 -21
  100. package/dist/command-contract.js +1 -26
  101. package/dist/commands/check.js +33 -10
  102. package/dist/commands/checklist.js +1 -1
  103. package/dist/commands/completion-candidates.js +6 -14
  104. package/dist/commands/config.js +2 -2
  105. package/dist/commands/core-readiness.js +12 -7
  106. package/dist/commands/debug.js +3 -3
  107. package/dist/commands/device-target.js +5 -5
  108. package/dist/commands/doctor.js +2 -14
  109. package/dist/commands/domain.js +2 -2
  110. package/dist/commands/ensure-ready.js +1 -7
  111. package/dist/commands/fixtures.js +5 -6
  112. package/dist/commands/help.js +3 -4
  113. package/dist/commands/launch/device.js +10 -17
  114. package/dist/commands/launch/extension.js +2 -8
  115. package/dist/commands/launch/mobile.js +1 -1
  116. package/dist/commands/logs.js +3 -3
  117. package/dist/commands/mobile-device-view.js +4 -2
  118. package/dist/commands/overlay.js +110 -0
  119. package/dist/commands/pin.js +1 -1
  120. package/dist/commands/pr-body.js +2 -2
  121. package/dist/commands/prepare.js +4 -9
  122. package/dist/commands/provision.js +3 -12
  123. package/dist/commands/recipe-advice.js +1 -2
  124. package/dist/commands/recipe-quality.js +2 -3
  125. package/dist/commands/resolve-extension.js +1 -7
  126. package/dist/commands/review.js +4 -4
  127. package/dist/commands/runtime-decision.js +1 -6
  128. package/dist/commands/runtime-health.js +1 -7
  129. package/dist/commands/runtime-launch.js +1 -13
  130. package/dist/commands/self-test.js +5 -8
  131. package/dist/commands/status-watch.js +1 -2
  132. package/dist/commands/status.js +2 -5
  133. package/dist/commands/task-init.js +2 -3
  134. package/dist/commands/tutorial.js +2 -2
  135. package/dist/commands/update.js +1 -1
  136. package/dist/completions-cache.js +1 -1
  137. package/dist/console-classifier.js +19 -0
  138. package/dist/doctor.js +2 -3
  139. package/dist/engine.js +57 -0
  140. package/dist/funding-execution-context.js +96 -1
  141. package/dist/host.js +32 -0
  142. package/dist/index.js +1 -6
  143. package/dist/live-tsx.js +49 -0
  144. package/dist/mm-harness-cli.js +4 -6
  145. package/dist/paths.js +34 -64
  146. package/dist/performance-observation.js +3 -5
  147. package/dist/progress.js +1 -1
  148. package/dist/recipe-assistance-context.js +6 -9
  149. package/dist/recipe-security.js +2 -59
  150. package/dist/review/knowledge.js +2 -2
  151. package/dist/runner.js +7 -4
  152. package/dist/runtime-context.js +1 -1
  153. package/dist/task-view.js +2 -3
  154. package/docs/CONTRIBUTING.md +5 -3
  155. package/docs/RECIPES.md +31 -3
  156. package/docs/cli-contract.md +2 -2
  157. package/docs/feature-guard.md +90 -0
  158. package/library/README.md +3 -1
  159. package/library/actions/core/perps/_controller.mjs +153 -134
  160. package/library/actions/core/perps/_rewards.mjs +186 -0
  161. package/library/actions/core/perps/close_positions.mjs +1 -1
  162. package/library/actions/core/perps/place_order.mjs +167 -45
  163. package/library/actions/core/perps/quote_fees.mjs +61 -0
  164. package/library/actions/core/wallet/list_accounts.mjs +14 -57
  165. package/library/actions/extension/feature_flags/state.mjs +1 -1
  166. package/library/actions/extension/perps/close_visible_position.mjs +5 -0
  167. package/library/actions/extension/perps/edit_margin.mjs +4 -0
  168. package/library/actions/extension/perps/mutation-receipt.mjs +95 -3
  169. package/library/actions/extension/perps/perps.mjs +320 -3
  170. package/library/actions/extension/perps/place_order.mjs +3 -1
  171. package/library/actions/extension/perps/update_position_tpsl.mjs +4 -0
  172. package/library/actions/extension/platform/cdp.mjs +73 -11
  173. package/library/actions/harness-exports.mjs +1 -6
  174. package/library/actions/mobile/app/network-control.mjs +6 -8
  175. package/library/actions/mobile/perps/perps.mjs +216 -11
  176. package/library/actions/mobile/perps/place_order.mjs +3 -1
  177. package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +1 -1
  178. package/library/actions/mobile/platform/bridge.mjs +8 -8
  179. package/library/actions/mobile/platform/native-session-name.mjs +21 -1
  180. package/library/actions/mobile/platform/native-session.mjs +3 -4
  181. package/library/actions/mobile/platform/observe-ui.mjs +12 -6
  182. package/library/actions/mobile/ui/native-navigation.mjs +4 -3
  183. package/library/actions/mobile/wallet/native-ui.mjs +3 -2
  184. package/library/actions/shared/analytics/_adapter.mjs +1 -1
  185. package/library/actions/shared/console-findings.mjs +1 -1
  186. package/library/actions/shared/perps/order-policy.mjs +177 -0
  187. package/library/actions/shared/wallet/fixture-accounts.mjs +84 -0
  188. package/library/actions/terminal/app/launch.mjs +3 -2
  189. package/library/actions/terminal/platform/hud.mjs +2 -1
  190. package/library/actions/terminal/platform/page.mjs +2 -1
  191. package/library/actions/terminal/platform/runtime.mjs +2 -1
  192. package/library/actions/terminal/wallet/_signature-log.mjs +40 -161
  193. package/library/actions/terminal/wallet/assert_signatures.mjs +6 -12
  194. package/library/actions/terminal/wallet/read_signatures.mjs +10 -9
  195. package/library/manifests/core.action-manifest.json +87 -13
  196. package/library/manifests/extension.action-manifest.json +4 -0
  197. package/library/manifests/mobile.action-manifest.json +12 -0
  198. package/package.json +8 -9
  199. package/site/assets/help-recipes.json +1 -0
  200. package/adapters/extension/lib/slot-title.cjs +0 -292
  201. package/adapters/mobile/bridge-runtime/console-forwarder.cjs +0 -472
  202. package/adapters/mobile/bridge-runtime/lib/bridge-errors.cjs +0 -125
  203. package/adapters/mobile/bridge-runtime/lib/cdp-broker.cjs +0 -1055
  204. package/adapters/mobile/bridge-runtime/lib/cdp-eval.cjs +0 -110
  205. package/adapters/mobile/bridge-runtime/lib/config.cjs +0 -61
  206. package/adapters/mobile/bridge-runtime/lib/console-format.cjs +0 -53
  207. package/adapters/mobile/bridge-runtime/lib/devtools-proxy.cjs +0 -177
  208. package/adapters/mobile/bridge-runtime/lib/issue-capture.cjs +0 -446
  209. package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +0 -84
  210. package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +0 -403
  211. package/adapters/mobile/bridge-runtime/lib/ws-client.cjs +0 -116
  212. package/adapters/mobile/coalesce-metro-log.cjs +0 -24
  213. package/adapters/mobile/launch-metro.cjs +0 -77
  214. package/adapters/mobile/metro-config.cjs +0 -98
  215. package/adapters/mobile/metro-log-generation.cjs +0 -106
  216. package/adapters/terminal/lib/origin.mjs +0 -30
  217. package/adapters/terminal/lib/page-script.mjs +0 -246
  218. package/adapters/terminal/lib/strict-wallet.mjs +0 -138
  219. package/dist/adapters/mobile/frame-metrics.js +0 -118
  220. package/dist/adapters/mobile/video-recorder.js +0 -289
  221. package/dist/artifact-files.js +0 -92
  222. package/dist/checkout-lock.js +0 -149
  223. package/dist/cli-color.js +0 -98
  224. package/dist/command-journal.js +0 -308
  225. package/dist/commands/call.js +0 -685
  226. package/dist/commands/last.js +0 -60
  227. package/dist/commands/launch/index.js +0 -109
  228. package/dist/commands/list-executables.js +0 -247
  229. package/dist/commands/manifest.js +0 -488
  230. package/dist/commands/parse-args.js +0 -279
  231. package/dist/commands/reload.js +0 -41
  232. package/dist/commands/run-engine.js +0 -1340
  233. package/dist/commands/run-report.js +0 -241
  234. package/dist/commands/run.js +0 -751
  235. package/dist/commands/shared.js +0 -323
  236. package/dist/commands/stop.js +0 -60
  237. package/dist/devices.js +0 -100
  238. package/dist/discovery.js +0 -15
  239. package/dist/execution-provenance.js +0 -332
  240. package/dist/harness.js +0 -451
  241. package/dist/heal-bounds.js +0 -137
  242. package/dist/json-stream.js +0 -60
  243. package/dist/leaf-invoke.js +0 -19
  244. package/dist/library-provenance.js +0 -33
  245. package/dist/live-adapter-contract.js +0 -380
  246. package/dist/metamask-action-validation.js +0 -68
  247. package/dist/network-observation.js +0 -290
  248. package/dist/recording-target.js +0 -120
  249. package/dist/run-diagnostics.js +0 -364
  250. package/dist/run-recording.js +0 -481
  251. package/dist/runtime-proof.js +0 -90
  252. package/library/actions/mobile/platform/tool-paths.mjs +0 -123
@@ -1,241 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { execFileSync } from "node:child_process";
4
- import { getAdapterSurface } from "../adapters/surface.js";
5
- import { isRecord } from "./parse-args.js";
6
- function writeRunReport(result) {
7
- const summaryPath = String(result.summaryPath);
8
- const tracePath = String(result.tracePath);
9
- const artifactManifestPath = String(result.artifactManifestPath);
10
- const artifactsDir = path.dirname(summaryPath);
11
- const summary = JSON.parse(fs.readFileSync(summaryPath, "utf8"));
12
- const trace = JSON.parse(fs.readFileSync(tracePath, "utf8"));
13
- const entries = Array.isArray(trace.entries) ? trace.entries : [];
14
- const lines = renderRunReport(summary, entries);
15
- const reportPath = path.join(artifactsDir, "report.md");
16
- fs.writeFileSync(reportPath, `${lines.join("\n")}
17
- `);
18
- indexRunReportArtifact(artifactManifestPath);
19
- return {
20
- path: reportPath,
21
- preview: lines.filter((line) => line.startsWith("- ")).slice(0, 6).map((line) => line.slice(2))
22
- };
23
- }
24
- function indexProductProvenanceArtifact(artifactManifestPath, target, adapter, browser = null) {
25
- const artifactsDir = path.dirname(artifactManifestPath);
26
- let gitRef = "unknown";
27
- let branch = "unknown";
28
- let dirty = true;
29
- try {
30
- gitRef = execFileSync("git", ["rev-parse", "HEAD"], {
31
- cwd: target,
32
- encoding: "utf8",
33
- stdio: ["ignore", "pipe", "ignore"]
34
- }).trim();
35
- branch = execFileSync("git", ["branch", "--show-current"], {
36
- cwd: target,
37
- encoding: "utf8",
38
- stdio: ["ignore", "pipe", "ignore"]
39
- }).trim() || "detached";
40
- dirty = execFileSync(
41
- "git",
42
- ["status", "--porcelain", "--untracked-files=normal"],
43
- {
44
- cwd: target,
45
- encoding: "utf8",
46
- stdio: ["ignore", "pipe", "ignore"]
47
- }
48
- ).trim().length > 0;
49
- } catch {
50
- }
51
- const provenance = {
52
- schemaVersion: 1,
53
- adapter,
54
- repository: path.basename(path.resolve(target)),
55
- git_ref: gitRef,
56
- branch,
57
- dirty,
58
- ...browser ? { browser } : {}
59
- };
60
- fs.writeFileSync(
61
- path.join(artifactsDir, "product-provenance.json"),
62
- `${JSON.stringify(provenance, null, 2)}
63
- `
64
- );
65
- let manifest;
66
- try {
67
- manifest = JSON.parse(fs.readFileSync(artifactManifestPath, "utf8"));
68
- } catch {
69
- return;
70
- }
71
- if (!isRecord(manifest)) return;
72
- const artifacts = Array.isArray(manifest.artifacts) ? manifest.artifacts : [];
73
- manifest.artifacts = [
74
- ...artifacts.filter(
75
- (artifact) => !isRecord(artifact) || artifact.path !== "product-provenance.json"
76
- ),
77
- {
78
- path: "product-provenance.json",
79
- type: "json",
80
- label: "Product checkout provenance",
81
- category: "system",
82
- metadata: {
83
- adapter,
84
- git_ref: gitRef,
85
- branch,
86
- dirty,
87
- ...browser?.boundTo && browser.boundTo !== "none" ? { browser: browser.browser, browser_version: browser.version, browser_source: browser.source, extension_loading: browser.extensionLoading } : {}
88
- }
89
- }
90
- ];
91
- fs.writeFileSync(
92
- artifactManifestPath,
93
- `${JSON.stringify(manifest, null, 2)}
94
- `
95
- );
96
- }
97
- function resolveTemplatedPort(value, params, recipe) {
98
- let resolved = value;
99
- const template = /^\{\{\s*params\.([\w-]+)\s*\}\}$/u.exec(String(value).trim());
100
- if (template) {
101
- const name = template[1];
102
- const schema = isRecord(recipe) && isRecord(recipe.paramsSchema) && isRecord(recipe.paramsSchema.properties) ? recipe.paramsSchema.properties[name] : void 0;
103
- resolved = isRecord(params) && params[name] !== void 0 ? params[name] : isRecord(schema) ? schema.default : void 0;
104
- }
105
- const text = String(resolved ?? "").trim();
106
- return /^\d+$/u.test(text) ? text : null;
107
- }
108
- function recipeCdpPorts(request) {
109
- const ports = /* @__PURE__ */ new Set();
110
- const envPort = request.env?.CDP_PORT || request.env?.RECIPE_CDP_PORT;
111
- if (envPort) ports.add(String(envPort));
112
- let recipe = request.recipeDocument;
113
- if (recipe === void 0 && request.recipePath) {
114
- try {
115
- recipe = JSON.parse(fs.readFileSync(request.recipePath, "utf8"));
116
- } catch {
117
- recipe = void 0;
118
- }
119
- }
120
- const workflow = isRecord(recipe) && isRecord(recipe.workflow) ? recipe.workflow : null;
121
- const nodes = workflow && isRecord(workflow.nodes) ? Object.values(workflow.nodes) : [];
122
- for (const node of nodes) {
123
- if (!isRecord(node) || node.cdp_port === void 0 || node.cdp_port === null) continue;
124
- const port = resolveTemplatedPort(node.cdp_port, request.params, recipe);
125
- ports.add(port ?? `unresolved ${String(node.cdp_port)}`);
126
- }
127
- return [...ports];
128
- }
129
- function executedBrowser(adapter, target, artifactManifestPath, ports) {
130
- const launched = getAdapterSurface(adapter).run?.launchedBrowser;
131
- if (!launched) return null;
132
- if (ports.length === 0) return { boundTo: "none", reason: "the run had no known CDP port" };
133
- if (ports.length > 1) return { boundTo: "none", reason: `the run drove several CDP ports (${ports.join(", ")})` };
134
- return launched(target, path.dirname(artifactManifestPath), ports[0]);
135
- }
136
- function renderRunReport(summary, entries) {
137
- const lines = [
138
- "# MetaMask Recipe Run",
139
- "",
140
- `Status: ${String(summary.status ?? "unknown")}`,
141
- `Duration: ${formatDuration(Number(summary.durationMs ?? 0))}`,
142
- `Nodes: ${Number(summary.passed ?? 0)}/${Number(summary.total ?? entries.length)} passed`
143
- ];
144
- const sideFindings = isRecord(summary.sideFindings) ? summary.sideFindings : void 0;
145
- const sideFindingCounts = sideFindings && isRecord(sideFindings.counts) ? sideFindings.counts : void 0;
146
- const sideFindingTotal = Number(sideFindingCounts?.total ?? 0);
147
- if (sideFindingTotal > 0) {
148
- lines.push(
149
- "",
150
- "## Side findings",
151
- `- REVIEW ${sideFindingTotal} distinct application warning/error event(s) (non-blocking; expanded below and stored in diagnostics.json)`
152
- );
153
- }
154
- lines.push("", "## Steps");
155
- for (const entry of entries) {
156
- if (!isRecord(entry)) continue;
157
- const mark = entry.ok === false ? "FAIL" : "PASS";
158
- const nodeId = String(entry.nodeId ?? "(node)");
159
- const action = String(entry.action ?? "(action)");
160
- const duration = formatDuration(Number(entry.durationMs ?? 0));
161
- const detail = summarizeNodeOutput(entry.output);
162
- lines.push(`- ${mark} ${nodeId} (${action}, ${duration})${detail ? `: ${detail}` : ""}`);
163
- }
164
- return lines;
165
- }
166
- function summarizeNodeOutput(output) {
167
- if (!isRecord(output)) return "";
168
- const parts = [];
169
- const preferredKeys = [
170
- "platform",
171
- "screen",
172
- "route",
173
- "page",
174
- "network",
175
- "account",
176
- "count",
177
- "matchingCount",
178
- "proofPath",
179
- "screenshot",
180
- "path"
181
- ];
182
- for (const key of preferredKeys) addPart(parts, labelFor(key), summarizeValue(output[key]));
183
- const accountState = isRecord(output.accountState) ? output.accountState : void 0;
184
- if (accountState) {
185
- addPart(parts, "totalBalance", accountState.totalBalance);
186
- addPart(parts, "spendable", accountState.spendableBalance);
187
- addPart(parts, "marginUsed", accountState.marginUsed);
188
- addPart(parts, "unrealizedPnl", accountState.unrealizedPnl);
189
- }
190
- if (parts.length === 0) {
191
- for (const [key, value] of Object.entries(output)) {
192
- if (parts.length >= 5) break;
193
- if (key === "liveAdapter" || key === "artifacts") continue;
194
- addPart(parts, key, summarizeValue(value));
195
- }
196
- }
197
- return parts.join(", ");
198
- }
199
- function labelFor(key) {
200
- return key === "matchingCount" ? "matching" : key === "proofPath" ? "proof" : key;
201
- }
202
- function summarizeValue(value) {
203
- if (typeof value === "string") return shortenAddress(value);
204
- if (typeof value === "number" || typeof value === "boolean") return value;
205
- if (Array.isArray(value)) return `${value.length} item${value.length === 1 ? "" : "s"}`;
206
- return void 0;
207
- }
208
- function addPart(parts, label, value) {
209
- if (value === void 0 || value === null || value === "") return;
210
- parts.push(`${label}=${String(value)}`);
211
- }
212
- function shortenAddress(value) {
213
- return /^0x[a-fA-F0-9]{40}$/u.test(value) ? `${value.slice(0, 6)}...${value.slice(-4)}` : value;
214
- }
215
- function formatDuration(ms) {
216
- if (!Number.isFinite(ms) || ms <= 0) return "0ms";
217
- if (ms < 1e3) return `${Math.round(ms)}ms`;
218
- return `${(ms / 1e3).toFixed(ms < 1e4 ? 1 : 0)}s`;
219
- }
220
- function indexRunReportArtifact(artifactManifestPath) {
221
- let manifest;
222
- try {
223
- manifest = JSON.parse(fs.readFileSync(artifactManifestPath, "utf8"));
224
- } catch {
225
- return;
226
- }
227
- if (!isRecord(manifest)) return;
228
- const artifacts = Array.isArray(manifest.artifacts) ? manifest.artifacts : [];
229
- manifest.artifacts = [
230
- ...artifacts.filter((artifact) => !isRecord(artifact) || artifact.path !== "report.md"),
231
- { path: "report.md", type: "report", label: "Human run report", category: "system" }
232
- ];
233
- fs.writeFileSync(artifactManifestPath, `${JSON.stringify(manifest, null, 2)}
234
- `);
235
- }
236
- export {
237
- executedBrowser,
238
- indexProductProvenanceArtifact,
239
- recipeCdpPorts,
240
- writeRunReport
241
- };