@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,407 @@
1
+ /**
2
+ * Golden command - Manage golden outputs for tool validation.
3
+ *
4
+ * Commands:
5
+ * bellwether golden save --tool <name> Save current output as golden
6
+ * bellwether golden compare Compare against all golden outputs
7
+ * bellwether golden list List all saved golden outputs
8
+ * bellwether golden delete --tool <name> Delete a golden output
9
+ */
10
+ import { Command } from 'commander';
11
+ import { existsSync, mkdirSync } from 'fs';
12
+ import { MCPClient } from '../../transport/mcp-client.js';
13
+ import { discover } from '../../discovery/discovery.js';
14
+ import { loadConfig, ConfigNotFoundError } from '../../config/loader.js';
15
+ import { validateConfigForCheck } from '../../config/validator.js';
16
+ import { getGoldenStorePath, saveGoldenOutput, createGoldenOutput, listGoldenOutputs, deleteGoldenOutput, compareWithGolden, } from '../../baseline/golden-output.js';
17
+ import * as output from '../output.js';
18
+ import { EXIT_CODES, PATHS } from '../../constants.js';
19
+ import { formatDateISO } from '../../utils/index.js';
20
+ export const goldenCommand = new Command('golden')
21
+ .description('Manage golden outputs for tool validation');
22
+ // Save command
23
+ goldenCommand
24
+ .command('save')
25
+ .description('Capture current tool output as golden reference')
26
+ .requiredOption('--tool <name>', 'Tool name to capture golden output for')
27
+ .option('-c, --config <path>', 'Path to config file', PATHS.DEFAULT_CONFIG_FILENAME)
28
+ .option('--args <json>', 'JSON arguments to pass to the tool')
29
+ .option('--mode <mode>', 'Comparison mode: exact, structural, semantic')
30
+ .option('--allowed-drift <paths>', 'Comma-separated JSONPath patterns for allowed changes')
31
+ .option('--no-normalize-timestamps', 'Disable timestamp normalization')
32
+ .option('--no-normalize-uuids', 'Disable UUID normalization')
33
+ .option('--description <text>', 'Description of this golden output')
34
+ .action(async (options) => {
35
+ // Load configuration
36
+ let config;
37
+ try {
38
+ config = loadConfig(options.config);
39
+ }
40
+ catch (error) {
41
+ if (error instanceof ConfigNotFoundError) {
42
+ output.error(error.message);
43
+ process.exit(EXIT_CODES.ERROR);
44
+ }
45
+ throw error;
46
+ }
47
+ // Validate config
48
+ const serverCommand = config.server.command;
49
+ const args = config.server.args;
50
+ try {
51
+ validateConfigForCheck(config, serverCommand);
52
+ }
53
+ catch (error) {
54
+ output.error(error instanceof Error ? error.message : String(error));
55
+ process.exit(EXIT_CODES.ERROR);
56
+ }
57
+ const argsJson = options.args ?? config.golden.defaultArgs;
58
+ const mode = options.mode ?? config.golden.mode;
59
+ const normalizeTimestamps = options.normalizeTimestamps === false
60
+ ? false
61
+ : config.golden.normalizeTimestamps;
62
+ const normalizeUuids = options.normalizeUuids === false
63
+ ? false
64
+ : config.golden.normalizeUuids;
65
+ // Parse tool arguments
66
+ let toolArgs;
67
+ try {
68
+ toolArgs = JSON.parse(argsJson);
69
+ }
70
+ catch (error) {
71
+ output.error(`Invalid JSON for --args: ${error instanceof Error ? error.message : error}`);
72
+ process.exit(EXIT_CODES.ERROR);
73
+ }
74
+ // Parse allowed drift paths
75
+ const allowedDrift = options.allowedDrift
76
+ ? options.allowedDrift.split(',').map((p) => p.trim())
77
+ : [];
78
+ // Validate comparison mode
79
+ const validModes = ['exact', 'structural', 'semantic'];
80
+ if (!validModes.includes(mode)) {
81
+ output.error(`Invalid mode "${mode}". Valid modes: ${validModes.join(', ')}`);
82
+ process.exit(EXIT_CODES.ERROR);
83
+ }
84
+ const outputDir = config.output.dir;
85
+ const storePath = getGoldenStorePath(outputDir);
86
+ output.info(`Capturing golden output for: ${options.tool}`);
87
+ output.info(`Mode: ${mode}`);
88
+ if (allowedDrift.length > 0) {
89
+ output.info(`Allowed drift paths: ${allowedDrift.join(', ')}`);
90
+ }
91
+ output.newline();
92
+ const mcpClient = new MCPClient({
93
+ timeout: config.server.timeout,
94
+ debug: config.logging.level === 'debug',
95
+ transport: 'stdio',
96
+ });
97
+ try {
98
+ // Connect to server
99
+ output.info('Connecting to MCP server...');
100
+ await mcpClient.connect(serverCommand, args, config.server.env);
101
+ // Discover tools
102
+ const discovery = await discover(mcpClient, serverCommand, args);
103
+ const tool = discovery.tools.find(t => t.name === options.tool);
104
+ if (!tool) {
105
+ output.error(`Tool not found: ${options.tool}`);
106
+ output.info(`Available tools: ${discovery.tools.map(t => t.name).join(', ')}`);
107
+ process.exit(EXIT_CODES.ERROR);
108
+ }
109
+ // Call the tool
110
+ output.info(`Calling tool: ${options.tool}`);
111
+ const response = await mcpClient.callTool(options.tool, toolArgs);
112
+ if (response.isError) {
113
+ output.error('Tool returned an error:');
114
+ const textContent = response.content.find(c => c.type === 'text');
115
+ if (textContent && 'text' in textContent) {
116
+ output.error(String(textContent.text));
117
+ }
118
+ process.exit(EXIT_CODES.ERROR);
119
+ }
120
+ // Create golden output
121
+ const golden = createGoldenOutput(options.tool, toolArgs, response, {
122
+ mode,
123
+ allowedDrift,
124
+ normalizeTimestamps,
125
+ normalizeUuids,
126
+ description: options.description,
127
+ });
128
+ // Ensure output directory exists
129
+ mkdirSync(outputDir, { recursive: true });
130
+ // Save golden output
131
+ saveGoldenOutput(golden, storePath);
132
+ output.success('\nGolden output saved!');
133
+ output.info(`Store: ${storePath}`);
134
+ output.info(`Tool: ${golden.toolName}`);
135
+ output.info(`Content type: ${golden.output.contentType}`);
136
+ output.info(`Content hash: ${golden.output.contentHash}`);
137
+ output.info(`Comparison mode: ${golden.tolerance.mode}`);
138
+ // Show preview of captured content
139
+ const preview = golden.output.raw.slice(0, 200);
140
+ if (preview) {
141
+ output.newline();
142
+ output.info('Output preview:');
143
+ output.info(preview + (golden.output.raw.length > 200 ? '...' : ''));
144
+ }
145
+ }
146
+ catch (error) {
147
+ output.error(`Failed to capture golden output: ${error instanceof Error ? error.message : error}`);
148
+ process.exit(EXIT_CODES.ERROR);
149
+ }
150
+ finally {
151
+ await mcpClient.disconnect();
152
+ }
153
+ });
154
+ // Compare command
155
+ goldenCommand
156
+ .command('compare')
157
+ .description('Compare current outputs against saved golden outputs')
158
+ .option('-c, --config <path>', 'Path to config file', PATHS.DEFAULT_CONFIG_FILENAME)
159
+ .option('--tool <name>', 'Only compare a specific tool')
160
+ .option('--fail-on-drift', 'Exit with error if any drift detected')
161
+ .option('--format <format>', 'Output format: text, json, markdown')
162
+ .action(async (options) => {
163
+ // Load configuration
164
+ let config;
165
+ try {
166
+ config = loadConfig(options.config);
167
+ }
168
+ catch (error) {
169
+ if (error instanceof ConfigNotFoundError) {
170
+ output.error(error.message);
171
+ process.exit(EXIT_CODES.ERROR);
172
+ }
173
+ throw error;
174
+ }
175
+ // Validate config
176
+ const serverCommand = config.server.command;
177
+ const args = config.server.args;
178
+ try {
179
+ validateConfigForCheck(config, serverCommand);
180
+ }
181
+ catch (error) {
182
+ output.error(error instanceof Error ? error.message : String(error));
183
+ process.exit(EXIT_CODES.ERROR);
184
+ }
185
+ const outputDir = config.output.dir;
186
+ const storePath = getGoldenStorePath(outputDir);
187
+ const format = options.format ?? config.golden.compareFormat;
188
+ if (!existsSync(storePath)) {
189
+ output.warn('No golden outputs found.');
190
+ output.info('Use "bellwether golden save --tool <name>" to capture golden outputs.');
191
+ process.exit(EXIT_CODES.CLEAN);
192
+ }
193
+ const goldens = listGoldenOutputs(storePath);
194
+ const filteredGoldens = options.tool
195
+ ? goldens.filter(g => g.toolName === options.tool)
196
+ : goldens;
197
+ if (filteredGoldens.length === 0) {
198
+ if (options.tool) {
199
+ output.warn(`No golden output found for tool: ${options.tool}`);
200
+ }
201
+ else {
202
+ output.warn('No golden outputs saved.');
203
+ }
204
+ process.exit(EXIT_CODES.CLEAN);
205
+ }
206
+ output.info(`Comparing ${filteredGoldens.length} golden output(s)...`);
207
+ output.newline();
208
+ const mcpClient = new MCPClient({
209
+ timeout: config.server.timeout,
210
+ debug: config.logging.level === 'debug',
211
+ transport: 'stdio',
212
+ });
213
+ try {
214
+ // Connect to server
215
+ output.info('Connecting to MCP server...');
216
+ await mcpClient.connect(serverCommand, args, config.server.env);
217
+ output.newline();
218
+ const results = [];
219
+ for (const golden of filteredGoldens) {
220
+ output.info(`Comparing: ${golden.toolName}`);
221
+ try {
222
+ const response = await mcpClient.callTool(golden.toolName, golden.inputArgs);
223
+ const result = compareWithGolden(golden, response);
224
+ results.push(result);
225
+ const icon = result.passed ? '\u2713' : '\u2717';
226
+ if (result.passed) {
227
+ output.success(` ${icon} ${result.summary}`);
228
+ }
229
+ else {
230
+ output.error(` ${icon} ${result.summary}`);
231
+ if (result.differences.filter(d => !d.allowed).length <= 5) {
232
+ for (const diff of result.differences.filter(d => !d.allowed)) {
233
+ output.warn(` - ${diff.description} at ${diff.path}`);
234
+ }
235
+ }
236
+ }
237
+ }
238
+ catch (error) {
239
+ results.push({
240
+ toolName: golden.toolName,
241
+ passed: false,
242
+ severity: 'breaking',
243
+ mode: golden.tolerance.mode,
244
+ goldenCapturedAt: golden.capturedAt,
245
+ differences: [{
246
+ type: 'changed',
247
+ path: '$',
248
+ expected: 'successful response',
249
+ actual: `error: ${error instanceof Error ? error.message : String(error)}`,
250
+ allowed: false,
251
+ description: 'Tool call failed',
252
+ }],
253
+ summary: `Tool call failed: ${error instanceof Error ? error.message : String(error)}`,
254
+ });
255
+ output.error(` \u2717 Tool call failed: ${error instanceof Error ? error.message : String(error)}`);
256
+ }
257
+ }
258
+ output.newline();
259
+ // Summary
260
+ const passed = results.filter(r => r.passed).length;
261
+ const failed = results.length - passed;
262
+ if (format === 'json') {
263
+ output.info(JSON.stringify(results, null, 2));
264
+ }
265
+ else if (format === 'markdown') {
266
+ output.info(formatResultsMarkdown(results));
267
+ }
268
+ else {
269
+ output.info('--- Summary ---');
270
+ output.info(`Total: ${results.length}`);
271
+ output.success(`Passed: ${passed}`);
272
+ if (failed > 0) {
273
+ output.error(`Failed: ${failed}`);
274
+ }
275
+ }
276
+ if (options.failOnDrift && failed > 0) {
277
+ process.exit(EXIT_CODES.BREAKING);
278
+ }
279
+ }
280
+ finally {
281
+ await mcpClient.disconnect();
282
+ }
283
+ });
284
+ // List command
285
+ goldenCommand
286
+ .command('list')
287
+ .description('List all saved golden outputs')
288
+ .option('-c, --config <path>', 'Path to config file', PATHS.DEFAULT_CONFIG_FILENAME)
289
+ .option('--format <format>', 'Output format: text, json')
290
+ .action(async (options) => {
291
+ // Load configuration
292
+ let config;
293
+ try {
294
+ config = loadConfig(options.config);
295
+ }
296
+ catch (error) {
297
+ if (error instanceof ConfigNotFoundError) {
298
+ output.error(error.message);
299
+ process.exit(EXIT_CODES.ERROR);
300
+ }
301
+ throw error;
302
+ }
303
+ const outputDir = config.output.dir;
304
+ const storePath = getGoldenStorePath(outputDir);
305
+ const format = options.format ?? config.golden.listFormat;
306
+ if (!existsSync(storePath)) {
307
+ output.info('No golden outputs found.');
308
+ output.info('Use "bellwether golden save --tool <name>" to capture golden outputs.');
309
+ return;
310
+ }
311
+ const goldens = listGoldenOutputs(storePath);
312
+ if (goldens.length === 0) {
313
+ output.info('No golden outputs saved.');
314
+ return;
315
+ }
316
+ if (format === 'json') {
317
+ output.info(JSON.stringify(goldens, null, 2));
318
+ return;
319
+ }
320
+ output.info(`Golden Outputs (${goldens.length}):`);
321
+ output.newline();
322
+ output.info('| Tool | Captured | Mode | Content Type |');
323
+ output.info('|------|----------|------|--------------|');
324
+ for (const golden of goldens) {
325
+ const captured = formatDateISO(new Date(golden.capturedAt));
326
+ output.info(`| \`${golden.toolName}\` | ${captured} | ${golden.tolerance.mode} | ${golden.output.contentType} |`);
327
+ }
328
+ output.newline();
329
+ output.info(`Store: ${storePath}`);
330
+ });
331
+ // Delete command
332
+ goldenCommand
333
+ .command('delete')
334
+ .description('Delete a saved golden output')
335
+ .requiredOption('--tool <name>', 'Tool name to delete golden output for')
336
+ .option('-c, --config <path>', 'Path to config file', PATHS.DEFAULT_CONFIG_FILENAME)
337
+ .option('--all', 'Delete all golden outputs for this tool (if multiple with different args)')
338
+ .action(async (options) => {
339
+ // Load configuration
340
+ let config;
341
+ try {
342
+ config = loadConfig(options.config);
343
+ }
344
+ catch (error) {
345
+ if (error instanceof ConfigNotFoundError) {
346
+ output.error(error.message);
347
+ process.exit(EXIT_CODES.ERROR);
348
+ }
349
+ throw error;
350
+ }
351
+ const outputDir = config.output.dir;
352
+ const storePath = getGoldenStorePath(outputDir);
353
+ if (!existsSync(storePath)) {
354
+ output.warn('No golden outputs found.');
355
+ return;
356
+ }
357
+ const deleted = deleteGoldenOutput(options.tool, storePath);
358
+ if (deleted) {
359
+ output.success(`Deleted golden output for: ${options.tool}`);
360
+ }
361
+ else {
362
+ output.warn(`No golden output found for: ${options.tool}`);
363
+ }
364
+ });
365
+ /**
366
+ * Format comparison results as Markdown.
367
+ */
368
+ function formatResultsMarkdown(results) {
369
+ const lines = [];
370
+ lines.push('## Golden Output Validation');
371
+ lines.push('');
372
+ lines.push('| Tool | Status | Mode | Differences |');
373
+ lines.push('|------|--------|------|-------------|');
374
+ for (const result of results) {
375
+ const status = result.passed ? '✓ Match' : `✗ ${result.severity}`;
376
+ const diffCount = result.differences.filter(d => !d.allowed).length;
377
+ lines.push(`| \`${result.toolName}\` | ${status} | ${result.mode} | ${diffCount} |`);
378
+ }
379
+ lines.push('');
380
+ // Details for failed comparisons
381
+ const failed = results.filter(r => !r.passed);
382
+ if (failed.length > 0) {
383
+ lines.push('### Drift Details');
384
+ lines.push('');
385
+ for (const result of failed) {
386
+ lines.push(`#### ${result.toolName}`);
387
+ lines.push('');
388
+ lines.push(`**Golden captured:** ${formatDateISO(new Date(result.goldenCapturedAt))}`);
389
+ lines.push(`**Mode:** ${result.mode}`);
390
+ lines.push(`**Severity:** ${result.severity}`);
391
+ lines.push('');
392
+ lines.push('**Changes:**');
393
+ for (const diff of result.differences.filter(d => !d.allowed)) {
394
+ lines.push(`- ${diff.description}`);
395
+ if (diff.expected !== undefined) {
396
+ lines.push(` - Expected: \`${String(diff.expected)}\``);
397
+ }
398
+ if (diff.actual !== undefined) {
399
+ lines.push(` - Actual: \`${String(diff.actual)}\``);
400
+ }
401
+ }
402
+ lines.push('');
403
+ }
404
+ }
405
+ return lines.join('\n');
406
+ }
407
+ //# sourceMappingURL=golden.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * History command for viewing baseline history in Bellwether Cloud.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const historyCommand: Command;
6
+ /**
7
+ * Diff command for comparing specific versions.
8
+ */
9
+ export declare const diffCommand: Command;
10
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1,202 @@
1
+ /**
2
+ * History command for viewing baseline history in Bellwether Cloud.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { getSessionToken, getLinkedProject } from '../../cloud/auth.js';
6
+ import { createCloudClient } from '../../cloud/client.js';
7
+ import { formatDateLocale } from '../../utils/index.js';
8
+ import { EXIT_CODES } from '../../constants.js';
9
+ import * as output from '../output.js';
10
+ import { getSeverityIcon } from '../output.js';
11
+ export const historyCommand = new Command('history')
12
+ .description('View baseline history for a project')
13
+ .argument('[project-id]', 'Project ID (uses linked project if not specified)')
14
+ .option('-n, --limit <n>', 'Number of versions to show', '10')
15
+ .option('--json', 'Output as JSON')
16
+ .option('--session <session>', 'Session token (overrides stored/env session)')
17
+ .action(async (projectIdArg, options) => {
18
+ // Get session
19
+ const sessionToken = options.session ?? getSessionToken();
20
+ if (!sessionToken) {
21
+ output.error('Not authenticated. Run `bellwether login` first.');
22
+ process.exit(EXIT_CODES.ERROR);
23
+ }
24
+ // Determine project ID
25
+ let projectId = projectIdArg;
26
+ if (!projectId) {
27
+ const link = getLinkedProject();
28
+ if (link) {
29
+ projectId = link.projectId;
30
+ }
31
+ }
32
+ if (!projectId) {
33
+ output.error('No project specified.');
34
+ output.error('\nEither:');
35
+ output.error(' - Provide a project ID as argument');
36
+ output.error(' - Run `bellwether link` to link this directory to a project');
37
+ process.exit(EXIT_CODES.ERROR);
38
+ }
39
+ // Create client and fetch history
40
+ const client = createCloudClient({ sessionToken });
41
+ if (!client.isAuthenticated()) {
42
+ output.error('Authentication failed. Run `bellwether login` to re-authenticate.');
43
+ process.exit(EXIT_CODES.ERROR);
44
+ }
45
+ const limit = parseInt(options.limit, 10);
46
+ try {
47
+ const history = await client.getHistory(projectId, limit);
48
+ if (options.json) {
49
+ output.info(JSON.stringify(history, null, 2));
50
+ return;
51
+ }
52
+ if (history.length === 0) {
53
+ output.info('No baselines uploaded yet.');
54
+ output.info('\nRun `bellwether check <server> --save-baseline` then `bellwether upload`.');
55
+ return;
56
+ }
57
+ // Get project info for display
58
+ const project = await client.getProject(projectId);
59
+ const projectName = project?.name ?? projectId;
60
+ output.info(`Baseline History: ${projectName}`);
61
+ output.info(`Showing ${history.length} version(s)\n`);
62
+ output.info('Ver Uploaded CLI Version Hash');
63
+ output.info('─── ─────────────────────── ─────────── ────────────────');
64
+ for (const baseline of history) {
65
+ const date = formatDateLocale(baseline.uploadedAt);
66
+ const cliVersion = baseline.cliVersion.padEnd(11);
67
+ const hash = baseline.hash.slice(0, 16);
68
+ output.info(`${baseline.version.toString().padStart(3)} ` +
69
+ `${date.padEnd(23)} ` +
70
+ `${cliVersion} ` +
71
+ hash);
72
+ }
73
+ // Show diff summary if multiple versions
74
+ if (history.length >= 2) {
75
+ output.info('\nLatest changes:');
76
+ try {
77
+ const diff = await client.getLatestDiff(projectId);
78
+ if (diff) {
79
+ printDiffSummary(diff);
80
+ }
81
+ }
82
+ catch {
83
+ // Diff failed, just skip
84
+ }
85
+ }
86
+ }
87
+ catch (error) {
88
+ output.error('Failed to fetch history: ' + (error instanceof Error ? error.message : String(error)));
89
+ process.exit(EXIT_CODES.ERROR);
90
+ }
91
+ });
92
+ /**
93
+ * Print a diff summary (compact format).
94
+ */
95
+ function printDiffSummary(diff) {
96
+ const parts = [];
97
+ if (diff.toolsAdded > 0) {
98
+ parts.push(`+${diff.toolsAdded} tools`);
99
+ }
100
+ if (diff.toolsRemoved > 0) {
101
+ parts.push(`-${diff.toolsRemoved} tools`);
102
+ }
103
+ if (diff.toolsModified > 0) {
104
+ parts.push(`~${diff.toolsModified} modified`);
105
+ }
106
+ if (diff.behaviorChanges > 0) {
107
+ parts.push(`${diff.behaviorChanges} behavior changes`);
108
+ }
109
+ if (parts.length === 0) {
110
+ output.info(' No changes from previous version');
111
+ }
112
+ else {
113
+ const icon = getSeverityIcon(diff.severity);
114
+ output.info(` ${icon} ${diff.severity}: ${parts.join(', ')}`);
115
+ }
116
+ }
117
+ /**
118
+ * Diff command for comparing specific versions.
119
+ */
120
+ export const diffCommand = new Command('diff')
121
+ .description('Compare two baseline versions')
122
+ .argument('<from>', 'From version number')
123
+ .argument('<to>', 'To version number')
124
+ .option('-p, --project <id>', 'Project ID (uses linked project if not specified)')
125
+ .option('--json', 'Output as JSON')
126
+ .option('--session <session>', 'Session token (overrides stored/env session)')
127
+ .action(async (fromArg, toArg, options) => {
128
+ // Get session
129
+ const sessionToken = options.session ?? getSessionToken();
130
+ if (!sessionToken) {
131
+ output.error('Not authenticated. Run `bellwether login` first.');
132
+ process.exit(EXIT_CODES.ERROR);
133
+ }
134
+ // Determine project ID
135
+ let projectId = options.project;
136
+ if (!projectId) {
137
+ const link = getLinkedProject();
138
+ if (link) {
139
+ projectId = link.projectId;
140
+ }
141
+ }
142
+ if (!projectId) {
143
+ output.error('No project specified. Use --project <id> or run `bellwether link`.');
144
+ process.exit(EXIT_CODES.ERROR);
145
+ }
146
+ // Parse versions
147
+ const fromVersion = parseInt(fromArg, 10);
148
+ const toVersion = parseInt(toArg, 10);
149
+ if (isNaN(fromVersion) || isNaN(toVersion)) {
150
+ output.error('Invalid version numbers. Provide integers (e.g., `bellwether diff 1 2`).');
151
+ process.exit(EXIT_CODES.ERROR);
152
+ }
153
+ // Create client and fetch diff
154
+ const client = createCloudClient({ sessionToken });
155
+ if (!client.isAuthenticated()) {
156
+ output.error('Authentication failed. Run `bellwether login` to re-authenticate.');
157
+ process.exit(EXIT_CODES.ERROR);
158
+ }
159
+ try {
160
+ const diff = await client.getDiff(projectId, fromVersion, toVersion);
161
+ if (options.json) {
162
+ output.info(JSON.stringify(diff, null, 2));
163
+ return;
164
+ }
165
+ output.info(`Comparing v${fromVersion} → v${toVersion}\n`);
166
+ const severityIcon = {
167
+ none: '✓',
168
+ info: 'ℹ',
169
+ warning: '⚠',
170
+ breaking: '✗',
171
+ };
172
+ output.info(`Severity: ${severityIcon[diff.severity] ?? '?'} ${diff.severity.toUpperCase()}`);
173
+ output.info('');
174
+ if (diff.toolsAdded > 0) {
175
+ output.info(`Tools added: +${diff.toolsAdded}`);
176
+ }
177
+ if (diff.toolsRemoved > 0) {
178
+ output.info(`Tools removed: -${diff.toolsRemoved}`);
179
+ }
180
+ if (diff.toolsModified > 0) {
181
+ output.info(`Tools modified: ~${diff.toolsModified}`);
182
+ }
183
+ if (diff.behaviorChanges > 0) {
184
+ output.info(`Behavior changes: ${diff.behaviorChanges}`);
185
+ }
186
+ if (diff.toolsAdded === 0 &&
187
+ diff.toolsRemoved === 0 &&
188
+ diff.toolsModified === 0 &&
189
+ diff.behaviorChanges === 0) {
190
+ output.info('No changes detected between these versions.');
191
+ }
192
+ if (diff.severity === 'breaking') {
193
+ output.info('\n⚠️ Breaking changes detected!');
194
+ output.info(' Tools were removed or modified in incompatible ways.');
195
+ }
196
+ }
197
+ catch (error) {
198
+ output.error('Failed to compute diff: ' + (error instanceof Error ? error.message : String(error)));
199
+ process.exit(EXIT_CODES.ERROR);
200
+ }
201
+ });
202
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Init command - creates a bellwether.yaml configuration file.
3
+ *
4
+ * The generated config includes ALL possible options with comments,
5
+ * making it self-documenting. Users can customize by editing the file.
6
+ */
7
+ import { Command } from 'commander';
8
+ export declare const initCommand: Command;
9
+ //# sourceMappingURL=init.d.ts.map