@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,332 +0,0 @@
1
- import { execFileSync } from "node:child_process";
2
- import { createHash } from "node:crypto";
3
- import fs, { constants as fsConstants } from "node:fs";
4
- import path from "node:path";
5
- import { getAdapterSurface } from "./adapters/surface.js";
6
- import { indexArtifactManifest } from "./artifact-files.js";
7
- import { importRecipeProtocol, runnerDir } from "./paths.js";
8
- const gitContexts = /* @__PURE__ */ new Map();
9
- let protocolPromise;
10
- class ProvenanceDriftError extends Error {
11
- code = "PROVENANCE_DRIFT";
12
- exitCode = 5;
13
- userAction;
14
- provenancePath;
15
- drift;
16
- constructor(provenancePath, drift, cause) {
17
- const fields = [...new Set(drift.map((entry) => entry.field))].join(", ");
18
- super(
19
- `Execution inputs changed after preparation (${fields}); evidence is invalid.`,
20
- cause === void 0 ? void 0 : { cause }
21
- );
22
- this.name = "ProvenanceDriftError";
23
- this.provenancePath = provenancePath;
24
- this.drift = drift;
25
- this.userAction = `restore the prepared recipe, library, and product source, then rerun; inspect ${provenancePath}`;
26
- }
27
- }
28
- async function captureExecutionProvenance(input, phase) {
29
- const protocol = await (protocolPromise ??= importRecipeProtocol());
30
- const recipeDigest = input.recipePath ? recipeFileDigest(protocol, input.recipePath) : protocol.digestRecipeDocument(input.recipeDocument);
31
- const libraries = (input.librarySources ?? []).map((source, index) => ({
32
- name: source.name ?? `library-${index + 1}`,
33
- ...sourceSnapshot(source.root)
34
- }));
35
- const runnerRoot = input.runnerRoot ?? runnerDir;
36
- return {
37
- phase,
38
- capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
39
- recipeDigest,
40
- product: sourceSnapshot(
41
- input.projectRoot,
42
- input.adapter,
43
- input.excludedProductRoots
44
- ),
45
- runner: sourceSnapshot(runnerRoot, void 0, [], [
46
- "src",
47
- "adapters",
48
- "library",
49
- "bin",
50
- "dist",
51
- "package.json"
52
- ]),
53
- libraries,
54
- helpers: (input.helperPaths ?? []).map((helperPath) => ({
55
- path: displayPath(input.projectRoot, helperPath),
56
- sourceFingerprint: fileFingerprint(helperPath)
57
- }))
58
- };
59
- }
60
- function executionProvenanceDrift(start, current) {
61
- const drift = [];
62
- if (current.phase === "start") return drift;
63
- const phase = current.phase;
64
- compare(drift, phase, "recipeDigest", start.recipeDigest, current.recipeDigest);
65
- compareSource(drift, phase, "product", start.product, current.product);
66
- compareSource(drift, phase, "runner", start.runner, current.runner);
67
- if (start.libraries.length !== current.libraries.length) {
68
- compare(
69
- drift,
70
- phase,
71
- "libraries.length",
72
- String(start.libraries.length),
73
- String(current.libraries.length)
74
- );
75
- }
76
- const count = Math.min(start.libraries.length, current.libraries.length);
77
- for (let index = 0; index < count; index += 1) {
78
- const expected = start.libraries[index];
79
- const actual = current.libraries[index];
80
- const prefix = `libraries[${index}]`;
81
- compare(drift, phase, `${prefix}.name`, expected.name, actual.name);
82
- compareSource(drift, phase, prefix, expected, actual);
83
- }
84
- if (start.helpers.length !== current.helpers.length) {
85
- compare(
86
- drift,
87
- phase,
88
- "helpers.length",
89
- String(start.helpers.length),
90
- String(current.helpers.length)
91
- );
92
- }
93
- const helperCount = Math.min(start.helpers.length, current.helpers.length);
94
- for (let index = 0; index < helperCount; index += 1) {
95
- compare(drift, phase, `helpers[${index}].path`, start.helpers[index].path, current.helpers[index].path);
96
- compare(
97
- drift,
98
- phase,
99
- `helpers[${index}].sourceFingerprint`,
100
- start.helpers[index].sourceFingerprint,
101
- current.helpers[index].sourceFingerprint
102
- );
103
- }
104
- return drift;
105
- }
106
- async function writeExecutionProvenance(artifactsDir, snapshots, drift, artifactManifestPath) {
107
- const provenancePath = path.join(path.resolve(artifactsDir), "execution-provenance.json");
108
- const record = {
109
- schemaVersion: 1,
110
- valid: drift.length === 0,
111
- snapshots,
112
- drift
113
- };
114
- fs.mkdirSync(path.dirname(provenancePath), { recursive: true });
115
- fs.writeFileSync(provenancePath, `${JSON.stringify(record, null, 2)}
116
- `);
117
- if (artifactManifestPath) {
118
- await indexArtifactManifest(artifactManifestPath, [
119
- {
120
- path: "execution-provenance.json",
121
- type: "json",
122
- label: "Execution provenance",
123
- category: "system",
124
- metadata: {
125
- valid: record.valid,
126
- errorCode: record.valid ? null : "PROVENANCE_DRIFT"
127
- }
128
- }
129
- ]);
130
- }
131
- return provenancePath;
132
- }
133
- function recipeFileDigest(protocol, recipePath) {
134
- const source = readRegularFileNoFollow(recipePath);
135
- try {
136
- return protocol.digestRecipeDocument(JSON.parse(source.toString("utf8")));
137
- } catch {
138
- return `invalid:sha256:${createHash("sha256").update(source).digest("hex")}`;
139
- }
140
- }
141
- function sourceSnapshot(root, adapter, excludedRoots = [], includedRoots = []) {
142
- const git = gitContext(root);
143
- if (!git) {
144
- return {
145
- head: null,
146
- status: "not-a-git-checkout",
147
- sourceFingerprint: directoryFingerprint(root, excludedRoots, includedRoots)
148
- };
149
- }
150
- const pathspecs = sourcePathspecs(git, excludedRoots, includedRoots);
151
- const status = gitText(git.topLevel, [
152
- "status",
153
- "--porcelain=v1",
154
- "--untracked-files=normal",
155
- "--",
156
- ...pathspecs
157
- ]);
158
- const head = gitBuffer(git.topLevel, ["rev-parse", "HEAD"]);
159
- const platformFingerprint = adapter ? getAdapterSurface(adapter).sourceFingerprint : void 0;
160
- return {
161
- head: head.toString("utf8").trim() || null,
162
- status,
163
- sourceFingerprint: platformFingerprint && path.resolve(root) === git.topLevel ? platformFingerprint(root) : nestedGitSourceFingerprint(root, git, pathspecs, excludedRoots, includedRoots, head)
164
- };
165
- }
166
- function nestedGitSourceFingerprint(root, git, pathspecs, excludedRoots, includedRoots, head) {
167
- const gitFingerprint = gitSourceFingerprint(git.topLevel, pathspecs, head);
168
- if (git.pathspec === "." && includedRoots.length === 0) return gitFingerprint;
169
- return createHash("sha256").update(gitFingerprint).update("\0nested-source\0").update(directoryFingerprint(root, excludedRoots, includedRoots)).digest("hex");
170
- }
171
- function gitContext(root) {
172
- const cacheKey = path.resolve(root);
173
- if (gitContexts.has(cacheKey)) return gitContexts.get(cacheKey) ?? null;
174
- try {
175
- const resolved = cacheKey;
176
- const topLevel = fs.realpathSync(
177
- gitText(resolved, ["rev-parse", "--show-toplevel"]).trim()
178
- );
179
- const relative = path.relative(topLevel, fs.realpathSync(resolved));
180
- const context = relative === ".." || relative.startsWith(`..${path.sep}`) ? null : { topLevel, pathspec: relative || "." };
181
- gitContexts.set(cacheKey, context);
182
- return context;
183
- } catch {
184
- gitContexts.set(cacheKey, null);
185
- return null;
186
- }
187
- }
188
- function gitSourceFingerprint(topLevel, pathspecs, head) {
189
- const hash = createHash("sha256");
190
- hash.update(head);
191
- hash.update("\0diff\0");
192
- hash.update(
193
- gitBuffer(topLevel, [
194
- "diff",
195
- "--no-ext-diff",
196
- "--binary",
197
- head.toString("utf8").trim(),
198
- "--",
199
- ...pathspecs
200
- ])
201
- );
202
- const untracked = gitText(topLevel, [
203
- "ls-files",
204
- "--others",
205
- "--exclude-standard",
206
- "-z",
207
- "--",
208
- ...pathspecs
209
- ]).split("\0").filter(Boolean).sort();
210
- for (const relative of untracked) {
211
- hash.update(`\0untracked\0${relative}\0`);
212
- const absolute = path.join(topLevel, relative);
213
- hash.update(readPathIdentity(absolute));
214
- }
215
- return hash.digest("hex");
216
- }
217
- function sourcePathspecs(git, excludedRoots, includedRoots) {
218
- const exclusions = excludedRoots.flatMap((root) => {
219
- const relative = path.relative(git.topLevel, fs.existsSync(root) ? fs.realpathSync(root) : path.resolve(root));
220
- return relative !== ".." && !relative.startsWith(`..${path.sep}`) ? [`:(exclude)${relative}`] : [];
221
- });
222
- const inclusions = includedRoots.length > 0 ? includedRoots.map((root) => path.join(git.pathspec === "." ? "" : git.pathspec, root)) : [git.pathspec];
223
- return [...inclusions, ...exclusions];
224
- }
225
- function directoryFingerprint(root, excludedRoots, includedRoots) {
226
- const hash = createHash("sha256");
227
- const resolvedRoot = path.resolve(root);
228
- const roots = includedRoots.length > 0 ? includedRoots : [""];
229
- for (const included of roots) {
230
- hashDirectory(
231
- hash,
232
- resolvedRoot,
233
- included,
234
- new Set(excludedRoots.map((entry) => path.resolve(entry)))
235
- );
236
- }
237
- return hash.digest("hex");
238
- }
239
- function hashDirectory(hash, root, relative, excludedRoots) {
240
- const absolute = path.join(root, relative);
241
- if ([...excludedRoots].some(
242
- (excluded) => absolute === excluded || absolute.startsWith(`${excluded}${path.sep}`)
243
- )) return;
244
- let stat;
245
- try {
246
- stat = fs.lstatSync(absolute);
247
- } catch (error) {
248
- if (error.code === "ENOENT") {
249
- hash.update(`absent\0${relative}\0`);
250
- return;
251
- }
252
- throw error;
253
- }
254
- if (stat.isDirectory()) {
255
- hash.update(`directory\0${relative}\0`);
256
- for (const name of fs.readdirSync(absolute).sort()) {
257
- if (relative === "" && (name === ".git" || name === "node_modules" || name === "temp")) continue;
258
- hashDirectory(hash, root, path.join(relative, name), excludedRoots);
259
- }
260
- return;
261
- }
262
- if (stat.isSymbolicLink()) {
263
- throw new Error(`Execution provenance source must not be a symbolic link: ${absolute}`);
264
- }
265
- hash.update(`file\0${relative}\0`);
266
- hash.update(readRegularFileNoFollow(absolute));
267
- hash.update("\0");
268
- }
269
- function fileFingerprint(filePath) {
270
- return createHash("sha256").update(readRegularFileNoFollow(filePath)).digest("hex");
271
- }
272
- function readPathIdentity(filePath) {
273
- const stat = fs.lstatSync(filePath);
274
- if (stat.isSymbolicLink()) {
275
- throw new Error(`Execution provenance source must not be a symbolic link: ${filePath}`);
276
- }
277
- return readRegularFileNoFollow(filePath);
278
- }
279
- function readRegularFileNoFollow(filePath) {
280
- let fd;
281
- try {
282
- fd = fs.openSync(filePath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
283
- } catch (error) {
284
- if (error.code === "ELOOP") {
285
- throw new Error(`Execution provenance source must not be a symbolic link: ${filePath}`);
286
- }
287
- throw error;
288
- }
289
- try {
290
- if (!fs.fstatSync(fd).isFile()) {
291
- throw new Error(`Execution provenance source is not a regular file: ${filePath}`);
292
- }
293
- return fs.readFileSync(fd);
294
- } finally {
295
- fs.closeSync(fd);
296
- }
297
- }
298
- function displayPath(projectRoot, filePath) {
299
- const relative = path.relative(path.resolve(projectRoot), path.resolve(filePath));
300
- return relative !== ".." && !relative.startsWith(`..${path.sep}`) ? relative || "." : path.resolve(filePath);
301
- }
302
- function gitText(cwd, args) {
303
- return gitBuffer(cwd, args).toString("utf8");
304
- }
305
- function gitBuffer(cwd, args) {
306
- return execFileSync("git", args, {
307
- cwd,
308
- encoding: "buffer",
309
- maxBuffer: 128 * 1024 * 1024,
310
- stdio: ["ignore", "pipe", "ignore"]
311
- });
312
- }
313
- function compareSource(drift, phase, prefix, start, current) {
314
- compare(drift, phase, `${prefix}.head`, start.head, current.head);
315
- compare(drift, phase, `${prefix}.status`, start.status, current.status);
316
- compare(
317
- drift,
318
- phase,
319
- `${prefix}.sourceFingerprint`,
320
- start.sourceFingerprint,
321
- current.sourceFingerprint
322
- );
323
- }
324
- function compare(drift, phase, field, start, current) {
325
- if (start !== current) drift.push({ phase, field, start, current });
326
- }
327
- export {
328
- ProvenanceDriftError,
329
- captureExecutionProvenance,
330
- executionProvenanceDrift,
331
- writeExecutionProvenance
332
- };