dd-trace 6.7.0 → 6.9.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 (272) hide show
  1. package/ci/diagnose.js +27 -25
  2. package/ci/init.js +6 -6
  3. package/ci/runbook.md +114 -20
  4. package/ci/test-optimization-validation/approval-artifacts.js +36 -3
  5. package/ci/test-optimization-validation/approval.js +78 -22
  6. package/ci/test-optimization-validation/blocker-category.js +24 -0
  7. package/ci/test-optimization-validation/ci-discovery.js +23 -17
  8. package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
  9. package/ci/test-optimization-validation/ci-remediation.js +1 -1
  10. package/ci/test-optimization-validation/cli.js +280 -52
  11. package/ci/test-optimization-validation/command-blocker.js +159 -20
  12. package/ci/test-optimization-validation/command-output-policy.js +14 -8
  13. package/ci/test-optimization-validation/command-runner.js +9 -7
  14. package/ci/test-optimization-validation/environment.js +4 -2
  15. package/ci/test-optimization-validation/executable.js +15 -13
  16. package/ci/test-optimization-validation/execution-lock.js +70 -0
  17. package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
  18. package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
  19. package/ci/test-optimization-validation/framework-adapters/playwright.js +5 -5
  20. package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
  21. package/ci/test-optimization-validation/generated-files.js +47 -37
  22. package/ci/test-optimization-validation/generated-test-contract.js +9 -7
  23. package/ci/test-optimization-validation/generated-verifier.js +24 -17
  24. package/ci/test-optimization-validation/literal-glob.js +52 -0
  25. package/ci/test-optimization-validation/manifest-loader.js +3 -0
  26. package/ci/test-optimization-validation/manifest-scaffold.js +301 -52
  27. package/ci/test-optimization-validation/manifest-schema.js +80 -17
  28. package/ci/test-optimization-validation/offline-fixtures.js +13 -4
  29. package/ci/test-optimization-validation/offline-output.js +6 -6
  30. package/ci/test-optimization-validation/package-check.js +94 -0
  31. package/ci/test-optimization-validation/plan-writer.js +183 -10
  32. package/ci/test-optimization-validation/preflight-runner.js +110 -31
  33. package/ci/test-optimization-validation/project-build-artifact.js +31 -0
  34. package/ci/test-optimization-validation/redaction.js +18 -27
  35. package/ci/test-optimization-validation/report-writer.js +182 -48
  36. package/ci/test-optimization-validation/result-semantics.js +20 -3
  37. package/ci/test-optimization-validation/runner-command.js +41 -21
  38. package/ci/test-optimization-validation/runner-contract.js +79 -43
  39. package/ci/test-optimization-validation/safe-files.js +4 -4
  40. package/ci/test-optimization-validation/scenarios/basic-reporting.js +60 -6
  41. package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
  42. package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
  43. package/ci/test-optimization-validation/scenarios/test-management.js +2 -2
  44. package/ci/test-optimization-validation/static-diagnosis.js +10 -3
  45. package/ci/test-optimization-validation/test-output.js +2 -1
  46. package/ci/test-optimization-validation/validation-blocker.js +21 -0
  47. package/ci/vitest-no-worker-init-setup.mjs +377 -84
  48. package/index.d.ts +175 -14
  49. package/init.js +1 -17
  50. package/initialize.mjs +11 -0
  51. package/loader-hook.mjs +6 -4
  52. package/package.json +12 -4
  53. package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
  54. package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
  55. package/packages/datadog-esbuild/index.js +4 -2
  56. package/packages/datadog-esbuild/src/utils.js +17 -2
  57. package/packages/datadog-instrumentations/src/ai.js +61 -34
  58. package/packages/datadog-instrumentations/src/bluebird.js +6 -6
  59. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +85 -9
  60. package/packages/datadog-instrumentations/src/cucumber.js +131 -51
  61. package/packages/datadog-instrumentations/src/dns.js +21 -2
  62. package/packages/datadog-instrumentations/src/electron.js +1 -0
  63. package/packages/datadog-instrumentations/src/fastify.js +3 -1
  64. package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
  65. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
  66. package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
  67. package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
  68. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
  69. package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
  70. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +34 -9
  71. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  72. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +175 -0
  73. package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
  74. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
  75. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
  76. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
  77. package/packages/datadog-instrumentations/src/helpers/router-helper.js +38 -7
  78. package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
  79. package/packages/datadog-instrumentations/src/http/client.js +1 -3
  80. package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
  81. package/packages/datadog-instrumentations/src/jest.js +986 -246
  82. package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
  83. package/packages/datadog-instrumentations/src/mocha/main.js +109 -51
  84. package/packages/datadog-instrumentations/src/mocha/utils.js +120 -32
  85. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +44 -0
  86. package/packages/datadog-instrumentations/src/mocha/worker.js +441 -43
  87. package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
  88. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  89. package/packages/datadog-instrumentations/src/next.js +155 -23
  90. package/packages/datadog-instrumentations/src/openai.js +14 -0
  91. package/packages/datadog-instrumentations/src/pg.js +180 -6
  92. package/packages/datadog-instrumentations/src/playwright.js +176 -81
  93. package/packages/datadog-instrumentations/src/promise-js.js +4 -4
  94. package/packages/datadog-instrumentations/src/promise.js +3 -3
  95. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  96. package/packages/datadog-instrumentations/src/router.js +195 -19
  97. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +567 -65
  98. package/packages/datadog-instrumentations/src/vitest-main.js +438 -54
  99. package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
  100. package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
  101. package/packages/datadog-instrumentations/src/webdriverio.js +1090 -0
  102. package/packages/datadog-instrumentations/src/when.js +3 -3
  103. package/packages/datadog-instrumentations/src/ws.js +5 -1
  104. package/packages/datadog-plugin-aerospike/src/index.js +1 -3
  105. package/packages/datadog-plugin-amqplib/src/client.js +1 -1
  106. package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
  107. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
  108. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  109. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
  110. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
  111. package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
  112. package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
  113. package/packages/datadog-plugin-child_process/src/index.js +3 -3
  114. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -11
  115. package/packages/datadog-plugin-cucumber/src/index.js +5 -1
  116. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
  117. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
  118. package/packages/datadog-plugin-cypress/src/support.js +7 -4
  119. package/packages/datadog-plugin-electron/src/net.js +10 -4
  120. package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
  121. package/packages/datadog-plugin-fs/src/index.js +0 -4
  122. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
  123. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
  124. package/packages/datadog-plugin-graphql/src/execute.js +1 -0
  125. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
  126. package/packages/datadog-plugin-http/src/client.js +3 -2
  127. package/packages/datadog-plugin-http2/src/client.js +1 -1
  128. package/packages/datadog-plugin-jest/src/index.js +3 -21
  129. package/packages/datadog-plugin-jest/src/util.js +4 -1
  130. package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
  131. package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
  132. package/packages/datadog-plugin-mocha/src/index.js +342 -6
  133. package/packages/datadog-plugin-next/src/index.js +57 -9
  134. package/packages/datadog-plugin-openai/src/tracing.js +4 -0
  135. package/packages/datadog-plugin-pg/src/index.js +65 -1
  136. package/packages/datadog-plugin-playwright/src/index.js +1 -1
  137. package/packages/datadog-plugin-prisma/src/index.js +5 -1
  138. package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
  139. package/packages/datadog-plugin-rhea/src/producer.js +1 -1
  140. package/packages/datadog-plugin-undici/src/index.js +2 -1
  141. package/packages/datadog-plugin-vitest/src/index.js +179 -18
  142. package/packages/datadog-shimmer/src/shimmer.js +6 -2
  143. package/packages/datadog-webpack/index.js +2 -2
  144. package/packages/dd-trace/src/aiguard/sdk.js +3 -0
  145. package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
  146. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
  147. package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
  148. package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
  149. package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
  150. package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
  151. package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
  152. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
  153. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
  154. package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
  155. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  156. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
  157. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +2 -2
  158. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
  159. package/packages/dd-trace/src/appsec/index.js +48 -476
  160. package/packages/dd-trace/src/appsec/sdk/track_event.js +10 -1
  161. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  162. package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
  163. package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
  164. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
  165. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +29 -15
  166. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +19 -1
  167. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +25 -1
  168. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
  169. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
  170. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
  171. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
  172. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
  173. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
  174. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +2 -2
  175. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
  176. package/packages/dd-trace/src/config/defaults.js +14 -6
  177. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
  178. package/packages/dd-trace/src/config/helper.js +2 -0
  179. package/packages/dd-trace/src/config/index.js +31 -5
  180. package/packages/dd-trace/src/config/parsers.js +19 -1
  181. package/packages/dd-trace/src/config/remote_config.js +1 -1
  182. package/packages/dd-trace/src/config/supported-configurations.json +13 -6
  183. package/packages/dd-trace/src/datastreams/encoding.js +3 -4
  184. package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
  185. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
  186. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
  187. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
  188. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
  189. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
  190. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
  191. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  192. package/packages/dd-trace/src/exporters/common/url.js +3 -5
  193. package/packages/dd-trace/src/exporters/electron/index.js +4 -1
  194. package/packages/dd-trace/src/external-logger/src/index.js +1 -2
  195. package/packages/dd-trace/src/flare/index.js +2 -2
  196. package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
  197. package/packages/dd-trace/src/guardrails/log.js +1 -10
  198. package/packages/dd-trace/src/id.js +1 -1
  199. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
  200. package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
  201. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
  202. package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
  203. package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
  204. package/packages/dd-trace/src/llmobs/experiments/index.js +66 -19
  205. package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
  206. package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
  207. package/packages/dd-trace/src/llmobs/experiments/util.js +220 -0
  208. package/packages/dd-trace/src/llmobs/noop.js +2 -0
  209. package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
  210. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
  211. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
  212. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
  213. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
  214. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
  215. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
  216. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
  217. package/packages/dd-trace/src/llmobs/sdk.js +152 -78
  218. package/packages/dd-trace/src/llmobs/span_processor.js +9 -7
  219. package/packages/dd-trace/src/llmobs/tagger.js +1 -2
  220. package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
  221. package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
  222. package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
  223. package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
  224. package/packages/dd-trace/src/log/channels.js +1 -9
  225. package/packages/dd-trace/src/log/levels.js +12 -0
  226. package/packages/dd-trace/src/noop/proxy.js +2 -2
  227. package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
  228. package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
  229. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
  230. package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
  231. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  232. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
  233. package/packages/dd-trace/src/opentelemetry/span.js +4 -0
  234. package/packages/dd-trace/src/opentracing/span.js +1 -1
  235. package/packages/dd-trace/src/opentracing/span_context.js +1 -1
  236. package/packages/dd-trace/src/plugins/ci_plugin.js +124 -23
  237. package/packages/dd-trace/src/plugins/index.js +2 -0
  238. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  239. package/packages/dd-trace/src/plugins/tracing.js +1 -0
  240. package/packages/dd-trace/src/plugins/util/ci.js +13 -6
  241. package/packages/dd-trace/src/plugins/util/git.js +7 -5
  242. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +3 -3
  243. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
  244. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  245. package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
  246. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  247. package/packages/dd-trace/src/plugins/util/test.js +356 -86
  248. package/packages/dd-trace/src/plugins/util/url.js +5 -5
  249. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  250. package/packages/dd-trace/src/plugins/util/web.js +24 -2
  251. package/packages/dd-trace/src/priority_sampler.js +6 -3
  252. package/packages/dd-trace/src/profiler.js +1 -1
  253. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
  254. package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
  255. package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
  256. package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
  257. package/packages/dd-trace/src/proxy.js +1 -0
  258. package/packages/dd-trace/src/ritm.js +10 -20
  259. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
  260. package/packages/dd-trace/src/sampling_rule.js +4 -2
  261. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
  262. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
  263. package/packages/dd-trace/src/startup-log.js +3 -0
  264. package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
  265. package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
  266. package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
  267. package/packages/dd-trace/src/util.js +16 -0
  268. package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
  269. package/vendor/dist/pprof-format/index.js +1 -1
  270. package/vendor/dist/source-map/index.js +1 -1
  271. package/version.js +10 -8
  272. /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
@@ -12,6 +12,7 @@ const { sanitizeForReport } = require('./redaction')
12
12
  const { getManifestInputFiles } = require('./runner-command')
13
13
 
14
14
  const APPROVAL_DIGEST_PATTERN = /^[a-f0-9]{64}$/
15
+ const MAX_CAPTURED_PROJECT_SOURCE_BYTES = 512 * 1024
15
16
  const OFFLINE_FIXTURE_NONCE_PATTERN = /^[a-f0-9]{32}$/
16
17
  const PACKAGE_SNAPSHOT_EXCLUDED_NAMES = new Set(['.git', '.nyc_output', 'node_modules'])
17
18
 
@@ -105,10 +106,7 @@ function getApprovalMaterial ({
105
106
  path: path.resolve(manifest.__path),
106
107
  sha256: getManifestDigest(manifest),
107
108
  },
108
- projectFiles: getManifestInputFiles(manifest, { includeLocal }).map(filename => ({
109
- path: filename,
110
- sha256: getFileDigest(filename),
111
- })),
109
+ projectFiles: getApprovalProjectFiles(manifest, { includeLocal }),
112
110
  selection: {
113
111
  frameworks: [...selectedFrameworkIds],
114
112
  scenario: requestedScenario,
@@ -117,6 +115,11 @@ function getApprovalMaterial ({
117
115
  outputDirectory: path.resolve(out),
118
116
  offlineFixtureNonce,
119
117
  keepTemporaryFiles: keepTempFiles,
118
+ requiredCapabilities: getRequiredCapabilities({
119
+ manifest,
120
+ requestedScenario,
121
+ selectedFrameworkIds,
122
+ }),
120
123
  verbose,
121
124
  },
122
125
  fixtureRecipeDigests: includeLocal
@@ -133,6 +136,51 @@ function getApprovalMaterial ({
133
136
  }
134
137
  }
135
138
 
139
+ // Capability metadata is approval-only; the validator does not request permissions or start prerequisites.
140
+ function getRequiredCapabilities ({ manifest, requestedScenario, selectedFrameworkIds = [] }) {
141
+ if (requestedScenario === 'ci-wiring') return []
142
+ const selected = new Set(selectedFrameworkIds)
143
+ const frameworks = (manifest.frameworks || []).filter(framework => {
144
+ return framework.status === 'runnable' && (selected.size === 0 || selected.has(framework.id))
145
+ })
146
+ const capabilities = new Set()
147
+ if (frameworks.some(framework => ['cypress', 'playwright'].includes(framework.framework) ||
148
+ (framework.framework === 'vitest' && framework.validation?.runnerArgs?.includes('--browser')) ||
149
+ framework.browserRequired === true)) {
150
+ capabilities.add('browser_process')
151
+ }
152
+ if (frameworks.some(framework => framework.localSocketRequired === true ||
153
+ (framework.validation?.fallbackTests || []).some(fallback => fallback.localSocketRequired === true))) {
154
+ capabilities.add('localhost_socket')
155
+ }
156
+ return [...capabilities].sort()
157
+ }
158
+
159
+ function getApprovalProjectFiles (manifest, { includeLocal = true } = {}) {
160
+ return getApprovalProjectSnapshot(manifest, { includeLocal }).projectFiles
161
+ }
162
+
163
+ // Hashes and static-analysis sources come from the same reads to avoid approval-time races.
164
+ function getApprovalProjectSnapshot (manifest, { includeLocal = true } = {}) {
165
+ const projectFiles = []
166
+ const sources = new Map()
167
+ for (const filename of getManifestInputFiles(manifest, { includeLocal })) {
168
+ const stat = fs.lstatSync(filename)
169
+ const contents = fs.readFileSync(filename)
170
+ projectFiles.push({
171
+ path: filename,
172
+ sha256: crypto.createHash('sha256').update(contents).digest('hex'),
173
+ })
174
+ sources.set(
175
+ filename,
176
+ stat.isFile() && !stat.isSymbolicLink() && contents.length <= MAX_CAPTURED_PROJECT_SOURCE_BYTES
177
+ ? contents
178
+ : undefined
179
+ )
180
+ }
181
+ return { projectFiles, sources }
182
+ }
183
+
136
184
  /**
137
185
  * Serializes approval material using stable formatting suitable for independent SHA-256 tools.
138
186
  *
@@ -192,21 +240,25 @@ function getApprovalCommand (id, command) {
192
240
  */
193
241
  function getGeneratedFileMaterial (manifest, requestedScenario) {
194
242
  const files = []
195
- for (const framework of manifest.frameworks || []) {
196
- const strategy = framework.generatedTestStrategy
197
- const selectedPaths = getSelectedGeneratedPaths(strategy, requestedScenario)
198
- for (const file of strategy?.files || []) {
199
- if (!selectedPaths.has(path.resolve(file.path))) continue
200
- const content = `${file.contentLines.join('\n')}\n`
201
- files.push(sanitizeForReport({
202
- frameworkId: framework.id,
203
- path: path.resolve(file.path),
204
- sha256: crypto.createHash('sha256').update(content).digest('hex'),
205
- content,
206
- removeAfterValidation: (strategy.cleanupPaths || []).some(cleanupPath => {
207
- return path.resolve(cleanupPath) === path.resolve(file.path)
208
- }),
209
- }))
243
+ if (manifest.frameworks) {
244
+ for (const framework of manifest.frameworks) {
245
+ const strategy = framework.generatedTestStrategy
246
+ const selectedPaths = getSelectedGeneratedPaths(strategy, requestedScenario)
247
+ if (strategy?.files) {
248
+ for (const file of strategy.files) {
249
+ if (!selectedPaths.has(path.resolve(file.path))) continue
250
+ const content = `${file.contentLines.join('\n')}\n`
251
+ files.push(sanitizeForReport({
252
+ frameworkId: framework.id,
253
+ path: path.resolve(file.path),
254
+ sha256: crypto.createHash('sha256').update(content).digest('hex'),
255
+ content,
256
+ removeAfterValidation: (strategy.cleanupPaths || []).some(cleanupPath => {
257
+ return path.resolve(cleanupPath) === path.resolve(file.path)
258
+ }),
259
+ }))
260
+ }
261
+ }
210
262
  }
211
263
  }
212
264
  return files
@@ -230,9 +282,11 @@ function getSelectedGeneratedPaths (strategy, requestedScenario) {
230
282
  return path.resolve(scenario.testIdentities[0].file)
231
283
  }))
232
284
  const selectedPaths = new Set()
233
- for (const file of strategy.files || []) {
234
- const filename = path.resolve(file.path)
235
- if (!requestedScenario || !scenarioPaths.has(filename)) selectedPaths.add(filename)
285
+ if (strategy.files) {
286
+ for (const file of strategy.files) {
287
+ const filename = path.resolve(file.path)
288
+ if (!requestedScenario || !scenarioPaths.has(filename)) selectedPaths.add(filename)
289
+ }
236
290
  }
237
291
  if (generatedId) {
238
292
  const scenario = strategy.scenarios?.find(candidate => candidate.id === generatedId)
@@ -332,5 +386,7 @@ module.exports = {
332
386
  assertApprovalDigest,
333
387
  getApprovalDigest,
334
388
  getApprovalMaterial,
389
+ getApprovalProjectSnapshot,
390
+ getRequiredCapabilities,
335
391
  serializeApprovalMaterial,
336
392
  }
@@ -0,0 +1,24 @@
1
+ 'use strict'
2
+
3
+ const BLOCKER_CATEGORIES = Object.freeze({
4
+ CLEAN_TEST_FAILED: 'CLEAN_TEST_FAILED',
5
+ EXECUTION_ENVIRONMENT_BLOCKED: 'EXECUTION_ENVIRONMENT_BLOCKED',
6
+ PROJECT_SETUP_REQUIRED: 'PROJECT_SETUP_REQUIRED',
7
+ UNSUPPORTED_VERSION: 'UNSUPPORTED_VERSION',
8
+ VALIDATOR_LIMITATION: 'VALIDATOR_LIMITATION',
9
+ })
10
+
11
+ const BLOCKER_CATEGORY_VALUES = new Set(Object.values(BLOCKER_CATEGORIES))
12
+
13
+ function getBlockerDomain (category) {
14
+ const domains = {
15
+ [BLOCKER_CATEGORIES.CLEAN_TEST_FAILED]: 'local_runtime',
16
+ [BLOCKER_CATEGORIES.EXECUTION_ENVIRONMENT_BLOCKED]: 'execution_environment',
17
+ [BLOCKER_CATEGORIES.PROJECT_SETUP_REQUIRED]: 'project_setup',
18
+ [BLOCKER_CATEGORIES.UNSUPPORTED_VERSION]: 'unsupported_version',
19
+ [BLOCKER_CATEGORIES.VALIDATOR_LIMITATION]: 'validator_adapter',
20
+ }
21
+ return domains[category]
22
+ }
23
+
24
+ module.exports = { BLOCKER_CATEGORIES, BLOCKER_CATEGORY_VALUES, getBlockerDomain }
@@ -61,18 +61,22 @@ function buildCiDiscovery ({ manifest, diagnosis }) {
61
61
  function getManifestWorkflowLocations (manifest) {
62
62
  const root = manifest.repository?.root
63
63
  const locations = []
64
- for (const framework of manifest.frameworks || []) {
65
- const configFile = framework.ciWiring?.configFile
66
- if (typeof configFile !== 'string') continue
67
- if (!root || !path.isAbsolute(configFile)) {
68
- locations.push(configFile)
69
- continue
64
+ if (manifest.frameworks) {
65
+ for (const framework of manifest.frameworks) {
66
+ const configFile = framework.ciWiring?.configFile
67
+ if (typeof configFile !== 'string') continue
68
+ if (!root || !path.isAbsolute(configFile)) {
69
+ locations.push(configFile)
70
+ continue
71
+ }
72
+
73
+ const relative = path.relative(root, configFile)
74
+ const isRelativePath = relative && relative !== '..' && !relative.startsWith(`..${path.sep}`) &&
75
+ !path.isAbsolute(relative)
76
+ locations.push(isRelativePath
77
+ ? relative.split(path.sep).join('/')
78
+ : configFile)
70
79
  }
71
-
72
- const relative = path.relative(root, configFile)
73
- locations.push(relative && relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative)
74
- ? relative.split(path.sep).join('/')
75
- : configFile)
76
80
  }
77
81
  return uniqueStrings(locations)
78
82
  }
@@ -106,12 +110,14 @@ function getCiDiscoveryContradictions ({ manifest, declaredFound, staticFound })
106
110
  )
107
111
  }
108
112
 
109
- for (const framework of manifest.frameworks || []) {
110
- if (!frameworkClaimsNoCi(framework)) continue
111
- contradictions.push(
112
- `framework ${framework.id || '<unknown>'} records no CI workflow, but static diagnosis found ` +
113
- formatList(staticFound)
114
- )
113
+ if (manifest.frameworks) {
114
+ for (const framework of manifest.frameworks) {
115
+ if (!frameworkClaimsNoCi(framework)) continue
116
+ contradictions.push(
117
+ `framework ${framework.id || '<unknown>'} records no CI workflow, but static diagnosis found ` +
118
+ formatList(staticFound)
119
+ )
120
+ }
115
121
  }
116
122
 
117
123
  return contradictions
@@ -3,7 +3,21 @@
3
3
  const { parseLiteralEnvironmentPrefix } = require('./literal-environment')
4
4
 
5
5
  const MAX_SCRIPT_EXPANSIONS = 16
6
- const DYNAMIC_VALUE_PATTERN = /[$`]|\r|\n|%[^%\s]+%|![^!\s]+!/
6
+ const DYNAMIC_VALUE_PATTERN = /[$`\r\n]|%[^%\s]+%|![^!\s]+!/
7
+ const RESERVED_PACKAGE_MANAGER_COMMANDS = {
8
+ pnpm: new Set([
9
+ 'add', 'audit', 'bin', 'c', 'config', 'create', 'deploy', 'dlx', 'env', 'exec', 'fetch', 'i', 'import', 'init',
10
+ 'install', 'link', 'list', 'ln', 'ls', 'outdated', 'pack', 'patch', 'patch-commit', 'prune', 'publish', 'rebuild',
11
+ 'remove', 'rm', 'root', 'self-update', 'server', 'setup', 'store', 'uninstall', 'unlink', 'up', 'update', 'view',
12
+ 'why',
13
+ ]),
14
+ yarn: new Set([
15
+ 'add', 'audit', 'bin', 'cache', 'check', 'config', 'constraints', 'create', 'dedupe', 'dlx', 'exec', 'global',
16
+ 'help', 'import', 'info', 'init', 'install', 'link', 'list', 'node', 'npm', 'outdated', 'owner', 'pack', 'patch',
17
+ 'plugin', 'policies', 'publish', 'rebuild', 'remove', 'set', 'stage', 'tag', 'team', 'unlink', 'unplug', 'up',
18
+ 'upgrade', 'version', 'versions', 'why', 'workspace', 'workspaces',
19
+ ]),
20
+ }
7
21
 
8
22
  /**
9
23
  * Expands bounded local package-script references without executing them.
@@ -45,7 +59,7 @@ function expandCommand (command, scripts, path, stack, state) {
45
59
  if (stack.has(invocation.script)) {
46
60
  return { error: `local package-script cycle includes ${invocation.script}` }
47
61
  }
48
- const lifecycleNames = invocation.manager === 'npm'
62
+ const lifecycleNames = invocation.manager === 'npm' || invocation.manager === 'bun'
49
63
  ? [`pre${invocation.script}`, `post${invocation.script}`]
50
64
  .filter(name => typeof scripts[name] === 'string')
51
65
  : []
@@ -60,8 +74,11 @@ function expandCommand (command, scripts, path, stack, state) {
60
74
  const nextStack = new Set(stack)
61
75
  nextStack.add(invocation.script)
62
76
  nextStack.add(scriptName)
77
+ const scriptCommand = scriptName === invocation.script && invocation.arguments
78
+ ? `${scripts[scriptName]} ${invocation.arguments}`
79
+ : scripts[scriptName]
63
80
  const expanded = expandCommand(
64
- scripts[scriptName],
81
+ scriptCommand,
65
82
  scripts,
66
83
  [...path, segment],
67
84
  nextStack,
@@ -129,13 +146,24 @@ function getPackageScriptInvocation (command) {
129
146
  const literalPrefix = parseLiteralEnvironmentPrefix(command)
130
147
  const source = command.slice(literalPrefix.length).trim()
131
148
  .replace(/^(?:c8|nyc)(?:\.cmd)?\s+/, '')
132
- const match = /^(npm(?:\.cmd)?|pnpm(?:\.cmd)?|yarn(?:pkg)?(?:\.cmd)?)\s+(?:(run|run-script)\s+)?([\w:-]+)$/
149
+ const match = /^(bun|npm(?:\.cmd)?|pnpm(?:\.cmd)?|yarn(?:pkg)?(?:\.cmd)?)\s+(?:(run|run-script)\s+)?([\w:-]+)(?:\s+(.+))?$/
133
150
  .exec(source)
134
151
  if (!match) return
135
152
 
136
- const manager = match[1].replace(/\.cmd$/i, '')
153
+ const manager = match[1].replace(/\.cmd$/i, '').replace(/^yarnpkg$/, 'yarn')
137
154
  if (manager === 'npm' && !match[2] && !['restart', 'start', 'stop', 'test'].includes(match[3])) return
138
- return { manager, script: match[3] }
155
+ if (manager === 'bun' && match[2] !== 'run') return
156
+ if (!match[2] && RESERVED_PACKAGE_MANAGER_COMMANDS[manager]?.has(match[3])) return
157
+ const args = match[4]?.trim()
158
+ const separatedArguments = args ? /^--(?:\s+(.+))?$/.exec(args) : undefined
159
+ if (['npm', 'pnpm'].includes(manager) && args && !separatedArguments) return
160
+ const scriptArguments = ['npm', 'pnpm'].includes(manager) ? separatedArguments?.[1]?.trim() : args
161
+ if (scriptArguments && !splitLiteralAndChain(scriptArguments)) return
162
+ return {
163
+ ...(scriptArguments ? { arguments: scriptArguments } : {}),
164
+ manager,
165
+ script: match[3],
166
+ }
139
167
  }
140
168
 
141
169
  module.exports = { expandLocalPackageScripts }
@@ -183,7 +183,7 @@ function isDatadogModuleSpecifier (specifier, entrypoint) {
183
183
  }
184
184
 
185
185
  function hasDynamicEnvironmentReference (value) {
186
- return /(?:\$[A-Za-z_{]|\$\(|%[A-Za-z_][A-Za-z0-9_]*%)/.test(value)
186
+ return /\$[A-Za-z_{]|\$\(|%[A-Za-z_][A-Za-z0-9_]*%/.test(value)
187
187
  }
188
188
 
189
189
  function getRecommendedValues (framework) {