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
@@ -20,6 +20,7 @@ import {
20
20
  SpecContent,
21
21
  ContentSyncResult,
22
22
  } from '../../../src/core/spec-content-sync.js';
23
+ import { ProgressCommentBuilder } from './progress-comment-builder.js';
23
24
  import path from 'path';
24
25
  import fs from 'fs/promises';
25
26
 
@@ -215,6 +216,11 @@ async function createGitHubIssue(
215
216
 
216
217
  /**
217
218
  * Update existing GitHub issue with spec content
219
+ *
220
+ * ARCHITECTURE: IMMUTABLE DESCRIPTIONS (Phase 4)
221
+ * - Issue description is NEVER edited after creation
222
+ * - All content updates communicated via progress comments
223
+ * - Metadata updates only (labels, milestone, assignees)
218
224
  */
219
225
  async function updateGitHubIssue(
220
226
  client: GitHubClientV2,
@@ -262,36 +268,47 @@ async function updateGitHubIssue(
262
268
  }
263
269
  }
264
270
 
265
- // Build updated content using compact format
266
- const newTitle = `[${spec.identifier.compact}] ${spec.title}`;
267
- const newBody = buildExternalDescription(spec);
268
-
269
271
  if (dryRun) {
270
- console.log('\n🔍 Dry run - would update issue:');
271
- console.log(` Title: ${newTitle}`);
272
- console.log(` Body:\n${newBody}`);
272
+ console.log('\n🔍 Dry run - would post progress comment');
273
273
 
274
274
  return {
275
275
  success: true,
276
- action: 'updated',
276
+ action: 'updated-via-comment',
277
277
  externalId: issueNumber.toString(),
278
278
  externalUrl: issue.html_url,
279
279
  };
280
280
  }
281
281
 
282
- // Update issue (ONLY title and description, NOT status!)
283
- await client.updateIssueBody(issueNumber, newBody);
282
+ // IMMUTABLE DESCRIPTION PATTERN:
283
+ // ❌ OLD: Update issue body (overwrites description)
284
+ // ✅ NEW: Post progress comment (preserves description)
284
285
 
285
- // Note: We do NOT update status/state - that's managed in GitHub
286
- // We also do NOT close/reopen issues - that's done by humans/automation in GitHub
286
+ // Update metadata only (labels via GitHub CLI - no direct API method)
287
+ const labels = [
288
+ 'specweave',
289
+ 'spec',
290
+ spec.project,
291
+ spec.metadata.priority || 'P2'
292
+ ].filter(Boolean);
293
+
294
+ await client.addLabels(issueNumber, labels);
295
+
296
+ // Post progress comment (NOT edit body)
297
+ await postProgressComment(
298
+ client,
299
+ specPath,
300
+ issueNumber,
301
+ spec,
302
+ verbose
303
+ );
287
304
 
288
305
  if (verbose) {
289
- console.log(`✅ Updated issue #${issueNumber}`);
306
+ console.log(`✅ Posted progress comment to issue #${issueNumber}`);
290
307
  }
291
308
 
292
309
  return {
293
310
  success: true,
294
- action: 'updated',
311
+ action: 'updated-via-comment',
295
312
  externalId: issueNumber.toString(),
296
313
  externalUrl: issue.html_url,
297
314
  };
@@ -304,6 +321,57 @@ async function updateGitHubIssue(
304
321
  }
305
322
  }
306
323
 
324
+ /**
325
+ * Post progress comment to GitHub issue (IMMUTABLE DESCRIPTION PATTERN)
326
+ *
327
+ * This replaces the old pattern of editing issue body.
328
+ * Benefits:
329
+ * - Preserves original issue description
330
+ * - Creates audit trail of changes
331
+ * - Stakeholders get notifications on updates
332
+ */
333
+ async function postProgressComment(
334
+ client: GitHubClientV2,
335
+ specPath: string,
336
+ issueNumber: number,
337
+ spec: SpecContent,
338
+ verbose: boolean = false
339
+ ): Promise<void> {
340
+ try {
341
+ // Extract increment ID from spec path or identifier
342
+ // Examples:
343
+ // - .specweave/increments/0031-external-tool-sync/spec.md → 0031
344
+ // - .specweave/docs/internal/specs/default/FS-031/us-001-*.md → FS-031
345
+
346
+ let incrementId = 'unknown';
347
+
348
+ // Try to extract from spec path
349
+ const incrementMatch = specPath.match(/increments\/([^/]+)/);
350
+ if (incrementMatch) {
351
+ incrementId = incrementMatch[1];
352
+ } else {
353
+ // Fallback: use spec identifier
354
+ incrementId = spec.identifier.compact;
355
+ }
356
+
357
+ // Build progress comment using ProgressCommentBuilder
358
+ const builder = new ProgressCommentBuilder(specPath);
359
+ const comment = await builder.buildProgressComment(incrementId);
360
+
361
+ // Post comment (using addComment method)
362
+ await client.addComment(issueNumber, comment);
363
+
364
+ if (verbose) {
365
+ console.log(` 📊 Progress comment posted (${comment.length} chars)`);
366
+ }
367
+ } catch (error: any) {
368
+ // Non-blocking: Log error but don't fail the sync
369
+ if (verbose) {
370
+ console.error(` ⚠️ Failed to post progress comment: ${error.message}`);
371
+ }
372
+ }
373
+ }
374
+
307
375
  /**
308
376
  * Count user stories in issue body
309
377
  */
@@ -0,0 +1,229 @@
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 ProgressCommentBuilder {
6
+ constructor(userStoryPath, projectRoot = process.cwd()) {
7
+ this.userStoryPath = userStoryPath;
8
+ this.projectRoot = projectRoot;
9
+ }
10
+ /**
11
+ * Build complete progress comment
12
+ */
13
+ async buildProgressComment(incrementId) {
14
+ const summary = await this.calculateProgressSummary();
15
+ const frontmatter = await this.extractFrontmatter();
16
+ let comment = "";
17
+ comment += `\u{1F4CA} **Progress Update from Increment ${incrementId}**
18
+
19
+ `;
20
+ comment += `**Status**: ${summary.statusSummary} (${summary.completedACs}/${summary.totalACs} AC implemented - ${summary.percentage}%)
21
+
22
+ `;
23
+ if (summary.completedCriteria.length > 0) {
24
+ comment += `## \u2705 Completed Acceptance Criteria
25
+
26
+ `;
27
+ for (const ac of summary.completedCriteria) {
28
+ const priority = ac.priority ? ` (${ac.priority})` : "";
29
+ const testable = ac.testable ? " [testable]" : "";
30
+ comment += `- [x] **${ac.id}**: ${ac.description}${priority}${testable}
31
+ `;
32
+ }
33
+ comment += "\n";
34
+ }
35
+ if (summary.remainingCriteria.length > 0) {
36
+ const p1 = summary.remainingCriteria.filter((ac) => ac.priority === "P1");
37
+ const p2 = summary.remainingCriteria.filter((ac) => ac.priority === "P2");
38
+ const p3 = summary.remainingCriteria.filter((ac) => ac.priority === "P3");
39
+ if (p1.length > 0) {
40
+ comment += `## \u{1F534} Remaining Work (P1 - Critical)
41
+
42
+ `;
43
+ for (const ac of p1) {
44
+ const testable = ac.testable ? " [testable]" : "";
45
+ comment += `- [ ] **${ac.id}**: ${ac.description} (P1)${testable}
46
+ `;
47
+ }
48
+ comment += "\n";
49
+ }
50
+ if (p2.length > 0 || p3.length > 0) {
51
+ comment += `## \u23F3 Remaining Work (P2-P3)
52
+
53
+ `;
54
+ for (const ac of [...p2, ...p3]) {
55
+ const priority = ac.priority ? ` (${ac.priority})` : "";
56
+ const testable = ac.testable ? " [testable]" : "";
57
+ comment += `- [ ] **${ac.id}**: ${ac.description}${priority}${testable}
58
+ `;
59
+ }
60
+ comment += "\n";
61
+ }
62
+ }
63
+ if (summary.tasks.length > 0) {
64
+ const completedTasks = summary.tasks.filter((t) => t.status).length;
65
+ const totalTasks = summary.tasks.length;
66
+ comment += `## \u{1F4CB} Implementation Tasks (${completedTasks}/${totalTasks})
67
+
68
+ `;
69
+ for (const task of summary.tasks) {
70
+ const checkbox = task.status ? "[x]" : "[ ]";
71
+ comment += `- ${checkbox} ${task.id}: ${task.title}
72
+ `;
73
+ }
74
+ comment += "\n";
75
+ }
76
+ comment += `---
77
+
78
+ `;
79
+ comment += `\u{1F916} Auto-synced by SpecWeave | `;
80
+ comment += `[View increment](../../increments/${incrementId}) | `;
81
+ comment += `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
82
+ `;
83
+ return comment;
84
+ }
85
+ /**
86
+ * Calculate progress summary
87
+ */
88
+ async calculateProgressSummary() {
89
+ const content = await readFile(this.userStoryPath, "utf-8");
90
+ const acceptanceCriteria = this.extractAcceptanceCriteria(content);
91
+ const tasks = await this.extractTasks(content);
92
+ const completedCriteria = acceptanceCriteria.filter((ac) => ac.completed);
93
+ const remainingCriteria = acceptanceCriteria.filter((ac) => !ac.completed);
94
+ const totalACs = acceptanceCriteria.length;
95
+ const completedACs = completedCriteria.length;
96
+ const percentage = totalACs > 0 ? Math.round(completedACs / totalACs * 100) : 0;
97
+ let statusSummary = "In Progress";
98
+ if (completedACs === totalACs && totalACs > 0) {
99
+ statusSummary = "Complete";
100
+ } else if (completedACs > 0) {
101
+ const p1Criteria = acceptanceCriteria.filter((ac) => ac.priority === "P1");
102
+ const p1Completed = p1Criteria.filter((ac) => ac.completed).length;
103
+ if (p1Completed === p1Criteria.length && p1Criteria.length > 0) {
104
+ statusSummary = "Core Complete";
105
+ }
106
+ }
107
+ return {
108
+ totalACs,
109
+ completedACs,
110
+ percentage,
111
+ statusSummary,
112
+ completedCriteria,
113
+ remainingCriteria,
114
+ tasks
115
+ };
116
+ }
117
+ /**
118
+ * Format AC checkboxes (for inline display)
119
+ */
120
+ formatACCheckboxes() {
121
+ return "";
122
+ }
123
+ /**
124
+ * Format task checkboxes (for inline display)
125
+ */
126
+ formatTaskCheckboxes() {
127
+ return "";
128
+ }
129
+ /**
130
+ * Calculate progress percentage
131
+ */
132
+ async calculateProgressPercentage() {
133
+ const summary = await this.calculateProgressSummary();
134
+ return summary.percentage;
135
+ }
136
+ /**
137
+ * Extract frontmatter from user story file
138
+ */
139
+ async extractFrontmatter() {
140
+ const content = await readFile(this.userStoryPath, "utf-8");
141
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
142
+ if (!match) {
143
+ throw new Error(`User story file missing YAML frontmatter: ${this.userStoryPath}`);
144
+ }
145
+ return yaml.parse(match[1]);
146
+ }
147
+ /**
148
+ * Extract acceptance criteria from content
149
+ */
150
+ extractAcceptanceCriteria(content) {
151
+ const criteria = [];
152
+ const acPattern = /- \[([ x])\] \*\*AC-US(\d+)-(\d+)\*\*:\s*([^(]+)(?:\(([^)]+)\))?/g;
153
+ let match;
154
+ while ((match = acPattern.exec(content)) !== null) {
155
+ const completed = match[1] === "x";
156
+ const usNumber = match[2];
157
+ const acNumber = match[3];
158
+ const description = match[4].trim();
159
+ const metadata = match[5] || "";
160
+ criteria.push({
161
+ id: `AC-US${usNumber}-${acNumber}`,
162
+ description,
163
+ completed,
164
+ priority: metadata.includes("P1") ? "P1" : metadata.includes("P2") ? "P2" : metadata.includes("P3") ? "P3" : "",
165
+ testable: metadata.includes("testable")
166
+ });
167
+ }
168
+ return criteria;
169
+ }
170
+ /**
171
+ * Extract tasks from Implementation section
172
+ */
173
+ async extractTasks(content) {
174
+ const tasks = [];
175
+ const incrementMatch = content.match(/\*\*Increment\*\*:\s*\[([^\]]+)\]/);
176
+ if (!incrementMatch) {
177
+ return tasks;
178
+ }
179
+ const incrementId = incrementMatch[1];
180
+ const tasksPath = path.join(
181
+ this.projectRoot,
182
+ ".specweave",
183
+ "increments",
184
+ incrementId,
185
+ "tasks.md"
186
+ );
187
+ if (!existsSync(tasksPath)) {
188
+ return tasks;
189
+ }
190
+ const tasksContent = await readFile(tasksPath, "utf-8");
191
+ const taskLinkPattern = /- \[([T-\d]+):\s*([^\]]+)\]/g;
192
+ let match;
193
+ while ((match = taskLinkPattern.exec(content)) !== null) {
194
+ const taskId = match[1];
195
+ const taskTitle = match[2].trim();
196
+ const taskPattern = new RegExp(`### ${taskId}[:\\s].*?\\n\\*\\*Status\\*\\*:\\s*\\[([x ]?)\\]`, "s");
197
+ const taskMatch = tasksContent.match(taskPattern);
198
+ const completed = taskMatch ? taskMatch[1] === "x" : false;
199
+ tasks.push({
200
+ id: taskId,
201
+ title: taskTitle,
202
+ status: completed
203
+ });
204
+ }
205
+ return tasks;
206
+ }
207
+ }
208
+ async function main() {
209
+ const args = process.argv.slice(2);
210
+ if (args.length < 4) {
211
+ console.error("Usage: node progress-comment-builder.js --user-story <path> --increment <id>");
212
+ process.exit(1);
213
+ }
214
+ const userStoryPath = args[args.indexOf("--user-story") + 1];
215
+ const incrementId = args[args.indexOf("--increment") + 1];
216
+ const builder = new ProgressCommentBuilder(userStoryPath);
217
+ const comment = await builder.buildProgressComment(incrementId);
218
+ console.log(comment);
219
+ }
220
+ if (require.main === module) {
221
+ main().catch((error) => {
222
+ console.error("Error generating progress comment:", error.message);
223
+ process.exit(1);
224
+ });
225
+ }
226
+ export {
227
+ ProgressCommentBuilder,
228
+ main
229
+ };
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Progress Comment Builder - Generate progress update comments for GitHub issues
3
+ *
4
+ * Architecture:
5
+ * - Reads user story files from living docs
6
+ * - Extracts current AC completion status
7
+ * - Formats progress comment with checkboxes
8
+ * - Creates audit trail of changes over time
9
+ *
10
+ * Key Principle: IMMUTABLE DESCRIPTIONS
11
+ * - Issue description created once (snapshot)
12
+ * - All updates via progress comments (current state)
13
+ * - Complete audit trail preserved
14
+ */
15
+
16
+ import { readFile } from 'fs/promises';
17
+ import { existsSync } from 'fs';
18
+ import * as path from 'path';
19
+ import * as yaml from 'yaml';
20
+
21
+ interface UserStoryFrontmatter {
22
+ id: string;
23
+ epic: string;
24
+ title: string;
25
+ status: 'complete' | 'active' | 'planning' | 'not-started';
26
+ created: string;
27
+ completed?: string;
28
+ }
29
+
30
+ interface AcceptanceCriterion {
31
+ id: string; // AC-US4-01
32
+ description: string;
33
+ completed: boolean;
34
+ priority: string; // P1, P2, P3
35
+ testable: boolean;
36
+ }
37
+
38
+ interface Task {
39
+ id: string; // T-008
40
+ title: string;
41
+ status: boolean; // true = completed
42
+ }
43
+
44
+ export interface ProgressSummary {
45
+ totalACs: number;
46
+ completedACs: number;
47
+ percentage: number;
48
+ statusSummary: string; // "Core Complete", "Complete", "In Progress"
49
+ completedCriteria: AcceptanceCriterion[];
50
+ remainingCriteria: AcceptanceCriterion[];
51
+ tasks: Task[];
52
+ }
53
+
54
+ export class ProgressCommentBuilder {
55
+ private userStoryPath: string;
56
+ private projectRoot: string;
57
+
58
+ constructor(userStoryPath: string, projectRoot: string = process.cwd()) {
59
+ this.userStoryPath = userStoryPath;
60
+ this.projectRoot = projectRoot;
61
+ }
62
+
63
+ /**
64
+ * Build complete progress comment
65
+ */
66
+ async buildProgressComment(incrementId: string): Promise<string> {
67
+ const summary = await this.calculateProgressSummary();
68
+ const frontmatter = await this.extractFrontmatter();
69
+
70
+ let comment = '';
71
+
72
+ // Header
73
+ comment += `📊 **Progress Update from Increment ${incrementId}**\n\n`;
74
+ comment += `**Status**: ${summary.statusSummary} (${summary.completedACs}/${summary.totalACs} AC implemented - ${summary.percentage}%)\n\n`;
75
+
76
+ // Completed Acceptance Criteria
77
+ if (summary.completedCriteria.length > 0) {
78
+ comment += `## ✅ Completed Acceptance Criteria\n\n`;
79
+ for (const ac of summary.completedCriteria) {
80
+ const priority = ac.priority ? ` (${ac.priority})` : '';
81
+ const testable = ac.testable ? ' [testable]' : '';
82
+ comment += `- [x] **${ac.id}**: ${ac.description}${priority}${testable}\n`;
83
+ }
84
+ comment += '\n';
85
+ }
86
+
87
+ // Remaining Work
88
+ if (summary.remainingCriteria.length > 0) {
89
+ // Group by priority
90
+ const p1 = summary.remainingCriteria.filter(ac => ac.priority === 'P1');
91
+ const p2 = summary.remainingCriteria.filter(ac => ac.priority === 'P2');
92
+ const p3 = summary.remainingCriteria.filter(ac => ac.priority === 'P3');
93
+
94
+ if (p1.length > 0) {
95
+ comment += `## 🔴 Remaining Work (P1 - Critical)\n\n`;
96
+ for (const ac of p1) {
97
+ const testable = ac.testable ? ' [testable]' : '';
98
+ comment += `- [ ] **${ac.id}**: ${ac.description} (P1)${testable}\n`;
99
+ }
100
+ comment += '\n';
101
+ }
102
+
103
+ if (p2.length > 0 || p3.length > 0) {
104
+ comment += `## ⏳ Remaining Work (P2-P3)\n\n`;
105
+ for (const ac of [...p2, ...p3]) {
106
+ const priority = ac.priority ? ` (${ac.priority})` : '';
107
+ const testable = ac.testable ? ' [testable]' : '';
108
+ comment += `- [ ] **${ac.id}**: ${ac.description}${priority}${testable}\n`;
109
+ }
110
+ comment += '\n';
111
+ }
112
+ }
113
+
114
+ // Tasks (if any)
115
+ if (summary.tasks.length > 0) {
116
+ const completedTasks = summary.tasks.filter(t => t.status).length;
117
+ const totalTasks = summary.tasks.length;
118
+ comment += `## 📋 Implementation Tasks (${completedTasks}/${totalTasks})\n\n`;
119
+
120
+ for (const task of summary.tasks) {
121
+ const checkbox = task.status ? '[x]' : '[ ]';
122
+ comment += `- ${checkbox} ${task.id}: ${task.title}\n`;
123
+ }
124
+ comment += '\n';
125
+ }
126
+
127
+ // Footer
128
+ comment += `---\n\n`;
129
+ comment += `🤖 Auto-synced by SpecWeave | `;
130
+ comment += `[View increment](../../increments/${incrementId}) | `;
131
+ comment += `${new Date().toISOString().split('T')[0]}\n`;
132
+
133
+ return comment;
134
+ }
135
+
136
+ /**
137
+ * Calculate progress summary
138
+ */
139
+ async calculateProgressSummary(): Promise<ProgressSummary> {
140
+ const content = await readFile(this.userStoryPath, 'utf-8');
141
+ const acceptanceCriteria = this.extractAcceptanceCriteria(content);
142
+ const tasks = await this.extractTasks(content);
143
+
144
+ const completedCriteria = acceptanceCriteria.filter(ac => ac.completed);
145
+ const remainingCriteria = acceptanceCriteria.filter(ac => !ac.completed);
146
+
147
+ const totalACs = acceptanceCriteria.length;
148
+ const completedACs = completedCriteria.length;
149
+ const percentage = totalACs > 0 ? Math.round((completedACs / totalACs) * 100) : 0;
150
+
151
+ // Determine status summary
152
+ let statusSummary = 'In Progress';
153
+ if (completedACs === totalACs && totalACs > 0) {
154
+ statusSummary = 'Complete';
155
+ } else if (completedACs > 0) {
156
+ // Check if all P1 are done
157
+ const p1Criteria = acceptanceCriteria.filter(ac => ac.priority === 'P1');
158
+ const p1Completed = p1Criteria.filter(ac => ac.completed).length;
159
+ if (p1Completed === p1Criteria.length && p1Criteria.length > 0) {
160
+ statusSummary = 'Core Complete';
161
+ }
162
+ }
163
+
164
+ return {
165
+ totalACs,
166
+ completedACs,
167
+ percentage,
168
+ statusSummary,
169
+ completedCriteria,
170
+ remainingCriteria,
171
+ tasks,
172
+ };
173
+ }
174
+
175
+ /**
176
+ * Format AC checkboxes (for inline display)
177
+ */
178
+ formatACCheckboxes(): string {
179
+ // This method is for simple inline formatting
180
+ // The full buildProgressComment does structured formatting
181
+ return ''; // Placeholder for CLI usage if needed
182
+ }
183
+
184
+ /**
185
+ * Format task checkboxes (for inline display)
186
+ */
187
+ formatTaskCheckboxes(): string {
188
+ // This method is for simple inline formatting
189
+ // The full buildProgressComment does structured formatting
190
+ return ''; // Placeholder for CLI usage if needed
191
+ }
192
+
193
+ /**
194
+ * Calculate progress percentage
195
+ */
196
+ async calculateProgressPercentage(): Promise<number> {
197
+ const summary = await this.calculateProgressSummary();
198
+ return summary.percentage;
199
+ }
200
+
201
+ /**
202
+ * Extract frontmatter from user story file
203
+ */
204
+ private async extractFrontmatter(): Promise<UserStoryFrontmatter> {
205
+ const content = await readFile(this.userStoryPath, 'utf-8');
206
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
207
+
208
+ if (!match) {
209
+ throw new Error(`User story file missing YAML frontmatter: ${this.userStoryPath}`);
210
+ }
211
+
212
+ return yaml.parse(match[1]) as UserStoryFrontmatter;
213
+ }
214
+
215
+ /**
216
+ * Extract acceptance criteria from content
217
+ */
218
+ private extractAcceptanceCriteria(content: string): AcceptanceCriterion[] {
219
+ const criteria: AcceptanceCriterion[] = [];
220
+
221
+ // Pattern: - [x] **AC-US4-01**: Description (P1, testable)
222
+ const acPattern =
223
+ /- \[([ x])\] \*\*AC-US(\d+)-(\d+)\*\*:\s*([^(]+)(?:\(([^)]+)\))?/g;
224
+
225
+ let match;
226
+ while ((match = acPattern.exec(content)) !== null) {
227
+ const completed = match[1] === 'x';
228
+ const usNumber = match[2];
229
+ const acNumber = match[3];
230
+ const description = match[4].trim();
231
+ const metadata = match[5] || '';
232
+
233
+ criteria.push({
234
+ id: `AC-US${usNumber}-${acNumber}`,
235
+ description,
236
+ completed,
237
+ priority: metadata.includes('P1') ? 'P1' : metadata.includes('P2') ? 'P2' : metadata.includes('P3') ? 'P3' : '',
238
+ testable: metadata.includes('testable'),
239
+ });
240
+ }
241
+
242
+ return criteria;
243
+ }
244
+
245
+ /**
246
+ * Extract tasks from Implementation section
247
+ */
248
+ private async extractTasks(content: string): Promise<Task[]> {
249
+ const tasks: Task[] = [];
250
+
251
+ // Extract increment ID from Implementation section
252
+ const incrementMatch = content.match(/\*\*Increment\*\*:\s*\[([^\]]+)\]/);
253
+ if (!incrementMatch) {
254
+ return tasks; // No increment linked
255
+ }
256
+
257
+ const incrementId = incrementMatch[1];
258
+
259
+ // Find tasks.md file
260
+ const tasksPath = path.join(
261
+ this.projectRoot,
262
+ '.specweave',
263
+ 'increments',
264
+ incrementId,
265
+ 'tasks.md'
266
+ );
267
+
268
+ if (!existsSync(tasksPath)) {
269
+ return tasks; // Tasks file not found
270
+ }
271
+
272
+ const tasksContent = await readFile(tasksPath, 'utf-8');
273
+
274
+ // Extract task links from user story (e.g., - [T-001: Title](link))
275
+ const taskLinkPattern = /- \[([T-\d]+):\s*([^\]]+)\]/g;
276
+ let match;
277
+
278
+ while ((match = taskLinkPattern.exec(content)) !== null) {
279
+ const taskId = match[1];
280
+ const taskTitle = match[2].trim();
281
+
282
+ // Check if task is completed in tasks.md
283
+ const taskPattern = new RegExp(`### ${taskId}[:\\s].*?\\n\\*\\*Status\\*\\*:\\s*\\[([x ]?)\\]`, 's');
284
+ const taskMatch = tasksContent.match(taskPattern);
285
+ const completed = taskMatch ? taskMatch[1] === 'x' : false;
286
+
287
+ tasks.push({
288
+ id: taskId,
289
+ title: taskTitle,
290
+ status: completed,
291
+ });
292
+ }
293
+
294
+ return tasks;
295
+ }
296
+ }
297
+
298
+ /**
299
+ * CLI entry point for generating progress comments
300
+ */
301
+ export async function main() {
302
+ const args = process.argv.slice(2);
303
+
304
+ if (args.length < 4) {
305
+ console.error('Usage: node progress-comment-builder.js --user-story <path> --increment <id>');
306
+ process.exit(1);
307
+ }
308
+
309
+ const userStoryPath = args[args.indexOf('--user-story') + 1];
310
+ const incrementId = args[args.indexOf('--increment') + 1];
311
+
312
+ const builder = new ProgressCommentBuilder(userStoryPath);
313
+ const comment = await builder.buildProgressComment(incrementId);
314
+
315
+ console.log(comment);
316
+ }
317
+
318
+ // Run if called directly
319
+ if (require.main === module) {
320
+ main().catch((error) => {
321
+ console.error('Error generating progress comment:', error.message);
322
+ process.exit(1);
323
+ });
324
+ }