specweave 0.6.7 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/.claude-plugin/README.md +1 -1
  2. package/CLAUDE.md +920 -107
  3. package/README.md +143 -207
  4. package/bin/specweave.js +67 -0
  5. package/dist/adapters/adapter-interface.d.ts +11 -11
  6. package/dist/adapters/adapter-interface.d.ts.map +1 -1
  7. package/dist/adapters/adapter-interface.js +1 -1
  8. package/dist/adapters/adapter-loader.d.ts +1 -2
  9. package/dist/adapters/adapter-loader.d.ts.map +1 -1
  10. package/dist/adapters/adapter-loader.js +3 -6
  11. package/dist/adapters/adapter-loader.js.map +1 -1
  12. package/dist/adapters/agents-md-generator.d.ts +3 -3
  13. package/dist/adapters/agents-md-generator.js +3 -3
  14. package/dist/adapters/generic/adapter.d.ts +2 -2
  15. package/dist/adapters/generic/adapter.d.ts.map +1 -1
  16. package/dist/adapters/generic/adapter.js +28 -9
  17. package/dist/adapters/generic/adapter.js.map +1 -1
  18. package/dist/cli/commands/abandon.d.ts +13 -0
  19. package/dist/cli/commands/abandon.d.ts.map +1 -0
  20. package/dist/cli/commands/abandon.js +15 -0
  21. package/dist/cli/commands/abandon.js.map +1 -0
  22. package/dist/cli/commands/init.d.ts.map +1 -1
  23. package/dist/cli/commands/init.js +141 -40
  24. package/dist/cli/commands/init.js.map +1 -1
  25. package/dist/cli/commands/pause.d.ts +13 -0
  26. package/dist/cli/commands/pause.d.ts.map +1 -0
  27. package/dist/cli/commands/pause.js +15 -0
  28. package/dist/cli/commands/pause.js.map +1 -0
  29. package/dist/cli/commands/qa.d.ts +54 -0
  30. package/dist/cli/commands/qa.d.ts.map +1 -0
  31. package/dist/cli/commands/qa.js +98 -0
  32. package/dist/cli/commands/qa.js.map +1 -0
  33. package/dist/cli/commands/resume.d.ts +12 -0
  34. package/dist/cli/commands/resume.d.ts.map +1 -0
  35. package/dist/cli/commands/resume.js +14 -0
  36. package/dist/cli/commands/resume.js.map +1 -0
  37. package/dist/cli/commands/status.d.ts +12 -0
  38. package/dist/cli/commands/status.d.ts.map +1 -0
  39. package/dist/cli/commands/status.js +23 -0
  40. package/dist/cli/commands/status.js.map +1 -0
  41. package/dist/cli/helpers/issue-tracker/ado.d.ts +57 -0
  42. package/dist/cli/helpers/issue-tracker/ado.d.ts.map +1 -0
  43. package/dist/cli/helpers/issue-tracker/ado.js +223 -0
  44. package/dist/cli/helpers/issue-tracker/ado.js.map +1 -0
  45. package/dist/cli/helpers/issue-tracker/github.d.ts +65 -0
  46. package/dist/cli/helpers/issue-tracker/github.d.ts.map +1 -0
  47. package/dist/cli/helpers/issue-tracker/github.js +284 -0
  48. package/dist/cli/helpers/issue-tracker/github.js.map +1 -0
  49. package/dist/cli/helpers/issue-tracker/index.d.ts +22 -0
  50. package/dist/cli/helpers/issue-tracker/index.d.ts.map +1 -0
  51. package/dist/cli/helpers/issue-tracker/index.js +270 -0
  52. package/dist/cli/helpers/issue-tracker/index.js.map +1 -0
  53. package/dist/cli/helpers/issue-tracker/jira.d.ts +61 -0
  54. package/dist/cli/helpers/issue-tracker/jira.d.ts.map +1 -0
  55. package/dist/cli/helpers/issue-tracker/jira.js +265 -0
  56. package/dist/cli/helpers/issue-tracker/jira.js.map +1 -0
  57. package/dist/cli/helpers/issue-tracker/types.d.ts +86 -0
  58. package/dist/cli/helpers/issue-tracker/types.d.ts.map +1 -0
  59. package/dist/cli/helpers/issue-tracker/types.js +16 -0
  60. package/dist/cli/helpers/issue-tracker/types.js.map +1 -0
  61. package/dist/cli/helpers/issue-tracker/utils.d.ts +103 -0
  62. package/dist/cli/helpers/issue-tracker/utils.d.ts.map +1 -0
  63. package/dist/cli/helpers/issue-tracker/utils.js +240 -0
  64. package/dist/cli/helpers/issue-tracker/utils.js.map +1 -0
  65. package/dist/core/increment/limits.d.ts +68 -0
  66. package/dist/core/increment/limits.d.ts.map +1 -0
  67. package/dist/core/increment/limits.js +224 -0
  68. package/dist/core/increment/limits.js.map +1 -0
  69. package/dist/core/increment/metadata-manager.d.ts +114 -0
  70. package/dist/core/increment/metadata-manager.d.ts.map +1 -0
  71. package/dist/core/increment/metadata-manager.js +320 -0
  72. package/dist/core/increment/metadata-manager.js.map +1 -0
  73. package/dist/core/increment/status-commands.d.ts +43 -0
  74. package/dist/core/increment/status-commands.d.ts.map +1 -0
  75. package/dist/core/increment/status-commands.js +277 -0
  76. package/dist/core/increment/status-commands.js.map +1 -0
  77. package/dist/core/plugin-detector.d.ts +1 -0
  78. package/dist/core/plugin-detector.d.ts.map +1 -1
  79. package/dist/core/plugin-detector.js +25 -0
  80. package/dist/core/plugin-detector.js.map +1 -1
  81. package/dist/core/qa/qa-runner.d.ts +16 -0
  82. package/dist/core/qa/qa-runner.d.ts.map +1 -0
  83. package/dist/core/qa/qa-runner.js +404 -0
  84. package/dist/core/qa/qa-runner.js.map +1 -0
  85. package/dist/core/qa/quality-gate-decider.d.ts +53 -0
  86. package/dist/core/qa/quality-gate-decider.d.ts.map +1 -0
  87. package/dist/core/qa/quality-gate-decider.js +268 -0
  88. package/dist/core/qa/quality-gate-decider.js.map +1 -0
  89. package/dist/core/qa/risk-calculator.d.ts +126 -0
  90. package/dist/core/qa/risk-calculator.d.ts.map +1 -0
  91. package/dist/core/qa/risk-calculator.js +247 -0
  92. package/dist/core/qa/risk-calculator.js.map +1 -0
  93. package/dist/core/qa/types.d.ts +315 -0
  94. package/dist/core/qa/types.d.ts.map +1 -0
  95. package/dist/core/qa/types.js +8 -0
  96. package/dist/core/qa/types.js.map +1 -0
  97. package/dist/core/types/config.d.ts +37 -2
  98. package/dist/core/types/config.d.ts.map +1 -1
  99. package/dist/core/types/config.js +16 -0
  100. package/dist/core/types/config.js.map +1 -1
  101. package/dist/core/types/increment-metadata.d.ts +120 -0
  102. package/dist/core/types/increment-metadata.d.ts.map +1 -0
  103. package/dist/core/types/increment-metadata.js +138 -0
  104. package/dist/core/types/increment-metadata.js.map +1 -0
  105. package/dist/hooks/lib/invoke-translator-skill.d.ts +60 -0
  106. package/dist/hooks/lib/invoke-translator-skill.d.ts.map +1 -0
  107. package/dist/hooks/lib/invoke-translator-skill.js +201 -0
  108. package/dist/hooks/lib/invoke-translator-skill.js.map +1 -0
  109. package/dist/hooks/lib/translate-file.d.ts +59 -0
  110. package/dist/hooks/lib/translate-file.d.ts.map +1 -0
  111. package/dist/hooks/lib/translate-file.js +350 -0
  112. package/dist/hooks/lib/translate-file.js.map +1 -0
  113. package/dist/locales/en/cli.json +3 -1
  114. package/dist/metrics/calculators/change-failure-rate.d.ts +22 -0
  115. package/dist/metrics/calculators/change-failure-rate.d.ts.map +1 -0
  116. package/dist/metrics/calculators/change-failure-rate.js +70 -0
  117. package/dist/metrics/calculators/change-failure-rate.js.map +1 -0
  118. package/dist/metrics/calculators/deployment-frequency.d.ts +20 -0
  119. package/dist/metrics/calculators/deployment-frequency.d.ts.map +1 -0
  120. package/dist/metrics/calculators/deployment-frequency.js +61 -0
  121. package/dist/metrics/calculators/deployment-frequency.js.map +1 -0
  122. package/dist/metrics/calculators/lead-time.d.ts +22 -0
  123. package/dist/metrics/calculators/lead-time.d.ts.map +1 -0
  124. package/dist/metrics/calculators/lead-time.js +82 -0
  125. package/dist/metrics/calculators/lead-time.js.map +1 -0
  126. package/dist/metrics/calculators/mttr.d.ts +21 -0
  127. package/dist/metrics/calculators/mttr.d.ts.map +1 -0
  128. package/dist/metrics/calculators/mttr.js +60 -0
  129. package/dist/metrics/calculators/mttr.js.map +1 -0
  130. package/dist/metrics/dora-calculator.d.ts +24 -0
  131. package/dist/metrics/dora-calculator.d.ts.map +1 -0
  132. package/dist/metrics/dora-calculator.js +104 -0
  133. package/dist/metrics/dora-calculator.js.map +1 -0
  134. package/dist/metrics/github-client.d.ts +51 -0
  135. package/dist/metrics/github-client.d.ts.map +1 -0
  136. package/dist/metrics/github-client.js +133 -0
  137. package/dist/metrics/github-client.js.map +1 -0
  138. package/dist/metrics/types.d.ts +112 -0
  139. package/dist/metrics/types.d.ts.map +1 -0
  140. package/dist/metrics/types.js +10 -0
  141. package/dist/metrics/types.js.map +1 -0
  142. package/dist/metrics/utils/percentile.d.ts +25 -0
  143. package/dist/metrics/utils/percentile.d.ts.map +1 -0
  144. package/dist/metrics/utils/percentile.js +46 -0
  145. package/dist/metrics/utils/percentile.js.map +1 -0
  146. package/dist/metrics/utils/tier-classifier.d.ts +61 -0
  147. package/dist/metrics/utils/tier-classifier.d.ts.map +1 -0
  148. package/dist/metrics/utils/tier-classifier.js +100 -0
  149. package/dist/metrics/utils/tier-classifier.js.map +1 -0
  150. package/dist/utils/auth-helpers.d.ts +58 -0
  151. package/dist/utils/auth-helpers.d.ts.map +1 -0
  152. package/dist/utils/auth-helpers.js +108 -0
  153. package/dist/utils/auth-helpers.js.map +1 -0
  154. package/dist/utils/env-file.d.ts +88 -0
  155. package/dist/utils/env-file.d.ts.map +1 -0
  156. package/dist/utils/env-file.js +180 -0
  157. package/dist/utils/env-file.js.map +1 -0
  158. package/dist/utils/plugin-detection.d.ts +50 -0
  159. package/dist/utils/plugin-detection.d.ts.map +1 -0
  160. package/dist/utils/plugin-detection.js +229 -0
  161. package/dist/utils/plugin-detection.js.map +1 -0
  162. package/dist/utils/secrets-loader.d.ts +88 -0
  163. package/dist/utils/secrets-loader.d.ts.map +1 -0
  164. package/dist/utils/secrets-loader.js +271 -0
  165. package/dist/utils/secrets-loader.js.map +1 -0
  166. package/dist/utils/translation.d.ts +187 -0
  167. package/dist/utils/translation.d.ts.map +1 -0
  168. package/dist/utils/translation.js +414 -0
  169. package/dist/utils/translation.js.map +1 -0
  170. package/package.json +28 -44
  171. package/plugins/specweave/.claude-plugin/plugin.json +3 -3
  172. package/plugins/specweave/agents/pm/AGENT.md +330 -54
  173. package/plugins/specweave/agents/test-aware-planner/AGENT.md +1035 -0
  174. package/plugins/specweave/agents/test-aware-planner/templates/README.md +118 -0
  175. package/plugins/specweave/agents/test-aware-planner/templates/task-non-testable.md.template +24 -0
  176. package/plugins/specweave/agents/test-aware-planner/templates/task-testable.md.template +53 -0
  177. package/plugins/specweave/agents/test-aware-planner/templates/tasks-frontmatter.md.template +11 -0
  178. package/plugins/specweave/commands/README.md +88 -163
  179. package/plugins/specweave/commands/specweave-abandon.md +314 -0
  180. package/plugins/specweave/commands/specweave-check-tests.md +546 -0
  181. package/plugins/specweave/commands/{do.md → specweave-do.md} +5 -5
  182. package/plugins/specweave/commands/{done.md → specweave-done.md} +2 -0
  183. package/plugins/specweave/commands/{increment.md → specweave-increment.md} +231 -4
  184. package/plugins/specweave/commands/specweave-pause.md +189 -0
  185. package/plugins/specweave/commands/specweave-qa.md +245 -0
  186. package/plugins/specweave/commands/specweave-resume.md +216 -0
  187. package/plugins/specweave/commands/specweave-status.md +397 -0
  188. package/plugins/specweave/commands/specweave-sync-tasks.md +256 -0
  189. package/plugins/specweave/commands/{translate.md → specweave-translate.md} +3 -3
  190. package/plugins/specweave/commands/specweave-update-scope.md +351 -0
  191. package/plugins/specweave/commands/{validate.md → specweave-validate.md} +2 -0
  192. package/plugins/specweave/commands/specweave.md +21 -21
  193. package/plugins/specweave/hooks/docs-changed.sh +23 -3
  194. package/plugins/specweave/hooks/human-input-required.sh +23 -3
  195. package/plugins/specweave/hooks/post-increment-planning.sh +335 -0
  196. package/plugins/specweave/hooks/post-task-completion.sh +161 -1
  197. package/plugins/specweave/hooks/pre-implementation.sh +23 -3
  198. package/plugins/specweave/skills/SKILLS-INDEX.md +1 -1
  199. package/plugins/specweave/skills/brownfield-analyzer/SKILL.md +9 -9
  200. package/plugins/specweave/skills/increment-planner/SKILL.md +400 -212
  201. package/plugins/specweave/skills/increment-quality-judge-v2/SKILL.md +499 -0
  202. package/plugins/specweave/skills/plugin-detector/SKILL.md +114 -1
  203. package/plugins/specweave/skills/project-kickstarter/SKILL.md +74 -1
  204. package/plugins/specweave/skills/{rfc-generator → spec-generator}/SKILL.md +22 -29
  205. package/plugins/specweave/skills/specweave-detector/SKILL.md +3 -3
  206. package/plugins/specweave/skills/specweave-framework/SKILL.md +2 -2
  207. package/plugins/specweave-ado/.claude-plugin/plugin.json +18 -4
  208. package/plugins/specweave-ado/agents/ado-manager/AGENT.md +426 -0
  209. package/plugins/specweave-ado/commands/close-workitem.md +52 -0
  210. package/plugins/specweave-ado/commands/create-workitem.md +53 -0
  211. package/plugins/specweave-ado/commands/status.md +53 -0
  212. package/plugins/specweave-ado/commands/sync.md +55 -0
  213. package/plugins/specweave-ado/lib/ado-client.ts +361 -0
  214. package/plugins/specweave-ado/reference/ado-specweave-mapping.md +552 -0
  215. package/plugins/specweave-ado/skills/ado-sync/SKILL.md +344 -193
  216. package/plugins/specweave-docs/skills/docusaurus/SKILL.md +73 -0
  217. package/plugins/specweave-github/agents/github-manager/AGENT.md +49 -0
  218. package/plugins/specweave-github/commands/{github-close-issue.md → close-issue.md} +1 -1
  219. package/plugins/specweave-github/commands/{github-create-issue.md → create-issue.md} +1 -1
  220. package/plugins/specweave-github/commands/{github-status.md → status.md} +1 -1
  221. package/plugins/specweave-github/commands/{github-sync-tasks.md → sync-tasks.md} +1 -1
  222. package/plugins/specweave-github/commands/{github-sync.md → sync.md} +1 -1
  223. package/plugins/specweave-github/reference/github-specweave-mapping.md +377 -0
  224. package/plugins/specweave-github/skills/github-sync/SKILL.md +11 -3
  225. package/plugins/specweave-infrastructure/commands/{specweave.monitor-setup.md → monitor-setup.md} +5 -0
  226. package/plugins/specweave-infrastructure/commands/{specweave.slo-implement.md → slo-implement.md} +5 -0
  227. package/plugins/specweave-jira/agents/jira-manager/AGENT.md +380 -0
  228. package/plugins/specweave-jira/commands/{specweave.sync-jira.md → sync.md} +1 -1
  229. package/plugins/specweave-jira/reference/jira-specweave-mapping.md +508 -0
  230. package/plugins/specweave-ml/commands/ml-deploy.md +1 -1
  231. package/plugins/specweave-ml/commands/ml-evaluate.md +1 -1
  232. package/plugins/specweave-ml/commands/ml-explain.md +1 -1
  233. package/plugins/specweave-ml/commands/{specweave.ml-pipeline.md → ml-pipeline.md} +5 -0
  234. package/src/templates/AGENTS.md.template +652 -1
  235. package/src/templates/CLAUDE.md.template +36 -21
  236. package/src/templates/COMPLETION-REPORT.template.md +128 -0
  237. package/src/templates/README.md.template +17 -16
  238. package/src/templates/docs/README.md +11 -9
  239. package/src/templates/docs/spec-template.md +229 -0
  240. package/dist/adapters/copilot/adapter.d.ts +0 -86
  241. package/dist/adapters/copilot/adapter.d.ts.map +0 -1
  242. package/dist/adapters/copilot/adapter.js +0 -396
  243. package/dist/adapters/copilot/adapter.js.map +0 -1
  244. package/plugins/.specweave/logs/hooks-debug.log +0 -24
  245. package/plugins/.specweave/logs/last-hook-fire +0 -1
  246. package/plugins/.specweave/logs/last-todowrite-time +0 -1
  247. package/plugins/.specweave/logs/tasks.log +0 -6
  248. package/plugins/specweave/commands/inc.md +0 -85
  249. package/plugins/specweave/commands/list-increments.md +0 -180
  250. package/src/adapters/README.md +0 -311
  251. package/src/adapters/adapter-base.ts +0 -182
  252. package/src/adapters/adapter-interface.ts +0 -166
  253. package/src/adapters/adapter-loader.ts +0 -259
  254. package/src/adapters/agents-md-generator.ts +0 -228
  255. package/src/adapters/claude/README.md +0 -233
  256. package/src/adapters/claude/adapter.ts +0 -468
  257. package/src/adapters/claude-md-generator.ts +0 -377
  258. package/src/adapters/codex/README.md +0 -105
  259. package/src/adapters/codex/adapter.ts +0 -333
  260. package/src/adapters/copilot/README.md +0 -240
  261. package/src/adapters/copilot/adapter.ts +0 -444
  262. package/src/adapters/cursor/.cursor/context/docs-context.md +0 -62
  263. package/src/adapters/cursor/.cursor/context/increments-context.md +0 -71
  264. package/src/adapters/cursor/.cursor/context/strategy-context.md +0 -73
  265. package/src/adapters/cursor/.cursor/context/tests-context.md +0 -89
  266. package/src/adapters/cursor/README.md +0 -283
  267. package/src/adapters/cursor/adapter.ts +0 -451
  268. package/src/adapters/doc-generator.ts +0 -331
  269. package/src/adapters/gemini/README.md +0 -97
  270. package/src/adapters/gemini/adapter.ts +0 -298
  271. package/src/adapters/generic/README.md +0 -277
  272. package/src/adapters/generic/adapter.ts +0 -359
  273. package/src/adapters/registry.yaml +0 -187
  274. /package/plugins/specweave/commands/{costs.md → specweave-costs.md} +0 -0
  275. /package/plugins/specweave/commands/{next.md → specweave-next.md} +0 -0
  276. /package/plugins/specweave/commands/{progress.md → specweave-progress.md} +0 -0
  277. /package/plugins/specweave/commands/{sync-docs.md → specweave-sync-docs.md} +0 -0
  278. /package/plugins/specweave/commands/{tdd-cycle.md → specweave-tdd-cycle.md} +0 -0
  279. /package/plugins/specweave/commands/{tdd-green.md → specweave-tdd-green.md} +0 -0
  280. /package/plugins/specweave/commands/{tdd-red.md → specweave-tdd-red.md} +0 -0
  281. /package/plugins/specweave/commands/{tdd-refactor.md → specweave-tdd-refactor.md} +0 -0
@@ -43,11 +43,11 @@ This master command routes to SpecWeave increment lifecycle subcommands.
43
43
 
44
44
  | Subcommand | Description | Example |
45
45
  |------------|-------------|---------|
46
- | **github.create-issue** | Create GitHub issue from increment | `/specweave github.create-issue 0001` |
47
- | **github.sync** | Bidirectional sync with GitHub | `/specweave github.sync 0001` |
48
- | **github.sync-tasks** | Sync tasks as GitHub sub-issues | `/specweave github.sync-tasks 0001` |
49
- | **github.close-issue** | Close GitHub issue | `/specweave github.close-issue 0001` |
50
- | **github.status** | Show GitHub sync status | `/specweave github.status` |
46
+ | **github:create-issue** | Create GitHub issue from increment | `/specweave-github:create-issue 0001` |
47
+ | **github:sync** | Bidirectional sync with GitHub | `/specweave-github:sync 0001` |
48
+ | **github:sync-tasks** | Sync tasks as GitHub sub-issues | `/specweave-github:sync-tasks 0001` |
49
+ | **github:close-issue** | Close GitHub issue | `/specweave-github:close-issue 0001` |
50
+ | **github:status** | Show GitHub sync status | `/specweave-github:status` |
51
51
 
52
52
  ---
53
53
 
@@ -73,11 +73,11 @@ subcommands:
73
73
  sync-jira: .claude/commands/specweave:sync-jira.md
74
74
 
75
75
  # GitHub Plugin Commands
76
- github.create-issue: .claude/commands/specweave-github:github-create-issue.md
77
- github.sync: .claude/commands/specweave-github:github-sync.md
78
- github.sync-tasks: .claude/commands/specweave-github:github-sync-tasks.md
79
- github.close-issue: .claude/commands/specweave-github:github-close-issue.md
80
- github.status: .claude/commands/specweave-github:github-status.md
76
+ github:create-issue: .claude/commands/specweave-github:create-issue.md
77
+ github:sync: .claude/commands/specweave-github:sync.md
78
+ github:sync-tasks: .claude/commands/specweave-github:sync-tasks.md
79
+ github:close-issue: .claude/commands/specweave-github:close-issue.md
80
+ github:status: .claude/commands/specweave-github:status.md
81
81
  ```
82
82
 
83
83
  ---
@@ -183,15 +183,15 @@ Available subcommands:
183
183
  sync-docs - Sync documentation (review/update)
184
184
 
185
185
  GitHub Plugin:
186
- github.create-issue - Create GitHub issue from increment
187
- github.sync - Bidirectional sync with GitHub
188
- github.sync-tasks - Sync tasks as GitHub sub-issues
189
- github.close-issue - Close GitHub issue
190
- github.status - Show GitHub sync status
186
+ github:create-issue - Create GitHub issue from increment
187
+ github:sync - Bidirectional sync with GitHub
188
+ github:sync-tasks - Sync tasks as GitHub sub-issues
189
+ github:close-issue - Close GitHub issue
190
+ github:status - Show GitHub sync status
191
191
 
192
192
  Usage: /specweave <subcommand> [arguments]
193
193
  Example: /specweave inc "User authentication"
194
- Example: /specweave github.create-issue 0001
194
+ Example: /specweave-github:create-issue 0001
195
195
  ```
196
196
 
197
197
  ---
@@ -433,11 +433,11 @@ Project Setup:
433
433
  sync-docs [mode] [id] - Sync documentation (review/update)
434
434
 
435
435
  GitHub Plugin:
436
- github.create-issue <id> - Create GitHub issue from increment
437
- github.sync <id> - Bidirectional sync with GitHub
438
- github.sync-tasks <id> - Sync tasks as GitHub sub-issues
439
- github.close-issue <id> - Close GitHub issue
440
- github.status - Show GitHub sync status
436
+ github:create-issue <id> - Create GitHub issue from increment
437
+ github:sync <id> - Bidirectional sync with GitHub
438
+ github:sync-tasks <id> - Sync tasks as GitHub sub-issues
439
+ github:close-issue <id> - Close GitHub issue
440
+ github:status - Show GitHub sync status
441
441
 
442
442
  Examples:
443
443
  /specweave inc "User authentication"
@@ -7,7 +7,26 @@
7
7
 
8
8
  set -e
9
9
 
10
- PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
10
+ # Find project root by searching upward for .specweave/ directory
11
+ # Works regardless of where hook is installed (source or .claude/hooks/)
12
+ find_project_root() {
13
+ local dir="$1"
14
+ while [ "$dir" != "/" ]; do
15
+ if [ -d "$dir/.specweave" ]; then
16
+ echo "$dir"
17
+ return 0
18
+ fi
19
+ dir="$(dirname "$dir")"
20
+ done
21
+ # Fallback: try current directory
22
+ if [ -d "$(pwd)/.specweave" ]; then
23
+ pwd
24
+ else
25
+ echo "$(pwd)"
26
+ fi
27
+ }
28
+
29
+ PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
11
30
  cd "$PROJECT_ROOT"
12
31
 
13
32
  # Colors
@@ -54,6 +73,7 @@ if [ -n "$DOC_CHANGES" ]; then
54
73
  esac
55
74
 
56
75
  # Log to hooks log
57
- mkdir -p .specweave/logs
58
- echo "[$(date)] Documentation changed: $DOC_CHANGES" >> .specweave/logs/hooks.log
76
+ LOGS_DIR=".specweave/logs"
77
+ mkdir -p "$LOGS_DIR"
78
+ echo "[$(date)] Documentation changed: $DOC_CHANGES" >> "$LOGS_DIR/hooks.log"
59
79
  fi
@@ -10,7 +10,26 @@
10
10
 
11
11
  set -e
12
12
 
13
- PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
13
+ # Find project root by searching upward for .specweave/ directory
14
+ # Works regardless of where hook is installed (source or .claude/hooks/)
15
+ find_project_root() {
16
+ local dir="$1"
17
+ while [ "$dir" != "/" ]; do
18
+ if [ -d "$dir/.specweave" ]; then
19
+ echo "$dir"
20
+ return 0
21
+ fi
22
+ dir="$(dirname "$dir")"
23
+ done
24
+ # Fallback: try current directory
25
+ if [ -d "$(pwd)/.specweave" ]; then
26
+ pwd
27
+ else
28
+ echo "$(pwd)"
29
+ fi
30
+ }
31
+
32
+ PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
14
33
  cd "$PROJECT_ROOT"
15
34
 
16
35
  # Get question/requirement (passed as argument or default)
@@ -37,8 +56,9 @@ play_sound() {
37
56
  play_sound &
38
57
 
39
58
  # 2. Log to main hooks log
40
- mkdir -p .specweave/logs
41
- echo "[$(date)] Human input required: $QUESTION" >> .specweave/logs/hooks.log
59
+ LOGS_DIR=".specweave/logs"
60
+ mkdir -p "$LOGS_DIR"
61
+ echo "[$(date)] Human input required: $QUESTION" >> "$LOGS_DIR/hooks.log"
42
62
 
43
63
  # 3. Log to current work context (if exists)
44
64
  CURRENT_WORK=$(find .specweave/work -maxdepth 1 -type d -name "current-*" | head -1 || true)
@@ -0,0 +1,335 @@
1
+ #!/bin/bash
2
+
3
+ # SpecWeave Post-Increment-Planning Hook
4
+ # Runs automatically after /specweave:inc completes
5
+ #
6
+ # PURPOSE:
7
+ # Translates newly generated spec.md, plan.md, and tasks.md from target language
8
+ # back to English for maintainability.
9
+ #
10
+ # WHY THIS MATTERS:
11
+ # - User works in native language (great UX during planning)
12
+ # - Framework translates to English automatically (maintainable docs)
13
+ # - Cost: ~$0.01 per increment (using Haiku)
14
+ #
15
+ # WORKFLOW:
16
+ # 1. User runs: /specweave:inc "Š”Š¾Š±Š°Š²ŠøŃ‚ŃŒ AI чат-бот" (in Russian)
17
+ # 2. PM agent generates spec.md in Russian (natural, user-friendly)
18
+ # 3. THIS HOOK fires automatically
19
+ # 4. Detects non-English content
20
+ # 5. Translates spec.md, plan.md, tasks.md to English
21
+ # 6. Files now in English (maintainable)
22
+ #
23
+ # @see .specweave/increments/0006-llm-native-i18n/reports/DESIGN-POST-GENERATION-TRANSLATION.md
24
+
25
+ set -e
26
+
27
+ # ============================================================================
28
+ # PROJECT ROOT DETECTION
29
+ # ============================================================================
30
+
31
+ # Find project root by searching upward for .specweave/ directory
32
+ find_project_root() {
33
+ local dir="$1"
34
+ while [ "$dir" != "/" ]; do
35
+ if [ -d "$dir/.specweave" ]; then
36
+ echo "$dir"
37
+ return 0
38
+ fi
39
+ dir="$(dirname "$dir")"
40
+ done
41
+ # Fallback: try current directory
42
+ if [ -d "$(pwd)/.specweave" ]; then
43
+ pwd
44
+ else
45
+ echo "$(pwd)"
46
+ fi
47
+ }
48
+
49
+ PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
50
+ cd "$PROJECT_ROOT" 2>/dev/null || true
51
+
52
+ # ============================================================================
53
+ # CONFIGURATION
54
+ # ============================================================================
55
+
56
+ # Translation settings (can be overridden by .specweave/config.json)
57
+ TRANSLATION_ENABLED=true
58
+ AUTO_TRANSLATE_INTERNAL_DOCS=true
59
+ TARGET_LANGUAGE="en" # Always translate TO English (for maintainability)
60
+
61
+ # Paths
62
+ SPECWEAVE_DIR=".specweave"
63
+ INCREMENTS_DIR="$SPECWEAVE_DIR/increments"
64
+ LOGS_DIR="$SPECWEAVE_DIR/logs"
65
+ CONFIG_FILE="$SPECWEAVE_DIR/config.json"
66
+ DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
67
+
68
+ mkdir -p "$LOGS_DIR" 2>/dev/null || true
69
+
70
+ # ============================================================================
71
+ # LOGGING
72
+ # ============================================================================
73
+
74
+ log_debug() {
75
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [post-increment-planning] $1" >> "$DEBUG_LOG" 2>/dev/null || true
76
+ }
77
+
78
+ log_info() {
79
+ echo "$1"
80
+ log_debug "$1"
81
+ }
82
+
83
+ log_error() {
84
+ echo "āŒ $1" >&2
85
+ log_debug "ERROR: $1"
86
+ }
87
+
88
+ # ============================================================================
89
+ # CONFIGURATION LOADING
90
+ # ============================================================================
91
+
92
+ load_config() {
93
+ if [ ! -f "$CONFIG_FILE" ]; then
94
+ log_debug "No config file found, using defaults"
95
+ return
96
+ fi
97
+
98
+ # Check if translation is enabled in config
99
+ local translation_enabled=$(cat "$CONFIG_FILE" | grep -o '"enabled"[[:space:]]*:[[:space:]]*\(true\|false\)' | grep -o '\(true\|false\)' || echo "true")
100
+
101
+ if [ "$translation_enabled" = "false" ]; then
102
+ TRANSLATION_ENABLED=false
103
+ log_debug "Translation disabled in config"
104
+ fi
105
+
106
+ # Check if auto-translation of internal docs is enabled
107
+ local auto_translate=$(cat "$CONFIG_FILE" | grep -o '"autoTranslateInternalDocs"[[:space:]]*:[[:space:]]*\(true\|false\)' | grep -o '\(true\|false\)' || echo "true")
108
+
109
+ if [ "$auto_translate" = "false" ]; then
110
+ AUTO_TRANSLATE_INTERNAL_DOCS=false
111
+ log_debug "Auto-translation of internal docs disabled in config"
112
+ fi
113
+ }
114
+
115
+ # ============================================================================
116
+ # INCREMENT DETECTION
117
+ # ============================================================================
118
+
119
+ get_latest_increment() {
120
+ # Find the most recently modified increment directory (excluding _backlog)
121
+ local latest=$(find "$INCREMENTS_DIR" -maxdepth 1 -type d -name "[0-9][0-9][0-9][0-9]-*" ! -name "_backlog" -exec stat -f "%m %N" {} \; 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)
122
+
123
+ if [ -z "$latest" ]; then
124
+ log_error "No increment directory found"
125
+ return 1
126
+ fi
127
+
128
+ echo "$latest"
129
+ }
130
+
131
+ # ============================================================================
132
+ # LANGUAGE DETECTION
133
+ # ============================================================================
134
+
135
+ detect_file_language() {
136
+ local file_path="$1"
137
+
138
+ if [ ! -f "$file_path" ]; then
139
+ echo "en" # Default to English if file doesn't exist
140
+ return
141
+ fi
142
+
143
+ # Count non-ASCII characters (Cyrillic, Chinese, etc.)
144
+ local total_chars=$(wc -c < "$file_path" | tr -d ' ')
145
+ local non_ascii_chars=$(LC_ALL=C grep -o '[^ -~]' "$file_path" 2>/dev/null | wc -l | tr -d ' ')
146
+
147
+ # If >10% non-ASCII, assume non-English
148
+ if [ "$total_chars" -gt 0 ]; then
149
+ local ratio=$((non_ascii_chars * 100 / total_chars))
150
+ if [ "$ratio" -gt 10 ]; then
151
+ echo "non-en"
152
+ return
153
+ fi
154
+ fi
155
+
156
+ echo "en"
157
+ }
158
+
159
+ # ============================================================================
160
+ # TRANSLATION EXECUTION
161
+ # ============================================================================
162
+
163
+ translate_file() {
164
+ local file_path="$1"
165
+ local file_name=$(basename "$file_path")
166
+
167
+ log_info " šŸ“„ Translating $file_name..."
168
+
169
+ # Call the translate-file.ts script
170
+ # In production, this would invoke the LLM via Task tool
171
+ # For now, we'll create a marker file to indicate translation is needed
172
+
173
+ if [ -f "$PROJECT_ROOT/dist/hooks/lib/translate-file.js" ]; then
174
+ # Production: Use compiled TypeScript
175
+ node "$PROJECT_ROOT/dist/hooks/lib/translate-file.js" "$file_path" --target-lang en --verbose 2>&1 | while read -r line; do
176
+ echo " $line"
177
+ done
178
+
179
+ if [ ${PIPESTATUS[0]} -eq 0 ]; then
180
+ log_info " āœ… $file_name translated successfully"
181
+ return 0
182
+ else
183
+ log_error " āš ļø Translation failed for $file_name"
184
+ return 1
185
+ fi
186
+ else
187
+ # Development/Testing: Just mark the file
188
+ log_info " ā„¹ļø Translation script not compiled (run 'npm run build')"
189
+ log_info " ā„¹ļø In production, $file_name would be translated to English"
190
+ return 0
191
+ fi
192
+ }
193
+
194
+ # ============================================================================
195
+ # MAIN LOGIC
196
+ # ============================================================================
197
+
198
+ main() {
199
+ log_debug "=== POST-INCREMENT-PLANNING HOOK START ==="
200
+
201
+ # 1. Load configuration
202
+ load_config
203
+
204
+ if [ "$TRANSLATION_ENABLED" = "false" ]; then
205
+ log_debug "Translation disabled, exiting"
206
+ cat <<EOF
207
+ {
208
+ "continue": true,
209
+ "message": "Translation disabled in config"
210
+ }
211
+ EOF
212
+ exit 0
213
+ fi
214
+
215
+ if [ "$AUTO_TRANSLATE_INTERNAL_DOCS" = "false" ]; then
216
+ log_debug "Auto-translation of internal docs disabled, exiting"
217
+ cat <<EOF
218
+ {
219
+ "continue": true,
220
+ "message": "Auto-translation of internal docs disabled"
221
+ }
222
+ EOF
223
+ exit 0
224
+ fi
225
+
226
+ # 2. Get latest increment directory
227
+ local increment_dir=$(get_latest_increment)
228
+
229
+ if [ $? -ne 0 ] || [ -z "$increment_dir" ]; then
230
+ log_error "Could not find latest increment directory"
231
+ cat <<EOF
232
+ {
233
+ "continue": true,
234
+ "error": "No increment directory found"
235
+ }
236
+ EOF
237
+ exit 0
238
+ fi
239
+
240
+ local increment_id=$(basename "$increment_dir")
241
+ log_debug "Latest increment: $increment_id"
242
+
243
+ # 3. Check if files need translation
244
+ local spec_file="$increment_dir/spec.md"
245
+ local plan_file="$increment_dir/plan.md"
246
+ local tasks_file="$increment_dir/tasks.md"
247
+
248
+ local needs_translation=false
249
+ local files_to_translate=()
250
+
251
+ # Detect language of each file
252
+ if [ -f "$spec_file" ]; then
253
+ local spec_lang=$(detect_file_language "$spec_file")
254
+ if [ "$spec_lang" = "non-en" ]; then
255
+ needs_translation=true
256
+ files_to_translate+=("$spec_file")
257
+ fi
258
+ fi
259
+
260
+ if [ -f "$plan_file" ]; then
261
+ local plan_lang=$(detect_file_language "$plan_file")
262
+ if [ "$plan_lang" = "non-en" ]; then
263
+ needs_translation=true
264
+ files_to_translate+=("$plan_file")
265
+ fi
266
+ fi
267
+
268
+ if [ -f "$tasks_file" ]; then
269
+ local tasks_lang=$(detect_file_language "$tasks_file")
270
+ if [ "$tasks_lang" = "non-en" ]; then
271
+ needs_translation=true
272
+ files_to_translate+=("$tasks_file")
273
+ fi
274
+ fi
275
+
276
+ # 4. If no translation needed, exit early
277
+ if [ "$needs_translation" = "false" ] || [ ${#files_to_translate[@]} -eq 0 ]; then
278
+ log_info "āœ… All increment files already in English, skipping translation"
279
+ cat <<EOF
280
+ {
281
+ "continue": true,
282
+ "message": "All files already in English"
283
+ }
284
+ EOF
285
+ exit 0
286
+ fi
287
+
288
+ # 5. Perform translation
289
+ log_info ""
290
+ log_info "🌐 Detected non-English content in increment $increment_id"
291
+ log_info " Translating to English for maintainability..."
292
+ log_info ""
293
+
294
+ local success_count=0
295
+ local total_count=${#files_to_translate[@]}
296
+
297
+ for file in "${files_to_translate[@]}"; do
298
+ if translate_file "$file"; then
299
+ ((success_count++))
300
+ fi
301
+ done
302
+
303
+ # 6. Summary
304
+ log_info ""
305
+ if [ "$success_count" -eq "$total_count" ]; then
306
+ log_info "āœ… Translation complete! All $total_count file(s) now in English"
307
+ log_info " Cost: ~\$0.01 (using Haiku)"
308
+ log_info ""
309
+
310
+ cat <<EOF
311
+ {
312
+ "continue": true,
313
+ "message": "Translated $total_count file(s) to English",
314
+ "files": $(printf '%s\n' "${files_to_translate[@]}" | jq -R . | jq -s .)
315
+ }
316
+ EOF
317
+ else
318
+ log_error "Translation completed with errors: $success_count/$total_count files translated"
319
+ cat <<EOF
320
+ {
321
+ "continue": true,
322
+ "warning": "Translation partially failed: $success_count/$total_count files",
323
+ "files": $(printf '%s\n' "${files_to_translate[@]}" | jq -R . | jq -s .)
324
+ }
325
+ EOF
326
+ fi
327
+
328
+ log_debug "=== POST-INCREMENT-PLANNING HOOK END ==="
329
+ }
330
+
331
+ # Run main function
332
+ main
333
+
334
+ # Always return success (non-blocking hook)
335
+ exit 0
@@ -28,7 +28,26 @@
28
28
 
29
29
  set -e
30
30
 
31
- PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
31
+ # Find project root by searching upward for .specweave/ directory
32
+ # Works regardless of where hook is installed (source or .claude/hooks/)
33
+ find_project_root() {
34
+ local dir="$1"
35
+ while [ "$dir" != "/" ]; do
36
+ if [ -d "$dir/.specweave" ]; then
37
+ echo "$dir"
38
+ return 0
39
+ fi
40
+ dir="$(dirname "$dir")"
41
+ done
42
+ # Fallback: try current directory
43
+ if [ -d "$(pwd)/.specweave" ]; then
44
+ pwd
45
+ else
46
+ echo "$(pwd)"
47
+ fi
48
+ }
49
+
50
+ PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
32
51
  cd "$PROJECT_ROOT" 2>/dev/null || true
33
52
 
34
53
  # ============================================================================
@@ -205,6 +224,147 @@ if command -v node &> /dev/null; then
205
224
  fi
206
225
  fi
207
226
 
227
+ # ============================================================================
228
+ # SYNC TO EXTERNAL TRACKERS (NEW in v0.7.0 - GitHub/Jira/ADO)
229
+ # ============================================================================
230
+
231
+ if [ -n "$CURRENT_INCREMENT" ]; then
232
+ echo "[$(date)] šŸ”— Checking external tracker sync for $CURRENT_INCREMENT" >> "$DEBUG_LOG" 2>/dev/null || true
233
+
234
+ # Check for metadata.json with GitHub/Jira issue link
235
+ METADATA_FILE=".specweave/increments/$CURRENT_INCREMENT/metadata.json"
236
+
237
+ if [ -f "$METADATA_FILE" ]; then
238
+ # Detect tracker type from metadata
239
+ GITHUB_ISSUE=$(jq -r '.github.issue // empty' "$METADATA_FILE" 2>/dev/null)
240
+ JIRA_ISSUE=$(jq -r '.jira.issue // empty' "$METADATA_FILE" 2>/dev/null)
241
+ ADO_ITEM=$(jq -r '.ado.item // empty' "$METADATA_FILE" 2>/dev/null)
242
+
243
+ # GitHub sync (if issue exists and gh CLI available)
244
+ if [ -n "$GITHUB_ISSUE" ] && command -v gh &> /dev/null; then
245
+ echo "[$(date)] šŸ”„ Syncing to GitHub issue #$GITHUB_ISSUE" >> "$DEBUG_LOG" 2>/dev/null || true
246
+
247
+ # Run GitHub sync - Update CHECKBOXES in issue description
248
+ TASKS_FILE=".specweave/increments/$CURRENT_INCREMENT/tasks.md"
249
+
250
+ if [ -f "$TASKS_FILE" ]; then
251
+ echo "[$(date)] šŸ“Š Syncing task checkboxes to GitHub issue #$GITHUB_ISSUE" >> "$DEBUG_LOG" 2>/dev/null || true
252
+
253
+ # Get list of completed tasks from tasks.md
254
+ # Find all "## T-XXX:" headers where the task has "[x]" checkbox
255
+ COMPLETED_TASK_IDS=$(awk '
256
+ /^## T-[0-9]+:/ {
257
+ task_id = $2
258
+ gsub(/:/, "", task_id)
259
+ current_task = task_id
260
+ task_title = substr($0, index($0, $3))
261
+ next
262
+ }
263
+ /^- \[x\]/ && current_task != "" {
264
+ # Found a completed checkbox under a task
265
+ print current_task
266
+ current_task = ""
267
+ }
268
+ ' "$TASKS_FILE" 2>/dev/null)
269
+
270
+ echo "[$(date)] Completed tasks found: $COMPLETED_TASK_IDS" >> "$DEBUG_LOG" 2>/dev/null || true
271
+
272
+ # Read current issue body
273
+ ISSUE_BODY=$(gh issue view "$GITHUB_ISSUE" --json body -q .body 2>/dev/null || echo "")
274
+
275
+ if [ -n "$ISSUE_BODY" ]; then
276
+ # Create temporary file for updated body
277
+ TEMP_BODY=$(mktemp)
278
+ echo "$ISSUE_BODY" > "$TEMP_BODY"
279
+
280
+ # Update checkboxes for completed tasks
281
+ # Pattern: "- [ ] task-name" -> "- [x] task-name"
282
+ for task_id in $COMPLETED_TASK_IDS; do
283
+ # Update checkbox for this task ID
284
+ # Look for patterns like "[ ] T-013:" or "[ ] CLAUDE.md updates" etc.
285
+ sed -i.bak "s/- \[ \] \(.*${task_id}.*\)/- [x] \1/g" "$TEMP_BODY" 2>/dev/null || true
286
+ sed -i.bak "s/- \[ \] \(.*T-0*${task_id#T-}[: ].*\)/- [x] \1/g" "$TEMP_BODY" 2>/dev/null || true
287
+
288
+ echo "[$(date)] Updated checkbox for task: $task_id" >> "$DEBUG_LOG" 2>/dev/null || true
289
+ done
290
+
291
+ # Also update based on task names (more reliable)
292
+ # Check for common patterns in issue body
293
+ if grep -q "test-aware-planner" "$TASKS_FILE" && grep -q "\[x\]" "$TASKS_FILE"; then
294
+ sed -i.bak "s/- \[ \] \(.*test-aware-planner.*\)/- [x] \1/g" "$TEMP_BODY" 2>/dev/null || true
295
+ fi
296
+ if grep -q "PM.*increment-planner" "$TASKS_FILE" && grep -q "\[x\]" "$TASKS_FILE"; then
297
+ sed -i.bak "s/- \[ \] \(.*PM.*increment-planner.*\)/- [x] \1/g" "$TEMP_BODY" 2>/dev/null || true
298
+ sed -i.bak "s/- \[ \] \(.*Enhanced PM.*\)/- [x] \1/g" "$TEMP_BODY" 2>/dev/null || true
299
+ fi
300
+ if grep -q "CLAUDE.md" "$TASKS_FILE" && grep -q "\[x\]" "$TASKS_FILE"; then
301
+ sed -i.bak "s/- \[ \] \(.*CLAUDE\.md.*\)/- [x] \1/g" "$TEMP_BODY" 2>/dev/null || true
302
+ fi
303
+
304
+ # Read updated body
305
+ UPDATED_BODY=$(cat "$TEMP_BODY")
306
+
307
+ # Update issue with new body
308
+ gh issue edit "$GITHUB_ISSUE" --body "$UPDATED_BODY" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
309
+ echo "[$(date)] āš ļø Failed to update issue description (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
310
+ }
311
+
312
+ # Cleanup
313
+ rm -f "$TEMP_BODY" "$TEMP_BODY.bak"
314
+
315
+ echo "[$(date)] āœ… Issue description checkboxes updated" >> "$DEBUG_LOG" 2>/dev/null || true
316
+ fi
317
+
318
+ # Calculate progress for comment
319
+ TOTAL_TASKS=$(grep -c "^## T-[0-9]" "$TASKS_FILE" 2>/dev/null || echo "0")
320
+ COMPLETED_TASKS=$(echo "$COMPLETED_TASK_IDS" | wc -w | tr -d ' ')
321
+
322
+ if [ "$TOTAL_TASKS" -gt 0 ]; then
323
+ PROGRESS_PCT=$((COMPLETED_TASKS * 100 / TOTAL_TASKS))
324
+
325
+ # Post progress comment
326
+ gh issue comment "$GITHUB_ISSUE" --body "**Progress Update**: $COMPLETED_TASKS/$TOTAL_TASKS tasks ($PROGRESS_PCT%)\n\nIncrement: \`$CURRENT_INCREMENT\`\n\n---\nšŸ¤– Auto-updated by SpecWeave" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
327
+ echo "[$(date)] āš ļø Failed to comment on GitHub issue (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
328
+ }
329
+ fi
330
+ else
331
+ echo "[$(date)] ā„¹ļø tasks.md not found, skipping GitHub sync" >> "$DEBUG_LOG" 2>/dev/null || true
332
+ fi
333
+ fi
334
+
335
+ # Jira sync (if issue exists)
336
+ if [ -n "$JIRA_ISSUE" ]; then
337
+ echo "[$(date)] šŸ”„ Syncing to Jira issue $JIRA_ISSUE" >> "$DEBUG_LOG" 2>/dev/null || true
338
+
339
+ # Run Jira sync command (non-blocking)
340
+ if command -v node &> /dev/null && [ -f "dist/commands/jira-sync.js" ]; then
341
+ node dist/commands/jira-sync.js "$CURRENT_INCREMENT" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
342
+ echo "[$(date)] āš ļø Failed to sync to Jira (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
343
+ }
344
+ fi
345
+ fi
346
+
347
+ # Azure DevOps sync (if work item exists)
348
+ if [ -n "$ADO_ITEM" ]; then
349
+ echo "[$(date)] šŸ”„ Syncing to Azure DevOps item $ADO_ITEM" >> "$DEBUG_LOG" 2>/dev/null || true
350
+
351
+ # Run ADO sync command (non-blocking)
352
+ if command -v node &> /dev/null && [ -f "dist/commands/ado-sync.js" ]; then
353
+ node dist/commands/ado-sync.js "$CURRENT_INCREMENT" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
354
+ echo "[$(date)] āš ļø Failed to sync to Azure DevOps (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
355
+ }
356
+ fi
357
+ fi
358
+
359
+ # Log if no external tracker configured
360
+ if [ -z "$GITHUB_ISSUE" ] && [ -z "$JIRA_ISSUE" ] && [ -z "$ADO_ITEM" ]; then
361
+ echo "[$(date)] ā„¹ļø No external tracker configured for $CURRENT_INCREMENT (skipping sync)" >> "$DEBUG_LOG" 2>/dev/null || true
362
+ fi
363
+ else
364
+ echo "[$(date)] ā„¹ļø No metadata.json found for $CURRENT_INCREMENT (skipping tracker sync)" >> "$DEBUG_LOG" 2>/dev/null || true
365
+ fi
366
+ fi
367
+
208
368
  # ============================================================================
209
369
  # PLAY SOUND (only if session is truly ending)
210
370
  # ============================================================================