@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,164 @@
1
+ /**
2
+ * Baseline migrate command - upgrade baselines to current format version.
3
+ *
4
+ * This command migrates baseline files from older format versions to the
5
+ * current format version, ensuring compatibility with the latest CLI features.
6
+ */
7
+ import { Command } from 'commander';
8
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
9
+ import { join } from 'path';
10
+ import { EXIT_CODES } from '../../constants.js';
11
+ import * as output from '../output.js';
12
+ import { formatVersion } from '../../baseline/version.js';
13
+ import { migrateBaseline, getMigrationInfo, } from '../../baseline/migrations.js';
14
+ import { recalculateIntegrityHash } from '../../baseline/saver.js';
15
+ import { loadConfig, ConfigNotFoundError } from '../../config/loader.js';
16
+ function loadConfigOrExit(configPath) {
17
+ try {
18
+ return loadConfig(configPath);
19
+ }
20
+ catch (error) {
21
+ if (error instanceof ConfigNotFoundError) {
22
+ output.error(error.message);
23
+ process.exit(EXIT_CODES.ERROR);
24
+ }
25
+ throw error;
26
+ }
27
+ }
28
+ /**
29
+ * Load raw baseline JSON without full validation.
30
+ * Used for migration where the format might not match current schema.
31
+ */
32
+ function loadRawBaseline(path) {
33
+ if (!existsSync(path)) {
34
+ throw new Error(`Baseline file not found: ${path}`);
35
+ }
36
+ const content = readFileSync(path, 'utf-8');
37
+ try {
38
+ return JSON.parse(content);
39
+ }
40
+ catch (error) {
41
+ throw new Error(`Invalid JSON in baseline file ${path}: ${error instanceof Error ? error.message : 'Unknown error'}`);
42
+ }
43
+ }
44
+ /**
45
+ * Save migrated baseline to file.
46
+ */
47
+ function saveMigratedBaseline(baseline, path) {
48
+ const serialized = JSON.stringify(baseline, null, 2);
49
+ writeFileSync(path, serialized, 'utf-8');
50
+ }
51
+ /**
52
+ * Create the migrate command.
53
+ */
54
+ export const migrateCommand = new Command('migrate')
55
+ .description('Migrate baseline to current format version')
56
+ .argument('[path]', 'Path to baseline file')
57
+ .option('-c, --config <path>', 'Path to config file')
58
+ .option('--dry-run', 'Show what would change without writing')
59
+ .option('-o, --output <path>', 'Output path (default: overwrite input)')
60
+ .option('-f, --force', 'Overwrite output file without prompting')
61
+ .option('--info', 'Show migration info without performing migration')
62
+ .action(async (baselinePath, options) => {
63
+ try {
64
+ const config = loadConfigOrExit(options.config);
65
+ const outputDir = config.output.dir;
66
+ const resolvedBaselinePath = baselinePath ?? config.baseline.path;
67
+ if (!resolvedBaselinePath) {
68
+ output.error('No baseline path provided. Set baseline.path in config or pass a path argument.');
69
+ process.exit(EXIT_CODES.ERROR);
70
+ }
71
+ // Resolve path
72
+ const baseDir = baselinePath ? process.cwd() : outputDir;
73
+ const fullPath = resolvedBaselinePath.startsWith('/')
74
+ ? resolvedBaselinePath
75
+ : join(baseDir, resolvedBaselinePath);
76
+ // Load raw baseline
77
+ const rawBaseline = loadRawBaseline(fullPath);
78
+ // Get migration info
79
+ const info = getMigrationInfo(rawBaseline);
80
+ // Info mode - just show status
81
+ if (options.info) {
82
+ output.info('=== Baseline Migration Info ===');
83
+ output.info(`File: ${fullPath}`);
84
+ output.info(`Current format version: ${formatVersion(info.currentVersion)}`);
85
+ output.info(`Target format version: ${formatVersion(info.targetVersion)}`);
86
+ output.info(`Needs migration: ${info.needsMigration ? 'Yes' : 'No'}`);
87
+ if (info.needsMigration) {
88
+ output.info(`Migrations to apply: ${info.migrationsToApply.join(' -> ')}`);
89
+ output.info(`Can migrate: ${info.canMigrate ? 'Yes' : 'No'}`);
90
+ }
91
+ else {
92
+ output.success('Baseline is already at the current format version.');
93
+ }
94
+ return;
95
+ }
96
+ // Check if migration is needed
97
+ if (!info.needsMigration) {
98
+ output.success(`Baseline is already at the current format version (${formatVersion(info.currentVersion)}).`);
99
+ return;
100
+ }
101
+ // Check if migration is possible
102
+ if (!info.canMigrate) {
103
+ output.error(`Cannot migrate baseline from ${formatVersion(info.currentVersion)} ` +
104
+ `to ${formatVersion(info.targetVersion)}. ` +
105
+ `This may require a newer version of the CLI.`);
106
+ process.exit(EXIT_CODES.ERROR);
107
+ }
108
+ // Dry run mode
109
+ if (options.dryRun) {
110
+ output.info('=== Dry Run - No changes will be made ===');
111
+ output.info(`File: ${fullPath}`);
112
+ output.info(`Would migrate from ${formatVersion(info.currentVersion)} to ${formatVersion(info.targetVersion)}`);
113
+ output.info(`Migrations to apply: ${info.migrationsToApply.join(' -> ')}`);
114
+ // Show what would change
115
+ const migrated = migrateBaseline(rawBaseline);
116
+ output.info('\nMigrated baseline preview:');
117
+ output.info(` Version: ${migrated.version}`);
118
+ output.info(` Tools: ${migrated.tools.length}`);
119
+ output.info(` Assertions: ${migrated.assertions.length}`);
120
+ if (migrated.workflowSignatures && migrated.workflowSignatures.length > 0) {
121
+ output.info(` Workflows: ${migrated.workflowSignatures.length}`);
122
+ }
123
+ return;
124
+ }
125
+ // Determine output path
126
+ const outputPath = options.output
127
+ ? options.output.startsWith('/')
128
+ ? options.output
129
+ : join(process.cwd(), options.output)
130
+ : fullPath;
131
+ // Check if output file exists (when different from input)
132
+ if (outputPath !== fullPath && existsSync(outputPath) && !options.force) {
133
+ output.error(`Output file already exists: ${outputPath}`);
134
+ output.error('Use --force to overwrite or specify a different --output path.');
135
+ process.exit(EXIT_CODES.ERROR);
136
+ }
137
+ // Perform migration
138
+ output.info(`Migrating baseline from ${formatVersion(info.currentVersion)} to ${formatVersion(info.targetVersion)}...`);
139
+ const migrated = migrateBaseline(rawBaseline);
140
+ // Recalculate integrity hash after migration
141
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
142
+ const { integrityHash: _, ...baselineWithoutHash } = migrated;
143
+ const finalBaseline = recalculateIntegrityHash(baselineWithoutHash);
144
+ // Save migrated baseline
145
+ saveMigratedBaseline(finalBaseline, outputPath);
146
+ output.success(`Baseline migrated successfully!`);
147
+ output.info(` From: ${formatVersion(info.currentVersion)}`);
148
+ output.info(` To: ${formatVersion(info.targetVersion)}`);
149
+ output.info(` Output: ${outputPath}`);
150
+ // Show summary
151
+ output.info('\nBaseline summary:');
152
+ output.info(` Server: ${finalBaseline.server.name} v${finalBaseline.server.version}`);
153
+ output.info(` Tools: ${finalBaseline.tools.length}`);
154
+ output.info(` Assertions: ${finalBaseline.assertions.length}`);
155
+ if (finalBaseline.workflowSignatures && finalBaseline.workflowSignatures.length > 0) {
156
+ output.info(` Workflows: ${finalBaseline.workflowSignatures.length}`);
157
+ }
158
+ }
159
+ catch (error) {
160
+ output.error(error instanceof Error ? error.message : String(error));
161
+ process.exit(EXIT_CODES.ERROR);
162
+ }
163
+ });
164
+ //# sourceMappingURL=baseline-migrate.js.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Baseline commands - manage baselines for drift detection.
3
+ *
4
+ * Subcommands:
5
+ * - save [path] Save test results as baseline
6
+ * - compare <path> Compare test results against baseline
7
+ * - show [path] Display baseline contents
8
+ * - diff <path1> <path2> Compare two baseline files
9
+ * - accept Accept detected drift as intentional
10
+ * - migrate Upgrade baseline to current format
11
+ */
12
+ import { Command } from 'commander';
13
+ export declare const baselineCommand: Command;
14
+ //# sourceMappingURL=baseline.d.ts.map
@@ -0,0 +1,449 @@
1
+ /**
2
+ * Baseline commands - manage baselines for drift detection.
3
+ *
4
+ * Subcommands:
5
+ * - save [path] Save test results as baseline
6
+ * - compare <path> Compare test results against baseline
7
+ * - show [path] Display baseline contents
8
+ * - diff <path1> <path2> Compare two baseline files
9
+ * - accept Accept detected drift as intentional
10
+ * - migrate Upgrade baseline to current format
11
+ */
12
+ import { Command } from 'commander';
13
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
14
+ import { join, basename } from 'path';
15
+ import { createBaseline, saveBaseline, loadBaseline, compareBaselines, formatDiffText, formatDiffJson, formatDiffMarkdown, formatDiffCompact, verifyIntegrity, } from '../../baseline/index.js';
16
+ import { createCloudBaseline } from '../../baseline/converter.js';
17
+ import { BaselineVersionError } from '../../baseline/version.js';
18
+ import { EXIT_CODES } from '../../constants.js';
19
+ import { migrateCommand } from './baseline-migrate.js';
20
+ import { acceptCommand } from './baseline-accept.js';
21
+ import { loadConfig, ConfigNotFoundError } from '../../config/loader.js';
22
+ import * as output from '../output.js';
23
+ /**
24
+ * Load interview result from JSON report.
25
+ * Only accepts check mode results - explore results are for documentation only.
26
+ */
27
+ function loadInterviewResult(reportPath) {
28
+ if (!existsSync(reportPath)) {
29
+ throw new Error(`Test report not found: ${reportPath}\n\n` +
30
+ 'Run `bellwether check` first with JSON output enabled.\n' +
31
+ 'Configure in bellwether.yaml:\n' +
32
+ ' output:\n' +
33
+ ' format: json # or "both" for JSON + markdown');
34
+ }
35
+ const content = readFileSync(reportPath, 'utf-8');
36
+ let result;
37
+ try {
38
+ result = JSON.parse(content);
39
+ }
40
+ catch (error) {
41
+ throw new Error(`Invalid JSON in report file ${reportPath}: ${error instanceof Error ? error.message : 'Unknown error'}`);
42
+ }
43
+ // Validate that this is a check mode result, not explore
44
+ if (result.metadata.model && result.metadata.model !== 'check') {
45
+ throw new Error(`Baseline operations only work with check mode results.\n\n` +
46
+ `The report at ${reportPath} was created with explore mode (model: ${result.metadata.model}).\n` +
47
+ `Explore results are for documentation only and cannot be used for baselines.\n\n` +
48
+ 'To create a baseline:\n' +
49
+ ' 1. Run `bellwether check` to generate a check mode report\n' +
50
+ ' 2. Run `bellwether baseline save` to create the baseline');
51
+ }
52
+ return result;
53
+ }
54
+ /**
55
+ * Get the output directory from config or use current directory.
56
+ */
57
+ function loadConfigOrExit(configPath) {
58
+ try {
59
+ return loadConfig(configPath);
60
+ }
61
+ catch (error) {
62
+ if (error instanceof ConfigNotFoundError) {
63
+ output.error(error.message);
64
+ process.exit(EXIT_CODES.ERROR);
65
+ }
66
+ throw error;
67
+ }
68
+ }
69
+ export const baselineCommand = new Command('baseline')
70
+ .description('Manage baselines for drift detection')
71
+ .addHelpText('after', `
72
+ Examples:
73
+ $ bellwether baseline save # Save baseline from last test
74
+ $ bellwether baseline save ./my-baseline.json # Save to specific path
75
+ $ bellwether baseline compare ./baseline.json # Compare test against baseline
76
+ $ bellwether baseline show # Show current baseline
77
+ $ bellwether baseline diff v1.json v2.json # Compare two baselines
78
+ $ bellwether baseline accept # Accept drift as intentional
79
+ $ bellwether baseline accept --reason "Added new feature"
80
+ $ bellwether baseline migrate # Upgrade baseline to current format
81
+ $ bellwether baseline migrate --info # Check if migration is needed
82
+ `);
83
+ baselineCommand.addCommand(migrateCommand);
84
+ baselineCommand.addCommand(acceptCommand);
85
+ // baseline save
86
+ baselineCommand
87
+ .command('save')
88
+ .description('Save test results as a baseline for drift detection')
89
+ .argument('[path]', 'Output path for baseline file')
90
+ .option('-c, --config <path>', 'Path to config file')
91
+ .option('--report <path>', 'Path to test report JSON file')
92
+ .option('--cloud', 'Save in cloud-compatible format')
93
+ .option('-f, --force', 'Overwrite existing baseline without prompting')
94
+ .action(async (baselinePath, options) => {
95
+ const config = loadConfigOrExit(options.config);
96
+ const outputDir = config.output.dir;
97
+ const defaultBaselinePath = config.baseline.savePath ?? config.baseline.path;
98
+ const resolvedBaselinePath = baselinePath ?? defaultBaselinePath;
99
+ if (!resolvedBaselinePath) {
100
+ output.error('No baseline path provided. Set baseline.path or baseline.savePath in config, or pass a path argument.');
101
+ process.exit(EXIT_CODES.ERROR);
102
+ }
103
+ // Find the report file
104
+ const reportPath = options.report || join(outputDir, config.output.files.checkReport);
105
+ // Load interview result
106
+ let result;
107
+ try {
108
+ result = loadInterviewResult(reportPath);
109
+ }
110
+ catch (error) {
111
+ output.error(error instanceof Error ? error.message : String(error));
112
+ process.exit(EXIT_CODES.ERROR);
113
+ }
114
+ // Determine baseline path (relative to output dir if not absolute)
115
+ const finalPath = resolvedBaselinePath.startsWith('/')
116
+ ? resolvedBaselinePath
117
+ : join(outputDir, resolvedBaselinePath);
118
+ // Check for existing baseline
119
+ if (existsSync(finalPath) && !options.force) {
120
+ output.error(`Baseline already exists: ${finalPath}`);
121
+ output.error('Use --force to overwrite.');
122
+ process.exit(EXIT_CODES.ERROR);
123
+ }
124
+ // Extract server command from result metadata
125
+ const serverCommand = result.metadata.serverCommand || 'unknown';
126
+ // Create and save baseline
127
+ if (options.cloud) {
128
+ const cloudBaseline = createCloudBaseline(result, serverCommand);
129
+ writeFileSync(finalPath, JSON.stringify(cloudBaseline, null, 2));
130
+ output.success(`Cloud baseline saved: ${finalPath}`);
131
+ }
132
+ else {
133
+ const baseline = createBaseline(result, serverCommand);
134
+ saveBaseline(baseline, finalPath);
135
+ output.success(`Baseline saved: ${finalPath}`);
136
+ }
137
+ // Show summary
138
+ const assertionCount = result.toolProfiles.reduce((sum, p) => sum + p.behavioralNotes.length + p.limitations.length + p.securityNotes.length, 0);
139
+ output.info(` Server: ${result.discovery.serverInfo.name} v${result.discovery.serverInfo.version}`);
140
+ output.info(` Tools: ${result.toolProfiles.length}`);
141
+ output.info(` Assertions: ${assertionCount}`);
142
+ });
143
+ // baseline compare
144
+ baselineCommand
145
+ .command('compare')
146
+ .description('Compare test results against a baseline')
147
+ .argument('[baseline-path]', 'Path to baseline file to compare against')
148
+ .option('-c, --config <path>', 'Path to config file')
149
+ .option('--report <path>', 'Path to test report JSON file')
150
+ .option('--format <format>', 'Output format: text, json, markdown, compact')
151
+ .option('--fail-on-drift', 'Exit with error if drift is detected')
152
+ .option('--ignore-version-mismatch', 'Force comparison even if format versions are incompatible')
153
+ .action(async (baselinePath, options) => {
154
+ const config = loadConfigOrExit(options.config);
155
+ const outputDir = config.output.dir;
156
+ const format = options.format ?? config.baseline.outputFormat;
157
+ const failOnDrift = options.failOnDrift ? true : config.baseline.failOnDrift;
158
+ const resolvedBaselinePath = baselinePath ?? config.baseline.comparePath ?? config.baseline.path;
159
+ // Load baseline
160
+ if (!resolvedBaselinePath) {
161
+ output.error('No baseline path provided. Set baseline.path or baseline.comparePath in config, or pass a path argument.');
162
+ process.exit(EXIT_CODES.ERROR);
163
+ }
164
+ const baselineBaseDir = baselinePath ? process.cwd() : outputDir;
165
+ const fullBaselinePath = resolvedBaselinePath.startsWith('/')
166
+ ? resolvedBaselinePath
167
+ : join(baselineBaseDir, resolvedBaselinePath);
168
+ if (!existsSync(fullBaselinePath)) {
169
+ output.error(`Baseline not found: ${fullBaselinePath}`);
170
+ process.exit(EXIT_CODES.ERROR);
171
+ }
172
+ let previousBaseline;
173
+ try {
174
+ previousBaseline = loadBaseline(fullBaselinePath);
175
+ }
176
+ catch (error) {
177
+ output.error(`Failed to load baseline: ${error instanceof Error ? error.message : error}`);
178
+ process.exit(EXIT_CODES.ERROR);
179
+ }
180
+ // Find and load the report file
181
+ const reportPath = options.report || join(outputDir, config.output.files.checkReport);
182
+ let result;
183
+ try {
184
+ result = loadInterviewResult(reportPath);
185
+ }
186
+ catch (error) {
187
+ output.error(error instanceof Error ? error.message : String(error));
188
+ process.exit(EXIT_CODES.ERROR);
189
+ }
190
+ // Create current baseline for comparison
191
+ const serverCommand = result.metadata.serverCommand || 'unknown';
192
+ const currentBaseline = createBaseline(result, serverCommand);
193
+ // Compare baselines
194
+ let diff;
195
+ try {
196
+ diff = compareBaselines(previousBaseline, currentBaseline, {
197
+ ignoreVersionMismatch: options.ignoreVersionMismatch,
198
+ });
199
+ }
200
+ catch (error) {
201
+ if (error instanceof BaselineVersionError) {
202
+ output.error('Version Compatibility Error:');
203
+ output.error(error.message);
204
+ output.error(`\nBaseline version: ${error.sourceVersion}`);
205
+ output.error(`Current version: ${error.targetVersion}`);
206
+ output.error('\nTo fix this, either:');
207
+ output.error(' 1. Run: bellwether baseline migrate <baseline-path>');
208
+ output.error(' 2. Use: --ignore-version-mismatch (results may be incorrect)');
209
+ process.exit(EXIT_CODES.ERROR);
210
+ }
211
+ throw error;
212
+ }
213
+ // Show version compatibility warning if applicable
214
+ if (diff.versionCompatibility?.warning) {
215
+ output.warn(`Version Warning: ${diff.versionCompatibility.warning}`);
216
+ output.newline();
217
+ }
218
+ // Format and output
219
+ switch (format) {
220
+ case 'json':
221
+ console.log(formatDiffJson(diff));
222
+ break;
223
+ case 'markdown':
224
+ console.log(formatDiffMarkdown(diff));
225
+ break;
226
+ case 'compact':
227
+ console.log(formatDiffCompact(diff));
228
+ break;
229
+ default:
230
+ output.info('--- Drift Report ---');
231
+ output.info(formatDiffText(diff));
232
+ }
233
+ // Show summary
234
+ const totalChanges = diff.toolsAdded.length + diff.toolsRemoved.length + diff.toolsModified.length;
235
+ output.newline();
236
+ output.info(`Changes: ${totalChanges} tools affected`);
237
+ output.info(`Severity: ${diff.severity}`);
238
+ if (diff.versionCompatibility) {
239
+ output.info(`Format versions: ${diff.versionCompatibility.sourceVersion} -> ${diff.versionCompatibility.targetVersion}`);
240
+ }
241
+ // Exit with error if drift detected and --fail-on-drift
242
+ if (failOnDrift) {
243
+ if (diff.severity === 'breaking') {
244
+ output.error('\nBreaking changes detected!');
245
+ process.exit(EXIT_CODES.ERROR);
246
+ }
247
+ else if (diff.severity === 'warning') {
248
+ output.warn('\nWarning-level changes detected.');
249
+ process.exit(EXIT_CODES.ERROR);
250
+ }
251
+ }
252
+ });
253
+ // baseline show
254
+ baselineCommand
255
+ .command('show')
256
+ .description('Display baseline contents')
257
+ .argument('[path]', 'Path to baseline file')
258
+ .option('-c, --config <path>', 'Path to config file')
259
+ .option('--json', 'Output raw JSON')
260
+ .option('--tools', 'Show only tool fingerprints')
261
+ .option('--assertions', 'Show only assertions')
262
+ .action(async (baselinePath, options) => {
263
+ const config = loadConfigOrExit(options.config);
264
+ const outputDir = config.output.dir;
265
+ const resolvedBaselinePath = baselinePath ?? config.baseline.comparePath ?? config.baseline.path;
266
+ if (!resolvedBaselinePath) {
267
+ output.error('No baseline path provided. Set baseline.path or baseline.comparePath in config, or pass a path argument.');
268
+ process.exit(EXIT_CODES.ERROR);
269
+ }
270
+ // Determine full path
271
+ const fullPath = resolvedBaselinePath.startsWith('/')
272
+ ? resolvedBaselinePath
273
+ : join(outputDir, resolvedBaselinePath);
274
+ if (!existsSync(fullPath)) {
275
+ output.error(`Baseline not found: ${fullPath}`);
276
+ output.error('\nRun `bellwether baseline save` to create a baseline.');
277
+ process.exit(EXIT_CODES.ERROR);
278
+ }
279
+ let baseline;
280
+ try {
281
+ baseline = loadBaseline(fullPath);
282
+ }
283
+ catch (error) {
284
+ output.error(`Failed to load baseline: ${error instanceof Error ? error.message : error}`);
285
+ process.exit(EXIT_CODES.ERROR);
286
+ }
287
+ // Raw JSON output
288
+ if (options.json) {
289
+ console.log(JSON.stringify(baseline, null, 2));
290
+ return;
291
+ }
292
+ // Formatted output
293
+ output.info('=== Baseline ===');
294
+ output.info(`File: ${fullPath}`);
295
+ output.info(`Format Version: ${baseline.version}`);
296
+ output.info(`Created: ${baseline.createdAt instanceof Date ? baseline.createdAt.toISOString() : baseline.createdAt}`);
297
+ output.info(`Mode: ${baseline.mode || 'check'}`);
298
+ output.info(`Server Command: ${baseline.serverCommand}`);
299
+ output.newline();
300
+ output.info('--- Server ---');
301
+ output.info(`Name: ${baseline.server.name}`);
302
+ output.info(`Version: ${baseline.server.version}`);
303
+ output.info(`Protocol: ${baseline.server.protocolVersion}`);
304
+ output.info(`Capabilities: ${baseline.server.capabilities.join(', ')}`);
305
+ output.newline();
306
+ // Tools
307
+ if (!options.assertions) {
308
+ output.info(`--- Tools (${baseline.tools.length}) ---`);
309
+ for (const tool of baseline.tools) {
310
+ output.info(`\n ${tool.name}`);
311
+ output.info(` Description: ${tool.description.slice(0, 80)}${tool.description.length > 80 ? '...' : ''}`);
312
+ output.info(` Schema Hash: ${tool.schemaHash}`);
313
+ if (tool.securityNotes.length > 0) {
314
+ output.info(` Security Notes: ${tool.securityNotes.length}`);
315
+ }
316
+ if (tool.limitations.length > 0) {
317
+ output.info(` Limitations: ${tool.limitations.length}`);
318
+ }
319
+ }
320
+ output.newline();
321
+ }
322
+ // Assertions
323
+ if (!options.tools) {
324
+ output.info(`--- Assertions (${baseline.assertions.length}) ---`);
325
+ const byTool = new Map();
326
+ for (const assertion of baseline.assertions) {
327
+ const existing = byTool.get(assertion.tool) || [];
328
+ existing.push(assertion);
329
+ byTool.set(assertion.tool, existing);
330
+ }
331
+ for (const [tool, assertions] of byTool) {
332
+ output.info(`\n ${tool}:`);
333
+ for (const a of assertions.slice(0, 5)) {
334
+ const icon = a.isPositive ? '+' : '-';
335
+ output.info(` [${icon}] ${a.aspect}: ${a.assertion.slice(0, 60)}${a.assertion.length > 60 ? '...' : ''}`);
336
+ }
337
+ if (assertions.length > 5) {
338
+ output.info(` ... and ${assertions.length - 5} more`);
339
+ }
340
+ }
341
+ output.newline();
342
+ }
343
+ // Workflows
344
+ if (baseline.workflowSignatures && baseline.workflowSignatures.length > 0) {
345
+ output.info(`--- Workflows (${baseline.workflowSignatures.length}) ---`);
346
+ for (const wf of baseline.workflowSignatures) {
347
+ const icon = wf.succeeded ? '\u2713' : '\u2717';
348
+ output.info(` ${icon} ${wf.name}: ${wf.toolSequence.join(' -> ')}`);
349
+ }
350
+ output.newline();
351
+ }
352
+ // Summary
353
+ output.info('--- Summary ---');
354
+ output.info(baseline.summary.slice(0, 500) + (baseline.summary.length > 500 ? '...' : ''));
355
+ // Integrity check
356
+ output.newline();
357
+ const isValid = verifyIntegrity(baseline);
358
+ if (isValid) {
359
+ output.success('Integrity: Valid');
360
+ }
361
+ else {
362
+ output.warn('Integrity: INVALID - file may have been modified');
363
+ }
364
+ });
365
+ // baseline diff
366
+ baselineCommand
367
+ .command('diff')
368
+ .description('Compare two baseline files')
369
+ .argument('<path1>', 'Path to first baseline file')
370
+ .argument('<path2>', 'Path to second baseline file')
371
+ .option('-c, --config <path>', 'Path to config file')
372
+ .option('--format <format>', 'Output format: text, json, markdown, compact')
373
+ .option('--ignore-version-mismatch', 'Force comparison even if format versions are incompatible')
374
+ .action(async (path1, path2, options) => {
375
+ const config = loadConfigOrExit(options.config);
376
+ const format = options.format ?? config.baseline.outputFormat;
377
+ // Load both baselines
378
+ if (!existsSync(path1)) {
379
+ output.error(`Baseline not found: ${path1}`);
380
+ process.exit(EXIT_CODES.ERROR);
381
+ }
382
+ if (!existsSync(path2)) {
383
+ output.error(`Baseline not found: ${path2}`);
384
+ process.exit(EXIT_CODES.ERROR);
385
+ }
386
+ let baseline1, baseline2;
387
+ try {
388
+ baseline1 = loadBaseline(path1);
389
+ baseline2 = loadBaseline(path2);
390
+ }
391
+ catch (error) {
392
+ output.error(`Failed to load baseline: ${error instanceof Error ? error.message : error}`);
393
+ process.exit(EXIT_CODES.ERROR);
394
+ }
395
+ // Compare
396
+ let diff;
397
+ try {
398
+ diff = compareBaselines(baseline1, baseline2, {
399
+ ignoreVersionMismatch: options.ignoreVersionMismatch,
400
+ });
401
+ }
402
+ catch (error) {
403
+ if (error instanceof BaselineVersionError) {
404
+ output.error('Version Compatibility Error:');
405
+ output.error(error.message);
406
+ output.error(`\nBaseline 1 version: ${error.sourceVersion}`);
407
+ output.error(`Baseline 2 version: ${error.targetVersion}`);
408
+ output.error('\nTo fix this, either:');
409
+ output.error(' 1. Run: bellwether baseline migrate <baseline-path>');
410
+ output.error(' 2. Use: --ignore-version-mismatch (results may be incorrect)');
411
+ process.exit(EXIT_CODES.ERROR);
412
+ }
413
+ throw error;
414
+ }
415
+ // Header
416
+ output.info(`Comparing baselines:`);
417
+ output.info(` Old: ${basename(path1)} (${baseline1.createdAt instanceof Date ? baseline1.createdAt.toISOString().split('T')[0] : 'unknown'}) [${baseline1.version}]`);
418
+ output.info(` New: ${basename(path2)} (${baseline2.createdAt instanceof Date ? baseline2.createdAt.toISOString().split('T')[0] : 'unknown'}) [${baseline2.version}]`);
419
+ output.newline();
420
+ // Show version compatibility warning if applicable
421
+ if (diff.versionCompatibility?.warning) {
422
+ output.warn(`Version Warning: ${diff.versionCompatibility.warning}`);
423
+ output.newline();
424
+ }
425
+ // Format and output
426
+ switch (format) {
427
+ case 'json':
428
+ console.log(formatDiffJson(diff));
429
+ break;
430
+ case 'markdown':
431
+ console.log(formatDiffMarkdown(diff));
432
+ break;
433
+ case 'compact':
434
+ console.log(formatDiffCompact(diff));
435
+ break;
436
+ default:
437
+ output.info(formatDiffText(diff));
438
+ }
439
+ // Summary
440
+ output.newline();
441
+ output.info(`Severity: ${diff.severity}`);
442
+ output.info(`Tools added: ${diff.toolsAdded.length}`);
443
+ output.info(`Tools removed: ${diff.toolsRemoved.length}`);
444
+ output.info(`Tools modified: ${diff.toolsModified.length}`);
445
+ if (diff.versionCompatibility) {
446
+ output.info(`Format versions: ${diff.versionCompatibility.sourceVersion} -> ${diff.versionCompatibility.targetVersion}`);
447
+ }
448
+ });
449
+ //# sourceMappingURL=baseline.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Beta command for Bellwether Cloud beta access management.
3
+ *
4
+ * Subcommands:
5
+ * - status: Check beta status and user's access
6
+ * - invite <code>: Enter and verify an invitation code
7
+ */
8
+ import { Command } from 'commander';
9
+ export declare const betaCommand: Command;
10
+ //# sourceMappingURL=beta.d.ts.map