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
@@ -1,477 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * GitHub Issue Dependency Visualizer
4
- *
5
- * Generates visual representations of issue dependency graphs:
6
- * - ASCII tree output for console
7
- * - Mermaid diagram format
8
- * - Graphviz DOT format
9
- * - JSON graph data
10
- *
11
- * @module dependency-visualizer
12
- */
13
-
14
- const fs = require('fs');
15
- const path = require('path');
16
- const DependencyTracker = require('./dependency-tracker.js');
17
-
18
- /**
19
- * DependencyVisualizer class for visualizing GitHub issue dependencies
20
- */
21
- class DependencyVisualizer {
22
- /**
23
- * Initialize dependency visualizer
24
- *
25
- * @param {Object} config - Configuration options
26
- * @param {string} config.owner - GitHub repository owner
27
- * @param {string} config.repo - GitHub repository name
28
- * @param {string} config.token - GitHub personal access token
29
- * @param {boolean} config.localMode - Enable local mode
30
- * @param {string} config.cacheDir - Directory for local cache
31
- */
32
- constructor(config = {}) {
33
- this.localMode = config.localMode || false;
34
- this.cacheDir = config.cacheDir || path.join(process.cwd(), '.claude', 'cache');
35
- this.tracker = new DependencyTracker(config);
36
- }
37
-
38
- /**
39
- * Generate dependency graph data structure
40
- *
41
- * @param {number} issueNumber - Root issue to start from
42
- * @param {Object} options - Generation options
43
- * @param {number} options.depth - Maximum depth to traverse
44
- * @returns {Promise<Object>} Graph with nodes and edges
45
- */
46
- async generateGraph(issueNumber, options = {}) {
47
- const maxDepth = options.depth || 10;
48
- const nodes = [];
49
- const edges = [];
50
- const visited = new Set();
51
- let hasCircular = false;
52
-
53
- /**
54
- * Recursively build graph
55
- */
56
- const buildGraph = async (current, depth = 0) => {
57
- if (depth > maxDepth) return;
58
-
59
- if (visited.has(current)) {
60
- hasCircular = true;
61
- return;
62
- }
63
-
64
- visited.add(current);
65
-
66
- try {
67
- // Get issue details
68
- let issueData;
69
-
70
- if (this.localMode) {
71
- issueData = await this._getIssueLocal(current);
72
- } else {
73
- const issue = await this.tracker.octokit.rest.issues.get({
74
- owner: this.tracker.owner,
75
- repo: this.tracker.repo,
76
- issue_number: current
77
- });
78
- issueData = issue.data;
79
- }
80
-
81
- // Add node
82
- nodes.push({
83
- number: issueData.number,
84
- title: issueData.title,
85
- state: issueData.state,
86
- labels: issueData.labels || [],
87
- assignees: issueData.assignees || []
88
- });
89
-
90
- // Get dependencies
91
- const dependencies = await this.tracker.getDependencies(current);
92
-
93
- // Add edges and recurse
94
- for (const dep of dependencies) {
95
- edges.push({
96
- from: current,
97
- to: dep
98
- });
99
-
100
- await buildGraph(dep, depth + 1);
101
- }
102
- } catch (error) {
103
- // Add error node
104
- nodes.push({
105
- number: current,
106
- title: 'Error loading issue',
107
- state: 'error',
108
- error: error.message
109
- });
110
- }
111
- };
112
-
113
- try {
114
- await buildGraph(issueNumber);
115
-
116
- return {
117
- nodes,
118
- edges,
119
- circular: hasCircular,
120
- rootIssue: issueNumber
121
- };
122
- } catch (error) {
123
- return {
124
- nodes: [],
125
- edges: [],
126
- error: error.message,
127
- rootIssue: issueNumber
128
- };
129
- }
130
- }
131
-
132
- /**
133
- * Get issue from local cache
134
- * @private
135
- */
136
- async _getIssueLocal(issueNumber) {
137
- const issuesFile = path.join(this.cacheDir, 'issues.json');
138
-
139
- if (!fs.existsSync(issuesFile)) {
140
- return {
141
- number: issueNumber,
142
- title: `Issue #${issueNumber}`,
143
- state: 'unknown',
144
- labels: [],
145
- assignees: []
146
- };
147
- }
148
-
149
- const issues = JSON.parse(fs.readFileSync(issuesFile, 'utf8'));
150
- return issues[issueNumber.toString()] || {
151
- number: issueNumber,
152
- title: `Issue #${issueNumber}`,
153
- state: 'unknown',
154
- labels: [],
155
- assignees: []
156
- };
157
- }
158
-
159
- /**
160
- * Export dependency graph as Mermaid diagram
161
- *
162
- * @param {number} issueNumber - Root issue
163
- * @param {Object} options - Export options
164
- * @param {boolean} options.showBlockedBy - Show issues this blocks
165
- * @param {string} options.outputFile - File to save to
166
- * @returns {Promise<string>} Mermaid diagram code
167
- */
168
- async exportMermaid(issueNumber, options = {}) {
169
- const graph = await this.generateGraph(issueNumber);
170
- const lines = ['graph TD'];
171
-
172
- // Add nodes
173
- for (const node of graph.nodes) {
174
- const title = this._escapeMermaid(node.title);
175
- const label = `#${node.number}: ${title}`;
176
- lines.push(` ${node.number}["${label}"]`);
177
-
178
- // Add styling based on state
179
- if (node.state === 'closed') {
180
- lines.push(` style ${node.number} fill:#d1ffd1,stroke:#4caf50`);
181
- } else if (node.state === 'open') {
182
- lines.push(` style ${node.number} fill:#fff3cd,stroke:#ff9800`);
183
- } else if (node.state === 'error') {
184
- lines.push(` style ${node.number} fill:#ffcccc,stroke:#f44336`);
185
- }
186
- }
187
-
188
- // Add edges
189
- for (const edge of graph.edges) {
190
- lines.push(` ${edge.from} --> ${edge.to}`);
191
- }
192
-
193
- // Add blocked-by relationships if requested
194
- if (options.showBlockedBy) {
195
- try {
196
- const blocked = await this.tracker.getBlockedIssues(issueNumber);
197
- for (const blockedNum of blocked) {
198
- if (!graph.nodes.find(n => n.number === blockedNum)) {
199
- const blockedIssue = await this.tracker.octokit.rest.issues.get({
200
- owner: this.tracker.owner,
201
- repo: this.tracker.repo,
202
- issue_number: blockedNum
203
- });
204
-
205
- const title = this._escapeMermaid(blockedIssue.data.title);
206
- lines.push(` ${blockedNum}["#${blockedNum}: ${title}"]`);
207
- lines.push(` ${blockedNum} -.-> ${issueNumber}`);
208
- }
209
- }
210
- } catch {
211
- // Silently ignore errors
212
- }
213
- }
214
-
215
- const mermaid = lines.join('\n');
216
-
217
- // Save to file if requested
218
- if (options.outputFile) {
219
- fs.writeFileSync(options.outputFile, mermaid, 'utf8');
220
- }
221
-
222
- return mermaid;
223
- }
224
-
225
- /**
226
- * Escape special characters for Mermaid
227
- * @private
228
- */
229
- _escapeMermaid(text) {
230
- if (!text) return '';
231
- return text
232
- .replace(/"/g, '&#34;')
233
- .replace(/\[/g, '&#91;')
234
- .replace(/\]/g, '&#93;')
235
- .replace(/\(/g, '&#40;')
236
- .replace(/\)/g, '&#41;')
237
- .substring(0, 50); // Limit length
238
- }
239
-
240
- /**
241
- * Export dependency graph as Graphviz DOT format
242
- *
243
- * @param {number} issueNumber - Root issue
244
- * @param {Object} options - Export options
245
- * @param {string} options.outputFile - File to save to
246
- * @returns {Promise<string>} DOT format code
247
- */
248
- async exportGraphviz(issueNumber, options = {}) {
249
- const graph = await this.generateGraph(issueNumber);
250
- const lines = ['digraph dependencies {'];
251
- lines.push(' rankdir=LR;');
252
- lines.push(' node [shape=box, style=filled];');
253
-
254
- // Add nodes
255
- for (const node of graph.nodes) {
256
- const title = this._escapeGraphviz(node.title);
257
- const label = `#${node.number}: ${title}`;
258
-
259
- let color = 'lightblue';
260
- if (node.state === 'closed') {
261
- color = 'lightgreen';
262
- } else if (node.state === 'error') {
263
- color = 'lightcoral';
264
- }
265
-
266
- lines.push(` ${node.number} [label="${label}", fillcolor="${color}"];`);
267
- }
268
-
269
- // Add edges
270
- for (const edge of graph.edges) {
271
- lines.push(` ${edge.from} -> ${edge.to};`);
272
- }
273
-
274
- lines.push('}');
275
-
276
- const dot = lines.join('\n');
277
-
278
- // Save to file if requested
279
- if (options.outputFile) {
280
- fs.writeFileSync(options.outputFile, dot, 'utf8');
281
- }
282
-
283
- return dot;
284
- }
285
-
286
- /**
287
- * Escape special characters for Graphviz
288
- * @private
289
- */
290
- _escapeGraphviz(text) {
291
- if (!text) return '';
292
- return text
293
- .replace(/"/g, '\\"')
294
- .replace(/\n/g, '\\n')
295
- .substring(0, 50);
296
- }
297
-
298
- /**
299
- * Print dependency tree to console
300
- *
301
- * @param {number} issueNumber - Root issue
302
- * @param {Object} options - Print options
303
- * @returns {Promise<void>}
304
- */
305
- async printTree(issueNumber, options = {}) {
306
- const visited = new Set();
307
-
308
- /**
309
- * Recursively print tree
310
- */
311
- const printNode = async (current, prefix = '', isLast = true, depth = 0) => {
312
- if (depth > 10) return;
313
-
314
- if (visited.has(current)) {
315
- console.log(`${prefix}${isLast ? '└── ' : '├── '}#${current} (circular)`);
316
- return;
317
- }
318
-
319
- visited.add(current);
320
-
321
- try {
322
- // Get issue details
323
- let issueData;
324
-
325
- if (this.localMode) {
326
- issueData = await this._getIssueLocal(current);
327
- } else {
328
- const issue = await this.tracker.octokit.rest.issues.get({
329
- owner: this.tracker.owner,
330
- repo: this.tracker.repo,
331
- issue_number: current
332
- });
333
- issueData = issue.data;
334
- }
335
-
336
- // Print node
337
- const icon = issueData.state === 'closed' ? '✓' : '○';
338
- const title = issueData.title.substring(0, 60);
339
- console.log(`${prefix}${isLast ? '└── ' : '├── '}${icon} #${current}: ${title}`);
340
-
341
- // Get and print dependencies
342
- const dependencies = await this.tracker.getDependencies(current);
343
-
344
- if (dependencies.length > 0) {
345
- const newPrefix = prefix + (isLast ? ' ' : '│ ');
346
-
347
- for (let i = 0; i < dependencies.length; i++) {
348
- const dep = dependencies[i];
349
- const isLastDep = i === dependencies.length - 1;
350
- await printNode(dep, newPrefix, isLastDep, depth + 1);
351
- }
352
- }
353
- } catch (error) {
354
- console.log(`${prefix}${isLast ? '└── ' : '├── '}✗ #${current}: Error - ${error.message}`);
355
- }
356
- };
357
-
358
- console.log('\nDependency Tree:');
359
- console.log('═'.repeat(50));
360
- await printNode(issueNumber);
361
- console.log('');
362
- }
363
-
364
- /**
365
- * Save graph data as JSON
366
- *
367
- * @param {Object} graph - Graph data from generateGraph
368
- * @param {string} filePath - File path to save to
369
- */
370
- saveGraphData(graph, filePath) {
371
- fs.writeFileSync(filePath, JSON.stringify(graph, null, 2), 'utf8');
372
- }
373
-
374
- /**
375
- * Generate summary statistics for graph
376
- *
377
- * @param {Object} graph - Graph data
378
- * @returns {Object} Statistics
379
- */
380
- getGraphStats(graph) {
381
- const total = graph.nodes.length;
382
- const open = graph.nodes.filter(n => n.state === 'open').length;
383
- const closed = graph.nodes.filter(n => n.state === 'closed').length;
384
- const errors = graph.nodes.filter(n => n.state === 'error').length;
385
-
386
- return {
387
- total,
388
- open,
389
- closed,
390
- errors,
391
- edges: graph.edges.length,
392
- circular: graph.circular,
393
- progress: total > 0 ? Math.round((closed / total) * 100) : 0
394
- };
395
- }
396
- }
397
-
398
- // CLI interface
399
- if (require.main === module) {
400
- const command = process.argv[2];
401
- const issueNumber = parseInt(process.argv[3], 10);
402
- const outputFile = process.argv[4];
403
-
404
- const visualizer = new DependencyVisualizer();
405
-
406
- (async () => {
407
- switch (command) {
408
- case 'tree':
409
- await visualizer.printTree(issueNumber);
410
- break;
411
-
412
- case 'mermaid':
413
- const mermaid = await visualizer.exportMermaid(issueNumber, {
414
- outputFile
415
- });
416
- if (!outputFile) {
417
- console.log(mermaid);
418
- } else {
419
- console.log(`✓ Mermaid diagram saved to: ${outputFile}`);
420
- }
421
- break;
422
-
423
- case 'graphviz':
424
- case 'dot':
425
- const dot = await visualizer.exportGraphviz(issueNumber, {
426
- outputFile
427
- });
428
- if (!outputFile) {
429
- console.log(dot);
430
- } else {
431
- console.log(`✓ Graphviz DOT saved to: ${outputFile}`);
432
- }
433
- break;
434
-
435
- case 'json':
436
- const graph = await visualizer.generateGraph(issueNumber);
437
- if (outputFile) {
438
- visualizer.saveGraphData(graph, outputFile);
439
- console.log(`✓ Graph data saved to: ${outputFile}`);
440
- } else {
441
- console.log(JSON.stringify(graph, null, 2));
442
- }
443
- break;
444
-
445
- case 'stats':
446
- const statsGraph = await visualizer.generateGraph(issueNumber);
447
- const stats = visualizer.getGraphStats(statsGraph);
448
-
449
- console.log('\nDependency Graph Statistics:');
450
- console.log('─'.repeat(50));
451
- console.log(`Total Issues: ${stats.total}`);
452
- console.log(`Open: ${stats.open}`);
453
- console.log(`Closed: ${stats.closed}`);
454
- console.log(`Errors: ${stats.errors}`);
455
- console.log(`Dependencies: ${stats.edges}`);
456
- console.log(`Circular: ${stats.circular ? 'YES ⚠' : 'NO'}`);
457
- console.log(`Progress: ${stats.progress}%`);
458
- break;
459
-
460
- default:
461
- console.error('Usage: dependency-visualizer.js <tree|mermaid|graphviz|json|stats> <issue> [output-file]');
462
- console.error('');
463
- console.error('Examples:');
464
- console.error(' dependency-visualizer.js tree 123');
465
- console.error(' dependency-visualizer.js mermaid 123 diagram.mmd');
466
- console.error(' dependency-visualizer.js graphviz 123 graph.dot');
467
- console.error(' dependency-visualizer.js json 123 data.json');
468
- console.error(' dependency-visualizer.js stats 123');
469
- process.exit(1);
470
- }
471
- })().catch(error => {
472
- console.error('Error:', error.message);
473
- process.exit(1);
474
- });
475
- }
476
-
477
- module.exports = DependencyVisualizer;