specweave 0.24.13 → 0.26.2

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 (377) hide show
  1. package/CLAUDE.md +586 -18
  2. package/bin/specweave.js +14 -0
  3. package/dist/plugins/specweave-github/lib/CodeValidator.js +2 -2
  4. package/dist/plugins/specweave-github/lib/CodeValidator.js.map +1 -1
  5. package/dist/plugins/specweave-github/lib/ThreeLayerSyncManager.js +1 -1
  6. package/dist/plugins/specweave-github/lib/ThreeLayerSyncManager.js.map +1 -1
  7. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
  8. package/dist/plugins/specweave-github/lib/github-client-v2.js +17 -1
  9. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  10. package/dist/plugins/specweave-github/lib/github-issue-updater.js +1 -1
  11. package/dist/plugins/specweave-github/lib/github-issue-updater.js.map +1 -1
  12. package/dist/plugins/specweave-github/lib/github-sync-bidirectional.js +1 -1
  13. package/dist/plugins/specweave-github/lib/github-sync-bidirectional.js.map +1 -1
  14. package/dist/plugins/specweave-github/lib/github-sync-increment-changes.js +1 -1
  15. package/dist/plugins/specweave-github/lib/github-sync-increment-changes.js.map +1 -1
  16. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -1
  17. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +7 -6
  18. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -1
  19. package/dist/plugins/specweave-jira/lib/jira-epic-sync.js +1 -1
  20. package/dist/plugins/specweave-jira/lib/jira-epic-sync.js.map +1 -1
  21. package/dist/src/adapters/adapter-base.js +1 -1
  22. package/dist/src/adapters/adapter-base.js.map +1 -1
  23. package/dist/src/adapters/adapter-loader.js +1 -1
  24. package/dist/src/adapters/adapter-loader.js.map +1 -1
  25. package/dist/src/adapters/agents-md-generator.js +1 -1
  26. package/dist/src/adapters/agents-md-generator.js.map +1 -1
  27. package/dist/src/adapters/claude/adapter.js +1 -1
  28. package/dist/src/adapters/claude/adapter.js.map +1 -1
  29. package/dist/src/adapters/claude-md-generator.js +1 -1
  30. package/dist/src/adapters/claude-md-generator.js.map +1 -1
  31. package/dist/src/adapters/codex/adapter.js +1 -1
  32. package/dist/src/adapters/codex/adapter.js.map +1 -1
  33. package/dist/src/adapters/cursor/adapter.js +1 -1
  34. package/dist/src/adapters/cursor/adapter.js.map +1 -1
  35. package/dist/src/adapters/doc-generator.js +1 -1
  36. package/dist/src/adapters/doc-generator.js.map +1 -1
  37. package/dist/src/adapters/gemini/adapter.js +1 -1
  38. package/dist/src/adapters/gemini/adapter.js.map +1 -1
  39. package/dist/src/adapters/generic/adapter.js +1 -1
  40. package/dist/src/adapters/generic/adapter.js.map +1 -1
  41. package/dist/src/cli/commands/cicd-monitor.js +1 -1
  42. package/dist/src/cli/commands/cicd-monitor.js.map +1 -1
  43. package/dist/src/cli/commands/delete-feature.d.ts +14 -0
  44. package/dist/src/cli/commands/delete-feature.d.ts.map +1 -0
  45. package/dist/src/cli/commands/delete-feature.js +87 -0
  46. package/dist/src/cli/commands/delete-feature.js.map +1 -0
  47. package/dist/src/cli/commands/detect-specs.js +1 -1
  48. package/dist/src/cli/commands/detect-specs.js.map +1 -1
  49. package/dist/src/cli/commands/import-external.js +1 -1
  50. package/dist/src/cli/commands/import-external.js.map +1 -1
  51. package/dist/src/cli/commands/init.d.ts.map +1 -1
  52. package/dist/src/cli/commands/init.js +39 -49
  53. package/dist/src/cli/commands/init.js.map +1 -1
  54. package/dist/src/cli/commands/install.js +1 -1
  55. package/dist/src/cli/commands/install.js.map +1 -1
  56. package/dist/src/cli/commands/list.js +1 -1
  57. package/dist/src/cli/commands/list.js.map +1 -1
  58. package/dist/src/cli/commands/migrate-to-multiproject.js +1 -1
  59. package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
  60. package/dist/src/cli/commands/migrate-to-profiles.js +1 -1
  61. package/dist/src/cli/commands/migrate-to-profiles.js.map +1 -1
  62. package/dist/src/cli/commands/plan/agent-invoker.js +1 -1
  63. package/dist/src/cli/commands/repair-status-desync.js +1 -1
  64. package/dist/src/cli/commands/repair-status-desync.js.map +1 -1
  65. package/dist/src/cli/commands/revert-wip-limit.js +1 -1
  66. package/dist/src/cli/commands/revert-wip-limit.js.map +1 -1
  67. package/dist/src/cli/commands/sync-specs.js +1 -1
  68. package/dist/src/cli/commands/sync-specs.js.map +1 -1
  69. package/dist/src/cli/helpers/init/initial-increment-generator.js +1 -1
  70. package/dist/src/cli/helpers/init/initial-increment-generator.js.map +1 -1
  71. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts.map +1 -1
  72. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +13 -46
  73. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
  74. package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  75. package/dist/src/cli/helpers/issue-tracker/index.js +12 -31
  76. package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
  77. package/dist/src/cli/helpers/issue-tracker/types.d.ts +6 -1
  78. package/dist/src/cli/helpers/issue-tracker/types.d.ts.map +1 -1
  79. package/dist/src/cli/helpers/issue-tracker/types.js.map +1 -1
  80. package/dist/src/config/import-config.js +1 -1
  81. package/dist/src/config/import-config.js.map +1 -1
  82. package/dist/src/config/types.d.ts +203 -1208
  83. package/dist/src/config/types.d.ts.map +1 -1
  84. package/dist/src/core/ac-test-validator-cli.js +1 -1
  85. package/dist/src/core/ac-test-validator-cli.js.map +1 -1
  86. package/dist/src/core/ac-test-validator.js +1 -1
  87. package/dist/src/core/ac-test-validator.js.map +1 -1
  88. package/dist/src/core/brownfield/analyzer.js +1 -1
  89. package/dist/src/core/brownfield/analyzer.js.map +1 -1
  90. package/dist/src/core/brownfield/importer.js +1 -1
  91. package/dist/src/core/brownfield/importer.js.map +1 -1
  92. package/dist/src/core/cicd/config-loader.js +1 -1
  93. package/dist/src/core/cicd/config-loader.js.map +1 -1
  94. package/dist/src/core/cicd/notifier.js +1 -1
  95. package/dist/src/core/cicd/notifier.js.map +1 -1
  96. package/dist/src/core/cicd/parent-repo-validator.js +1 -1
  97. package/dist/src/core/cicd/parent-repo-validator.js.map +1 -1
  98. package/dist/src/core/cicd/state-manager.js +1 -1
  99. package/dist/src/core/cicd/state-manager.js.map +1 -1
  100. package/dist/src/core/config-manager.js +1 -1
  101. package/dist/src/core/config-manager.js.map +1 -1
  102. package/dist/src/core/cost-tracker.js +1 -1
  103. package/dist/src/core/cost-tracker.js.map +1 -1
  104. package/dist/src/core/deduplication/command-deduplicator.js +1 -1
  105. package/dist/src/core/deduplication/command-deduplicator.js.map +1 -1
  106. package/dist/src/core/feature-deleter/audit-logger.d.ts +30 -0
  107. package/dist/src/core/feature-deleter/audit-logger.d.ts.map +1 -0
  108. package/dist/src/core/feature-deleter/audit-logger.js +77 -0
  109. package/dist/src/core/feature-deleter/audit-logger.js.map +1 -0
  110. package/dist/src/core/feature-deleter/confirmation-manager.d.ts +39 -0
  111. package/dist/src/core/feature-deleter/confirmation-manager.d.ts.map +1 -0
  112. package/dist/src/core/feature-deleter/confirmation-manager.js +89 -0
  113. package/dist/src/core/feature-deleter/confirmation-manager.js.map +1 -0
  114. package/dist/src/core/feature-deleter/deletion-transaction.d.ts +51 -0
  115. package/dist/src/core/feature-deleter/deletion-transaction.d.ts.map +1 -0
  116. package/dist/src/core/feature-deleter/deletion-transaction.js +185 -0
  117. package/dist/src/core/feature-deleter/deletion-transaction.js.map +1 -0
  118. package/dist/src/core/feature-deleter/git-service.d.ts +43 -0
  119. package/dist/src/core/feature-deleter/git-service.d.ts.map +1 -0
  120. package/dist/src/core/feature-deleter/git-service.js +127 -0
  121. package/dist/src/core/feature-deleter/git-service.js.map +1 -0
  122. package/dist/src/core/feature-deleter/github-service.d.ts +36 -0
  123. package/dist/src/core/feature-deleter/github-service.d.ts.map +1 -0
  124. package/dist/src/core/feature-deleter/github-service.js +102 -0
  125. package/dist/src/core/feature-deleter/github-service.js.map +1 -0
  126. package/dist/src/core/feature-deleter/index.d.ts +35 -0
  127. package/dist/src/core/feature-deleter/index.d.ts.map +1 -0
  128. package/dist/src/core/feature-deleter/index.js +199 -0
  129. package/dist/src/core/feature-deleter/index.js.map +1 -0
  130. package/dist/src/core/feature-deleter/types.d.ts +179 -0
  131. package/dist/src/core/feature-deleter/types.d.ts.map +1 -0
  132. package/dist/src/core/feature-deleter/types.js +7 -0
  133. package/dist/src/core/feature-deleter/types.js.map +1 -0
  134. package/dist/src/core/feature-deleter/validator.d.ts +46 -0
  135. package/dist/src/core/feature-deleter/validator.d.ts.map +1 -0
  136. package/dist/src/core/feature-deleter/validator.js +231 -0
  137. package/dist/src/core/feature-deleter/validator.js.map +1 -0
  138. package/dist/src/core/hooks/HealthReporter.js +1 -1
  139. package/dist/src/core/hooks/HealthReporter.js.map +1 -1
  140. package/dist/src/core/hooks/HookAutoFixer.js +1 -1
  141. package/dist/src/core/hooks/HookAutoFixer.js.map +1 -1
  142. package/dist/src/core/hooks/HookScanner.js +1 -1
  143. package/dist/src/core/hooks/HookScanner.js.map +1 -1
  144. package/dist/src/core/i18n/language-manager.js +1 -1
  145. package/dist/src/core/i18n/language-manager.js.map +1 -1
  146. package/dist/src/core/i18n/locale-manager.js +1 -1
  147. package/dist/src/core/i18n/locale-manager.js.map +1 -1
  148. package/dist/src/core/i18n/system-prompt-injector.js +1 -1
  149. package/dist/src/core/i18n/system-prompt-injector.js.map +1 -1
  150. package/dist/src/core/increment/ac-status-manager.d.ts.map +1 -1
  151. package/dist/src/core/increment/ac-status-manager.js +18 -4
  152. package/dist/src/core/increment/ac-status-manager.js.map +1 -1
  153. package/dist/src/core/increment/active-increment-manager.js +1 -1
  154. package/dist/src/core/increment/active-increment-manager.js.map +1 -1
  155. package/dist/src/core/increment/completion-validator.js +1 -1
  156. package/dist/src/core/increment/completion-validator.js.map +1 -1
  157. package/dist/src/core/increment/conflict-resolver.js +1 -1
  158. package/dist/src/core/increment/conflict-resolver.js.map +1 -1
  159. package/dist/src/core/increment/desync-detector.js +1 -1
  160. package/dist/src/core/increment/desync-detector.js.map +1 -1
  161. package/dist/src/core/increment/discipline-checker.js +1 -1
  162. package/dist/src/core/increment/discipline-checker.js.map +1 -1
  163. package/dist/src/core/increment/duplicate-detector.js +1 -1
  164. package/dist/src/core/increment/duplicate-detector.js.map +1 -1
  165. package/dist/src/core/increment/increment-archiver.js +1 -1
  166. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  167. package/dist/src/core/increment/increment-reopener.js +1 -1
  168. package/dist/src/core/increment/increment-reopener.js.map +1 -1
  169. package/dist/src/core/increment/metadata-manager.js +1 -1
  170. package/dist/src/core/increment/metadata-manager.js.map +1 -1
  171. package/dist/src/core/increment/metadata-validator.js +1 -1
  172. package/dist/src/core/increment/metadata-validator.js.map +1 -1
  173. package/dist/src/core/increment/recent-work-scanner.js +1 -1
  174. package/dist/src/core/increment/recent-work-scanner.js.map +1 -1
  175. package/dist/src/core/increment/spec-frontmatter-updater.js +1 -1
  176. package/dist/src/core/increment/spec-frontmatter-updater.js.map +1 -1
  177. package/dist/src/core/increment/status-auto-transition.js +1 -1
  178. package/dist/src/core/increment/status-auto-transition.js.map +1 -1
  179. package/dist/src/core/increment-status.js +1 -1
  180. package/dist/src/core/increment-status.js.map +1 -1
  181. package/dist/src/core/living-docs/content-distributor.js +1 -1
  182. package/dist/src/core/living-docs/content-distributor.js.map +1 -1
  183. package/dist/src/core/living-docs/cross-linker.js +1 -1
  184. package/dist/src/core/living-docs/cross-linker.js.map +1 -1
  185. package/dist/src/core/living-docs/feature-archiver.js +1 -1
  186. package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
  187. package/dist/src/core/living-docs/feature-id-manager.js +1 -1
  188. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
  189. package/dist/src/core/living-docs/hierarchy-mapper.js +1 -1
  190. package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
  191. package/dist/src/core/living-docs/living-docs-sync.d.ts +14 -0
  192. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  193. package/dist/src/core/living-docs/living-docs-sync.js +72 -13
  194. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  195. package/dist/src/core/living-docs/project-detector.js +1 -1
  196. package/dist/src/core/living-docs/project-detector.js.map +1 -1
  197. package/dist/src/core/living-docs/task-project-specific-generator.js +1 -1
  198. package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -1
  199. package/dist/src/core/logging/prompt-logger.js +1 -1
  200. package/dist/src/core/logging/prompt-logger.js.map +1 -1
  201. package/dist/src/core/plugin-loader.js +1 -1
  202. package/dist/src/core/plugin-loader.js.map +1 -1
  203. package/dist/src/core/project-manager.js +1 -1
  204. package/dist/src/core/project-manager.js.map +1 -1
  205. package/dist/src/core/qa/qa-runner.js +1 -1
  206. package/dist/src/core/qa/qa-runner.js.map +1 -1
  207. package/dist/src/core/repo-structure/folder-detector.js +1 -1
  208. package/dist/src/core/repo-structure/folder-detector.js.map +1 -1
  209. package/dist/src/core/repo-structure/setup-state-manager.js +1 -1
  210. package/dist/src/core/repo-structure/setup-state-manager.js.map +1 -1
  211. package/dist/src/core/spec-detector.js +1 -1
  212. package/dist/src/core/spec-detector.js.map +1 -1
  213. package/dist/src/core/specs/spec-metadata-manager.js +1 -1
  214. package/dist/src/core/specs/spec-metadata-manager.js.map +1 -1
  215. package/dist/src/core/status-line/status-line-updater.js +1 -1
  216. package/dist/src/core/status-line/status-line-updater.js.map +1 -1
  217. package/dist/src/core/status-line-validator.js +1 -1
  218. package/dist/src/core/status-line-validator.js.map +1 -1
  219. package/dist/src/core/sync/bidirectional-engine.js +1 -1
  220. package/dist/src/core/sync/bidirectional-engine.js.map +1 -1
  221. package/dist/src/core/sync/profile-manager.js +1 -1
  222. package/dist/src/core/sync/profile-manager.js.map +1 -1
  223. package/dist/src/core/sync/project-context.js +1 -1
  224. package/dist/src/core/sync/project-context.js.map +1 -1
  225. package/dist/src/core/sync/sync-event-logger.js +1 -1
  226. package/dist/src/core/sync/sync-event-logger.js.map +1 -1
  227. package/dist/src/core/types/config.js +1 -1
  228. package/dist/src/core/types/config.js.map +1 -1
  229. package/dist/src/core/us-completion-detector.d.ts +124 -0
  230. package/dist/src/core/us-completion-detector.d.ts.map +1 -0
  231. package/dist/src/core/us-completion-detector.js +270 -0
  232. package/dist/src/core/us-completion-detector.js.map +1 -0
  233. package/dist/src/core/utils/permission-checker.js +1 -1
  234. package/dist/src/core/utils/permission-checker.js.map +1 -1
  235. package/dist/src/core/workflow/autonomous-executor.js +1 -1
  236. package/dist/src/core/workflow/autonomous-executor.js.map +1 -1
  237. package/dist/src/core/workflow/backlog-scanner.js +1 -1
  238. package/dist/src/core/workflow/backlog-scanner.js.map +1 -1
  239. package/dist/src/core/workflow/cost-estimator.js +1 -1
  240. package/dist/src/core/workflow/cost-estimator.js.map +1 -1
  241. package/dist/src/core/workflow/state-manager.js +1 -1
  242. package/dist/src/core/workflow/state-manager.js.map +1 -1
  243. package/dist/src/importers/duplicate-detector.js +1 -1
  244. package/dist/src/importers/duplicate-detector.js.map +1 -1
  245. package/dist/src/importers/item-converter.js +1 -1
  246. package/dist/src/importers/item-converter.js.map +1 -1
  247. package/dist/src/init/architecture/types.d.ts +33 -140
  248. package/dist/src/init/architecture/types.d.ts.map +1 -1
  249. package/dist/src/init/compliance/types.d.ts +30 -27
  250. package/dist/src/init/compliance/types.d.ts.map +1 -1
  251. package/dist/src/init/repo/types.d.ts +11 -34
  252. package/dist/src/init/repo/types.d.ts.map +1 -1
  253. package/dist/src/init/research/src/config/types.d.ts +15 -82
  254. package/dist/src/init/research/src/config/types.d.ts.map +1 -1
  255. package/dist/src/init/research/types.d.ts +38 -93
  256. package/dist/src/init/research/types.d.ts.map +1 -1
  257. package/dist/src/init/team/types.d.ts +4 -42
  258. package/dist/src/init/team/types.d.ts.map +1 -1
  259. package/dist/src/integrations/jira/jira-incremental-mapper.d.ts +1 -1
  260. package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
  261. package/dist/src/integrations/jira/jira-incremental-mapper.js +3 -3
  262. package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
  263. package/dist/src/living-docs/fs-id-allocator.js +1 -1
  264. package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
  265. package/dist/src/living-docs/id-registry.js +1 -1
  266. package/dist/src/living-docs/id-registry.js.map +1 -1
  267. package/dist/src/sync/external-item-sync-service.js +1 -1
  268. package/dist/src/sync/external-item-sync-service.js.map +1 -1
  269. package/dist/src/sync/sync-metadata.js +1 -1
  270. package/dist/src/sync/sync-metadata.js.map +1 -1
  271. package/dist/src/utils/agents-md-compiler.js +1 -1
  272. package/dist/src/utils/agents-md-compiler.js.map +1 -1
  273. package/dist/src/utils/auto-install.js +1 -1
  274. package/dist/src/utils/auto-install.js.map +1 -1
  275. package/dist/src/utils/cost-reporter.js +1 -1
  276. package/dist/src/utils/cost-reporter.js.map +1 -1
  277. package/dist/src/utils/docs-preview/config-generator.js +1 -1
  278. package/dist/src/utils/docs-preview/config-generator.js.map +1 -1
  279. package/dist/src/utils/docs-preview/docusaurus-setup.js +1 -1
  280. package/dist/src/utils/docs-preview/docusaurus-setup.js.map +1 -1
  281. package/dist/src/utils/docs-preview/package-installer.js +1 -1
  282. package/dist/src/utils/docs-preview/package-installer.js.map +1 -1
  283. package/dist/src/utils/docs-preview/sidebar-builder.js +1 -1
  284. package/dist/src/utils/docs-preview/sidebar-builder.js.map +1 -1
  285. package/dist/src/utils/env-file-generator.js +1 -1
  286. package/dist/src/utils/env-file-generator.js.map +1 -1
  287. package/dist/src/utils/external-resource-validator.js +1 -1
  288. package/dist/src/utils/external-resource-validator.js.map +1 -1
  289. package/dist/src/utils/fs-native.d.ts +51 -5
  290. package/dist/src/utils/fs-native.d.ts.map +1 -1
  291. package/dist/src/utils/fs-native.js +100 -5
  292. package/dist/src/utils/fs-native.js.map +1 -1
  293. package/dist/src/utils/plugin-validator.js +1 -1
  294. package/dist/src/utils/plugin-validator.js.map +1 -1
  295. package/dist/src/utils/project-detection.js +1 -1
  296. package/dist/src/utils/project-detection.js.map +1 -1
  297. package/dist/src/utils/project-validator.js +1 -1
  298. package/dist/src/utils/project-validator.js.map +1 -1
  299. package/dist/src/utils/spec-parser.js +1 -1
  300. package/dist/src/utils/spec-parser.js.map +1 -1
  301. package/dist/src/utils/spec-splitter.js +1 -1
  302. package/dist/src/utils/spec-splitter.js.map +1 -1
  303. package/dist/src/validators/ac-coverage-validator.js +1 -1
  304. package/dist/src/validators/ac-coverage-validator.js.map +1 -1
  305. package/package.json +5 -6
  306. package/plugins/specweave/agents/code-standards-detective/AGENT.md +47 -0
  307. package/plugins/specweave/agents/docs-writer/AGENT.md +134 -1
  308. package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +1 -0
  309. package/plugins/specweave/agents/infrastructure/AGENT.md +48 -1
  310. package/plugins/specweave/agents/performance/AGENT.md +46 -0
  311. package/plugins/specweave/agents/pm/AGENT.md +115 -3
  312. package/plugins/specweave/agents/qa-lead/AGENT.md +40 -1
  313. package/plugins/specweave/agents/reflective-reviewer/AGENT.md +5 -0
  314. package/plugins/specweave/agents/security/AGENT.md +45 -0
  315. package/plugins/specweave/agents/tdd-orchestrator/AGENT.md +128 -1
  316. package/plugins/specweave/agents/tech-lead/AGENT.md +138 -1
  317. package/plugins/specweave/agents/translator/AGENT.md +132 -0
  318. package/plugins/specweave/commands/specweave-sync-progress.md +616 -0
  319. package/plugins/specweave/hooks/hooks.json +0 -9
  320. package/plugins/specweave/hooks/post-increment-completion.sh +133 -0
  321. package/plugins/specweave/hooks/post-metadata-change.sh +28 -23
  322. package/plugins/specweave/hooks/post-task-completion.sh +7 -0
  323. package/plugins/specweave/hooks/pre-edit-write-consolidated.sh +44 -7
  324. package/plugins/specweave/hooks/shared/bulk-operation-detector.sh +167 -0
  325. package/plugins/specweave/lib/hooks/consolidated-sync.js +19 -2
  326. package/plugins/specweave/lib/hooks/us-completion-orchestrator.js +135 -0
  327. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +18 -4
  328. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -1
  329. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +1 -1
  330. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -1
  331. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +1 -1
  332. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -1
  333. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +1 -1
  334. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
  335. package/plugins/specweave/skills/code-reviewer/SKILL.md +1 -1
  336. package/plugins/specweave/skills/progress-sync/SKILL.md +405 -0
  337. package/plugins/specweave-ado/lib/ado-project-detector.js +1 -1
  338. package/plugins/specweave-ado/lib/ado-project-detector.ts +1 -1
  339. package/plugins/specweave-ado/lib/conflict-resolver.js +1 -1
  340. package/plugins/specweave-ado/lib/conflict-resolver.ts +1 -1
  341. package/plugins/specweave-backend/agents/database-optimizer/AGENT.md +1 -1
  342. package/plugins/specweave-frontend/agents/frontend-architect/AGENT.md +5 -0
  343. package/plugins/specweave-github/.claude-plugin/plugin.json +1 -15
  344. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +186 -0
  345. package/plugins/specweave-github/hooks/README.md +34 -25
  346. package/plugins/specweave-github/lib/CodeValidator.js +1 -1
  347. package/plugins/specweave-github/lib/CodeValidator.ts +2 -2
  348. package/plugins/specweave-github/lib/ThreeLayerSyncManager.js +1 -1
  349. package/plugins/specweave-github/lib/ThreeLayerSyncManager.ts +1 -1
  350. package/plugins/specweave-github/lib/github-client-v2.js +13 -1
  351. package/plugins/specweave-github/lib/github-client-v2.ts +17 -1
  352. package/plugins/specweave-github/lib/github-issue-updater.js +1 -1
  353. package/plugins/specweave-github/lib/github-issue-updater.ts +1 -1
  354. package/plugins/specweave-github/lib/github-sync-bidirectional.js +1 -1
  355. package/plugins/specweave-github/lib/github-sync-bidirectional.ts +1 -1
  356. package/plugins/specweave-github/lib/github-sync-increment-changes.js +1 -1
  357. package/plugins/specweave-github/lib/github-sync-increment-changes.ts +1 -1
  358. package/plugins/specweave-github/lib/user-story-issue-builder.js +4 -4
  359. package/plugins/specweave-github/lib/user-story-issue-builder.ts +7 -6
  360. package/plugins/specweave-infrastructure/agents/devops/AGENT.md +48 -1
  361. package/plugins/specweave-infrastructure/agents/network-engineer/AGENT.md +6 -1
  362. package/plugins/specweave-infrastructure/agents/observability-engineer/AGENT.md +6 -1
  363. package/plugins/specweave-infrastructure/agents/performance-engineer/AGENT.md +6 -1
  364. package/plugins/specweave-infrastructure/agents/sre/AGENT.md +5 -0
  365. package/plugins/specweave-jira/lib/jira-epic-sync.js +1 -1
  366. package/plugins/specweave-jira/lib/jira-epic-sync.ts +1 -1
  367. package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +5 -0
  368. package/plugins/specweave-kubernetes/agents/kubernetes-architect/AGENT.md +47 -2
  369. package/plugins/specweave-ml/agents/data-scientist/AGENT.md +1 -1
  370. package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +5 -0
  371. package/plugins/specweave-ml/agents/mlops-engineer/AGENT.md +6 -1
  372. package/plugins/specweave-payments/agents/payment-integration/AGENT.md +1 -1
  373. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +138 -0
  374. package/plugins/specweave-ado/hooks/hooks.json +0 -15
  375. package/plugins/specweave-github/hooks/hooks.json +0 -15
  376. package/plugins/specweave-jira/hooks/hooks.json +0 -15
  377. package/plugins/specweave-release/hooks/hooks.json +0 -15
@@ -25,6 +25,32 @@ fi
25
25
  PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)"
26
26
  INCREMENT_DIR="$PROJECT_ROOT/.specweave/increments/$INCREMENT_ID"
27
27
 
28
+ # ============================================================================
29
+ # RECURSION PREVENTION (v0.26.1 - CRITICAL)
30
+ # ============================================================================
31
+ # PROBLEM: consolidated-sync.js does Edit/Write operations which trigger hooks.
32
+ # If no guard exists, those hooks will run full sync → more Edit/Write → INFINITE LOOP.
33
+ #
34
+ # SOLUTION: Create recursion guard file BEFORE calling any sync scripts.
35
+ # Other hooks check this file and exit early if it exists.
36
+ #
37
+ # See: ADR-0073 (Hook Recursion Prevention Strategy)
38
+ # See: .specweave/increments/0051-*/reports/GITHUB-COMMENT-RECURSION-ROOT-CAUSE-2025-11-24.md
39
+
40
+ RECURSION_GUARD_FILE="$PROJECT_ROOT/.specweave/state/.hook-recursion-guard"
41
+
42
+ if [[ -f "$RECURSION_GUARD_FILE" ]]; then
43
+ # Silent exit - we're already inside a hook chain
44
+ exit 0
45
+ fi
46
+
47
+ # Create guard file (atomic operation)
48
+ mkdir -p "$PROJECT_ROOT/.specweave/state" 2>/dev/null || true
49
+ touch "$RECURSION_GUARD_FILE"
50
+
51
+ # Ensure guard file is ALWAYS removed when script exits (even on error)
52
+ trap 'rm -f "$RECURSION_GUARD_FILE" 2>/dev/null || true' EXIT SIGINT SIGTERM
53
+
28
54
  # Check if increment exists
29
55
  if [ ! -d "$INCREMENT_DIR" ]; then
30
56
  echo "⚠️ $HOOK_NAME: Increment $INCREMENT_ID not found" >&2
@@ -233,4 +259,111 @@ else
233
259
  echo ""
234
260
  fi
235
261
 
262
+ # ============================================================================
263
+ # GITHUB SYNC (v0.26.1 - CRITICAL FIX)
264
+ # ============================================================================
265
+ # After living docs sync, create GitHub issues for user stories.
266
+ # This is the AUTOMATIC GitHub sync that runs once per increment completion.
267
+ #
268
+ # CRITICAL: This was MISSING in v0.26.0, causing GitHub issues to NEVER be
269
+ # created automatically. The consolidated-sync.js has the full logic for:
270
+ # - Creating GitHub issues for user stories (with 3-layer idempotency)
271
+ # - Syncing task completion comments to existing issues
272
+ # - Format preservation sync for external tools
273
+ #
274
+ # GATE SYSTEM (4 gates - all checked inside consolidated-sync.js):
275
+ # - GATE 1: canUpsertInternalItems (living docs sync enabled)
276
+ # - GATE 2: canUpdateExternalItems (external tool sync enabled)
277
+ # - GATE 3: autoSyncOnCompletion (automatic sync enabled)
278
+ # - GATE 4: sync.github.enabled (GitHub-specific sync enabled)
279
+ #
280
+ # RECURSION SAFETY:
281
+ # - Recursion guard created at script start (line 49)
282
+ # - consolidated-sync.js does Edit/Write operations
283
+ # - Other hooks see the guard and exit early
284
+ # - Guard removed via trap on script exit
285
+ #
286
+ # USER PROJECT COMPATIBILITY:
287
+ # - Script detection works for: development, dist/, node_modules/, marketplace
288
+ # - Works in both SpecWeave framework repo AND user projects using SpecWeave
289
+ # - GITHUB_TOKEN loaded from project's .env file
290
+ #
291
+ # See: Root cause analysis in initial implementation planning
292
+ # See: ADR-0073 (Hook Recursion Prevention Strategy)
293
+
294
+ if command -v node &> /dev/null; then
295
+ echo ""
296
+ echo "🔗 Creating GitHub issues for user stories..."
297
+
298
+ # ========================================================================
299
+ # LOCATE CONSOLIDATED SYNC SCRIPT
300
+ # ========================================================================
301
+ # Find consolidated-sync.js in order of preference:
302
+ # 1. In-place compiled (development, esbuild output)
303
+ # 2. Local dist (development, tsc output)
304
+ # 3. node_modules (installed as dependency) ← USER PROJECTS
305
+ # 4. Plugin marketplace (Claude Code global installation)
306
+
307
+ CONSOLIDATED_SCRIPT=""
308
+ if [ -f "$PROJECT_ROOT/plugins/specweave/lib/hooks/consolidated-sync.js" ]; then
309
+ # Development: Use in-place compiled hooks (esbuild, not tsc)
310
+ CONSOLIDATED_SCRIPT="$PROJECT_ROOT/plugins/specweave/lib/hooks/consolidated-sync.js"
311
+ echo " 🔧 Using in-place compiled hook (development mode)"
312
+ elif [ -f "$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/consolidated-sync.js" ]; then
313
+ # Development: Use project's compiled files (has node_modules)
314
+ CONSOLIDATED_SCRIPT="$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/consolidated-sync.js"
315
+ echo " 🔧 Using local dist (development mode)"
316
+ elif [ -f "$PROJECT_ROOT/node_modules/specweave/dist/plugins/specweave/lib/hooks/consolidated-sync.js" ]; then
317
+ # Installed as dependency: Use node_modules version (MOST USER PROJECTS)
318
+ CONSOLIDATED_SCRIPT="$PROJECT_ROOT/node_modules/specweave/dist/plugins/specweave/lib/hooks/consolidated-sync.js"
319
+ echo " 📦 Using node_modules version"
320
+ elif [ -n "${CLAUDE_PLUGIN_ROOT}" ] && [ -f "${CLAUDE_PLUGIN_ROOT}/lib/hooks/consolidated-sync.js" ]; then
321
+ # Fallback: Plugin marketplace (may fail if deps missing)
322
+ CONSOLIDATED_SCRIPT="${CLAUDE_PLUGIN_ROOT}/lib/hooks/consolidated-sync.js"
323
+ echo " 🌐 Using plugin marketplace version"
324
+ fi
325
+
326
+ # ========================================================================
327
+ # EXECUTE GITHUB SYNC
328
+ # ========================================================================
329
+ # Run consolidated sync to create GitHub issues and sync task completion.
330
+ # Non-blocking: Errors logged but don't crash hook (increment already closed)
331
+ #
332
+ # CRITICAL: Do NOT set SKIP_GITHUB_SYNC=true here!
333
+ # That flag is ONLY for post-task-completion hook to prevent duplicate comments.
334
+ # On increment completion, we WANT GitHub sync to run.
335
+
336
+ if [ -n "$CONSOLIDATED_SCRIPT" ]; then
337
+ # Load GITHUB_TOKEN from .env for gh CLI authentication
338
+ if [ -f "$PROJECT_ROOT/.env" ]; then
339
+ # Extract GITHUB_TOKEN from .env (handles various formats)
340
+ GITHUB_TOKEN_FROM_ENV=$(grep -E '^GITHUB_TOKEN=' "$PROJECT_ROOT/.env" 2>/dev/null | head -1 | cut -d'=' -f2- | sed 's/^["'\'']//' | sed 's/["'\'']$//')
341
+ if [ -n "$GITHUB_TOKEN_FROM_ENV" ]; then
342
+ export GITHUB_TOKEN="$GITHUB_TOKEN_FROM_ENV"
343
+ echo " 🔑 GitHub token loaded from .env"
344
+ fi
345
+ fi
346
+
347
+ # Run consolidated sync (synchronous - user sees immediate feedback)
348
+ # This creates GitHub issues, syncs comments, and performs format preservation
349
+ if (cd "$PROJECT_ROOT" && node "$CONSOLIDATED_SCRIPT" "$INCREMENT_ID") 2>&1; then
350
+ echo " ✅ GitHub sync complete"
351
+ echo ""
352
+ else
353
+ echo " ⚠️ Failed to sync GitHub issues (non-blocking - you can run /specweave-github:sync manually)" >&2
354
+ echo " 💡 Check that sync.github.enabled=true in .specweave/config.json" >&2
355
+ echo ""
356
+ fi
357
+ else
358
+ echo " ⚠️ consolidated-sync.js not found in any location - skipping GitHub sync" >&2
359
+ echo " 💡 To manually sync: /specweave-github:sync" >&2
360
+ echo ""
361
+ fi
362
+ else
363
+ echo ""
364
+ echo " ⚠️ Node.js not found - skipping GitHub sync" >&2
365
+ echo " 💡 Install Node.js to enable automatic GitHub sync" >&2
366
+ echo ""
367
+ fi
368
+
236
369
  exit 0
@@ -61,6 +61,24 @@ fi
61
61
  # Ensure logs directory exists
62
62
  mkdir -p "$LOGS_DIR" 2>/dev/null || true
63
63
 
64
+ # ============================================================================
65
+ # READ STDIN (v0.26.1 - CRITICAL FIX)
66
+ # ============================================================================
67
+ # PostToolUse hooks receive JSON data from Claude Code via STDIN, NOT env vars!
68
+ # This was the critical bug: hook was looking for environment variables that don't exist.
69
+ #
70
+ # Example STDIN data:
71
+ # {"tool": "Edit", "tool_input": {"file_path": "/path/to/file.md", ...}}
72
+ # {"tool": "Write", "tool_input": {"file_path": "/path/to/file.md", ...}}
73
+
74
+ STDIN_DATA=$(mktemp)
75
+ cat > "$STDIN_DATA"
76
+
77
+ echo "[$(date)] post-metadata-change: Hook fired" >> "$DEBUG_LOG" 2>/dev/null || true
78
+ echo "[$(date)] Input JSON:" >> "$DEBUG_LOG" 2>/dev/null || true
79
+ cat "$STDIN_DATA" >> "$DEBUG_LOG" 2>/dev/null || true
80
+ echo "" >> "$DEBUG_LOG" 2>/dev/null || true
81
+
64
82
  # ============================================================================
65
83
  # EARLY EXIT OPTIMIZATION (v0.25.0): Ultra-Fast Rejection of Non-Metadata Changes
66
84
  # ============================================================================
@@ -68,37 +86,24 @@ mkdir -p "$LOGS_DIR" 2>/dev/null || true
68
86
  # 99.9% of Edit/Write operations are NOT metadata.json.
69
87
  # Do fastest possible check first to minimize overhead.
70
88
 
71
- # Quick check: If TOOL_USE_CONTENT doesn't contain "metadata.json", exit immediately
72
- if [[ -n "${TOOL_USE_CONTENT:-}" ]] && [[ "$TOOL_USE_CONTENT" != *"metadata.json"* ]]; then
89
+ # Quick check: If STDIN doesn't contain "metadata.json", exit immediately
90
+ if ! grep -q "metadata\.json" "$STDIN_DATA" 2>/dev/null; then
91
+ echo "[$(date)] post-metadata-change: Not metadata.json - exiting" >> "$DEBUG_LOG" 2>/dev/null || true
92
+ rm -f "$STDIN_DATA"
73
93
  exit 0 # Fast path: Not metadata.json
74
94
  fi
75
95
 
76
- # Quick check: If TOOL_USE_ARGS doesn't contain "metadata.json", exit immediately
77
- if [[ -n "${TOOL_USE_ARGS:-}" ]] && [[ "$TOOL_USE_ARGS" != *"metadata.json"* ]]; then
78
- exit 0 # Fast path: Not metadata.json
79
- fi
96
+ echo "[$(date)] post-metadata-change: metadata.json detected in input" >> "$DEBUG_LOG" 2>/dev/null || true
80
97
 
81
98
  # ============================================================================
82
- # STANDARD FILE DETECTION (Only if quick checks passed)
99
+ # EXTRACT FILE PATH FROM STDIN JSON
83
100
  # ============================================================================
84
101
 
85
- # Extract modified file from environment variables (Claude Code provides this)
86
- MODIFIED_FILE=""
87
-
88
- # Method 1: TOOL_USE_CONTENT environment variable (primary for Write)
89
- if [[ -n "${TOOL_USE_CONTENT:-}" ]]; then
90
- MODIFIED_FILE="$TOOL_USE_CONTENT"
91
- fi
92
-
93
- # Method 2: TOOL_RESULT environment variable (fallback)
94
- if [[ -z "$MODIFIED_FILE" ]] && [[ -n "${TOOL_RESULT:-}" ]]; then
95
- MODIFIED_FILE=$(echo "$TOOL_RESULT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
96
- fi
102
+ # Parse file_path from JSON (handles both Edit and Write tool formats)
103
+ MODIFIED_FILE=$(grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' "$STDIN_DATA" | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
97
104
 
98
- # Method 3: Parse tool use arguments (last resort for Edit)
99
- if [[ -z "$MODIFIED_FILE" ]] && [[ -n "${TOOL_USE_ARGS:-}" ]]; then
100
- MODIFIED_FILE=$(echo "$TOOL_USE_ARGS" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
101
- fi
105
+ # Clean up temp file
106
+ rm -f "$STDIN_DATA"
102
107
 
103
108
  echo "[$(date)] post-metadata-change: Detected file: ${MODIFIED_FILE:-<none>}" >> "$DEBUG_LOG" 2>/dev/null || true
104
109
 
@@ -455,6 +455,13 @@ fi
455
455
  # This prevents 27 duplicate comments (see root cause analysis)
456
456
  export SKIP_GITHUB_SYNC=true
457
457
 
458
+ # EMERGENCY FIX (v0.25.1): Skip US sync in post-task-completion hook
459
+ # CRITICAL: US sync triggers livingDocsSync.syncIncrement() which calls
460
+ # syncToExternalTools() without respecting SKIP_GITHUB_SYNC, causing
461
+ # Edit/Write operations that trigger new hook chains → infinite recursion → crash
462
+ # See: ROOT-CAUSE-ANALYSIS-TODOWRITE-CRASH-2025-11-24.md
463
+ export SKIP_US_SYNC=true
464
+
458
465
  # Run consolidated sync (single Node.js process handles ALL operations)
459
466
  if (cd "$PROJECT_ROOT" && node "$CONSOLIDATED_SCRIPT" "$CURRENT_INCREMENT") >> "$DEBUG_LOG" 2>&1; then
460
467
  echo "[$(date)] ✅ Consolidated sync completed" >> "$DEBUG_LOG" 2>/dev/null || true
@@ -3,17 +3,23 @@
3
3
  # Pre-Edit/Write Consolidated Hook: Capture File Path BEFORE Edit/Write Executes
4
4
  #
5
5
  # Purpose: Unified hook for both Edit and Write tools
6
- # Strategy: Detect file path, signal post-hook if it's a spec/tasks file
6
+ # Strategy: Hierarchical early exit for maximum performance
7
7
  #
8
8
  # CONSOLIDATION (v0.25.0):
9
9
  # - Replaces pre-edit-spec.sh and pre-write-spec.sh (identical code)
10
10
  # - Reduces hook overhead by 50% (2 pre-hooks → 1)
11
11
  # - Single point of maintenance
12
12
  #
13
- # TIER 2 COORDINATION:
14
- # 1. Extract file_path from TOOL_USE_ARGS (reliable in PreToolUse)
15
- # 2. If it's spec.md/tasks.md in increments folder, signal PostToolUse hook
16
- # 3. Write file path to .pending-status-update for PostToolUse to consume
13
+ # HIERARCHICAL EARLY EXIT (v0.26.1):
14
+ # - Tier 0: TOOL_USE_ARGS check (< 1ms) - Exit if empty (Claude Code bug)
15
+ # - Tier 1: .specweave/ path check (< 5ms) - Exit if not SpecWeave file
16
+ # - Tier 2: Active increment check (< 10ms) - Exit if archived/completed
17
+ # - Tier 3: Full processing - AC sync, status line, living docs
18
+ #
19
+ # GRACEFUL DEGRADATION:
20
+ # - PreToolUse works if TOOL_USE_ARGS is available (fast filtering)
21
+ # - PostToolUse fallback uses mtime if PreToolUse disabled (slower but works)
22
+ # - Self-tuning: Disables PreToolUse if consistently useless
17
23
  #
18
24
  # Architecture:
19
25
  # PreToolUse:Edit/Write → pre-edit-write-consolidated.sh (this file)
@@ -22,8 +28,8 @@
22
28
  # ↓ read by
23
29
  # PostToolUse:Edit/Write → post-edit-write-consolidated.sh
24
30
  #
25
- # Version: v0.25.0 (HOOK CONSOLIDATION)
26
- # Date: 2025-11-23
31
+ # Version: v0.26.1 (HIERARCHICAL EARLY EXIT)
32
+ # Date: 2025-11-24
27
33
  #
28
34
  # EMERGENCY FIXES (v0.24.3):
29
35
  # - Kill switch: Set SPECWEAVE_DISABLE_HOOKS=1 to disable ALL hooks
@@ -34,6 +40,37 @@
34
40
  # EMERGENCY FIX: Remove set -e - it causes Claude Code crashes!
35
41
  set +e
36
42
 
43
+ # ============================================================================
44
+ # TIER 0: ULTRA-FAST REJECTION (< 1ms) - v0.26.1 CRITICAL FIX
45
+ # ============================================================================
46
+ # Problem: Claude Code doesn't pass TOOL_USE_ARGS to PreToolUse hooks (bug)
47
+ # Result: PreToolUse hooks are "blind" - can't filter files, fire for everything
48
+ # Impact: Massive overhead (1 pre-hook per Edit/Write on ANY file)
49
+ #
50
+ # Solution: Exit immediately if TOOL_USE_ARGS is empty
51
+ # - No find_project_root, no file path extraction, no processing
52
+ # - Eliminates 33% of hook overhead (1 of 3 hooks per operation)
53
+ # - Falls back to PostToolUse mtime detection (slower but works)
54
+ #
55
+ # See: ADR-0128 (Hierarchical Hook Early Exit Strategy)
56
+
57
+ if [[ -z "${TOOL_USE_ARGS:-}" ]]; then
58
+ # Telemetry: Track PreToolUse disabled events (lightweight counter)
59
+ # This helps us understand if Claude Code ever fixes the TOOL_USE_ARGS bug
60
+ TELEMETRY_DIR="${HOME}/.claude/.specweave-telemetry"
61
+ mkdir -p "$TELEMETRY_DIR" 2>/dev/null || true
62
+ echo "$(date -u +%s)" >> "$TELEMETRY_DIR/pretooluse-disabled.log" 2>/dev/null || true
63
+
64
+ # Silent exit - PreToolUse is useless without TOOL_USE_ARGS
65
+ # PostToolUse will handle via mtime fallback
66
+ exit 0
67
+ fi
68
+
69
+ # Telemetry: Track PreToolUse enabled events (TOOL_USE_ARGS available)
70
+ TELEMETRY_DIR="${HOME}/.claude/.specweave-telemetry"
71
+ mkdir -p "$TELEMETRY_DIR" 2>/dev/null || true
72
+ echo "$(date -u +%s)" >> "$TELEMETRY_DIR/pretooluse-enabled.log" 2>/dev/null || true
73
+
37
74
  # Find project root (must be BEFORE recursion guard to get PROJECT_ROOT)
38
75
  find_project_root() {
39
76
  local dir="$PWD"
@@ -0,0 +1,167 @@
1
+ #!/bin/bash
2
+ # Bulk Operation Detector (v0.26.0)
3
+ #
4
+ # Detects bulk edit operations (5+ edits in 10 seconds) and triggers batch mode.
5
+ # Part of ADR-0130: Hook Bulk Operation Detection and Batching
6
+ #
7
+ # Usage:
8
+ # source bulk-operation-detector.sh
9
+ # BULK_STATUS=$(detect_bulk_operation "$INCREMENT_ID")
10
+ #
11
+ # if [ "$BULK_STATUS" = "BULK_MODE_DETECTED" ]; then
12
+ # # Skip individual hook, batch job will run later
13
+ # exit 0
14
+ # fi
15
+
16
+ # Configuration
17
+ BULK_THRESHOLD=${SPECWEAVE_BULK_THRESHOLD:-5} # 5+ operations = bulk mode
18
+ BULK_WINDOW=${SPECWEAVE_BULK_WINDOW:-10} # seconds
19
+ IDLE_DELAY=${SPECWEAVE_IDLE_DELAY:-5} # seconds before batch execution
20
+
21
+ # State files
22
+ STATE_DIR="$PROJECT_ROOT/.specweave/state"
23
+ OPERATION_COUNTER="$STATE_DIR/.hook-operation-counter"
24
+ OPERATION_TIMESTAMP="$STATE_DIR/.hook-operation-timestamp"
25
+
26
+ # Ensure state directory exists
27
+ mkdir -p "$STATE_DIR"
28
+
29
+ ##
30
+ # Detect bulk operation
31
+ #
32
+ # Uses sliding window counter to detect operation bursts:
33
+ # - Counts operations within BULK_WINDOW (10 seconds)
34
+ # - If count >= BULK_THRESHOLD (5 operations) → bulk mode
35
+ # - Resets counter after idle period
36
+ #
37
+ # Args:
38
+ # $1 - INCREMENT_ID (optional, for logging)
39
+ #
40
+ # Returns:
41
+ # BULK_MODE_DETECTED - Bulk operation detected, skip individual hook
42
+ # SINGLE_OPERATION - Single operation, run hook normally
43
+ ##
44
+ detect_bulk_operation() {
45
+ local INCREMENT_ID="${1:-unknown}"
46
+ local CURRENT_TIME=$(date +%s)
47
+
48
+ # Read existing counter and timestamp
49
+ local RECENT_OPS=0
50
+ local LAST_OP_TIME=0
51
+
52
+ if [ -f "$OPERATION_COUNTER" ]; then
53
+ RECENT_OPS=$(cat "$OPERATION_COUNTER" 2>/dev/null || echo 0)
54
+ fi
55
+
56
+ if [ -f "$OPERATION_TIMESTAMP" ]; then
57
+ LAST_OP_TIME=$(cat "$OPERATION_TIMESTAMP" 2>/dev/null || echo 0)
58
+ fi
59
+
60
+ # Reset counter if outside window (idle period detected)
61
+ local TIME_SINCE_LAST_OP=$((CURRENT_TIME - LAST_OP_TIME))
62
+ if (( TIME_SINCE_LAST_OP > BULK_WINDOW )); then
63
+ RECENT_OPS=0
64
+ fi
65
+
66
+ # Increment operation counter
67
+ RECENT_OPS=$((RECENT_OPS + 1))
68
+
69
+ # Write atomically (use temp file + rename for atomicity)
70
+ echo "$RECENT_OPS" > "${OPERATION_COUNTER}.tmp"
71
+ mv "${OPERATION_COUNTER}.tmp" "$OPERATION_COUNTER"
72
+
73
+ echo "$CURRENT_TIME" > "${OPERATION_TIMESTAMP}.tmp"
74
+ mv "${OPERATION_TIMESTAMP}.tmp" "$OPERATION_TIMESTAMP"
75
+
76
+ # Bulk operation detected?
77
+ if (( RECENT_OPS >= BULK_THRESHOLD )); then
78
+ # Log bulk mode activation
79
+ local DEBUG_LOG="$PROJECT_ROOT/.specweave/logs/hook-debug.log"
80
+ echo "[$(date)] [BULK] Detected bulk operation for $INCREMENT_ID (op #$RECENT_OPS)" >> "$DEBUG_LOG" 2>/dev/null || true
81
+
82
+ # Schedule batch job (if not already scheduled)
83
+ schedule_batch_job "$INCREMENT_ID"
84
+
85
+ echo "BULK_MODE_DETECTED"
86
+ return 0
87
+ fi
88
+
89
+ # Single operation
90
+ echo "SINGLE_OPERATION"
91
+ return 0
92
+ }
93
+
94
+ ##
95
+ # Schedule batch job
96
+ #
97
+ # Schedules a batch job to run after idle period (IDLE_DELAY seconds).
98
+ # If a batch job is already scheduled, it gets canceled and rescheduled.
99
+ #
100
+ # Args:
101
+ # $1 - INCREMENT_ID
102
+ ##
103
+ schedule_batch_job() {
104
+ local INCREMENT_ID="$1"
105
+ local BATCH_LOCK="$STATE_DIR/.batch-job-${INCREMENT_ID}.lock"
106
+ local DEBUG_LOG="$PROJECT_ROOT/.specweave/logs/hook-debug.log"
107
+
108
+ # Cancel existing batch job (if any)
109
+ if [ -f "$BATCH_LOCK" ]; then
110
+ local OLD_PID=$(cat "$BATCH_LOCK" 2>/dev/null || echo "")
111
+ if [ -n "$OLD_PID" ] && kill -0 "$OLD_PID" 2>/dev/null; then
112
+ kill "$OLD_PID" 2>/dev/null || true
113
+ echo "[$(date)] [BATCH] Canceled previous batch job (PID: $OLD_PID)" >> "$DEBUG_LOG" 2>/dev/null || true
114
+ fi
115
+ rm -f "$BATCH_LOCK"
116
+ fi
117
+
118
+ # Schedule new batch job (background process)
119
+ (
120
+ # Wait for idle period
121
+ sleep "$IDLE_DELAY"
122
+
123
+ # If operation counter still exists → run batched hook
124
+ if [ -f "$OPERATION_COUNTER" ]; then
125
+ local OPERATION_COUNT=$(cat "$OPERATION_COUNTER" 2>/dev/null || echo 0)
126
+
127
+ echo "[$(date)] [BATCH] Idle period detected, running batch job for $INCREMENT_ID ($OPERATION_COUNT ops)" >> "$DEBUG_LOG" 2>/dev/null || true
128
+
129
+ # Clear operation counter (batch job starting)
130
+ rm -f "$OPERATION_COUNTER" "$OPERATION_TIMESTAMP"
131
+
132
+ # Run consolidated hook in batch mode
133
+ bash "$PROJECT_ROOT/plugins/specweave/hooks/post-task-completion.sh" \
134
+ --batch-mode \
135
+ --increment "$INCREMENT_ID" \
136
+ >> "$PROJECT_ROOT/.specweave/logs/batch-jobs.log" 2>&1
137
+
138
+ echo "[$(date)] [BATCH] ✅ Batch job completed for $INCREMENT_ID" >> "$DEBUG_LOG" 2>/dev/null || true
139
+ else
140
+ echo "[$(date)] [BATCH] Operation counter cleared before batch job ran (duplicate batch?)" >> "$DEBUG_LOG" 2>/dev/null || true
141
+ fi
142
+
143
+ # Cleanup batch lock
144
+ rm -f "$BATCH_LOCK"
145
+ ) &
146
+
147
+ # Save PID for cancellation
148
+ local BATCH_PID=$!
149
+ echo "$BATCH_PID" > "$BATCH_LOCK"
150
+
151
+ echo "[$(date)] [BATCH] Scheduled batch job for $INCREMENT_ID (PID: $BATCH_PID, delay: ${IDLE_DELAY}s)" >> "$DEBUG_LOG" 2>/dev/null || true
152
+ }
153
+
154
+ ##
155
+ # Reset bulk operation counter
156
+ #
157
+ # Manually resets the operation counter (useful for testing or troubleshooting).
158
+ ##
159
+ reset_bulk_counter() {
160
+ rm -f "$OPERATION_COUNTER" "$OPERATION_TIMESTAMP"
161
+ echo "[$(date)] [BULK] Operation counter reset" >> "$PROJECT_ROOT/.specweave/logs/hook-debug.log" 2>/dev/null || true
162
+ }
163
+
164
+ # Export functions for use in hooks
165
+ export -f detect_bulk_operation
166
+ export -f schedule_batch_job
167
+ export -f reset_bulk_counter
@@ -47,6 +47,9 @@ import { ACStatusManager } from '../vendor/core/increment/ac-status-manager.js';
47
47
  import { SyncCoordinator } from '../../../../dist/src/sync/sync-coordinator.js';
48
48
  import { consoleLogger } from '../vendor/utils/logger.js';
49
49
 
50
+ // Import US completion orchestrator (NEW in v0.25.0+)
51
+ import { syncCompletedUserStories } from './us-completion-orchestrator.js';
52
+
50
53
  // ============================================================================
51
54
  // WRAPPER: UPDATE AC STATUS
52
55
  // ============================================================================
@@ -172,7 +175,20 @@ async function runConsolidatedSync(incrementId) {
172
175
  results.translate = { success: false, error: error.message };
173
176
  }
174
177
 
175
- // OPERATION 5: Sync to GitHub (NEW in v0.24.0+)
178
+ // OPERATION 5: Detect and sync newly completed user stories (NEW in v0.25.0+)
179
+ // CRITICAL: This operation runs AFTER AC sync to ensure ACs are up-to-date
180
+ // When a user story becomes fully complete (all ACs satisfied), this:
181
+ // - Detects the completion
182
+ // - Updates living docs
183
+ // - Triggers external tool sync (GitHub/JIRA/ADO)
184
+ try {
185
+ results.usCompletion = await syncCompletedUserStories(incrementId);
186
+ } catch (error) {
187
+ console.error('❌ Error detecting completed user stories:', error.message);
188
+ results.usCompletion = { success: false, error: error.message };
189
+ }
190
+
191
+ // OPERATION 6: Sync to GitHub (NEW in v0.24.0+)
176
192
  // FIX (v0.26.0): Skip GitHub sync in post-task-completion hook!
177
193
  // WHY: GitHub sync should ONLY run on increment COMPLETION, not task completion
178
194
  // This prevents 27 duplicate comments on every TodoWrite (see root cause analysis)
@@ -180,10 +196,11 @@ async function runConsolidatedSync(incrementId) {
180
196
  // GitHub sync is now ONLY triggered by:
181
197
  // - post-increment-completion.sh (when status → "completed")
182
198
  // - Manual sync via /specweave-github:sync command
199
+ // - US completion orchestrator (OPERATION 5) when user stories complete
183
200
  //
184
201
  // See: .specweave/increments/0051-*/reports/GITHUB-COMMENT-RECURSION-ROOT-CAUSE-2025-11-24.md
185
202
  if (process.env.SKIP_GITHUB_SYNC === 'true') {
186
- console.log('\n⏭️ [5/5] GitHub sync SKIPPED (called from post-task-completion hook)');
203
+ console.log('\n⏭️ [6/6] GitHub sync SKIPPED (called from post-task-completion hook)');
187
204
  console.log(' GitHub sync will run automatically on increment completion.');
188
205
  results.syncGitHub = { success: true, skipped: true };
189
206
  } else {
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * User Story Completion Orchestrator
4
+ *
5
+ * Orchestrates the sync cascade when user stories become complete:
6
+ * 1. Detect newly completed user stories (all ACs satisfied)
7
+ * 2. Update living docs for completed USs
8
+ * 3. Trigger external tool sync (GitHub/JIRA/ADO)
9
+ *
10
+ * CRITICAL: This is the bridge between AC-level completion and US-level sync.
11
+ * Called by consolidated-sync.js after AC sync completes.
12
+ *
13
+ * Architecture:
14
+ * - Uses USCompletionDetector to find newly completed USs
15
+ * - Uses LivingDocsSync to update living docs (which triggers external tools)
16
+ * - Non-blocking: Errors logged but don't break workflow
17
+ *
18
+ * Integration:
19
+ * - Called from consolidated-sync.js (OPERATION 6)
20
+ * - Runs after AC sync (ensures ACs are up-to-date)
21
+ * - Skipped if SKIP_US_SYNC=true (performance optimization)
22
+ */
23
+
24
+ // Import REAL implementations
25
+ import { USCompletionDetector } from '../../../../dist/src/core/us-completion-detector.js';
26
+ import { LivingDocsSync } from '../../../../dist/src/core/living-docs/living-docs-sync.js';
27
+ import { consoleLogger } from '../vendor/utils/logger.js';
28
+
29
+ /**
30
+ * Detect and sync newly completed user stories
31
+ *
32
+ * @param incrementId - Increment ID (e.g., "0053-safe-feature-deletion")
33
+ * @returns Result object with success status and sync details
34
+ */
35
+ export async function syncCompletedUserStories(incrementId) {
36
+ try {
37
+ console.log(`\n🎯 [6/6] Detecting completed user stories for ${incrementId}...`);
38
+
39
+ const projectRoot = process.cwd();
40
+
41
+ // Skip if disabled (performance optimization)
42
+ if (process.env.SKIP_US_SYNC === 'true') {
43
+ console.log('ℹ️ User story sync skipped (SKIP_US_SYNC=true)');
44
+ return { success: true, message: 'Sync skipped', skipped: true };
45
+ }
46
+
47
+ // 1. Initialize US completion detector
48
+ const detector = new USCompletionDetector(projectRoot, {
49
+ logger: consoleLogger
50
+ });
51
+
52
+ // 2. Detect newly completed user stories
53
+ const newlyCompleted = await detector.getNewlyCompletedUSs(incrementId);
54
+
55
+ if (newlyCompleted.length === 0) {
56
+ console.log('✅ No newly completed user stories detected (no sync needed)');
57
+ return { success: true, newlyCompleted: [], message: 'No new completions' };
58
+ }
59
+
60
+ console.log(`\n🎉 DETECTED ${newlyCompleted.length} NEWLY COMPLETED USER STORIES:`);
61
+ for (const us of newlyCompleted) {
62
+ console.log(` ${us.usId}: ${us.title} (${us.completedACs}/${us.totalACs} ACs complete)`);
63
+ }
64
+
65
+ // 3. Save completion state (mark USs as complete to prevent re-sync)
66
+ const allCompletions = await detector.detectCompletions(incrementId);
67
+ await detector.saveCompletionState(incrementId, allCompletions);
68
+
69
+ // 4. Trigger living docs sync (which will sync to external tools)
70
+ console.log(`\n📚 Syncing living docs for ${incrementId}...`);
71
+
72
+ const livingDocsSync = new LivingDocsSync(projectRoot, {
73
+ logger: consoleLogger
74
+ });
75
+
76
+ const syncResult = await livingDocsSync.syncIncrement(incrementId);
77
+
78
+ if (syncResult.success) {
79
+ console.log(`✅ Living docs synced successfully`);
80
+ console.log(` Feature: ${syncResult.featureId}`);
81
+ console.log(` Files updated: ${syncResult.filesCreated.length + syncResult.filesUpdated.length}`);
82
+
83
+ // External tool sync happens automatically inside livingDocsSync.syncIncrement()
84
+ // It calls syncToExternalTools() which handles GitHub/JIRA/ADO
85
+ console.log(`\n📡 External tool sync completed (GitHub/JIRA/ADO updated if configured)`);
86
+ } else {
87
+ console.warn(`⚠️ Living docs sync had errors (see logs)`);
88
+ console.warn(` Errors: ${syncResult.errors.join(', ')}`);
89
+ }
90
+
91
+ return {
92
+ success: true,
93
+ newlyCompleted: newlyCompleted.map(us => ({
94
+ usId: us.usId,
95
+ title: us.title,
96
+ totalACs: us.totalACs,
97
+ completedACs: us.completedACs
98
+ })),
99
+ syncResult,
100
+ message: `${newlyCompleted.length} user stories synced`
101
+ };
102
+
103
+ } catch (error) {
104
+ // Non-blocking: Log error but don't break workflow
105
+ console.error('❌ Error in US completion orchestrator:', error.message);
106
+ return { success: false, error: error.message };
107
+ }
108
+ }
109
+
110
+ // CLI Interface (for manual testing)
111
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`;
112
+ if (isMainModule) {
113
+ const incrementId = process.argv[2];
114
+
115
+ if (!incrementId) {
116
+ console.error('Usage: node us-completion-orchestrator.js <increment-id>');
117
+ console.error('Example: node us-completion-orchestrator.js 0053-safe-feature-deletion');
118
+ process.exit(1);
119
+ }
120
+
121
+ syncCompletedUserStories(incrementId)
122
+ .then(result => {
123
+ if (result.success) {
124
+ console.log('\n✅ US completion orchestration completed successfully');
125
+ process.exit(0);
126
+ } else {
127
+ console.error('\n❌ US completion orchestration failed');
128
+ process.exit(1);
129
+ }
130
+ })
131
+ .catch(error => {
132
+ console.error('\n❌ Fatal error:', error);
133
+ process.exit(1);
134
+ });
135
+ }