claude-autopm 2.7.0 → 2.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/README.md +307 -56
  2. package/autopm/.claude/.env +158 -0
  3. package/autopm/.claude/settings.local.json +9 -0
  4. package/bin/autopm.js +11 -2
  5. package/bin/commands/epic.js +23 -3
  6. package/bin/commands/plugin.js +395 -0
  7. package/bin/commands/team.js +184 -10
  8. package/install/install.js +223 -4
  9. package/lib/cli/commands/issue.js +360 -20
  10. package/lib/plugins/PluginManager.js +1328 -0
  11. package/lib/plugins/PluginManager.old.js +400 -0
  12. package/lib/providers/AzureDevOpsProvider.js +575 -0
  13. package/lib/providers/GitHubProvider.js +475 -0
  14. package/lib/services/EpicService.js +1092 -3
  15. package/lib/services/IssueService.js +991 -0
  16. package/package.json +9 -1
  17. package/scripts/publish-plugins.sh +166 -0
  18. package/autopm/.claude/agents/cloud/README.md +0 -55
  19. package/autopm/.claude/agents/cloud/aws-cloud-architect.md +0 -521
  20. package/autopm/.claude/agents/cloud/azure-cloud-architect.md +0 -436
  21. package/autopm/.claude/agents/cloud/gcp-cloud-architect.md +0 -385
  22. package/autopm/.claude/agents/cloud/gcp-cloud-functions-engineer.md +0 -306
  23. package/autopm/.claude/agents/cloud/gemini-api-expert.md +0 -880
  24. package/autopm/.claude/agents/cloud/kubernetes-orchestrator.md +0 -566
  25. package/autopm/.claude/agents/cloud/openai-python-expert.md +0 -1087
  26. package/autopm/.claude/agents/cloud/terraform-infrastructure-expert.md +0 -454
  27. package/autopm/.claude/agents/core/agent-manager.md +0 -296
  28. package/autopm/.claude/agents/core/code-analyzer.md +0 -131
  29. package/autopm/.claude/agents/core/file-analyzer.md +0 -162
  30. package/autopm/.claude/agents/core/test-runner.md +0 -200
  31. package/autopm/.claude/agents/data/airflow-orchestration-expert.md +0 -52
  32. package/autopm/.claude/agents/data/kedro-pipeline-expert.md +0 -50
  33. package/autopm/.claude/agents/data/langgraph-workflow-expert.md +0 -520
  34. package/autopm/.claude/agents/databases/README.md +0 -50
  35. package/autopm/.claude/agents/databases/bigquery-expert.md +0 -392
  36. package/autopm/.claude/agents/databases/cosmosdb-expert.md +0 -368
  37. package/autopm/.claude/agents/databases/mongodb-expert.md +0 -398
  38. package/autopm/.claude/agents/databases/postgresql-expert.md +0 -321
  39. package/autopm/.claude/agents/databases/redis-expert.md +0 -52
  40. package/autopm/.claude/agents/devops/README.md +0 -52
  41. package/autopm/.claude/agents/devops/azure-devops-specialist.md +0 -308
  42. package/autopm/.claude/agents/devops/docker-containerization-expert.md +0 -298
  43. package/autopm/.claude/agents/devops/github-operations-specialist.md +0 -335
  44. package/autopm/.claude/agents/devops/mcp-context-manager.md +0 -319
  45. package/autopm/.claude/agents/devops/observability-engineer.md +0 -574
  46. package/autopm/.claude/agents/devops/ssh-operations-expert.md +0 -1093
  47. package/autopm/.claude/agents/devops/traefik-proxy-expert.md +0 -444
  48. package/autopm/.claude/agents/frameworks/README.md +0 -64
  49. package/autopm/.claude/agents/frameworks/e2e-test-engineer.md +0 -360
  50. package/autopm/.claude/agents/frameworks/nats-messaging-expert.md +0 -254
  51. package/autopm/.claude/agents/frameworks/react-frontend-engineer.md +0 -217
  52. package/autopm/.claude/agents/frameworks/react-ui-expert.md +0 -226
  53. package/autopm/.claude/agents/frameworks/tailwindcss-expert.md +0 -770
  54. package/autopm/.claude/agents/frameworks/ux-design-expert.md +0 -244
  55. package/autopm/.claude/agents/integration/message-queue-engineer.md +0 -794
  56. package/autopm/.claude/agents/languages/README.md +0 -50
  57. package/autopm/.claude/agents/languages/bash-scripting-expert.md +0 -541
  58. package/autopm/.claude/agents/languages/javascript-frontend-engineer.md +0 -197
  59. package/autopm/.claude/agents/languages/nodejs-backend-engineer.md +0 -226
  60. package/autopm/.claude/agents/languages/python-backend-engineer.md +0 -214
  61. package/autopm/.claude/agents/languages/python-backend-expert.md +0 -289
  62. package/autopm/.claude/agents/testing/frontend-testing-engineer.md +0 -395
  63. package/autopm/.claude/commands/ai/langgraph-workflow.md +0 -65
  64. package/autopm/.claude/commands/ai/openai-chat.md +0 -65
  65. package/autopm/.claude/commands/azure/COMMANDS.md +0 -107
  66. package/autopm/.claude/commands/azure/COMMAND_MAPPING.md +0 -252
  67. package/autopm/.claude/commands/azure/INTEGRATION_FIX.md +0 -103
  68. package/autopm/.claude/commands/azure/README.md +0 -246
  69. package/autopm/.claude/commands/azure/active-work.md +0 -198
  70. package/autopm/.claude/commands/azure/aliases.md +0 -143
  71. package/autopm/.claude/commands/azure/blocked-items.md +0 -287
  72. package/autopm/.claude/commands/azure/clean.md +0 -93
  73. package/autopm/.claude/commands/azure/docs-query.md +0 -48
  74. package/autopm/.claude/commands/azure/feature-decompose.md +0 -380
  75. package/autopm/.claude/commands/azure/feature-list.md +0 -61
  76. package/autopm/.claude/commands/azure/feature-new.md +0 -115
  77. package/autopm/.claude/commands/azure/feature-show.md +0 -205
  78. package/autopm/.claude/commands/azure/feature-start.md +0 -130
  79. package/autopm/.claude/commands/azure/fix-integration-example.md +0 -93
  80. package/autopm/.claude/commands/azure/help.md +0 -150
  81. package/autopm/.claude/commands/azure/import-us.md +0 -269
  82. package/autopm/.claude/commands/azure/init.md +0 -211
  83. package/autopm/.claude/commands/azure/next-task.md +0 -262
  84. package/autopm/.claude/commands/azure/search.md +0 -160
  85. package/autopm/.claude/commands/azure/sprint-status.md +0 -235
  86. package/autopm/.claude/commands/azure/standup.md +0 -260
  87. package/autopm/.claude/commands/azure/sync-all.md +0 -99
  88. package/autopm/.claude/commands/azure/task-analyze.md +0 -186
  89. package/autopm/.claude/commands/azure/task-close.md +0 -329
  90. package/autopm/.claude/commands/azure/task-edit.md +0 -145
  91. package/autopm/.claude/commands/azure/task-list.md +0 -263
  92. package/autopm/.claude/commands/azure/task-new.md +0 -84
  93. package/autopm/.claude/commands/azure/task-reopen.md +0 -79
  94. package/autopm/.claude/commands/azure/task-show.md +0 -126
  95. package/autopm/.claude/commands/azure/task-start.md +0 -301
  96. package/autopm/.claude/commands/azure/task-status.md +0 -65
  97. package/autopm/.claude/commands/azure/task-sync.md +0 -67
  98. package/autopm/.claude/commands/azure/us-edit.md +0 -164
  99. package/autopm/.claude/commands/azure/us-list.md +0 -202
  100. package/autopm/.claude/commands/azure/us-new.md +0 -265
  101. package/autopm/.claude/commands/azure/us-parse.md +0 -253
  102. package/autopm/.claude/commands/azure/us-show.md +0 -188
  103. package/autopm/.claude/commands/azure/us-status.md +0 -320
  104. package/autopm/.claude/commands/azure/validate.md +0 -86
  105. package/autopm/.claude/commands/azure/work-item-sync.md +0 -47
  106. package/autopm/.claude/commands/cloud/infra-deploy.md +0 -38
  107. package/autopm/.claude/commands/github/workflow-create.md +0 -42
  108. package/autopm/.claude/commands/infrastructure/ssh-security.md +0 -65
  109. package/autopm/.claude/commands/infrastructure/traefik-setup.md +0 -65
  110. package/autopm/.claude/commands/kubernetes/deploy.md +0 -37
  111. package/autopm/.claude/commands/playwright/test-scaffold.md +0 -38
  112. package/autopm/.claude/commands/pm/blocked.md +0 -28
  113. package/autopm/.claude/commands/pm/clean.md +0 -119
  114. package/autopm/.claude/commands/pm/context-create.md +0 -136
  115. package/autopm/.claude/commands/pm/context-prime.md +0 -170
  116. package/autopm/.claude/commands/pm/context-update.md +0 -292
  117. package/autopm/.claude/commands/pm/context.md +0 -28
  118. package/autopm/.claude/commands/pm/epic-close.md +0 -86
  119. package/autopm/.claude/commands/pm/epic-decompose.md +0 -370
  120. package/autopm/.claude/commands/pm/epic-edit.md +0 -83
  121. package/autopm/.claude/commands/pm/epic-list.md +0 -30
  122. package/autopm/.claude/commands/pm/epic-merge.md +0 -222
  123. package/autopm/.claude/commands/pm/epic-oneshot.md +0 -119
  124. package/autopm/.claude/commands/pm/epic-refresh.md +0 -119
  125. package/autopm/.claude/commands/pm/epic-show.md +0 -28
  126. package/autopm/.claude/commands/pm/epic-split.md +0 -120
  127. package/autopm/.claude/commands/pm/epic-start.md +0 -195
  128. package/autopm/.claude/commands/pm/epic-status.md +0 -28
  129. package/autopm/.claude/commands/pm/epic-sync-modular.md +0 -338
  130. package/autopm/.claude/commands/pm/epic-sync-original.md +0 -473
  131. package/autopm/.claude/commands/pm/epic-sync.md +0 -486
  132. package/autopm/.claude/commands/pm/help.md +0 -28
  133. package/autopm/.claude/commands/pm/import.md +0 -115
  134. package/autopm/.claude/commands/pm/in-progress.md +0 -28
  135. package/autopm/.claude/commands/pm/init.md +0 -28
  136. package/autopm/.claude/commands/pm/issue-analyze.md +0 -202
  137. package/autopm/.claude/commands/pm/issue-close.md +0 -119
  138. package/autopm/.claude/commands/pm/issue-edit.md +0 -93
  139. package/autopm/.claude/commands/pm/issue-reopen.md +0 -87
  140. package/autopm/.claude/commands/pm/issue-show.md +0 -41
  141. package/autopm/.claude/commands/pm/issue-start.md +0 -234
  142. package/autopm/.claude/commands/pm/issue-status.md +0 -95
  143. package/autopm/.claude/commands/pm/issue-sync.md +0 -411
  144. package/autopm/.claude/commands/pm/next.md +0 -28
  145. package/autopm/.claude/commands/pm/prd-edit.md +0 -82
  146. package/autopm/.claude/commands/pm/prd-list.md +0 -28
  147. package/autopm/.claude/commands/pm/prd-new.md +0 -55
  148. package/autopm/.claude/commands/pm/prd-parse.md +0 -42
  149. package/autopm/.claude/commands/pm/prd-status.md +0 -28
  150. package/autopm/.claude/commands/pm/search.md +0 -28
  151. package/autopm/.claude/commands/pm/standup.md +0 -28
  152. package/autopm/.claude/commands/pm/status.md +0 -28
  153. package/autopm/.claude/commands/pm/sync.md +0 -99
  154. package/autopm/.claude/commands/pm/test-reference-update.md +0 -151
  155. package/autopm/.claude/commands/pm/validate.md +0 -28
  156. package/autopm/.claude/commands/pm/what-next.md +0 -28
  157. package/autopm/.claude/commands/python/api-scaffold.md +0 -50
  158. package/autopm/.claude/commands/python/docs-query.md +0 -48
  159. package/autopm/.claude/commands/react/app-scaffold.md +0 -50
  160. package/autopm/.claude/commands/testing/prime.md +0 -314
  161. package/autopm/.claude/commands/testing/run.md +0 -125
  162. package/autopm/.claude/commands/ui/bootstrap-scaffold.md +0 -65
  163. package/autopm/.claude/commands/ui/tailwind-system.md +0 -64
  164. package/autopm/.claude/rules/ai-integration-patterns.md +0 -219
  165. package/autopm/.claude/rules/ci-cd-kubernetes-strategy.md +0 -25
  166. package/autopm/.claude/rules/database-management-strategy.md +0 -17
  167. package/autopm/.claude/rules/database-pipeline.md +0 -94
  168. package/autopm/.claude/rules/devops-troubleshooting-playbook.md +0 -450
  169. package/autopm/.claude/rules/docker-first-development.md +0 -404
  170. package/autopm/.claude/rules/infrastructure-pipeline.md +0 -128
  171. package/autopm/.claude/rules/performance-guidelines.md +0 -403
  172. package/autopm/.claude/rules/ui-development-standards.md +0 -281
  173. package/autopm/.claude/rules/ui-framework-rules.md +0 -151
  174. package/autopm/.claude/rules/ux-design-rules.md +0 -209
  175. package/autopm/.claude/rules/visual-testing.md +0 -223
  176. package/autopm/.claude/scripts/azure/README.md +0 -192
  177. package/autopm/.claude/scripts/azure/active-work.js +0 -524
  178. package/autopm/.claude/scripts/azure/active-work.sh +0 -20
  179. package/autopm/.claude/scripts/azure/blocked.js +0 -520
  180. package/autopm/.claude/scripts/azure/blocked.sh +0 -20
  181. package/autopm/.claude/scripts/azure/daily.js +0 -533
  182. package/autopm/.claude/scripts/azure/daily.sh +0 -20
  183. package/autopm/.claude/scripts/azure/dashboard.js +0 -970
  184. package/autopm/.claude/scripts/azure/dashboard.sh +0 -20
  185. package/autopm/.claude/scripts/azure/feature-list.js +0 -254
  186. package/autopm/.claude/scripts/azure/feature-list.sh +0 -20
  187. package/autopm/.claude/scripts/azure/feature-show.js +0 -7
  188. package/autopm/.claude/scripts/azure/feature-show.sh +0 -20
  189. package/autopm/.claude/scripts/azure/feature-status.js +0 -604
  190. package/autopm/.claude/scripts/azure/feature-status.sh +0 -20
  191. package/autopm/.claude/scripts/azure/help.js +0 -342
  192. package/autopm/.claude/scripts/azure/help.sh +0 -20
  193. package/autopm/.claude/scripts/azure/next-task.js +0 -508
  194. package/autopm/.claude/scripts/azure/next-task.sh +0 -20
  195. package/autopm/.claude/scripts/azure/search.js +0 -469
  196. package/autopm/.claude/scripts/azure/search.sh +0 -20
  197. package/autopm/.claude/scripts/azure/setup.js +0 -745
  198. package/autopm/.claude/scripts/azure/setup.sh +0 -20
  199. package/autopm/.claude/scripts/azure/sprint-report.js +0 -1012
  200. package/autopm/.claude/scripts/azure/sprint-report.sh +0 -20
  201. package/autopm/.claude/scripts/azure/sync.js +0 -563
  202. package/autopm/.claude/scripts/azure/sync.sh +0 -20
  203. package/autopm/.claude/scripts/azure/us-list.js +0 -210
  204. package/autopm/.claude/scripts/azure/us-list.sh +0 -20
  205. package/autopm/.claude/scripts/azure/us-status.js +0 -238
  206. package/autopm/.claude/scripts/azure/us-status.sh +0 -20
  207. package/autopm/.claude/scripts/azure/validate.js +0 -626
  208. package/autopm/.claude/scripts/azure/validate.sh +0 -20
  209. package/autopm/.claude/scripts/azure/wrapper-template.sh +0 -20
  210. package/autopm/.claude/scripts/github/dependency-tracker.js +0 -554
  211. package/autopm/.claude/scripts/github/dependency-validator.js +0 -545
  212. package/autopm/.claude/scripts/github/dependency-visualizer.js +0 -477
  213. package/autopm/.claude/scripts/pm/analytics.js +0 -425
  214. package/autopm/.claude/scripts/pm/blocked.js +0 -164
  215. package/autopm/.claude/scripts/pm/blocked.sh +0 -78
  216. package/autopm/.claude/scripts/pm/clean.js +0 -464
  217. package/autopm/.claude/scripts/pm/context-create.js +0 -216
  218. package/autopm/.claude/scripts/pm/context-prime.js +0 -335
  219. package/autopm/.claude/scripts/pm/context-update.js +0 -344
  220. package/autopm/.claude/scripts/pm/context.js +0 -338
  221. package/autopm/.claude/scripts/pm/epic-close.js +0 -347
  222. package/autopm/.claude/scripts/pm/epic-edit.js +0 -382
  223. package/autopm/.claude/scripts/pm/epic-list.js +0 -273
  224. package/autopm/.claude/scripts/pm/epic-list.sh +0 -109
  225. package/autopm/.claude/scripts/pm/epic-show.js +0 -291
  226. package/autopm/.claude/scripts/pm/epic-show.sh +0 -105
  227. package/autopm/.claude/scripts/pm/epic-split.js +0 -522
  228. package/autopm/.claude/scripts/pm/epic-start/epic-start.js +0 -183
  229. package/autopm/.claude/scripts/pm/epic-start/epic-start.sh +0 -94
  230. package/autopm/.claude/scripts/pm/epic-status.js +0 -291
  231. package/autopm/.claude/scripts/pm/epic-status.sh +0 -104
  232. package/autopm/.claude/scripts/pm/epic-sync/README.md +0 -208
  233. package/autopm/.claude/scripts/pm/epic-sync/create-epic-issue.sh +0 -77
  234. package/autopm/.claude/scripts/pm/epic-sync/create-task-issues.sh +0 -86
  235. package/autopm/.claude/scripts/pm/epic-sync/update-epic-file.sh +0 -79
  236. package/autopm/.claude/scripts/pm/epic-sync/update-references.sh +0 -89
  237. package/autopm/.claude/scripts/pm/epic-sync.sh +0 -137
  238. package/autopm/.claude/scripts/pm/help.js +0 -92
  239. package/autopm/.claude/scripts/pm/help.sh +0 -90
  240. package/autopm/.claude/scripts/pm/in-progress.js +0 -178
  241. package/autopm/.claude/scripts/pm/in-progress.sh +0 -93
  242. package/autopm/.claude/scripts/pm/init.js +0 -321
  243. package/autopm/.claude/scripts/pm/init.sh +0 -178
  244. package/autopm/.claude/scripts/pm/issue-close.js +0 -232
  245. package/autopm/.claude/scripts/pm/issue-edit.js +0 -310
  246. package/autopm/.claude/scripts/pm/issue-show.js +0 -272
  247. package/autopm/.claude/scripts/pm/issue-start.js +0 -181
  248. package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +0 -468
  249. package/autopm/.claude/scripts/pm/issue-sync/gather-updates.sh +0 -460
  250. package/autopm/.claude/scripts/pm/issue-sync/post-comment.sh +0 -330
  251. package/autopm/.claude/scripts/pm/issue-sync/preflight-validation.sh +0 -348
  252. package/autopm/.claude/scripts/pm/issue-sync/update-frontmatter.sh +0 -387
  253. package/autopm/.claude/scripts/pm/lib/README.md +0 -85
  254. package/autopm/.claude/scripts/pm/lib/epic-discovery.js +0 -119
  255. package/autopm/.claude/scripts/pm/lib/logger.js +0 -78
  256. package/autopm/.claude/scripts/pm/next.js +0 -189
  257. package/autopm/.claude/scripts/pm/next.sh +0 -72
  258. package/autopm/.claude/scripts/pm/optimize.js +0 -407
  259. package/autopm/.claude/scripts/pm/pr-create.js +0 -337
  260. package/autopm/.claude/scripts/pm/pr-list.js +0 -257
  261. package/autopm/.claude/scripts/pm/prd-list.js +0 -242
  262. package/autopm/.claude/scripts/pm/prd-list.sh +0 -103
  263. package/autopm/.claude/scripts/pm/prd-new.js +0 -684
  264. package/autopm/.claude/scripts/pm/prd-parse.js +0 -547
  265. package/autopm/.claude/scripts/pm/prd-status.js +0 -152
  266. package/autopm/.claude/scripts/pm/prd-status.sh +0 -63
  267. package/autopm/.claude/scripts/pm/release.js +0 -460
  268. package/autopm/.claude/scripts/pm/search.js +0 -192
  269. package/autopm/.claude/scripts/pm/search.sh +0 -89
  270. package/autopm/.claude/scripts/pm/standup.js +0 -362
  271. package/autopm/.claude/scripts/pm/standup.sh +0 -95
  272. package/autopm/.claude/scripts/pm/status.js +0 -148
  273. package/autopm/.claude/scripts/pm/status.sh +0 -59
  274. package/autopm/.claude/scripts/pm/sync-batch.js +0 -337
  275. package/autopm/.claude/scripts/pm/sync.js +0 -343
  276. package/autopm/.claude/scripts/pm/template-list.js +0 -141
  277. package/autopm/.claude/scripts/pm/template-new.js +0 -366
  278. package/autopm/.claude/scripts/pm/validate.js +0 -274
  279. package/autopm/.claude/scripts/pm/validate.sh +0 -106
  280. package/autopm/.claude/scripts/pm/what-next.js +0 -660
  281. package/bin/node/azure-feature-show.js +0 -7
@@ -0,0 +1,575 @@
1
+ /**
2
+ * Azure DevOps Provider for ClaudeAutoPM
3
+ *
4
+ * Provides bidirectional synchronization with Azure DevOps Work Items
5
+ * following 2025 best practices
6
+ *
7
+ * Features:
8
+ * - Full CRUD operations for work items (Epic, Feature, User Story, Task, Bug)
9
+ * - Comment management
10
+ * - Area Path and Iteration Path management
11
+ * - WIQL queries for advanced filtering
12
+ * - Relation management (Parent/Child links)
13
+ * - State mapping (Azure DevOps <-> Local)
14
+ * - Error handling with meaningful messages
15
+ *
16
+ * @module lib/providers/AzureDevOpsProvider
17
+ */
18
+
19
+ const azdev = require('azure-devops-node-api');
20
+
21
+ /**
22
+ * Azure DevOps Provider Class
23
+ *
24
+ * Manages integration with Azure DevOps Work Item Tracking API
25
+ *
26
+ * @class AzureDevOpsProvider
27
+ */
28
+ class AzureDevOpsProvider {
29
+ /**
30
+ * Creates a new Azure DevOps provider instance
31
+ *
32
+ * @param {Object} options - Configuration options
33
+ * @param {string} [options.token] - Personal Access Token (PAT)
34
+ * @param {string} [options.organization] - Azure DevOps organization name
35
+ * @param {string} [options.project] - Project name
36
+ */
37
+ constructor(options = {}) {
38
+ this.token = options.token || process.env.AZURE_DEVOPS_PAT;
39
+ this.organization = options.organization || process.env.AZURE_DEVOPS_ORG;
40
+ this.project = options.project || process.env.AZURE_DEVOPS_PROJECT;
41
+
42
+ this.connection = null;
43
+ this.witApi = null;
44
+ }
45
+
46
+ /**
47
+ * Authenticates with Azure DevOps API
48
+ *
49
+ * Creates connection using PAT and verifies project access
50
+ *
51
+ * @async
52
+ * @returns {Promise<Object>} Project object
53
+ * @throws {Error} If token, organization, or project is missing
54
+ * @throws {Error} If project not found or access denied
55
+ */
56
+ async authenticate() {
57
+ if (!this.token) {
58
+ throw new Error('Azure DevOps PAT token is required');
59
+ }
60
+
61
+ if (!this.organization) {
62
+ throw new Error('Azure DevOps organization is required');
63
+ }
64
+
65
+ if (!this.project) {
66
+ throw new Error('Azure DevOps project is required');
67
+ }
68
+
69
+ // Create organization URL
70
+ const orgUrl = `https://dev.azure.com/${this.organization}`;
71
+
72
+ // Create auth handler
73
+ const authHandler = azdev.getPersonalAccessTokenHandler(this.token);
74
+
75
+ // Create connection
76
+ this.connection = new azdev.WebApi(orgUrl, authHandler);
77
+
78
+ // Get Work Item Tracking API
79
+ this.witApi = await this.connection.getWorkItemTrackingApi();
80
+
81
+ // Verify project access
82
+ const project = await this.witApi.getProject(this.project);
83
+ if (!project) {
84
+ throw new Error('Project not found or access denied');
85
+ }
86
+
87
+ return project;
88
+ }
89
+
90
+ /**
91
+ * Fetches a single work item by ID
92
+ *
93
+ * @async
94
+ * @param {number} id - Work item ID
95
+ * @param {string} [expand] - Expand option (None, Relations, Fields, Links, All)
96
+ * @returns {Promise<Object>} Work item object
97
+ * @throws {Error} If work item is not found
98
+ */
99
+ async getWorkItem(id, expand) {
100
+ try {
101
+ return await this._makeRequest(async () => {
102
+ return await this.witApi.getWorkItem(id, expand);
103
+ });
104
+ } catch (error) {
105
+ if (error.statusCode === 404) {
106
+ throw new Error(`Work item not found: ${id}`);
107
+ }
108
+ throw error;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Lists work items with optional filtering
114
+ *
115
+ * @async
116
+ * @param {Object} [filters={}] - Filter options
117
+ * @param {string} [filters.type] - Work item type (Epic, Feature, User Story, Task, Bug)
118
+ * @param {string} [filters.state] - Work item state (New, Active, Resolved, Closed)
119
+ * @param {string} [filters.areaPath] - Area path filter
120
+ * @param {string} [filters.iterationPath] - Iteration path filter
121
+ * @returns {Promise<Array>} Array of work item objects
122
+ */
123
+ async listWorkItems(filters = {}) {
124
+ // Build WIQL query
125
+ let wiql = `SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = '${this.project}'`;
126
+
127
+ if (filters.type) {
128
+ wiql += ` AND [System.WorkItemType] = '${filters.type}'`;
129
+ }
130
+
131
+ if (filters.state) {
132
+ wiql += ` AND [System.State] = '${filters.state}'`;
133
+ }
134
+
135
+ if (filters.areaPath) {
136
+ wiql += ` AND [System.AreaPath] = '${filters.areaPath}'`;
137
+ }
138
+
139
+ if (filters.iterationPath) {
140
+ wiql += ` AND [System.IterationPath] = '${filters.iterationPath}'`;
141
+ }
142
+
143
+ // Execute query
144
+ const queryResult = await this.witApi.queryByWiql(
145
+ { query: wiql },
146
+ this.project
147
+ );
148
+
149
+ // Get work item IDs
150
+ const ids = queryResult.workItems ? queryResult.workItems.map(wi => wi.id) : [];
151
+
152
+ if (ids.length === 0) {
153
+ return [];
154
+ }
155
+
156
+ // Fetch full work items
157
+ const workItems = await this.witApi.getWorkItems(
158
+ ids,
159
+ undefined,
160
+ undefined,
161
+ 'None'
162
+ );
163
+
164
+ return workItems;
165
+ }
166
+
167
+ /**
168
+ * Creates a new work item
169
+ *
170
+ * @async
171
+ * @param {string} type - Work item type (Epic, Feature, User Story, Task, Bug)
172
+ * @param {Object} data - Work item data
173
+ * @param {string} data.title - Work item title (required)
174
+ * @param {string} [data.description] - Work item description
175
+ * @param {string} [data.state] - Work item state
176
+ * @param {string} [data.areaPath] - Area path
177
+ * @param {string} [data.iterationPath] - Iteration path
178
+ * @returns {Promise<Object>} Created work item object
179
+ * @throws {Error} If title is missing
180
+ */
181
+ async createWorkItem(type, data) {
182
+ if (!data.title) {
183
+ throw new Error('Work item title is required');
184
+ }
185
+
186
+ // Build JSON Patch Document
187
+ const patchDoc = [
188
+ {
189
+ op: 'add',
190
+ path: '/fields/System.Title',
191
+ value: data.title
192
+ }
193
+ ];
194
+
195
+ if (data.description) {
196
+ patchDoc.push({
197
+ op: 'add',
198
+ path: '/fields/System.Description',
199
+ value: data.description
200
+ });
201
+ }
202
+
203
+ if (data.state) {
204
+ patchDoc.push({
205
+ op: 'add',
206
+ path: '/fields/System.State',
207
+ value: data.state
208
+ });
209
+ }
210
+
211
+ if (data.areaPath) {
212
+ patchDoc.push({
213
+ op: 'add',
214
+ path: '/fields/System.AreaPath',
215
+ value: data.areaPath
216
+ });
217
+ }
218
+
219
+ if (data.iterationPath) {
220
+ patchDoc.push({
221
+ op: 'add',
222
+ path: '/fields/System.IterationPath',
223
+ value: data.iterationPath
224
+ });
225
+ }
226
+
227
+ return await this.witApi.createWorkItem(
228
+ null,
229
+ patchDoc,
230
+ this.project,
231
+ type
232
+ );
233
+ }
234
+
235
+ /**
236
+ * Updates an existing work item
237
+ *
238
+ * @async
239
+ * @param {number} id - Work item ID
240
+ * @param {Object} data - Fields to update
241
+ * @param {string} [data.title] - New title
242
+ * @param {string} [data.description] - New description
243
+ * @param {string} [data.state] - New state
244
+ * @param {string} [data.areaPath] - New area path
245
+ * @param {string} [data.iterationPath] - New iteration path
246
+ * @returns {Promise<Object>} Updated work item object
247
+ */
248
+ async updateWorkItem(id, data) {
249
+ // Build JSON Patch Document
250
+ const patchDoc = [];
251
+
252
+ if (data.title) {
253
+ patchDoc.push({
254
+ op: 'replace',
255
+ path: '/fields/System.Title',
256
+ value: data.title
257
+ });
258
+ }
259
+
260
+ if (data.description) {
261
+ patchDoc.push({
262
+ op: 'replace',
263
+ path: '/fields/System.Description',
264
+ value: data.description
265
+ });
266
+ }
267
+
268
+ if (data.state) {
269
+ patchDoc.push({
270
+ op: 'replace',
271
+ path: '/fields/System.State',
272
+ value: data.state
273
+ });
274
+ }
275
+
276
+ if (data.areaPath) {
277
+ patchDoc.push({
278
+ op: 'replace',
279
+ path: '/fields/System.AreaPath',
280
+ value: data.areaPath
281
+ });
282
+ }
283
+
284
+ if (data.iterationPath) {
285
+ patchDoc.push({
286
+ op: 'replace',
287
+ path: '/fields/System.IterationPath',
288
+ value: data.iterationPath
289
+ });
290
+ }
291
+
292
+ return await this.witApi.updateWorkItem(null, patchDoc, id);
293
+ }
294
+
295
+ /**
296
+ * Deletes a work item
297
+ *
298
+ * @async
299
+ * @param {number} id - Work item ID
300
+ * @returns {Promise<Object>} Delete result
301
+ * @throws {Error} If work item not found
302
+ */
303
+ async deleteWorkItem(id) {
304
+ try {
305
+ return await this._makeRequest(async () => {
306
+ return await this.witApi.deleteWorkItem(id);
307
+ }, { id });
308
+ } catch (error) {
309
+ if (error.statusCode === 404) {
310
+ throw new Error(`Work item not found: ${id}`);
311
+ }
312
+ throw error;
313
+ }
314
+ }
315
+
316
+ /**
317
+ * Adds a comment to a work item
318
+ *
319
+ * @async
320
+ * @param {number} workItemId - Work item ID
321
+ * @param {string} text - Comment text
322
+ * @returns {Promise<Object>} Created comment object
323
+ * @throws {Error} If text is empty
324
+ */
325
+ async addComment(workItemId, text) {
326
+ if (!text || text.trim() === '') {
327
+ throw new Error('Comment text is required');
328
+ }
329
+
330
+ return await this.witApi.addComment(
331
+ { text },
332
+ this.project,
333
+ workItemId
334
+ );
335
+ }
336
+
337
+ /**
338
+ * Gets all comments for a work item
339
+ *
340
+ * @async
341
+ * @param {number} workItemId - Work item ID
342
+ * @returns {Promise<Object>} Comments object with comments array
343
+ */
344
+ async getComments(workItemId) {
345
+ return await this.witApi.getComments(this.project, workItemId);
346
+ }
347
+
348
+ /**
349
+ * Updates a comment
350
+ *
351
+ * @async
352
+ * @param {number} workItemId - Work item ID
353
+ * @param {number} commentId - Comment ID
354
+ * @param {string} text - New comment text
355
+ * @returns {Promise<Object>} Updated comment object
356
+ */
357
+ async updateComment(workItemId, commentId, text) {
358
+ return await this.witApi.updateComment(
359
+ { text },
360
+ this.project,
361
+ workItemId,
362
+ commentId
363
+ );
364
+ }
365
+
366
+ /**
367
+ * Deletes a comment
368
+ *
369
+ * @async
370
+ * @param {number} workItemId - Work item ID
371
+ * @param {number} commentId - Comment ID
372
+ * @returns {Promise<void>}
373
+ */
374
+ async deleteComment(workItemId, commentId) {
375
+ return await this.witApi.deleteComment(
376
+ this.project,
377
+ workItemId,
378
+ commentId
379
+ );
380
+ }
381
+
382
+ /**
383
+ * Sets the area path for a work item
384
+ *
385
+ * @async
386
+ * @param {number} workItemId - Work item ID
387
+ * @param {string} path - Area path (e.g., "project\\Team A")
388
+ * @returns {Promise<Object>} Updated work item object
389
+ */
390
+ async setAreaPath(workItemId, path) {
391
+ const patchDoc = [
392
+ {
393
+ op: 'replace',
394
+ path: '/fields/System.AreaPath',
395
+ value: path
396
+ }
397
+ ];
398
+
399
+ return await this.witApi.updateWorkItem(null, patchDoc, workItemId);
400
+ }
401
+
402
+ /**
403
+ * Sets the iteration path for a work item
404
+ *
405
+ * @async
406
+ * @param {number} workItemId - Work item ID
407
+ * @param {string} path - Iteration path (e.g., "project\\Sprint 1")
408
+ * @returns {Promise<Object>} Updated work item object
409
+ */
410
+ async setIterationPath(workItemId, path) {
411
+ const patchDoc = [
412
+ {
413
+ op: 'replace',
414
+ path: '/fields/System.IterationPath',
415
+ value: path
416
+ }
417
+ ];
418
+
419
+ return await this.witApi.updateWorkItem(null, patchDoc, workItemId);
420
+ }
421
+
422
+ /**
423
+ * Executes a WIQL query
424
+ *
425
+ * @async
426
+ * @param {string} wiql - WIQL query string
427
+ * @param {Object} [options={}] - Query options
428
+ * @param {string} [options.expand] - Expand option for work items
429
+ * @returns {Promise<Array>} Array of work item objects
430
+ */
431
+ async queryWorkItems(wiql, options = {}) {
432
+ // Execute query
433
+ const queryResult = await this.witApi.queryByWiql(
434
+ { query: wiql },
435
+ this.project
436
+ );
437
+
438
+ // Get work item IDs
439
+ const ids = queryResult.workItems ? queryResult.workItems.map(wi => wi.id) : [];
440
+
441
+ if (ids.length === 0 || !ids.length) {
442
+ return [];
443
+ }
444
+
445
+ // Fetch full work items
446
+ const expand = options.expand || 'None';
447
+ const workItems = await this.witApi.getWorkItems(
448
+ ids,
449
+ undefined,
450
+ undefined,
451
+ expand
452
+ );
453
+
454
+ return workItems;
455
+ }
456
+
457
+ /**
458
+ * Adds a relation to a work item
459
+ *
460
+ * @async
461
+ * @param {number} workItemId - Work item ID
462
+ * @param {Object} relation - Relation object
463
+ * @param {string} relation.rel - Relation type (e.g., "System.LinkTypes.Hierarchy-Reverse")
464
+ * @param {string} relation.url - Related work item URL
465
+ * @returns {Promise<Object>} Updated work item object
466
+ */
467
+ async addRelation(workItemId, relation) {
468
+ const patchDoc = [
469
+ {
470
+ op: 'add',
471
+ path: '/relations/-',
472
+ value: relation
473
+ }
474
+ ];
475
+
476
+ return await this.witApi.updateWorkItem(null, patchDoc, workItemId);
477
+ }
478
+
479
+ /**
480
+ * Gets all relations for a work item
481
+ *
482
+ * @async
483
+ * @param {number} workItemId - Work item ID
484
+ * @returns {Promise<Array>} Array of relation objects
485
+ */
486
+ async getRelations(workItemId) {
487
+ const workItem = await this.witApi.getWorkItem(workItemId, 'Relations');
488
+
489
+ return workItem.relations || [];
490
+ }
491
+
492
+ /**
493
+ * Checks rate limit status
494
+ *
495
+ * Azure DevOps does not expose rate limit information via API
496
+ *
497
+ * @async
498
+ * @returns {Promise<Object>} Rate limit information (not available)
499
+ */
500
+ async checkRateLimit() {
501
+ return {
502
+ available: false,
503
+ message: 'Azure DevOps does not expose rate limit information via API'
504
+ };
505
+ }
506
+
507
+ /**
508
+ * Maps Azure DevOps state to local status
509
+ *
510
+ * @param {string} azureState - Azure DevOps state
511
+ * @returns {string} Local status
512
+ */
513
+ _mapStateToLocal(azureState) {
514
+ const stateMap = {
515
+ 'New': 'open',
516
+ 'Active': 'in-progress',
517
+ 'Resolved': 'done',
518
+ 'Closed': 'closed',
519
+ 'Removed': 'closed'
520
+ };
521
+
522
+ return stateMap[azureState] || azureState;
523
+ }
524
+
525
+ /**
526
+ * Maps local status to Azure DevOps state
527
+ *
528
+ * @param {string} localStatus - Local status
529
+ * @returns {string} Azure DevOps state
530
+ */
531
+ _mapLocalStatusToState(localStatus) {
532
+ const statusMap = {
533
+ 'open': 'New',
534
+ 'in-progress': 'Active',
535
+ 'done': 'Resolved',
536
+ 'closed': 'Closed'
537
+ };
538
+
539
+ return statusMap[localStatus] || localStatus;
540
+ }
541
+
542
+ /**
543
+ * Makes a request with error handling
544
+ *
545
+ * @async
546
+ * @param {Function} requestFn - Function that makes the request
547
+ * @param {Object} [context={}] - Context for error messages
548
+ * @returns {Promise<*>} Response data
549
+ * @throws {Error} If request fails with meaningful error message
550
+ * @private
551
+ */
552
+ async _makeRequest(requestFn, context = {}) {
553
+ try {
554
+ return await requestFn();
555
+ } catch (error) {
556
+ // Handle specific error codes
557
+ if (error.statusCode === 401) {
558
+ throw new Error('Authentication failed - check AZURE_DEVOPS_PAT');
559
+ }
560
+
561
+ if (error.statusCode === 403) {
562
+ throw new Error('Access denied - check PAT permissions');
563
+ }
564
+
565
+ if (error.statusCode === 404 && context.id) {
566
+ throw new Error(`Work item not found: ${context.id}`);
567
+ }
568
+
569
+ // Rethrow other errors
570
+ throw error;
571
+ }
572
+ }
573
+ }
574
+
575
+ module.exports = AzureDevOpsProvider;