specweave 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (428) hide show
  1. package/CLAUDE.md +229 -1817
  2. package/README.md +68 -0
  3. package/bin/specweave.js +62 -6
  4. package/dist/locales/de/.gitkeep +0 -0
  5. package/dist/locales/de/cli.json +108 -0
  6. package/dist/locales/en/cli.json +287 -0
  7. package/dist/locales/en/errors.json +7 -0
  8. package/dist/locales/en/templates.json +6 -0
  9. package/dist/locales/es/.gitkeep +0 -0
  10. package/dist/locales/es/cli.json +41 -0
  11. package/dist/locales/fr/.gitkeep +0 -0
  12. package/dist/locales/fr/cli.json +108 -0
  13. package/dist/locales/ja/.gitkeep +0 -0
  14. package/dist/locales/ja/cli.json +108 -0
  15. package/dist/locales/ko/.gitkeep +0 -0
  16. package/dist/locales/ko/cli.json +108 -0
  17. package/dist/locales/pt/.gitkeep +0 -0
  18. package/dist/locales/pt/cli.json +108 -0
  19. package/dist/locales/ru/.gitkeep +0 -0
  20. package/dist/locales/ru/cli.json +269 -0
  21. package/dist/locales/zh/.gitkeep +0 -0
  22. package/dist/locales/zh/cli.json +108 -0
  23. package/dist/plugins/specweave/lib/hooks/sync-living-docs.d.ts.map +1 -1
  24. package/dist/plugins/specweave/lib/hooks/sync-living-docs.js +3 -0
  25. package/dist/plugins/specweave/lib/hooks/sync-living-docs.js.map +1 -1
  26. package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts +21 -0
  27. package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts.map +1 -0
  28. package/dist/plugins/specweave/lib/hooks/update-ac-status.js +162 -0
  29. package/dist/plugins/specweave/lib/hooks/update-ac-status.js.map +1 -0
  30. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts.map +1 -1
  31. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js +65 -6
  32. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js.map +1 -1
  33. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts +25 -0
  34. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts.map +1 -0
  35. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js +191 -0
  36. package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js.map +1 -0
  37. package/dist/plugins/specweave-github/lib/completion-calculator.d.ts +112 -0
  38. package/dist/plugins/specweave-github/lib/completion-calculator.d.ts.map +1 -0
  39. package/dist/plugins/specweave-github/lib/completion-calculator.js +301 -0
  40. package/dist/plugins/specweave-github/lib/completion-calculator.js.map +1 -0
  41. package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts +3 -3
  42. package/dist/plugins/specweave-github/lib/duplicate-detector.js +3 -3
  43. package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts +70 -0
  44. package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +1 -0
  45. package/dist/plugins/specweave-github/lib/epic-content-builder.js +258 -0
  46. package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +1 -0
  47. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +14 -0
  48. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
  49. package/dist/plugins/specweave-github/lib/github-client-v2.js +51 -0
  50. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  51. package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts +2 -2
  52. package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts.map +1 -1
  53. package/dist/plugins/specweave-github/lib/github-epic-sync.js +20 -5
  54. package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +1 -1
  55. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +87 -0
  56. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -0
  57. package/dist/plugins/specweave-github/lib/github-feature-sync.js +412 -0
  58. package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -0
  59. package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
  60. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +64 -13
  61. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
  62. package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts +78 -0
  63. package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts.map +1 -0
  64. package/dist/plugins/specweave-github/lib/progress-comment-builder.js +237 -0
  65. package/dist/plugins/specweave-github/lib/progress-comment-builder.js.map +1 -0
  66. package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts +97 -0
  67. package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts.map +1 -0
  68. package/dist/plugins/specweave-github/lib/user-story-content-builder.js +301 -0
  69. package/dist/plugins/specweave-github/lib/user-story-content-builder.js.map +1 -0
  70. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts +83 -0
  71. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -0
  72. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +386 -0
  73. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -0
  74. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts +28 -0
  75. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts.map +1 -0
  76. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js +156 -0
  77. package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js.map +1 -0
  78. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.d.ts +57 -0
  79. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.d.ts.map +1 -0
  80. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +248 -0
  81. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.js.map +1 -0
  82. package/dist/plugins/specweave-kafka/lib/cli/types.d.ts +82 -0
  83. package/dist/plugins/specweave-kafka/lib/cli/types.d.ts.map +1 -0
  84. package/dist/plugins/specweave-kafka/lib/cli/types.js +13 -0
  85. package/dist/plugins/specweave-kafka/lib/cli/types.js.map +1 -0
  86. package/dist/plugins/specweave-kafka/lib/mcp/detector.d.ts +49 -0
  87. package/dist/plugins/specweave-kafka/lib/mcp/detector.d.ts.map +1 -0
  88. package/dist/plugins/specweave-kafka/lib/mcp/detector.js +316 -0
  89. package/dist/plugins/specweave-kafka/lib/mcp/detector.js.map +1 -0
  90. package/dist/plugins/specweave-kafka/lib/mcp/types.d.ts +70 -0
  91. package/dist/plugins/specweave-kafka/lib/mcp/types.d.ts.map +1 -0
  92. package/dist/plugins/specweave-kafka/lib/mcp/types.js +23 -0
  93. package/dist/plugins/specweave-kafka/lib/mcp/types.js.map +1 -0
  94. package/dist/plugins/specweave-kafka/lib/utils/partitioning.d.ts +85 -0
  95. package/dist/plugins/specweave-kafka/lib/utils/partitioning.d.ts.map +1 -0
  96. package/dist/plugins/specweave-kafka/lib/utils/partitioning.js +281 -0
  97. package/dist/plugins/specweave-kafka/lib/utils/partitioning.js.map +1 -0
  98. package/dist/plugins/specweave-kafka/lib/utils/sizing.d.ts +75 -0
  99. package/dist/plugins/specweave-kafka/lib/utils/sizing.d.ts.map +1 -0
  100. package/dist/plugins/specweave-kafka/lib/utils/sizing.js +238 -0
  101. package/dist/plugins/specweave-kafka/lib/utils/sizing.js.map +1 -0
  102. package/dist/spec-parser.js +629 -0
  103. package/dist/src/cli/commands/import-docs.js +4 -4
  104. package/dist/src/cli/commands/import-docs.js.map +1 -1
  105. package/dist/src/cli/commands/init-multiproject.d.ts.map +1 -1
  106. package/dist/src/cli/commands/init-multiproject.js +17 -18
  107. package/dist/src/cli/commands/init-multiproject.js.map +1 -1
  108. package/dist/src/cli/commands/init.d.ts.map +1 -1
  109. package/dist/src/cli/commands/init.js +107 -3
  110. package/dist/src/cli/commands/init.js.map +1 -1
  111. package/dist/src/cli/commands/migrate-to-multiproject.d.ts.map +1 -1
  112. package/dist/src/cli/commands/migrate-to-multiproject.js +8 -4
  113. package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
  114. package/dist/src/cli/commands/switch-project.d.ts.map +1 -1
  115. package/dist/src/cli/commands/switch-project.js +9 -26
  116. package/dist/src/cli/commands/switch-project.js.map +1 -1
  117. package/dist/src/cli/commands/sync-spec-content.js +3 -0
  118. package/dist/src/cli/commands/sync-spec-content.js.map +1 -1
  119. package/dist/src/core/deduplication/command-deduplicator.d.ts +166 -0
  120. package/dist/src/core/deduplication/command-deduplicator.d.ts.map +1 -0
  121. package/dist/src/core/deduplication/command-deduplicator.js +254 -0
  122. package/dist/src/core/deduplication/command-deduplicator.js.map +1 -0
  123. package/dist/src/core/increment/active-increment-manager.d.ts +42 -15
  124. package/dist/src/core/increment/active-increment-manager.d.ts.map +1 -1
  125. package/dist/src/core/increment/active-increment-manager.js +113 -46
  126. package/dist/src/core/increment/active-increment-manager.js.map +1 -1
  127. package/dist/src/core/increment/conflict-resolver.d.ts +40 -0
  128. package/dist/src/core/increment/conflict-resolver.d.ts.map +1 -0
  129. package/dist/src/core/increment/conflict-resolver.js +219 -0
  130. package/dist/src/core/increment/conflict-resolver.js.map +1 -0
  131. package/dist/src/core/increment/discipline-checker.d.ts.map +1 -1
  132. package/dist/src/core/increment/discipline-checker.js +7 -1
  133. package/dist/src/core/increment/discipline-checker.js.map +1 -1
  134. package/dist/src/core/increment/duplicate-detector.d.ts +52 -0
  135. package/dist/src/core/increment/duplicate-detector.d.ts.map +1 -0
  136. package/dist/src/core/increment/duplicate-detector.js +276 -0
  137. package/dist/src/core/increment/duplicate-detector.js.map +1 -0
  138. package/dist/src/core/increment/increment-archiver.d.ts +90 -0
  139. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -0
  140. package/dist/src/core/increment/increment-archiver.js +368 -0
  141. package/dist/src/core/increment/increment-archiver.js.map +1 -0
  142. package/dist/src/core/increment/increment-reopener.d.ts +165 -0
  143. package/dist/src/core/increment/increment-reopener.d.ts.map +1 -0
  144. package/dist/src/core/increment/increment-reopener.js +390 -0
  145. package/dist/src/core/increment/increment-reopener.js.map +1 -0
  146. package/dist/src/core/increment/metadata-manager.d.ts +26 -1
  147. package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
  148. package/dist/src/core/increment/metadata-manager.js +143 -5
  149. package/dist/src/core/increment/metadata-manager.js.map +1 -1
  150. package/dist/src/core/increment/recent-work-scanner.d.ts +121 -0
  151. package/dist/src/core/increment/recent-work-scanner.d.ts.map +1 -0
  152. package/dist/src/core/increment/recent-work-scanner.js +303 -0
  153. package/dist/src/core/increment/recent-work-scanner.js.map +1 -0
  154. package/dist/src/core/increment/types.d.ts +1 -0
  155. package/dist/src/core/increment/types.d.ts.map +1 -1
  156. package/dist/src/core/increment-utils.d.ts +112 -0
  157. package/dist/src/core/increment-utils.d.ts.map +1 -0
  158. package/dist/src/core/increment-utils.js +210 -0
  159. package/dist/src/core/increment-utils.js.map +1 -0
  160. package/dist/src/core/living-docs/ac-project-specific-generator.d.ts +65 -0
  161. package/dist/src/core/living-docs/ac-project-specific-generator.d.ts.map +1 -0
  162. package/dist/src/core/living-docs/ac-project-specific-generator.js +175 -0
  163. package/dist/src/core/living-docs/ac-project-specific-generator.js.map +1 -0
  164. package/dist/src/core/living-docs/feature-archiver.d.ts +130 -0
  165. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -0
  166. package/dist/src/core/living-docs/feature-archiver.js +549 -0
  167. package/dist/src/core/living-docs/feature-archiver.js.map +1 -0
  168. package/dist/src/core/living-docs/feature-id-manager.d.ts +81 -0
  169. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -0
  170. package/dist/src/core/living-docs/feature-id-manager.js +339 -0
  171. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -0
  172. package/dist/src/core/living-docs/hierarchy-mapper.d.ts +144 -83
  173. package/dist/src/core/living-docs/hierarchy-mapper.d.ts.map +1 -1
  174. package/dist/src/core/living-docs/hierarchy-mapper.js +488 -270
  175. package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
  176. package/dist/src/core/living-docs/index.d.ts +6 -0
  177. package/dist/src/core/living-docs/index.d.ts.map +1 -1
  178. package/dist/src/core/living-docs/index.js +6 -0
  179. package/dist/src/core/living-docs/index.js.map +1 -1
  180. package/dist/src/core/living-docs/project-detector.d.ts +6 -0
  181. package/dist/src/core/living-docs/project-detector.d.ts.map +1 -1
  182. package/dist/src/core/living-docs/project-detector.js +35 -1
  183. package/dist/src/core/living-docs/project-detector.js.map +1 -1
  184. package/dist/src/core/living-docs/spec-distributor.d.ts +100 -26
  185. package/dist/src/core/living-docs/spec-distributor.d.ts.map +1 -1
  186. package/dist/src/core/living-docs/spec-distributor.js +1275 -258
  187. package/dist/src/core/living-docs/spec-distributor.js.map +1 -1
  188. package/dist/src/core/living-docs/task-project-specific-generator.d.ts +109 -0
  189. package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -0
  190. package/dist/src/core/living-docs/task-project-specific-generator.js +221 -0
  191. package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -0
  192. package/dist/src/core/living-docs/types.d.ts +143 -0
  193. package/dist/src/core/living-docs/types.d.ts.map +1 -1
  194. package/dist/src/core/project-manager.d.ts +2 -17
  195. package/dist/src/core/project-manager.d.ts.map +1 -1
  196. package/dist/src/core/project-manager.js +68 -48
  197. package/dist/src/core/project-manager.js.map +1 -1
  198. package/dist/src/core/spec-content-sync.d.ts +1 -1
  199. package/dist/src/core/spec-content-sync.d.ts.map +1 -1
  200. package/dist/src/core/sync/enhanced-content-builder.d.ts +32 -54
  201. package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -1
  202. package/dist/src/core/sync/enhanced-content-builder.js +142 -138
  203. package/dist/src/core/sync/enhanced-content-builder.js.map +1 -1
  204. package/dist/src/core/sync/performance-optimizer.d.ts +153 -0
  205. package/dist/src/core/sync/performance-optimizer.d.ts.map +1 -0
  206. package/dist/src/core/sync/performance-optimizer.js +220 -0
  207. package/dist/src/core/sync/performance-optimizer.js.map +1 -0
  208. package/dist/src/core/sync/retry-handler.d.ts +98 -0
  209. package/dist/src/core/sync/retry-handler.d.ts.map +1 -0
  210. package/dist/src/core/sync/retry-handler.js +196 -0
  211. package/dist/src/core/sync/retry-handler.js.map +1 -0
  212. package/dist/src/core/sync/spec-content-sync.d.ts +88 -0
  213. package/dist/src/core/sync/spec-content-sync.d.ts.map +1 -0
  214. package/dist/src/core/sync/spec-content-sync.js +5 -0
  215. package/dist/src/core/sync/spec-content-sync.js.map +1 -0
  216. package/dist/src/core/sync/types.d.ts +52 -0
  217. package/dist/src/core/sync/types.d.ts.map +1 -0
  218. package/dist/src/core/sync/types.js +5 -0
  219. package/dist/src/core/sync/types.js.map +1 -0
  220. package/dist/src/core/types/config.d.ts +125 -0
  221. package/dist/src/core/types/config.d.ts.map +1 -1
  222. package/dist/src/core/types/config.js +25 -0
  223. package/dist/src/core/types/config.js.map +1 -1
  224. package/dist/src/core/types/increment-metadata.d.ts +10 -0
  225. package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
  226. package/dist/src/core/types/increment-metadata.js +10 -1
  227. package/dist/src/core/types/increment-metadata.js.map +1 -1
  228. package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
  229. package/dist/src/integrations/jira/jira-incremental-mapper.js +4 -8
  230. package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
  231. package/dist/src/integrations/jira/jira-mapper.d.ts.map +1 -1
  232. package/dist/src/integrations/jira/jira-mapper.js +4 -8
  233. package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
  234. package/dist/tsconfig.tsbuildinfo +1 -0
  235. package/package.json +1 -1
  236. package/plugins/specweave/COMMANDS.md +13 -4
  237. package/plugins/specweave/agents/pm/AGENT.md +159 -12
  238. package/plugins/specweave/commands/specweave-abandon.md +22 -20
  239. package/plugins/specweave/commands/specweave-archive-features.md +121 -0
  240. package/plugins/specweave/commands/specweave-archive-increments.md +82 -0
  241. package/plugins/specweave/commands/specweave-archive.md +363 -0
  242. package/plugins/specweave/commands/specweave-backlog.md +211 -0
  243. package/plugins/specweave/commands/specweave-fix-duplicates.md +517 -0
  244. package/plugins/specweave/commands/specweave-increment.md +4 -3
  245. package/plugins/specweave/commands/specweave-progress.md +176 -27
  246. package/plugins/specweave/commands/specweave-reopen.md +391 -0
  247. package/plugins/specweave/commands/specweave-restore-feature.md +90 -0
  248. package/plugins/specweave/commands/specweave-restore.md +309 -0
  249. package/plugins/specweave/commands/specweave-resume.md +51 -23
  250. package/plugins/specweave/commands/specweave-status.md +41 -7
  251. package/plugins/specweave/commands/specweave-sync-specs.md +425 -0
  252. package/plugins/specweave/commands/specweave.md +70 -405
  253. package/plugins/specweave/hooks/hooks.json +4 -0
  254. package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
  255. package/plugins/specweave/hooks/post-increment-planning.sh +26 -2
  256. package/plugins/specweave/hooks/post-task-completion.sh +39 -0
  257. package/plugins/specweave/hooks/pre-command-deduplication.sh +83 -0
  258. package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
  259. package/plugins/specweave/lib/hooks/sync-living-docs.js +2 -0
  260. package/plugins/specweave/lib/hooks/sync-living-docs.ts +4 -0
  261. package/plugins/specweave/lib/hooks/update-ac-status.js +102 -0
  262. package/plugins/specweave/lib/hooks/update-ac-status.ts +192 -0
  263. package/plugins/specweave/skills/archive-increments/SKILL.md +198 -0
  264. package/plugins/specweave/skills/increment-planner/scripts/feature-utils.js +14 -0
  265. package/plugins/specweave/skills/smart-reopen-detector/SKILL.md +244 -0
  266. package/plugins/specweave-ado/lib/ado-spec-content-sync.js +49 -5
  267. package/plugins/specweave-ado/lib/ado-spec-content-sync.ts +72 -6
  268. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
  269. package/plugins/specweave-confluent/.claude-plugin/plugin.json +23 -0
  270. package/plugins/specweave-confluent/README.md +375 -0
  271. package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +306 -0
  272. package/plugins/specweave-confluent/skills/confluent-kafka-connect/SKILL.md +453 -0
  273. package/plugins/specweave-confluent/skills/confluent-ksqldb/SKILL.md +470 -0
  274. package/plugins/specweave-confluent/skills/confluent-schema-registry/SKILL.md +316 -0
  275. package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +2 -2
  276. package/plugins/specweave-github/agents/user-story-updater/AGENT.md +148 -0
  277. package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +1 -1
  278. package/plugins/specweave-github/commands/specweave-github-update-user-story.md +156 -0
  279. package/plugins/specweave-github/hooks/post-task-completion.sh +42 -9
  280. package/plugins/specweave-github/lib/completion-calculator.js +262 -0
  281. package/plugins/specweave-github/lib/completion-calculator.ts +434 -0
  282. package/plugins/specweave-github/lib/duplicate-detector.js +3 -3
  283. package/plugins/specweave-github/lib/duplicate-detector.ts +4 -4
  284. package/plugins/specweave-github/lib/epic-content-builder.js +265 -0
  285. package/plugins/specweave-github/lib/epic-content-builder.ts +376 -0
  286. package/plugins/specweave-github/lib/github-client-v2.js +49 -0
  287. package/plugins/specweave-github/lib/github-client-v2.ts +59 -0
  288. package/plugins/specweave-github/lib/github-epic-sync.js +23 -24
  289. package/plugins/specweave-github/lib/github-epic-sync.ts +30 -5
  290. package/plugins/specweave-github/lib/github-feature-sync.js +381 -0
  291. package/plugins/specweave-github/lib/github-feature-sync.ts +568 -0
  292. package/plugins/specweave-github/lib/github-spec-content-sync.js +40 -10
  293. package/plugins/specweave-github/lib/github-spec-content-sync.ts +82 -14
  294. package/plugins/specweave-github/lib/progress-comment-builder.js +229 -0
  295. package/plugins/specweave-github/lib/progress-comment-builder.ts +324 -0
  296. package/plugins/specweave-github/lib/user-story-content-builder.js +299 -0
  297. package/plugins/specweave-github/lib/user-story-content-builder.ts +413 -0
  298. package/plugins/specweave-github/lib/user-story-issue-builder.js +344 -0
  299. package/plugins/specweave-github/lib/user-story-issue-builder.ts +543 -0
  300. package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +189 -0
  301. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
  302. package/plugins/specweave-jira/lib/{enhanced-jira-sync.ts.disabled → enhanced-jira-sync.ts} +26 -52
  303. package/plugins/specweave-kafka/.claude-plugin/plugin.json +26 -0
  304. package/plugins/specweave-kafka/IMPLEMENTATION-COMPLETE.md +483 -0
  305. package/plugins/specweave-kafka/README.md +242 -0
  306. package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +235 -0
  307. package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +209 -0
  308. package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +266 -0
  309. package/plugins/specweave-kafka/commands/deploy.md +99 -0
  310. package/plugins/specweave-kafka/commands/dev-env.md +176 -0
  311. package/plugins/specweave-kafka/commands/mcp-configure.md +101 -0
  312. package/plugins/specweave-kafka/commands/monitor-setup.md +96 -0
  313. package/plugins/specweave-kafka/docker/kafka-local/docker-compose.yml +187 -0
  314. package/plugins/specweave-kafka/docker/redpanda/docker-compose.yml +199 -0
  315. package/plugins/specweave-kafka/docker/templates/consumer-nodejs.js +225 -0
  316. package/plugins/specweave-kafka/docker/templates/consumer-python.py +220 -0
  317. package/plugins/specweave-kafka/docker/templates/producer-nodejs.js +168 -0
  318. package/plugins/specweave-kafka/docker/templates/producer-python.py +167 -0
  319. package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.js +438 -0
  320. package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.ts +541 -0
  321. package/plugins/specweave-kafka/lib/adapters/platform-adapter.js +47 -0
  322. package/plugins/specweave-kafka/lib/adapters/platform-adapter.ts +343 -0
  323. package/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +258 -0
  324. package/plugins/specweave-kafka/lib/cli/kcat-wrapper.ts +298 -0
  325. package/plugins/specweave-kafka/lib/cli/types.js +10 -0
  326. package/plugins/specweave-kafka/lib/cli/types.ts +92 -0
  327. package/plugins/specweave-kafka/lib/connectors/connector-catalog.js +305 -0
  328. package/plugins/specweave-kafka/lib/connectors/connector-catalog.ts +528 -0
  329. package/plugins/specweave-kafka/lib/documentation/diagram-generator.js +114 -0
  330. package/plugins/specweave-kafka/lib/documentation/diagram-generator.ts +195 -0
  331. package/plugins/specweave-kafka/lib/documentation/exporter.js +210 -0
  332. package/plugins/specweave-kafka/lib/documentation/exporter.ts +338 -0
  333. package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.js +60 -0
  334. package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.ts +130 -0
  335. package/plugins/specweave-kafka/lib/documentation/topology-generator.js +143 -0
  336. package/plugins/specweave-kafka/lib/documentation/topology-generator.ts +290 -0
  337. package/plugins/specweave-kafka/lib/mcp/detector.js +298 -0
  338. package/plugins/specweave-kafka/lib/mcp/detector.ts +352 -0
  339. package/plugins/specweave-kafka/lib/mcp/types.js +21 -0
  340. package/plugins/specweave-kafka/lib/mcp/types.ts +77 -0
  341. package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.js +193 -0
  342. package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.ts +362 -0
  343. package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.js +188 -0
  344. package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.ts +359 -0
  345. package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.js +195 -0
  346. package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.ts +380 -0
  347. package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.js +209 -0
  348. package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.ts +358 -0
  349. package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.js +354 -0
  350. package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.ts +563 -0
  351. package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.js +259 -0
  352. package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.ts +516 -0
  353. package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.js +233 -0
  354. package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.ts +423 -0
  355. package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.js +266 -0
  356. package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.ts +445 -0
  357. package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.js +312 -0
  358. package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.ts +561 -0
  359. package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.js +289 -0
  360. package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.ts +607 -0
  361. package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.js +264 -0
  362. package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.ts +498 -0
  363. package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.js +263 -0
  364. package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.ts +549 -0
  365. package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.js +205 -0
  366. package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.ts +399 -0
  367. package/plugins/specweave-kafka/lib/performance/performance-optimizer.js +249 -0
  368. package/plugins/specweave-kafka/lib/performance/performance-optimizer.ts +427 -0
  369. package/plugins/specweave-kafka/lib/security/kafka-security.js +252 -0
  370. package/plugins/specweave-kafka/lib/security/kafka-security.ts +494 -0
  371. package/plugins/specweave-kafka/lib/utils/capacity-planner.js +203 -0
  372. package/plugins/specweave-kafka/lib/utils/capacity-planner.ts +469 -0
  373. package/plugins/specweave-kafka/lib/utils/config-validator.js +419 -0
  374. package/plugins/specweave-kafka/lib/utils/config-validator.ts +564 -0
  375. package/plugins/specweave-kafka/lib/utils/partitioning.js +329 -0
  376. package/plugins/specweave-kafka/lib/utils/partitioning.ts +473 -0
  377. package/plugins/specweave-kafka/lib/utils/sizing.js +221 -0
  378. package/plugins/specweave-kafka/lib/utils/sizing.ts +374 -0
  379. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-broker-metrics.json +628 -0
  380. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-cluster-overview.json +564 -0
  381. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-consumer-lag.json +509 -0
  382. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-jvm-metrics.json +674 -0
  383. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-topic-metrics.json +578 -0
  384. package/plugins/specweave-kafka/monitoring/grafana/provisioning/dashboards/kafka.yml +17 -0
  385. package/plugins/specweave-kafka/monitoring/grafana/provisioning/datasources/prometheus.yml +17 -0
  386. package/plugins/specweave-kafka/monitoring/prometheus/kafka-alerts.yml +415 -0
  387. package/plugins/specweave-kafka/monitoring/prometheus/kafka-jmx-exporter.yml +256 -0
  388. package/plugins/specweave-kafka/package.json +41 -0
  389. package/plugins/specweave-kafka/skills/kafka-architecture/SKILL.md +647 -0
  390. package/plugins/specweave-kafka/skills/kafka-cli-tools/SKILL.md +433 -0
  391. package/plugins/specweave-kafka/skills/kafka-iac-deployment/SKILL.md +449 -0
  392. package/plugins/specweave-kafka/skills/kafka-kubernetes/SKILL.md +667 -0
  393. package/plugins/specweave-kafka/skills/kafka-mcp-integration/SKILL.md +273 -0
  394. package/plugins/specweave-kafka/skills/kafka-observability/SKILL.md +576 -0
  395. package/plugins/specweave-kafka/templates/config/broker-production.properties +254 -0
  396. package/plugins/specweave-kafka/templates/config/consumer-low-latency.properties +112 -0
  397. package/plugins/specweave-kafka/templates/config/producer-high-throughput.properties +120 -0
  398. package/plugins/specweave-kafka/templates/migration/mirrormaker2-config.properties +234 -0
  399. package/plugins/specweave-kafka/templates/monitoring/grafana/multi-cluster-dashboard.json +686 -0
  400. package/plugins/specweave-kafka/terraform/apache-kafka/main.tf +347 -0
  401. package/plugins/specweave-kafka/terraform/apache-kafka/outputs.tf +107 -0
  402. package/plugins/specweave-kafka/terraform/apache-kafka/templates/kafka-broker-init.sh.tpl +216 -0
  403. package/plugins/specweave-kafka/terraform/apache-kafka/variables.tf +156 -0
  404. package/plugins/specweave-kafka/terraform/aws-msk/main.tf +362 -0
  405. package/plugins/specweave-kafka/terraform/aws-msk/outputs.tf +93 -0
  406. package/plugins/specweave-kafka/terraform/aws-msk/templates/server.properties.tpl +32 -0
  407. package/plugins/specweave-kafka/terraform/aws-msk/variables.tf +235 -0
  408. package/plugins/specweave-kafka/terraform/azure-event-hubs/main.tf +281 -0
  409. package/plugins/specweave-kafka/terraform/azure-event-hubs/outputs.tf +118 -0
  410. package/plugins/specweave-kafka/terraform/azure-event-hubs/variables.tf +148 -0
  411. package/plugins/specweave-kafka/tsconfig.json +21 -0
  412. package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +23 -0
  413. package/plugins/specweave-kafka-streams/README.md +310 -0
  414. package/plugins/specweave-kafka-streams/skills/kafka-streams-topology/SKILL.md +539 -0
  415. package/plugins/specweave-n8n/.claude-plugin/plugin.json +22 -0
  416. package/plugins/specweave-n8n/README.md +354 -0
  417. package/plugins/specweave-n8n/skills/n8n-kafka-workflows/SKILL.md +504 -0
  418. package/plugins/specweave-release/commands/specweave-release-platform.md +1 -1
  419. package/plugins/specweave-release/hooks/post-task-completion.sh +2 -2
  420. package/src/templates/AGENTS.md.template +601 -7
  421. package/src/templates/CLAUDE.md.template +188 -88
  422. package/plugins/specweave-ado/commands/specweave-ado-sync-spec.md +0 -255
  423. package/plugins/specweave-github/commands/specweave-github-sync-epic.md +0 -248
  424. package/plugins/specweave-github/commands/specweave-github-sync-from.md +0 -147
  425. package/plugins/specweave-github/commands/specweave-github-sync-spec.md +0 -208
  426. package/plugins/specweave-github/commands/specweave-github-sync-tasks.md +0 -530
  427. package/plugins/specweave-jira/commands/specweave-jira-sync-epic.md +0 -267
  428. package/plugins/specweave-jira/commands/specweave-jira-sync-spec.md +0 -240
@@ -0,0 +1,266 @@
1
+ import { CompressionTypes } from "kafkajs";
2
+ class ExactlyOnceProducer {
3
+ constructor(kafka, config) {
4
+ this.inTransaction = false;
5
+ this.config = {
6
+ transactionalId: config.transactionalId,
7
+ transactionTimeout: config.transactionTimeout || 6e4,
8
+ idempotent: config.idempotent !== false,
9
+ // Default true
10
+ maxInFlightRequests: config.maxInFlightRequests || 5,
11
+ compressionType: config.compressionType || CompressionTypes.GZIP
12
+ };
13
+ this.producer = kafka.producer({
14
+ transactionalId: this.config.transactionalId,
15
+ idempotent: this.config.idempotent,
16
+ maxInFlightRequests: this.config.maxInFlightRequests
17
+ });
18
+ }
19
+ /**
20
+ * Connect producer
21
+ */
22
+ async connect() {
23
+ await this.producer.connect();
24
+ }
25
+ /**
26
+ * Disconnect producer
27
+ */
28
+ async disconnect() {
29
+ if (this.inTransaction) {
30
+ await this.abortTransaction();
31
+ }
32
+ await this.producer.disconnect();
33
+ }
34
+ /**
35
+ * Begin transaction
36
+ */
37
+ async beginTransaction() {
38
+ if (this.inTransaction) {
39
+ throw new Error("Transaction already in progress");
40
+ }
41
+ await this.producer.transaction();
42
+ this.inTransaction = true;
43
+ }
44
+ /**
45
+ * Send message within transaction
46
+ */
47
+ async send(topic, messages) {
48
+ if (!this.inTransaction) {
49
+ throw new Error("No active transaction. Call beginTransaction() first.");
50
+ }
51
+ return this.producer.send({
52
+ topic,
53
+ messages,
54
+ compression: this.config.compressionType
55
+ });
56
+ }
57
+ /**
58
+ * Commit transaction
59
+ */
60
+ async commitTransaction() {
61
+ if (!this.inTransaction) {
62
+ throw new Error("No active transaction to commit");
63
+ }
64
+ await this.producer.commit();
65
+ this.inTransaction = false;
66
+ }
67
+ /**
68
+ * Abort transaction
69
+ */
70
+ async abortTransaction() {
71
+ if (!this.inTransaction) {
72
+ throw new Error("No active transaction to abort");
73
+ }
74
+ await this.producer.abort();
75
+ this.inTransaction = false;
76
+ }
77
+ /**
78
+ * Execute operation within transaction (auto-commit/abort)
79
+ */
80
+ async executeTransaction(operation) {
81
+ await this.beginTransaction();
82
+ try {
83
+ const result = await operation(this.producer);
84
+ await this.commitTransaction();
85
+ return result;
86
+ } catch (error) {
87
+ await this.abortTransaction();
88
+ throw error;
89
+ }
90
+ }
91
+ }
92
+ class ExactlyOnceConsumer {
93
+ constructor(kafka, config) {
94
+ this.config = {
95
+ groupId: config.groupId,
96
+ isolationLevel: config.isolationLevel || "read_committed",
97
+ enableAutoCommit: false
98
+ // Must be false for EOS
99
+ };
100
+ this.consumer = kafka.consumer({
101
+ groupId: this.config.groupId,
102
+ // @ts-ignore - isolationLevel typing issue in kafkajs
103
+ isolationLevel: this.config.isolationLevel
104
+ });
105
+ }
106
+ /**
107
+ * Connect consumer
108
+ */
109
+ async connect() {
110
+ await this.consumer.connect();
111
+ }
112
+ /**
113
+ * Disconnect consumer
114
+ */
115
+ async disconnect() {
116
+ await this.consumer.disconnect();
117
+ }
118
+ /**
119
+ * Subscribe to topics
120
+ */
121
+ async subscribe(topics) {
122
+ await this.consumer.subscribe({
123
+ topics,
124
+ fromBeginning: false
125
+ });
126
+ }
127
+ /**
128
+ * Run consumer with exactly-once processing
129
+ *
130
+ * Automatically commits offsets only after successful processing.
131
+ */
132
+ async run(handler) {
133
+ await this.consumer.run({
134
+ autoCommit: false,
135
+ // Manual offset management for EOS
136
+ eachMessage: async (payload) => {
137
+ try {
138
+ await handler(payload);
139
+ await this.consumer.commitOffsets([
140
+ {
141
+ topic: payload.topic,
142
+ partition: payload.partition,
143
+ offset: (parseInt(payload.message.offset) + 1).toString()
144
+ }
145
+ ]);
146
+ } catch (error) {
147
+ console.error("Message processing failed:", error);
148
+ throw error;
149
+ }
150
+ }
151
+ });
152
+ }
153
+ }
154
+ class ExactlyOnceProcessor {
155
+ constructor(kafka, consumerGroupId, transactionalId) {
156
+ this.transactionalId = transactionalId;
157
+ this.consumer = kafka.consumer({
158
+ groupId: consumerGroupId,
159
+ // @ts-ignore
160
+ isolationLevel: "read_committed"
161
+ });
162
+ this.producer = kafka.producer({
163
+ transactionalId,
164
+ idempotent: true,
165
+ maxInFlightRequests: 5
166
+ });
167
+ }
168
+ /**
169
+ * Connect consumer and producer
170
+ */
171
+ async connect() {
172
+ await this.consumer.connect();
173
+ await this.producer.connect();
174
+ }
175
+ /**
176
+ * Disconnect consumer and producer
177
+ */
178
+ async disconnect() {
179
+ await this.consumer.disconnect();
180
+ await this.producer.disconnect();
181
+ }
182
+ /**
183
+ * Subscribe to input topics
184
+ */
185
+ async subscribe(topics) {
186
+ await this.consumer.subscribe({ topics, fromBeginning: false });
187
+ }
188
+ /**
189
+ * Run exactly-once consume-process-produce loop
190
+ *
191
+ * Pattern: Read → Transform → Write → Commit (all atomic)
192
+ */
193
+ async run(handler) {
194
+ await this.consumer.run({
195
+ autoCommit: false,
196
+ eachMessage: async (payload) => {
197
+ const transaction = await this.producer.transaction();
198
+ try {
199
+ const output = await handler(payload);
200
+ if (output) {
201
+ await transaction.send(output);
202
+ }
203
+ await transaction.sendOffsets({
204
+ consumerGroupId: this.consumer.groupId,
205
+ topics: [
206
+ {
207
+ topic: payload.topic,
208
+ partitions: [
209
+ {
210
+ partition: payload.partition,
211
+ offset: (parseInt(payload.message.offset) + 1).toString()
212
+ }
213
+ ]
214
+ }
215
+ ]
216
+ });
217
+ await transaction.commit();
218
+ } catch (error) {
219
+ await transaction.abort();
220
+ console.error("Transaction aborted:", error);
221
+ throw error;
222
+ }
223
+ }
224
+ });
225
+ }
226
+ }
227
+ class IdempotentProducer {
228
+ constructor(kafka) {
229
+ this.producer = kafka.producer({
230
+ idempotent: true,
231
+ // Enable idempotence
232
+ maxInFlightRequests: 5,
233
+ // Max 5 for idempotence
234
+ acks: -1
235
+ // Wait for all replicas
236
+ });
237
+ }
238
+ async connect() {
239
+ await this.producer.connect();
240
+ }
241
+ async disconnect() {
242
+ await this.producer.disconnect();
243
+ }
244
+ async send(topic, messages) {
245
+ return this.producer.send({
246
+ topic,
247
+ messages,
248
+ acks: -1,
249
+ // Wait for all in-sync replicas
250
+ compression: CompressionTypes.GZIP
251
+ });
252
+ }
253
+ }
254
+ var exactly_once_semantics_default = {
255
+ ExactlyOnceProducer,
256
+ ExactlyOnceConsumer,
257
+ ExactlyOnceProcessor,
258
+ IdempotentProducer
259
+ };
260
+ export {
261
+ ExactlyOnceConsumer,
262
+ ExactlyOnceProcessor,
263
+ ExactlyOnceProducer,
264
+ IdempotentProducer,
265
+ exactly_once_semantics_default as default
266
+ };
@@ -0,0 +1,445 @@
1
+ /**
2
+ * Exactly-Once Semantics (EOS) Implementation for Kafka
3
+ *
4
+ * Provides patterns and utilities for achieving exactly-once delivery
5
+ * guarantees in Kafka producers and consumers.
6
+ *
7
+ * @module exactly-once-semantics
8
+ */
9
+
10
+ import { Producer, Consumer, Kafka, EachMessagePayload, CompressionTypes } from 'kafkajs';
11
+
12
+ /**
13
+ * EOS Configuration for Producer
14
+ */
15
+ export interface EOSProducerConfig {
16
+ /** Transactional ID (must be unique per producer instance) */
17
+ transactionalId: string;
18
+ /** Max time to wait for transaction commit (default: 60000ms) */
19
+ transactionTimeout?: number;
20
+ /** Enable idempotent producer (required for EOS) */
21
+ idempotent?: boolean;
22
+ /** Max in-flight requests (default: 5 for EOS) */
23
+ maxInFlightRequests?: number;
24
+ /** Compression type (default: gzip) */
25
+ compressionType?: CompressionTypes;
26
+ }
27
+
28
+ /**
29
+ * EOS Configuration for Consumer
30
+ */
31
+ export interface EOSConsumerConfig {
32
+ /** Consumer group ID */
33
+ groupId: string;
34
+ /** Isolation level (read_committed for EOS) */
35
+ isolationLevel?: 'read_committed' | 'read_uncommitted';
36
+ /** Enable auto-commit (must be false for EOS) */
37
+ enableAutoCommit?: boolean;
38
+ }
39
+
40
+ /**
41
+ * Exactly-Once Producer
42
+ *
43
+ * Implements transactional producer with exactly-once delivery guarantees.
44
+ */
45
+ export class ExactlyOnceProducer {
46
+ private producer: Producer;
47
+ private config: Required<EOSProducerConfig>;
48
+ private inTransaction = false;
49
+
50
+ constructor(kafka: Kafka, config: EOSProducerConfig) {
51
+ this.config = {
52
+ transactionalId: config.transactionalId,
53
+ transactionTimeout: config.transactionTimeout || 60000,
54
+ idempotent: config.idempotent !== false, // Default true
55
+ maxInFlightRequests: config.maxInFlightRequests || 5,
56
+ compressionType: config.compressionType || CompressionTypes.GZIP,
57
+ };
58
+
59
+ this.producer = kafka.producer({
60
+ transactionalId: this.config.transactionalId,
61
+ idempotent: this.config.idempotent,
62
+ maxInFlightRequests: this.config.maxInFlightRequests,
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Connect producer
68
+ */
69
+ async connect(): Promise<void> {
70
+ await this.producer.connect();
71
+ }
72
+
73
+ /**
74
+ * Disconnect producer
75
+ */
76
+ async disconnect(): Promise<void> {
77
+ if (this.inTransaction) {
78
+ await this.abortTransaction();
79
+ }
80
+ await this.producer.disconnect();
81
+ }
82
+
83
+ /**
84
+ * Begin transaction
85
+ */
86
+ async beginTransaction(): Promise<void> {
87
+ if (this.inTransaction) {
88
+ throw new Error('Transaction already in progress');
89
+ }
90
+ await this.producer.transaction();
91
+ this.inTransaction = true;
92
+ }
93
+
94
+ /**
95
+ * Send message within transaction
96
+ */
97
+ async send(topic: string, messages: Array<{ key?: string; value: string }>) {
98
+ if (!this.inTransaction) {
99
+ throw new Error('No active transaction. Call beginTransaction() first.');
100
+ }
101
+
102
+ return this.producer.send({
103
+ topic,
104
+ messages,
105
+ compression: this.config.compressionType,
106
+ });
107
+ }
108
+
109
+ /**
110
+ * Commit transaction
111
+ */
112
+ async commitTransaction(): Promise<void> {
113
+ if (!this.inTransaction) {
114
+ throw new Error('No active transaction to commit');
115
+ }
116
+ await this.producer.commit();
117
+ this.inTransaction = false;
118
+ }
119
+
120
+ /**
121
+ * Abort transaction
122
+ */
123
+ async abortTransaction(): Promise<void> {
124
+ if (!this.inTransaction) {
125
+ throw new Error('No active transaction to abort');
126
+ }
127
+ await this.producer.abort();
128
+ this.inTransaction = false;
129
+ }
130
+
131
+ /**
132
+ * Execute operation within transaction (auto-commit/abort)
133
+ */
134
+ async executeTransaction<T>(
135
+ operation: (producer: Producer) => Promise<T>
136
+ ): Promise<T> {
137
+ await this.beginTransaction();
138
+ try {
139
+ const result = await operation(this.producer);
140
+ await this.commitTransaction();
141
+ return result;
142
+ } catch (error) {
143
+ await this.abortTransaction();
144
+ throw error;
145
+ }
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Exactly-Once Consumer
151
+ *
152
+ * Implements consumer with read_committed isolation level for EOS.
153
+ */
154
+ export class ExactlyOnceConsumer {
155
+ private consumer: Consumer;
156
+ private config: Required<EOSConsumerConfig>;
157
+
158
+ constructor(kafka: Kafka, config: EOSConsumerConfig) {
159
+ this.config = {
160
+ groupId: config.groupId,
161
+ isolationLevel: config.isolationLevel || 'read_committed',
162
+ enableAutoCommit: false, // Must be false for EOS
163
+ };
164
+
165
+ this.consumer = kafka.consumer({
166
+ groupId: this.config.groupId,
167
+ // @ts-ignore - isolationLevel typing issue in kafkajs
168
+ isolationLevel: this.config.isolationLevel,
169
+ });
170
+ }
171
+
172
+ /**
173
+ * Connect consumer
174
+ */
175
+ async connect(): Promise<void> {
176
+ await this.consumer.connect();
177
+ }
178
+
179
+ /**
180
+ * Disconnect consumer
181
+ */
182
+ async disconnect(): Promise<void> {
183
+ await this.consumer.disconnect();
184
+ }
185
+
186
+ /**
187
+ * Subscribe to topics
188
+ */
189
+ async subscribe(topics: string[]): Promise<void> {
190
+ await this.consumer.subscribe({
191
+ topics,
192
+ fromBeginning: false,
193
+ });
194
+ }
195
+
196
+ /**
197
+ * Run consumer with exactly-once processing
198
+ *
199
+ * Automatically commits offsets only after successful processing.
200
+ */
201
+ async run(
202
+ handler: (payload: EachMessagePayload) => Promise<void>
203
+ ): Promise<void> {
204
+ await this.consumer.run({
205
+ autoCommit: false, // Manual offset management for EOS
206
+ eachMessage: async (payload) => {
207
+ try {
208
+ // Process message
209
+ await handler(payload);
210
+
211
+ // Commit offset only after successful processing
212
+ await this.consumer.commitOffsets([
213
+ {
214
+ topic: payload.topic,
215
+ partition: payload.partition,
216
+ offset: (parseInt(payload.message.offset) + 1).toString(),
217
+ },
218
+ ]);
219
+ } catch (error) {
220
+ // Error: offset NOT committed, message will be reprocessed
221
+ console.error('Message processing failed:', error);
222
+ throw error;
223
+ }
224
+ },
225
+ });
226
+ }
227
+ }
228
+
229
+ /**
230
+ * End-to-End Exactly-Once Pattern
231
+ *
232
+ * Combines transactional producer and consumer for consume-process-produce pattern.
233
+ */
234
+ export class ExactlyOnceProcessor {
235
+ private consumer: Consumer;
236
+ private producer: Producer;
237
+ private transactionalId: string;
238
+
239
+ constructor(kafka: Kafka, consumerGroupId: string, transactionalId: string) {
240
+ this.transactionalId = transactionalId;
241
+
242
+ // Consumer with read_committed
243
+ this.consumer = kafka.consumer({
244
+ groupId: consumerGroupId,
245
+ // @ts-ignore
246
+ isolationLevel: 'read_committed',
247
+ });
248
+
249
+ // Transactional producer
250
+ this.producer = kafka.producer({
251
+ transactionalId,
252
+ idempotent: true,
253
+ maxInFlightRequests: 5,
254
+ });
255
+ }
256
+
257
+ /**
258
+ * Connect consumer and producer
259
+ */
260
+ async connect(): Promise<void> {
261
+ await this.consumer.connect();
262
+ await this.producer.connect();
263
+ }
264
+
265
+ /**
266
+ * Disconnect consumer and producer
267
+ */
268
+ async disconnect(): Promise<void> {
269
+ await this.consumer.disconnect();
270
+ await this.producer.disconnect();
271
+ }
272
+
273
+ /**
274
+ * Subscribe to input topics
275
+ */
276
+ async subscribe(topics: string[]): Promise<void> {
277
+ await this.consumer.subscribe({ topics, fromBeginning: false });
278
+ }
279
+
280
+ /**
281
+ * Run exactly-once consume-process-produce loop
282
+ *
283
+ * Pattern: Read → Transform → Write → Commit (all atomic)
284
+ */
285
+ async run(
286
+ handler: (
287
+ payload: EachMessagePayload
288
+ ) => Promise<{ topic: string; messages: Array<{ key?: string; value: string }> } | null>
289
+ ): Promise<void> {
290
+ await this.consumer.run({
291
+ autoCommit: false,
292
+ eachMessage: async (payload) => {
293
+ // Begin transaction
294
+ const transaction = await this.producer.transaction();
295
+
296
+ try {
297
+ // 1. Process message (transform)
298
+ const output = await handler(payload);
299
+
300
+ // 2. Send output (if any)
301
+ if (output) {
302
+ await transaction.send(output);
303
+ }
304
+
305
+ // 3. Commit consumer offset within transaction
306
+ await transaction.sendOffsets({
307
+ consumerGroupId: this.consumer.groupId,
308
+ topics: [
309
+ {
310
+ topic: payload.topic,
311
+ partitions: [
312
+ {
313
+ partition: payload.partition,
314
+ offset: (parseInt(payload.message.offset) + 1).toString(),
315
+ },
316
+ ],
317
+ },
318
+ ],
319
+ });
320
+
321
+ // 4. Commit transaction (atomic: write + offset commit)
322
+ await transaction.commit();
323
+ } catch (error) {
324
+ // Abort transaction (rollback everything)
325
+ await transaction.abort();
326
+ console.error('Transaction aborted:', error);
327
+ throw error;
328
+ }
329
+ },
330
+ });
331
+ }
332
+ }
333
+
334
+ /**
335
+ * Idempotent Producer (Simplified EOS)
336
+ *
337
+ * Ensures at-least-once delivery without duplicates (no transactions).
338
+ */
339
+ export class IdempotentProducer {
340
+ private producer: Producer;
341
+
342
+ constructor(kafka: Kafka) {
343
+ this.producer = kafka.producer({
344
+ idempotent: true, // Enable idempotence
345
+ maxInFlightRequests: 5, // Max 5 for idempotence
346
+ acks: -1, // Wait for all replicas
347
+ });
348
+ }
349
+
350
+ async connect(): Promise<void> {
351
+ await this.producer.connect();
352
+ }
353
+
354
+ async disconnect(): Promise<void> {
355
+ await this.producer.disconnect();
356
+ }
357
+
358
+ async send(topic: string, messages: Array<{ key?: string; value: string }>) {
359
+ return this.producer.send({
360
+ topic,
361
+ messages,
362
+ acks: -1, // Wait for all in-sync replicas
363
+ compression: CompressionTypes.GZIP,
364
+ });
365
+ }
366
+ }
367
+
368
+ /**
369
+ * Example Usage: Exactly-Once Producer
370
+ *
371
+ * ```typescript
372
+ * const kafka = new Kafka({ brokers: ['localhost:9092'] });
373
+ * const eosProducer = new ExactlyOnceProducer(kafka, {
374
+ * transactionalId: 'my-producer-1', // Unique per instance
375
+ * });
376
+ *
377
+ * await eosProducer.connect();
378
+ *
379
+ * // Option 1: Manual transaction control
380
+ * await eosProducer.beginTransaction();
381
+ * await eosProducer.send('orders', [{ key: '123', value: '{"total": 99.99}' }]);
382
+ * await eosProducer.send('analytics', [{ value: '{"event": "order_created"}' }]);
383
+ * await eosProducer.commitTransaction(); // Atomic commit
384
+ *
385
+ * // Option 2: Auto-commit/abort wrapper
386
+ * await eosProducer.executeTransaction(async (producer) => {
387
+ * await producer.send({ topic: 'orders', messages: [...] });
388
+ * await producer.send({ topic: 'analytics', messages: [...] });
389
+ * });
390
+ * ```
391
+ */
392
+
393
+ /**
394
+ * Example Usage: Exactly-Once Consumer
395
+ *
396
+ * ```typescript
397
+ * const eosConsumer = new ExactlyOnceConsumer(kafka, {
398
+ * groupId: 'my-consumer-group',
399
+ * });
400
+ *
401
+ * await eosConsumer.connect();
402
+ * await eosConsumer.subscribe(['orders']);
403
+ *
404
+ * await eosConsumer.run(async ({ message }) => {
405
+ * const order = JSON.parse(message.value.toString());
406
+ * await processOrder(order); // Process message
407
+ * // Offset committed automatically only on success
408
+ * });
409
+ * ```
410
+ */
411
+
412
+ /**
413
+ * Example Usage: End-to-End Exactly-Once
414
+ *
415
+ * ```typescript
416
+ * const processor = new ExactlyOnceProcessor(
417
+ * kafka,
418
+ * 'transform-consumer-group',
419
+ * 'transform-producer-1'
420
+ * );
421
+ *
422
+ * await processor.connect();
423
+ * await processor.subscribe(['input-topic']);
424
+ *
425
+ * await processor.run(async ({ message }) => {
426
+ * // Transform message
427
+ * const input = JSON.parse(message.value.toString());
428
+ * const output = transform(input);
429
+ *
430
+ * // Return output to send (or null to skip)
431
+ * return {
432
+ * topic: 'output-topic',
433
+ * messages: [{ key: input.id, value: JSON.stringify(output) }],
434
+ * };
435
+ * });
436
+ * // Read, transform, write, and offset commit are ALL atomic!
437
+ * ```
438
+ */
439
+
440
+ export default {
441
+ ExactlyOnceProducer,
442
+ ExactlyOnceConsumer,
443
+ ExactlyOnceProcessor,
444
+ IdempotentProducer,
445
+ };