specweave 0.18.1 → 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 (384) 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/plugins/specweave-kafka/lib/cli/kcat-wrapper.d.ts +57 -0
  54. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.d.ts.map +1 -0
  55. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +248 -0
  56. package/dist/plugins/specweave-kafka/lib/cli/kcat-wrapper.js.map +1 -0
  57. package/dist/plugins/specweave-kafka/lib/cli/types.d.ts +82 -0
  58. package/dist/plugins/specweave-kafka/lib/cli/types.d.ts.map +1 -0
  59. package/dist/plugins/specweave-kafka/lib/cli/types.js +13 -0
  60. package/dist/plugins/specweave-kafka/lib/cli/types.js.map +1 -0
  61. package/dist/plugins/specweave-kafka/lib/mcp/detector.d.ts +49 -0
  62. package/dist/plugins/specweave-kafka/lib/mcp/detector.d.ts.map +1 -0
  63. package/dist/plugins/specweave-kafka/lib/mcp/detector.js +316 -0
  64. package/dist/plugins/specweave-kafka/lib/mcp/detector.js.map +1 -0
  65. package/dist/plugins/specweave-kafka/lib/mcp/types.d.ts +70 -0
  66. package/dist/plugins/specweave-kafka/lib/mcp/types.d.ts.map +1 -0
  67. package/dist/plugins/specweave-kafka/lib/mcp/types.js +23 -0
  68. package/dist/plugins/specweave-kafka/lib/mcp/types.js.map +1 -0
  69. package/dist/plugins/specweave-kafka/lib/utils/partitioning.d.ts +85 -0
  70. package/dist/plugins/specweave-kafka/lib/utils/partitioning.d.ts.map +1 -0
  71. package/dist/plugins/specweave-kafka/lib/utils/partitioning.js +281 -0
  72. package/dist/plugins/specweave-kafka/lib/utils/partitioning.js.map +1 -0
  73. package/dist/plugins/specweave-kafka/lib/utils/sizing.d.ts +75 -0
  74. package/dist/plugins/specweave-kafka/lib/utils/sizing.d.ts.map +1 -0
  75. package/dist/plugins/specweave-kafka/lib/utils/sizing.js +238 -0
  76. package/dist/plugins/specweave-kafka/lib/utils/sizing.js.map +1 -0
  77. package/dist/src/cli/commands/import-docs.js +4 -4
  78. package/dist/src/cli/commands/import-docs.js.map +1 -1
  79. package/dist/src/cli/commands/init-multiproject.d.ts.map +1 -1
  80. package/dist/src/cli/commands/init-multiproject.js +17 -18
  81. package/dist/src/cli/commands/init-multiproject.js.map +1 -1
  82. package/dist/src/cli/commands/migrate-to-multiproject.d.ts.map +1 -1
  83. package/dist/src/cli/commands/migrate-to-multiproject.js +8 -4
  84. package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
  85. package/dist/src/cli/commands/switch-project.d.ts.map +1 -1
  86. package/dist/src/cli/commands/switch-project.js +9 -26
  87. package/dist/src/cli/commands/switch-project.js.map +1 -1
  88. package/dist/src/cli/commands/sync-spec-content.js +3 -0
  89. package/dist/src/cli/commands/sync-spec-content.js.map +1 -1
  90. package/dist/src/core/deduplication/command-deduplicator.d.ts +166 -0
  91. package/dist/src/core/deduplication/command-deduplicator.d.ts.map +1 -0
  92. package/dist/src/core/deduplication/command-deduplicator.js +254 -0
  93. package/dist/src/core/deduplication/command-deduplicator.js.map +1 -0
  94. package/dist/src/core/increment/active-increment-manager.d.ts +42 -15
  95. package/dist/src/core/increment/active-increment-manager.d.ts.map +1 -1
  96. package/dist/src/core/increment/active-increment-manager.js +113 -46
  97. package/dist/src/core/increment/active-increment-manager.js.map +1 -1
  98. package/dist/src/core/increment/conflict-resolver.d.ts +40 -0
  99. package/dist/src/core/increment/conflict-resolver.d.ts.map +1 -0
  100. package/dist/src/core/increment/conflict-resolver.js +219 -0
  101. package/dist/src/core/increment/conflict-resolver.js.map +1 -0
  102. package/dist/src/core/increment/discipline-checker.d.ts.map +1 -1
  103. package/dist/src/core/increment/discipline-checker.js +7 -1
  104. package/dist/src/core/increment/discipline-checker.js.map +1 -1
  105. package/dist/src/core/increment/duplicate-detector.d.ts +52 -0
  106. package/dist/src/core/increment/duplicate-detector.d.ts.map +1 -0
  107. package/dist/src/core/increment/duplicate-detector.js +276 -0
  108. package/dist/src/core/increment/duplicate-detector.js.map +1 -0
  109. package/dist/src/core/increment/increment-archiver.d.ts +90 -0
  110. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -0
  111. package/dist/src/core/increment/increment-archiver.js +368 -0
  112. package/dist/src/core/increment/increment-archiver.js.map +1 -0
  113. package/dist/src/core/increment/increment-reopener.d.ts +165 -0
  114. package/dist/src/core/increment/increment-reopener.d.ts.map +1 -0
  115. package/dist/src/core/increment/increment-reopener.js +390 -0
  116. package/dist/src/core/increment/increment-reopener.js.map +1 -0
  117. package/dist/src/core/increment/metadata-manager.d.ts +26 -1
  118. package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
  119. package/dist/src/core/increment/metadata-manager.js +143 -5
  120. package/dist/src/core/increment/metadata-manager.js.map +1 -1
  121. package/dist/src/core/increment/recent-work-scanner.d.ts +121 -0
  122. package/dist/src/core/increment/recent-work-scanner.d.ts.map +1 -0
  123. package/dist/src/core/increment/recent-work-scanner.js +303 -0
  124. package/dist/src/core/increment/recent-work-scanner.js.map +1 -0
  125. package/dist/src/core/increment/types.d.ts +1 -0
  126. package/dist/src/core/increment/types.d.ts.map +1 -1
  127. package/dist/src/core/increment-utils.d.ts +112 -0
  128. package/dist/src/core/increment-utils.d.ts.map +1 -0
  129. package/dist/src/core/increment-utils.js +210 -0
  130. package/dist/src/core/increment-utils.js.map +1 -0
  131. package/dist/src/core/living-docs/ac-project-specific-generator.d.ts +65 -0
  132. package/dist/src/core/living-docs/ac-project-specific-generator.d.ts.map +1 -0
  133. package/dist/src/core/living-docs/ac-project-specific-generator.js +175 -0
  134. package/dist/src/core/living-docs/ac-project-specific-generator.js.map +1 -0
  135. package/dist/src/core/living-docs/feature-archiver.d.ts +130 -0
  136. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -0
  137. package/dist/src/core/living-docs/feature-archiver.js +549 -0
  138. package/dist/src/core/living-docs/feature-archiver.js.map +1 -0
  139. package/dist/src/core/living-docs/feature-id-manager.d.ts +81 -0
  140. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -0
  141. package/dist/src/core/living-docs/feature-id-manager.js +339 -0
  142. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -0
  143. package/dist/src/core/living-docs/hierarchy-mapper.d.ts +144 -83
  144. package/dist/src/core/living-docs/hierarchy-mapper.d.ts.map +1 -1
  145. package/dist/src/core/living-docs/hierarchy-mapper.js +488 -270
  146. package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
  147. package/dist/src/core/living-docs/index.d.ts +6 -0
  148. package/dist/src/core/living-docs/index.d.ts.map +1 -1
  149. package/dist/src/core/living-docs/index.js +6 -0
  150. package/dist/src/core/living-docs/index.js.map +1 -1
  151. package/dist/src/core/living-docs/project-detector.d.ts +6 -0
  152. package/dist/src/core/living-docs/project-detector.d.ts.map +1 -1
  153. package/dist/src/core/living-docs/project-detector.js +35 -1
  154. package/dist/src/core/living-docs/project-detector.js.map +1 -1
  155. package/dist/src/core/living-docs/spec-distributor.d.ts +100 -26
  156. package/dist/src/core/living-docs/spec-distributor.d.ts.map +1 -1
  157. package/dist/src/core/living-docs/spec-distributor.js +1275 -258
  158. package/dist/src/core/living-docs/spec-distributor.js.map +1 -1
  159. package/dist/src/core/living-docs/task-project-specific-generator.d.ts +109 -0
  160. package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -0
  161. package/dist/src/core/living-docs/task-project-specific-generator.js +221 -0
  162. package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -0
  163. package/dist/src/core/living-docs/types.d.ts +143 -0
  164. package/dist/src/core/living-docs/types.d.ts.map +1 -1
  165. package/dist/src/core/project-manager.d.ts +2 -17
  166. package/dist/src/core/project-manager.d.ts.map +1 -1
  167. package/dist/src/core/project-manager.js +68 -48
  168. package/dist/src/core/project-manager.js.map +1 -1
  169. package/dist/src/core/spec-content-sync.d.ts +1 -1
  170. package/dist/src/core/spec-content-sync.d.ts.map +1 -1
  171. package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -1
  172. package/dist/src/core/sync/enhanced-content-builder.js +2 -1
  173. package/dist/src/core/sync/enhanced-content-builder.js.map +1 -1
  174. package/dist/src/core/sync/performance-optimizer.d.ts +153 -0
  175. package/dist/src/core/sync/performance-optimizer.d.ts.map +1 -0
  176. package/dist/src/core/sync/performance-optimizer.js +220 -0
  177. package/dist/src/core/sync/performance-optimizer.js.map +1 -0
  178. package/dist/src/core/sync/retry-handler.d.ts +98 -0
  179. package/dist/src/core/sync/retry-handler.d.ts.map +1 -0
  180. package/dist/src/core/sync/retry-handler.js +196 -0
  181. package/dist/src/core/sync/retry-handler.js.map +1 -0
  182. package/dist/src/core/types/config.d.ts +94 -0
  183. package/dist/src/core/types/config.d.ts.map +1 -1
  184. package/dist/src/core/types/config.js +16 -0
  185. package/dist/src/core/types/config.js.map +1 -1
  186. package/dist/src/core/types/increment-metadata.d.ts +6 -0
  187. package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
  188. package/dist/src/core/types/increment-metadata.js +10 -1
  189. package/dist/src/core/types/increment-metadata.js.map +1 -1
  190. package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
  191. package/dist/src/integrations/jira/jira-incremental-mapper.js +4 -8
  192. package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
  193. package/dist/src/integrations/jira/jira-mapper.d.ts.map +1 -1
  194. package/dist/src/integrations/jira/jira-mapper.js +4 -8
  195. package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
  196. package/package.json +1 -1
  197. package/plugins/specweave/COMMANDS.md +13 -4
  198. package/plugins/specweave/commands/specweave-abandon.md +22 -20
  199. package/plugins/specweave/commands/specweave-archive-features.md +121 -0
  200. package/plugins/specweave/commands/specweave-archive-increments.md +82 -0
  201. package/plugins/specweave/commands/specweave-archive.md +363 -0
  202. package/plugins/specweave/commands/specweave-backlog.md +211 -0
  203. package/plugins/specweave/commands/specweave-fix-duplicates.md +517 -0
  204. package/plugins/specweave/commands/specweave-increment.md +4 -3
  205. package/plugins/specweave/commands/specweave-progress.md +176 -27
  206. package/plugins/specweave/commands/specweave-reopen.md +391 -0
  207. package/plugins/specweave/commands/specweave-restore-feature.md +90 -0
  208. package/plugins/specweave/commands/specweave-restore.md +309 -0
  209. package/plugins/specweave/commands/specweave-resume.md +51 -23
  210. package/plugins/specweave/commands/specweave-status.md +41 -7
  211. package/plugins/specweave/commands/specweave-sync-specs.md +425 -0
  212. package/plugins/specweave/hooks/hooks.json +4 -0
  213. package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
  214. package/plugins/specweave/hooks/post-task-completion.sh +39 -0
  215. package/plugins/specweave/hooks/pre-command-deduplication.sh +83 -0
  216. package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
  217. package/plugins/specweave/lib/hooks/sync-living-docs.js +2 -0
  218. package/plugins/specweave/lib/hooks/sync-living-docs.ts +4 -0
  219. package/plugins/specweave/lib/hooks/update-ac-status.js +102 -0
  220. package/plugins/specweave/lib/hooks/update-ac-status.ts +192 -0
  221. package/plugins/specweave/skills/archive-increments/SKILL.md +198 -0
  222. package/plugins/specweave/skills/increment-planner/scripts/feature-utils.js +14 -0
  223. package/plugins/specweave/skills/smart-reopen-detector/SKILL.md +244 -0
  224. package/plugins/specweave-ado/lib/ado-spec-content-sync.js +49 -5
  225. package/plugins/specweave-ado/lib/ado-spec-content-sync.ts +72 -6
  226. package/plugins/specweave-confluent/.claude-plugin/plugin.json +23 -0
  227. package/plugins/specweave-confluent/README.md +375 -0
  228. package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +306 -0
  229. package/plugins/specweave-confluent/skills/confluent-kafka-connect/SKILL.md +453 -0
  230. package/plugins/specweave-confluent/skills/confluent-ksqldb/SKILL.md +470 -0
  231. package/plugins/specweave-confluent/skills/confluent-schema-registry/SKILL.md +316 -0
  232. package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +2 -2
  233. package/plugins/specweave-github/agents/user-story-updater/AGENT.md +148 -0
  234. package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +1 -1
  235. package/plugins/specweave-github/commands/specweave-github-update-user-story.md +156 -0
  236. package/plugins/specweave-github/hooks/post-task-completion.sh +10 -9
  237. package/plugins/specweave-github/lib/completion-calculator.js +262 -0
  238. package/plugins/specweave-github/lib/completion-calculator.ts +434 -0
  239. package/plugins/specweave-github/lib/duplicate-detector.js +3 -3
  240. package/plugins/specweave-github/lib/duplicate-detector.ts +4 -4
  241. package/plugins/specweave-github/lib/epic-content-builder.js +38 -0
  242. package/plugins/specweave-github/lib/epic-content-builder.ts +59 -0
  243. package/plugins/specweave-github/lib/github-client-v2.js +49 -0
  244. package/plugins/specweave-github/lib/github-client-v2.ts +59 -0
  245. package/plugins/specweave-github/lib/github-epic-sync.ts +1 -1
  246. package/plugins/specweave-github/lib/github-feature-sync.js +381 -0
  247. package/plugins/specweave-github/lib/github-feature-sync.ts +568 -0
  248. package/plugins/specweave-github/lib/github-spec-content-sync.js +40 -10
  249. package/plugins/specweave-github/lib/github-spec-content-sync.ts +82 -14
  250. package/plugins/specweave-github/lib/progress-comment-builder.js +229 -0
  251. package/plugins/specweave-github/lib/progress-comment-builder.ts +324 -0
  252. package/plugins/specweave-github/lib/user-story-content-builder.js +299 -0
  253. package/plugins/specweave-github/lib/user-story-content-builder.ts +413 -0
  254. package/plugins/specweave-github/lib/user-story-issue-builder.js +344 -0
  255. package/plugins/specweave-github/lib/user-story-issue-builder.ts +543 -0
  256. package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +189 -0
  257. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
  258. package/plugins/specweave-jira/lib/{enhanced-jira-sync.ts.disabled → enhanced-jira-sync.ts} +26 -52
  259. package/plugins/specweave-kafka/.claude-plugin/plugin.json +26 -0
  260. package/plugins/specweave-kafka/IMPLEMENTATION-COMPLETE.md +483 -0
  261. package/plugins/specweave-kafka/README.md +242 -0
  262. package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +235 -0
  263. package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +209 -0
  264. package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +266 -0
  265. package/plugins/specweave-kafka/commands/deploy.md +99 -0
  266. package/plugins/specweave-kafka/commands/dev-env.md +176 -0
  267. package/plugins/specweave-kafka/commands/mcp-configure.md +101 -0
  268. package/plugins/specweave-kafka/commands/monitor-setup.md +96 -0
  269. package/plugins/specweave-kafka/docker/kafka-local/docker-compose.yml +187 -0
  270. package/plugins/specweave-kafka/docker/redpanda/docker-compose.yml +199 -0
  271. package/plugins/specweave-kafka/docker/templates/consumer-nodejs.js +225 -0
  272. package/plugins/specweave-kafka/docker/templates/consumer-python.py +220 -0
  273. package/plugins/specweave-kafka/docker/templates/producer-nodejs.js +168 -0
  274. package/plugins/specweave-kafka/docker/templates/producer-python.py +167 -0
  275. package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.js +438 -0
  276. package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.ts +541 -0
  277. package/plugins/specweave-kafka/lib/adapters/platform-adapter.js +47 -0
  278. package/plugins/specweave-kafka/lib/adapters/platform-adapter.ts +343 -0
  279. package/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +258 -0
  280. package/plugins/specweave-kafka/lib/cli/kcat-wrapper.ts +298 -0
  281. package/plugins/specweave-kafka/lib/cli/types.js +10 -0
  282. package/plugins/specweave-kafka/lib/cli/types.ts +92 -0
  283. package/plugins/specweave-kafka/lib/connectors/connector-catalog.js +305 -0
  284. package/plugins/specweave-kafka/lib/connectors/connector-catalog.ts +528 -0
  285. package/plugins/specweave-kafka/lib/documentation/diagram-generator.js +114 -0
  286. package/plugins/specweave-kafka/lib/documentation/diagram-generator.ts +195 -0
  287. package/plugins/specweave-kafka/lib/documentation/exporter.js +210 -0
  288. package/plugins/specweave-kafka/lib/documentation/exporter.ts +338 -0
  289. package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.js +60 -0
  290. package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.ts +130 -0
  291. package/plugins/specweave-kafka/lib/documentation/topology-generator.js +143 -0
  292. package/plugins/specweave-kafka/lib/documentation/topology-generator.ts +290 -0
  293. package/plugins/specweave-kafka/lib/mcp/detector.js +298 -0
  294. package/plugins/specweave-kafka/lib/mcp/detector.ts +352 -0
  295. package/plugins/specweave-kafka/lib/mcp/types.js +21 -0
  296. package/plugins/specweave-kafka/lib/mcp/types.ts +77 -0
  297. package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.js +193 -0
  298. package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.ts +362 -0
  299. package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.js +188 -0
  300. package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.ts +359 -0
  301. package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.js +195 -0
  302. package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.ts +380 -0
  303. package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.js +209 -0
  304. package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.ts +358 -0
  305. package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.js +354 -0
  306. package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.ts +563 -0
  307. package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.js +259 -0
  308. package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.ts +516 -0
  309. package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.js +233 -0
  310. package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.ts +423 -0
  311. package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.js +266 -0
  312. package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.ts +445 -0
  313. package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.js +312 -0
  314. package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.ts +561 -0
  315. package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.js +289 -0
  316. package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.ts +607 -0
  317. package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.js +264 -0
  318. package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.ts +498 -0
  319. package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.js +263 -0
  320. package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.ts +549 -0
  321. package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.js +205 -0
  322. package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.ts +399 -0
  323. package/plugins/specweave-kafka/lib/performance/performance-optimizer.js +249 -0
  324. package/plugins/specweave-kafka/lib/performance/performance-optimizer.ts +427 -0
  325. package/plugins/specweave-kafka/lib/security/kafka-security.js +252 -0
  326. package/plugins/specweave-kafka/lib/security/kafka-security.ts +494 -0
  327. package/plugins/specweave-kafka/lib/utils/capacity-planner.js +203 -0
  328. package/plugins/specweave-kafka/lib/utils/capacity-planner.ts +469 -0
  329. package/plugins/specweave-kafka/lib/utils/config-validator.js +419 -0
  330. package/plugins/specweave-kafka/lib/utils/config-validator.ts +564 -0
  331. package/plugins/specweave-kafka/lib/utils/partitioning.js +329 -0
  332. package/plugins/specweave-kafka/lib/utils/partitioning.ts +473 -0
  333. package/plugins/specweave-kafka/lib/utils/sizing.js +221 -0
  334. package/plugins/specweave-kafka/lib/utils/sizing.ts +374 -0
  335. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-broker-metrics.json +628 -0
  336. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-cluster-overview.json +564 -0
  337. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-consumer-lag.json +509 -0
  338. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-jvm-metrics.json +674 -0
  339. package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-topic-metrics.json +578 -0
  340. package/plugins/specweave-kafka/monitoring/grafana/provisioning/dashboards/kafka.yml +17 -0
  341. package/plugins/specweave-kafka/monitoring/grafana/provisioning/datasources/prometheus.yml +17 -0
  342. package/plugins/specweave-kafka/monitoring/prometheus/kafka-alerts.yml +415 -0
  343. package/plugins/specweave-kafka/monitoring/prometheus/kafka-jmx-exporter.yml +256 -0
  344. package/plugins/specweave-kafka/package.json +41 -0
  345. package/plugins/specweave-kafka/skills/kafka-architecture/SKILL.md +647 -0
  346. package/plugins/specweave-kafka/skills/kafka-cli-tools/SKILL.md +433 -0
  347. package/plugins/specweave-kafka/skills/kafka-iac-deployment/SKILL.md +449 -0
  348. package/plugins/specweave-kafka/skills/kafka-kubernetes/SKILL.md +667 -0
  349. package/plugins/specweave-kafka/skills/kafka-mcp-integration/SKILL.md +273 -0
  350. package/plugins/specweave-kafka/skills/kafka-observability/SKILL.md +576 -0
  351. package/plugins/specweave-kafka/templates/config/broker-production.properties +254 -0
  352. package/plugins/specweave-kafka/templates/config/consumer-low-latency.properties +112 -0
  353. package/plugins/specweave-kafka/templates/config/producer-high-throughput.properties +120 -0
  354. package/plugins/specweave-kafka/templates/migration/mirrormaker2-config.properties +234 -0
  355. package/plugins/specweave-kafka/templates/monitoring/grafana/multi-cluster-dashboard.json +686 -0
  356. package/plugins/specweave-kafka/terraform/apache-kafka/main.tf +347 -0
  357. package/plugins/specweave-kafka/terraform/apache-kafka/outputs.tf +107 -0
  358. package/plugins/specweave-kafka/terraform/apache-kafka/templates/kafka-broker-init.sh.tpl +216 -0
  359. package/plugins/specweave-kafka/terraform/apache-kafka/variables.tf +156 -0
  360. package/plugins/specweave-kafka/terraform/aws-msk/main.tf +362 -0
  361. package/plugins/specweave-kafka/terraform/aws-msk/outputs.tf +93 -0
  362. package/plugins/specweave-kafka/terraform/aws-msk/templates/server.properties.tpl +32 -0
  363. package/plugins/specweave-kafka/terraform/aws-msk/variables.tf +235 -0
  364. package/plugins/specweave-kafka/terraform/azure-event-hubs/main.tf +281 -0
  365. package/plugins/specweave-kafka/terraform/azure-event-hubs/outputs.tf +118 -0
  366. package/plugins/specweave-kafka/terraform/azure-event-hubs/variables.tf +148 -0
  367. package/plugins/specweave-kafka/tsconfig.json +21 -0
  368. package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +23 -0
  369. package/plugins/specweave-kafka-streams/README.md +310 -0
  370. package/plugins/specweave-kafka-streams/skills/kafka-streams-topology/SKILL.md +539 -0
  371. package/plugins/specweave-n8n/.claude-plugin/plugin.json +22 -0
  372. package/plugins/specweave-n8n/README.md +354 -0
  373. package/plugins/specweave-n8n/skills/n8n-kafka-workflows/SKILL.md +504 -0
  374. package/plugins/specweave-release/commands/specweave-release-platform.md +1 -1
  375. package/plugins/specweave-release/hooks/post-task-completion.sh +2 -2
  376. package/src/templates/AGENTS.md.template +601 -7
  377. package/src/templates/CLAUDE.md.template +188 -88
  378. package/plugins/specweave-ado/commands/specweave-ado-sync-spec.md +0 -255
  379. package/plugins/specweave-github/commands/specweave-github-sync-epic.md +0 -248
  380. package/plugins/specweave-github/commands/specweave-github-sync-from.md +0 -147
  381. package/plugins/specweave-github/commands/specweave-github-sync-spec.md +0 -208
  382. package/plugins/specweave-github/commands/specweave-github-sync-tasks.md +0 -530
  383. package/plugins/specweave-jira/commands/specweave-jira-sync-epic.md +0 -267
  384. package/plugins/specweave-jira/commands/specweave-jira-sync-spec.md +0 -240
@@ -0,0 +1,262 @@
1
+ import { readFile } from "fs/promises";
2
+ import { existsSync } from "fs";
3
+ import * as path from "path";
4
+ import * as yaml from "yaml";
5
+ class CompletionCalculator {
6
+ constructor(projectRoot) {
7
+ this.projectRoot = projectRoot;
8
+ }
9
+ /**
10
+ * Calculate ACTUAL completion from markdown checkboxes
11
+ *
12
+ * Returns true only if:
13
+ * - All ACs have [x] (not [ ])
14
+ * - All Tasks have **Status**: [x] (not [ ])
15
+ * - At least 1 AC exists (no empty user stories)
16
+ *
17
+ * @param userStoryPath - Path to us-*.md file
18
+ * @returns Completion status with detailed metrics
19
+ */
20
+ async calculateCompletion(userStoryPath) {
21
+ const content = await readFile(userStoryPath, "utf-8");
22
+ const frontmatter = this.parseUserStoryFrontmatter(content);
23
+ const acs = this.extractAcceptanceCriteria(content);
24
+ const tasks = await this.extractTasks(content, frontmatter.id);
25
+ const acsCompleted = acs.filter((ac) => ac.completed).length;
26
+ const tasksCompleted = tasks.filter((t) => t.completed).length;
27
+ const overallComplete = acs.length > 0 && acsCompleted === acs.length && (tasks.length === 0 || tasksCompleted === tasks.length);
28
+ return {
29
+ acsTotal: acs.length,
30
+ acsCompleted,
31
+ acsPercentage: acs.length > 0 ? acsCompleted / acs.length * 100 : 0,
32
+ tasksTotal: tasks.length,
33
+ tasksCompleted,
34
+ tasksPercentage: tasks.length > 0 ? tasksCompleted / tasks.length * 100 : 0,
35
+ overallComplete,
36
+ blockingAcs: acs.filter((ac) => !ac.completed).map((ac) => ac.id),
37
+ blockingTasks: tasks.filter((t) => !t.completed).map((t) => t.id)
38
+ };
39
+ }
40
+ /**
41
+ * Parse User Story frontmatter
42
+ */
43
+ parseUserStoryFrontmatter(content) {
44
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
45
+ if (!match) {
46
+ throw new Error("Missing YAML frontmatter in user story");
47
+ }
48
+ return yaml.parse(match[1]);
49
+ }
50
+ /**
51
+ * Extract Acceptance Criteria with checkbox state
52
+ *
53
+ * Supports TWO formats:
54
+ * - Format 1 (preferred): AC-US1-01, AC-US1-02 (project-specific)
55
+ * - Format 2 (legacy): AC-001, AC-002, AC-020 (global)
56
+ *
57
+ * Patterns:
58
+ * - [x] **AC-US1-01**: Description (completed)
59
+ * - [ ] **AC-US1-01**: Description (not completed)
60
+ * - **AC-US1-01**: Description (no checkbox, default to not completed)
61
+ */
62
+ extractAcceptanceCriteria(content) {
63
+ const criteria = [];
64
+ const acMatch = content.match(/##\s*Acceptance Criteria\s*\n+([\s\S]*?)(?=\n##|$)/i);
65
+ if (!acMatch) {
66
+ return criteria;
67
+ }
68
+ const acSection = acMatch[1];
69
+ const acPatternWithCheckbox = /(?:^|\n)\s*[-*]\s+\[([x ])\]\s+\*\*([A-Z]+-(?:[A-Z]+\d+-)?(\d+))\*\*:\s*([^\n]+)/g;
70
+ const acPatternNoCheckbox = /(?:^|\n)\s*[-*]?\s*\*\*([A-Z]+-(?:[A-Z]+\d+-)?(\d+))\*\*:\s*([^\n]+)/g;
71
+ let match;
72
+ let foundAny = false;
73
+ while ((match = acPatternWithCheckbox.exec(acSection)) !== null) {
74
+ foundAny = true;
75
+ criteria.push({
76
+ id: match[2],
77
+ // e.g., "AC-US1-01" or "AC-020"
78
+ description: match[4].trim(),
79
+ completed: match[1] === "x"
80
+ // ✅ Read checkbox state from source!
81
+ });
82
+ }
83
+ if (!foundAny) {
84
+ while ((match = acPatternNoCheckbox.exec(acSection)) !== null) {
85
+ criteria.push({
86
+ id: match[1],
87
+ // e.g., "AC-US1-01" or "AC-020"
88
+ description: match[3].trim(),
89
+ completed: false
90
+ // Default to not completed
91
+ });
92
+ }
93
+ }
94
+ return criteria;
95
+ }
96
+ /**
97
+ * Extract tasks from increment's tasks.md that map to this User Story
98
+ *
99
+ * Process:
100
+ * 1. Find increment link in user story's "Implementation" section
101
+ * 2. Read increment's tasks.md
102
+ * 3. Filter tasks that reference this user story's ACs
103
+ * 4. Extract completion status from **Status**: [x] or [ ]
104
+ */
105
+ async extractTasks(userStoryContent, userStoryId) {
106
+ const tasks = [];
107
+ const implMatch = userStoryContent.match(/##\s*Implementation\s*\n+([\s\S]*?)(?=\n##|$)/i);
108
+ if (!implMatch) {
109
+ return tasks;
110
+ }
111
+ const implSection = implMatch[1];
112
+ const incrementMatch = implSection.match(/\*\*Increment\*\*:\s*\[([^\]]+)\]/);
113
+ if (!incrementMatch) {
114
+ return tasks;
115
+ }
116
+ const incrementId = incrementMatch[1];
117
+ const tasksPath = path.join(
118
+ this.projectRoot,
119
+ ".specweave",
120
+ "increments",
121
+ incrementId,
122
+ "tasks.md"
123
+ );
124
+ if (!existsSync(tasksPath)) {
125
+ return tasks;
126
+ }
127
+ const tasksContent = await readFile(tasksPath, "utf-8");
128
+ const taskPattern = /###?\s+(T-\d+):\s*([^\n]+)\n([\s\S]*?)(?=\n###?\s+T-\d+:|$)/g;
129
+ let match;
130
+ while ((match = taskPattern.exec(tasksContent)) !== null) {
131
+ const taskId = match[1];
132
+ const taskTitle = match[2].trim();
133
+ const taskBody = match[3];
134
+ const acMatch = taskBody.match(/\*\*AC\*\*:\s*([^\n]+)/);
135
+ if (!acMatch) {
136
+ continue;
137
+ }
138
+ const acList = acMatch[1].trim();
139
+ const acIds = acList.split(",").map((ac) => ac.trim());
140
+ const belongsToThisUS = acIds.some((acId) => {
141
+ const usMatch = acId.match(/AC-([A-Z]+\d+)-/);
142
+ if (!usMatch) return false;
143
+ const extractedUsId = usMatch[1];
144
+ const extractedNum = extractedUsId.replace(/^US/, "");
145
+ const normalizedExtracted = `US-${extractedNum.padStart(3, "0")}`;
146
+ const currentNum = userStoryId.replace(/^US-?/, "");
147
+ const normalizedCurrent = `US-${currentNum.padStart(3, "0")}`;
148
+ return normalizedExtracted === normalizedCurrent;
149
+ });
150
+ if (!belongsToThisUS) {
151
+ continue;
152
+ }
153
+ const statusMatch = taskBody.match(/\*\*Status\*\*:\s*\[([x ])\]/);
154
+ const completed = statusMatch ? statusMatch[1] === "x" : false;
155
+ tasks.push({
156
+ id: taskId,
157
+ title: taskTitle,
158
+ completed,
159
+ // ✅ Now reads actual completion status!
160
+ userStories: acIds
161
+ });
162
+ }
163
+ return tasks;
164
+ }
165
+ /**
166
+ * Build completion comment for GitHub issue closure
167
+ *
168
+ * Used when closing issue after verification
169
+ */
170
+ buildCompletionComment(completion) {
171
+ return `\u2705 **User Story Verified Complete**
172
+
173
+ **Completion Status**:
174
+ - \u2705 Acceptance Criteria: ${completion.acsCompleted}/${completion.acsTotal} (100%)
175
+ - \u2705 Implementation Tasks: ${completion.tasksCompleted}/${completion.tasksTotal} (100%)
176
+
177
+ All work has been verified and completed. This issue is now closed.
178
+
179
+ \u{1F916} Auto-verified by SpecWeave AC Completion Gate`;
180
+ }
181
+ /**
182
+ * Build progress comment for GitHub issue update
183
+ *
184
+ * Used when issue stays open (not 100% complete)
185
+ */
186
+ buildProgressComment(completion) {
187
+ const sections = [];
188
+ sections.push("\u{1F4CA} **Progress Update**");
189
+ sections.push("");
190
+ const acIcon = completion.acsPercentage === 100 ? "\u2705" : "\u{1F504}";
191
+ sections.push(
192
+ `${acIcon} **Acceptance Criteria**: ${completion.acsCompleted}/${completion.acsTotal} (${completion.acsPercentage.toFixed(0)}%)`
193
+ );
194
+ if (completion.blockingAcs.length > 0) {
195
+ sections.push("");
196
+ sections.push("**Incomplete ACs**:");
197
+ for (const acId of completion.blockingAcs) {
198
+ sections.push(`- [ ] ${acId}`);
199
+ }
200
+ }
201
+ sections.push("");
202
+ const taskIcon = completion.tasksPercentage === 100 ? "\u2705" : "\u{1F504}";
203
+ sections.push(
204
+ `${taskIcon} **Implementation Tasks**: ${completion.tasksCompleted}/${completion.tasksTotal} (${completion.tasksPercentage.toFixed(0)}%)`
205
+ );
206
+ if (completion.blockingTasks.length > 0) {
207
+ sections.push("");
208
+ sections.push("**Incomplete Tasks**:");
209
+ for (const taskId of completion.blockingTasks) {
210
+ sections.push(`- [ ] ${taskId}`);
211
+ }
212
+ }
213
+ sections.push("");
214
+ sections.push("---");
215
+ sections.push("\u{1F916} Auto-updated by SpecWeave AC Completion Gate");
216
+ return sections.join("\n");
217
+ }
218
+ /**
219
+ * Build reopen comment for GitHub issue
220
+ *
221
+ * Used when reopening prematurely closed issue
222
+ */
223
+ buildReopenComment(completion, reason = "Work verification failed") {
224
+ const sections = [];
225
+ sections.push(`\u{1F504} **Reopening Issue - ${reason}**`);
226
+ sections.push("");
227
+ sections.push("**Current Status**:");
228
+ sections.push(
229
+ `- Acceptance Criteria: ${completion.acsCompleted}/${completion.acsTotal} (${completion.acsPercentage.toFixed(0)}%)`
230
+ );
231
+ sections.push(
232
+ `- Implementation Tasks: ${completion.tasksCompleted}/${completion.tasksTotal} (${completion.tasksPercentage.toFixed(0)}%)`
233
+ );
234
+ const totalBlocking = completion.blockingAcs.length + completion.blockingTasks.length;
235
+ if (totalBlocking > 0) {
236
+ sections.push("");
237
+ sections.push(`**Blocking Items** (${totalBlocking}):`);
238
+ if (completion.blockingAcs.length > 0) {
239
+ sections.push("");
240
+ sections.push("**Acceptance Criteria**:");
241
+ for (const acId of completion.blockingAcs) {
242
+ sections.push(`- [ ] ${acId}`);
243
+ }
244
+ }
245
+ if (completion.blockingTasks.length > 0) {
246
+ sections.push("");
247
+ sections.push("**Implementation Tasks**:");
248
+ for (const taskId of completion.blockingTasks) {
249
+ sections.push(`- [ ] ${taskId}`);
250
+ }
251
+ }
252
+ }
253
+ sections.push("");
254
+ sections.push("\u26A0\uFE0F This issue cannot be closed until all ACs and tasks are verified complete.");
255
+ sections.push("");
256
+ sections.push("\u{1F916} Auto-reopened by SpecWeave AC Completion Gate");
257
+ return sections.join("\n");
258
+ }
259
+ }
260
+ export {
261
+ CompletionCalculator
262
+ };
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Completion Calculator - Verifies actual work completion from markdown checkboxes
3
+ *
4
+ * CRITICAL FIX: Prevents premature GitHub issue closure by verifying actual
5
+ * AC and Task completion state, not just frontmatter status.
6
+ *
7
+ * Problem:
8
+ * - OLD: Issues closed based on frontmatter `status: complete`
9
+ * - Issue #574: Closed with 0/5 ACs complete!
10
+ *
11
+ * Solution:
12
+ * - NEW: Parse actual checkbox states ([x] vs [ ])
13
+ * - Close ONLY when ALL ACs and ALL tasks are verified [x]
14
+ *
15
+ * Architecture:
16
+ * - Acceptance Criteria: Read from us-*.md files
17
+ * - Tasks: Read from increment's tasks.md
18
+ * - Verification Gate: 100% completion required
19
+ */
20
+
21
+ import { readFile } from 'fs/promises';
22
+ import { existsSync } from 'fs';
23
+ import * as path from 'path';
24
+ import * as yaml from 'yaml';
25
+
26
+ /**
27
+ * Acceptance Criteria with completion status
28
+ */
29
+ export interface AcceptanceCriteria {
30
+ id: string; // e.g., "AC-US1-01" or "AC-020"
31
+ description: string;
32
+ completed: boolean; // ✅ Read from [x] or [ ] checkbox
33
+ }
34
+
35
+ /**
36
+ * Implementation Task with completion status
37
+ */
38
+ export interface Task {
39
+ id: string; // e.g., "T-001"
40
+ title: string;
41
+ completed: boolean; // ✅ Read from **Status**: [x] or [ ]
42
+ userStories: string[]; // ACs this task implements (e.g., ["AC-US1-01", "AC-US1-02"])
43
+ }
44
+
45
+ /**
46
+ * Complete verification status
47
+ */
48
+ export interface CompletionStatus {
49
+ // Acceptance Criteria metrics
50
+ acsTotal: number;
51
+ acsCompleted: number;
52
+ acsPercentage: number;
53
+
54
+ // Task metrics
55
+ tasksTotal: number;
56
+ tasksCompleted: number;
57
+ tasksPercentage: number;
58
+
59
+ // Overall completion gate
60
+ overallComplete: boolean; // true ONLY if ALL ACs AND tasks are [x]
61
+
62
+ // Blocking items (for reopen)
63
+ blockingAcs: string[]; // List of incomplete AC-IDs
64
+ blockingTasks: string[]; // List of incomplete Task-IDs
65
+ }
66
+
67
+ /**
68
+ * User Story Frontmatter
69
+ */
70
+ interface UserStoryFrontmatter {
71
+ id: string;
72
+ feature: string;
73
+ title: string;
74
+ status: 'complete' | 'active' | 'planning' | 'not-started';
75
+ project?: string;
76
+ }
77
+
78
+ export class CompletionCalculator {
79
+ private projectRoot: string;
80
+
81
+ constructor(projectRoot: string) {
82
+ this.projectRoot = projectRoot;
83
+ }
84
+
85
+ /**
86
+ * Calculate ACTUAL completion from markdown checkboxes
87
+ *
88
+ * Returns true only if:
89
+ * - All ACs have [x] (not [ ])
90
+ * - All Tasks have **Status**: [x] (not [ ])
91
+ * - At least 1 AC exists (no empty user stories)
92
+ *
93
+ * @param userStoryPath - Path to us-*.md file
94
+ * @returns Completion status with detailed metrics
95
+ */
96
+ async calculateCompletion(userStoryPath: string): Promise<CompletionStatus> {
97
+ // Step 1: Read and parse user story
98
+ const content = await readFile(userStoryPath, 'utf-8');
99
+ const frontmatter = this.parseUserStoryFrontmatter(content);
100
+
101
+ // Step 2: Extract Acceptance Criteria
102
+ const acs = this.extractAcceptanceCriteria(content);
103
+
104
+ // Step 3: Extract Tasks from increment (if linked)
105
+ const tasks = await this.extractTasks(content, frontmatter.id);
106
+
107
+ // Step 4: Calculate metrics
108
+ const acsCompleted = acs.filter((ac) => ac.completed).length;
109
+ const tasksCompleted = tasks.filter((t) => t.completed).length;
110
+
111
+ // Step 5: Determine overall completion
112
+ // MUST have:
113
+ // - At least 1 AC (no empty user stories)
114
+ // - ALL ACs completed
115
+ // - ALL Tasks completed (or no tasks if not implemented yet)
116
+ const overallComplete =
117
+ acs.length > 0 &&
118
+ acsCompleted === acs.length &&
119
+ (tasks.length === 0 || tasksCompleted === tasks.length);
120
+
121
+ return {
122
+ acsTotal: acs.length,
123
+ acsCompleted,
124
+ acsPercentage: acs.length > 0 ? (acsCompleted / acs.length) * 100 : 0,
125
+ tasksTotal: tasks.length,
126
+ tasksCompleted,
127
+ tasksPercentage: tasks.length > 0 ? (tasksCompleted / tasks.length) * 100 : 0,
128
+ overallComplete,
129
+ blockingAcs: acs.filter((ac) => !ac.completed).map((ac) => ac.id),
130
+ blockingTasks: tasks.filter((t) => !t.completed).map((t) => t.id),
131
+ };
132
+ }
133
+
134
+ /**
135
+ * Parse User Story frontmatter
136
+ */
137
+ private parseUserStoryFrontmatter(content: string): UserStoryFrontmatter {
138
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
139
+
140
+ if (!match) {
141
+ throw new Error('Missing YAML frontmatter in user story');
142
+ }
143
+
144
+ return yaml.parse(match[1]) as UserStoryFrontmatter;
145
+ }
146
+
147
+ /**
148
+ * Extract Acceptance Criteria with checkbox state
149
+ *
150
+ * Supports TWO formats:
151
+ * - Format 1 (preferred): AC-US1-01, AC-US1-02 (project-specific)
152
+ * - Format 2 (legacy): AC-001, AC-002, AC-020 (global)
153
+ *
154
+ * Patterns:
155
+ * - [x] **AC-US1-01**: Description (completed)
156
+ * - [ ] **AC-US1-01**: Description (not completed)
157
+ * - **AC-US1-01**: Description (no checkbox, default to not completed)
158
+ */
159
+ private extractAcceptanceCriteria(content: string): AcceptanceCriteria[] {
160
+ const criteria: AcceptanceCriteria[] = [];
161
+
162
+ // Look for "Acceptance Criteria" section
163
+ const acMatch = content.match(/##\s*Acceptance Criteria\s*\n+([\s\S]*?)(?=\n##|$)/i);
164
+
165
+ if (!acMatch) {
166
+ return criteria;
167
+ }
168
+
169
+ const acSection = acMatch[1];
170
+
171
+ // Pattern with checkboxes (PREFERRED)
172
+ // Matches: - [x] **AC-US1-01**: Description
173
+ // - [ ] **AC-020**: Description
174
+ const acPatternWithCheckbox =
175
+ /(?:^|\n)\s*[-*]\s+\[([x ])\]\s+\*\*([A-Z]+-(?:[A-Z]+\d+-)?(\d+))\*\*:\s*([^\n]+)/g;
176
+
177
+ // Pattern without checkboxes (FALLBACK)
178
+ // Matches: - **AC-US1-01**: Description
179
+ const acPatternNoCheckbox =
180
+ /(?:^|\n)\s*[-*]?\s*\*\*([A-Z]+-(?:[A-Z]+\d+-)?(\d+))\*\*:\s*([^\n]+)/g;
181
+
182
+ // First try pattern with checkboxes
183
+ let match;
184
+ let foundAny = false;
185
+
186
+ while ((match = acPatternWithCheckbox.exec(acSection)) !== null) {
187
+ foundAny = true;
188
+ criteria.push({
189
+ id: match[2], // e.g., "AC-US1-01" or "AC-020"
190
+ description: match[4].trim(),
191
+ completed: match[1] === 'x', // ✅ Read checkbox state from source!
192
+ });
193
+ }
194
+
195
+ // If no checkboxes found, try pattern without checkboxes
196
+ if (!foundAny) {
197
+ while ((match = acPatternNoCheckbox.exec(acSection)) !== null) {
198
+ criteria.push({
199
+ id: match[1], // e.g., "AC-US1-01" or "AC-020"
200
+ description: match[3].trim(),
201
+ completed: false, // Default to not completed
202
+ });
203
+ }
204
+ }
205
+
206
+ return criteria;
207
+ }
208
+
209
+ /**
210
+ * Extract tasks from increment's tasks.md that map to this User Story
211
+ *
212
+ * Process:
213
+ * 1. Find increment link in user story's "Implementation" section
214
+ * 2. Read increment's tasks.md
215
+ * 3. Filter tasks that reference this user story's ACs
216
+ * 4. Extract completion status from **Status**: [x] or [ ]
217
+ */
218
+ private async extractTasks(userStoryContent: string, userStoryId: string): Promise<Task[]> {
219
+ const tasks: Task[] = [];
220
+
221
+ // Look for "Implementation" section with increment link
222
+ const implMatch = userStoryContent.match(/##\s*Implementation\s*\n+([\s\S]*?)(?=\n##|$)/i);
223
+
224
+ if (!implMatch) {
225
+ return tasks; // No implementation yet
226
+ }
227
+
228
+ const implSection = implMatch[1];
229
+
230
+ // Extract increment ID from Implementation section
231
+ // Pattern: **Increment**: [0031-external-tool-status-sync](...)
232
+ const incrementMatch = implSection.match(/\*\*Increment\*\*:\s*\[([^\]]+)\]/);
233
+
234
+ if (!incrementMatch) {
235
+ return tasks; // No increment linked
236
+ }
237
+
238
+ const incrementId = incrementMatch[1];
239
+
240
+ // Try to read increment's tasks.md
241
+ const tasksPath = path.join(
242
+ this.projectRoot,
243
+ '.specweave',
244
+ 'increments',
245
+ incrementId,
246
+ 'tasks.md'
247
+ );
248
+
249
+ if (!existsSync(tasksPath)) {
250
+ return tasks; // Increment has no tasks.md yet
251
+ }
252
+
253
+ const tasksContent = await readFile(tasksPath, 'utf-8');
254
+
255
+ // Extract tasks that reference this User Story via AC-IDs
256
+ // Pattern:
257
+ // ### T-001: Task Title
258
+ // **User Story**: ...
259
+ // **Status**: [x] (100% - Completed) or [ ] (0% - Not started)
260
+ // **AC**: AC-US1-01, AC-US1-02
261
+ const taskPattern = /###?\s+(T-\d+):\s*([^\n]+)\n([\s\S]*?)(?=\n###?\s+T-\d+:|$)/g;
262
+ let match;
263
+
264
+ while ((match = taskPattern.exec(tasksContent)) !== null) {
265
+ const taskId = match[1];
266
+ const taskTitle = match[2].trim();
267
+ const taskBody = match[3];
268
+
269
+ // Extract AC list
270
+ const acMatch = taskBody.match(/\*\*AC\*\*:\s*([^\n]+)/);
271
+ if (!acMatch) {
272
+ continue; // Skip tasks without AC field
273
+ }
274
+ const acList = acMatch[1].trim();
275
+
276
+ // Check if any AC in this task belongs to current User Story
277
+ // AC-US1-01 → US-001
278
+ // AC-US001-01 → US-001
279
+ const acIds = acList.split(',').map((ac) => ac.trim());
280
+ const belongsToThisUS = acIds.some((acId) => {
281
+ // Extract US ID from AC-ID
282
+ // AC-US1-01 → US1 → US-001
283
+ // AC-US001-01 → US001 → US-001
284
+ const usMatch = acId.match(/AC-([A-Z]+\d+)-/);
285
+ if (!usMatch) return false;
286
+
287
+ // Normalize to US-XXX format (pad with zeros)
288
+ const extractedUsId = usMatch[1]; // e.g., "US1" or "US001"
289
+ const extractedNum = extractedUsId.replace(/^US/, ''); // "1" or "001"
290
+ const normalizedExtracted = `US-${extractedNum.padStart(3, '0')}`; // "US-001"
291
+
292
+ const currentNum = userStoryId.replace(/^US-?/, ''); // "001" or "1"
293
+ const normalizedCurrent = `US-${currentNum.padStart(3, '0')}`; // "US-001"
294
+
295
+ return normalizedExtracted === normalizedCurrent;
296
+ });
297
+
298
+ if (!belongsToThisUS) {
299
+ continue;
300
+ }
301
+
302
+ // ✅ Extract completion status from **Status**: [x] or [ ]
303
+ const statusMatch = taskBody.match(/\*\*Status\*\*:\s*\[([x ])\]/);
304
+ const completed = statusMatch ? statusMatch[1] === 'x' : false;
305
+
306
+ tasks.push({
307
+ id: taskId,
308
+ title: taskTitle,
309
+ completed, // ✅ Now reads actual completion status!
310
+ userStories: acIds,
311
+ });
312
+ }
313
+
314
+ return tasks;
315
+ }
316
+
317
+ /**
318
+ * Build completion comment for GitHub issue closure
319
+ *
320
+ * Used when closing issue after verification
321
+ */
322
+ buildCompletionComment(completion: CompletionStatus): string {
323
+ return `✅ **User Story Verified Complete**
324
+
325
+ **Completion Status**:
326
+ - ✅ Acceptance Criteria: ${completion.acsCompleted}/${completion.acsTotal} (100%)
327
+ - ✅ Implementation Tasks: ${completion.tasksCompleted}/${completion.tasksTotal} (100%)
328
+
329
+ All work has been verified and completed. This issue is now closed.
330
+
331
+ 🤖 Auto-verified by SpecWeave AC Completion Gate`;
332
+ }
333
+
334
+ /**
335
+ * Build progress comment for GitHub issue update
336
+ *
337
+ * Used when issue stays open (not 100% complete)
338
+ */
339
+ buildProgressComment(completion: CompletionStatus): string {
340
+ const sections: string[] = [];
341
+
342
+ sections.push('📊 **Progress Update**');
343
+ sections.push('');
344
+
345
+ // AC progress
346
+ const acIcon = completion.acsPercentage === 100 ? '✅' : '🔄';
347
+ sections.push(
348
+ `${acIcon} **Acceptance Criteria**: ${completion.acsCompleted}/${completion.acsTotal} (${completion.acsPercentage.toFixed(0)}%)`
349
+ );
350
+
351
+ if (completion.blockingAcs.length > 0) {
352
+ sections.push('');
353
+ sections.push('**Incomplete ACs**:');
354
+ for (const acId of completion.blockingAcs) {
355
+ sections.push(`- [ ] ${acId}`);
356
+ }
357
+ }
358
+
359
+ sections.push('');
360
+
361
+ // Task progress
362
+ const taskIcon = completion.tasksPercentage === 100 ? '✅' : '🔄';
363
+ sections.push(
364
+ `${taskIcon} **Implementation Tasks**: ${completion.tasksCompleted}/${completion.tasksTotal} (${completion.tasksPercentage.toFixed(0)}%)`
365
+ );
366
+
367
+ if (completion.blockingTasks.length > 0) {
368
+ sections.push('');
369
+ sections.push('**Incomplete Tasks**:');
370
+ for (const taskId of completion.blockingTasks) {
371
+ sections.push(`- [ ] ${taskId}`);
372
+ }
373
+ }
374
+
375
+ sections.push('');
376
+ sections.push('---');
377
+ sections.push('🤖 Auto-updated by SpecWeave AC Completion Gate');
378
+
379
+ return sections.join('\n');
380
+ }
381
+
382
+ /**
383
+ * Build reopen comment for GitHub issue
384
+ *
385
+ * Used when reopening prematurely closed issue
386
+ */
387
+ buildReopenComment(
388
+ completion: CompletionStatus,
389
+ reason: string = 'Work verification failed'
390
+ ): string {
391
+ const sections: string[] = [];
392
+
393
+ sections.push(`🔄 **Reopening Issue - ${reason}**`);
394
+ sections.push('');
395
+
396
+ sections.push('**Current Status**:');
397
+ sections.push(
398
+ `- Acceptance Criteria: ${completion.acsCompleted}/${completion.acsTotal} (${completion.acsPercentage.toFixed(0)}%)`
399
+ );
400
+ sections.push(
401
+ `- Implementation Tasks: ${completion.tasksCompleted}/${completion.tasksTotal} (${completion.tasksPercentage.toFixed(0)}%)`
402
+ );
403
+
404
+ const totalBlocking = completion.blockingAcs.length + completion.blockingTasks.length;
405
+
406
+ if (totalBlocking > 0) {
407
+ sections.push('');
408
+ sections.push(`**Blocking Items** (${totalBlocking}):`);
409
+
410
+ if (completion.blockingAcs.length > 0) {
411
+ sections.push('');
412
+ sections.push('**Acceptance Criteria**:');
413
+ for (const acId of completion.blockingAcs) {
414
+ sections.push(`- [ ] ${acId}`);
415
+ }
416
+ }
417
+
418
+ if (completion.blockingTasks.length > 0) {
419
+ sections.push('');
420
+ sections.push('**Implementation Tasks**:');
421
+ for (const taskId of completion.blockingTasks) {
422
+ sections.push(`- [ ] ${taskId}`);
423
+ }
424
+ }
425
+ }
426
+
427
+ sections.push('');
428
+ sections.push('⚠️ This issue cannot be closed until all ACs and tasks are verified complete.');
429
+ sections.push('');
430
+ sections.push('🤖 Auto-reopened by SpecWeave AC Completion Gate');
431
+
432
+ return sections.join('\n');
433
+ }
434
+ }