@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,129 @@
1
+ /**
2
+ * Response schema evolution tracking.
3
+ *
4
+ * Tracks response schema consistency across runs and detects when tools
5
+ * return different field structures, enabling schema evolution analysis
6
+ * for drift detection.
7
+ */
8
+ import type { InferredSchema } from './response-fingerprint.js';
9
+ /**
10
+ * Response schema evolution record.
11
+ * Tracks schema stability and inconsistencies across samples.
12
+ */
13
+ export interface ResponseSchemaEvolution {
14
+ /** Current schema hash */
15
+ currentHash: string;
16
+ /** Historical schema hashes (most recent first) */
17
+ history: SchemaVersion[];
18
+ /** Whether schema has been stable across all samples */
19
+ isStable: boolean;
20
+ /** Confidence in schema stability (0-1) */
21
+ stabilityConfidence: number;
22
+ /** Fields that appear inconsistently */
23
+ inconsistentFields: string[];
24
+ /** Total number of samples analyzed */
25
+ sampleCount: number;
26
+ }
27
+ /**
28
+ * A historical schema version.
29
+ */
30
+ export interface SchemaVersion {
31
+ /** Schema hash */
32
+ hash: string;
33
+ /** The schema at this version */
34
+ schema: InferredSchema;
35
+ /** When this version was observed */
36
+ observedAt: Date;
37
+ /** Number of samples with this version */
38
+ sampleCount: number;
39
+ }
40
+ /**
41
+ * Schema comparison result for evolution detection.
42
+ */
43
+ export interface SchemaEvolutionDiff {
44
+ /** Whether schema structure changed */
45
+ structureChanged: boolean;
46
+ /** Fields added in new schema */
47
+ fieldsAdded: string[];
48
+ /** Fields removed from schema */
49
+ fieldsRemoved: string[];
50
+ /** Fields with type changes */
51
+ typeChanges: SchemaTypeChange[];
52
+ /** Fields that became required */
53
+ newRequired: string[];
54
+ /** Fields that became optional */
55
+ newOptional: string[];
56
+ /** Backward compatibility assessment */
57
+ backwardCompatible: boolean;
58
+ /** Whether the change is breaking for consumers */
59
+ isBreaking: boolean;
60
+ /** Human-readable summary of changes */
61
+ summary: string;
62
+ }
63
+ /**
64
+ * A type change for a field.
65
+ */
66
+ export interface SchemaTypeChange {
67
+ /** Field path (dot notation for nested fields) */
68
+ field: string;
69
+ /** Previous type */
70
+ previousType: string;
71
+ /** Current type */
72
+ currentType: string;
73
+ /** Whether this change is backward compatible */
74
+ backwardCompatible: boolean;
75
+ }
76
+ /**
77
+ * Compare two inferred schemas for evolution.
78
+ *
79
+ * @param previous - Previous schema (or undefined if new)
80
+ * @param current - Current schema (or undefined if removed)
81
+ * @returns Detailed comparison result
82
+ */
83
+ export declare function compareInferredSchemas(previous: InferredSchema | undefined, current: InferredSchema | undefined): SchemaEvolutionDiff;
84
+ /**
85
+ * Build response schema evolution from multiple samples.
86
+ *
87
+ * @param schemas - Array of inferred schemas from samples
88
+ * @returns Schema evolution record
89
+ */
90
+ export declare function buildSchemaEvolution(schemas: InferredSchema[]): ResponseSchemaEvolution;
91
+ /**
92
+ * Compare schema evolution records between baselines.
93
+ *
94
+ * @param previous - Previous schema evolution
95
+ * @param current - Current schema evolution
96
+ * @returns Evolution comparison result
97
+ */
98
+ export declare function compareSchemaEvolution(previous: ResponseSchemaEvolution | undefined, current: ResponseSchemaEvolution | undefined): SchemaEvolutionDiff;
99
+ /**
100
+ * Format schema evolution for display.
101
+ *
102
+ * @param evolution - Schema evolution record
103
+ * @returns Formatted string representation
104
+ */
105
+ export declare function formatSchemaEvolution(evolution: ResponseSchemaEvolution): string;
106
+ /**
107
+ * Format schema evolution diff for display.
108
+ *
109
+ * @param diff - Schema evolution diff
110
+ * @param useColors - Whether to use ANSI colors
111
+ * @returns Formatted string representation
112
+ */
113
+ export declare function formatSchemaEvolutionDiff(diff: SchemaEvolutionDiff, useColors?: boolean): string[];
114
+ /**
115
+ * Determine if schema evolution indicates breaking changes.
116
+ *
117
+ * @param evolution - Schema evolution record
118
+ * @param threshold - Confidence threshold for stability
119
+ * @returns Whether the schema evolution indicates issues
120
+ */
121
+ export declare function hasSchemaEvolutionIssues(evolution: ResponseSchemaEvolution, threshold?: number): boolean;
122
+ /**
123
+ * Get schema evolution stability grade.
124
+ *
125
+ * @param evolution - Schema evolution record
126
+ * @returns Grade from A-F
127
+ */
128
+ export declare function getSchemaStabilityGrade(evolution: ResponseSchemaEvolution): 'A' | 'B' | 'C' | 'D' | 'F' | 'N/A';
129
+ //# sourceMappingURL=response-schema-tracker.d.ts.map
@@ -0,0 +1,420 @@
1
+ /**
2
+ * Response schema evolution tracking.
3
+ *
4
+ * Tracks response schema consistency across runs and detects when tools
5
+ * return different field structures, enabling schema evolution analysis
6
+ * for drift detection.
7
+ */
8
+ import { computeInferredSchemaHash } from './response-fingerprint.js';
9
+ import { SCHEMA_EVOLUTION } from '../constants.js';
10
+ /**
11
+ * Compare two inferred schemas for evolution.
12
+ *
13
+ * @param previous - Previous schema (or undefined if new)
14
+ * @param current - Current schema (or undefined if removed)
15
+ * @returns Detailed comparison result
16
+ */
17
+ export function compareInferredSchemas(previous, current) {
18
+ // Both undefined - no change
19
+ if (!previous && !current) {
20
+ return createEmptyDiff();
21
+ }
22
+ // Schema added (new tool or first response)
23
+ if (!previous) {
24
+ const fields = current?.properties ? Object.keys(current.properties) : [];
25
+ return {
26
+ structureChanged: fields.length > 0,
27
+ fieldsAdded: fields,
28
+ fieldsRemoved: [],
29
+ typeChanges: [],
30
+ newRequired: current?.required ?? [],
31
+ newOptional: [],
32
+ backwardCompatible: true, // Adding fields is backward compatible
33
+ isBreaking: false,
34
+ summary: fields.length > 0
35
+ ? `Schema established with ${fields.length} field(s)`
36
+ : 'Empty schema established',
37
+ };
38
+ }
39
+ // Schema removed
40
+ if (!current) {
41
+ const fields = previous.properties ? Object.keys(previous.properties) : [];
42
+ return {
43
+ structureChanged: fields.length > 0,
44
+ fieldsAdded: [],
45
+ fieldsRemoved: fields,
46
+ typeChanges: [],
47
+ newRequired: [],
48
+ newOptional: [],
49
+ backwardCompatible: false, // Removing all fields is breaking
50
+ isBreaking: true,
51
+ summary: fields.length > 0
52
+ ? `Schema removed (${fields.length} field(s) lost)`
53
+ : 'Schema removed',
54
+ };
55
+ }
56
+ // Both schemas exist - compare them
57
+ return compareSchemaStructures(previous, current);
58
+ }
59
+ /**
60
+ * Compare two schema structures in detail.
61
+ */
62
+ function compareSchemaStructures(previous, current) {
63
+ const prevFields = new Set(Object.keys(previous.properties ?? {}));
64
+ const currFields = new Set(Object.keys(current.properties ?? {}));
65
+ const fieldsAdded = [...currFields].filter(f => !prevFields.has(f));
66
+ const fieldsRemoved = [...prevFields].filter(f => !currFields.has(f));
67
+ // Check for type changes in common fields
68
+ const typeChanges = [];
69
+ for (const field of prevFields) {
70
+ if (currFields.has(field)) {
71
+ const prevProp = previous.properties?.[field];
72
+ const currProp = current.properties?.[field];
73
+ if (prevProp && currProp && prevProp.type !== currProp.type) {
74
+ const isCompatible = isTypeChangeCompatible(prevProp.type, currProp.type);
75
+ typeChanges.push({
76
+ field,
77
+ previousType: prevProp.type,
78
+ currentType: currProp.type,
79
+ backwardCompatible: isCompatible,
80
+ });
81
+ }
82
+ }
83
+ }
84
+ // Check required field changes
85
+ const prevRequired = new Set(previous.required ?? []);
86
+ const currRequired = new Set(current.required ?? []);
87
+ const newRequired = [...currRequired].filter(f => !prevRequired.has(f) && prevFields.has(f));
88
+ const newOptional = [...prevRequired].filter(f => !currRequired.has(f) && currFields.has(f));
89
+ const structureChanged = fieldsAdded.length > 0 ||
90
+ fieldsRemoved.length > 0 ||
91
+ typeChanges.length > 0 ||
92
+ newRequired.length > 0 ||
93
+ newOptional.length > 0;
94
+ // Backward compatible if:
95
+ // - No fields removed
96
+ // - No breaking type changes
97
+ // - No new required fields on existing fields
98
+ const backwardCompatible = fieldsRemoved.length === 0 &&
99
+ typeChanges.every(tc => tc.backwardCompatible) &&
100
+ newRequired.length === 0;
101
+ // Breaking if:
102
+ // - Fields removed
103
+ // - Breaking type changes
104
+ // - New required fields (consumers may not provide them)
105
+ const isBreaking = fieldsRemoved.length > 0 ||
106
+ typeChanges.some(tc => !tc.backwardCompatible) ||
107
+ newRequired.length > 0;
108
+ // Build summary
109
+ const summary = buildChangeSummary({
110
+ fieldsAdded,
111
+ fieldsRemoved,
112
+ typeChanges,
113
+ newRequired,
114
+ newOptional,
115
+ });
116
+ return {
117
+ structureChanged,
118
+ fieldsAdded,
119
+ fieldsRemoved,
120
+ typeChanges,
121
+ newRequired,
122
+ newOptional,
123
+ backwardCompatible,
124
+ isBreaking,
125
+ summary,
126
+ };
127
+ }
128
+ /**
129
+ * Check if a type change is backward compatible.
130
+ */
131
+ function isTypeChangeCompatible(prevType, currType) {
132
+ // Widening type changes are compatible (more permissive)
133
+ const wideningChanges = {
134
+ 'integer': ['number'], // integer -> number is compatible
135
+ 'null': ['string', 'number', 'integer', 'boolean', 'object', 'array'], // null -> anything
136
+ };
137
+ if (wideningChanges[prevType]?.includes(currType)) {
138
+ return true;
139
+ }
140
+ // Adding nullable is compatible
141
+ if (prevType !== 'null' && currType === 'mixed') {
142
+ return true;
143
+ }
144
+ return false;
145
+ }
146
+ /**
147
+ * Build a human-readable summary of schema changes.
148
+ */
149
+ function buildChangeSummary(changes) {
150
+ const parts = [];
151
+ if (changes.fieldsRemoved.length > 0) {
152
+ parts.push(`${changes.fieldsRemoved.length} field(s) removed`);
153
+ }
154
+ if (changes.fieldsAdded.length > 0) {
155
+ parts.push(`${changes.fieldsAdded.length} field(s) added`);
156
+ }
157
+ if (changes.typeChanges.length > 0) {
158
+ parts.push(`${changes.typeChanges.length} type change(s)`);
159
+ }
160
+ if (changes.newRequired.length > 0) {
161
+ parts.push(`${changes.newRequired.length} field(s) now required`);
162
+ }
163
+ if (changes.newOptional.length > 0) {
164
+ parts.push(`${changes.newOptional.length} field(s) now optional`);
165
+ }
166
+ if (parts.length === 0) {
167
+ return 'No schema changes';
168
+ }
169
+ return parts.join(', ');
170
+ }
171
+ /**
172
+ * Create an empty diff result.
173
+ */
174
+ function createEmptyDiff() {
175
+ return {
176
+ structureChanged: false,
177
+ fieldsAdded: [],
178
+ fieldsRemoved: [],
179
+ typeChanges: [],
180
+ newRequired: [],
181
+ newOptional: [],
182
+ backwardCompatible: true,
183
+ isBreaking: false,
184
+ summary: 'No schema changes',
185
+ };
186
+ }
187
+ /**
188
+ * Build response schema evolution from multiple samples.
189
+ *
190
+ * @param schemas - Array of inferred schemas from samples
191
+ * @returns Schema evolution record
192
+ */
193
+ export function buildSchemaEvolution(schemas) {
194
+ if (schemas.length === 0) {
195
+ return {
196
+ currentHash: 'empty',
197
+ history: [],
198
+ isStable: true,
199
+ stabilityConfidence: 0,
200
+ inconsistentFields: [],
201
+ sampleCount: 0,
202
+ };
203
+ }
204
+ // Track field presence across samples
205
+ const fieldPresence = new Map();
206
+ const fieldTypes = new Map();
207
+ for (const schema of schemas) {
208
+ if (schema.properties) {
209
+ for (const [field, propSchema] of Object.entries(schema.properties)) {
210
+ fieldPresence.set(field, (fieldPresence.get(field) ?? 0) + 1);
211
+ if (!fieldTypes.has(field)) {
212
+ fieldTypes.set(field, new Set());
213
+ }
214
+ fieldTypes.get(field).add(propSchema.type);
215
+ }
216
+ }
217
+ }
218
+ // Find inconsistent fields (not present in all samples or type varies)
219
+ const inconsistentFields = [];
220
+ for (const [field, count] of fieldPresence) {
221
+ if (count < schemas.length) {
222
+ inconsistentFields.push(field);
223
+ }
224
+ else if ((fieldTypes.get(field)?.size ?? 0) > 1) {
225
+ inconsistentFields.push(field);
226
+ }
227
+ }
228
+ // Calculate stability
229
+ const totalFields = fieldPresence.size;
230
+ const isStable = inconsistentFields.length === 0;
231
+ // Confidence based on consistency ratio and sample count
232
+ let stabilityConfidence = isStable
233
+ ? 1
234
+ : 1 - (inconsistentFields.length / Math.max(1, totalFields));
235
+ // Adjust confidence based on sample count
236
+ // More samples = higher confidence in stability assessment
237
+ const sampleCountFactor = Math.min(1, schemas.length / SCHEMA_EVOLUTION.HIGH_CONFIDENCE_MIN_SAMPLES);
238
+ stabilityConfidence = stabilityConfidence * sampleCountFactor;
239
+ // Build history (most recent schema)
240
+ const currentSchema = schemas[schemas.length - 1];
241
+ const currentHash = computeInferredSchemaHash(currentSchema);
242
+ const history = [{
243
+ hash: currentHash,
244
+ schema: currentSchema,
245
+ observedAt: new Date(),
246
+ sampleCount: schemas.length,
247
+ }];
248
+ return {
249
+ currentHash,
250
+ history,
251
+ isStable,
252
+ stabilityConfidence: Math.round(stabilityConfidence * 100) / 100,
253
+ inconsistentFields: inconsistentFields.sort(),
254
+ sampleCount: schemas.length,
255
+ };
256
+ }
257
+ /**
258
+ * Compare schema evolution records between baselines.
259
+ *
260
+ * @param previous - Previous schema evolution
261
+ * @param current - Current schema evolution
262
+ * @returns Evolution comparison result
263
+ */
264
+ export function compareSchemaEvolution(previous, current) {
265
+ // Handle missing evolution records
266
+ if (!previous && !current) {
267
+ return createEmptyDiff();
268
+ }
269
+ if (!previous) {
270
+ return {
271
+ ...createEmptyDiff(),
272
+ structureChanged: (current?.inconsistentFields.length ?? 0) > 0 ||
273
+ current?.currentHash !== 'empty',
274
+ summary: current?.isStable
275
+ ? 'Schema tracking established (stable)'
276
+ : `Schema tracking established (${current?.inconsistentFields.length ?? 0} inconsistent field(s))`,
277
+ };
278
+ }
279
+ if (!current) {
280
+ return {
281
+ ...createEmptyDiff(),
282
+ structureChanged: true,
283
+ isBreaking: true,
284
+ backwardCompatible: false,
285
+ summary: 'Schema evolution data removed',
286
+ };
287
+ }
288
+ // Compare current schemas if available
289
+ const prevSchema = previous.history[0]?.schema;
290
+ const currSchema = current.history[0]?.schema;
291
+ if (prevSchema && currSchema) {
292
+ return compareInferredSchemas(prevSchema, currSchema);
293
+ }
294
+ // Compare hashes directly
295
+ if (previous.currentHash !== current.currentHash) {
296
+ return {
297
+ ...createEmptyDiff(),
298
+ structureChanged: true,
299
+ summary: 'Schema hash changed',
300
+ };
301
+ }
302
+ // Check stability change
303
+ if (previous.isStable !== current.isStable) {
304
+ return {
305
+ ...createEmptyDiff(),
306
+ structureChanged: false,
307
+ summary: current.isStable
308
+ ? 'Schema stabilized'
309
+ : 'Schema became unstable',
310
+ };
311
+ }
312
+ return createEmptyDiff();
313
+ }
314
+ /**
315
+ * Format schema evolution for display.
316
+ *
317
+ * @param evolution - Schema evolution record
318
+ * @returns Formatted string representation
319
+ */
320
+ export function formatSchemaEvolution(evolution) {
321
+ const lines = [];
322
+ const stabilityIcon = evolution.isStable ? '✓' : '⚠';
323
+ const confidencePercent = Math.round(evolution.stabilityConfidence * 100);
324
+ lines.push(`${stabilityIcon} Schema ${evolution.isStable ? 'Stable' : 'Unstable'} (${confidencePercent}% confidence)`);
325
+ if (evolution.sampleCount > 0) {
326
+ lines.push(` Samples: ${evolution.sampleCount}`);
327
+ lines.push(` Hash: ${evolution.currentHash}`);
328
+ }
329
+ if (evolution.inconsistentFields.length > 0) {
330
+ const fieldsDisplay = evolution.inconsistentFields.length <= 3
331
+ ? evolution.inconsistentFields.join(', ')
332
+ : `${evolution.inconsistentFields.slice(0, 3).join(', ')} +${evolution.inconsistentFields.length - 3} more`;
333
+ lines.push(` Inconsistent fields: ${fieldsDisplay}`);
334
+ }
335
+ return lines.join('\n');
336
+ }
337
+ /**
338
+ * Format schema evolution diff for display.
339
+ *
340
+ * @param diff - Schema evolution diff
341
+ * @param useColors - Whether to use ANSI colors
342
+ * @returns Formatted string representation
343
+ */
344
+ export function formatSchemaEvolutionDiff(diff, useColors = true) {
345
+ const lines = [];
346
+ const { red, green, yellow } = useColors ? colors : noColors;
347
+ if (!diff.structureChanged) {
348
+ return [];
349
+ }
350
+ if (diff.fieldsRemoved.length > 0) {
351
+ lines.push(red(` ${diff.fieldsRemoved.length} field(s) removed: ${diff.fieldsRemoved.join(', ')}`));
352
+ }
353
+ if (diff.fieldsAdded.length > 0) {
354
+ lines.push(green(` ${diff.fieldsAdded.length} field(s) added: ${diff.fieldsAdded.join(', ')}`));
355
+ }
356
+ for (const tc of diff.typeChanges) {
357
+ const changeColor = tc.backwardCompatible ? yellow : red;
358
+ lines.push(changeColor(` Type change: ${tc.field}: ${tc.previousType} → ${tc.currentType}`));
359
+ }
360
+ if (diff.newRequired.length > 0) {
361
+ lines.push(red(` Now required: ${diff.newRequired.join(', ')}`));
362
+ }
363
+ if (diff.newOptional.length > 0) {
364
+ lines.push(green(` Now optional: ${diff.newOptional.join(', ')}`));
365
+ }
366
+ return lines;
367
+ }
368
+ /**
369
+ * Determine if schema evolution indicates breaking changes.
370
+ *
371
+ * @param evolution - Schema evolution record
372
+ * @param threshold - Confidence threshold for stability
373
+ * @returns Whether the schema evolution indicates issues
374
+ */
375
+ export function hasSchemaEvolutionIssues(evolution, threshold = SCHEMA_EVOLUTION.STABILITY_THRESHOLD) {
376
+ // Unstable schema with high sample count is concerning
377
+ if (!evolution.isStable && evolution.sampleCount >= SCHEMA_EVOLUTION.MIN_SAMPLES_FOR_STABILITY) {
378
+ return true;
379
+ }
380
+ // Low stability confidence with enough samples
381
+ if (evolution.stabilityConfidence < threshold &&
382
+ evolution.sampleCount >= SCHEMA_EVOLUTION.MIN_SAMPLES_FOR_STABILITY) {
383
+ return true;
384
+ }
385
+ return false;
386
+ }
387
+ /**
388
+ * Get schema evolution stability grade.
389
+ *
390
+ * @param evolution - Schema evolution record
391
+ * @returns Grade from A-F
392
+ */
393
+ export function getSchemaStabilityGrade(evolution) {
394
+ if (evolution.sampleCount < SCHEMA_EVOLUTION.MIN_SAMPLES_FOR_STABILITY) {
395
+ return 'N/A';
396
+ }
397
+ const confidence = evolution.stabilityConfidence;
398
+ const { A, B, C, D } = SCHEMA_EVOLUTION.GRADE_THRESHOLDS;
399
+ if (evolution.isStable && confidence >= A)
400
+ return 'A';
401
+ if (confidence >= B)
402
+ return 'B';
403
+ if (confidence >= C)
404
+ return 'C';
405
+ if (confidence >= D)
406
+ return 'D';
407
+ return 'F';
408
+ }
409
+ // Color utilities
410
+ const colors = {
411
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
412
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
413
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
414
+ };
415
+ const noColors = {
416
+ red: (s) => s,
417
+ green: (s) => s,
418
+ yellow: (s) => s,
419
+ };
420
+ //# sourceMappingURL=response-schema-tracker.js.map
@@ -0,0 +1,54 @@
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 type { BehavioralDiff } from './types.js';
9
+ /**
10
+ * A single risk factor contributing to the overall score.
11
+ */
12
+ export interface RiskFactor {
13
+ /** Name of the risk factor */
14
+ name: string;
15
+ /** Weight in overall calculation (0-1) */
16
+ weight: number;
17
+ /** Raw score (0-100) */
18
+ score: number;
19
+ /** Weighted contribution to overall score */
20
+ weightedScore: number;
21
+ /** Details about this factor */
22
+ details: string;
23
+ }
24
+ /**
25
+ * Complete regression risk score.
26
+ */
27
+ export interface RegressionRiskScore {
28
+ /** Overall risk score (0-100) */
29
+ score: number;
30
+ /** Risk level classification */
31
+ level: 'critical' | 'high' | 'medium' | 'low' | 'info';
32
+ /** Individual risk factors */
33
+ factors: RiskFactor[];
34
+ /** Human-readable recommendation */
35
+ recommendation: string;
36
+ /** Breakdown of changes by severity */
37
+ changeSummary: {
38
+ breaking: number;
39
+ warning: number;
40
+ info: number;
41
+ toolsRemoved: number;
42
+ toolsAdded: number;
43
+ toolsModified: number;
44
+ };
45
+ }
46
+ /**
47
+ * Calculate regression risk score from a behavioral diff.
48
+ */
49
+ export declare function calculateRiskScore(diff: BehavioralDiff): RegressionRiskScore;
50
+ /**
51
+ * Generate markdown report for risk score.
52
+ */
53
+ export declare function generateRiskScoreMarkdown(riskScore: RegressionRiskScore): string;
54
+ //# sourceMappingURL=risk-scorer.d.ts.map