@dotsetlabs/bellwether 0.10.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 (403) hide show
  1. package/CHANGELOG.md +291 -0
  2. package/LICENSE +21 -0
  3. package/README.md +739 -0
  4. package/dist/auth/credentials.d.ts +64 -0
  5. package/dist/auth/credentials.js +218 -0
  6. package/dist/auth/index.d.ts +6 -0
  7. package/dist/auth/index.js +6 -0
  8. package/dist/auth/keychain.d.ts +64 -0
  9. package/dist/auth/keychain.js +268 -0
  10. package/dist/baseline/ab-testing.d.ts +80 -0
  11. package/dist/baseline/ab-testing.js +236 -0
  12. package/dist/baseline/ai-compatibility-scorer.d.ts +95 -0
  13. package/dist/baseline/ai-compatibility-scorer.js +606 -0
  14. package/dist/baseline/calibration.d.ts +77 -0
  15. package/dist/baseline/calibration.js +136 -0
  16. package/dist/baseline/category-matching.d.ts +85 -0
  17. package/dist/baseline/category-matching.js +289 -0
  18. package/dist/baseline/change-impact-analyzer.d.ts +98 -0
  19. package/dist/baseline/change-impact-analyzer.js +592 -0
  20. package/dist/baseline/comparator.d.ts +64 -0
  21. package/dist/baseline/comparator.js +916 -0
  22. package/dist/baseline/confidence.d.ts +55 -0
  23. package/dist/baseline/confidence.js +122 -0
  24. package/dist/baseline/converter.d.ts +61 -0
  25. package/dist/baseline/converter.js +585 -0
  26. package/dist/baseline/dependency-analyzer.d.ts +89 -0
  27. package/dist/baseline/dependency-analyzer.js +567 -0
  28. package/dist/baseline/deprecation-tracker.d.ts +133 -0
  29. package/dist/baseline/deprecation-tracker.js +322 -0
  30. package/dist/baseline/diff.d.ts +55 -0
  31. package/dist/baseline/diff.js +1584 -0
  32. package/dist/baseline/documentation-scorer.d.ts +205 -0
  33. package/dist/baseline/documentation-scorer.js +466 -0
  34. package/dist/baseline/embeddings.d.ts +118 -0
  35. package/dist/baseline/embeddings.js +251 -0
  36. package/dist/baseline/error-analyzer.d.ts +198 -0
  37. package/dist/baseline/error-analyzer.js +721 -0
  38. package/dist/baseline/evaluation/evaluator.d.ts +42 -0
  39. package/dist/baseline/evaluation/evaluator.js +323 -0
  40. package/dist/baseline/evaluation/expanded-dataset.d.ts +45 -0
  41. package/dist/baseline/evaluation/expanded-dataset.js +1164 -0
  42. package/dist/baseline/evaluation/golden-dataset.d.ts +58 -0
  43. package/dist/baseline/evaluation/golden-dataset.js +717 -0
  44. package/dist/baseline/evaluation/index.d.ts +15 -0
  45. package/dist/baseline/evaluation/index.js +15 -0
  46. package/dist/baseline/evaluation/types.d.ts +186 -0
  47. package/dist/baseline/evaluation/types.js +8 -0
  48. package/dist/baseline/external-dependency-detector.d.ts +181 -0
  49. package/dist/baseline/external-dependency-detector.js +524 -0
  50. package/dist/baseline/golden-output.d.ts +162 -0
  51. package/dist/baseline/golden-output.js +636 -0
  52. package/dist/baseline/health-scorer.d.ts +174 -0
  53. package/dist/baseline/health-scorer.js +451 -0
  54. package/dist/baseline/incremental-checker.d.ts +97 -0
  55. package/dist/baseline/incremental-checker.js +174 -0
  56. package/dist/baseline/index.d.ts +31 -0
  57. package/dist/baseline/index.js +42 -0
  58. package/dist/baseline/migration-generator.d.ts +137 -0
  59. package/dist/baseline/migration-generator.js +554 -0
  60. package/dist/baseline/migrations.d.ts +60 -0
  61. package/dist/baseline/migrations.js +197 -0
  62. package/dist/baseline/performance-tracker.d.ts +214 -0
  63. package/dist/baseline/performance-tracker.js +577 -0
  64. package/dist/baseline/pr-comment-generator.d.ts +117 -0
  65. package/dist/baseline/pr-comment-generator.js +546 -0
  66. package/dist/baseline/response-fingerprint.d.ts +127 -0
  67. package/dist/baseline/response-fingerprint.js +728 -0
  68. package/dist/baseline/response-schema-tracker.d.ts +129 -0
  69. package/dist/baseline/response-schema-tracker.js +420 -0
  70. package/dist/baseline/risk-scorer.d.ts +54 -0
  71. package/dist/baseline/risk-scorer.js +434 -0
  72. package/dist/baseline/saver.d.ts +89 -0
  73. package/dist/baseline/saver.js +554 -0
  74. package/dist/baseline/scenario-generator.d.ts +151 -0
  75. package/dist/baseline/scenario-generator.js +905 -0
  76. package/dist/baseline/schema-compare.d.ts +86 -0
  77. package/dist/baseline/schema-compare.js +557 -0
  78. package/dist/baseline/schema-evolution.d.ts +189 -0
  79. package/dist/baseline/schema-evolution.js +467 -0
  80. package/dist/baseline/semantic.d.ts +203 -0
  81. package/dist/baseline/semantic.js +908 -0
  82. package/dist/baseline/synonyms.d.ts +60 -0
  83. package/dist/baseline/synonyms.js +386 -0
  84. package/dist/baseline/telemetry.d.ts +165 -0
  85. package/dist/baseline/telemetry.js +294 -0
  86. package/dist/baseline/test-pruner.d.ts +120 -0
  87. package/dist/baseline/test-pruner.js +387 -0
  88. package/dist/baseline/types.d.ts +449 -0
  89. package/dist/baseline/types.js +5 -0
  90. package/dist/baseline/version.d.ts +138 -0
  91. package/dist/baseline/version.js +206 -0
  92. package/dist/cache/index.d.ts +5 -0
  93. package/dist/cache/index.js +5 -0
  94. package/dist/cache/response-cache.d.ts +151 -0
  95. package/dist/cache/response-cache.js +287 -0
  96. package/dist/ci/index.d.ts +60 -0
  97. package/dist/ci/index.js +342 -0
  98. package/dist/cli/commands/auth.d.ts +12 -0
  99. package/dist/cli/commands/auth.js +352 -0
  100. package/dist/cli/commands/badge.d.ts +3 -0
  101. package/dist/cli/commands/badge.js +74 -0
  102. package/dist/cli/commands/baseline-accept.d.ts +15 -0
  103. package/dist/cli/commands/baseline-accept.js +178 -0
  104. package/dist/cli/commands/baseline-migrate.d.ts +12 -0
  105. package/dist/cli/commands/baseline-migrate.js +164 -0
  106. package/dist/cli/commands/baseline.d.ts +14 -0
  107. package/dist/cli/commands/baseline.js +449 -0
  108. package/dist/cli/commands/beta.d.ts +10 -0
  109. package/dist/cli/commands/beta.js +231 -0
  110. package/dist/cli/commands/check.d.ts +11 -0
  111. package/dist/cli/commands/check.js +820 -0
  112. package/dist/cli/commands/cloud/badge.d.ts +3 -0
  113. package/dist/cli/commands/cloud/badge.js +74 -0
  114. package/dist/cli/commands/cloud/diff.d.ts +6 -0
  115. package/dist/cli/commands/cloud/diff.js +79 -0
  116. package/dist/cli/commands/cloud/history.d.ts +6 -0
  117. package/dist/cli/commands/cloud/history.js +102 -0
  118. package/dist/cli/commands/cloud/link.d.ts +9 -0
  119. package/dist/cli/commands/cloud/link.js +119 -0
  120. package/dist/cli/commands/cloud/login.d.ts +7 -0
  121. package/dist/cli/commands/cloud/login.js +499 -0
  122. package/dist/cli/commands/cloud/projects.d.ts +6 -0
  123. package/dist/cli/commands/cloud/projects.js +44 -0
  124. package/dist/cli/commands/cloud/shared.d.ts +7 -0
  125. package/dist/cli/commands/cloud/shared.js +42 -0
  126. package/dist/cli/commands/cloud/teams.d.ts +8 -0
  127. package/dist/cli/commands/cloud/teams.js +169 -0
  128. package/dist/cli/commands/cloud/upload.d.ts +8 -0
  129. package/dist/cli/commands/cloud/upload.js +181 -0
  130. package/dist/cli/commands/contract.d.ts +11 -0
  131. package/dist/cli/commands/contract.js +280 -0
  132. package/dist/cli/commands/discover.d.ts +3 -0
  133. package/dist/cli/commands/discover.js +82 -0
  134. package/dist/cli/commands/eval.d.ts +9 -0
  135. package/dist/cli/commands/eval.js +187 -0
  136. package/dist/cli/commands/explore.d.ts +11 -0
  137. package/dist/cli/commands/explore.js +437 -0
  138. package/dist/cli/commands/feedback.d.ts +9 -0
  139. package/dist/cli/commands/feedback.js +174 -0
  140. package/dist/cli/commands/golden.d.ts +12 -0
  141. package/dist/cli/commands/golden.js +407 -0
  142. package/dist/cli/commands/history.d.ts +10 -0
  143. package/dist/cli/commands/history.js +202 -0
  144. package/dist/cli/commands/init.d.ts +9 -0
  145. package/dist/cli/commands/init.js +219 -0
  146. package/dist/cli/commands/interview.d.ts +3 -0
  147. package/dist/cli/commands/interview.js +903 -0
  148. package/dist/cli/commands/link.d.ts +10 -0
  149. package/dist/cli/commands/link.js +169 -0
  150. package/dist/cli/commands/login.d.ts +7 -0
  151. package/dist/cli/commands/login.js +499 -0
  152. package/dist/cli/commands/preset.d.ts +33 -0
  153. package/dist/cli/commands/preset.js +297 -0
  154. package/dist/cli/commands/profile.d.ts +33 -0
  155. package/dist/cli/commands/profile.js +286 -0
  156. package/dist/cli/commands/registry.d.ts +11 -0
  157. package/dist/cli/commands/registry.js +146 -0
  158. package/dist/cli/commands/shared.d.ts +79 -0
  159. package/dist/cli/commands/shared.js +196 -0
  160. package/dist/cli/commands/teams.d.ts +8 -0
  161. package/dist/cli/commands/teams.js +169 -0
  162. package/dist/cli/commands/test.d.ts +9 -0
  163. package/dist/cli/commands/test.js +500 -0
  164. package/dist/cli/commands/upload.d.ts +8 -0
  165. package/dist/cli/commands/upload.js +223 -0
  166. package/dist/cli/commands/validate-config.d.ts +6 -0
  167. package/dist/cli/commands/validate-config.js +35 -0
  168. package/dist/cli/commands/verify.d.ts +11 -0
  169. package/dist/cli/commands/verify.js +283 -0
  170. package/dist/cli/commands/watch.d.ts +12 -0
  171. package/dist/cli/commands/watch.js +253 -0
  172. package/dist/cli/index.d.ts +3 -0
  173. package/dist/cli/index.js +178 -0
  174. package/dist/cli/interactive.d.ts +47 -0
  175. package/dist/cli/interactive.js +216 -0
  176. package/dist/cli/output/terminal-reporter.d.ts +19 -0
  177. package/dist/cli/output/terminal-reporter.js +104 -0
  178. package/dist/cli/output.d.ts +226 -0
  179. package/dist/cli/output.js +438 -0
  180. package/dist/cli/utils/env.d.ts +5 -0
  181. package/dist/cli/utils/env.js +14 -0
  182. package/dist/cli/utils/progress.d.ts +59 -0
  183. package/dist/cli/utils/progress.js +206 -0
  184. package/dist/cli/utils/server-context.d.ts +10 -0
  185. package/dist/cli/utils/server-context.js +36 -0
  186. package/dist/cloud/auth.d.ts +144 -0
  187. package/dist/cloud/auth.js +374 -0
  188. package/dist/cloud/client.d.ts +24 -0
  189. package/dist/cloud/client.js +65 -0
  190. package/dist/cloud/http-client.d.ts +38 -0
  191. package/dist/cloud/http-client.js +215 -0
  192. package/dist/cloud/index.d.ts +23 -0
  193. package/dist/cloud/index.js +25 -0
  194. package/dist/cloud/mock-client.d.ts +107 -0
  195. package/dist/cloud/mock-client.js +545 -0
  196. package/dist/cloud/types.d.ts +515 -0
  197. package/dist/cloud/types.js +15 -0
  198. package/dist/config/defaults.d.ts +160 -0
  199. package/dist/config/defaults.js +169 -0
  200. package/dist/config/loader.d.ts +24 -0
  201. package/dist/config/loader.js +122 -0
  202. package/dist/config/template.d.ts +42 -0
  203. package/dist/config/template.js +647 -0
  204. package/dist/config/validator.d.ts +2112 -0
  205. package/dist/config/validator.js +658 -0
  206. package/dist/constants/cloud.d.ts +107 -0
  207. package/dist/constants/cloud.js +110 -0
  208. package/dist/constants/core.d.ts +521 -0
  209. package/dist/constants/core.js +556 -0
  210. package/dist/constants/testing.d.ts +1283 -0
  211. package/dist/constants/testing.js +1568 -0
  212. package/dist/constants.d.ts +10 -0
  213. package/dist/constants.js +10 -0
  214. package/dist/contract/index.d.ts +6 -0
  215. package/dist/contract/index.js +5 -0
  216. package/dist/contract/validator.d.ts +177 -0
  217. package/dist/contract/validator.js +574 -0
  218. package/dist/cost/index.d.ts +6 -0
  219. package/dist/cost/index.js +5 -0
  220. package/dist/cost/tracker.d.ts +134 -0
  221. package/dist/cost/tracker.js +313 -0
  222. package/dist/discovery/discovery.d.ts +16 -0
  223. package/dist/discovery/discovery.js +173 -0
  224. package/dist/discovery/types.d.ts +51 -0
  225. package/dist/discovery/types.js +2 -0
  226. package/dist/docs/agents.d.ts +3 -0
  227. package/dist/docs/agents.js +995 -0
  228. package/dist/docs/contract.d.ts +51 -0
  229. package/dist/docs/contract.js +1681 -0
  230. package/dist/docs/generator.d.ts +4 -0
  231. package/dist/docs/generator.js +4 -0
  232. package/dist/docs/html-reporter.d.ts +9 -0
  233. package/dist/docs/html-reporter.js +757 -0
  234. package/dist/docs/index.d.ts +10 -0
  235. package/dist/docs/index.js +11 -0
  236. package/dist/docs/junit-reporter.d.ts +18 -0
  237. package/dist/docs/junit-reporter.js +210 -0
  238. package/dist/docs/report.d.ts +14 -0
  239. package/dist/docs/report.js +44 -0
  240. package/dist/docs/sarif-reporter.d.ts +19 -0
  241. package/dist/docs/sarif-reporter.js +335 -0
  242. package/dist/docs/shared.d.ts +35 -0
  243. package/dist/docs/shared.js +162 -0
  244. package/dist/docs/templates.d.ts +12 -0
  245. package/dist/docs/templates.js +76 -0
  246. package/dist/errors/index.d.ts +6 -0
  247. package/dist/errors/index.js +6 -0
  248. package/dist/errors/retry.d.ts +92 -0
  249. package/dist/errors/retry.js +323 -0
  250. package/dist/errors/types.d.ts +321 -0
  251. package/dist/errors/types.js +584 -0
  252. package/dist/index.d.ts +32 -0
  253. package/dist/index.js +32 -0
  254. package/dist/interview/dependency-resolver.d.ts +11 -0
  255. package/dist/interview/dependency-resolver.js +32 -0
  256. package/dist/interview/interviewer.d.ts +232 -0
  257. package/dist/interview/interviewer.js +1939 -0
  258. package/dist/interview/mock-response-generator.d.ts +7 -0
  259. package/dist/interview/mock-response-generator.js +102 -0
  260. package/dist/interview/orchestrator.d.ts +237 -0
  261. package/dist/interview/orchestrator.js +1296 -0
  262. package/dist/interview/rate-limiter.d.ts +15 -0
  263. package/dist/interview/rate-limiter.js +55 -0
  264. package/dist/interview/response-validator.d.ts +10 -0
  265. package/dist/interview/response-validator.js +132 -0
  266. package/dist/interview/schema-inferrer.d.ts +8 -0
  267. package/dist/interview/schema-inferrer.js +71 -0
  268. package/dist/interview/schema-test-generator.d.ts +71 -0
  269. package/dist/interview/schema-test-generator.js +834 -0
  270. package/dist/interview/smart-value-generator.d.ts +155 -0
  271. package/dist/interview/smart-value-generator.js +554 -0
  272. package/dist/interview/stateful-test-runner.d.ts +19 -0
  273. package/dist/interview/stateful-test-runner.js +106 -0
  274. package/dist/interview/types.d.ts +561 -0
  275. package/dist/interview/types.js +2 -0
  276. package/dist/llm/anthropic.d.ts +41 -0
  277. package/dist/llm/anthropic.js +355 -0
  278. package/dist/llm/client.d.ts +123 -0
  279. package/dist/llm/client.js +42 -0
  280. package/dist/llm/factory.d.ts +38 -0
  281. package/dist/llm/factory.js +145 -0
  282. package/dist/llm/fallback.d.ts +140 -0
  283. package/dist/llm/fallback.js +379 -0
  284. package/dist/llm/index.d.ts +18 -0
  285. package/dist/llm/index.js +15 -0
  286. package/dist/llm/ollama.d.ts +37 -0
  287. package/dist/llm/ollama.js +330 -0
  288. package/dist/llm/openai.d.ts +25 -0
  289. package/dist/llm/openai.js +320 -0
  290. package/dist/llm/token-budget.d.ts +161 -0
  291. package/dist/llm/token-budget.js +395 -0
  292. package/dist/logging/logger.d.ts +70 -0
  293. package/dist/logging/logger.js +130 -0
  294. package/dist/metrics/collector.d.ts +106 -0
  295. package/dist/metrics/collector.js +547 -0
  296. package/dist/metrics/index.d.ts +7 -0
  297. package/dist/metrics/index.js +7 -0
  298. package/dist/metrics/prometheus.d.ts +20 -0
  299. package/dist/metrics/prometheus.js +241 -0
  300. package/dist/metrics/types.d.ts +209 -0
  301. package/dist/metrics/types.js +5 -0
  302. package/dist/persona/builtins.d.ts +54 -0
  303. package/dist/persona/builtins.js +219 -0
  304. package/dist/persona/index.d.ts +8 -0
  305. package/dist/persona/index.js +8 -0
  306. package/dist/persona/loader.d.ts +30 -0
  307. package/dist/persona/loader.js +190 -0
  308. package/dist/persona/types.d.ts +144 -0
  309. package/dist/persona/types.js +5 -0
  310. package/dist/persona/validation.d.ts +94 -0
  311. package/dist/persona/validation.js +332 -0
  312. package/dist/prompts/index.d.ts +5 -0
  313. package/dist/prompts/index.js +5 -0
  314. package/dist/prompts/templates.d.ts +180 -0
  315. package/dist/prompts/templates.js +431 -0
  316. package/dist/registry/client.d.ts +49 -0
  317. package/dist/registry/client.js +191 -0
  318. package/dist/registry/index.d.ts +7 -0
  319. package/dist/registry/index.js +6 -0
  320. package/dist/registry/types.d.ts +140 -0
  321. package/dist/registry/types.js +6 -0
  322. package/dist/scenarios/evaluator.d.ts +43 -0
  323. package/dist/scenarios/evaluator.js +206 -0
  324. package/dist/scenarios/index.d.ts +10 -0
  325. package/dist/scenarios/index.js +9 -0
  326. package/dist/scenarios/loader.d.ts +20 -0
  327. package/dist/scenarios/loader.js +285 -0
  328. package/dist/scenarios/types.d.ts +153 -0
  329. package/dist/scenarios/types.js +8 -0
  330. package/dist/security/index.d.ts +17 -0
  331. package/dist/security/index.js +18 -0
  332. package/dist/security/payloads.d.ts +61 -0
  333. package/dist/security/payloads.js +268 -0
  334. package/dist/security/security-tester.d.ts +42 -0
  335. package/dist/security/security-tester.js +582 -0
  336. package/dist/security/types.d.ts +166 -0
  337. package/dist/security/types.js +8 -0
  338. package/dist/transport/base-transport.d.ts +59 -0
  339. package/dist/transport/base-transport.js +38 -0
  340. package/dist/transport/http-transport.d.ts +67 -0
  341. package/dist/transport/http-transport.js +238 -0
  342. package/dist/transport/mcp-client.d.ts +141 -0
  343. package/dist/transport/mcp-client.js +496 -0
  344. package/dist/transport/sse-transport.d.ts +88 -0
  345. package/dist/transport/sse-transport.js +316 -0
  346. package/dist/transport/stdio-transport.d.ts +43 -0
  347. package/dist/transport/stdio-transport.js +238 -0
  348. package/dist/transport/types.d.ts +125 -0
  349. package/dist/transport/types.js +16 -0
  350. package/dist/utils/concurrency.d.ts +123 -0
  351. package/dist/utils/concurrency.js +213 -0
  352. package/dist/utils/formatters.d.ts +16 -0
  353. package/dist/utils/formatters.js +37 -0
  354. package/dist/utils/index.d.ts +8 -0
  355. package/dist/utils/index.js +8 -0
  356. package/dist/utils/jsonpath.d.ts +87 -0
  357. package/dist/utils/jsonpath.js +326 -0
  358. package/dist/utils/markdown.d.ts +113 -0
  359. package/dist/utils/markdown.js +265 -0
  360. package/dist/utils/network.d.ts +14 -0
  361. package/dist/utils/network.js +17 -0
  362. package/dist/utils/sanitize.d.ts +92 -0
  363. package/dist/utils/sanitize.js +191 -0
  364. package/dist/utils/semantic.d.ts +194 -0
  365. package/dist/utils/semantic.js +1051 -0
  366. package/dist/utils/smart-truncate.d.ts +94 -0
  367. package/dist/utils/smart-truncate.js +361 -0
  368. package/dist/utils/timeout.d.ts +153 -0
  369. package/dist/utils/timeout.js +205 -0
  370. package/dist/utils/yaml-parser.d.ts +58 -0
  371. package/dist/utils/yaml-parser.js +86 -0
  372. package/dist/validation/index.d.ts +32 -0
  373. package/dist/validation/index.js +32 -0
  374. package/dist/validation/semantic-test-generator.d.ts +50 -0
  375. package/dist/validation/semantic-test-generator.js +176 -0
  376. package/dist/validation/semantic-types.d.ts +66 -0
  377. package/dist/validation/semantic-types.js +94 -0
  378. package/dist/validation/semantic-validator.d.ts +38 -0
  379. package/dist/validation/semantic-validator.js +340 -0
  380. package/dist/verification/index.d.ts +6 -0
  381. package/dist/verification/index.js +5 -0
  382. package/dist/verification/types.d.ts +133 -0
  383. package/dist/verification/types.js +5 -0
  384. package/dist/verification/verifier.d.ts +30 -0
  385. package/dist/verification/verifier.js +309 -0
  386. package/dist/version.d.ts +19 -0
  387. package/dist/version.js +48 -0
  388. package/dist/workflow/auto-generator.d.ts +27 -0
  389. package/dist/workflow/auto-generator.js +513 -0
  390. package/dist/workflow/discovery.d.ts +40 -0
  391. package/dist/workflow/discovery.js +195 -0
  392. package/dist/workflow/executor.d.ts +82 -0
  393. package/dist/workflow/executor.js +611 -0
  394. package/dist/workflow/index.d.ts +10 -0
  395. package/dist/workflow/index.js +10 -0
  396. package/dist/workflow/loader.d.ts +24 -0
  397. package/dist/workflow/loader.js +194 -0
  398. package/dist/workflow/state-tracker.d.ts +98 -0
  399. package/dist/workflow/state-tracker.js +424 -0
  400. package/dist/workflow/types.d.ts +337 -0
  401. package/dist/workflow/types.js +5 -0
  402. package/package.json +94 -0
  403. package/schemas/bellwether-check.schema.json +651 -0
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Regression Risk Scorer.
3
+ *
4
+ * Calculates weighted risk scores for detected changes to help prioritize fixes.
5
+ * Considers multiple factors: breaking changes, tool importance, error rates,
6
+ * performance regressions, and security posture.
7
+ */
8
+ import { REGRESSION_RISK } from '../constants.js';
9
+ /**
10
+ * Calculate regression risk score from a behavioral diff.
11
+ */
12
+ export function calculateRiskScore(diff) {
13
+ const factors = [];
14
+ // Factor 1: Breaking Change Severity
15
+ const breakingFactor = scoreBreakingChanges(diff);
16
+ factors.push(breakingFactor);
17
+ // Factor 2: Affected Tool Importance
18
+ const importanceFactor = scoreToolImportance(diff);
19
+ factors.push(importanceFactor);
20
+ // Factor 3: Error Rate Delta
21
+ const errorFactor = scoreErrorDelta(diff);
22
+ factors.push(errorFactor);
23
+ // Factor 4: Performance Regression
24
+ const performanceFactor = scorePerformanceRegression(diff);
25
+ factors.push(performanceFactor);
26
+ // Factor 5: Security Posture
27
+ const securityFactor = scoreSecurityChange(diff);
28
+ factors.push(securityFactor);
29
+ // Calculate overall score
30
+ const overallScore = Math.round(factors.reduce((sum, f) => sum + f.weightedScore, 0));
31
+ // Determine risk level
32
+ const level = getRiskLevel(overallScore);
33
+ // Generate recommendation
34
+ const recommendation = generateRecommendation(overallScore, factors, diff);
35
+ // Build change summary
36
+ const changeSummary = {
37
+ breaking: diff.breakingCount,
38
+ warning: diff.warningCount,
39
+ info: diff.infoCount,
40
+ toolsRemoved: diff.toolsRemoved.length,
41
+ toolsAdded: diff.toolsAdded.length,
42
+ toolsModified: diff.toolsModified.length,
43
+ };
44
+ return {
45
+ score: overallScore,
46
+ level,
47
+ factors,
48
+ recommendation,
49
+ changeSummary,
50
+ };
51
+ }
52
+ /**
53
+ * Score breaking changes based on type and count.
54
+ */
55
+ function scoreBreakingChanges(diff) {
56
+ const weight = REGRESSION_RISK.WEIGHTS.breakingChangeSeverity;
57
+ let score = 0;
58
+ const details = [];
59
+ // Score removed tools (most severe)
60
+ if (diff.toolsRemoved.length > 0) {
61
+ score = Math.max(score, REGRESSION_RISK.BREAKING_SCORES.toolRemoved);
62
+ details.push(`${diff.toolsRemoved.length} tool(s) removed`);
63
+ }
64
+ // Score breaking behavior changes
65
+ for (const change of diff.behaviorChanges) {
66
+ if (change.severity === 'breaking') {
67
+ const changeScore = getChangeScore(change);
68
+ score = Math.max(score, changeScore);
69
+ details.push(`${change.aspect}: ${change.description.slice(0, 50)}`);
70
+ }
71
+ }
72
+ // Compound score based on count
73
+ if (diff.breakingCount > 1) {
74
+ score = Math.min(100, score + (diff.breakingCount - 1) * 10);
75
+ }
76
+ return {
77
+ name: 'Breaking Changes',
78
+ weight,
79
+ score,
80
+ weightedScore: score * weight,
81
+ details: details.length > 0 ? details.join('; ') : 'No breaking changes',
82
+ };
83
+ }
84
+ /**
85
+ * Get score for a specific change type.
86
+ */
87
+ function getChangeScore(change) {
88
+ const description = change.description.toLowerCase();
89
+ if (description.includes('removed') && description.includes('required')) {
90
+ return REGRESSION_RISK.BREAKING_SCORES.requiredParamRemoved;
91
+ }
92
+ if (description.includes('type') && description.includes('changed')) {
93
+ return REGRESSION_RISK.BREAKING_SCORES.typeChanged;
94
+ }
95
+ if (description.includes('enum') && description.includes('removed')) {
96
+ return REGRESSION_RISK.BREAKING_SCORES.enumValueRemoved;
97
+ }
98
+ if (description.includes('constraint') && description.includes('tightened')) {
99
+ return REGRESSION_RISK.BREAKING_SCORES.constraintTightened;
100
+ }
101
+ if (description.includes('required') && description.includes('added')) {
102
+ return REGRESSION_RISK.BREAKING_SCORES.requiredParamAdded;
103
+ }
104
+ // Default score for unrecognized breaking changes
105
+ return 50;
106
+ }
107
+ /**
108
+ * Score based on importance of affected tools.
109
+ */
110
+ function scoreToolImportance(diff) {
111
+ const weight = REGRESSION_RISK.WEIGHTS.toolImportance;
112
+ let score = 0;
113
+ const details = [];
114
+ // Analyze affected tools
115
+ const affectedTools = [
116
+ ...diff.toolsRemoved,
117
+ ...diff.toolsModified.map(t => t.tool),
118
+ ];
119
+ let highImportanceCount = 0;
120
+ let lowImportanceCount = 0;
121
+ for (const toolDiff of diff.toolsModified) {
122
+ const description = toolDiff.previous?.description || toolDiff.current?.description || '';
123
+ // Check for high importance indicators
124
+ const isHighImportance = REGRESSION_RISK.IMPORTANCE_PATTERNS.highFrequency.some(pattern => pattern.test(description));
125
+ // Check for low importance indicators
126
+ const isLowImportance = REGRESSION_RISK.IMPORTANCE_PATTERNS.lowFrequency.some(pattern => pattern.test(description));
127
+ if (isHighImportance) {
128
+ highImportanceCount++;
129
+ }
130
+ else if (isLowImportance) {
131
+ lowImportanceCount++;
132
+ }
133
+ }
134
+ // Calculate score based on importance distribution
135
+ const totalAffected = affectedTools.length;
136
+ if (totalAffected > 0) {
137
+ const importanceRatio = highImportanceCount / totalAffected;
138
+ score = Math.round(importanceRatio * 100);
139
+ if (highImportanceCount > 0) {
140
+ details.push(`${highImportanceCount} high-importance tool(s) affected`);
141
+ }
142
+ if (lowImportanceCount > 0 && lowImportanceCount === totalAffected) {
143
+ score = Math.max(0, score - 20);
144
+ details.push('Only low-importance tools affected');
145
+ }
146
+ }
147
+ // Minimum score if there are any breaking changes in any tools
148
+ if (diff.breakingCount > 0 && score < 30) {
149
+ score = 30;
150
+ }
151
+ return {
152
+ name: 'Tool Importance',
153
+ weight,
154
+ score,
155
+ weightedScore: score * weight,
156
+ details: details.length > 0 ? details.join('; ') : 'No high-importance tools affected',
157
+ };
158
+ }
159
+ /**
160
+ * Score based on error rate changes.
161
+ */
162
+ function scoreErrorDelta(diff) {
163
+ const weight = REGRESSION_RISK.WEIGHTS.errorRateDelta;
164
+ let score = 0;
165
+ const details = [];
166
+ // Check error trend report if available
167
+ if (diff.errorTrendReport) {
168
+ const report = diff.errorTrendReport;
169
+ // Score based on new error categories
170
+ if (report.newCategories.length > 0) {
171
+ score = Math.max(score, 70);
172
+ details.push(`${report.newCategories.length} new error category(s)`);
173
+ }
174
+ // Score based on increasing error rates
175
+ for (const trend of report.trends) {
176
+ if (trend.trend === 'increasing') {
177
+ if (trend.changePercent >= REGRESSION_RISK.ERROR_RATE.CRITICAL_INCREASE) {
178
+ score = Math.max(score, 90);
179
+ details.push(`${trend.category}: +${Math.round(trend.changePercent)}%`);
180
+ }
181
+ else if (trend.changePercent >= REGRESSION_RISK.ERROR_RATE.SIGNIFICANT_INCREASE) {
182
+ score = Math.max(score, 60);
183
+ }
184
+ }
185
+ }
186
+ }
187
+ // Fallback to behavior changes for error patterns
188
+ const errorChanges = diff.behaviorChanges.filter(c => c.aspect === 'error_pattern');
189
+ if (errorChanges.length > 0 && score === 0) {
190
+ score = REGRESSION_RISK.ERROR_RATE.BASE_SCORE;
191
+ details.push(`${errorChanges.length} error pattern change(s)`);
192
+ }
193
+ return {
194
+ name: 'Error Rate',
195
+ weight,
196
+ score,
197
+ weightedScore: score * weight,
198
+ details: details.length > 0 ? details.join('; ') : 'No error rate changes',
199
+ };
200
+ }
201
+ /**
202
+ * Score based on performance regressions.
203
+ */
204
+ function scorePerformanceRegression(diff) {
205
+ const weight = REGRESSION_RISK.WEIGHTS.performanceRegression;
206
+ let score = 0;
207
+ const details = [];
208
+ if (!diff.performanceReport) {
209
+ return {
210
+ name: 'Performance',
211
+ weight,
212
+ score: 0,
213
+ weightedScore: 0,
214
+ details: 'No performance data available',
215
+ };
216
+ }
217
+ const report = diff.performanceReport;
218
+ if (!report.hasRegressions) {
219
+ if (report.improvementCount > 0) {
220
+ details.push(`${report.improvementCount} tool(s) improved`);
221
+ }
222
+ return {
223
+ name: 'Performance',
224
+ weight,
225
+ score: 0,
226
+ weightedScore: 0,
227
+ details: details.length > 0 ? details.join('; ') : 'No performance regressions',
228
+ };
229
+ }
230
+ // Score each regression
231
+ for (const regression of report.regressions) {
232
+ if (!regression.exceedsThreshold)
233
+ continue;
234
+ const percent = regression.regressionPercent;
235
+ let regressionScore;
236
+ if (percent >= REGRESSION_RISK.PERFORMANCE.CRITICAL_REGRESSION) {
237
+ regressionScore = REGRESSION_RISK.PERFORMANCE.SCORES.critical;
238
+ details.push(`${regression.toolName}: +${Math.round(percent)}% (critical)`);
239
+ }
240
+ else if (percent >= REGRESSION_RISK.PERFORMANCE.MAJOR_REGRESSION) {
241
+ regressionScore = REGRESSION_RISK.PERFORMANCE.SCORES.major;
242
+ details.push(`${regression.toolName}: +${Math.round(percent)}% (major)`);
243
+ }
244
+ else {
245
+ regressionScore = REGRESSION_RISK.PERFORMANCE.SCORES.minor;
246
+ }
247
+ score = Math.max(score, regressionScore);
248
+ }
249
+ // Compound for multiple regressions
250
+ if (report.regressionCount > 1) {
251
+ score = Math.min(100, score + (report.regressionCount - 1) * 5);
252
+ }
253
+ return {
254
+ name: 'Performance',
255
+ weight,
256
+ score,
257
+ weightedScore: score * weight,
258
+ details: details.length > 0 ? details.join('; ') : `${report.regressionCount} regression(s)`,
259
+ };
260
+ }
261
+ /**
262
+ * Score based on security posture changes.
263
+ */
264
+ function scoreSecurityChange(diff) {
265
+ const weight = REGRESSION_RISK.WEIGHTS.securityPosture;
266
+ let score = 0;
267
+ const details = [];
268
+ if (!diff.securityReport) {
269
+ return {
270
+ name: 'Security',
271
+ weight,
272
+ score: 0,
273
+ weightedScore: 0,
274
+ details: 'No security testing data',
275
+ };
276
+ }
277
+ const report = diff.securityReport;
278
+ // Score new vulnerabilities
279
+ if (report.newFindings && report.newFindings.length > 0) {
280
+ const criticalCount = report.newFindings.filter(f => f.riskLevel === 'critical').length;
281
+ const highCount = report.newFindings.filter(f => f.riskLevel === 'high').length;
282
+ if (criticalCount > 0) {
283
+ score = REGRESSION_RISK.SECURITY.NEW_VULNERABILITY;
284
+ details.push(`${criticalCount} new critical vulnerability(ies)`);
285
+ }
286
+ else if (highCount > 0) {
287
+ score = Math.max(score, 80);
288
+ details.push(`${highCount} new high severity finding(s)`);
289
+ }
290
+ else {
291
+ score = Math.max(score, 50);
292
+ details.push(`${report.newFindings.length} new security finding(s)`);
293
+ }
294
+ }
295
+ // Credit resolved vulnerabilities
296
+ if (report.resolvedFindings && report.resolvedFindings.length > 0) {
297
+ score = Math.max(0, score + REGRESSION_RISK.SECURITY.RESOLVED_VULNERABILITY);
298
+ details.push(`${report.resolvedFindings.length} resolved`);
299
+ }
300
+ // Score severity increases
301
+ if (report.riskScoreChange && report.riskScoreChange > 0) {
302
+ score = Math.max(score, REGRESSION_RISK.SECURITY.SEVERITY_INCREASE);
303
+ details.push('Overall security risk score increased');
304
+ }
305
+ return {
306
+ name: 'Security',
307
+ weight,
308
+ score: Math.max(0, score),
309
+ weightedScore: Math.max(0, score) * weight,
310
+ details: details.length > 0 ? details.join('; ') : 'No security changes',
311
+ };
312
+ }
313
+ /**
314
+ * Get risk level from score.
315
+ */
316
+ function getRiskLevel(score) {
317
+ if (score >= REGRESSION_RISK.LEVEL_THRESHOLDS.critical)
318
+ return 'critical';
319
+ if (score >= REGRESSION_RISK.LEVEL_THRESHOLDS.high)
320
+ return 'high';
321
+ if (score >= REGRESSION_RISK.LEVEL_THRESHOLDS.medium)
322
+ return 'medium';
323
+ if (score >= REGRESSION_RISK.LEVEL_THRESHOLDS.low)
324
+ return 'low';
325
+ return 'info';
326
+ }
327
+ /**
328
+ * Generate recommendation based on risk analysis.
329
+ */
330
+ function generateRecommendation(score, factors, diff) {
331
+ const level = getRiskLevel(score);
332
+ // Find highest contributing factor
333
+ const sortedFactors = [...factors].sort((a, b) => b.weightedScore - a.weightedScore);
334
+ const topFactor = sortedFactors[0];
335
+ switch (level) {
336
+ case 'critical':
337
+ if (diff.toolsRemoved.length > 0) {
338
+ return 'CRITICAL: Tools were removed. Ensure consumers are migrated before releasing.';
339
+ }
340
+ if (topFactor.name === 'Security') {
341
+ return 'CRITICAL: Security vulnerabilities introduced. Address before any deployment.';
342
+ }
343
+ return 'CRITICAL: Major breaking changes detected. Requires thorough review and migration plan.';
344
+ case 'high':
345
+ if (topFactor.name === 'Performance') {
346
+ return 'HIGH RISK: Significant performance regressions. Profile and optimize before release.';
347
+ }
348
+ if (topFactor.name === 'Error Rate') {
349
+ return 'HIGH RISK: Error rates increased substantially. Investigate new failure modes.';
350
+ }
351
+ return 'HIGH RISK: Multiple breaking changes. Create deprecation notices and migration guides.';
352
+ case 'medium':
353
+ if (topFactor.name === 'Tool Importance') {
354
+ return 'MEDIUM RISK: Changes affect important tools. Stage release with deprecation warnings.';
355
+ }
356
+ return 'MEDIUM RISK: Notable changes detected. Test with key consumers before release.';
357
+ case 'low':
358
+ if (diff.warningCount > 0) {
359
+ return 'LOW RISK: Minor changes with warnings. Review before release but likely safe.';
360
+ }
361
+ return 'LOW RISK: Changes are minor. Standard release process should be sufficient.';
362
+ default:
363
+ if (diff.infoCount > 0) {
364
+ return 'MINIMAL RISK: Only informational changes. Safe to release.';
365
+ }
366
+ return 'NO RISK: No significant changes detected.';
367
+ }
368
+ }
369
+ /**
370
+ * Generate markdown report for risk score.
371
+ */
372
+ export function generateRiskScoreMarkdown(riskScore) {
373
+ const lines = [];
374
+ // Risk level badge
375
+ const levelEmoji = {
376
+ critical: '🔴',
377
+ high: '🟠',
378
+ medium: '🟡',
379
+ low: '🟢',
380
+ info: '⚪',
381
+ };
382
+ lines.push('## Regression Risk Assessment');
383
+ lines.push('');
384
+ lines.push(`**Risk Level: ${levelEmoji[riskScore.level]} ${riskScore.level.toUpperCase()}** (Score: ${riskScore.score}/100)`);
385
+ lines.push('');
386
+ lines.push(`> ${riskScore.recommendation}`);
387
+ lines.push('');
388
+ // Factor breakdown
389
+ lines.push('### Risk Factors');
390
+ lines.push('');
391
+ lines.push('| Factor | Score | Weight | Details |');
392
+ lines.push('|--------|-------|--------|---------|');
393
+ for (const factor of riskScore.factors) {
394
+ const bar = generateScoreBar(factor.score);
395
+ const weightPercent = Math.round(factor.weight * 100);
396
+ lines.push(`| ${factor.name} | ${bar} ${factor.score}/100 | ${weightPercent}% | ${factor.details} |`);
397
+ }
398
+ lines.push('');
399
+ // Change summary
400
+ lines.push('### Change Summary');
401
+ lines.push('');
402
+ const summary = riskScore.changeSummary;
403
+ if (summary.breaking > 0 || summary.warning > 0 || summary.info > 0) {
404
+ lines.push('| Type | Count |');
405
+ lines.push('|------|-------|');
406
+ if (summary.breaking > 0)
407
+ lines.push(`| Breaking | ${summary.breaking} |`);
408
+ if (summary.warning > 0)
409
+ lines.push(`| Warnings | ${summary.warning} |`);
410
+ if (summary.info > 0)
411
+ lines.push(`| Info | ${summary.info} |`);
412
+ if (summary.toolsRemoved > 0)
413
+ lines.push(`| Tools Removed | ${summary.toolsRemoved} |`);
414
+ if (summary.toolsAdded > 0)
415
+ lines.push(`| Tools Added | ${summary.toolsAdded} |`);
416
+ if (summary.toolsModified > 0)
417
+ lines.push(`| Tools Modified | ${summary.toolsModified} |`);
418
+ lines.push('');
419
+ }
420
+ else {
421
+ lines.push('No changes detected.');
422
+ lines.push('');
423
+ }
424
+ return lines.join('\n');
425
+ }
426
+ /**
427
+ * Generate ASCII score bar.
428
+ */
429
+ function generateScoreBar(score, width = 10) {
430
+ const filled = Math.round((score / 100) * width);
431
+ const empty = width - filled;
432
+ return '[' + 'â–ˆ'.repeat(filled) + 'â–‘'.repeat(empty) + ']';
433
+ }
434
+ //# sourceMappingURL=risk-scorer.js.map
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Baseline save/load functionality.
3
+ */
4
+ import type { InterviewResult } from '../interview/types.js';
5
+ import type { BehavioralBaseline, BehavioralDiff } from './types.js';
6
+ /**
7
+ * Options for loading a baseline.
8
+ */
9
+ export interface LoadBaselineOptions {
10
+ /**
11
+ * Automatically migrate old baseline formats to the current version.
12
+ * If false and the baseline is outdated, a warning will be logged but
13
+ * the baseline will still be loaded (with potential compatibility issues).
14
+ * @default true
15
+ */
16
+ migrate?: boolean;
17
+ /**
18
+ * Skip integrity hash verification.
19
+ * Use with caution - only for debugging or when you know the file was modified intentionally.
20
+ * @default false
21
+ */
22
+ skipIntegrityCheck?: boolean;
23
+ }
24
+ /**
25
+ * Create a behavioral baseline from interview results.
26
+ *
27
+ * Baselines can only be created from check mode results.
28
+ * Explore mode results are for documentation only.
29
+ */
30
+ export declare function createBaseline(result: InterviewResult, serverCommand: string): BehavioralBaseline;
31
+ /**
32
+ * Save baseline to a file.
33
+ */
34
+ export declare function saveBaseline(baseline: BehavioralBaseline, path: string): void;
35
+ /**
36
+ * Load baseline from a file.
37
+ * Validates against Zod schema to prevent malicious JSON injection.
38
+ *
39
+ * @param path - Path to the baseline file
40
+ * @param options - Load options
41
+ * @returns Loaded baseline (migrated to current version if needed)
42
+ */
43
+ export declare function loadBaseline(path: string, options?: LoadBaselineOptions): BehavioralBaseline;
44
+ /**
45
+ * Verify baseline integrity.
46
+ */
47
+ export declare function verifyIntegrity(baseline: BehavioralBaseline): boolean;
48
+ /**
49
+ * Recalculate and update the integrity hash for a baseline.
50
+ * Useful after migration or manual modifications.
51
+ */
52
+ export declare function recalculateIntegrityHash(baseline: Omit<BehavioralBaseline, 'integrityHash'>): BehavioralBaseline;
53
+ /**
54
+ * Check if a baseline file exists.
55
+ * Returns false for directories - baselines must be files.
56
+ */
57
+ export declare function baselineExists(path: string): boolean;
58
+ /**
59
+ * Options for accepting drift.
60
+ */
61
+ export interface AcceptDriftOptions {
62
+ /** Who is accepting the drift (for audit trail) */
63
+ acceptedBy?: string;
64
+ /** Reason for accepting the drift */
65
+ reason?: string;
66
+ }
67
+ /**
68
+ * Accept drift by updating a baseline with drift acceptance metadata.
69
+ *
70
+ * This marks the current state of the server as the new expected baseline,
71
+ * acknowledging that the detected changes were intentional.
72
+ *
73
+ * @param currentBaseline - The new baseline from the current server state
74
+ * @param diff - The diff that is being accepted
75
+ * @param options - Acceptance options (reason, acceptedBy)
76
+ * @returns The baseline with acceptance metadata attached
77
+ */
78
+ export declare function acceptDrift(currentBaseline: BehavioralBaseline, diff: BehavioralDiff, options?: AcceptDriftOptions): BehavioralBaseline;
79
+ /**
80
+ * Check if a baseline has acceptance metadata.
81
+ */
82
+ export declare function hasAcceptance(baseline: BehavioralBaseline): boolean;
83
+ /**
84
+ * Clear acceptance metadata from a baseline.
85
+ * Useful when re-running checks after the accepted changes are no longer relevant.
86
+ * Returns a new baseline without acceptance, with recalculated integrity hash.
87
+ */
88
+ export declare function clearAcceptance(baseline: BehavioralBaseline): BehavioralBaseline;
89
+ //# sourceMappingURL=saver.d.ts.map