specweave 0.18.1 → 0.20.1

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 (389) hide show
  1. package/CLAUDE.md +229 -1817
  2. package/README.md +68 -0
  3. package/bin/specweave.js +62 -6
  4. package/dist/plugins/specweave/lib/hooks/sync-living-docs.d.ts.map +1 -1
  5. package/dist/plugins/specweave/lib/hooks/sync-living-docs.js +3 -0
  6. package/dist/plugins/specweave/lib/hooks/sync-living-docs.js.map +1 -1
  7. package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts +21 -0
  8. package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts.map +1 -0
  9. package/dist/plugins/specweave/lib/hooks/update-ac-status.js +162 -0
  10. package/dist/plugins/specweave/lib/hooks/update-ac-status.js.map +1 -0
  11. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts.map +1 -1
  12. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js +65 -6
  13. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js.map +1 -1
  14. package/dist/plugins/specweave-github/lib/completion-calculator.d.ts +112 -0
  15. package/dist/plugins/specweave-github/lib/completion-calculator.d.ts.map +1 -0
  16. package/dist/plugins/specweave-github/lib/completion-calculator.js +301 -0
  17. package/dist/plugins/specweave-github/lib/completion-calculator.js.map +1 -0
  18. package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts +3 -3
  19. package/dist/plugins/specweave-github/lib/duplicate-detector.js +3 -3
  20. package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts +7 -0
  21. package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +1 -1
  22. package/dist/plugins/specweave-github/lib/epic-content-builder.js +42 -0
  23. package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +1 -1
  24. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +14 -0
  25. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
  26. package/dist/plugins/specweave-github/lib/github-client-v2.js +51 -0
  27. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  28. package/dist/plugins/specweave-github/lib/github-epic-sync.js +1 -1
  29. package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +1 -1
  30. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +87 -0
  31. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -0
  32. package/dist/plugins/specweave-github/lib/github-feature-sync.js +412 -0
  33. package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -0
  34. package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
  35. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +64 -13
  36. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
  37. package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts +78 -0
  38. package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts.map +1 -0
  39. package/dist/plugins/specweave-github/lib/progress-comment-builder.js +237 -0
  40. package/dist/plugins/specweave-github/lib/progress-comment-builder.js.map +1 -0
  41. package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts +97 -0
  42. package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts.map +1 -0
  43. package/dist/plugins/specweave-github/lib/user-story-content-builder.js +301 -0
  44. package/dist/plugins/specweave-github/lib/user-story-content-builder.js.map +1 -0
  45. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts +83 -0
  46. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -0
  47. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +386 -0
  48. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -0
  49. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts +8 -6
  50. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts.map +1 -1
  51. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js +78 -117
  52. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js.map +1 -1
  53. package/dist/src/cli/commands/import-docs.js +4 -4
  54. package/dist/src/cli/commands/import-docs.js.map +1 -1
  55. package/dist/src/cli/commands/init-multiproject.d.ts.map +1 -1
  56. package/dist/src/cli/commands/init-multiproject.js +17 -18
  57. package/dist/src/cli/commands/init-multiproject.js.map +1 -1
  58. package/dist/src/cli/commands/migrate-to-multiproject.d.ts.map +1 -1
  59. package/dist/src/cli/commands/migrate-to-multiproject.js +8 -4
  60. package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
  61. package/dist/src/cli/commands/switch-project.d.ts.map +1 -1
  62. package/dist/src/cli/commands/switch-project.js +9 -26
  63. package/dist/src/cli/commands/switch-project.js.map +1 -1
  64. package/dist/src/cli/commands/sync-spec-content.js +3 -0
  65. package/dist/src/cli/commands/sync-spec-content.js.map +1 -1
  66. package/dist/src/core/deduplication/command-deduplicator.d.ts +166 -0
  67. package/dist/src/core/deduplication/command-deduplicator.d.ts.map +1 -0
  68. package/dist/src/core/deduplication/command-deduplicator.js +254 -0
  69. package/dist/src/core/deduplication/command-deduplicator.js.map +1 -0
  70. package/dist/src/core/increment/active-increment-manager.d.ts +42 -15
  71. package/dist/src/core/increment/active-increment-manager.d.ts.map +1 -1
  72. package/dist/src/core/increment/active-increment-manager.js +113 -46
  73. package/dist/src/core/increment/active-increment-manager.js.map +1 -1
  74. package/dist/src/core/increment/conflict-resolver.d.ts +40 -0
  75. package/dist/src/core/increment/conflict-resolver.d.ts.map +1 -0
  76. package/dist/src/core/increment/conflict-resolver.js +219 -0
  77. package/dist/src/core/increment/conflict-resolver.js.map +1 -0
  78. package/dist/src/core/increment/discipline-checker.d.ts.map +1 -1
  79. package/dist/src/core/increment/discipline-checker.js +7 -1
  80. package/dist/src/core/increment/discipline-checker.js.map +1 -1
  81. package/dist/src/core/increment/duplicate-detector.d.ts +52 -0
  82. package/dist/src/core/increment/duplicate-detector.d.ts.map +1 -0
  83. package/dist/src/core/increment/duplicate-detector.js +276 -0
  84. package/dist/src/core/increment/duplicate-detector.js.map +1 -0
  85. package/dist/src/core/increment/increment-archiver.d.ts +90 -0
  86. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -0
  87. package/dist/src/core/increment/increment-archiver.js +368 -0
  88. package/dist/src/core/increment/increment-archiver.js.map +1 -0
  89. package/dist/src/core/increment/increment-reopener.d.ts +165 -0
  90. package/dist/src/core/increment/increment-reopener.d.ts.map +1 -0
  91. package/dist/src/core/increment/increment-reopener.js +390 -0
  92. package/dist/src/core/increment/increment-reopener.js.map +1 -0
  93. package/dist/src/core/increment/metadata-manager.d.ts +26 -1
  94. package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
  95. package/dist/src/core/increment/metadata-manager.js +143 -5
  96. package/dist/src/core/increment/metadata-manager.js.map +1 -1
  97. package/dist/src/core/increment/recent-work-scanner.d.ts +121 -0
  98. package/dist/src/core/increment/recent-work-scanner.d.ts.map +1 -0
  99. package/dist/src/core/increment/recent-work-scanner.js +303 -0
  100. package/dist/src/core/increment/recent-work-scanner.js.map +1 -0
  101. package/dist/src/core/increment/types.d.ts +1 -0
  102. package/dist/src/core/increment/types.d.ts.map +1 -1
  103. package/dist/src/core/increment-utils.d.ts +112 -0
  104. package/dist/src/core/increment-utils.d.ts.map +1 -0
  105. package/dist/src/core/increment-utils.js +210 -0
  106. package/dist/src/core/increment-utils.js.map +1 -0
  107. package/dist/src/core/living-docs/ac-project-specific-generator.d.ts +65 -0
  108. package/dist/src/core/living-docs/ac-project-specific-generator.d.ts.map +1 -0
  109. package/dist/src/core/living-docs/ac-project-specific-generator.js +175 -0
  110. package/dist/src/core/living-docs/ac-project-specific-generator.js.map +1 -0
  111. package/dist/src/core/living-docs/feature-archiver.d.ts +130 -0
  112. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -0
  113. package/dist/src/core/living-docs/feature-archiver.js +549 -0
  114. package/dist/src/core/living-docs/feature-archiver.js.map +1 -0
  115. package/dist/src/core/living-docs/feature-id-manager.d.ts +81 -0
  116. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -0
  117. package/dist/src/core/living-docs/feature-id-manager.js +339 -0
  118. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -0
  119. package/dist/src/core/living-docs/hierarchy-mapper.d.ts +144 -83
  120. package/dist/src/core/living-docs/hierarchy-mapper.d.ts.map +1 -1
  121. package/dist/src/core/living-docs/hierarchy-mapper.js +488 -270
  122. package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
  123. package/dist/src/core/living-docs/index.d.ts +6 -0
  124. package/dist/src/core/living-docs/index.d.ts.map +1 -1
  125. package/dist/src/core/living-docs/index.js +6 -0
  126. package/dist/src/core/living-docs/index.js.map +1 -1
  127. package/dist/src/core/living-docs/project-detector.d.ts +6 -0
  128. package/dist/src/core/living-docs/project-detector.d.ts.map +1 -1
  129. package/dist/src/core/living-docs/project-detector.js +35 -1
  130. package/dist/src/core/living-docs/project-detector.js.map +1 -1
  131. package/dist/src/core/living-docs/spec-distributor.d.ts +100 -26
  132. package/dist/src/core/living-docs/spec-distributor.d.ts.map +1 -1
  133. package/dist/src/core/living-docs/spec-distributor.js +1275 -258
  134. package/dist/src/core/living-docs/spec-distributor.js.map +1 -1
  135. package/dist/src/core/living-docs/task-project-specific-generator.d.ts +109 -0
  136. package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -0
  137. package/dist/src/core/living-docs/task-project-specific-generator.js +221 -0
  138. package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -0
  139. package/dist/src/core/living-docs/types.d.ts +143 -0
  140. package/dist/src/core/living-docs/types.d.ts.map +1 -1
  141. package/dist/src/core/project-manager.d.ts +2 -17
  142. package/dist/src/core/project-manager.d.ts.map +1 -1
  143. package/dist/src/core/project-manager.js +68 -48
  144. package/dist/src/core/project-manager.js.map +1 -1
  145. package/dist/src/core/spec-content-sync.d.ts +1 -1
  146. package/dist/src/core/spec-content-sync.d.ts.map +1 -1
  147. package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -1
  148. package/dist/src/core/sync/enhanced-content-builder.js +2 -1
  149. package/dist/src/core/sync/enhanced-content-builder.js.map +1 -1
  150. package/dist/src/core/sync/performance-optimizer.d.ts +153 -0
  151. package/dist/src/core/sync/performance-optimizer.d.ts.map +1 -0
  152. package/dist/src/core/sync/performance-optimizer.js +220 -0
  153. package/dist/src/core/sync/performance-optimizer.js.map +1 -0
  154. package/dist/src/core/sync/retry-handler.d.ts +98 -0
  155. package/dist/src/core/sync/retry-handler.d.ts.map +1 -0
  156. package/dist/src/core/sync/retry-handler.js +196 -0
  157. package/dist/src/core/sync/retry-handler.js.map +1 -0
  158. package/dist/src/core/types/config.d.ts +94 -0
  159. package/dist/src/core/types/config.d.ts.map +1 -1
  160. package/dist/src/core/types/config.js +16 -0
  161. package/dist/src/core/types/config.js.map +1 -1
  162. package/dist/src/core/types/increment-metadata.d.ts +6 -0
  163. package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
  164. package/dist/src/core/types/increment-metadata.js +10 -1
  165. package/dist/src/core/types/increment-metadata.js.map +1 -1
  166. package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
  167. package/dist/src/integrations/jira/jira-incremental-mapper.js +4 -8
  168. package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
  169. package/dist/src/integrations/jira/jira-mapper.d.ts.map +1 -1
  170. package/dist/src/integrations/jira/jira-mapper.js +4 -8
  171. package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
  172. package/package.json +1 -1
  173. package/plugins/specweave/COMMANDS.md +13 -4
  174. package/plugins/specweave/commands/specweave-abandon.md +22 -20
  175. package/plugins/specweave/commands/specweave-archive-features.md +121 -0
  176. package/plugins/specweave/commands/specweave-archive-increments.md +82 -0
  177. package/plugins/specweave/commands/specweave-archive.md +363 -0
  178. package/plugins/specweave/commands/specweave-backlog.md +211 -0
  179. package/plugins/specweave/commands/specweave-fix-duplicates.md +517 -0
  180. package/plugins/specweave/commands/specweave-increment.md +4 -3
  181. package/plugins/specweave/commands/specweave-progress.md +176 -27
  182. package/plugins/specweave/commands/specweave-reopen.md +391 -0
  183. package/plugins/specweave/commands/specweave-restore-feature.md +90 -0
  184. package/plugins/specweave/commands/specweave-restore.md +309 -0
  185. package/plugins/specweave/commands/specweave-resume.md +51 -23
  186. package/plugins/specweave/commands/specweave-status.md +41 -7
  187. package/plugins/specweave/commands/specweave-sync-specs.md +425 -0
  188. package/plugins/specweave/hooks/hooks.json +4 -0
  189. package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
  190. package/plugins/specweave/hooks/post-task-completion.sh +39 -0
  191. package/plugins/specweave/hooks/pre-command-deduplication.sh +83 -0
  192. package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
  193. package/plugins/specweave/lib/hooks/sync-living-docs.js +2 -0
  194. package/plugins/specweave/lib/hooks/sync-living-docs.ts +4 -0
  195. package/plugins/specweave/lib/hooks/update-ac-status.js +102 -0
  196. package/plugins/specweave/lib/hooks/update-ac-status.ts +192 -0
  197. package/plugins/specweave/skills/archive-increments/SKILL.md +198 -0
  198. package/plugins/specweave/skills/increment-planner/scripts/feature-utils.js +14 -0
  199. package/plugins/specweave/skills/smart-reopen-detector/SKILL.md +244 -0
  200. package/plugins/specweave-ado/lib/ado-spec-content-sync.js +49 -5
  201. package/plugins/specweave-ado/lib/ado-spec-content-sync.ts +72 -6
  202. package/plugins/specweave-confluent/.claude-plugin/plugin.json +23 -0
  203. package/plugins/specweave-confluent/README.md +375 -0
  204. package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +306 -0
  205. package/plugins/specweave-confluent/skills/confluent-kafka-connect/SKILL.md +453 -0
  206. package/plugins/specweave-confluent/skills/confluent-ksqldb/SKILL.md +470 -0
  207. package/plugins/specweave-confluent/skills/confluent-schema-registry/SKILL.md +316 -0
  208. package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +2 -2
  209. package/plugins/specweave-github/agents/user-story-updater/AGENT.md +148 -0
  210. package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +1 -1
  211. package/plugins/specweave-github/commands/specweave-github-update-user-story.md +156 -0
  212. package/plugins/specweave-github/hooks/post-task-completion.sh +10 -9
  213. package/plugins/specweave-github/lib/completion-calculator.js +262 -0
  214. package/plugins/specweave-github/lib/completion-calculator.ts +434 -0
  215. package/plugins/specweave-github/lib/duplicate-detector.js +3 -3
  216. package/plugins/specweave-github/lib/duplicate-detector.ts +4 -4
  217. package/plugins/specweave-github/lib/epic-content-builder.js +38 -0
  218. package/plugins/specweave-github/lib/epic-content-builder.ts +59 -0
  219. package/plugins/specweave-github/lib/github-client-v2.js +49 -0
  220. package/plugins/specweave-github/lib/github-client-v2.ts +59 -0
  221. package/plugins/specweave-github/lib/github-epic-sync.ts +1 -1
  222. package/plugins/specweave-github/lib/github-feature-sync.js +381 -0
  223. package/plugins/specweave-github/lib/github-feature-sync.ts +568 -0
  224. package/plugins/specweave-github/lib/github-spec-content-sync.js +40 -10
  225. package/plugins/specweave-github/lib/github-spec-content-sync.ts +82 -14
  226. package/plugins/specweave-github/lib/progress-comment-builder.js +229 -0
  227. package/plugins/specweave-github/lib/progress-comment-builder.ts +324 -0
  228. package/plugins/specweave-github/lib/user-story-content-builder.js +299 -0
  229. package/plugins/specweave-github/lib/user-story-content-builder.ts +413 -0
  230. package/plugins/specweave-github/lib/user-story-issue-builder.js +344 -0
  231. package/plugins/specweave-github/lib/user-story-issue-builder.ts +543 -0
  232. package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +189 -0
  233. package/plugins/{specweave-ado/lib/enhanced-ado-sync.js → specweave-jira/lib/enhanced-jira-sync.js} +25 -61
  234. package/plugins/specweave-jira/lib/{enhanced-jira-sync.ts.disabled → enhanced-jira-sync.ts} +26 -52
  235. package/plugins/specweave-kafka/.claude-plugin/plugin.json +26 -0
  236. package/plugins/specweave-kafka/IMPLEMENTATION-COMPLETE.md +483 -0
  237. package/plugins/specweave-kafka/README.md +242 -0
  238. package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +235 -0
  239. package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +209 -0
  240. package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +266 -0
  241. package/plugins/specweave-kafka/commands/deploy.md +99 -0
  242. package/plugins/specweave-kafka/commands/dev-env.md +176 -0
  243. package/plugins/specweave-kafka/commands/mcp-configure.md +101 -0
  244. package/plugins/specweave-kafka/commands/monitor-setup.md +96 -0
  245. package/plugins/specweave-kafka/docker/kafka-local/docker-compose.yml +187 -0
  246. package/plugins/specweave-kafka/docker/redpanda/docker-compose.yml +199 -0
  247. package/plugins/specweave-kafka/docker/templates/consumer-nodejs.js +225 -0
  248. package/plugins/specweave-kafka/docker/templates/consumer-python.py +220 -0
  249. package/plugins/specweave-kafka/docker/templates/producer-nodejs.js +168 -0
  250. package/plugins/specweave-kafka/docker/templates/producer-python.py +167 -0
  251. package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.js +438 -0
  252. package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.ts +541 -0
  253. package/plugins/specweave-kafka/lib/adapters/platform-adapter.js +47 -0
  254. package/plugins/specweave-kafka/lib/adapters/platform-adapter.ts +343 -0
  255. package/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +258 -0
  256. package/plugins/specweave-kafka/lib/cli/kcat-wrapper.ts +298 -0
  257. package/plugins/specweave-kafka/lib/cli/types.js +10 -0
  258. package/plugins/specweave-kafka/lib/cli/types.ts +92 -0
  259. package/plugins/specweave-kafka/lib/connectors/connector-catalog.js +305 -0
  260. package/plugins/specweave-kafka/lib/connectors/connector-catalog.ts +528 -0
  261. package/plugins/specweave-kafka/lib/documentation/diagram-generator.js +114 -0
  262. package/plugins/specweave-kafka/lib/documentation/diagram-generator.ts +195 -0
  263. package/plugins/specweave-kafka/lib/documentation/exporter.js +210 -0
  264. package/plugins/specweave-kafka/lib/documentation/exporter.ts +338 -0
  265. package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.js +60 -0
  266. package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.ts +130 -0
  267. package/plugins/specweave-kafka/lib/documentation/topology-generator.js +143 -0
  268. package/plugins/specweave-kafka/lib/documentation/topology-generator.ts +290 -0
  269. package/plugins/specweave-kafka/lib/mcp/detector.js +298 -0
  270. package/plugins/specweave-kafka/lib/mcp/detector.ts +352 -0
  271. package/plugins/specweave-kafka/lib/mcp/types.js +21 -0
  272. package/plugins/specweave-kafka/lib/mcp/types.ts +77 -0
  273. package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.js +193 -0
  274. package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.ts +362 -0
  275. package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.js +188 -0
  276. package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.ts +359 -0
  277. package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.js +195 -0
  278. package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.ts +380 -0
  279. package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.js +209 -0
  280. package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.ts +358 -0
  281. package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.js +354 -0
  282. package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.ts +563 -0
  283. package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.js +259 -0
  284. package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.ts +516 -0
  285. package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.js +233 -0
  286. package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.ts +423 -0
  287. package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.js +266 -0
  288. package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.ts +445 -0
  289. package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.js +312 -0
  290. package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.ts +561 -0
  291. package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.js +289 -0
  292. package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.ts +607 -0
  293. package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.js +264 -0
  294. package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.ts +498 -0
  295. package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.js +263 -0
  296. package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.ts +549 -0
  297. package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.js +205 -0
  298. package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.ts +399 -0
  299. package/plugins/specweave-kafka/lib/performance/performance-optimizer.js +249 -0
  300. package/plugins/specweave-kafka/lib/performance/performance-optimizer.ts +427 -0
  301. package/plugins/specweave-kafka/lib/security/kafka-security.js +252 -0
  302. package/plugins/specweave-kafka/lib/security/kafka-security.ts +494 -0
  303. package/plugins/specweave-kafka/lib/utils/capacity-planner.js +203 -0
  304. package/plugins/specweave-kafka/lib/utils/capacity-planner.ts +469 -0
  305. package/plugins/specweave-kafka/lib/utils/config-validator.js +419 -0
  306. package/plugins/specweave-kafka/lib/utils/config-validator.ts +564 -0
  307. package/plugins/specweave-kafka/lib/utils/partitioning.js +329 -0
  308. package/plugins/specweave-kafka/lib/utils/partitioning.ts +473 -0
  309. package/plugins/specweave-kafka/lib/utils/sizing.js +221 -0
  310. package/plugins/specweave-kafka/lib/utils/sizing.ts +374 -0
  311. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-broker-metrics.json +628 -0
  312. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-cluster-overview.json +564 -0
  313. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-consumer-lag.json +509 -0
  314. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-jvm-metrics.json +674 -0
  315. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-topic-metrics.json +578 -0
  316. package/plugins/specweave-kafka/monitoring/grafana/provisioning/dashboards/kafka.yml +17 -0
  317. package/plugins/specweave-kafka/monitoring/grafana/provisioning/datasources/prometheus.yml +17 -0
  318. package/plugins/specweave-kafka/monitoring/prometheus/kafka-alerts.yml +415 -0
  319. package/plugins/specweave-kafka/monitoring/prometheus/kafka-jmx-exporter.yml +256 -0
  320. package/plugins/specweave-kafka/package.json +41 -0
  321. package/plugins/specweave-kafka/skills/kafka-architecture/SKILL.md +647 -0
  322. package/plugins/specweave-kafka/skills/kafka-cli-tools/SKILL.md +433 -0
  323. package/plugins/specweave-kafka/skills/kafka-iac-deployment/SKILL.md +449 -0
  324. package/plugins/specweave-kafka/skills/kafka-kubernetes/SKILL.md +667 -0
  325. package/plugins/specweave-kafka/skills/kafka-mcp-integration/SKILL.md +273 -0
  326. package/plugins/specweave-kafka/skills/kafka-observability/SKILL.md +576 -0
  327. package/plugins/specweave-kafka/templates/config/broker-production.properties +254 -0
  328. package/plugins/specweave-kafka/templates/config/consumer-low-latency.properties +112 -0
  329. package/plugins/specweave-kafka/templates/config/producer-high-throughput.properties +120 -0
  330. package/plugins/specweave-kafka/templates/migration/mirrormaker2-config.properties +234 -0
  331. package/plugins/specweave-kafka/templates/monitoring/grafana/multi-cluster-dashboard.json +686 -0
  332. package/plugins/specweave-kafka/terraform/apache-kafka/main.tf +347 -0
  333. package/plugins/specweave-kafka/terraform/apache-kafka/outputs.tf +107 -0
  334. package/plugins/specweave-kafka/terraform/apache-kafka/templates/kafka-broker-init.sh.tpl +216 -0
  335. package/plugins/specweave-kafka/terraform/apache-kafka/variables.tf +156 -0
  336. package/plugins/specweave-kafka/terraform/aws-msk/main.tf +362 -0
  337. package/plugins/specweave-kafka/terraform/aws-msk/outputs.tf +93 -0
  338. package/plugins/specweave-kafka/terraform/aws-msk/templates/server.properties.tpl +32 -0
  339. package/plugins/specweave-kafka/terraform/aws-msk/variables.tf +235 -0
  340. package/plugins/specweave-kafka/terraform/azure-event-hubs/main.tf +281 -0
  341. package/plugins/specweave-kafka/terraform/azure-event-hubs/outputs.tf +118 -0
  342. package/plugins/specweave-kafka/terraform/azure-event-hubs/variables.tf +148 -0
  343. package/plugins/specweave-kafka/tsconfig.json +21 -0
  344. package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +23 -0
  345. package/plugins/specweave-kafka-streams/README.md +310 -0
  346. package/plugins/specweave-kafka-streams/skills/kafka-streams-topology/SKILL.md +539 -0
  347. package/plugins/specweave-n8n/.claude-plugin/plugin.json +22 -0
  348. package/plugins/specweave-n8n/README.md +354 -0
  349. package/plugins/specweave-n8n/skills/n8n-kafka-workflows/SKILL.md +504 -0
  350. package/plugins/specweave-release/commands/specweave-release-platform.md +1 -1
  351. package/plugins/specweave-release/hooks/post-task-completion.sh +2 -2
  352. package/src/templates/AGENTS.md.template +601 -7
  353. package/src/templates/CLAUDE.md.template +188 -88
  354. package/dist/locales/de/.gitkeep +0 -0
  355. package/dist/locales/de/cli.json +0 -108
  356. package/dist/locales/en/cli.json +0 -287
  357. package/dist/locales/en/errors.json +0 -7
  358. package/dist/locales/en/templates.json +0 -6
  359. package/dist/locales/es/.gitkeep +0 -0
  360. package/dist/locales/es/cli.json +0 -41
  361. package/dist/locales/fr/.gitkeep +0 -0
  362. package/dist/locales/fr/cli.json +0 -108
  363. package/dist/locales/ja/.gitkeep +0 -0
  364. package/dist/locales/ja/cli.json +0 -108
  365. package/dist/locales/ko/.gitkeep +0 -0
  366. package/dist/locales/ko/cli.json +0 -108
  367. package/dist/locales/pt/.gitkeep +0 -0
  368. package/dist/locales/pt/cli.json +0 -108
  369. package/dist/locales/ru/.gitkeep +0 -0
  370. package/dist/locales/ru/cli.json +0 -269
  371. package/dist/locales/zh/.gitkeep +0 -0
  372. package/dist/locales/zh/cli.json +0 -108
  373. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts +0 -25
  374. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts.map +0 -1
  375. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -191
  376. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js.map +0 -1
  377. package/dist/spec-parser.js +0 -629
  378. package/dist/src/core/sync/spec-content-sync.d.ts +0 -88
  379. package/dist/src/core/sync/spec-content-sync.d.ts.map +0 -1
  380. package/dist/src/core/sync/spec-content-sync.js +0 -5
  381. package/dist/src/core/sync/spec-content-sync.js.map +0 -1
  382. package/dist/tsconfig.tsbuildinfo +0 -1
  383. package/plugins/specweave-ado/commands/specweave-ado-sync-spec.md +0 -255
  384. package/plugins/specweave-github/commands/specweave-github-sync-epic.md +0 -248
  385. package/plugins/specweave-github/commands/specweave-github-sync-from.md +0 -147
  386. package/plugins/specweave-github/commands/specweave-github-sync-spec.md +0 -208
  387. package/plugins/specweave-github/commands/specweave-github-sync-tasks.md +0 -530
  388. package/plugins/specweave-jira/commands/specweave-jira-sync-epic.md +0 -267
  389. package/plugins/specweave-jira/commands/specweave-jira-sync-spec.md +0 -240
@@ -0,0 +1,473 @@
1
+ /**
2
+ * Partitioning Strategy Analyzer
3
+ *
4
+ * Analyzes partition key distribution and provides recommendations
5
+ * for optimal Kafka topic partitioning strategies.
6
+ */
7
+
8
+ export interface PartitionKeyAnalysis {
9
+ key: string;
10
+ sampleValues: string[];
11
+ estimatedCardinality: number;
12
+ distribution: 'uniform' | 'skewed' | 'severely-skewed';
13
+ hotspotRisk: 'low' | 'medium' | 'high';
14
+ }
15
+
16
+ export interface PartitioningRecommendation {
17
+ recommendedPartitions: number;
18
+ keyStrategy: 'simple-hash' | 'compound-hash' | 'custom-partitioner' | 'round-robin';
19
+ keyField: string | null;
20
+ reasoning: string;
21
+ warnings: string[];
22
+ examples: string[];
23
+ }
24
+
25
+ export interface PartitionAnalysisRequest {
26
+ // Topic metadata
27
+ topicName: string;
28
+ currentPartitionCount?: number;
29
+
30
+ // Workload characteristics
31
+ expectedMessagesPerSecond: number;
32
+ peakMultiplier?: number; // Default: 3x (peak = 3x average)
33
+
34
+ // Key characteristics
35
+ potentialKeys: Array<{
36
+ fieldName: string;
37
+ sampleValues: string[];
38
+ estimatedUniqueCount: number;
39
+ }>;
40
+
41
+ // Business requirements
42
+ orderingRequired: boolean;
43
+ targetLatencyMs?: number; // Default: 100ms
44
+ targetThroughputMBps?: number;
45
+ }
46
+
47
+ export class PartitioningStrategyAnalyzer {
48
+ private readonly MAX_PARTITION_THROUGHPUT_MBPS = 20;
49
+ private readonly MAX_PARTITION_MSG_PER_SEC = 50000;
50
+ private readonly IDEAL_PARTITIONS_PER_CONSUMER = 2;
51
+
52
+ /**
53
+ * Analyze partition key candidates and recommend strategy
54
+ */
55
+ analyze(req: PartitionAnalysisRequest): PartitioningRecommendation {
56
+ const peakMultiplier = req.peakMultiplier ?? 3;
57
+ const targetLatency = req.targetLatencyMs ?? 100;
58
+ const peakMessagesPerSec = req.expectedMessagesPerSecond * peakMultiplier;
59
+
60
+ // Analyze each potential key
61
+ const keyAnalyses = req.potentialKeys.map(key => this.analyzeKey(key));
62
+
63
+ // Find best key based on distribution
64
+ const bestKey = this.selectBestKey(keyAnalyses, req.orderingRequired);
65
+
66
+ // Calculate partitions needed based on throughput
67
+ let partitionsForThroughput = 1;
68
+ if (req.targetThroughputMBps) {
69
+ partitionsForThroughput = Math.ceil(
70
+ req.targetThroughputMBps / this.MAX_PARTITION_THROUGHPUT_MBPS
71
+ );
72
+ }
73
+
74
+ // Calculate partitions needed based on message rate
75
+ const partitionsForMsgRate = Math.ceil(
76
+ peakMessagesPerSec / this.MAX_PARTITION_MSG_PER_SEC
77
+ );
78
+
79
+ // Calculate partitions for consumer parallelism
80
+ const partitionsForParallelism = Math.max(4, partitionsForMsgRate * this.IDEAL_PARTITIONS_PER_CONSUMER);
81
+
82
+ // Take maximum (most constraining)
83
+ let recommendedPartitions = Math.max(
84
+ partitionsForThroughput,
85
+ partitionsForMsgRate,
86
+ partitionsForParallelism
87
+ );
88
+
89
+ // Round up to nearest power of 2 or multiple of 3 (for rack awareness)
90
+ if (recommendedPartitions <= 16) {
91
+ recommendedPartitions = this.nextPowerOfTwo(recommendedPartitions);
92
+ } else {
93
+ recommendedPartitions = Math.ceil(recommendedPartitions / 12) * 12; // Multiple of 12 (3 racks × 4)
94
+ }
95
+
96
+ // Ensure minimum partitions
97
+ recommendedPartitions = Math.max(recommendedPartitions, 3);
98
+
99
+ // Determine key strategy
100
+ const { keyStrategy, keyField, reasoning } = this.determineKeyStrategy(
101
+ bestKey,
102
+ req.orderingRequired,
103
+ recommendedPartitions
104
+ );
105
+
106
+ // Generate warnings
107
+ const warnings = this.generateWarnings({
108
+ bestKey,
109
+ recommendedPartitions,
110
+ currentPartitionCount: req.currentPartitionCount,
111
+ req
112
+ });
113
+
114
+ // Generate usage examples
115
+ const examples = this.generateExamples(keyStrategy, keyField, req.topicName);
116
+
117
+ return {
118
+ recommendedPartitions,
119
+ keyStrategy,
120
+ keyField,
121
+ reasoning,
122
+ warnings,
123
+ examples
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Analyze a single partition key candidate
129
+ */
130
+ private analyzeKey(key: { fieldName: string; sampleValues: string[]; estimatedUniqueCount: number }): PartitionKeyAnalysis {
131
+ const cardinality = key.estimatedUniqueCount;
132
+ const sampleSize = key.sampleValues.length;
133
+
134
+ // Estimate distribution from sample
135
+ const uniqueInSample = new Set(key.sampleValues).size;
136
+ const uniquenessRatio = uniqueInSample / sampleSize;
137
+
138
+ // Classify distribution
139
+ let distribution: 'uniform' | 'skewed' | 'severely-skewed';
140
+ if (uniquenessRatio > 0.9) {
141
+ distribution = 'uniform'; // Most values are unique
142
+ } else if (uniquenessRatio > 0.5) {
143
+ distribution = 'skewed'; // Some duplicate values
144
+ } else {
145
+ distribution = 'severely-skewed'; // Many duplicate values
146
+ }
147
+
148
+ // Assess hotspot risk
149
+ let hotspotRisk: 'low' | 'medium' | 'high';
150
+ if (cardinality > 10000 && distribution === 'uniform') {
151
+ hotspotRisk = 'low';
152
+ } else if (cardinality > 1000 && distribution !== 'severely-skewed') {
153
+ hotspotRisk = 'medium';
154
+ } else {
155
+ hotspotRisk = 'high';
156
+ }
157
+
158
+ return {
159
+ key: key.fieldName,
160
+ sampleValues: key.sampleValues.slice(0, 5), // Top 5 examples
161
+ estimatedCardinality: cardinality,
162
+ distribution,
163
+ hotspotRisk
164
+ };
165
+ }
166
+
167
+ /**
168
+ * Select best partition key from candidates
169
+ */
170
+ private selectBestKey(
171
+ analyses: PartitionKeyAnalysis[],
172
+ orderingRequired: boolean
173
+ ): PartitionKeyAnalysis {
174
+ // Sort by hotspot risk (low is best) and cardinality (high is best)
175
+ const sorted = [...analyses].sort((a, b) => {
176
+ const riskScore = { low: 0, medium: 1, high: 2 };
177
+ const riskDiff = riskScore[a.hotspotRisk] - riskScore[b.hotspotRisk];
178
+
179
+ if (riskDiff !== 0) return riskDiff; // Lower risk wins
180
+
181
+ // If risks equal, higher cardinality wins
182
+ return b.estimatedCardinality - a.estimatedCardinality;
183
+ });
184
+
185
+ return sorted[0];
186
+ }
187
+
188
+ /**
189
+ * Determine optimal partitioning key strategy
190
+ */
191
+ private determineKeyStrategy(
192
+ bestKey: PartitionKeyAnalysis | null,
193
+ orderingRequired: boolean,
194
+ partitionCount: number
195
+ ): { keyStrategy: string; keyField: string | null; reasoning: string } {
196
+ // No ordering required and no good key → round-robin
197
+ if (!orderingRequired && (!bestKey || bestKey.hotspotRisk === 'high')) {
198
+ return {
199
+ keyStrategy: 'round-robin',
200
+ keyField: null,
201
+ reasoning: 'No ordering requirement and no suitable key field. Round-robin provides best load distribution.'
202
+ };
203
+ }
204
+
205
+ // Ordering required but bad key → need compound key or custom partitioner
206
+ if (orderingRequired && bestKey && bestKey.hotspotRisk === 'high') {
207
+ return {
208
+ keyStrategy: 'compound-hash',
209
+ keyField: bestKey.key,
210
+ reasoning: `Ordering required but ${bestKey.key} has high hotspot risk. Use compound key (e.g., ${bestKey.key} + timestamp) to distribute load.`
211
+ };
212
+ }
213
+
214
+ // Good key with ordering → simple hash
215
+ if (orderingRequired && bestKey && bestKey.hotspotRisk !== 'high') {
216
+ return {
217
+ keyStrategy: 'simple-hash',
218
+ keyField: bestKey.key,
219
+ reasoning: `${bestKey.key} has ${bestKey.distribution} distribution with ${bestKey.hotspotRisk} hotspot risk. Use simple hash partitioning.`
220
+ };
221
+ }
222
+
223
+ // No ordering, but good key available → can use for locality
224
+ if (!orderingRequired && bestKey && bestKey.hotspotRisk === 'low') {
225
+ return {
226
+ keyStrategy: 'simple-hash',
227
+ keyField: bestKey.key,
228
+ reasoning: `${bestKey.key} has excellent distribution. Use hash partitioning for data locality even though ordering not required.`
229
+ };
230
+ }
231
+
232
+ // Fallback: custom partitioner for complex cases
233
+ return {
234
+ keyStrategy: 'custom-partitioner',
235
+ keyField: bestKey?.key ?? null,
236
+ reasoning: 'Complex partitioning requirements. Implement custom partitioner for optimal distribution.'
237
+ };
238
+ }
239
+
240
+ /**
241
+ * Generate warnings for partitioning strategy
242
+ */
243
+ private generateWarnings(params: {
244
+ bestKey: PartitionKeyAnalysis | null;
245
+ recommendedPartitions: number;
246
+ currentPartitionCount?: number;
247
+ req: PartitionAnalysisRequest;
248
+ }): string[] {
249
+ const warnings: string[] = [];
250
+
251
+ // Hotspot warnings
252
+ if (params.bestKey && params.bestKey.hotspotRisk === 'high') {
253
+ warnings.push(
254
+ `⚠️ Best key (${params.bestKey.key}) has HIGH hotspot risk with cardinality ${params.bestKey.estimatedCardinality}. ` +
255
+ `Consider compound key or custom partitioner.`
256
+ );
257
+ }
258
+
259
+ if (params.bestKey && params.bestKey.hotspotRisk === 'medium') {
260
+ warnings.push(
261
+ `⚠️ Key (${params.bestKey.key}) has MEDIUM hotspot risk. Monitor partition distribution in production.`
262
+ );
263
+ }
264
+
265
+ // Partition count warnings
266
+ if (params.currentPartitionCount && params.recommendedPartitions > params.currentPartitionCount) {
267
+ warnings.push(
268
+ `⚠️ Current partition count (${params.currentPartitionCount}) is below recommended (${params.recommendedPartitions}). ` +
269
+ `Increasing partitions requires re-creating topic or using partition expansion (Kafka 2.4+).`
270
+ );
271
+ }
272
+
273
+ if (params.recommendedPartitions > 100) {
274
+ warnings.push(
275
+ `⚠️ Recommended ${params.recommendedPartitions} partitions is high. Ensure cluster can handle this (max ~4000 per broker).`
276
+ );
277
+ }
278
+
279
+ // Ordering warnings
280
+ if (params.req.orderingRequired && !params.bestKey) {
281
+ warnings.push(
282
+ `🚨 CRITICAL: Ordering required but no suitable partition key found. ALL messages will be unordered!`
283
+ );
284
+ }
285
+
286
+ // Throughput warnings
287
+ if (params.req.targetThroughputMBps && params.req.targetThroughputMBps > params.recommendedPartitions * this.MAX_PARTITION_THROUGHPUT_MBPS) {
288
+ const neededPartitions = Math.ceil(params.req.targetThroughputMBps / this.MAX_PARTITION_THROUGHPUT_MBPS);
289
+ warnings.push(
290
+ `⚠️ Target throughput (${params.req.targetThroughputMBps} MB/s) requires ${neededPartitions} partitions, ` +
291
+ `but recommended only ${params.recommendedPartitions}. Increase partition count.`
292
+ );
293
+ }
294
+
295
+ return warnings;
296
+ }
297
+
298
+ /**
299
+ * Generate usage examples for the recommended strategy
300
+ */
301
+ private generateExamples(
302
+ keyStrategy: string,
303
+ keyField: string | null,
304
+ topicName: string
305
+ ): string[] {
306
+ const examples: string[] = [];
307
+
308
+ switch (keyStrategy) {
309
+ case 'simple-hash':
310
+ examples.push(
311
+ `// Producer (JavaScript/Node.js)`,
312
+ `await producer.send({`,
313
+ ` topic: '${topicName}',`,
314
+ ` messages: [{`,
315
+ ` key: record.${keyField}, // Hash this key`,
316
+ ` value: JSON.stringify(record)`,
317
+ ` }]`,
318
+ `});`,
319
+ ``,
320
+ `// Producer (Java)`,
321
+ `ProducerRecord<String, String> record = new ProducerRecord<>(`,
322
+ ` "${topicName}",`,
323
+ ` record.get${this.capitalize(keyField || 'id')}(), // Partition key`,
324
+ ` jsonValue`,
325
+ `);`,
326
+ `producer.send(record);`
327
+ );
328
+ break;
329
+
330
+ case 'compound-hash':
331
+ examples.push(
332
+ `// Producer (JavaScript/Node.js) - Compound Key`,
333
+ `const compoundKey = \`\${record.${keyField}}-\${Date.now() % 100}\`; // Add temporal component`,
334
+ `await producer.send({`,
335
+ ` topic: '${topicName}',`,
336
+ ` messages: [{`,
337
+ ` key: compoundKey,`,
338
+ ` value: JSON.stringify(record)`,
339
+ ` }]`,
340
+ `});`,
341
+ ``,
342
+ `// Alternative: Geographic + Entity ID`,
343
+ `const compoundKey = \`\${record.region}-\${record.${keyField}}\`;`
344
+ );
345
+ break;
346
+
347
+ case 'custom-partitioner':
348
+ examples.push(
349
+ `// Custom Partitioner (Java)`,
350
+ `public class CustomPartitioner implements Partitioner {`,
351
+ ` @Override`,
352
+ ` public int partition(String topic, Object key, byte[] keyBytes,`,
353
+ ` Object value, byte[] valueBytes, Cluster cluster) {`,
354
+ ` int partitionCount = cluster.partitionCountForTopic(topic);`,
355
+ ` `,
356
+ ` // Custom logic here`,
357
+ ` String keyStr = (String) key;`,
358
+ ` if (keyStr.startsWith("priority-")) {`,
359
+ ` return 0; // High-priority partition`,
360
+ ` }`,
361
+ ` `,
362
+ ` // Default hashing for others`,
363
+ ` return Math.abs(keyStr.hashCode()) % (partitionCount - 1) + 1;`,
364
+ ` }`,
365
+ `}`,
366
+ ``,
367
+ `// Configure producer`,
368
+ `props.put("partitioner.class", "com.example.CustomPartitioner");`
369
+ );
370
+ break;
371
+
372
+ case 'round-robin':
373
+ examples.push(
374
+ `// Producer (JavaScript/Node.js) - No Key`,
375
+ `await producer.send({`,
376
+ ` topic: '${topicName}',`,
377
+ ` messages: [{`,
378
+ ` value: JSON.stringify(record) // No key = round-robin`,
379
+ ` }]`,
380
+ `});`,
381
+ ``,
382
+ `// Producer (Java)`,
383
+ `ProducerRecord<String, String> record = new ProducerRecord<>(`,
384
+ ` "${topicName}",`,
385
+ ` null, // No key`,
386
+ ` jsonValue`,
387
+ `);`,
388
+ `producer.send(record);`
389
+ );
390
+ break;
391
+ }
392
+
393
+ return examples;
394
+ }
395
+
396
+ /**
397
+ * Helper: Next power of 2
398
+ */
399
+ private nextPowerOfTwo(n: number): number {
400
+ return Math.pow(2, Math.ceil(Math.log2(n)));
401
+ }
402
+
403
+ /**
404
+ * Helper: Capitalize first letter
405
+ */
406
+ private capitalize(str: string): string {
407
+ return str.charAt(0).toUpperCase() + str.slice(1);
408
+ }
409
+
410
+ /**
411
+ * Calculate partition distribution for a given key
412
+ */
413
+ calculateDistribution(
414
+ sampleValues: string[],
415
+ partitionCount: number
416
+ ): { partition: number; count: number; percentage: number }[] {
417
+ // Simulate Kafka's DefaultPartitioner
418
+ const partitionCounts = new Map<number, number>();
419
+
420
+ for (const value of sampleValues) {
421
+ const hash = this.murmur2Hash(value);
422
+ const partition = Math.abs(hash) % partitionCount;
423
+ partitionCounts.set(partition, (partitionCounts.get(partition) || 0) + 1);
424
+ }
425
+
426
+ // Convert to array and calculate percentages
427
+ const distribution = Array.from(partitionCounts.entries())
428
+ .map(([partition, count]) => ({
429
+ partition,
430
+ count,
431
+ percentage: (count / sampleValues.length) * 100
432
+ }))
433
+ .sort((a, b) => b.count - a.count);
434
+
435
+ return distribution;
436
+ }
437
+
438
+ /**
439
+ * Simple MurmurHash2 implementation (matches Kafka's DefaultPartitioner)
440
+ */
441
+ private murmur2Hash(data: string): number {
442
+ const bytes = Buffer.from(data, 'utf-8');
443
+ const length = bytes.length;
444
+ const seed = 0x9747b28c;
445
+
446
+ const m = 0x5bd1e995;
447
+ const r = 24;
448
+ let h = seed ^ length;
449
+
450
+ for (let i = 0; i + 4 <= length; i += 4) {
451
+ let k = bytes.readInt32LE(i);
452
+ k = Math.imul(k, m);
453
+ k ^= k >>> r;
454
+ k = Math.imul(k, m);
455
+ h = Math.imul(h, m);
456
+ h ^= k;
457
+ }
458
+
459
+ const remaining = length % 4;
460
+ if (remaining >= 3) h ^= bytes[length - 3] << 16;
461
+ if (remaining >= 2) h ^= bytes[length - 2] << 8;
462
+ if (remaining >= 1) {
463
+ h ^= bytes[length - 1];
464
+ h = Math.imul(h, m);
465
+ }
466
+
467
+ h ^= h >>> 13;
468
+ h = Math.imul(h, m);
469
+ h ^= h >>> 15;
470
+
471
+ return h;
472
+ }
473
+ }
@@ -0,0 +1,221 @@
1
+ class ClusterSizingCalculator {
2
+ constructor() {
3
+ // Constants (empirical limits from production deployments)
4
+ this.MAX_PARTITIONS_PER_BROKER = 4e3;
5
+ this.SINGLE_PARTITION_WRITE_MBPS = 20;
6
+ // Conservative estimate
7
+ this.SINGLE_PARTITION_READ_MBPS = 40;
8
+ this.NETWORK_OVERHEAD = 1.3;
9
+ // 30% overhead for protocol, replication
10
+ this.BASE_RAM_GB = 8;
11
+ // Minimum OS + Kafka overhead
12
+ this.RAM_PER_PARTITION_MB = 1;
13
+ // Page cache per partition
14
+ this.RAM_PER_REPLICATION_MB = 2;
15
+ }
16
+ // Replica fetcher overhead
17
+ /**
18
+ * Calculate recommended cluster size
19
+ */
20
+ calculate(req) {
21
+ const growthFactor = req.growthFactor ?? 2;
22
+ const targetCPU = req.targetCPUUtilization ?? 0.6;
23
+ const targetDisk = req.targetDiskUtilization ?? 0.7;
24
+ const writeThru = req.writeThroughputMBps * growthFactor;
25
+ const readThru = req.readThroughputMBps * growthFactor;
26
+ const totalPartitions = req.topicCount * req.avgPartitionsPerTopic;
27
+ const brokersForWrite = Math.ceil(
28
+ writeThru * this.NETWORK_OVERHEAD / (this.SINGLE_PARTITION_WRITE_MBPS * this.MAX_PARTITIONS_PER_BROKER / 10)
29
+ );
30
+ const brokersForRead = Math.ceil(
31
+ readThru * this.NETWORK_OVERHEAD / (this.SINGLE_PARTITION_READ_MBPS * this.MAX_PARTITIONS_PER_BROKER / 10)
32
+ );
33
+ const brokersForPartitions = Math.ceil(totalPartitions / this.MAX_PARTITIONS_PER_BROKER);
34
+ let brokerCount = Math.max(brokersForWrite, brokersForRead, brokersForPartitions);
35
+ brokerCount = Math.max(brokerCount, req.replicationFactor);
36
+ if (brokerCount > 3 && brokerCount % 3 !== 0) {
37
+ brokerCount = Math.ceil(brokerCount / 3) * 3;
38
+ }
39
+ const partitionsPerBroker = Math.ceil(totalPartitions / brokerCount);
40
+ const dailyDataVolumeMB = req.messagesPerDay * req.avgMessageSizeKB / 1024;
41
+ const totalStorageGB = dailyDataVolumeMB * req.retentionDays / 1024;
42
+ const storageWithReplicationGB = totalStorageGB * req.replicationFactor;
43
+ const diskPerBrokerGB = Math.ceil(
44
+ storageWithReplicationGB / brokerCount / targetDisk
45
+ );
46
+ const ramForPartitionsGB = partitionsPerBroker * this.RAM_PER_PARTITION_MB / 1024;
47
+ const ramForReplicationGB = partitionsPerBroker * req.replicationFactor * this.RAM_PER_REPLICATION_MB / 1024;
48
+ const ramGB = Math.ceil(this.BASE_RAM_GB + ramForPartitionsGB + ramForReplicationGB);
49
+ const cpuCores = Math.ceil(partitionsPerBroker / 500) + 8;
50
+ const networkGbps = this.calculateNetworkBandwidth(writeThru, readThru, brokerCount);
51
+ const estimatedWriteThroughputMBps = brokerCount * this.SINGLE_PARTITION_WRITE_MBPS * (partitionsPerBroker / 10);
52
+ const estimatedReadThroughputMBps = brokerCount * this.SINGLE_PARTITION_READ_MBPS * (partitionsPerBroker / 10);
53
+ const estimatedLatencyP99Ms = this.estimateLatency(partitionsPerBroker, diskPerBrokerGB);
54
+ const warnings = this.generateWarnings({
55
+ partitionsPerBroker,
56
+ brokerCount,
57
+ req,
58
+ diskPerBrokerGB
59
+ });
60
+ const recommendations = this.generateRecommendations({
61
+ partitionsPerBroker,
62
+ brokerCount,
63
+ req,
64
+ ramGB,
65
+ diskPerBrokerGB
66
+ });
67
+ return {
68
+ brokerCount,
69
+ totalPartitions,
70
+ partitionsPerBroker,
71
+ cpuCores,
72
+ ramGB,
73
+ diskGB: diskPerBrokerGB,
74
+ networkGbps,
75
+ estimatedWriteThroughputMBps,
76
+ estimatedReadThroughputMBps,
77
+ estimatedLatencyP99Ms,
78
+ dailyDataVolumeMB,
79
+ totalStorageRequiredGB: totalStorageGB,
80
+ storageWithReplicationGB,
81
+ warnings,
82
+ recommendations
83
+ };
84
+ }
85
+ /**
86
+ * Calculate network bandwidth requirements
87
+ */
88
+ calculateNetworkBandwidth(writeMBps, readMBps, brokerCount) {
89
+ const replicationTrafficMBps = writeMBps * 2;
90
+ const totalTrafficMBps = writeMBps + readMBps + replicationTrafficMBps;
91
+ const perBrokerMBps = totalTrafficMBps / brokerCount;
92
+ const gbps = Math.ceil(perBrokerMBps * 8 / 1e3);
93
+ if (gbps <= 1) return 1;
94
+ if (gbps <= 10) return 10;
95
+ if (gbps <= 25) return 25;
96
+ if (gbps <= 40) return 40;
97
+ return 100;
98
+ }
99
+ /**
100
+ * Estimate p99 latency based on partition count and disk size
101
+ */
102
+ estimateLatency(partitionsPerBroker, diskGB) {
103
+ let latencyMs = 5;
104
+ if (partitionsPerBroker > 2e3) {
105
+ latencyMs += 5;
106
+ } else if (partitionsPerBroker > 1e3) {
107
+ latencyMs += 2;
108
+ }
109
+ if (diskGB > 1e4) {
110
+ latencyMs += 10;
111
+ } else if (diskGB > 5e3) {
112
+ latencyMs += 5;
113
+ }
114
+ return latencyMs;
115
+ }
116
+ /**
117
+ * Generate warnings for potential issues
118
+ */
119
+ generateWarnings(params) {
120
+ const warnings = [];
121
+ if (params.partitionsPerBroker > 4e3) {
122
+ warnings.push(
123
+ `\u26A0\uFE0F ${params.partitionsPerBroker} partitions per broker exceeds recommended limit (4000). Consider increasing broker count to ${Math.ceil(params.req.topicCount * params.req.avgPartitionsPerTopic / 4e3)}.`
124
+ );
125
+ }
126
+ if (params.partitionsPerBroker < 100) {
127
+ warnings.push(
128
+ `\u26A0\uFE0F ${params.partitionsPerBroker} partitions per broker is very low. You may be over-provisioned. Consider reducing to ${Math.max(3, Math.ceil(params.brokerCount / 2))} brokers.`
129
+ );
130
+ }
131
+ if (params.brokerCount < params.req.replicationFactor) {
132
+ warnings.push(
133
+ `\u{1F6A8} CRITICAL: ${params.brokerCount} brokers < replication factor (${params.req.replicationFactor}). Minimum required: ${params.req.replicationFactor} brokers.`
134
+ );
135
+ }
136
+ if (params.brokerCount === params.req.replicationFactor) {
137
+ warnings.push(
138
+ `\u26A0\uFE0F Broker count equals replication factor. No fault tolerance! Increase to at least ${params.req.replicationFactor + 1} brokers.`
139
+ );
140
+ }
141
+ if (params.diskPerBrokerGB > 1e4) {
142
+ warnings.push(
143
+ `\u26A0\uFE0F ${params.diskPerBrokerGB} GB per broker is very large. Consider using HDD for cost savings or increasing broker count to reduce disk per broker.`
144
+ );
145
+ }
146
+ if (params.req.minInsyncReplicas && params.req.minInsyncReplicas >= params.req.replicationFactor) {
147
+ warnings.push(
148
+ `\u{1F6A8} CRITICAL: min.insync.replicas (${params.req.minInsyncReplicas}) >= replication.factor (${params.req.replicationFactor}). This will cause writes to fail! Set min.insync.replicas to ${params.req.replicationFactor - 1}.`
149
+ );
150
+ }
151
+ return warnings;
152
+ }
153
+ /**
154
+ * Generate optimization recommendations
155
+ */
156
+ generateRecommendations(params) {
157
+ const recommendations = [];
158
+ if (params.req.avgPartitionsPerTopic < 10) {
159
+ recommendations.push(
160
+ `\u{1F4A1} Consider increasing partitions per topic to 12-24 for better parallelism and future growth.`
161
+ );
162
+ }
163
+ if (params.req.avgPartitionsPerTopic > 100) {
164
+ recommendations.push(
165
+ `\u{1F4A1} ${params.req.avgPartitionsPerTopic} partitions per topic is high. Consider splitting into multiple topics or reducing partition count unless you need extreme parallelism.`
166
+ );
167
+ }
168
+ if (params.diskPerBrokerGB > 5e3) {
169
+ recommendations.push(
170
+ `\u{1F4A1} Large disk requirement (${params.diskPerBrokerGB} GB). Consider using tiered storage (Kafka 2.8+) to offload old data to S3/Azure Blob/GCS.`
171
+ );
172
+ }
173
+ if (params.ramGB > 128) {
174
+ recommendations.push(
175
+ `\u{1F4A1} High RAM requirement (${params.ramGB} GB). Ensure your infrastructure supports this. Consider AWS i3en/i4i instances or equivalent.`
176
+ );
177
+ }
178
+ if (!params.req.minInsyncReplicas) {
179
+ recommendations.push(
180
+ `\u{1F4A1} Set min.insync.replicas=2 for production (currently not configured). This prevents data loss if a broker fails.`
181
+ );
182
+ }
183
+ if (params.req.replicationFactor < 3) {
184
+ recommendations.push(
185
+ `\u{1F4A1} Increase replication factor to 3 for production durability (currently ${params.req.replicationFactor}).`
186
+ );
187
+ }
188
+ if (params.brokerCount % 3 !== 0 && params.brokerCount > 3) {
189
+ recommendations.push(
190
+ `\u{1F4A1} Broker count (${params.brokerCount}) is not a multiple of 3. Consider using ${Math.ceil(params.brokerCount / 3) * 3} brokers for better rack awareness.`
191
+ );
192
+ }
193
+ return recommendations;
194
+ }
195
+ /**
196
+ * Calculate disk IOPS requirements
197
+ */
198
+ calculateDiskIOPS(writeThroughputMBps, replicationFactor) {
199
+ const writeIOPS = writeThroughputMBps * 1024 / 4;
200
+ const replicationWriteIOPS = writeIOPS * (replicationFactor - 1);
201
+ const readIOPS = writeIOPS * 0.5;
202
+ const totalWriteIOPS = writeIOPS + replicationWriteIOPS;
203
+ const totalReadIOPS = readIOPS;
204
+ let recommendation = "";
205
+ if (totalWriteIOPS > 5e4) {
206
+ recommendation = "Use NVMe SSDs (500K+ IOPS)";
207
+ } else if (totalWriteIOPS > 1e4) {
208
+ recommendation = "Use Premium SSD (20K-64K IOPS)";
209
+ } else {
210
+ recommendation = "Standard SSD (3K-6K IOPS) sufficient";
211
+ }
212
+ return {
213
+ readIOPS: Math.ceil(totalReadIOPS),
214
+ writeIOPS: Math.ceil(totalWriteIOPS),
215
+ recommendation
216
+ };
217
+ }
218
+ }
219
+ export {
220
+ ClusterSizingCalculator
221
+ };