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,380 @@
1
+ /**
2
+ * Health Aggregator
3
+ *
4
+ * Aggregates health metrics across multiple Kafka clusters
5
+ *
6
+ * @module health-aggregator
7
+ */
8
+
9
+ import { Admin } from 'kafkajs';
10
+ import { ClusterSwitcher } from './cluster-switcher';
11
+ import { ClusterConfig } from './cluster-config-manager';
12
+
13
+ /**
14
+ * Cluster Health Metrics
15
+ */
16
+ export interface ClusterHealthMetrics {
17
+ /** Cluster ID */
18
+ clusterId: string;
19
+ /** Cluster name */
20
+ clusterName: string;
21
+ /** Environment */
22
+ environment: string;
23
+ /** Overall health status */
24
+ status: 'healthy' | 'degraded' | 'down';
25
+ /** Number of brokers */
26
+ brokerCount: number;
27
+ /** Number of online brokers */
28
+ onlineBrokerCount: number;
29
+ /** Number of topics */
30
+ topicCount: number;
31
+ /** Number of partitions */
32
+ partitionCount: number;
33
+ /** Under-replicated partitions */
34
+ underReplicatedPartitions: number;
35
+ /** Offline partitions */
36
+ offlinePartitions: number;
37
+ /** Consumer groups */
38
+ consumerGroupCount: number;
39
+ /** Controller ID */
40
+ controllerId?: number;
41
+ /** Last check timestamp */
42
+ lastCheck: Date;
43
+ /** Error message (if down) */
44
+ error?: string;
45
+ }
46
+
47
+ /**
48
+ * Aggregated Health Summary
49
+ */
50
+ export interface AggregatedHealthSummary {
51
+ /** Total clusters */
52
+ totalClusters: number;
53
+ /** Healthy clusters */
54
+ healthyClusters: number;
55
+ /** Degraded clusters */
56
+ degradedClusters: number;
57
+ /** Down clusters */
58
+ downClusters: number;
59
+ /** Total brokers across all clusters */
60
+ totalBrokers: number;
61
+ /** Total topics across all clusters */
62
+ totalTopics: number;
63
+ /** Total partitions across all clusters */
64
+ totalPartitions: number;
65
+ /** Total under-replicated partitions across all clusters */
66
+ totalUnderReplicatedPartitions: number;
67
+ /** Per-cluster metrics */
68
+ clusterMetrics: ClusterHealthMetrics[];
69
+ /** Last update timestamp */
70
+ lastUpdate: Date;
71
+ }
72
+
73
+ /**
74
+ * Health Aggregator
75
+ *
76
+ * Collects and aggregates health metrics from multiple Kafka clusters
77
+ */
78
+ export class HealthAggregator {
79
+ private switcher: ClusterSwitcher;
80
+
81
+ constructor(switcher: ClusterSwitcher) {
82
+ this.switcher = switcher;
83
+ }
84
+
85
+ /**
86
+ * Collect health metrics for a single cluster
87
+ */
88
+ async collectClusterHealth(clusterId: string): Promise<ClusterHealthMetrics> {
89
+ try {
90
+ // Get cluster config
91
+ const clusters = this.switcher.listClusters();
92
+ const clusterConfig = clusters.find((c) => c.id === clusterId);
93
+ if (!clusterConfig) {
94
+ throw new Error(`Cluster "${clusterId}" not found`);
95
+ }
96
+
97
+ // Execute health check on this cluster
98
+ const metrics = await this.switcher.executeOn(clusterId, async (kafka) => {
99
+ const admin = kafka.admin();
100
+ await admin.connect();
101
+
102
+ try {
103
+ // Get cluster metadata
104
+ const cluster = await admin.describeCluster();
105
+ const topics = await admin.listTopics();
106
+ const groups = await admin.listGroups();
107
+
108
+ // Get topic metadata (for partition counts)
109
+ const metadata = await admin.fetchTopicMetadata({ topics });
110
+
111
+ // Calculate partition counts
112
+ let totalPartitions = 0;
113
+ let underReplicatedPartitions = 0;
114
+ let offlinePartitions = 0;
115
+
116
+ for (const topic of metadata.topics) {
117
+ for (const partition of topic.partitions) {
118
+ totalPartitions++;
119
+
120
+ // Under-replicated: ISR < replicas
121
+ if (partition.isr.length < partition.replicas.length) {
122
+ underReplicatedPartitions++;
123
+ }
124
+
125
+ // Offline: ISR empty
126
+ if (partition.isr.length === 0) {
127
+ offlinePartitions++;
128
+ }
129
+ }
130
+ }
131
+
132
+ return {
133
+ clusterId,
134
+ clusterName: clusterConfig.name,
135
+ environment: clusterConfig.environment,
136
+ status: this.determineStatus(underReplicatedPartitions, offlinePartitions),
137
+ brokerCount: cluster.brokers.length,
138
+ onlineBrokerCount: cluster.brokers.length, // All in describeCluster are online
139
+ topicCount: topics.length,
140
+ partitionCount: totalPartitions,
141
+ underReplicatedPartitions,
142
+ offlinePartitions,
143
+ consumerGroupCount: groups.groups.length,
144
+ controllerId: cluster.controller ? Number(cluster.controller) : undefined,
145
+ lastCheck: new Date(),
146
+ };
147
+ } finally {
148
+ await admin.disconnect();
149
+ }
150
+ });
151
+
152
+ return metrics as ClusterHealthMetrics;
153
+ } catch (error) {
154
+ // Return minimal metrics with down status
155
+ const clusters = this.switcher.listClusters();
156
+ const clusterConfig = clusters.find((c) => c.id === clusterId)!;
157
+
158
+ return {
159
+ clusterId,
160
+ clusterName: clusterConfig.name,
161
+ environment: clusterConfig.environment,
162
+ status: 'down',
163
+ brokerCount: 0,
164
+ onlineBrokerCount: 0,
165
+ topicCount: 0,
166
+ partitionCount: 0,
167
+ underReplicatedPartitions: 0,
168
+ offlinePartitions: 0,
169
+ consumerGroupCount: 0,
170
+ lastCheck: new Date(),
171
+ error: (error as Error).message,
172
+ };
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Determine cluster status based on metrics
178
+ */
179
+ private determineStatus(
180
+ underReplicatedPartitions: number,
181
+ offlinePartitions: number
182
+ ): 'healthy' | 'degraded' | 'down' {
183
+ if (offlinePartitions > 0) {
184
+ return 'down'; // Any offline partitions = cluster down
185
+ }
186
+
187
+ if (underReplicatedPartitions > 0) {
188
+ return 'degraded'; // Under-replicated = degraded
189
+ }
190
+
191
+ return 'healthy';
192
+ }
193
+
194
+ /**
195
+ * Collect health metrics for all clusters
196
+ */
197
+ async collectAllClusters(): Promise<ClusterHealthMetrics[]> {
198
+ const clusters = this.switcher.listClusters();
199
+ const promises = clusters.map((c) => this.collectClusterHealth(c.id));
200
+
201
+ return Promise.all(promises);
202
+ }
203
+
204
+ /**
205
+ * Aggregate health across all clusters
206
+ */
207
+ async aggregateHealth(): Promise<AggregatedHealthSummary> {
208
+ const clusterMetrics = await this.collectAllClusters();
209
+
210
+ // Calculate totals
211
+ let totalBrokers = 0;
212
+ let totalTopics = 0;
213
+ let totalPartitions = 0;
214
+ let totalUnderReplicatedPartitions = 0;
215
+ let healthyClusters = 0;
216
+ let degradedClusters = 0;
217
+ let downClusters = 0;
218
+
219
+ for (const metrics of clusterMetrics) {
220
+ totalBrokers += metrics.brokerCount;
221
+ totalTopics += metrics.topicCount;
222
+ totalPartitions += metrics.partitionCount;
223
+ totalUnderReplicatedPartitions += metrics.underReplicatedPartitions;
224
+
225
+ if (metrics.status === 'healthy') healthyClusters++;
226
+ else if (metrics.status === 'degraded') degradedClusters++;
227
+ else if (metrics.status === 'down') downClusters++;
228
+ }
229
+
230
+ return {
231
+ totalClusters: clusterMetrics.length,
232
+ healthyClusters,
233
+ degradedClusters,
234
+ downClusters,
235
+ totalBrokers,
236
+ totalTopics,
237
+ totalPartitions,
238
+ totalUnderReplicatedPartitions,
239
+ clusterMetrics,
240
+ lastUpdate: new Date(),
241
+ };
242
+ }
243
+
244
+ /**
245
+ * Get health summary as formatted text
246
+ */
247
+ async getHealthSummaryText(): Promise<string> {
248
+ const summary = await this.aggregateHealth();
249
+
250
+ const lines: string[] = [];
251
+ lines.push('=== Kafka Multi-Cluster Health Summary ===');
252
+ lines.push('');
253
+ lines.push(`Total Clusters: ${summary.totalClusters}`);
254
+ lines.push(` ✓ Healthy: ${summary.healthyClusters}`);
255
+ lines.push(` ⚠ Degraded: ${summary.degradedClusters}`);
256
+ lines.push(` ✗ Down: ${summary.downClusters}`);
257
+ lines.push('');
258
+ lines.push(`Total Brokers: ${summary.totalBrokers}`);
259
+ lines.push(`Total Topics: ${summary.totalTopics}`);
260
+ lines.push(`Total Partitions: ${summary.totalPartitions}`);
261
+ if (summary.totalUnderReplicatedPartitions > 0) {
262
+ lines.push(`⚠ Under-Replicated Partitions: ${summary.totalUnderReplicatedPartitions}`);
263
+ }
264
+ lines.push('');
265
+ lines.push('=== Per-Cluster Status ===');
266
+
267
+ for (const cluster of summary.clusterMetrics) {
268
+ const icon =
269
+ cluster.status === 'healthy' ? '✓' : cluster.status === 'degraded' ? '⚠' : '✗';
270
+
271
+ lines.push('');
272
+ lines.push(
273
+ `${icon} ${cluster.clusterName} (${cluster.environment}) - ${cluster.status.toUpperCase()}`
274
+ );
275
+ lines.push(` Brokers: ${cluster.onlineBrokerCount}/${cluster.brokerCount}`);
276
+ lines.push(` Topics: ${cluster.topicCount}`);
277
+ lines.push(` Partitions: ${cluster.partitionCount}`);
278
+
279
+ if (cluster.underReplicatedPartitions > 0) {
280
+ lines.push(` ⚠ Under-Replicated: ${cluster.underReplicatedPartitions}`);
281
+ }
282
+
283
+ if (cluster.offlinePartitions > 0) {
284
+ lines.push(` ✗ Offline: ${cluster.offlinePartitions}`);
285
+ }
286
+
287
+ if (cluster.error) {
288
+ lines.push(` Error: ${cluster.error}`);
289
+ }
290
+ }
291
+
292
+ lines.push('');
293
+ lines.push(`Last Updated: ${summary.lastUpdate.toISOString()}`);
294
+
295
+ return lines.join('\n');
296
+ }
297
+
298
+ /**
299
+ * Check if any cluster is unhealthy
300
+ */
301
+ async hasUnhealthyClusters(): Promise<boolean> {
302
+ const summary = await this.aggregateHealth();
303
+ return summary.degradedClusters > 0 || summary.downClusters > 0;
304
+ }
305
+
306
+ /**
307
+ * Get list of unhealthy clusters
308
+ */
309
+ async getUnhealthyClusters(): Promise<ClusterHealthMetrics[]> {
310
+ const clusterMetrics = await this.collectAllClusters();
311
+ return clusterMetrics.filter((c) => c.status !== 'healthy');
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Example Usage: Health Check All Clusters
317
+ *
318
+ * ```typescript
319
+ * const switcher = new ClusterSwitcher();
320
+ * const aggregator = new HealthAggregator(switcher);
321
+ *
322
+ * // Get aggregated health summary
323
+ * const summary = await aggregator.aggregateHealth();
324
+ * console.log(`Total clusters: ${summary.totalClusters}`);
325
+ * console.log(`Healthy: ${summary.healthyClusters}`);
326
+ * console.log(`Degraded: ${summary.degradedClusters}`);
327
+ * console.log(`Down: ${summary.downClusters}`);
328
+ *
329
+ * // Print formatted summary
330
+ * const text = await aggregator.getHealthSummaryText();
331
+ * console.log(text);
332
+ * ```
333
+ */
334
+
335
+ /**
336
+ * Example Usage: Alert on Unhealthy Clusters
337
+ *
338
+ * ```typescript
339
+ * const switcher = new ClusterSwitcher();
340
+ * const aggregator = new HealthAggregator(switcher);
341
+ *
342
+ * // Check for unhealthy clusters
343
+ * if (await aggregator.hasUnhealthyClusters()) {
344
+ * const unhealthy = await aggregator.getUnhealthyClusters();
345
+ * for (const cluster of unhealthy) {
346
+ * console.error(`⚠ ${cluster.clusterName} is ${cluster.status}`);
347
+ * console.error(` Under-replicated: ${cluster.underReplicatedPartitions}`);
348
+ * console.error(` Offline: ${cluster.offlinePartitions}`);
349
+ * }
350
+ * // Send alert to PagerDuty, Slack, etc.
351
+ * }
352
+ * ```
353
+ */
354
+
355
+ /**
356
+ * Example Usage: Scheduled Health Monitoring
357
+ *
358
+ * ```typescript
359
+ * const switcher = new ClusterSwitcher();
360
+ * const aggregator = new HealthAggregator(switcher);
361
+ *
362
+ * // Run health check every 5 minutes
363
+ * setInterval(async () => {
364
+ * const summary = await aggregator.aggregateHealth();
365
+ *
366
+ * // Export to Prometheus (push gateway)
367
+ * pushToPrometheus('kafka_clusters_total', summary.totalClusters);
368
+ * pushToPrometheus('kafka_clusters_healthy', summary.healthyClusters);
369
+ * pushToPrometheus('kafka_clusters_degraded', summary.degradedClusters);
370
+ * pushToPrometheus('kafka_clusters_down', summary.downClusters);
371
+ *
372
+ * // Alert if any cluster is down
373
+ * if (summary.downClusters > 0) {
374
+ * sendSlackAlert(`⚠ ${summary.downClusters} Kafka cluster(s) down!`);
375
+ * }
376
+ * }, 5 * 60 * 1000); // 5 minutes
377
+ * ```
378
+ */
379
+
380
+ export default HealthAggregator;
@@ -0,0 +1,209 @@
1
+ import {
2
+ trace,
3
+ context,
4
+ SpanKind,
5
+ SpanStatusCode,
6
+ propagation
7
+ } from "@opentelemetry/api";
8
+ const KafkaAttributes = {
9
+ MESSAGING_SYSTEM: "messaging.system",
10
+ MESSAGING_DESTINATION: "messaging.destination",
11
+ MESSAGING_DESTINATION_KIND: "messaging.destination_kind",
12
+ MESSAGING_OPERATION: "messaging.operation",
13
+ MESSAGING_KAFKA_MESSAGE_KEY: "messaging.kafka.message_key",
14
+ MESSAGING_KAFKA_PARTITION: "messaging.kafka.partition",
15
+ MESSAGING_KAFKA_OFFSET: "messaging.kafka.offset",
16
+ MESSAGING_KAFKA_TOMBSTONE: "messaging.kafka.tombstone",
17
+ MESSAGING_KAFKA_CLIENT_ID: "messaging.kafka.client_id",
18
+ MESSAGING_KAFKA_CONSUMER_GROUP: "messaging.kafka.consumer.group"
19
+ };
20
+ const TRACEPARENT_HEADER = "traceparent";
21
+ const TRACESTATE_HEADER = "tracestate";
22
+ class KafkaProducerTracing {
23
+ constructor(config = {}) {
24
+ this.config = {
25
+ tracerName: config.tracerName || "kafka-producer",
26
+ capturePayloads: config.capturePayloads || false,
27
+ captureKeys: config.captureKeys || true,
28
+ maxPayloadSize: config.maxPayloadSize || 1024
29
+ };
30
+ this.tracer = trace.getTracer(this.config.tracerName);
31
+ }
32
+ /**
33
+ * Instrument a producer.send() call with distributed tracing
34
+ */
35
+ async traceSend(producer, topic, messages, clientId) {
36
+ return this.tracer.startActiveSpan(
37
+ `${topic} send`,
38
+ {
39
+ kind: SpanKind.PRODUCER,
40
+ attributes: {
41
+ [KafkaAttributes.MESSAGING_SYSTEM]: "kafka",
42
+ [KafkaAttributes.MESSAGING_DESTINATION]: topic,
43
+ [KafkaAttributes.MESSAGING_DESTINATION_KIND]: "topic",
44
+ [KafkaAttributes.MESSAGING_OPERATION]: "send",
45
+ [KafkaAttributes.MESSAGING_KAFKA_CLIENT_ID]: clientId || "unknown",
46
+ "messaging.batch.message_count": messages.length
47
+ }
48
+ },
49
+ async (span) => {
50
+ try {
51
+ const instrumentedMessages = messages.map((msg) => {
52
+ const headers = msg.headers || {};
53
+ propagation.inject(context.active(), headers, {
54
+ set: (carrier, key, value) => {
55
+ carrier[key] = value;
56
+ }
57
+ });
58
+ if (this.config.captureKeys && msg.key) {
59
+ span.setAttribute(
60
+ KafkaAttributes.MESSAGING_KAFKA_MESSAGE_KEY,
61
+ msg.key.toString()
62
+ );
63
+ }
64
+ if (this.config.capturePayloads && msg.value) {
65
+ const payload = msg.value.toString();
66
+ const truncated = payload.length > this.config.maxPayloadSize ? payload.substring(0, this.config.maxPayloadSize) + "..." : payload;
67
+ span.setAttribute("messaging.message.payload", truncated);
68
+ }
69
+ return { ...msg, headers };
70
+ });
71
+ const result = await producer.send({
72
+ topic,
73
+ messages: instrumentedMessages
74
+ });
75
+ span.setStatus({ code: SpanStatusCode.OK });
76
+ result.forEach((metadata, index) => {
77
+ span.addEvent("message.sent", {
78
+ [KafkaAttributes.MESSAGING_KAFKA_PARTITION]: metadata.partition,
79
+ [KafkaAttributes.MESSAGING_KAFKA_OFFSET]: metadata.offset?.toString() || "unknown",
80
+ "message.index": index
81
+ });
82
+ });
83
+ return result;
84
+ } catch (error) {
85
+ span.setStatus({
86
+ code: SpanStatusCode.ERROR,
87
+ message: error instanceof Error ? error.message : String(error)
88
+ });
89
+ span.recordException(error);
90
+ throw error;
91
+ } finally {
92
+ span.end();
93
+ }
94
+ }
95
+ );
96
+ }
97
+ }
98
+ class KafkaConsumerTracing {
99
+ constructor(config = {}) {
100
+ this.config = {
101
+ tracerName: config.tracerName || "kafka-consumer",
102
+ capturePayloads: config.capturePayloads || false,
103
+ captureKeys: config.captureKeys || true,
104
+ maxPayloadSize: config.maxPayloadSize || 1024
105
+ };
106
+ this.tracer = trace.getTracer(this.config.tracerName);
107
+ }
108
+ /**
109
+ * Instrument a message consumption with distributed tracing
110
+ */
111
+ async traceMessage(topic, partition, message, consumerGroup, handler) {
112
+ const parentContext = propagation.extract(
113
+ context.active(),
114
+ message.headers || {},
115
+ {
116
+ get: (carrier, key) => {
117
+ const value = carrier[key];
118
+ return Array.isArray(value) ? value[0]?.toString() : value?.toString();
119
+ },
120
+ keys: (carrier) => Object.keys(carrier)
121
+ }
122
+ );
123
+ return this.tracer.startActiveSpan(
124
+ `${topic} receive`,
125
+ {
126
+ kind: SpanKind.CONSUMER,
127
+ attributes: {
128
+ [KafkaAttributes.MESSAGING_SYSTEM]: "kafka",
129
+ [KafkaAttributes.MESSAGING_DESTINATION]: topic,
130
+ [KafkaAttributes.MESSAGING_DESTINATION_KIND]: "topic",
131
+ [KafkaAttributes.MESSAGING_OPERATION]: "receive",
132
+ [KafkaAttributes.MESSAGING_KAFKA_PARTITION]: partition,
133
+ [KafkaAttributes.MESSAGING_KAFKA_OFFSET]: message.offset,
134
+ [KafkaAttributes.MESSAGING_KAFKA_CONSUMER_GROUP]: consumerGroup,
135
+ [KafkaAttributes.MESSAGING_KAFKA_TOMBSTONE]: message.value === null
136
+ }
137
+ },
138
+ parentContext,
139
+ async (span) => {
140
+ try {
141
+ if (this.config.captureKeys && message.key) {
142
+ span.setAttribute(
143
+ KafkaAttributes.MESSAGING_KAFKA_MESSAGE_KEY,
144
+ message.key.toString()
145
+ );
146
+ }
147
+ if (this.config.capturePayloads && message.value) {
148
+ const payload = message.value.toString();
149
+ const truncated = payload.length > this.config.maxPayloadSize ? payload.substring(0, this.config.maxPayloadSize) + "..." : payload;
150
+ span.setAttribute("messaging.message.payload", truncated);
151
+ }
152
+ const result = await handler(context.active());
153
+ span.setStatus({ code: SpanStatusCode.OK });
154
+ return result;
155
+ } catch (error) {
156
+ span.setStatus({
157
+ code: SpanStatusCode.ERROR,
158
+ message: error instanceof Error ? error.message : String(error)
159
+ });
160
+ span.recordException(error);
161
+ throw error;
162
+ } finally {
163
+ span.end();
164
+ }
165
+ }
166
+ );
167
+ }
168
+ /**
169
+ * Create a processing span for custom operations within message handler
170
+ */
171
+ createProcessingSpan(name, operation, callback) {
172
+ return this.tracer.startActiveSpan(
173
+ name,
174
+ {
175
+ kind: SpanKind.INTERNAL,
176
+ attributes: {
177
+ "operation.name": operation
178
+ }
179
+ },
180
+ async (span) => {
181
+ try {
182
+ const result = await callback(span);
183
+ span.setStatus({ code: SpanStatusCode.OK });
184
+ return result;
185
+ } catch (error) {
186
+ span.setStatus({
187
+ code: SpanStatusCode.ERROR,
188
+ message: error instanceof Error ? error.message : String(error)
189
+ });
190
+ span.recordException(error);
191
+ throw error;
192
+ } finally {
193
+ span.end();
194
+ }
195
+ }
196
+ );
197
+ }
198
+ }
199
+ var opentelemetry_kafka_default = {
200
+ KafkaProducerTracing,
201
+ KafkaConsumerTracing,
202
+ KafkaAttributes
203
+ };
204
+ export {
205
+ KafkaAttributes,
206
+ KafkaConsumerTracing,
207
+ KafkaProducerTracing,
208
+ opentelemetry_kafka_default as default
209
+ };