@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,174 @@
1
+ /**
2
+ * Health Scoring System
3
+ *
4
+ * Calculates a comprehensive health score (0-100) for an MCP server.
5
+ * Combines multiple factors: test coverage, error rate, performance, deprecation, and breaking changes.
6
+ */
7
+ import type { BehavioralBaseline, BehavioralDiff, ChangeSeverity } from './types.js';
8
+ import type { PerformanceReport } from './performance-tracker.js';
9
+ import type { DeprecationReport } from './deprecation-tracker.js';
10
+ import type { DiffImpactAnalysis } from './change-impact-analyzer.js';
11
+ /**
12
+ * Health trend direction.
13
+ */
14
+ export type HealthTrend = 'improving' | 'stable' | 'degrading';
15
+ /**
16
+ * Priority level for action items.
17
+ */
18
+ export type ActionPriority = 'critical' | 'high' | 'medium' | 'low';
19
+ /**
20
+ * Action item for improving health score.
21
+ */
22
+ export interface HealthActionItem {
23
+ /** Priority of the action */
24
+ priority: ActionPriority;
25
+ /** Category of the action */
26
+ category: 'coverage' | 'errors' | 'performance' | 'deprecation' | 'breaking_changes' | 'documentation';
27
+ /** Description of the issue */
28
+ description: string;
29
+ /** Suggested action to take */
30
+ suggestedAction: string;
31
+ /** Estimated impact on health score */
32
+ estimatedImpact: number;
33
+ /** Related tool name (if applicable) */
34
+ tool?: string;
35
+ }
36
+ /**
37
+ * Component scores that make up the overall health score.
38
+ */
39
+ export interface HealthComponents {
40
+ /** Test coverage score (0-100) - % of tools with passing tests */
41
+ testCoverage: number;
42
+ /** Error rate score (0-100) - inverse of % failing tests */
43
+ errorRate: number;
44
+ /** Performance score (0-100) - based on latency trends */
45
+ performanceScore: number;
46
+ /** Deprecation score (0-100) - penalty for deprecated tools */
47
+ deprecationScore: number;
48
+ /** Breaking change score (0-100) - penalty for breaking changes */
49
+ breakingChangeScore: number;
50
+ /** Documentation score (0-100) - based on description quality */
51
+ documentationScore: number;
52
+ }
53
+ /**
54
+ * Comprehensive health score result.
55
+ */
56
+ export interface HealthScore {
57
+ /** Overall health score (0-100) */
58
+ overall: number;
59
+ /** Individual component scores */
60
+ components: HealthComponents;
61
+ /** Health trend (requires historical data) */
62
+ trend: HealthTrend;
63
+ /** Letter grade (A-F) */
64
+ grade: string;
65
+ /** Severity classification */
66
+ severity: ChangeSeverity;
67
+ /** Prioritized action items for improvement */
68
+ actionItems: HealthActionItem[];
69
+ /** Human-readable summary */
70
+ summary: string;
71
+ /** Timestamp of when score was calculated */
72
+ calculatedAt: Date;
73
+ }
74
+ /**
75
+ * Historical health data for trend analysis.
76
+ */
77
+ export interface HealthHistory {
78
+ /** Timestamp */
79
+ timestamp: Date;
80
+ /** Overall score at that time */
81
+ overallScore: number;
82
+ /** Component scores at that time */
83
+ components: HealthComponents;
84
+ }
85
+ /**
86
+ * Input data for health calculation.
87
+ */
88
+ export interface HealthInput {
89
+ /** Current baseline */
90
+ baseline: BehavioralBaseline;
91
+ /** Diff from previous baseline (if available) */
92
+ diff?: BehavioralDiff;
93
+ /** Performance report (if available) */
94
+ performanceReport?: PerformanceReport;
95
+ /** Deprecation report (if available) */
96
+ deprecationReport?: DeprecationReport;
97
+ /** Impact analysis (if available) */
98
+ impactAnalysis?: DiffImpactAnalysis;
99
+ /** Historical health data for trend analysis */
100
+ history?: HealthHistory[];
101
+ /** Test results (tool name -> passed/failed) */
102
+ testResults?: Map<string, {
103
+ passed: number;
104
+ failed: number;
105
+ }>;
106
+ }
107
+ export { HEALTH_SCORING } from '../constants.js';
108
+ /**
109
+ * Weight configuration for component scores.
110
+ * Uses values from centralized constants.
111
+ */
112
+ export declare const HEALTH_WEIGHTS: {
113
+ readonly testCoverage: 0.25;
114
+ readonly errorRate: 0.25;
115
+ readonly performanceScore: 0.15;
116
+ readonly deprecationScore: 0.1;
117
+ readonly breakingChangeScore: 0.15;
118
+ readonly documentationScore: 0.1;
119
+ };
120
+ /**
121
+ * Grade thresholds.
122
+ * Uses values from centralized constants.
123
+ */
124
+ export declare const GRADE_THRESHOLDS: {
125
+ readonly A: 90;
126
+ readonly B: 80;
127
+ readonly C: 70;
128
+ readonly D: 60;
129
+ readonly F: 0;
130
+ };
131
+ /**
132
+ * Severity thresholds.
133
+ * Uses values from centralized constants.
134
+ */
135
+ export declare const SEVERITY_THRESHOLDS: {
136
+ readonly none: 90;
137
+ readonly info: 70;
138
+ readonly warning: 50;
139
+ readonly breaking: 0;
140
+ };
141
+ /**
142
+ * Penalty values for various issues.
143
+ * Uses values from centralized constants.
144
+ */
145
+ export declare const HEALTH_PENALTIES: {
146
+ readonly deprecatedTool: 10;
147
+ readonly expiredTool: 25;
148
+ readonly breakingChange: 15;
149
+ readonly warningChange: 5;
150
+ readonly missingDescription: 5;
151
+ readonly shortDescription: 2;
152
+ readonly performanceRegression: 10;
153
+ };
154
+ /**
155
+ * Calculate comprehensive health score for an MCP server.
156
+ */
157
+ export declare function calculateHealthScore(input: HealthInput): HealthScore;
158
+ /**
159
+ * Format health score for console output.
160
+ */
161
+ export declare function formatHealthScore(score: HealthScore): string;
162
+ /**
163
+ * Check if health score meets minimum threshold.
164
+ */
165
+ export declare function meetsHealthThreshold(score: HealthScore, minScore: number): boolean;
166
+ /**
167
+ * Get health badge color based on score.
168
+ */
169
+ export declare function getHealthBadgeColor(score: number): 'green' | 'yellow' | 'orange' | 'red';
170
+ /**
171
+ * Create a health history entry from a health score.
172
+ */
173
+ export declare function createHealthHistoryEntry(score: HealthScore): HealthHistory;
174
+ //# sourceMappingURL=health-scorer.d.ts.map
@@ -0,0 +1,451 @@
1
+ /**
2
+ * Health Scoring System
3
+ *
4
+ * Calculates a comprehensive health score (0-100) for an MCP server.
5
+ * Combines multiple factors: test coverage, error rate, performance, deprecation, and breaking changes.
6
+ */
7
+ import { HEALTH_SCORING } from '../constants.js';
8
+ // Re-export centralized constant for backwards compatibility
9
+ export { HEALTH_SCORING } from '../constants.js';
10
+ /**
11
+ * Weight configuration for component scores.
12
+ * Uses values from centralized constants.
13
+ */
14
+ export const HEALTH_WEIGHTS = HEALTH_SCORING.WEIGHTS;
15
+ /**
16
+ * Grade thresholds.
17
+ * Uses values from centralized constants.
18
+ */
19
+ export const GRADE_THRESHOLDS = HEALTH_SCORING.GRADE_THRESHOLDS;
20
+ /**
21
+ * Severity thresholds.
22
+ * Uses values from centralized constants.
23
+ */
24
+ export const SEVERITY_THRESHOLDS = HEALTH_SCORING.SEVERITY_THRESHOLDS;
25
+ /**
26
+ * Penalty values for various issues.
27
+ * Uses values from centralized constants.
28
+ */
29
+ export const HEALTH_PENALTIES = HEALTH_SCORING.PENALTIES;
30
+ /**
31
+ * Calculate comprehensive health score for an MCP server.
32
+ */
33
+ export function calculateHealthScore(input) {
34
+ const components = calculateComponents(input);
35
+ const overall = calculateOverallScore(components);
36
+ const grade = calculateGrade(overall);
37
+ const severity = calculateSeverity(overall);
38
+ const trend = calculateTrend(overall, input.history);
39
+ const actionItems = generateActionItems(input, components);
40
+ const summary = generateHealthSummary(overall, components, trend);
41
+ return {
42
+ overall,
43
+ components,
44
+ trend,
45
+ grade,
46
+ severity,
47
+ actionItems,
48
+ summary,
49
+ calculatedAt: new Date(),
50
+ };
51
+ }
52
+ /**
53
+ * Calculate individual component scores.
54
+ */
55
+ function calculateComponents(input) {
56
+ return {
57
+ testCoverage: calculateTestCoverageScore(input),
58
+ errorRate: calculateErrorRateScore(input),
59
+ performanceScore: calculatePerformanceScore(input),
60
+ deprecationScore: calculateDeprecationScore(input),
61
+ breakingChangeScore: calculateBreakingChangeScore(input),
62
+ documentationScore: calculateDocumentationScore(input),
63
+ };
64
+ }
65
+ /**
66
+ * Calculate overall score from component scores.
67
+ */
68
+ function calculateOverallScore(components) {
69
+ const weighted = components.testCoverage * HEALTH_WEIGHTS.testCoverage +
70
+ components.errorRate * HEALTH_WEIGHTS.errorRate +
71
+ components.performanceScore * HEALTH_WEIGHTS.performanceScore +
72
+ components.deprecationScore * HEALTH_WEIGHTS.deprecationScore +
73
+ components.breakingChangeScore * HEALTH_WEIGHTS.breakingChangeScore +
74
+ components.documentationScore * HEALTH_WEIGHTS.documentationScore;
75
+ return Math.round(Math.max(0, Math.min(100, weighted)));
76
+ }
77
+ /**
78
+ * Calculate test coverage score.
79
+ */
80
+ function calculateTestCoverageScore(input) {
81
+ const { baseline, testResults } = input;
82
+ if (!testResults || testResults.size === 0) {
83
+ // If no explicit test results, use tool count as proxy for coverage
84
+ const toolCount = baseline.tools.length;
85
+ if (toolCount === 0)
86
+ return 100; // No tools = perfect score
87
+ return 80; // Default score when no test data
88
+ }
89
+ const totalTools = baseline.tools.length;
90
+ const testedTools = testResults.size;
91
+ // Coverage percentage
92
+ const coveragePercent = totalTools > 0 ? (testedTools / totalTools) * 100 : 100;
93
+ return Math.round(coveragePercent);
94
+ }
95
+ /**
96
+ * Calculate error rate score (inverse of error rate).
97
+ */
98
+ function calculateErrorRateScore(input) {
99
+ const { testResults } = input;
100
+ if (!testResults || testResults.size === 0) {
101
+ return 100; // No data = assume perfect
102
+ }
103
+ let totalPassed = 0;
104
+ let totalFailed = 0;
105
+ for (const { passed, failed } of testResults.values()) {
106
+ totalPassed += passed;
107
+ totalFailed += failed;
108
+ }
109
+ const total = totalPassed + totalFailed;
110
+ if (total === 0)
111
+ return 100;
112
+ // Score is inverse of error rate
113
+ const successRate = totalPassed / total;
114
+ return Math.round(successRate * 100);
115
+ }
116
+ /**
117
+ * Calculate performance score.
118
+ */
119
+ function calculatePerformanceScore(input) {
120
+ const { performanceReport } = input;
121
+ if (!performanceReport) {
122
+ return 100; // No data = assume perfect
123
+ }
124
+ // Start with 100 and subtract penalties
125
+ let score = 100;
126
+ // Penalty for regressions
127
+ score -= performanceReport.regressionCount * HEALTH_PENALTIES.performanceRegression;
128
+ // Bonus for improvements
129
+ score += performanceReport.improvementCount * 5;
130
+ return Math.round(Math.max(0, Math.min(100, score)));
131
+ }
132
+ /**
133
+ * Calculate deprecation score.
134
+ */
135
+ function calculateDeprecationScore(input) {
136
+ const { baseline, deprecationReport } = input;
137
+ // Start with perfect score
138
+ let score = 100;
139
+ if (deprecationReport) {
140
+ // Penalty for deprecated tools
141
+ score -= deprecationReport.deprecatedCount * HEALTH_PENALTIES.deprecatedTool;
142
+ // Higher penalty for expired tools
143
+ score -= deprecationReport.expiredCount * HEALTH_PENALTIES.expiredTool;
144
+ }
145
+ else {
146
+ // Calculate from baseline directly
147
+ const deprecatedTools = baseline.tools.filter(t => t.deprecated);
148
+ score -= deprecatedTools.length * HEALTH_PENALTIES.deprecatedTool;
149
+ const expiredTools = baseline.tools.filter(t => {
150
+ if (!t.deprecated || !t.removalDate)
151
+ return false;
152
+ return new Date() > new Date(t.removalDate);
153
+ });
154
+ score -= expiredTools.length * HEALTH_PENALTIES.expiredTool;
155
+ }
156
+ return Math.round(Math.max(0, Math.min(100, score)));
157
+ }
158
+ /**
159
+ * Calculate breaking change score.
160
+ */
161
+ function calculateBreakingChangeScore(input) {
162
+ const { diff, impactAnalysis } = input;
163
+ // No changes = perfect score
164
+ if (!diff) {
165
+ return 100;
166
+ }
167
+ let score = 100;
168
+ // Penalty for removed tools
169
+ score -= diff.toolsRemoved.length * HEALTH_PENALTIES.breakingChange;
170
+ // Penalty for breaking changes
171
+ score -= diff.breakingCount * HEALTH_PENALTIES.breakingChange;
172
+ // Smaller penalty for warnings
173
+ score -= diff.warningCount * HEALTH_PENALTIES.warningChange;
174
+ // Use impact analysis if available for more accurate scoring
175
+ if (impactAnalysis) {
176
+ for (const [, impact] of impactAnalysis.toolImpacts) {
177
+ if (!impact.backwardsCompatible) {
178
+ score -= 5; // Additional penalty for non-backwards-compatible changes
179
+ }
180
+ }
181
+ }
182
+ return Math.round(Math.max(0, Math.min(100, score)));
183
+ }
184
+ /**
185
+ * Calculate documentation score.
186
+ */
187
+ function calculateDocumentationScore(input) {
188
+ const { baseline } = input;
189
+ if (baseline.tools.length === 0) {
190
+ return 100;
191
+ }
192
+ let score = 100;
193
+ for (const tool of baseline.tools) {
194
+ if (!tool.description || tool.description.trim() === '') {
195
+ score -= HEALTH_PENALTIES.missingDescription;
196
+ }
197
+ else if (tool.description.length < HEALTH_SCORING.MIN_DESCRIPTION_LENGTH) {
198
+ score -= HEALTH_PENALTIES.shortDescription;
199
+ }
200
+ }
201
+ return Math.round(Math.max(0, Math.min(100, score)));
202
+ }
203
+ /**
204
+ * Calculate letter grade from score.
205
+ */
206
+ function calculateGrade(score) {
207
+ if (score >= GRADE_THRESHOLDS.A)
208
+ return 'A';
209
+ if (score >= GRADE_THRESHOLDS.B)
210
+ return 'B';
211
+ if (score >= GRADE_THRESHOLDS.C)
212
+ return 'C';
213
+ if (score >= GRADE_THRESHOLDS.D)
214
+ return 'D';
215
+ return 'F';
216
+ }
217
+ /**
218
+ * Calculate severity from score.
219
+ */
220
+ function calculateSeverity(score) {
221
+ if (score >= SEVERITY_THRESHOLDS.none)
222
+ return 'none';
223
+ if (score >= SEVERITY_THRESHOLDS.info)
224
+ return 'info';
225
+ if (score >= SEVERITY_THRESHOLDS.warning)
226
+ return 'warning';
227
+ return 'breaking';
228
+ }
229
+ /**
230
+ * Calculate trend from historical data.
231
+ */
232
+ function calculateTrend(current, history) {
233
+ if (!history || history.length < 2) {
234
+ return 'stable';
235
+ }
236
+ // Sort by timestamp (newest first)
237
+ const sorted = [...history].sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
238
+ // Compare current to recent average
239
+ const recentScores = sorted.slice(0, HEALTH_SCORING.MAX_ACTION_ITEMS_DISPLAY).map(h => h.overallScore);
240
+ const recentAvg = recentScores.reduce((sum, s) => sum + s, 0) / recentScores.length;
241
+ const diff = current - recentAvg;
242
+ if (diff > HEALTH_SCORING.TREND_THRESHOLD)
243
+ return 'improving';
244
+ if (diff < -HEALTH_SCORING.TREND_THRESHOLD)
245
+ return 'degrading';
246
+ return 'stable';
247
+ }
248
+ /**
249
+ * Generate prioritized action items for improving health.
250
+ */
251
+ function generateActionItems(input, components) {
252
+ const items = [];
253
+ // Low test coverage
254
+ if (components.testCoverage < 80) {
255
+ items.push({
256
+ priority: components.testCoverage < 50 ? 'high' : 'medium',
257
+ category: 'coverage',
258
+ description: `Test coverage is ${components.testCoverage}%`,
259
+ suggestedAction: 'Add tests for uncovered tools',
260
+ estimatedImpact: Math.min(20, 100 - components.testCoverage) * HEALTH_WEIGHTS.testCoverage,
261
+ });
262
+ }
263
+ // High error rate
264
+ if (components.errorRate < 90) {
265
+ items.push({
266
+ priority: components.errorRate < 70 ? 'critical' : 'high',
267
+ category: 'errors',
268
+ description: `${100 - components.errorRate}% of tests are failing`,
269
+ suggestedAction: 'Fix failing tests or update test expectations',
270
+ estimatedImpact: (100 - components.errorRate) * HEALTH_WEIGHTS.errorRate,
271
+ });
272
+ }
273
+ // Performance issues
274
+ if (components.performanceScore < 80 && input.performanceReport) {
275
+ const regressions = input.performanceReport.toolComparisons.filter(c => c.hasRegression);
276
+ for (const regression of regressions) {
277
+ items.push({
278
+ priority: 'high',
279
+ category: 'performance',
280
+ description: `Performance regression detected for "${regression.toolName}"`,
281
+ suggestedAction: 'Investigate and optimize the tool implementation',
282
+ estimatedImpact: HEALTH_PENALTIES.performanceRegression * HEALTH_WEIGHTS.performanceScore,
283
+ tool: regression.toolName,
284
+ });
285
+ }
286
+ }
287
+ // Deprecation issues
288
+ if (components.deprecationScore < 100 && input.deprecationReport) {
289
+ const expired = input.deprecationReport.warnings.filter(w => w.isPastRemoval);
290
+ for (const warning of expired) {
291
+ items.push({
292
+ priority: 'critical',
293
+ category: 'deprecation',
294
+ description: `Tool "${warning.toolName}" is past its removal date`,
295
+ suggestedAction: warning.replacementTool
296
+ ? `Migrate to "${warning.replacementTool}"`
297
+ : 'Remove usage of deprecated tool',
298
+ estimatedImpact: HEALTH_PENALTIES.expiredTool * HEALTH_WEIGHTS.deprecationScore,
299
+ tool: warning.toolName,
300
+ });
301
+ }
302
+ const deprecated = input.deprecationReport.warnings.filter(w => !w.isPastRemoval);
303
+ for (const warning of deprecated) {
304
+ items.push({
305
+ priority: warning.daysUntilRemoval !== undefined && warning.daysUntilRemoval < 30 ? 'high' : 'medium',
306
+ category: 'deprecation',
307
+ description: `Tool "${warning.toolName}" is deprecated`,
308
+ suggestedAction: warning.replacementTool
309
+ ? `Plan migration to "${warning.replacementTool}"`
310
+ : 'Plan to remove deprecated tool usage',
311
+ estimatedImpact: HEALTH_PENALTIES.deprecatedTool * HEALTH_WEIGHTS.deprecationScore,
312
+ tool: warning.toolName,
313
+ });
314
+ }
315
+ }
316
+ // Breaking changes
317
+ if (components.breakingChangeScore < 100 && input.diff) {
318
+ for (const removed of input.diff.toolsRemoved) {
319
+ items.push({
320
+ priority: 'critical',
321
+ category: 'breaking_changes',
322
+ description: `Tool "${removed}" has been removed`,
323
+ suggestedAction: 'Update consumers to not depend on this tool',
324
+ estimatedImpact: HEALTH_PENALTIES.breakingChange * HEALTH_WEIGHTS.breakingChangeScore,
325
+ tool: removed,
326
+ });
327
+ }
328
+ }
329
+ // Documentation issues
330
+ if (components.documentationScore < 80) {
331
+ const undocumented = input.baseline.tools.filter(t => !t.description || t.description.trim() === '');
332
+ if (undocumented.length > 0) {
333
+ items.push({
334
+ priority: 'low',
335
+ category: 'documentation',
336
+ description: `${undocumented.length} tool(s) have no description`,
337
+ suggestedAction: 'Add descriptions to improve discoverability',
338
+ estimatedImpact: undocumented.length * HEALTH_PENALTIES.missingDescription * HEALTH_WEIGHTS.documentationScore,
339
+ });
340
+ }
341
+ }
342
+ // Sort by priority and impact
343
+ const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
344
+ items.sort((a, b) => {
345
+ const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
346
+ if (priorityDiff !== 0)
347
+ return priorityDiff;
348
+ return b.estimatedImpact - a.estimatedImpact;
349
+ });
350
+ return items;
351
+ }
352
+ /**
353
+ * Generate human-readable health summary.
354
+ */
355
+ function generateHealthSummary(overall, components, trend) {
356
+ const grade = calculateGrade(overall);
357
+ const parts = [];
358
+ parts.push(`Health Score: ${overall}/100 (Grade: ${grade})`);
359
+ // Trend indicator
360
+ const trendIndicator = trend === 'improving' ? '↗' : trend === 'degrading' ? '↘' : '→';
361
+ parts.push(`Trend: ${trendIndicator} ${trend}`);
362
+ // Highlight problem areas
363
+ const issues = [];
364
+ if (components.testCoverage < 70)
365
+ issues.push('low test coverage');
366
+ if (components.errorRate < 80)
367
+ issues.push('high error rate');
368
+ if (components.performanceScore < 70)
369
+ issues.push('performance issues');
370
+ if (components.deprecationScore < 80)
371
+ issues.push('deprecated tools');
372
+ if (components.breakingChangeScore < 70)
373
+ issues.push('breaking changes');
374
+ if (components.documentationScore < 70)
375
+ issues.push('documentation gaps');
376
+ if (issues.length > 0) {
377
+ parts.push(`Issues: ${issues.join(', ')}`);
378
+ }
379
+ else {
380
+ parts.push('No critical issues detected.');
381
+ }
382
+ return parts.join('. ');
383
+ }
384
+ /**
385
+ * Format health score for console output.
386
+ */
387
+ export function formatHealthScore(score) {
388
+ const lines = [
389
+ 'Health Report',
390
+ '═'.repeat(50),
391
+ '',
392
+ `Overall Score: ${score.overall}/100 (${score.grade})`,
393
+ `Trend: ${score.trend}`,
394
+ `Severity: ${score.severity}`,
395
+ '',
396
+ 'Component Scores:',
397
+ ` Test Coverage: ${score.components.testCoverage}%`,
398
+ ` Error Rate: ${score.components.errorRate}%`,
399
+ ` Performance: ${score.components.performanceScore}%`,
400
+ ` Deprecation: ${score.components.deprecationScore}%`,
401
+ ` Breaking Changes: ${score.components.breakingChangeScore}%`,
402
+ ` Documentation: ${score.components.documentationScore}%`,
403
+ '',
404
+ ];
405
+ if (score.actionItems.length > 0) {
406
+ lines.push('Action Items:');
407
+ const maxDisplay = HEALTH_SCORING.MAX_ACTION_ITEMS_DISPLAY;
408
+ for (const item of score.actionItems.slice(0, maxDisplay)) {
409
+ const icon = item.priority === 'critical' ? '❌' :
410
+ item.priority === 'high' ? '⚠️' :
411
+ item.priority === 'medium' ? '📝' : 'ℹ️';
412
+ lines.push(` ${icon} [${item.priority.toUpperCase()}] ${item.description}`);
413
+ lines.push(` → ${item.suggestedAction}`);
414
+ }
415
+ if (score.actionItems.length > maxDisplay) {
416
+ lines.push(` ... and ${score.actionItems.length - maxDisplay} more items`);
417
+ }
418
+ }
419
+ lines.push('');
420
+ lines.push(score.summary);
421
+ return lines.join('\n');
422
+ }
423
+ /**
424
+ * Check if health score meets minimum threshold.
425
+ */
426
+ export function meetsHealthThreshold(score, minScore) {
427
+ return score.overall >= minScore;
428
+ }
429
+ /**
430
+ * Get health badge color based on score.
431
+ */
432
+ export function getHealthBadgeColor(score) {
433
+ if (score >= 80)
434
+ return 'green';
435
+ if (score >= 60)
436
+ return 'yellow';
437
+ if (score >= 40)
438
+ return 'orange';
439
+ return 'red';
440
+ }
441
+ /**
442
+ * Create a health history entry from a health score.
443
+ */
444
+ export function createHealthHistoryEntry(score) {
445
+ return {
446
+ timestamp: score.calculatedAt,
447
+ overallScore: score.overall,
448
+ components: { ...score.components },
449
+ };
450
+ }
451
+ //# sourceMappingURL=health-scorer.js.map