specweave 0.18.0 → 0.20.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 (428) hide show
  1. package/CLAUDE.md +229 -1817
  2. package/README.md +68 -0
  3. package/bin/specweave.js +62 -6
  4. package/dist/locales/de/.gitkeep +0 -0
  5. package/dist/locales/de/cli.json +108 -0
  6. package/dist/locales/en/cli.json +287 -0
  7. package/dist/locales/en/errors.json +7 -0
  8. package/dist/locales/en/templates.json +6 -0
  9. package/dist/locales/es/.gitkeep +0 -0
  10. package/dist/locales/es/cli.json +41 -0
  11. package/dist/locales/fr/.gitkeep +0 -0
  12. package/dist/locales/fr/cli.json +108 -0
  13. package/dist/locales/ja/.gitkeep +0 -0
  14. package/dist/locales/ja/cli.json +108 -0
  15. package/dist/locales/ko/.gitkeep +0 -0
  16. package/dist/locales/ko/cli.json +108 -0
  17. package/dist/locales/pt/.gitkeep +0 -0
  18. package/dist/locales/pt/cli.json +108 -0
  19. package/dist/locales/ru/.gitkeep +0 -0
  20. package/dist/locales/ru/cli.json +269 -0
  21. package/dist/locales/zh/.gitkeep +0 -0
  22. package/dist/locales/zh/cli.json +108 -0
  23. package/dist/plugins/specweave/lib/hooks/sync-living-docs.d.ts.map +1 -1
  24. package/dist/plugins/specweave/lib/hooks/sync-living-docs.js +3 -0
  25. package/dist/plugins/specweave/lib/hooks/sync-living-docs.js.map +1 -1
  26. package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts +21 -0
  27. package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts.map +1 -0
  28. package/dist/plugins/specweave/lib/hooks/update-ac-status.js +162 -0
  29. package/dist/plugins/specweave/lib/hooks/update-ac-status.js.map +1 -0
  30. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts.map +1 -1
  31. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js +65 -6
  32. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js.map +1 -1
  33. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts +25 -0
  34. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts.map +1 -0
  35. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js +191 -0
  36. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js.map +1 -0
  37. package/dist/plugins/specweave-github/lib/completion-calculator.d.ts +112 -0
  38. package/dist/plugins/specweave-github/lib/completion-calculator.d.ts.map +1 -0
  39. package/dist/plugins/specweave-github/lib/completion-calculator.js +301 -0
  40. package/dist/plugins/specweave-github/lib/completion-calculator.js.map +1 -0
  41. package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts +3 -3
  42. package/dist/plugins/specweave-github/lib/duplicate-detector.js +3 -3
  43. package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts +70 -0
  44. package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +1 -0
  45. package/dist/plugins/specweave-github/lib/epic-content-builder.js +258 -0
  46. package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +1 -0
  47. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +14 -0
  48. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
  49. package/dist/plugins/specweave-github/lib/github-client-v2.js +51 -0
  50. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  51. package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts +2 -2
  52. package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts.map +1 -1
  53. package/dist/plugins/specweave-github/lib/github-epic-sync.js +20 -5
  54. package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +1 -1
  55. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +87 -0
  56. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -0
  57. package/dist/plugins/specweave-github/lib/github-feature-sync.js +412 -0
  58. package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -0
  59. package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
  60. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +64 -13
  61. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
  62. package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts +78 -0
  63. package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts.map +1 -0
  64. package/dist/plugins/specweave-github/lib/progress-comment-builder.js +237 -0
  65. package/dist/plugins/specweave-github/lib/progress-comment-builder.js.map +1 -0
  66. package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts +97 -0
  67. package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts.map +1 -0
  68. package/dist/plugins/specweave-github/lib/user-story-content-builder.js +301 -0
  69. package/dist/plugins/specweave-github/lib/user-story-content-builder.js.map +1 -0
  70. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts +83 -0
  71. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -0
  72. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +386 -0
  73. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -0
  74. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts +28 -0
  75. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts.map +1 -0
  76. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js +156 -0
  77. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js.map +1 -0
  78. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.d.ts +57 -0
  79. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.d.ts.map +1 -0
  80. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +248 -0
  81. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.js.map +1 -0
  82. package/dist/plugins/specweave-kafka/lib/cli/types.d.ts +82 -0
  83. package/dist/plugins/specweave-kafka/lib/cli/types.d.ts.map +1 -0
  84. package/dist/plugins/specweave-kafka/lib/cli/types.js +13 -0
  85. package/dist/plugins/specweave-kafka/lib/cli/types.js.map +1 -0
  86. package/dist/plugins/specweave-kafka/lib/mcp/detector.d.ts +49 -0
  87. package/dist/plugins/specweave-kafka/lib/mcp/detector.d.ts.map +1 -0
  88. package/dist/plugins/specweave-kafka/lib/mcp/detector.js +316 -0
  89. package/dist/plugins/specweave-kafka/lib/mcp/detector.js.map +1 -0
  90. package/dist/plugins/specweave-kafka/lib/mcp/types.d.ts +70 -0
  91. package/dist/plugins/specweave-kafka/lib/mcp/types.d.ts.map +1 -0
  92. package/dist/plugins/specweave-kafka/lib/mcp/types.js +23 -0
  93. package/dist/plugins/specweave-kafka/lib/mcp/types.js.map +1 -0
  94. package/dist/plugins/specweave-kafka/lib/utils/partitioning.d.ts +85 -0
  95. package/dist/plugins/specweave-kafka/lib/utils/partitioning.d.ts.map +1 -0
  96. package/dist/plugins/specweave-kafka/lib/utils/partitioning.js +281 -0
  97. package/dist/plugins/specweave-kafka/lib/utils/partitioning.js.map +1 -0
  98. package/dist/plugins/specweave-kafka/lib/utils/sizing.d.ts +75 -0
  99. package/dist/plugins/specweave-kafka/lib/utils/sizing.d.ts.map +1 -0
  100. package/dist/plugins/specweave-kafka/lib/utils/sizing.js +238 -0
  101. package/dist/plugins/specweave-kafka/lib/utils/sizing.js.map +1 -0
  102. package/dist/spec-parser.js +629 -0
  103. package/dist/src/cli/commands/import-docs.js +4 -4
  104. package/dist/src/cli/commands/import-docs.js.map +1 -1
  105. package/dist/src/cli/commands/init-multiproject.d.ts.map +1 -1
  106. package/dist/src/cli/commands/init-multiproject.js +17 -18
  107. package/dist/src/cli/commands/init-multiproject.js.map +1 -1
  108. package/dist/src/cli/commands/init.d.ts.map +1 -1
  109. package/dist/src/cli/commands/init.js +107 -3
  110. package/dist/src/cli/commands/init.js.map +1 -1
  111. package/dist/src/cli/commands/migrate-to-multiproject.d.ts.map +1 -1
  112. package/dist/src/cli/commands/migrate-to-multiproject.js +8 -4
  113. package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
  114. package/dist/src/cli/commands/switch-project.d.ts.map +1 -1
  115. package/dist/src/cli/commands/switch-project.js +9 -26
  116. package/dist/src/cli/commands/switch-project.js.map +1 -1
  117. package/dist/src/cli/commands/sync-spec-content.js +3 -0
  118. package/dist/src/cli/commands/sync-spec-content.js.map +1 -1
  119. package/dist/src/core/deduplication/command-deduplicator.d.ts +166 -0
  120. package/dist/src/core/deduplication/command-deduplicator.d.ts.map +1 -0
  121. package/dist/src/core/deduplication/command-deduplicator.js +254 -0
  122. package/dist/src/core/deduplication/command-deduplicator.js.map +1 -0
  123. package/dist/src/core/increment/active-increment-manager.d.ts +42 -15
  124. package/dist/src/core/increment/active-increment-manager.d.ts.map +1 -1
  125. package/dist/src/core/increment/active-increment-manager.js +113 -46
  126. package/dist/src/core/increment/active-increment-manager.js.map +1 -1
  127. package/dist/src/core/increment/conflict-resolver.d.ts +40 -0
  128. package/dist/src/core/increment/conflict-resolver.d.ts.map +1 -0
  129. package/dist/src/core/increment/conflict-resolver.js +219 -0
  130. package/dist/src/core/increment/conflict-resolver.js.map +1 -0
  131. package/dist/src/core/increment/discipline-checker.d.ts.map +1 -1
  132. package/dist/src/core/increment/discipline-checker.js +7 -1
  133. package/dist/src/core/increment/discipline-checker.js.map +1 -1
  134. package/dist/src/core/increment/duplicate-detector.d.ts +52 -0
  135. package/dist/src/core/increment/duplicate-detector.d.ts.map +1 -0
  136. package/dist/src/core/increment/duplicate-detector.js +276 -0
  137. package/dist/src/core/increment/duplicate-detector.js.map +1 -0
  138. package/dist/src/core/increment/increment-archiver.d.ts +90 -0
  139. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -0
  140. package/dist/src/core/increment/increment-archiver.js +368 -0
  141. package/dist/src/core/increment/increment-archiver.js.map +1 -0
  142. package/dist/src/core/increment/increment-reopener.d.ts +165 -0
  143. package/dist/src/core/increment/increment-reopener.d.ts.map +1 -0
  144. package/dist/src/core/increment/increment-reopener.js +390 -0
  145. package/dist/src/core/increment/increment-reopener.js.map +1 -0
  146. package/dist/src/core/increment/metadata-manager.d.ts +26 -1
  147. package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
  148. package/dist/src/core/increment/metadata-manager.js +143 -5
  149. package/dist/src/core/increment/metadata-manager.js.map +1 -1
  150. package/dist/src/core/increment/recent-work-scanner.d.ts +121 -0
  151. package/dist/src/core/increment/recent-work-scanner.d.ts.map +1 -0
  152. package/dist/src/core/increment/recent-work-scanner.js +303 -0
  153. package/dist/src/core/increment/recent-work-scanner.js.map +1 -0
  154. package/dist/src/core/increment/types.d.ts +1 -0
  155. package/dist/src/core/increment/types.d.ts.map +1 -1
  156. package/dist/src/core/increment-utils.d.ts +112 -0
  157. package/dist/src/core/increment-utils.d.ts.map +1 -0
  158. package/dist/src/core/increment-utils.js +210 -0
  159. package/dist/src/core/increment-utils.js.map +1 -0
  160. package/dist/src/core/living-docs/ac-project-specific-generator.d.ts +65 -0
  161. package/dist/src/core/living-docs/ac-project-specific-generator.d.ts.map +1 -0
  162. package/dist/src/core/living-docs/ac-project-specific-generator.js +175 -0
  163. package/dist/src/core/living-docs/ac-project-specific-generator.js.map +1 -0
  164. package/dist/src/core/living-docs/feature-archiver.d.ts +130 -0
  165. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -0
  166. package/dist/src/core/living-docs/feature-archiver.js +549 -0
  167. package/dist/src/core/living-docs/feature-archiver.js.map +1 -0
  168. package/dist/src/core/living-docs/feature-id-manager.d.ts +81 -0
  169. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -0
  170. package/dist/src/core/living-docs/feature-id-manager.js +339 -0
  171. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -0
  172. package/dist/src/core/living-docs/hierarchy-mapper.d.ts +144 -83
  173. package/dist/src/core/living-docs/hierarchy-mapper.d.ts.map +1 -1
  174. package/dist/src/core/living-docs/hierarchy-mapper.js +488 -270
  175. package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
  176. package/dist/src/core/living-docs/index.d.ts +6 -0
  177. package/dist/src/core/living-docs/index.d.ts.map +1 -1
  178. package/dist/src/core/living-docs/index.js +6 -0
  179. package/dist/src/core/living-docs/index.js.map +1 -1
  180. package/dist/src/core/living-docs/project-detector.d.ts +6 -0
  181. package/dist/src/core/living-docs/project-detector.d.ts.map +1 -1
  182. package/dist/src/core/living-docs/project-detector.js +35 -1
  183. package/dist/src/core/living-docs/project-detector.js.map +1 -1
  184. package/dist/src/core/living-docs/spec-distributor.d.ts +100 -26
  185. package/dist/src/core/living-docs/spec-distributor.d.ts.map +1 -1
  186. package/dist/src/core/living-docs/spec-distributor.js +1275 -258
  187. package/dist/src/core/living-docs/spec-distributor.js.map +1 -1
  188. package/dist/src/core/living-docs/task-project-specific-generator.d.ts +109 -0
  189. package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -0
  190. package/dist/src/core/living-docs/task-project-specific-generator.js +221 -0
  191. package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -0
  192. package/dist/src/core/living-docs/types.d.ts +143 -0
  193. package/dist/src/core/living-docs/types.d.ts.map +1 -1
  194. package/dist/src/core/project-manager.d.ts +2 -17
  195. package/dist/src/core/project-manager.d.ts.map +1 -1
  196. package/dist/src/core/project-manager.js +68 -48
  197. package/dist/src/core/project-manager.js.map +1 -1
  198. package/dist/src/core/spec-content-sync.d.ts +1 -1
  199. package/dist/src/core/spec-content-sync.d.ts.map +1 -1
  200. package/dist/src/core/sync/enhanced-content-builder.d.ts +32 -54
  201. package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -1
  202. package/dist/src/core/sync/enhanced-content-builder.js +142 -138
  203. package/dist/src/core/sync/enhanced-content-builder.js.map +1 -1
  204. package/dist/src/core/sync/performance-optimizer.d.ts +153 -0
  205. package/dist/src/core/sync/performance-optimizer.d.ts.map +1 -0
  206. package/dist/src/core/sync/performance-optimizer.js +220 -0
  207. package/dist/src/core/sync/performance-optimizer.js.map +1 -0
  208. package/dist/src/core/sync/retry-handler.d.ts +98 -0
  209. package/dist/src/core/sync/retry-handler.d.ts.map +1 -0
  210. package/dist/src/core/sync/retry-handler.js +196 -0
  211. package/dist/src/core/sync/retry-handler.js.map +1 -0
  212. package/dist/src/core/sync/spec-content-sync.d.ts +88 -0
  213. package/dist/src/core/sync/spec-content-sync.d.ts.map +1 -0
  214. package/dist/src/core/sync/spec-content-sync.js +5 -0
  215. package/dist/src/core/sync/spec-content-sync.js.map +1 -0
  216. package/dist/src/core/sync/types.d.ts +52 -0
  217. package/dist/src/core/sync/types.d.ts.map +1 -0
  218. package/dist/src/core/sync/types.js +5 -0
  219. package/dist/src/core/sync/types.js.map +1 -0
  220. package/dist/src/core/types/config.d.ts +125 -0
  221. package/dist/src/core/types/config.d.ts.map +1 -1
  222. package/dist/src/core/types/config.js +25 -0
  223. package/dist/src/core/types/config.js.map +1 -1
  224. package/dist/src/core/types/increment-metadata.d.ts +10 -0
  225. package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
  226. package/dist/src/core/types/increment-metadata.js +10 -1
  227. package/dist/src/core/types/increment-metadata.js.map +1 -1
  228. package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
  229. package/dist/src/integrations/jira/jira-incremental-mapper.js +4 -8
  230. package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
  231. package/dist/src/integrations/jira/jira-mapper.d.ts.map +1 -1
  232. package/dist/src/integrations/jira/jira-mapper.js +4 -8
  233. package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
  234. package/dist/tsconfig.tsbuildinfo +1 -0
  235. package/package.json +1 -1
  236. package/plugins/specweave/COMMANDS.md +13 -4
  237. package/plugins/specweave/agents/pm/AGENT.md +159 -12
  238. package/plugins/specweave/commands/specweave-abandon.md +22 -20
  239. package/plugins/specweave/commands/specweave-archive-features.md +121 -0
  240. package/plugins/specweave/commands/specweave-archive-increments.md +82 -0
  241. package/plugins/specweave/commands/specweave-archive.md +363 -0
  242. package/plugins/specweave/commands/specweave-backlog.md +211 -0
  243. package/plugins/specweave/commands/specweave-fix-duplicates.md +517 -0
  244. package/plugins/specweave/commands/specweave-increment.md +4 -3
  245. package/plugins/specweave/commands/specweave-progress.md +176 -27
  246. package/plugins/specweave/commands/specweave-reopen.md +391 -0
  247. package/plugins/specweave/commands/specweave-restore-feature.md +90 -0
  248. package/plugins/specweave/commands/specweave-restore.md +309 -0
  249. package/plugins/specweave/commands/specweave-resume.md +51 -23
  250. package/plugins/specweave/commands/specweave-status.md +41 -7
  251. package/plugins/specweave/commands/specweave-sync-specs.md +425 -0
  252. package/plugins/specweave/commands/specweave.md +70 -405
  253. package/plugins/specweave/hooks/hooks.json +4 -0
  254. package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
  255. package/plugins/specweave/hooks/post-increment-planning.sh +26 -2
  256. package/plugins/specweave/hooks/post-task-completion.sh +39 -0
  257. package/plugins/specweave/hooks/pre-command-deduplication.sh +83 -0
  258. package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
  259. package/plugins/specweave/lib/hooks/sync-living-docs.js +2 -0
  260. package/plugins/specweave/lib/hooks/sync-living-docs.ts +4 -0
  261. package/plugins/specweave/lib/hooks/update-ac-status.js +102 -0
  262. package/plugins/specweave/lib/hooks/update-ac-status.ts +192 -0
  263. package/plugins/specweave/skills/archive-increments/SKILL.md +198 -0
  264. package/plugins/specweave/skills/increment-planner/scripts/feature-utils.js +14 -0
  265. package/plugins/specweave/skills/smart-reopen-detector/SKILL.md +244 -0
  266. package/plugins/specweave-ado/lib/ado-spec-content-sync.js +49 -5
  267. package/plugins/specweave-ado/lib/ado-spec-content-sync.ts +72 -6
  268. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
  269. package/plugins/specweave-confluent/.claude-plugin/plugin.json +23 -0
  270. package/plugins/specweave-confluent/README.md +375 -0
  271. package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +306 -0
  272. package/plugins/specweave-confluent/skills/confluent-kafka-connect/SKILL.md +453 -0
  273. package/plugins/specweave-confluent/skills/confluent-ksqldb/SKILL.md +470 -0
  274. package/plugins/specweave-confluent/skills/confluent-schema-registry/SKILL.md +316 -0
  275. package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +2 -2
  276. package/plugins/specweave-github/agents/user-story-updater/AGENT.md +148 -0
  277. package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +1 -1
  278. package/plugins/specweave-github/commands/specweave-github-update-user-story.md +156 -0
  279. package/plugins/specweave-github/hooks/post-task-completion.sh +42 -9
  280. package/plugins/specweave-github/lib/completion-calculator.js +262 -0
  281. package/plugins/specweave-github/lib/completion-calculator.ts +434 -0
  282. package/plugins/specweave-github/lib/duplicate-detector.js +3 -3
  283. package/plugins/specweave-github/lib/duplicate-detector.ts +4 -4
  284. package/plugins/specweave-github/lib/epic-content-builder.js +265 -0
  285. package/plugins/specweave-github/lib/epic-content-builder.ts +376 -0
  286. package/plugins/specweave-github/lib/github-client-v2.js +49 -0
  287. package/plugins/specweave-github/lib/github-client-v2.ts +59 -0
  288. package/plugins/specweave-github/lib/github-epic-sync.js +23 -24
  289. package/plugins/specweave-github/lib/github-epic-sync.ts +30 -5
  290. package/plugins/specweave-github/lib/github-feature-sync.js +381 -0
  291. package/plugins/specweave-github/lib/github-feature-sync.ts +568 -0
  292. package/plugins/specweave-github/lib/github-spec-content-sync.js +40 -10
  293. package/plugins/specweave-github/lib/github-spec-content-sync.ts +82 -14
  294. package/plugins/specweave-github/lib/progress-comment-builder.js +229 -0
  295. package/plugins/specweave-github/lib/progress-comment-builder.ts +324 -0
  296. package/plugins/specweave-github/lib/user-story-content-builder.js +299 -0
  297. package/plugins/specweave-github/lib/user-story-content-builder.ts +413 -0
  298. package/plugins/specweave-github/lib/user-story-issue-builder.js +344 -0
  299. package/plugins/specweave-github/lib/user-story-issue-builder.ts +543 -0
  300. package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +189 -0
  301. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
  302. package/plugins/specweave-jira/lib/{enhanced-jira-sync.ts.disabled → enhanced-jira-sync.ts} +26 -52
  303. package/plugins/specweave-kafka/.claude-plugin/plugin.json +26 -0
  304. package/plugins/specweave-kafka/IMPLEMENTATION-COMPLETE.md +483 -0
  305. package/plugins/specweave-kafka/README.md +242 -0
  306. package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +235 -0
  307. package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +209 -0
  308. package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +266 -0
  309. package/plugins/specweave-kafka/commands/deploy.md +99 -0
  310. package/plugins/specweave-kafka/commands/dev-env.md +176 -0
  311. package/plugins/specweave-kafka/commands/mcp-configure.md +101 -0
  312. package/plugins/specweave-kafka/commands/monitor-setup.md +96 -0
  313. package/plugins/specweave-kafka/docker/kafka-local/docker-compose.yml +187 -0
  314. package/plugins/specweave-kafka/docker/redpanda/docker-compose.yml +199 -0
  315. package/plugins/specweave-kafka/docker/templates/consumer-nodejs.js +225 -0
  316. package/plugins/specweave-kafka/docker/templates/consumer-python.py +220 -0
  317. package/plugins/specweave-kafka/docker/templates/producer-nodejs.js +168 -0
  318. package/plugins/specweave-kafka/docker/templates/producer-python.py +167 -0
  319. package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.js +438 -0
  320. package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.ts +541 -0
  321. package/plugins/specweave-kafka/lib/adapters/platform-adapter.js +47 -0
  322. package/plugins/specweave-kafka/lib/adapters/platform-adapter.ts +343 -0
  323. package/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +258 -0
  324. package/plugins/specweave-kafka/lib/cli/kcat-wrapper.ts +298 -0
  325. package/plugins/specweave-kafka/lib/cli/types.js +10 -0
  326. package/plugins/specweave-kafka/lib/cli/types.ts +92 -0
  327. package/plugins/specweave-kafka/lib/connectors/connector-catalog.js +305 -0
  328. package/plugins/specweave-kafka/lib/connectors/connector-catalog.ts +528 -0
  329. package/plugins/specweave-kafka/lib/documentation/diagram-generator.js +114 -0
  330. package/plugins/specweave-kafka/lib/documentation/diagram-generator.ts +195 -0
  331. package/plugins/specweave-kafka/lib/documentation/exporter.js +210 -0
  332. package/plugins/specweave-kafka/lib/documentation/exporter.ts +338 -0
  333. package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.js +60 -0
  334. package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.ts +130 -0
  335. package/plugins/specweave-kafka/lib/documentation/topology-generator.js +143 -0
  336. package/plugins/specweave-kafka/lib/documentation/topology-generator.ts +290 -0
  337. package/plugins/specweave-kafka/lib/mcp/detector.js +298 -0
  338. package/plugins/specweave-kafka/lib/mcp/detector.ts +352 -0
  339. package/plugins/specweave-kafka/lib/mcp/types.js +21 -0
  340. package/plugins/specweave-kafka/lib/mcp/types.ts +77 -0
  341. package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.js +193 -0
  342. package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.ts +362 -0
  343. package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.js +188 -0
  344. package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.ts +359 -0
  345. package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.js +195 -0
  346. package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.ts +380 -0
  347. package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.js +209 -0
  348. package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.ts +358 -0
  349. package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.js +354 -0
  350. package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.ts +563 -0
  351. package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.js +259 -0
  352. package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.ts +516 -0
  353. package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.js +233 -0
  354. package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.ts +423 -0
  355. package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.js +266 -0
  356. package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.ts +445 -0
  357. package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.js +312 -0
  358. package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.ts +561 -0
  359. package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.js +289 -0
  360. package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.ts +607 -0
  361. package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.js +264 -0
  362. package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.ts +498 -0
  363. package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.js +263 -0
  364. package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.ts +549 -0
  365. package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.js +205 -0
  366. package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.ts +399 -0
  367. package/plugins/specweave-kafka/lib/performance/performance-optimizer.js +249 -0
  368. package/plugins/specweave-kafka/lib/performance/performance-optimizer.ts +427 -0
  369. package/plugins/specweave-kafka/lib/security/kafka-security.js +252 -0
  370. package/plugins/specweave-kafka/lib/security/kafka-security.ts +494 -0
  371. package/plugins/specweave-kafka/lib/utils/capacity-planner.js +203 -0
  372. package/plugins/specweave-kafka/lib/utils/capacity-planner.ts +469 -0
  373. package/plugins/specweave-kafka/lib/utils/config-validator.js +419 -0
  374. package/plugins/specweave-kafka/lib/utils/config-validator.ts +564 -0
  375. package/plugins/specweave-kafka/lib/utils/partitioning.js +329 -0
  376. package/plugins/specweave-kafka/lib/utils/partitioning.ts +473 -0
  377. package/plugins/specweave-kafka/lib/utils/sizing.js +221 -0
  378. package/plugins/specweave-kafka/lib/utils/sizing.ts +374 -0
  379. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-broker-metrics.json +628 -0
  380. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-cluster-overview.json +564 -0
  381. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-consumer-lag.json +509 -0
  382. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-jvm-metrics.json +674 -0
  383. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-topic-metrics.json +578 -0
  384. package/plugins/specweave-kafka/monitoring/grafana/provisioning/dashboards/kafka.yml +17 -0
  385. package/plugins/specweave-kafka/monitoring/grafana/provisioning/datasources/prometheus.yml +17 -0
  386. package/plugins/specweave-kafka/monitoring/prometheus/kafka-alerts.yml +415 -0
  387. package/plugins/specweave-kafka/monitoring/prometheus/kafka-jmx-exporter.yml +256 -0
  388. package/plugins/specweave-kafka/package.json +41 -0
  389. package/plugins/specweave-kafka/skills/kafka-architecture/SKILL.md +647 -0
  390. package/plugins/specweave-kafka/skills/kafka-cli-tools/SKILL.md +433 -0
  391. package/plugins/specweave-kafka/skills/kafka-iac-deployment/SKILL.md +449 -0
  392. package/plugins/specweave-kafka/skills/kafka-kubernetes/SKILL.md +667 -0
  393. package/plugins/specweave-kafka/skills/kafka-mcp-integration/SKILL.md +273 -0
  394. package/plugins/specweave-kafka/skills/kafka-observability/SKILL.md +576 -0
  395. package/plugins/specweave-kafka/templates/config/broker-production.properties +254 -0
  396. package/plugins/specweave-kafka/templates/config/consumer-low-latency.properties +112 -0
  397. package/plugins/specweave-kafka/templates/config/producer-high-throughput.properties +120 -0
  398. package/plugins/specweave-kafka/templates/migration/mirrormaker2-config.properties +234 -0
  399. package/plugins/specweave-kafka/templates/monitoring/grafana/multi-cluster-dashboard.json +686 -0
  400. package/plugins/specweave-kafka/terraform/apache-kafka/main.tf +347 -0
  401. package/plugins/specweave-kafka/terraform/apache-kafka/outputs.tf +107 -0
  402. package/plugins/specweave-kafka/terraform/apache-kafka/templates/kafka-broker-init.sh.tpl +216 -0
  403. package/plugins/specweave-kafka/terraform/apache-kafka/variables.tf +156 -0
  404. package/plugins/specweave-kafka/terraform/aws-msk/main.tf +362 -0
  405. package/plugins/specweave-kafka/terraform/aws-msk/outputs.tf +93 -0
  406. package/plugins/specweave-kafka/terraform/aws-msk/templates/server.properties.tpl +32 -0
  407. package/plugins/specweave-kafka/terraform/aws-msk/variables.tf +235 -0
  408. package/plugins/specweave-kafka/terraform/azure-event-hubs/main.tf +281 -0
  409. package/plugins/specweave-kafka/terraform/azure-event-hubs/outputs.tf +118 -0
  410. package/plugins/specweave-kafka/terraform/azure-event-hubs/variables.tf +148 -0
  411. package/plugins/specweave-kafka/tsconfig.json +21 -0
  412. package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +23 -0
  413. package/plugins/specweave-kafka-streams/README.md +310 -0
  414. package/plugins/specweave-kafka-streams/skills/kafka-streams-topology/SKILL.md +539 -0
  415. package/plugins/specweave-n8n/.claude-plugin/plugin.json +22 -0
  416. package/plugins/specweave-n8n/README.md +354 -0
  417. package/plugins/specweave-n8n/skills/n8n-kafka-workflows/SKILL.md +504 -0
  418. package/plugins/specweave-release/commands/specweave-release-platform.md +1 -1
  419. package/plugins/specweave-release/hooks/post-task-completion.sh +2 -2
  420. package/src/templates/AGENTS.md.template +601 -7
  421. package/src/templates/CLAUDE.md.template +188 -88
  422. package/plugins/specweave-ado/commands/specweave-ado-sync-spec.md +0 -255
  423. package/plugins/specweave-github/commands/specweave-github-sync-epic.md +0 -248
  424. package/plugins/specweave-github/commands/specweave-github-sync-from.md +0 -147
  425. package/plugins/specweave-github/commands/specweave-github-sync-spec.md +0 -208
  426. package/plugins/specweave-github/commands/specweave-github-sync-tasks.md +0 -530
  427. package/plugins/specweave-jira/commands/specweave-jira-sync-epic.md +0 -267
  428. package/plugins/specweave-jira/commands/specweave-jira-sync-spec.md +0 -240
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Cluster Switcher
3
+ *
4
+ * Provides context switching between multiple Kafka clusters
5
+ *
6
+ * @module cluster-switcher
7
+ */
8
+
9
+ import { Kafka, Admin, Producer, Consumer } from 'kafkajs';
10
+ import { ClusterConfigManager, ClusterConfig } from './cluster-config-manager';
11
+
12
+ /**
13
+ * Cluster Context
14
+ *
15
+ * Active connections to a Kafka cluster
16
+ */
17
+ export interface ClusterContext {
18
+ /** Cluster ID */
19
+ clusterId: string;
20
+ /** Cluster configuration */
21
+ config: ClusterConfig;
22
+ /** Kafka client */
23
+ kafka: Kafka;
24
+ /** Admin client (lazy initialized) */
25
+ admin?: Admin;
26
+ /** Producer (lazy initialized) */
27
+ producer?: Producer;
28
+ /** Consumers (lazy initialized) */
29
+ consumers: Map<string, Consumer>;
30
+ }
31
+
32
+ /**
33
+ * Cluster Switcher
34
+ *
35
+ * Manages active connections to multiple Kafka clusters with context switching
36
+ */
37
+ export class ClusterSwitcher {
38
+ private configManager: ClusterConfigManager;
39
+ private contexts: Map<string, ClusterContext> = new Map();
40
+ private activeContext: ClusterContext | null = null;
41
+
42
+ constructor(configManager?: ClusterConfigManager) {
43
+ this.configManager = configManager || new ClusterConfigManager();
44
+ }
45
+
46
+ /**
47
+ * Get or create cluster context
48
+ */
49
+ private async getContext(clusterId: string): Promise<ClusterContext> {
50
+ // Return cached context if exists
51
+ if (this.contexts.has(clusterId)) {
52
+ return this.contexts.get(clusterId)!;
53
+ }
54
+
55
+ // Get cluster config
56
+ const config = this.configManager.getCluster(clusterId);
57
+ if (!config) {
58
+ throw new Error(`Cluster "${clusterId}" not found`);
59
+ }
60
+
61
+ // Create Kafka client
62
+ const kafkaConfig = this.buildKafkaConfig(config);
63
+ const kafka = new Kafka(kafkaConfig);
64
+
65
+ // Create context
66
+ const context: ClusterContext = {
67
+ clusterId,
68
+ config,
69
+ kafka,
70
+ consumers: new Map(),
71
+ };
72
+
73
+ // Cache context
74
+ this.contexts.set(clusterId, context);
75
+
76
+ return context;
77
+ }
78
+
79
+ /**
80
+ * Build kafkajs configuration from cluster config
81
+ */
82
+ private buildKafkaConfig(config: ClusterConfig): any {
83
+ const kafkaConfig: any = {
84
+ clientId: `kafka-client-${config.id}`,
85
+ brokers: config.bootstrapServers,
86
+ };
87
+
88
+ // Security configuration
89
+ if (config.securityProtocol !== 'PLAINTEXT') {
90
+ if (config.securityProtocol === 'SSL' || config.securityProtocol === 'SASL_SSL') {
91
+ kafkaConfig.ssl = { rejectUnauthorized: true };
92
+ // Note: In production, load SSL certs from files
93
+ }
94
+
95
+ if (config.securityProtocol.startsWith('SASL')) {
96
+ kafkaConfig.sasl = {
97
+ mechanism: config.saslMechanism || 'PLAIN',
98
+ username: config.saslUsername || '',
99
+ password: config.saslPassword || '',
100
+ };
101
+ }
102
+ }
103
+
104
+ return kafkaConfig;
105
+ }
106
+
107
+ /**
108
+ * Switch to a different cluster
109
+ */
110
+ async switch(clusterId: string): Promise<void> {
111
+ console.log(`Switching to cluster: ${clusterId}`);
112
+
113
+ // Get or create context
114
+ const context = await this.getContext(clusterId);
115
+
116
+ // Disconnect previous context (optional - keep connections alive for faster switching)
117
+ // if (this.activeContext && this.activeContext.clusterId !== clusterId) {
118
+ // await this.disconnectContext(this.activeContext);
119
+ // }
120
+
121
+ // Set active context
122
+ this.activeContext = context;
123
+
124
+ // Update config manager active cluster
125
+ this.configManager.setActiveCluster(clusterId);
126
+
127
+ console.log(`Now connected to cluster: ${context.config.name} (${context.config.environment})`);
128
+ }
129
+
130
+ /**
131
+ * Get active cluster ID
132
+ */
133
+ getActiveClusterId(): string | null {
134
+ return this.activeContext?.clusterId || null;
135
+ }
136
+
137
+ /**
138
+ * Get active cluster configuration
139
+ */
140
+ getActiveCluster(): ClusterConfig | null {
141
+ return this.activeContext?.config || null;
142
+ }
143
+
144
+ /**
145
+ * Get Admin client for active cluster
146
+ */
147
+ async getAdmin(): Promise<Admin> {
148
+ if (!this.activeContext) {
149
+ throw new Error('No active cluster. Use switch() first.');
150
+ }
151
+
152
+ // Lazy initialize admin
153
+ if (!this.activeContext.admin) {
154
+ this.activeContext.admin = this.activeContext.kafka.admin();
155
+ await this.activeContext.admin.connect();
156
+ }
157
+
158
+ return this.activeContext.admin;
159
+ }
160
+
161
+ /**
162
+ * Get Producer for active cluster
163
+ */
164
+ async getProducer(): Promise<Producer> {
165
+ if (!this.activeContext) {
166
+ throw new Error('No active cluster. Use switch() first.');
167
+ }
168
+
169
+ // Lazy initialize producer
170
+ if (!this.activeContext.producer) {
171
+ this.activeContext.producer = this.activeContext.kafka.producer();
172
+ await this.activeContext.producer.connect();
173
+ }
174
+
175
+ return this.activeContext.producer;
176
+ }
177
+
178
+ /**
179
+ * Get or create Consumer for active cluster
180
+ */
181
+ async getConsumer(groupId: string): Promise<Consumer> {
182
+ if (!this.activeContext) {
183
+ throw new Error('No active cluster. Use switch() first.');
184
+ }
185
+
186
+ // Return existing consumer
187
+ if (this.activeContext.consumers.has(groupId)) {
188
+ return this.activeContext.consumers.get(groupId)!;
189
+ }
190
+
191
+ // Create new consumer
192
+ const consumer = this.activeContext.kafka.consumer({ groupId });
193
+ await consumer.connect();
194
+
195
+ // Cache consumer
196
+ this.activeContext.consumers.set(groupId, consumer);
197
+
198
+ return consumer;
199
+ }
200
+
201
+ /**
202
+ * Disconnect all connections for a specific cluster
203
+ */
204
+ private async disconnectContext(context: ClusterContext): Promise<void> {
205
+ console.log(`Disconnecting cluster: ${context.clusterId}`);
206
+
207
+ // Disconnect admin
208
+ if (context.admin) {
209
+ await context.admin.disconnect();
210
+ context.admin = undefined;
211
+ }
212
+
213
+ // Disconnect producer
214
+ if (context.producer) {
215
+ await context.producer.disconnect();
216
+ context.producer = undefined;
217
+ }
218
+
219
+ // Disconnect all consumers
220
+ for (const [groupId, consumer] of context.consumers.entries()) {
221
+ await consumer.disconnect();
222
+ }
223
+ context.consumers.clear();
224
+ }
225
+
226
+ /**
227
+ * Disconnect all clusters
228
+ */
229
+ async disconnectAll(): Promise<void> {
230
+ for (const context of this.contexts.values()) {
231
+ await this.disconnectContext(context);
232
+ }
233
+
234
+ this.contexts.clear();
235
+ this.activeContext = null;
236
+ }
237
+
238
+ /**
239
+ * List all available clusters
240
+ */
241
+ listClusters(): ClusterConfig[] {
242
+ return this.configManager.getAllClusters();
243
+ }
244
+
245
+ /**
246
+ * Get cluster health status
247
+ */
248
+ async getClusterHealth(clusterId?: string): Promise<{
249
+ clusterId: string;
250
+ healthy: boolean;
251
+ error?: string;
252
+ }> {
253
+ const targetClusterId = clusterId || this.activeContext?.clusterId;
254
+ if (!targetClusterId) {
255
+ throw new Error('No cluster specified and no active cluster');
256
+ }
257
+
258
+ try {
259
+ const context = await this.getContext(targetClusterId);
260
+ const admin = context.kafka.admin();
261
+ await admin.connect();
262
+
263
+ // Simple health check: list topics
264
+ await admin.listTopics();
265
+
266
+ await admin.disconnect();
267
+
268
+ return {
269
+ clusterId: targetClusterId,
270
+ healthy: true,
271
+ };
272
+ } catch (error) {
273
+ return {
274
+ clusterId: targetClusterId,
275
+ healthy: false,
276
+ error: (error as Error).message,
277
+ };
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Execute operation on specific cluster (without switching context)
283
+ */
284
+ async executeOn<T>(
285
+ clusterId: string,
286
+ operation: (kafka: Kafka) => Promise<T>
287
+ ): Promise<T> {
288
+ const context = await this.getContext(clusterId);
289
+ return operation(context.kafka);
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Example Usage: Basic Context Switching
295
+ *
296
+ * ```typescript
297
+ * const switcher = new ClusterSwitcher();
298
+ *
299
+ * // Switch to dev cluster
300
+ * await switcher.switch('dev');
301
+ * const producer = await switcher.getProducer();
302
+ * await producer.send({
303
+ * topic: 'test-topic',
304
+ * messages: [{ value: 'Hello from dev!' }],
305
+ * });
306
+ *
307
+ * // Switch to prod cluster
308
+ * await switcher.switch('prod');
309
+ * const consumer = await switcher.getConsumer('my-consumer-group');
310
+ * await consumer.subscribe({ topic: 'events' });
311
+ * await consumer.run({
312
+ * eachMessage: async ({ message }) => {
313
+ * console.log(`Prod event: ${message.value?.toString()}`);
314
+ * },
315
+ * });
316
+ * ```
317
+ */
318
+
319
+ /**
320
+ * Example Usage: Execute on Specific Cluster
321
+ *
322
+ * ```typescript
323
+ * const switcher = new ClusterSwitcher();
324
+ *
325
+ * // Active cluster: dev
326
+ * await switcher.switch('dev');
327
+ *
328
+ * // Execute operation on prod without switching
329
+ * await switcher.executeOn('prod', async (kafka) => {
330
+ * const admin = kafka.admin();
331
+ * await admin.connect();
332
+ * const topics = await admin.listTopics();
333
+ * await admin.disconnect();
334
+ * console.log(`Prod topics: ${topics.join(', ')}`);
335
+ * });
336
+ *
337
+ * // Active cluster is still dev
338
+ * console.log(`Active: ${switcher.getActiveClusterId()}`); // "dev"
339
+ * ```
340
+ */
341
+
342
+ /**
343
+ * Example Usage: Multi-Cluster Health Check
344
+ *
345
+ * ```typescript
346
+ * const switcher = new ClusterSwitcher();
347
+ * const clusters = switcher.listClusters();
348
+ *
349
+ * for (const cluster of clusters) {
350
+ * const health = await switcher.getClusterHealth(cluster.id);
351
+ * console.log(`${cluster.name}: ${health.healthy ? 'UP' : 'DOWN'}`);
352
+ * if (!health.healthy) {
353
+ * console.error(` Error: ${health.error}`);
354
+ * }
355
+ * }
356
+ * ```
357
+ */
358
+
359
+ export default ClusterSwitcher;
@@ -0,0 +1,195 @@
1
+ class HealthAggregator {
2
+ constructor(switcher) {
3
+ this.switcher = switcher;
4
+ }
5
+ /**
6
+ * Collect health metrics for a single cluster
7
+ */
8
+ async collectClusterHealth(clusterId) {
9
+ try {
10
+ const clusters = this.switcher.listClusters();
11
+ const clusterConfig = clusters.find((c) => c.id === clusterId);
12
+ if (!clusterConfig) {
13
+ throw new Error(`Cluster "${clusterId}" not found`);
14
+ }
15
+ const metrics = await this.switcher.executeOn(clusterId, async (kafka) => {
16
+ const admin = kafka.admin();
17
+ await admin.connect();
18
+ try {
19
+ const cluster = await admin.describeCluster();
20
+ const topics = await admin.listTopics();
21
+ const groups = await admin.listGroups();
22
+ const metadata = await admin.fetchTopicMetadata({ topics });
23
+ let totalPartitions = 0;
24
+ let underReplicatedPartitions = 0;
25
+ let offlinePartitions = 0;
26
+ for (const topic of metadata.topics) {
27
+ for (const partition of topic.partitions) {
28
+ totalPartitions++;
29
+ if (partition.isr.length < partition.replicas.length) {
30
+ underReplicatedPartitions++;
31
+ }
32
+ if (partition.isr.length === 0) {
33
+ offlinePartitions++;
34
+ }
35
+ }
36
+ }
37
+ return {
38
+ clusterId,
39
+ clusterName: clusterConfig.name,
40
+ environment: clusterConfig.environment,
41
+ status: this.determineStatus(underReplicatedPartitions, offlinePartitions),
42
+ brokerCount: cluster.brokers.length,
43
+ onlineBrokerCount: cluster.brokers.length,
44
+ // All in describeCluster are online
45
+ topicCount: topics.length,
46
+ partitionCount: totalPartitions,
47
+ underReplicatedPartitions,
48
+ offlinePartitions,
49
+ consumerGroupCount: groups.groups.length,
50
+ controllerId: cluster.controller ? Number(cluster.controller) : void 0,
51
+ lastCheck: /* @__PURE__ */ new Date()
52
+ };
53
+ } finally {
54
+ await admin.disconnect();
55
+ }
56
+ });
57
+ return metrics;
58
+ } catch (error) {
59
+ const clusters = this.switcher.listClusters();
60
+ const clusterConfig = clusters.find((c) => c.id === clusterId);
61
+ return {
62
+ clusterId,
63
+ clusterName: clusterConfig.name,
64
+ environment: clusterConfig.environment,
65
+ status: "down",
66
+ brokerCount: 0,
67
+ onlineBrokerCount: 0,
68
+ topicCount: 0,
69
+ partitionCount: 0,
70
+ underReplicatedPartitions: 0,
71
+ offlinePartitions: 0,
72
+ consumerGroupCount: 0,
73
+ lastCheck: /* @__PURE__ */ new Date(),
74
+ error: error.message
75
+ };
76
+ }
77
+ }
78
+ /**
79
+ * Determine cluster status based on metrics
80
+ */
81
+ determineStatus(underReplicatedPartitions, offlinePartitions) {
82
+ if (offlinePartitions > 0) {
83
+ return "down";
84
+ }
85
+ if (underReplicatedPartitions > 0) {
86
+ return "degraded";
87
+ }
88
+ return "healthy";
89
+ }
90
+ /**
91
+ * Collect health metrics for all clusters
92
+ */
93
+ async collectAllClusters() {
94
+ const clusters = this.switcher.listClusters();
95
+ const promises = clusters.map((c) => this.collectClusterHealth(c.id));
96
+ return Promise.all(promises);
97
+ }
98
+ /**
99
+ * Aggregate health across all clusters
100
+ */
101
+ async aggregateHealth() {
102
+ const clusterMetrics = await this.collectAllClusters();
103
+ let totalBrokers = 0;
104
+ let totalTopics = 0;
105
+ let totalPartitions = 0;
106
+ let totalUnderReplicatedPartitions = 0;
107
+ let healthyClusters = 0;
108
+ let degradedClusters = 0;
109
+ let downClusters = 0;
110
+ for (const metrics of clusterMetrics) {
111
+ totalBrokers += metrics.brokerCount;
112
+ totalTopics += metrics.topicCount;
113
+ totalPartitions += metrics.partitionCount;
114
+ totalUnderReplicatedPartitions += metrics.underReplicatedPartitions;
115
+ if (metrics.status === "healthy") healthyClusters++;
116
+ else if (metrics.status === "degraded") degradedClusters++;
117
+ else if (metrics.status === "down") downClusters++;
118
+ }
119
+ return {
120
+ totalClusters: clusterMetrics.length,
121
+ healthyClusters,
122
+ degradedClusters,
123
+ downClusters,
124
+ totalBrokers,
125
+ totalTopics,
126
+ totalPartitions,
127
+ totalUnderReplicatedPartitions,
128
+ clusterMetrics,
129
+ lastUpdate: /* @__PURE__ */ new Date()
130
+ };
131
+ }
132
+ /**
133
+ * Get health summary as formatted text
134
+ */
135
+ async getHealthSummaryText() {
136
+ const summary = await this.aggregateHealth();
137
+ const lines = [];
138
+ lines.push("=== Kafka Multi-Cluster Health Summary ===");
139
+ lines.push("");
140
+ lines.push(`Total Clusters: ${summary.totalClusters}`);
141
+ lines.push(` \u2713 Healthy: ${summary.healthyClusters}`);
142
+ lines.push(` \u26A0 Degraded: ${summary.degradedClusters}`);
143
+ lines.push(` \u2717 Down: ${summary.downClusters}`);
144
+ lines.push("");
145
+ lines.push(`Total Brokers: ${summary.totalBrokers}`);
146
+ lines.push(`Total Topics: ${summary.totalTopics}`);
147
+ lines.push(`Total Partitions: ${summary.totalPartitions}`);
148
+ if (summary.totalUnderReplicatedPartitions > 0) {
149
+ lines.push(`\u26A0 Under-Replicated Partitions: ${summary.totalUnderReplicatedPartitions}`);
150
+ }
151
+ lines.push("");
152
+ lines.push("=== Per-Cluster Status ===");
153
+ for (const cluster of summary.clusterMetrics) {
154
+ const icon = cluster.status === "healthy" ? "\u2713" : cluster.status === "degraded" ? "\u26A0" : "\u2717";
155
+ lines.push("");
156
+ lines.push(
157
+ `${icon} ${cluster.clusterName} (${cluster.environment}) - ${cluster.status.toUpperCase()}`
158
+ );
159
+ lines.push(` Brokers: ${cluster.onlineBrokerCount}/${cluster.brokerCount}`);
160
+ lines.push(` Topics: ${cluster.topicCount}`);
161
+ lines.push(` Partitions: ${cluster.partitionCount}`);
162
+ if (cluster.underReplicatedPartitions > 0) {
163
+ lines.push(` \u26A0 Under-Replicated: ${cluster.underReplicatedPartitions}`);
164
+ }
165
+ if (cluster.offlinePartitions > 0) {
166
+ lines.push(` \u2717 Offline: ${cluster.offlinePartitions}`);
167
+ }
168
+ if (cluster.error) {
169
+ lines.push(` Error: ${cluster.error}`);
170
+ }
171
+ }
172
+ lines.push("");
173
+ lines.push(`Last Updated: ${summary.lastUpdate.toISOString()}`);
174
+ return lines.join("\n");
175
+ }
176
+ /**
177
+ * Check if any cluster is unhealthy
178
+ */
179
+ async hasUnhealthyClusters() {
180
+ const summary = await this.aggregateHealth();
181
+ return summary.degradedClusters > 0 || summary.downClusters > 0;
182
+ }
183
+ /**
184
+ * Get list of unhealthy clusters
185
+ */
186
+ async getUnhealthyClusters() {
187
+ const clusterMetrics = await this.collectAllClusters();
188
+ return clusterMetrics.filter((c) => c.status !== "healthy");
189
+ }
190
+ }
191
+ var health_aggregator_default = HealthAggregator;
192
+ export {
193
+ HealthAggregator,
194
+ health_aggregator_default as default
195
+ };