specweave 0.32.0 → 0.32.3

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 (347) hide show
  1. package/CLAUDE.md +215 -2
  2. package/README.md +22 -0
  3. package/bin/specweave.js +52 -1
  4. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts +100 -0
  5. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts.map +1 -0
  6. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js +291 -0
  7. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js.map +1 -0
  8. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts +103 -0
  9. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts.map +1 -0
  10. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js +310 -0
  11. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js.map +1 -0
  12. package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts +126 -0
  13. package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts.map +1 -0
  14. package/dist/plugins/specweave-jira/lib/jira-permission-gate.js +207 -0
  15. package/dist/plugins/specweave-jira/lib/jira-permission-gate.js.map +1 -0
  16. package/dist/src/adapters/codex/README.md +1 -1
  17. package/dist/src/adapters/codex/adapter.js +1 -1
  18. package/dist/src/cli/commands/archive.d.ts +2 -0
  19. package/dist/src/cli/commands/archive.d.ts.map +1 -1
  20. package/dist/src/cli/commands/archive.js +33 -0
  21. package/dist/src/cli/commands/archive.js.map +1 -1
  22. package/dist/src/cli/commands/cache.d.ts +17 -0
  23. package/dist/src/cli/commands/cache.d.ts.map +1 -0
  24. package/dist/src/cli/commands/cache.js +126 -0
  25. package/dist/src/cli/commands/cache.js.map +1 -0
  26. package/dist/src/cli/commands/context.d.ts +92 -0
  27. package/dist/src/cli/commands/context.d.ts.map +1 -0
  28. package/dist/src/cli/commands/context.js +205 -0
  29. package/dist/src/cli/commands/context.js.map +1 -0
  30. package/dist/src/cli/commands/init.d.ts.map +1 -1
  31. package/dist/src/cli/commands/init.js +112 -70
  32. package/dist/src/cli/commands/init.js.map +1 -1
  33. package/dist/src/cli/commands/plan/increment-detector.js +2 -2
  34. package/dist/src/cli/commands/plan/increment-detector.js.map +1 -1
  35. package/dist/src/cli/commands/sync-spec-commits.js +1 -1
  36. package/dist/src/cli/commands/sync-spec-commits.js.map +1 -1
  37. package/dist/src/cli/commands/sync-specs.js +2 -2
  38. package/dist/src/cli/commands/sync-specs.js.map +1 -1
  39. package/dist/src/cli/helpers/github/increment-profile-selector.js +1 -1
  40. package/dist/src/cli/helpers/github/increment-profile-selector.js.map +1 -1
  41. package/dist/src/cli/helpers/init/external-import.d.ts +3 -0
  42. package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
  43. package/dist/src/cli/helpers/init/external-import.js +17 -4
  44. package/dist/src/cli/helpers/init/external-import.js.map +1 -1
  45. package/dist/src/cli/helpers/init/index.d.ts +1 -0
  46. package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
  47. package/dist/src/cli/helpers/init/index.js +2 -0
  48. package/dist/src/cli/helpers/init/index.js.map +1 -1
  49. package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts +70 -0
  50. package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts.map +1 -1
  51. package/dist/src/cli/helpers/init/jira-ado-auto-detect.js +214 -4
  52. package/dist/src/cli/helpers/init/jira-ado-auto-detect.js.map +1 -1
  53. package/dist/src/cli/helpers/init/living-docs-preflight.d.ts +4 -0
  54. package/dist/src/cli/helpers/init/living-docs-preflight.d.ts.map +1 -1
  55. package/dist/src/cli/helpers/init/living-docs-preflight.js +34 -3
  56. package/dist/src/cli/helpers/init/living-docs-preflight.js.map +1 -1
  57. package/dist/src/cli/helpers/init/testing-config.d.ts +3 -0
  58. package/dist/src/cli/helpers/init/testing-config.d.ts.map +1 -1
  59. package/dist/src/cli/helpers/init/testing-config.js +9 -2
  60. package/dist/src/cli/helpers/init/testing-config.js.map +1 -1
  61. package/dist/src/cli/helpers/init/translation-config.d.ts +3 -0
  62. package/dist/src/cli/helpers/init/translation-config.d.ts.map +1 -1
  63. package/dist/src/cli/helpers/init/translation-config.js +21 -4
  64. package/dist/src/cli/helpers/init/translation-config.js.map +1 -1
  65. package/dist/src/cli/helpers/init/wizard-navigation.d.ts +45 -0
  66. package/dist/src/cli/helpers/init/wizard-navigation.d.ts.map +1 -0
  67. package/dist/src/cli/helpers/init/wizard-navigation.js +97 -0
  68. package/dist/src/cli/helpers/init/wizard-navigation.js.map +1 -0
  69. package/dist/src/cli/workers/living-docs-worker.js +66 -1
  70. package/dist/src/cli/workers/living-docs-worker.js.map +1 -1
  71. package/dist/src/config/types.d.ts +203 -1208
  72. package/dist/src/config/types.d.ts.map +1 -1
  73. package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -1
  74. package/dist/src/core/discrepancy/increment-generator.js +5 -2
  75. package/dist/src/core/discrepancy/increment-generator.js.map +1 -1
  76. package/dist/src/core/increment/duplicate-detector.js +2 -2
  77. package/dist/src/core/increment/duplicate-detector.js.map +1 -1
  78. package/dist/src/core/increment/increment-archiver.d.ts +49 -4
  79. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
  80. package/dist/src/core/increment/increment-archiver.js +123 -22
  81. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  82. package/dist/src/core/increment/increment-status.js +2 -2
  83. package/dist/src/core/increment/increment-status.js.map +1 -1
  84. package/dist/src/core/increment/increment-utils.d.ts +150 -0
  85. package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
  86. package/dist/src/core/increment/increment-utils.js +216 -4
  87. package/dist/src/core/increment/increment-utils.js.map +1 -1
  88. package/dist/src/core/increment/metadata-validator.js +1 -1
  89. package/dist/src/core/increment/metadata-validator.js.map +1 -1
  90. package/dist/src/core/living-docs/feature-archiver.d.ts +4 -0
  91. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
  92. package/dist/src/core/living-docs/feature-archiver.js +32 -10
  93. package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
  94. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
  95. package/dist/src/core/living-docs/feature-id-manager.js +8 -4
  96. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
  97. package/dist/src/core/living-docs/governance/ecosystem-detector.d.ts +38 -0
  98. package/dist/src/core/living-docs/governance/ecosystem-detector.d.ts.map +1 -0
  99. package/dist/src/core/living-docs/governance/ecosystem-detector.js +325 -0
  100. package/dist/src/core/living-docs/governance/ecosystem-detector.js.map +1 -0
  101. package/dist/src/core/living-docs/governance/frontend-standards-parser.d.ts +74 -0
  102. package/dist/src/core/living-docs/governance/frontend-standards-parser.d.ts.map +1 -0
  103. package/dist/src/core/living-docs/governance/frontend-standards-parser.js +366 -0
  104. package/dist/src/core/living-docs/governance/frontend-standards-parser.js.map +1 -0
  105. package/dist/src/core/living-docs/governance/go-standards-parser.d.ts +64 -0
  106. package/dist/src/core/living-docs/governance/go-standards-parser.d.ts.map +1 -0
  107. package/dist/src/core/living-docs/governance/go-standards-parser.js +229 -0
  108. package/dist/src/core/living-docs/governance/go-standards-parser.js.map +1 -0
  109. package/dist/src/core/living-docs/governance/index.d.ts +50 -0
  110. package/dist/src/core/living-docs/governance/index.d.ts.map +1 -0
  111. package/dist/src/core/living-docs/governance/index.js +56 -0
  112. package/dist/src/core/living-docs/governance/index.js.map +1 -0
  113. package/dist/src/core/living-docs/governance/java-standards-parser.d.ts +89 -0
  114. package/dist/src/core/living-docs/governance/java-standards-parser.d.ts.map +1 -0
  115. package/dist/src/core/living-docs/governance/java-standards-parser.js +356 -0
  116. package/dist/src/core/living-docs/governance/java-standards-parser.js.map +1 -0
  117. package/dist/src/core/living-docs/governance/python-standards-parser.d.ts +83 -0
  118. package/dist/src/core/living-docs/governance/python-standards-parser.d.ts.map +1 -0
  119. package/dist/src/core/living-docs/governance/python-standards-parser.js +347 -0
  120. package/dist/src/core/living-docs/governance/python-standards-parser.js.map +1 -0
  121. package/dist/src/core/living-docs/governance/standards-generator.d.ts +38 -0
  122. package/dist/src/core/living-docs/governance/standards-generator.d.ts.map +1 -0
  123. package/dist/src/core/living-docs/governance/standards-generator.js +476 -0
  124. package/dist/src/core/living-docs/governance/standards-generator.js.map +1 -0
  125. package/dist/src/core/living-docs/hierarchy-mapper.js +3 -3
  126. package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
  127. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts +18 -0
  128. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts.map +1 -0
  129. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js +299 -0
  130. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -0
  131. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts +15 -0
  132. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts.map +1 -0
  133. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js +138 -0
  134. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js.map +1 -0
  135. package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts +24 -0
  136. package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts.map +1 -0
  137. package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js +198 -0
  138. package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js.map +1 -0
  139. package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts +17 -0
  140. package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts.map +1 -0
  141. package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js +241 -0
  142. package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js.map +1 -0
  143. package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts +28 -0
  144. package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts.map +1 -0
  145. package/dist/src/core/living-docs/intelligent-analyzer/index.js +197 -0
  146. package/dist/src/core/living-docs/intelligent-analyzer/index.js.map +1 -0
  147. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts +22 -0
  148. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts.map +1 -0
  149. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js +482 -0
  150. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -0
  151. package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts +42 -0
  152. package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts.map +1 -0
  153. package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js +343 -0
  154. package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js.map +1 -0
  155. package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +190 -0
  156. package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -0
  157. package/dist/src/core/living-docs/intelligent-analyzer/types.js +7 -0
  158. package/dist/src/core/living-docs/intelligent-analyzer/types.js.map +1 -0
  159. package/dist/src/core/living-docs/living-docs-sync.d.ts +11 -3
  160. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  161. package/dist/src/core/living-docs/living-docs-sync.js +53 -10
  162. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  163. package/dist/src/core/living-docs/module-analyzer.d.ts +22 -0
  164. package/dist/src/core/living-docs/module-analyzer.d.ts.map +1 -1
  165. package/dist/src/core/living-docs/module-analyzer.js +123 -19
  166. package/dist/src/core/living-docs/module-analyzer.js.map +1 -1
  167. package/dist/src/core/llm/provider-factory.js +2 -2
  168. package/dist/src/core/llm/provider-factory.js.map +1 -1
  169. package/dist/src/core/llm/providers/anthropic-provider.js +1 -1
  170. package/dist/src/core/llm/providers/bedrock-provider.d.ts.map +1 -1
  171. package/dist/src/core/llm/providers/bedrock-provider.js +8 -4
  172. package/dist/src/core/llm/providers/bedrock-provider.js.map +1 -1
  173. package/dist/src/core/sync/spec-increment-mapper.js +3 -3
  174. package/dist/src/core/sync/spec-increment-mapper.js.map +1 -1
  175. package/dist/src/importers/item-converter.d.ts +25 -0
  176. package/dist/src/importers/item-converter.d.ts.map +1 -1
  177. package/dist/src/importers/item-converter.js +135 -5
  178. package/dist/src/importers/item-converter.js.map +1 -1
  179. package/dist/src/importers/jira-importer.d.ts +14 -0
  180. package/dist/src/importers/jira-importer.d.ts.map +1 -1
  181. package/dist/src/importers/jira-importer.js +75 -0
  182. package/dist/src/importers/jira-importer.js.map +1 -1
  183. package/dist/src/init/architecture/types.d.ts +33 -140
  184. package/dist/src/init/architecture/types.d.ts.map +1 -1
  185. package/dist/src/init/compliance/types.d.ts +30 -27
  186. package/dist/src/init/compliance/types.d.ts.map +1 -1
  187. package/dist/src/init/repo/types.d.ts +11 -34
  188. package/dist/src/init/repo/types.d.ts.map +1 -1
  189. package/dist/src/init/research/src/config/types.d.ts +15 -82
  190. package/dist/src/init/research/src/config/types.d.ts.map +1 -1
  191. package/dist/src/init/research/types.d.ts +38 -93
  192. package/dist/src/init/research/types.d.ts.map +1 -1
  193. package/dist/src/init/team/types.d.ts +4 -42
  194. package/dist/src/init/team/types.d.ts.map +1 -1
  195. package/dist/src/integrations/jira/jira-token-provider.d.ts +93 -0
  196. package/dist/src/integrations/jira/jira-token-provider.d.ts.map +1 -0
  197. package/dist/src/integrations/jira/jira-token-provider.js +160 -0
  198. package/dist/src/integrations/jira/jira-token-provider.js.map +1 -0
  199. package/dist/src/sync/ado-reconciler.d.ts +92 -0
  200. package/dist/src/sync/ado-reconciler.d.ts.map +1 -0
  201. package/dist/src/sync/ado-reconciler.js +335 -0
  202. package/dist/src/sync/ado-reconciler.js.map +1 -0
  203. package/dist/src/sync/jira-reconciler.d.ts +106 -0
  204. package/dist/src/sync/jira-reconciler.d.ts.map +1 -0
  205. package/dist/src/sync/jira-reconciler.js +405 -0
  206. package/dist/src/sync/jira-reconciler.js.map +1 -0
  207. package/dist/src/types/dashboard-cache.d.ts +181 -0
  208. package/dist/src/types/dashboard-cache.d.ts.map +1 -0
  209. package/dist/src/types/dashboard-cache.js +65 -0
  210. package/dist/src/types/dashboard-cache.js.map +1 -0
  211. package/dist/src/types/model-selection.d.ts +6 -4
  212. package/dist/src/types/model-selection.d.ts.map +1 -1
  213. package/dist/src/types/model-selection.js +3 -1
  214. package/dist/src/types/model-selection.js.map +1 -1
  215. package/dist/src/utils/docs-validator.d.ts +131 -0
  216. package/dist/src/utils/docs-validator.d.ts.map +1 -0
  217. package/dist/src/utils/docs-validator.js +529 -0
  218. package/dist/src/utils/docs-validator.js.map +1 -0
  219. package/dist/src/utils/external-tool-drift-detector.d.ts +1 -1
  220. package/dist/src/utils/external-tool-drift-detector.d.ts.map +1 -1
  221. package/dist/src/utils/external-tool-drift-detector.js +5 -4
  222. package/dist/src/utils/external-tool-drift-detector.js.map +1 -1
  223. package/dist/src/utils/feature-id-collision.js +1 -1
  224. package/dist/src/utils/feature-id-collision.js.map +1 -1
  225. package/dist/src/utils/feature-id-derivation.d.ts +8 -3
  226. package/dist/src/utils/feature-id-derivation.d.ts.map +1 -1
  227. package/dist/src/utils/feature-id-derivation.js +14 -6
  228. package/dist/src/utils/feature-id-derivation.js.map +1 -1
  229. package/dist/src/utils/html-to-mdx.d.ts +1 -0
  230. package/dist/src/utils/html-to-mdx.d.ts.map +1 -1
  231. package/dist/src/utils/html-to-mdx.js +43 -5
  232. package/dist/src/utils/html-to-mdx.js.map +1 -1
  233. package/dist/src/utils/model-selection.d.ts +3 -4
  234. package/dist/src/utils/model-selection.d.ts.map +1 -1
  235. package/dist/src/utils/model-selection.js +3 -4
  236. package/dist/src/utils/model-selection.js.map +1 -1
  237. package/package.json +1 -1
  238. package/plugins/specweave/agents/code-standards-detective/AGENT.md +48 -0
  239. package/plugins/specweave/agents/pm/AGENT.md +10 -7
  240. package/plugins/specweave/commands/specweave-archive-features.md +5 -7
  241. package/plugins/specweave/commands/specweave-archive.md +2 -1
  242. package/plugins/specweave/commands/specweave-costs.md +4 -4
  243. package/plugins/specweave/commands/specweave-do.md +44 -10
  244. package/plugins/specweave/commands/specweave-done.md +109 -0
  245. package/plugins/specweave/commands/specweave-import-external.md +45 -18
  246. package/plugins/specweave/commands/specweave-increment.md +331 -33
  247. package/plugins/specweave/commands/specweave-jobs.md +2 -2
  248. package/plugins/specweave/commands/specweave-progress.md +4 -4
  249. package/plugins/specweave/commands/specweave-restore-feature.md +5 -4
  250. package/plugins/specweave/commands/specweave-sync-docs.md +1 -1
  251. package/plugins/specweave/commands/specweave-sync-specs.md +216 -322
  252. package/plugins/specweave/commands/specweave-validate-features.md +13 -8
  253. package/plugins/specweave/commands/specweave-validate.md +27 -1
  254. package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
  255. package/plugins/specweave/hooks/hooks.json +43 -4
  256. package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
  257. package/plugins/specweave/hooks/lib/common-setup.sh +375 -0
  258. package/plugins/specweave/hooks/lib/crash-prevention.sh +336 -0
  259. package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
  260. package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
  261. package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
  262. package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
  263. package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
  264. package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
  265. package/plugins/specweave/hooks/post-task-completion.sh +4 -23
  266. package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
  267. package/plugins/specweave/hooks/pre-command-deduplication.sh +1 -6
  268. package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
  269. package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
  270. package/plugins/specweave/hooks/pre-task-completion.sh +8 -37
  271. package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
  272. package/plugins/specweave/hooks/pre-tool-use.sh +2 -11
  273. package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
  274. package/plugins/specweave/hooks/spec-project-validator.sh +80 -25
  275. package/plugins/specweave/hooks/universal/dispatcher.mjs +135 -42
  276. package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +183 -0
  277. package/plugins/specweave/hooks/user-prompt-submit.sh +140 -38
  278. package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
  279. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +12 -0
  280. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +89 -0
  281. package/plugins/specweave/hooks/v2/guards/bash-file-guard.sh +211 -0
  282. package/plugins/specweave/hooks/v2/guards/bash-file-guard.test.sh +163 -0
  283. package/plugins/specweave/hooks/v2/guards/completion-guard.sh +26 -28
  284. package/plugins/specweave/hooks/v2/guards/features-folder-guard.sh +50 -0
  285. package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +135 -0
  286. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +2 -2
  287. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -1
  288. package/plugins/specweave/scripts/README.md +166 -0
  289. package/plugins/specweave/scripts/cleanup-state.sh +142 -0
  290. package/plugins/specweave/scripts/force-kill.sh +142 -0
  291. package/plugins/specweave/scripts/jobs.js +171 -0
  292. package/plugins/specweave/scripts/progress.js +170 -0
  293. package/plugins/specweave/scripts/read-costs.sh +132 -0
  294. package/plugins/specweave/scripts/read-jobs.sh +324 -0
  295. package/plugins/specweave/scripts/read-progress.sh +185 -0
  296. package/plugins/specweave/scripts/read-status.sh +146 -0
  297. package/plugins/specweave/scripts/read-workflow.sh +173 -0
  298. package/plugins/specweave/scripts/rebuild-dashboard-cache.sh +327 -0
  299. package/plugins/specweave/scripts/session-watchdog.sh +192 -0
  300. package/plugins/specweave/scripts/status.js +154 -0
  301. package/plugins/specweave/scripts/update-dashboard-cache.sh +281 -0
  302. package/plugins/specweave/skills/code-standards-analyzer/SKILL.md +58 -6
  303. package/plugins/specweave/skills/increment-planner/SKILL.md +388 -48
  304. package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +17 -7
  305. package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +6 -1
  306. package/plugins/specweave/skills/increment-planner/templates/tasks-multi-project.md +1 -1
  307. package/plugins/specweave/skills/increment-planner/templates/tasks-single-project.md +1 -1
  308. package/plugins/specweave/skills/instant-status/SKILL.md +70 -0
  309. package/plugins/specweave-ado/commands/cleanup-duplicates.md +212 -0
  310. package/plugins/specweave-ado/commands/reconcile.md +120 -0
  311. package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
  312. package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
  313. package/plugins/specweave-ado/lib/ado-duplicate-detector.js +279 -0
  314. package/plugins/specweave-ado/lib/ado-duplicate-detector.ts +407 -0
  315. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
  316. package/plugins/specweave-docs/commands/build.md +32 -4
  317. package/plugins/specweave-docs/commands/preview.md +43 -1
  318. package/plugins/specweave-docs/commands/validate.md +250 -0
  319. package/plugins/specweave-github/agents/github-manager/AGENT.md +2 -2
  320. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1262 -0
  321. package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
  322. package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
  323. package/plugins/specweave-infrastructure/skills/hetzner-provisioner/README.md +1 -1
  324. package/plugins/specweave-jira/agents/jira-manager/AGENT.md +1 -1
  325. package/plugins/specweave-jira/agents/jira-multi-project-mapper/AGENT.md +530 -0
  326. package/plugins/specweave-jira/agents/jira-sync-judge/AGENT.md +438 -0
  327. package/plugins/specweave-jira/commands/cleanup-duplicates.md +219 -0
  328. package/plugins/specweave-jira/commands/close.md +297 -0
  329. package/plugins/specweave-jira/commands/create.md +198 -0
  330. package/plugins/specweave-jira/commands/reconcile.md +123 -0
  331. package/plugins/specweave-jira/commands/status.md +215 -0
  332. package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
  333. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
  334. package/plugins/specweave-jira/lib/jira-duplicate-detector.js +296 -0
  335. package/plugins/specweave-jira/lib/jira-duplicate-detector.ts +434 -0
  336. package/plugins/specweave-jira/lib/jira-permission-gate.js +160 -0
  337. package/plugins/specweave-jira/lib/jira-permission-gate.ts +276 -0
  338. package/plugins/specweave-jira/lib/jira-profile-resolver.js +222 -0
  339. package/plugins/specweave-jira/lib/jira-profile-resolver.ts +427 -0
  340. package/plugins/specweave-jira/reference/jira-specweave-mapping.md +16 -11
  341. package/plugins/specweave-release/commands/specweave-release-npm.md +140 -14
  342. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1254 -0
  343. package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
  344. package/plugins/specweave/hooks/post-edit-spec.sh +0 -265
  345. package/plugins/specweave/hooks/post-write-spec.sh +0 -267
  346. package/plugins/specweave/hooks/pre-edit-spec.sh +0 -151
  347. package/plugins/specweave/hooks/pre-write-spec.sh +0 -151
@@ -0,0 +1,212 @@
1
+ ---
2
+ name: specweave-ado:cleanup-duplicates
3
+ description: Clean up duplicate Azure DevOps work items for a Feature. Finds work items with duplicate titles and closes all except the first created item.
4
+ justification: |
5
+ CRITICAL INCIDENT RESPONSE TOOL - DO NOT DELETE!
6
+
7
+ Why This Command Exists:
8
+ - Prevention systems work for single-process execution
9
+ - Multiple parallel Claude Code instances bypass all prevention (file-based cache, no distributed locking)
10
+ - ADO API race conditions: Time gap between "check exists" and "create work item" allows duplicates
11
+ - Historical duplicates from pre-v0.33.0 users (before prevention was added)
12
+
13
+ Evidence of Need:
14
+ - GitHub had 123 duplicate issues incident (cleaned to 29 unique) - same risk exists for ADO
15
+ - Parallel execution creates race conditions that prevention CANNOT solve
16
+ - Industry standard: Prevention + Detection + Cleanup (defense in depth)
17
+
18
+ When to Delete:
19
+ - ONLY if distributed locking implemented
20
+ - AND parallel execution tested (100+ concurrent syncs with zero duplicates)
21
+ - AND zero duplicates for 6+ months in production
22
+ ---
23
+
24
+ # Clean Up Duplicate ADO Work Items
25
+
26
+ **CRITICAL**: This command detects and closes duplicate ADO work items created by multiple syncs.
27
+
28
+ ## Usage
29
+
30
+ ```bash
31
+ /specweave-ado:cleanup-duplicates <feature-id> [--dry-run]
32
+ ```
33
+
34
+ ## What It Does
35
+
36
+ **Duplicate Detection & Cleanup**:
37
+
38
+ 1. **Find all work items** for the Feature (searches by Feature ID in title)
39
+ 2. **Group by title** (detect duplicates)
40
+ 3. **For each duplicate group**:
41
+ - Keep the **FIRST created** work item (lowest ID)
42
+ - Close all **LATER** work items with comment: "Duplicate of #XXX"
43
+ 4. **Update Feature README** with correct work item IDs
44
+
45
+ ## Examples
46
+
47
+ ### Dry Run (No Changes)
48
+
49
+ ```bash
50
+ /specweave-ado:cleanup-duplicates FS-031 --dry-run
51
+ ```
52
+
53
+ **Output**:
54
+ ```
55
+ Scanning for duplicates in Feature FS-031...
56
+ Found 25 total work items
57
+ Detected 10 duplicate groups:
58
+
59
+ Group 1: "[FS-031] External Tool Status Synchronization"
60
+ - #1250 (KEEP) - Created 2025-11-10
61
+ - #1255 (CLOSE) - Created 2025-11-11 - DUPLICATE
62
+ - #1260 (CLOSE) - Created 2025-11-12 - DUPLICATE
63
+
64
+ Group 2: "[FS-031] Multi-Project ADO Sync"
65
+ - #1251 (KEEP) - Created 2025-11-10
66
+ - #1256 (CLOSE) - Created 2025-11-11 - DUPLICATE
67
+
68
+ ...
69
+
70
+ Dry run complete!
71
+ Total work items: 25
72
+ Duplicate groups: 10
73
+ Work items to close: 15
74
+
75
+ This was a DRY RUN - no changes made.
76
+ Run without --dry-run to actually close duplicates.
77
+ ```
78
+
79
+ ### Actual Cleanup
80
+
81
+ ```bash
82
+ /specweave-ado:cleanup-duplicates FS-031
83
+ ```
84
+
85
+ **Output**:
86
+ ```
87
+ Scanning for duplicates in Feature FS-031...
88
+ Found 25 total work items
89
+ Detected 10 duplicate groups
90
+
91
+ CONFIRM: Close 15 duplicate work items? [y/N]
92
+ > y
93
+
94
+ Closing duplicates...
95
+ Closed #1255 (duplicate of #1250)
96
+ Closed #1256 (duplicate of #1251)
97
+ Closed #1260 (duplicate of #1250)
98
+ ...
99
+
100
+ Updating Feature README frontmatter...
101
+ Updated frontmatter with correct work item IDs
102
+
103
+ Cleanup complete!
104
+ Closed: 15 duplicates
105
+ Kept: 10 original work items
106
+ ```
107
+
108
+ ## Arguments
109
+
110
+ - `<feature-id>` - Feature ID (e.g., `FS-031` or just `031`)
111
+ - `--dry-run` - Preview changes without actually closing work items (optional)
112
+
113
+ ## Safety Features
114
+
115
+ - **Confirmation prompt**: Asks before closing work items (unless --dry-run)
116
+ - **Dry run mode**: Preview changes safely
117
+ - **Keeps oldest work item**: Preserves the first created item
118
+ - **Adds closure comment**: Links to the original work item
119
+ - **Updates metadata**: Fixes Feature README frontmatter
120
+
121
+ ## What Gets Closed
122
+
123
+ **Closed work items**:
124
+ - Duplicate titles (second, third, etc. occurrences)
125
+ - Closed with comment: "Duplicate of #XXX"
126
+ - Original work item kept open (or maintains its status)
127
+
128
+ **Example comment on closed duplicate**:
129
+ ```markdown
130
+ ## Duplicate of #1250
131
+
132
+ This work item was automatically closed by SpecWeave cleanup because it is a duplicate.
133
+
134
+ The original work item (#1250) contains the same content and should be used for tracking instead.
135
+
136
+ Auto-closed by SpecWeave Duplicate Cleanup
137
+ ```
138
+
139
+ ## Requirements
140
+
141
+ 1. **Azure DevOps PAT** configured (`AZURE_DEVOPS_PAT`)
142
+ 2. **Organization** configured (`AZURE_DEVOPS_ORG`)
143
+ 3. **Project** configured (`AZURE_DEVOPS_PROJECT`)
144
+ 4. **Write access** to project (for closing work items)
145
+ 5. **Feature folder exists** at `.specweave/docs/internal/specs/FS-XXX-name/`
146
+
147
+ ## When to Use
148
+
149
+ **Use this command when**:
150
+ - You see multiple work items with the same title in ADO
151
+ - Feature sync ran multiple times and created duplicates
152
+ - Feature README frontmatter got corrupted and reset
153
+ - Post-sync validation warns about duplicates
154
+
155
+ **Example warning that triggers this**:
156
+ ```
157
+ WARNING: 10 duplicate(s) detected!
158
+ Run cleanup command to resolve:
159
+ /specweave-ado:cleanup-duplicates FS-031
160
+ ```
161
+
162
+ ## Architecture
163
+
164
+ **Duplicate Detection Logic**:
165
+ 1. Query WIQL for work items with Feature ID in title
166
+ 2. Group work items by **exact title match**
167
+ 3. Within each group, sort by **work item ID** (ascending)
168
+ 4. Keep **first work item** (lowest ID = oldest)
169
+ 5. Close **all others** as duplicates via state transition
170
+
171
+ **Why lowest ID?**:
172
+ - Lower work item IDs were created first
173
+ - Preserves chronological order
174
+ - Maintains links from old documentation
175
+
176
+ ## Related Commands
177
+
178
+ - `/specweave-ado:sync` - Sync Feature to ADO (with duplicate detection)
179
+ - `/specweave-ado:reconcile` - Reconcile work item states
180
+ - `/specweave:validate` - Validate increment completeness
181
+
182
+ ## Implementation
183
+
184
+ **File**: `plugins/specweave-ado/lib/ado-duplicate-detector.ts`
185
+
186
+ **Class**: `AdoDuplicateDetector`
187
+
188
+ **Algorithm** (3-phase protection):
189
+ 1. **Detection**: WIQL query for existing work items matching pattern
190
+ 2. **Verification**: Count check to detect duplicates after creation
191
+ 3. **Reflection**: Auto-close duplicates automatically
192
+
193
+ For manual cleanup:
194
+ 1. WIQL query for all work items with Feature ID
195
+ 2. Group by title (Map<string, number[]>)
196
+ 3. Filter groups with >1 item (duplicates)
197
+ 4. For each duplicate group:
198
+ - Keep first work item (lowest ID)
199
+ - Close others via ADO REST API
200
+
201
+ ## Next Steps
202
+
203
+ After cleanup:
204
+
205
+ 1. **Verify cleanup**: Check ADO for remaining work items
206
+ 2. **Check Feature FEATURE.md**: Verify frontmatter has correct work item IDs
207
+ 3. **Re-run sync**: `/specweave-ado:sync` (should show no duplicates)
208
+ 4. **Duplicate detection**: Automatically enabled via AdoDuplicateDetector
209
+
210
+ ---
211
+
212
+ **SAFE TO USE**: This command is idempotent and safe to run multiple times.
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: specweave-ado:reconcile
3
+ description: Reconcile Azure DevOps work item states with increment statuses. Fixes drift by closing work items for completed increments and reactivating work items for resumed increments.
4
+ ---
5
+
6
+ # Azure DevOps Status Reconciliation
7
+
8
+ Scan all increments and fix any drift between local metadata.json status and ADO work item states.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ /specweave-ado:reconcile [options]
14
+ ```
15
+
16
+ ## Options
17
+
18
+ - `--dry-run`: Preview changes without making them
19
+ - `--verbose`: Show detailed output for each work item checked
20
+
21
+ ## What It Does
22
+
23
+ 1. **Scans** all non-archived increments
24
+ 2. **Compares** metadata.json status with ADO work item state
25
+ 3. **Fixes** mismatches:
26
+ - `metadata=completed` + `ADO=Active` → **Close** the work item
27
+ - `metadata=in-progress` + `ADO=Closed` → **Reactivate** the work item
28
+
29
+ ## When to Use
30
+
31
+ - After manual metadata.json edits
32
+ - After git pulls that changed increment statuses
33
+ - When you notice active work items for completed work
34
+ - As a periodic health check
35
+
36
+ ## Implementation
37
+
38
+ Run the reconciliation using the AdoReconciler:
39
+
40
+ ```typescript
41
+ import { AdoReconciler } from '../../../src/sync/ado-reconciler.js';
42
+
43
+ const reconciler = new AdoReconciler({
44
+ projectRoot: process.cwd(),
45
+ dryRun: args.includes('--dry-run'),
46
+ });
47
+
48
+ const result = await reconciler.reconcile();
49
+
50
+ // Report results
51
+ console.log(`\nReconciliation complete:`);
52
+ console.log(` Scanned: ${result.scanned} increments`);
53
+ console.log(` Fixed: ${result.closed} closed, ${result.reopened} reopened`);
54
+ if (result.errors.length > 0) {
55
+ console.log(` Errors: ${result.errors.length}`);
56
+ }
57
+ ```
58
+
59
+ ## Example Output
60
+
61
+ ```
62
+ 📊 Scanning 5 increment(s) for ADO state drift...
63
+
64
+ ✅ Work Item #1234 (0056-plugin-fix/US-001): State matches (Active)
65
+ ❌ Work Item #1240 (0066-import-wizard/US-003): Active but should be CLOSED (status=completed)
66
+ ✅ Closed work item #1240
67
+ ❌ Work Item #1238 (0063-multi-repo/US-001): CLOSED but should be ACTIVE (status=in-progress)
68
+ ✅ Reactivated work item #1238
69
+
70
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
71
+ 📊 ADO RECONCILIATION SUMMARY
72
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
73
+ Increments scanned: 5
74
+ Mismatches found: 2
75
+ Work items closed: 1
76
+ Work items reopened: 1
77
+ Errors: 0
78
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
79
+ ```
80
+
81
+ ## Dry Run Mode
82
+
83
+ ```bash
84
+ /specweave-ado:reconcile --dry-run
85
+ ```
86
+
87
+ Shows what would be changed without making any modifications:
88
+
89
+ ```
90
+ ❌ Work Item #1240 (0066-import-wizard/US-003): Active but should be CLOSED
91
+ [DRY RUN] Would close work item #1240
92
+
93
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
94
+ 📊 ADO RECONCILIATION SUMMARY
95
+ ⚠️ DRY RUN - No changes were made
96
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
97
+ ```
98
+
99
+ ## Requirements
100
+
101
+ - Azure DevOps PAT configured (`AZURE_DEVOPS_PAT`)
102
+ - `sync.ado.enabled = true` in config.json
103
+ - `sync.settings.canUpdateExternalItems = true` in config.json
104
+
105
+ ## ADO Status Mapping
106
+
107
+ | SpecWeave Status | Expected ADO State |
108
+ |-----------------|-------------------|
109
+ | `completed` | Closed, Done, Resolved |
110
+ | `abandoned` | Closed, Removed |
111
+ | `in-progress` | Active, In Progress |
112
+ | `active` | Active, New |
113
+ | `planning` | New |
114
+
115
+ ## Related Commands
116
+
117
+ - `/specweave-ado:status`: View sync status for increments
118
+ - `/specweave-ado:sync`: Manual sync to ADO
119
+ - `/specweave:done`: Close increment (triggers auto-close)
120
+ - `/specweave:resume`: Resume increment (now triggers auto-reopen)
@@ -0,0 +1,353 @@
1
+ #!/bin/bash
2
+
3
+ # ============================================================================
4
+ # Post Living Docs Update Hook - Azure DevOps Sync
5
+ # ============================================================================
6
+ #
7
+ # Triggered after living docs are updated to sync with Azure DevOps.
8
+ # CRITICAL: External tool status ALWAYS wins in conflicts!
9
+ #
10
+ # Triggers:
11
+ # 1. After /specweave:done (increment completion)
12
+ # 2. After /specweave:sync-docs update
13
+ # 3. After manual spec edits
14
+ # 4. After webhook from ADO
15
+ #
16
+ # ============================================================================
17
+
18
+ set -e
19
+
20
+ # Configuration
21
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
22
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
23
+ LIVING_DOCS_DIR="$PROJECT_ROOT/.specweave/docs/internal/specs"
24
+ LOG_FILE="$PROJECT_ROOT/.specweave/logs/ado-sync.log"
25
+ DEBUG=${DEBUG:-0}
26
+
27
+ # Ensure log directory exists
28
+ mkdir -p "$(dirname "$LOG_FILE")"
29
+
30
+ # ============================================================================
31
+ # Logging
32
+ # ============================================================================
33
+
34
+ log() {
35
+ local level=$1
36
+ shift
37
+ local message="$@"
38
+ local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
39
+ echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
40
+ [ "$DEBUG" -eq 1 ] && echo "[$level] $message" >&2
41
+ }
42
+
43
+ log_info() {
44
+ log "INFO" "$@"
45
+ }
46
+
47
+ log_error() {
48
+ log "ERROR" "$@"
49
+ }
50
+
51
+ log_debug() {
52
+ [ "$DEBUG" -eq 1 ] && log "DEBUG" "$@"
53
+ }
54
+
55
+ # ============================================================================
56
+ # External Tool Detection
57
+ # ============================================================================
58
+
59
+ detect_external_tool() {
60
+ local spec_path=$1
61
+
62
+ # Check for external links in spec metadata
63
+ if grep -q "externalLinks:" "$spec_path"; then
64
+ if grep -q "ado:" "$spec_path"; then
65
+ echo "ado"
66
+ elif grep -q "jira:" "$spec_path"; then
67
+ echo "jira"
68
+ elif grep -q "github:" "$spec_path"; then
69
+ echo "github"
70
+ fi
71
+ fi
72
+ }
73
+
74
+ # ============================================================================
75
+ # Status Mapping
76
+ # ============================================================================
77
+
78
+ map_ado_status_to_local() {
79
+ local ado_status=$1
80
+
81
+ case "$ado_status" in
82
+ "New")
83
+ echo "draft"
84
+ ;;
85
+ "Active")
86
+ echo "in-progress"
87
+ ;;
88
+ "Resolved")
89
+ echo "implemented"
90
+ ;;
91
+ "Closed")
92
+ echo "complete"
93
+ ;;
94
+ "In Review"|"In QA")
95
+ echo "in-qa"
96
+ ;;
97
+ *)
98
+ echo "unknown"
99
+ ;;
100
+ esac
101
+ }
102
+
103
+ map_local_status_to_ado() {
104
+ local local_status=$1
105
+
106
+ case "$local_status" in
107
+ "draft")
108
+ echo "New"
109
+ ;;
110
+ "in-progress")
111
+ echo "Active"
112
+ ;;
113
+ "implemented")
114
+ echo "Resolved"
115
+ ;;
116
+ "complete")
117
+ echo "Closed"
118
+ ;;
119
+ "in-qa")
120
+ echo "In Review"
121
+ ;;
122
+ *)
123
+ echo "Active"
124
+ ;;
125
+ esac
126
+ }
127
+
128
+ # ============================================================================
129
+ # ADO API Functions
130
+ # ============================================================================
131
+
132
+ get_ado_work_item_status() {
133
+ local work_item_id=$1
134
+ local org="${AZURE_DEVOPS_ORG}"
135
+ local project="${AZURE_DEVOPS_PROJECT}"
136
+ local pat="${AZURE_DEVOPS_PAT}"
137
+
138
+ if [ -z "$org" ] || [ -z "$pat" ]; then
139
+ log_error "ADO credentials not configured"
140
+ return 1
141
+ fi
142
+
143
+ local api_url="https://dev.azure.com/${org}/${project}/_apis/wit/workitems/${work_item_id}?api-version=7.0"
144
+
145
+ log_debug "Fetching ADO work item $work_item_id status"
146
+
147
+ local response=$(curl -s -u ":${pat}" \
148
+ -H "Content-Type: application/json" \
149
+ "$api_url")
150
+
151
+ if [ $? -ne 0 ]; then
152
+ log_error "Failed to fetch ADO work item status"
153
+ return 1
154
+ fi
155
+
156
+ # Extract status from response
157
+ local status=$(echo "$response" | jq -r '.fields["System.State"]')
158
+
159
+ if [ "$status" = "null" ] || [ -z "$status" ]; then
160
+ log_error "Could not extract status from ADO response"
161
+ return 1
162
+ fi
163
+
164
+ echo "$status"
165
+ }
166
+
167
+ update_ado_work_item() {
168
+ local work_item_id=$1
169
+ local spec_content=$2
170
+ local org="${AZURE_DEVOPS_ORG}"
171
+ local project="${AZURE_DEVOPS_PROJECT}"
172
+ local pat="${AZURE_DEVOPS_PAT}"
173
+
174
+ if [ -z "$org" ] || [ -z "$pat" ]; then
175
+ log_error "ADO credentials not configured"
176
+ return 1
177
+ fi
178
+
179
+ # Extract current status from spec
180
+ local local_status=$(echo "$spec_content" | grep "^status:" | cut -d: -f2 | tr -d ' ')
181
+ local ado_status=$(map_local_status_to_ado "$local_status")
182
+
183
+ local api_url="https://dev.azure.com/${org}/${project}/_apis/wit/workitems/${work_item_id}?api-version=7.0"
184
+
185
+ # Create update payload
186
+ local payload=$(cat <<EOF
187
+ [
188
+ {
189
+ "op": "add",
190
+ "path": "/fields/System.State",
191
+ "value": "$ado_status"
192
+ },
193
+ {
194
+ "op": "add",
195
+ "path": "/fields/System.History",
196
+ "value": "Updated from SpecWeave living docs"
197
+ }
198
+ ]
199
+ EOF
200
+ )
201
+
202
+ log_debug "Updating ADO work item $work_item_id with status: $ado_status"
203
+
204
+ curl -s -X PATCH \
205
+ -u ":${pat}" \
206
+ -H "Content-Type: application/json-patch+json" \
207
+ -d "$payload" \
208
+ "$api_url" > /dev/null
209
+
210
+ if [ $? -ne 0 ]; then
211
+ log_error "Failed to update ADO work item"
212
+ return 1
213
+ fi
214
+
215
+ log_info "Updated ADO work item $work_item_id"
216
+ }
217
+
218
+ # ============================================================================
219
+ # Conflict Resolution - CRITICAL: External Wins!
220
+ # ============================================================================
221
+
222
+ resolve_status_conflict() {
223
+ local spec_path=$1
224
+ local local_status=$2
225
+ local external_status=$3
226
+
227
+ local mapped_external=$(map_ado_status_to_local "$external_status")
228
+
229
+ if [ "$local_status" != "$mapped_external" ]; then
230
+ log_info "Status conflict detected:"
231
+ log_info " Local: $local_status"
232
+ log_info " External: $external_status (mapped: $mapped_external)"
233
+ log_info " Resolution: EXTERNAL WINS - applying $mapped_external"
234
+
235
+ # Update local spec with external status
236
+ sed -i.bak "s/^status: .*/status: $mapped_external/" "$spec_path"
237
+
238
+ # Add sync metadata
239
+ local timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
240
+
241
+ # Check if syncedAt exists, update or add
242
+ if grep -q "syncedAt:" "$spec_path"; then
243
+ sed -i.bak "s/syncedAt: .*/syncedAt: \"$timestamp\"/" "$spec_path"
244
+ else
245
+ # Add after externalLinks section
246
+ sed -i.bak "/externalLinks:/a\\
247
+ syncedAt: \"$timestamp\"" "$spec_path"
248
+ fi
249
+
250
+ # Clean up backup files
251
+ rm -f "${spec_path}.bak"
252
+
253
+ log_info "Local spec updated with external status: $mapped_external"
254
+ return 0
255
+ else
256
+ log_debug "No status conflict - local and external match: $local_status"
257
+ return 0
258
+ fi
259
+ }
260
+
261
+ # ============================================================================
262
+ # Main Sync Function
263
+ # ============================================================================
264
+
265
+ sync_spec_with_ado() {
266
+ local spec_path=$1
267
+
268
+ if [ ! -f "$spec_path" ]; then
269
+ log_error "Spec file not found: $spec_path"
270
+ return 1
271
+ fi
272
+
273
+ local spec_name=$(basename "$spec_path")
274
+ log_info "Syncing spec: $spec_name"
275
+
276
+ # Read spec content
277
+ local spec_content=$(cat "$spec_path")
278
+
279
+ # Extract ADO work item ID from metadata
280
+ local work_item_id=$(echo "$spec_content" | grep -A5 "externalLinks:" | grep -A3 "ado:" | grep "featureId:" | cut -d: -f2 | tr -d ' ')
281
+
282
+ if [ -z "$work_item_id" ]; then
283
+ log_debug "No ADO work item linked to spec, skipping sync"
284
+ return 0
285
+ fi
286
+
287
+ log_info "Found ADO work item ID: $work_item_id"
288
+
289
+ # Step 1: Push updates to ADO (content changes)
290
+ update_ado_work_item "$work_item_id" "$spec_content"
291
+
292
+ # Step 2: CRITICAL - Pull status from ADO (external wins!)
293
+ local external_status=$(get_ado_work_item_status "$work_item_id")
294
+
295
+ if [ -z "$external_status" ]; then
296
+ log_error "Could not fetch ADO status"
297
+ return 1
298
+ fi
299
+
300
+ log_info "ADO status: $external_status"
301
+
302
+ # Step 3: Extract local status
303
+ local local_status=$(echo "$spec_content" | grep "^status:" | cut -d: -f2 | tr -d ' ')
304
+
305
+ log_info "Local status: $local_status"
306
+
307
+ # Step 4: Resolve conflicts - EXTERNAL WINS
308
+ resolve_status_conflict "$spec_path" "$local_status" "$external_status"
309
+
310
+ log_info "Sync completed for $spec_name"
311
+ }
312
+
313
+ # ============================================================================
314
+ # Entry Point
315
+ # ============================================================================
316
+
317
+ main() {
318
+ log_info "=== Post Living Docs Update Hook Started ==="
319
+
320
+ # Get the spec path from arguments or environment
321
+ local spec_path="${1:-$SPECWEAVE_UPDATED_SPEC}"
322
+
323
+ if [ -z "$spec_path" ]; then
324
+ log_error "No spec path provided"
325
+ exit 1
326
+ fi
327
+
328
+ # Detect external tool
329
+ local tool=$(detect_external_tool "$spec_path")
330
+
331
+ if [ "$tool" != "ado" ]; then
332
+ log_debug "Not an ADO-linked spec, skipping"
333
+ exit 0
334
+ fi
335
+
336
+ log_info "Detected ADO integration for spec"
337
+
338
+ # Perform sync
339
+ sync_spec_with_ado "$spec_path"
340
+
341
+ local exit_code=$?
342
+
343
+ if [ $exit_code -eq 0 ]; then
344
+ log_info "=== Sync completed successfully ==="
345
+ else
346
+ log_error "=== Sync failed with exit code: $exit_code ==="
347
+ fi
348
+
349
+ exit $exit_code
350
+ }
351
+
352
+ # Run main function
353
+ main "$@"