specweave 0.29.2 → 0.30.1

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 (366) hide show
  1. package/README.md +65 -16
  2. package/bin/specweave.js +16 -0
  3. package/dist/plugins/specweave-ado/lib/ado-spec-commit-sync.d.ts +1 -1
  4. package/dist/plugins/specweave-ado/lib/ado-spec-commit-sync.d.ts.map +1 -1
  5. package/dist/plugins/specweave-ado/lib/ado-spec-commit-sync.js +1 -1
  6. package/dist/plugins/specweave-ado/lib/ado-spec-commit-sync.js.map +1 -1
  7. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts +1 -1
  8. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts.map +1 -1
  9. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js +1 -1
  10. package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js.map +1 -1
  11. package/dist/plugins/specweave-ado/lib/conflict-resolver.d.ts +134 -0
  12. package/dist/plugins/specweave-ado/lib/conflict-resolver.d.ts.map +1 -0
  13. package/dist/plugins/specweave-ado/lib/conflict-resolver.js +423 -0
  14. package/dist/plugins/specweave-ado/lib/conflict-resolver.js.map +1 -0
  15. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +23 -1
  16. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
  17. package/dist/plugins/specweave-github/lib/github-client-v2.js +95 -0
  18. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  19. package/dist/plugins/specweave-github/lib/github-spec-commit-sync.d.ts +1 -1
  20. package/dist/plugins/specweave-github/lib/github-spec-commit-sync.d.ts.map +1 -1
  21. package/dist/plugins/specweave-github/lib/github-spec-commit-sync.js +1 -1
  22. package/dist/plugins/specweave-github/lib/github-spec-commit-sync.js.map +1 -1
  23. package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts +1 -1
  24. package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
  25. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +1 -1
  26. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
  27. package/dist/plugins/specweave-github/lib/types.d.ts +20 -0
  28. package/dist/plugins/specweave-github/lib/types.d.ts.map +1 -1
  29. package/dist/plugins/specweave-jira/lib/jira-spec-commit-sync.d.ts +1 -1
  30. package/dist/plugins/specweave-jira/lib/jira-spec-commit-sync.d.ts.map +1 -1
  31. package/dist/plugins/specweave-jira/lib/jira-spec-commit-sync.js +1 -1
  32. package/dist/plugins/specweave-jira/lib/jira-spec-commit-sync.js.map +1 -1
  33. package/dist/plugins/specweave-jira/lib/jira-spec-content-sync.d.ts +1 -1
  34. package/dist/plugins/specweave-jira/lib/jira-spec-content-sync.d.ts.map +1 -1
  35. package/dist/plugins/specweave-jira/lib/jira-spec-content-sync.js +1 -1
  36. package/dist/plugins/specweave-jira/lib/jira-spec-content-sync.js.map +1 -1
  37. package/dist/plugins/specweave-jira/lib/setup-wizard.d.ts +2 -2
  38. package/dist/plugins/specweave-jira/lib/setup-wizard.d.ts.map +1 -1
  39. package/dist/plugins/specweave-jira/lib/setup-wizard.js +1 -1
  40. package/dist/plugins/specweave-jira/lib/setup-wizard.js.map +1 -1
  41. package/dist/src/adapters/claude/adapter.js +1 -1
  42. package/dist/src/adapters/claude/adapter.js.map +1 -1
  43. package/dist/src/cli/commands/detect-project.js +1 -1
  44. package/dist/src/cli/commands/detect-project.js.map +1 -1
  45. package/dist/src/cli/commands/detect-specs.js +1 -1
  46. package/dist/src/cli/commands/detect-specs.js.map +1 -1
  47. package/dist/src/cli/commands/import-docs.js +1 -1
  48. package/dist/src/cli/commands/import-docs.js.map +1 -1
  49. package/dist/src/cli/commands/init-multiproject.js +1 -1
  50. package/dist/src/cli/commands/init-multiproject.js.map +1 -1
  51. package/dist/src/cli/commands/init.d.ts.map +1 -1
  52. package/dist/src/cli/commands/init.js +31 -1
  53. package/dist/src/cli/commands/init.js.map +1 -1
  54. package/dist/src/cli/commands/jobs.js +15 -1
  55. package/dist/src/cli/commands/jobs.js.map +1 -1
  56. package/dist/src/cli/commands/migrate-to-multiproject.js +1 -1
  57. package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
  58. package/dist/src/cli/commands/switch-project.js +1 -1
  59. package/dist/src/cli/commands/switch-project.js.map +1 -1
  60. package/dist/src/cli/commands/sync-scheduled.d.ts +38 -0
  61. package/dist/src/cli/commands/sync-scheduled.d.ts.map +1 -0
  62. package/dist/src/cli/commands/sync-scheduled.js +170 -0
  63. package/dist/src/cli/commands/sync-scheduled.js.map +1 -0
  64. package/dist/src/cli/helpers/init/external-import-grouping.d.ts +53 -0
  65. package/dist/src/cli/helpers/init/external-import-grouping.d.ts.map +1 -0
  66. package/dist/src/cli/helpers/init/external-import-grouping.js +287 -0
  67. package/dist/src/cli/helpers/init/external-import-grouping.js.map +1 -0
  68. package/dist/src/cli/helpers/init/external-import.d.ts +1 -34
  69. package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
  70. package/dist/src/cli/helpers/init/external-import.js +15 -486
  71. package/dist/src/cli/helpers/init/external-import.js.map +1 -1
  72. package/dist/src/cli/helpers/init/living-docs-preflight.d.ts +58 -0
  73. package/dist/src/cli/helpers/init/living-docs-preflight.d.ts.map +1 -0
  74. package/dist/src/cli/helpers/init/living-docs-preflight.js +290 -0
  75. package/dist/src/cli/helpers/init/living-docs-preflight.js.map +1 -0
  76. package/dist/src/cli/helpers/init/sync-profile-helpers.d.ts +48 -0
  77. package/dist/src/cli/helpers/init/sync-profile-helpers.d.ts.map +1 -0
  78. package/dist/src/cli/helpers/init/sync-profile-helpers.js +238 -0
  79. package/dist/src/cli/helpers/init/sync-profile-helpers.js.map +1 -0
  80. package/dist/src/cli/helpers/init/types.d.ts +1 -0
  81. package/dist/src/cli/helpers/init/types.d.ts.map +1 -1
  82. package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
  83. package/dist/src/cli/helpers/issue-tracker/ado.js +113 -3
  84. package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
  85. package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  86. package/dist/src/cli/helpers/issue-tracker/index.js +2 -287
  87. package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
  88. package/dist/src/cli/helpers/issue-tracker/sync-config-writer.d.ts +25 -0
  89. package/dist/src/cli/helpers/issue-tracker/sync-config-writer.d.ts.map +1 -0
  90. package/dist/src/cli/helpers/issue-tracker/sync-config-writer.js +306 -0
  91. package/dist/src/cli/helpers/issue-tracker/sync-config-writer.js.map +1 -0
  92. package/dist/src/cli/helpers/issue-tracker/types.d.ts +27 -0
  93. package/dist/src/cli/helpers/issue-tracker/types.d.ts.map +1 -1
  94. package/dist/src/cli/helpers/issue-tracker/types.js.map +1 -1
  95. package/dist/src/cli/workers/living-docs-worker.d.ts +16 -0
  96. package/dist/src/cli/workers/living-docs-worker.d.ts.map +1 -0
  97. package/dist/src/cli/workers/living-docs-worker.js +395 -0
  98. package/dist/src/cli/workers/living-docs-worker.js.map +1 -0
  99. package/dist/src/core/background/job-dependency.d.ts +45 -0
  100. package/dist/src/core/background/job-dependency.d.ts.map +1 -0
  101. package/dist/src/core/background/job-dependency.js +144 -0
  102. package/dist/src/core/background/job-dependency.js.map +1 -0
  103. package/dist/src/core/background/job-launcher.d.ts +21 -1
  104. package/dist/src/core/background/job-launcher.d.ts.map +1 -1
  105. package/dist/src/core/background/job-launcher.js +93 -0
  106. package/dist/src/core/background/job-launcher.js.map +1 -1
  107. package/dist/src/core/background/types.d.ts +73 -2
  108. package/dist/src/core/background/types.d.ts.map +1 -1
  109. package/dist/src/core/brownfield/importer.js +1 -1
  110. package/dist/src/core/brownfield/importer.js.map +1 -1
  111. package/dist/src/core/comment-builder.d.ts +1 -1
  112. package/dist/src/core/comment-builder.d.ts.map +1 -1
  113. package/dist/src/core/{cost-tracker.d.ts → cost/cost-tracker.d.ts} +2 -2
  114. package/dist/src/core/cost/cost-tracker.d.ts.map +1 -0
  115. package/dist/src/core/{cost-tracker.js → cost/cost-tracker.js} +2 -2
  116. package/dist/src/core/cost/cost-tracker.js.map +1 -0
  117. package/dist/src/core/credentials/credentials-manager.d.ts.map +1 -0
  118. package/dist/src/core/credentials/credentials-manager.js.map +1 -0
  119. package/dist/src/core/increment/discipline-checker.js +1 -1
  120. package/dist/src/core/increment/discipline-checker.js.map +1 -1
  121. package/dist/src/core/increment/increment-archiver.d.ts +9 -8
  122. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
  123. package/dist/src/core/increment/increment-archiver.js +40 -42
  124. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  125. package/dist/src/core/increment/increment-status.d.ts.map +1 -0
  126. package/dist/src/core/{increment-status.js → increment/increment-status.js} +1 -1
  127. package/dist/src/core/increment/increment-status.js.map +1 -0
  128. package/dist/src/core/increment/increment-utils.d.ts.map +1 -0
  129. package/dist/src/core/increment/increment-utils.js.map +1 -0
  130. package/dist/src/core/increment/metadata-validator.js +1 -1
  131. package/dist/src/core/increment/metadata-validator.js.map +1 -1
  132. package/dist/src/core/living-docs/checkpoint-manager.d.ts +120 -0
  133. package/dist/src/core/living-docs/checkpoint-manager.d.ts.map +1 -0
  134. package/dist/src/core/living-docs/checkpoint-manager.js +231 -0
  135. package/dist/src/core/living-docs/checkpoint-manager.js.map +1 -0
  136. package/dist/src/core/living-docs/discovery.d.ts +91 -0
  137. package/dist/src/core/living-docs/discovery.d.ts.map +1 -0
  138. package/dist/src/core/living-docs/discovery.js +656 -0
  139. package/dist/src/core/living-docs/discovery.js.map +1 -0
  140. package/dist/src/core/living-docs/feature-archiver.d.ts +23 -4
  141. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
  142. package/dist/src/core/living-docs/feature-archiver.js +133 -30
  143. package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
  144. package/dist/src/core/living-docs/foundation-builder.d.ts +37 -0
  145. package/dist/src/core/living-docs/foundation-builder.d.ts.map +1 -0
  146. package/dist/src/core/living-docs/foundation-builder.js +357 -0
  147. package/dist/src/core/living-docs/foundation-builder.js.map +1 -0
  148. package/dist/src/core/living-docs/living-docs-sync.d.ts +58 -0
  149. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  150. package/dist/src/core/living-docs/living-docs-sync.js +204 -7
  151. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  152. package/dist/src/core/living-docs/module-analyzer.d.ts +97 -0
  153. package/dist/src/core/living-docs/module-analyzer.d.ts.map +1 -0
  154. package/dist/src/core/living-docs/module-analyzer.js +427 -0
  155. package/dist/src/core/living-docs/module-analyzer.js.map +1 -0
  156. package/dist/src/core/living-docs/suggestions-generator.d.ts +112 -0
  157. package/dist/src/core/living-docs/suggestions-generator.d.ts.map +1 -0
  158. package/dist/src/core/living-docs/suggestions-generator.js +362 -0
  159. package/dist/src/core/living-docs/suggestions-generator.js.map +1 -0
  160. package/dist/src/core/living-docs/workitem-matcher.d.ts +116 -0
  161. package/dist/src/core/living-docs/workitem-matcher.d.ts.map +1 -0
  162. package/dist/src/core/living-docs/workitem-matcher.js +356 -0
  163. package/dist/src/core/living-docs/workitem-matcher.js.map +1 -0
  164. package/dist/src/core/{plugin-loader.d.ts → plugins/plugin-loader.d.ts} +1 -1
  165. package/dist/src/core/plugins/plugin-loader.d.ts.map +1 -0
  166. package/dist/src/core/{plugin-loader.js → plugins/plugin-loader.js} +2 -2
  167. package/dist/src/core/plugins/plugin-loader.js.map +1 -0
  168. package/dist/src/core/{project-manager.d.ts → project/project-manager.d.ts} +1 -1
  169. package/dist/src/core/project/project-manager.d.ts.map +1 -0
  170. package/dist/src/core/{project-manager.js → project/project-manager.js} +3 -3
  171. package/dist/src/core/project/project-manager.js.map +1 -0
  172. package/dist/src/core/project/project-structure-detector.d.ts.map +1 -0
  173. package/dist/src/core/project/project-structure-detector.js.map +1 -0
  174. package/dist/src/core/{rfc-generator-v2.d.ts → rfc/rfc-generator-v2.d.ts} +1 -1
  175. package/dist/src/core/rfc/rfc-generator-v2.d.ts.map +1 -0
  176. package/dist/src/core/{rfc-generator-v2.js → rfc/rfc-generator-v2.js} +1 -1
  177. package/dist/src/core/rfc/rfc-generator-v2.js.map +1 -0
  178. package/dist/src/core/scheduler/index.d.ts +1 -0
  179. package/dist/src/core/scheduler/index.d.ts.map +1 -1
  180. package/dist/src/core/scheduler/index.js +1 -0
  181. package/dist/src/core/scheduler/index.js.map +1 -1
  182. package/dist/src/core/scheduler/scheduled-job.d.ts +1 -1
  183. package/dist/src/core/scheduler/scheduled-job.d.ts.map +1 -1
  184. package/dist/src/core/scheduler/scheduled-job.js.map +1 -1
  185. package/dist/src/core/scheduler/session-sync-executor.d.ts +138 -0
  186. package/dist/src/core/scheduler/session-sync-executor.d.ts.map +1 -0
  187. package/dist/src/core/scheduler/session-sync-executor.js +333 -0
  188. package/dist/src/core/scheduler/session-sync-executor.js.map +1 -0
  189. package/dist/src/core/{spec-content-sync.d.ts → specs/spec-content-sync.d.ts} +2 -2
  190. package/dist/src/core/specs/spec-content-sync.d.ts.map +1 -0
  191. package/dist/src/core/{spec-content-sync.js → specs/spec-content-sync.js} +1 -1
  192. package/dist/src/core/specs/spec-content-sync.js.map +1 -0
  193. package/dist/src/core/{spec-detector.d.ts → specs/spec-detector.d.ts} +1 -1
  194. package/dist/src/core/specs/spec-detector.d.ts.map +1 -0
  195. package/dist/src/core/{spec-detector.js → specs/spec-detector.js} +1 -1
  196. package/dist/src/core/specs/spec-detector.js.map +1 -0
  197. package/dist/src/core/{spec-identifier-detector.d.ts → specs/spec-identifier-detector.d.ts} +2 -2
  198. package/dist/src/core/specs/spec-identifier-detector.d.ts.map +1 -0
  199. package/dist/src/core/{spec-identifier-detector.js → specs/spec-identifier-detector.js} +1 -1
  200. package/dist/src/core/specs/spec-identifier-detector.js.map +1 -0
  201. package/dist/src/core/specs/spec-metadata-manager.js +1 -1
  202. package/dist/src/core/specs/spec-metadata-manager.js.map +1 -1
  203. package/dist/src/core/specs/spec-task-mapper.d.ts.map +1 -0
  204. package/dist/src/core/specs/spec-task-mapper.js.map +1 -0
  205. package/dist/src/core/sync/sync-audit-logger.d.ts +62 -0
  206. package/dist/src/core/sync/sync-audit-logger.d.ts.map +1 -1
  207. package/dist/src/core/sync/sync-audit-logger.js +59 -0
  208. package/dist/src/core/sync/sync-audit-logger.js.map +1 -1
  209. package/dist/src/importers/item-converter.d.ts +51 -27
  210. package/dist/src/importers/item-converter.d.ts.map +1 -1
  211. package/dist/src/importers/item-converter.js +219 -179
  212. package/dist/src/importers/item-converter.js.map +1 -1
  213. package/dist/src/importers/markdown-generator.d.ts +75 -0
  214. package/dist/src/importers/markdown-generator.d.ts.map +1 -0
  215. package/dist/src/importers/markdown-generator.js +250 -0
  216. package/dist/src/importers/markdown-generator.js.map +1 -0
  217. package/dist/src/integrations/ado/ado-client.d.ts +93 -0
  218. package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
  219. package/dist/src/integrations/ado/ado-client.js +172 -1
  220. package/dist/src/integrations/ado/ado-client.js.map +1 -1
  221. package/dist/src/integrations/jira/jira-client.d.ts +44 -0
  222. package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
  223. package/dist/src/integrations/jira/jira-client.js +119 -1
  224. package/dist/src/integrations/jira/jira-client.js.map +1 -1
  225. package/dist/src/integrations/jira/jira-incremental-mapper.js +2 -2
  226. package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
  227. package/dist/src/integrations/jira/jira-mapper.js +1 -1
  228. package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
  229. package/dist/src/living-docs/epic-id-allocator.d.ts +177 -0
  230. package/dist/src/living-docs/epic-id-allocator.d.ts.map +1 -0
  231. package/dist/src/living-docs/epic-id-allocator.js +363 -0
  232. package/dist/src/living-docs/epic-id-allocator.js.map +1 -0
  233. package/dist/src/sync/external-change-puller.d.ts +94 -0
  234. package/dist/src/sync/external-change-puller.d.ts.map +1 -0
  235. package/dist/src/sync/external-change-puller.js +181 -0
  236. package/dist/src/sync/external-change-puller.js.map +1 -0
  237. package/dist/src/sync/index.d.ts +4 -0
  238. package/dist/src/sync/index.d.ts.map +1 -1
  239. package/dist/src/sync/index.js +2 -0
  240. package/dist/src/sync/index.js.map +1 -1
  241. package/dist/src/sync/living-docs-updater.d.ts +93 -0
  242. package/dist/src/sync/living-docs-updater.d.ts.map +1 -0
  243. package/dist/src/sync/living-docs-updater.js +218 -0
  244. package/dist/src/sync/living-docs-updater.js.map +1 -0
  245. package/dist/src/testing/test-generator.js +1 -1
  246. package/dist/src/testing/test-generator.js.map +1 -1
  247. package/dist/src/utils/cost-reporter.d.ts +1 -1
  248. package/dist/src/utils/cost-reporter.d.ts.map +1 -1
  249. package/dist/src/utils/model-selection.js +4 -4
  250. package/dist/src/utils/model-selection.js.map +1 -1
  251. package/dist/src/utils/pricing-constants.d.ts +2 -2
  252. package/dist/src/utils/pricing-constants.js +2 -2
  253. package/package.json +1 -1
  254. package/plugins/specweave/.claude-plugin/plugin.json +1 -28
  255. package/plugins/specweave/agents/code-standards-detective/AGENT.md +3 -3
  256. package/plugins/specweave/agents/infrastructure/AGENT.md +4 -0
  257. package/plugins/specweave/agents/performance/AGENT.md +2 -2
  258. package/plugins/specweave/agents/reflective-reviewer/AGENT.md +3 -3
  259. package/plugins/specweave/agents/translator/AGENT.md +2 -2
  260. package/plugins/specweave/commands/specweave-costs.md +2 -2
  261. package/plugins/specweave/commands/specweave-do.md +2 -2
  262. package/plugins/specweave/hooks/lib/scheduler-startup.sh +59 -8
  263. package/plugins/specweave/skills/code-reviewer/SKILL.md +1 -1
  264. package/plugins/specweave/skills/role-orchestrator/README.md +1 -1
  265. package/plugins/specweave-ado/agents/ado-manager/AGENT.md +8 -2
  266. package/plugins/specweave-ado/agents/ado-multi-project-mapper/AGENT.md +2 -2
  267. package/plugins/specweave-ado/agents/ado-sync-judge/AGENT.md +2 -2
  268. package/plugins/specweave-ado/lib/ado-spec-commit-sync.d.ts +1 -1
  269. package/plugins/specweave-ado/lib/ado-spec-commit-sync.js +1 -1
  270. package/plugins/specweave-ado/lib/ado-spec-commit-sync.ts +1 -1
  271. package/plugins/specweave-ado/lib/ado-spec-content-sync.js +1 -1
  272. package/plugins/specweave-ado/lib/ado-spec-content-sync.ts +1 -1
  273. package/plugins/specweave-ado/lib/conflict-resolver.js +87 -0
  274. package/plugins/specweave-ado/lib/conflict-resolver.ts +124 -0
  275. package/plugins/specweave-ado/skills/specweave-ado-mapper/SKILL.md +1 -1
  276. package/plugins/specweave-backend/agents/database-optimizer/AGENT.md +3 -3
  277. package/plugins/specweave-backend/skills/dotnet-backend/SKILL.md +1 -1
  278. package/plugins/specweave-backend/skills/nodejs-backend/SKILL.md +1 -1
  279. package/plugins/specweave-backend/skills/python-backend/SKILL.md +1 -1
  280. package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +6 -1
  281. package/plugins/specweave-diagrams/agents/diagrams-architect/AGENT.md +2 -2
  282. package/plugins/specweave-diagrams/skills/diagrams-architect/SKILL.md +1 -1
  283. package/plugins/specweave-frontend/agents/frontend-architect/AGENT.md +4 -0
  284. package/plugins/specweave-github/agents/github-manager/AGENT.md +1 -1
  285. package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +11 -1
  286. package/plugins/specweave-github/agents/user-story-updater/AGENT.md +6 -1
  287. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +90 -0
  288. package/plugins/specweave-github/lib/github-client-v2.js +97 -0
  289. package/plugins/specweave-github/lib/github-client-v2.ts +115 -1
  290. package/plugins/specweave-github/lib/github-spec-commit-sync.d.ts +1 -1
  291. package/plugins/specweave-github/lib/github-spec-commit-sync.js +1 -1
  292. package/plugins/specweave-github/lib/github-spec-commit-sync.ts +1 -1
  293. package/plugins/specweave-github/lib/github-spec-content-sync.js +1 -1
  294. package/plugins/specweave-github/lib/github-spec-content-sync.ts +1 -1
  295. package/plugins/specweave-github/lib/types.ts +21 -0
  296. package/plugins/specweave-infrastructure/agents/devops/AGENT.md +1 -1
  297. package/plugins/specweave-infrastructure/agents/network-engineer/AGENT.md +3 -3
  298. package/plugins/specweave-infrastructure/agents/observability-engineer/AGENT.md +2 -2
  299. package/plugins/specweave-infrastructure/agents/performance-engineer/AGENT.md +3 -3
  300. package/plugins/specweave-infrastructure/agents/sre/AGENT.md +2 -2
  301. package/plugins/specweave-jira/agents/jira-manager/AGENT.md +11 -1
  302. package/plugins/specweave-jira/commands/import-projects.js +1 -1
  303. package/plugins/specweave-jira/commands/import-projects.ts +1 -1
  304. package/plugins/specweave-jira/lib/jira-spec-commit-sync.d.ts +1 -1
  305. package/plugins/specweave-jira/lib/jira-spec-commit-sync.js +1 -1
  306. package/plugins/specweave-jira/lib/jira-spec-commit-sync.ts +1 -1
  307. package/plugins/specweave-jira/lib/jira-spec-content-sync.js +1 -1
  308. package/plugins/specweave-jira/lib/jira-spec-content-sync.ts +1 -1
  309. package/plugins/specweave-jira/lib/setup-wizard.js +2 -2
  310. package/plugins/specweave-jira/lib/setup-wizard.ts +2 -2
  311. package/plugins/specweave-jira/skills/specweave-jira-mapper/SKILL.md +1 -1
  312. package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +5 -1
  313. package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +6 -1
  314. package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +6 -1
  315. package/plugins/specweave-kubernetes/agents/kubernetes-architect/AGENT.md +3 -3
  316. package/plugins/specweave-ml/agents/data-scientist/AGENT.md +2 -1
  317. package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +2 -1
  318. package/plugins/specweave-ml/agents/mlops-engineer/AGENT.md +3 -3
  319. package/plugins/specweave-mobile/agents/mobile-architect/AGENT.md +6 -1
  320. package/plugins/specweave-payments/agents/payment-integration/AGENT.md +3 -3
  321. package/plugins/specweave-release/agents/release-manager/AGENT.md +6 -1
  322. package/plugins/specweave-release/commands/specweave-release-npm.md +8 -0
  323. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +135 -0
  324. package/plugins/specweave-testing/agents/qa-engineer/AGENT.md +5 -0
  325. package/src/templates/AGENTS.md.template +97 -0
  326. package/dist/src/core/cost-tracker.d.ts.map +0 -1
  327. package/dist/src/core/cost-tracker.js.map +0 -1
  328. package/dist/src/core/credentials-manager.d.ts.map +0 -1
  329. package/dist/src/core/credentials-manager.js.map +0 -1
  330. package/dist/src/core/increment-status.d.ts.map +0 -1
  331. package/dist/src/core/increment-status.js.map +0 -1
  332. package/dist/src/core/increment-utils.d.ts.map +0 -1
  333. package/dist/src/core/increment-utils.js.map +0 -1
  334. package/dist/src/core/plugin-loader.d.ts.map +0 -1
  335. package/dist/src/core/plugin-loader.js.map +0 -1
  336. package/dist/src/core/project-manager.d.ts.map +0 -1
  337. package/dist/src/core/project-manager.js.map +0 -1
  338. package/dist/src/core/project-structure-detector.d.ts.map +0 -1
  339. package/dist/src/core/project-structure-detector.js.map +0 -1
  340. package/dist/src/core/rfc-generator-v2.d.ts.map +0 -1
  341. package/dist/src/core/rfc-generator-v2.js.map +0 -1
  342. package/dist/src/core/spec-content-sync.d.ts.map +0 -1
  343. package/dist/src/core/spec-content-sync.js.map +0 -1
  344. package/dist/src/core/spec-detector.d.ts.map +0 -1
  345. package/dist/src/core/spec-detector.js.map +0 -1
  346. package/dist/src/core/spec-identifier-detector.d.ts.map +0 -1
  347. package/dist/src/core/spec-identifier-detector.js.map +0 -1
  348. package/dist/src/core/spec-task-mapper.d.ts.map +0 -1
  349. package/dist/src/core/spec-task-mapper.js.map +0 -1
  350. package/dist/src/utils/spec-parser.d.ts +0 -145
  351. package/dist/src/utils/spec-parser.d.ts.map +0 -1
  352. package/dist/src/utils/spec-parser.js +0 -640
  353. package/dist/src/utils/spec-parser.js.map +0 -1
  354. package/plugins/specweave/agents/pm/AGENT.md.bak2 +0 -1754
  355. package/plugins/specweave/hooks/hooks.json.bak +0 -72
  356. package/plugins/specweave/hooks/hooks.json.v1-backup +0 -16
  357. package/plugins/specweave/hooks/v2/hooks.json +0 -16
  358. /package/dist/src/core/{credentials-manager.d.ts → credentials/credentials-manager.d.ts} +0 -0
  359. /package/dist/src/core/{credentials-manager.js → credentials/credentials-manager.js} +0 -0
  360. /package/dist/src/core/{increment-status.d.ts → increment/increment-status.d.ts} +0 -0
  361. /package/dist/src/core/{increment-utils.d.ts → increment/increment-utils.d.ts} +0 -0
  362. /package/dist/src/core/{increment-utils.js → increment/increment-utils.js} +0 -0
  363. /package/dist/src/core/{project-structure-detector.d.ts → project/project-structure-detector.d.ts} +0 -0
  364. /package/dist/src/core/{project-structure-detector.js → project/project-structure-detector.js} +0 -0
  365. /package/dist/src/core/{spec-task-mapper.d.ts → specs/spec-task-mapper.d.ts} +0 -0
  366. /package/dist/src/core/{spec-task-mapper.js → specs/spec-task-mapper.js} +0 -0
@@ -13,11 +13,13 @@ import { ItemConverter } from '../../../importers/item-converter.js';
13
13
  import { loadImportConfig } from '../../../config/import-config.js';
14
14
  import { selectRepositories } from '../github-repo-selector.js';
15
15
  import { detectAllConfigs } from './config-detection.js';
16
- import { parseEnvFile } from '../../../utils/env-file.js';
17
16
  import { getGitHubAuthFromProject } from '../../../utils/auth-helpers.js';
18
17
  import { detectJiraStructure, confirmJiraMapping, detectAdoStructure, confirmAdoMapping, buildJiraCoordinatorConfig, buildAdoCoordinatorConfig, } from './jira-ado-auto-detect.js';
19
18
  import { normalizeToProjectId } from '../../../utils/project-id-generator.js';
20
19
  import { getJobManager, launchImportJob, detectOrphanedJobs, getActiveImportJob } from '../../../core/background/index.js';
20
+ // Extracted helpers for better maintainability
21
+ import { getExistingSyncProfiles, isUmbrellaModeFromConfig, getSyncProfileProviders, loadAdoConfigFromSyncProfile, getUmbrellaProjects, } from './sync-profile-helpers.js';
22
+ import { groupItemsByExternalContainer, groupAdoItemsByParentHierarchy, groupNonHierarchyItems, } from './external-import-grouping.js';
21
23
  /**
22
24
  * Get translated strings for external import
23
25
  */
@@ -580,229 +582,11 @@ export async function promptAndRunExternalImport(targetDir, isCI, language = 'en
580
582
  estimatedTotal: options.estimatedTotal || 100 // Default estimate for progress tracking
581
583
  });
582
584
  }
583
- /**
584
- * Get existing sync profiles from config.json
585
- * Returns array of "owner/repo" strings if profiles exist
586
- *
587
- * CRITICAL FIX (2025-11-26): Also includes parent repo from umbrella config
588
- * Bug: Parent repo was NOT being imported in umbrella mode - only child repos were processed
589
- */
590
- function getExistingSyncProfiles(targetDir) {
591
- try {
592
- const configPath = path.join(targetDir, '.specweave', 'config.json');
593
- if (!fs.existsSync(configPath)) {
594
- return null;
595
- }
596
- const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
597
- const repos = [];
598
- // Check for sync.profiles structure (umbrella repo setup - child repos)
599
- if (config.sync?.profiles && typeof config.sync.profiles === 'object') {
600
- const profiles = config.sync.profiles;
601
- for (const [profileId, profile] of Object.entries(profiles)) {
602
- const p = profile;
603
- if (p.config?.owner && p.config?.repo) {
604
- repos.push(`${p.config.owner}/${p.config.repo}`);
605
- }
606
- }
607
- }
608
- // CRITICAL FIX: Also include parent repo from umbrella config
609
- // Parent repo may have issues/items that need to be imported too!
610
- if (config.umbrella?.enabled && config.umbrella?.parentRepo) {
611
- // parentRepo can be "owner/repo" or just "repo" (same owner as git remote)
612
- let parentRepoFullName = config.umbrella.parentRepo;
613
- // If parentRepo is just the repo name, try to get owner from git remote or first child repo
614
- if (!parentRepoFullName.includes('/')) {
615
- // Try to find owner from sync profiles (same owner as child repos)
616
- const firstProfile = Object.values(config.sync?.profiles || {})[0];
617
- const owner = firstProfile?.config?.owner;
618
- if (owner) {
619
- parentRepoFullName = `${owner}/${parentRepoFullName}`;
620
- }
621
- }
622
- // Add parent repo if not already in the list
623
- if (parentRepoFullName.includes('/') && !repos.includes(parentRepoFullName)) {
624
- repos.push(parentRepoFullName);
625
- }
626
- }
627
- return repos.length > 0 ? repos : null;
628
- }
629
- catch (error) {
630
- // Log warning for debugging - config parsing errors shouldn't be silent
631
- console.warn(chalk.yellow(` ⚠️ Failed to read sync profiles: ${error instanceof Error ? error.message : String(error)}`));
632
- return null;
633
- }
634
- }
635
- /**
636
- * Check if umbrella mode is enabled from config.json
637
- * Returns true if sync.profiles exist OR umbrella.enabled is true
638
- *
639
- * CRITICAL: Used to force global collision detection even for single-group batches
640
- */
641
- function isUmbrellaModeFromConfig(targetDir) {
642
- try {
643
- const configPath = path.join(targetDir, '.specweave', 'config.json');
644
- if (!fs.existsSync(configPath)) {
645
- return false;
646
- }
647
- const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
648
- // Check 1: umbrella.enabled is explicitly true
649
- if (config.umbrella?.enabled === true) {
650
- return true;
651
- }
652
- // Check 2: sync.profiles has multiple entries (umbrella repo setup)
653
- if (config.sync?.profiles && typeof config.sync.profiles === 'object') {
654
- const profileCount = Object.keys(config.sync.profiles).length;
655
- if (profileCount >= 2) {
656
- return true;
657
- }
658
- }
659
- // Check 3: multiProject.enabled is true
660
- if (config.multiProject?.enabled === true) {
661
- return true;
662
- }
663
- return false;
664
- }
665
- catch {
666
- return false;
667
- }
668
- }
669
- /**
670
- * Get sync profile providers from config.json
671
- * Returns array of provider names ('github', 'jira', 'ado') from sync profiles
672
- */
673
- function getSyncProfileProviders(targetDir) {
674
- try {
675
- const configPath = path.join(targetDir, '.specweave', 'config.json');
676
- if (!fs.existsSync(configPath)) {
677
- return [];
678
- }
679
- const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
680
- const providers = new Set();
681
- // Check sync.profiles structure
682
- if (config.sync?.profiles && typeof config.sync.profiles === 'object') {
683
- for (const profile of Object.values(config.sync.profiles)) {
684
- const p = profile;
685
- if (p.provider) {
686
- providers.add(p.provider.toLowerCase());
687
- }
688
- }
689
- }
690
- // Also check top-level sync.provider
691
- if (config.sync?.provider) {
692
- providers.add(config.sync.provider.toLowerCase());
693
- }
694
- return Array.from(providers);
695
- }
696
- catch {
697
- return [];
698
- }
699
- }
700
- /**
701
- * Load ADO config from sync profile when detectAllConfigs() fails
702
- * This ensures work items are imported even when the main detection fails
703
- *
704
- * CRITICAL FIX (2025-11-29): This fixes the bug where ADO folders were created
705
- * but no work items were imported because ado was null in the import flow.
706
- *
707
- * ENHANCED (2025-11-30): Now supports multi-project ADO setups by collecting
708
- * ALL ADO profiles and building the projects array for multi-project import.
709
- */
710
- function loadAdoConfigFromSyncProfile(targetDir) {
711
- try {
712
- const configPath = path.join(targetDir, '.specweave', 'config.json');
713
- if (!fs.existsSync(configPath)) {
714
- return null;
715
- }
716
- const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
717
- // Load PAT from .env file (needed for all profiles)
718
- let pat;
719
- const envPath = path.join(targetDir, '.env');
720
- if (fs.existsSync(envPath)) {
721
- const envContent = fs.readFileSync(envPath, 'utf-8');
722
- const envVars = parseEnvFile(envContent);
723
- pat = envVars.AZURE_DEVOPS_PAT || envVars.ADO_PAT;
724
- }
725
- // Also check environment variables
726
- if (!pat) {
727
- pat = process.env.AZURE_DEVOPS_PAT || process.env.ADO_PAT;
728
- }
729
- if (!pat) {
730
- return null;
731
- }
732
- // Collect ALL ADO profiles for multi-project support
733
- const adoProjects = [];
734
- let organization;
735
- let strategy;
736
- if (config.sync?.profiles && typeof config.sync.profiles === 'object') {
737
- const activeProfileId = config.sync.activeProfile;
738
- for (const [profileId, profile] of Object.entries(config.sync.profiles)) {
739
- const p = profile;
740
- if (p.provider?.toLowerCase() === 'ado' && p.config) {
741
- const profileConfig = p.config;
742
- if (profileConfig.organization && profileConfig.project) {
743
- // Use first organization found (they should all be the same)
744
- if (!organization) {
745
- organization = profileConfig.organization;
746
- }
747
- // Use first strategy found
748
- if (!strategy && profileConfig.strategy) {
749
- strategy = profileConfig.strategy;
750
- }
751
- adoProjects.push({
752
- name: profileConfig.project,
753
- areaPaths: profileConfig.areaPaths,
754
- isDefault: profileId === activeProfileId,
755
- isUmbrella: profileConfig.isUmbrella
756
- });
757
- }
758
- }
759
- }
760
- }
761
- // Return null if no ADO projects found
762
- if (adoProjects.length === 0 || !organization) {
763
- return null;
764
- }
765
- // Return multi-project config
766
- const defaultProject = adoProjects.find(p => p.isDefault) || adoProjects[0];
767
- return {
768
- orgUrl: `https://dev.azure.com/${organization}`,
769
- project: defaultProject.name, // Primary project for backwards compatibility
770
- pat,
771
- strategy,
772
- projects: adoProjects // Multi-project support
773
- };
774
- }
775
- catch {
776
- return null;
777
- }
778
- }
779
- /**
780
- * Get umbrella project names from config.json
781
- * Umbrella projects are folder-structure-only (no items imported)
782
- */
783
- function getUmbrellaProjects(targetDir) {
784
- try {
785
- const configPath = path.join(targetDir, '.specweave', 'config.json');
786
- if (!fs.existsSync(configPath)) {
787
- return [];
788
- }
789
- const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
790
- const umbrellaProjects = [];
791
- // Check sync.profiles for ADO profiles with isUmbrella flag
792
- if (config.sync?.profiles && typeof config.sync.profiles === 'object') {
793
- for (const profile of Object.values(config.sync.profiles)) {
794
- const p = profile;
795
- if (p.provider === 'ado' && p.config?.isUmbrella && p.config?.project) {
796
- umbrellaProjects.push(p.config.project);
797
- }
798
- }
799
- }
800
- return umbrellaProjects;
801
- }
802
- catch {
803
- return [];
804
- }
805
- }
585
+ // getExistingSyncProfiles moved to ./sync-profile-helpers.ts
586
+ // isUmbrellaModeFromConfig moved to ./sync-profile-helpers.ts
587
+ // getSyncProfileProviders moved to ./sync-profile-helpers.ts
588
+ // loadAdoConfigFromSyncProfile moved to ./sync-profile-helpers.ts
589
+ // getUmbrellaProjects moved to ./sync-profile-helpers.ts
806
590
  /**
807
591
  * Prompt for multi-repository selection
808
592
  */
@@ -1206,268 +990,12 @@ async function convertToLivingDocs(targetDir, result, spinner) {
1206
990
  throw conversionError;
1207
991
  }
1208
992
  }
1209
- /**
1210
- * Group items by their source repository
1211
- * Items without sourceRepo go into '_default' group
1212
- */
1213
- function groupItemsBySourceRepo(items) {
1214
- const groups = new Map();
1215
- for (const item of items) {
1216
- // Extract repo name from sourceRepo (e.g., "owner/repo" -> "repo")
1217
- let repoKey = '_default';
1218
- if (item.sourceRepo) {
1219
- // sourceRepo is "owner/repo", we want just "repo"
1220
- const parts = item.sourceRepo.split('/');
1221
- const rawRepoName = parts.length > 1 ? parts[1] : item.sourceRepo;
1222
- // Sanitize repo name to prevent path injection:
1223
- // - Allow only alphanumeric, hyphens, underscores
1224
- // - Trim leading/trailing hyphens
1225
- // - Limit to 100 chars
1226
- repoKey = rawRepoName
1227
- .replace(/[^a-zA-Z0-9-_]/g, '-')
1228
- .replace(/^-+|-+$/g, '')
1229
- .slice(0, 100);
1230
- // Fall back to _default if sanitization results in empty string
1231
- if (!repoKey) {
1232
- repoKey = '_default';
1233
- }
1234
- }
1235
- if (!groups.has(repoKey)) {
1236
- groups.set(repoKey, []);
1237
- }
1238
- groups.get(repoKey).push(item);
1239
- }
1240
- return groups;
1241
- }
1242
- function groupItemsByExternalContainer(items) {
1243
- const groups = new Map();
1244
- // Check if we have ADO items with hierarchy
1245
- const adoItems = items.filter(item => item.platform === 'ado' && item.adoProjectName);
1246
- const hasAdoHierarchy = adoItems.some(item => item.parentId || item.type === 'epic');
1247
- // For ADO with hierarchy, use parent-based grouping
1248
- if (hasAdoHierarchy && adoItems.length > 0) {
1249
- const adoGroups = groupAdoItemsByParentHierarchy(adoItems);
1250
- for (const group of adoGroups) {
1251
- groups.set(group.projectId, group);
1252
- }
1253
- // Also process non-ADO items normally
1254
- const nonAdoItems = items.filter(item => item.platform !== 'ado' || !item.adoProjectName);
1255
- if (nonAdoItems.length > 0) {
1256
- const nonAdoGroups = groupNonHierarchyItems(nonAdoItems);
1257
- for (const group of nonAdoGroups) {
1258
- // Avoid key collisions with ADO groups
1259
- const uniqueKey = `other:${group.projectId}`;
1260
- groups.set(uniqueKey, group);
1261
- }
1262
- }
1263
- return Array.from(groups.values());
1264
- }
1265
- // No ADO hierarchy - use original grouping logic for all items
1266
- return groupNonHierarchyItems(items);
1267
- }
1268
- /**
1269
- * Group ADO items by their parent Epic/Capability hierarchy
1270
- * Each top-level Epic/Capability becomes its own FS-XXX folder
1271
- */
1272
- function groupAdoItemsByParentHierarchy(items) {
1273
- const groups = new Map();
1274
- // Build item lookup map
1275
- const itemById = new Map();
1276
- for (const item of items) {
1277
- itemById.set(item.id, item);
1278
- }
1279
- // Find feature-level types (these become folder leaders)
1280
- const featureLevelTypes = new Set(['capability', 'epic', 'feature']);
1281
- // Find ALL top-level parents (Epics/Capabilities that are NOT children of other items in our dataset)
1282
- const topLevelParents = new Map();
1283
- for (const item of items) {
1284
- const witType = item.adoWorkItemType?.toLowerCase() || item.type;
1285
- if (featureLevelTypes.has(witType)) {
1286
- // Check if this item's parent is NOT in our dataset (making it a top-level parent)
1287
- const hasParentInDataset = item.parentId && itemById.has(item.parentId);
1288
- if (!hasParentInDataset) {
1289
- topLevelParents.set(item.id, item);
1290
- }
1291
- }
1292
- }
1293
- // Function to find the top-level parent for an item
1294
- function findTopLevelParent(item) {
1295
- // If this item IS a top-level parent, return it
1296
- if (topLevelParents.has(item.id)) {
1297
- return item;
1298
- }
1299
- // Walk up the parent chain
1300
- let current = item;
1301
- const visited = new Set();
1302
- while (current && current.parentId && !visited.has(current.id)) {
1303
- visited.add(current.id);
1304
- // Check if parent is a top-level parent
1305
- if (topLevelParents.has(current.parentId)) {
1306
- return topLevelParents.get(current.parentId);
1307
- }
1308
- // Move to parent
1309
- current = itemById.get(current.parentId);
1310
- }
1311
- // No top-level parent found
1312
- return undefined;
1313
- }
1314
- // Create groups for each top-level parent first
1315
- for (const [parentId, parentItem] of topLevelParents) {
1316
- const containerId = parentItem.adoProjectName || 'default';
1317
- const projectId = normalizeToProjectId(parentItem.title) || `ado-${parentId.replace('ADO-', '')}`;
1318
- const groupKey = `ado:parent:${parentId}`;
1319
- groups.set(groupKey, {
1320
- containerId,
1321
- containerType: 'ado',
1322
- projectId,
1323
- items: [parentItem], // Parent item goes first
1324
- externalContainer: {
1325
- type: 'ado-project',
1326
- containerId,
1327
- containerName: containerId,
1328
- areaPath: parentItem.adoAreaPath
1329
- },
1330
- parentItem
1331
- });
1332
- }
1333
- // Assign child items to their parent groups
1334
- for (const item of items) {
1335
- // Skip top-level parents (already added)
1336
- if (topLevelParents.has(item.id)) {
1337
- continue;
1338
- }
1339
- // Find the top-level parent
1340
- const topLevelParent = findTopLevelParent(item);
1341
- if (topLevelParent) {
1342
- // Add to parent's group
1343
- const groupKey = `ado:parent:${topLevelParent.id}`;
1344
- const group = groups.get(groupKey);
1345
- if (group) {
1346
- group.items.push(item);
1347
- }
1348
- }
1349
- else {
1350
- // No parent found - group by area path (2-level structure: project/areaPath)
1351
- // This handles orphan items (User Stories with parents outside our dataset)
1352
- // CRITICAL FIX (2025-12-01): Group by area path, NOT by User Story title
1353
- const containerId = item.adoProjectName || 'default';
1354
- // Extract area path leaf segment for grouping (e.g., "Project\Platform-Engineering" → "platform-engineering")
1355
- let areaFolder = '_default';
1356
- if (item.adoAreaPath) {
1357
- const segments = item.adoAreaPath.split('\\');
1358
- // Use leaf segment, or second segment if only project name
1359
- const leafSegment = segments.length > 1 ? segments[segments.length - 1] : segments[0];
1360
- areaFolder = normalizeToProjectId(leafSegment) || '_default';
1361
- }
1362
- // Group all items without parents by their area path
1363
- // This ensures siblings with same area path stay together
1364
- const groupKey = `ado:area:${containerId}:${areaFolder}`;
1365
- const projectId = areaFolder;
1366
- if (!groups.has(groupKey)) {
1367
- groups.set(groupKey, {
1368
- containerId,
1369
- containerType: 'ado',
1370
- projectId,
1371
- items: [],
1372
- externalContainer: {
1373
- type: 'ado-project',
1374
- containerId,
1375
- containerName: containerId,
1376
- areaPath: item.adoAreaPath
1377
- }
1378
- });
1379
- }
1380
- groups.get(groupKey).items.push(item);
1381
- }
1382
- }
1383
- // Log grouping results for diagnostics
1384
- console.log(chalk.cyan(` 📊 ADO Hierarchy Grouping:`));
1385
- console.log(chalk.gray(` → ${topLevelParents.size} top-level Epics/Capabilities found`));
1386
- for (const [key, group] of groups) {
1387
- const parentInfo = group.parentItem
1388
- ? ` (parent: ${group.parentItem.adoWorkItemType || 'Epic'} "${group.parentItem.title.slice(0, 30)}...")`
1389
- : '';
1390
- console.log(chalk.gray(` → ${group.projectId}: ${group.items.length} items${parentInfo}`));
1391
- }
1392
- return Array.from(groups.values());
1393
- }
1394
- /**
1395
- * Group non-hierarchy items (JIRA, GitHub, or ADO without hierarchy)
1396
- * Original grouping logic by project/board/repo
1397
- */
1398
- function groupNonHierarchyItems(items) {
1399
- const groups = new Map();
1400
- for (const item of items) {
1401
- let groupKey;
1402
- let containerType = null;
1403
- let containerId;
1404
- let projectId;
1405
- let externalContainer;
1406
- // Check for JIRA container context
1407
- if (item.jiraProjectKey) {
1408
- containerType = 'jira';
1409
- containerId = item.jiraProjectKey;
1410
- // Project ID from board name (if available) or default
1411
- projectId = item.jiraBoardName
1412
- ? normalizeToProjectId(item.jiraBoardName) || 'default'
1413
- : 'default';
1414
- groupKey = `jira:${containerId}:${projectId}`;
1415
- externalContainer = {
1416
- type: 'jira-project',
1417
- containerId: containerId,
1418
- containerName: containerId,
1419
- boardId: item.jiraBoardId,
1420
- boardName: item.jiraBoardName
1421
- };
1422
- }
1423
- // Check for ADO container context (without hierarchy)
1424
- else if (item.adoProjectName) {
1425
- containerType = 'ado';
1426
- containerId = item.adoProjectName;
1427
- // Project ID from area path (extract last segment) or default
1428
- if (item.adoAreaPath) {
1429
- const areaSegments = item.adoAreaPath.split('\\');
1430
- const lastSegment = areaSegments[areaSegments.length - 1];
1431
- projectId = normalizeToProjectId(lastSegment) || 'default';
1432
- }
1433
- else {
1434
- projectId = 'default';
1435
- }
1436
- groupKey = `ado:${containerId}:${projectId}`;
1437
- externalContainer = {
1438
- type: 'ado-project',
1439
- containerId: containerId,
1440
- containerName: containerId,
1441
- areaPath: item.adoAreaPath
1442
- };
1443
- }
1444
- // GitHub or default (1-level structure)
1445
- else {
1446
- // Use sourceRepo if available, otherwise '_default'
1447
- if (item.sourceRepo) {
1448
- const parts = item.sourceRepo.split('/');
1449
- const rawRepoName = parts.length > 1 ? parts[1] : item.sourceRepo;
1450
- projectId = normalizeToProjectId(rawRepoName) || '_default';
1451
- }
1452
- else {
1453
- projectId = '_default';
1454
- }
1455
- groupKey = `gh:${projectId}`;
1456
- // No externalContainer for GitHub (1-level structure)
1457
- }
1458
- if (!groups.has(groupKey)) {
1459
- groups.set(groupKey, {
1460
- containerId: containerId || projectId,
1461
- containerType,
1462
- projectId,
1463
- items: [],
1464
- externalContainer
1465
- });
1466
- }
1467
- groups.get(groupKey).items.push(item);
1468
- }
1469
- return Array.from(groups.values());
1470
- }
993
+ // groupItemsBySourceRepo moved to ./external-import-grouping.ts
994
+ // Grouping functions moved to ./external-import-grouping.ts
995
+ // - ContainerGroup interface
996
+ // - groupItemsByExternalContainer()
997
+ // - groupAdoItemsByParentHierarchy()
998
+ // - groupNonHierarchyItems()
1471
999
  /**
1472
1000
  * Create empty result object
1473
1001
  */
@@ -1483,6 +1011,7 @@ function emptyResult() {
1483
1011
  // ============================================================================
1484
1012
  // TEST EXPORTS - For unit testing internal functions
1485
1013
  // ============================================================================
1014
+ // Re-export from extracted modules for backwards compatibility
1486
1015
  export const __test__ = {
1487
1016
  groupAdoItemsByParentHierarchy,
1488
1017
  groupItemsByExternalContainer,