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.
- package/README.md +307 -56
- package/autopm/.claude/.env +158 -0
- package/autopm/.claude/settings.local.json +9 -0
- package/bin/autopm.js +11 -2
- package/bin/commands/epic.js +23 -3
- package/bin/commands/plugin.js +395 -0
- package/bin/commands/team.js +184 -10
- package/install/install.js +223 -4
- package/lib/cli/commands/issue.js +360 -20
- package/lib/plugins/PluginManager.js +1328 -0
- package/lib/plugins/PluginManager.old.js +400 -0
- package/lib/providers/AzureDevOpsProvider.js +575 -0
- package/lib/providers/GitHubProvider.js +475 -0
- package/lib/services/EpicService.js +1092 -3
- package/lib/services/IssueService.js +991 -0
- package/package.json +9 -1
- package/scripts/publish-plugins.sh +166 -0
- package/autopm/.claude/agents/cloud/README.md +0 -55
- package/autopm/.claude/agents/cloud/aws-cloud-architect.md +0 -521
- package/autopm/.claude/agents/cloud/azure-cloud-architect.md +0 -436
- package/autopm/.claude/agents/cloud/gcp-cloud-architect.md +0 -385
- package/autopm/.claude/agents/cloud/gcp-cloud-functions-engineer.md +0 -306
- package/autopm/.claude/agents/cloud/gemini-api-expert.md +0 -880
- package/autopm/.claude/agents/cloud/kubernetes-orchestrator.md +0 -566
- package/autopm/.claude/agents/cloud/openai-python-expert.md +0 -1087
- package/autopm/.claude/agents/cloud/terraform-infrastructure-expert.md +0 -454
- package/autopm/.claude/agents/core/agent-manager.md +0 -296
- package/autopm/.claude/agents/core/code-analyzer.md +0 -131
- package/autopm/.claude/agents/core/file-analyzer.md +0 -162
- package/autopm/.claude/agents/core/test-runner.md +0 -200
- package/autopm/.claude/agents/data/airflow-orchestration-expert.md +0 -52
- package/autopm/.claude/agents/data/kedro-pipeline-expert.md +0 -50
- package/autopm/.claude/agents/data/langgraph-workflow-expert.md +0 -520
- package/autopm/.claude/agents/databases/README.md +0 -50
- package/autopm/.claude/agents/databases/bigquery-expert.md +0 -392
- package/autopm/.claude/agents/databases/cosmosdb-expert.md +0 -368
- package/autopm/.claude/agents/databases/mongodb-expert.md +0 -398
- package/autopm/.claude/agents/databases/postgresql-expert.md +0 -321
- package/autopm/.claude/agents/databases/redis-expert.md +0 -52
- package/autopm/.claude/agents/devops/README.md +0 -52
- package/autopm/.claude/agents/devops/azure-devops-specialist.md +0 -308
- package/autopm/.claude/agents/devops/docker-containerization-expert.md +0 -298
- package/autopm/.claude/agents/devops/github-operations-specialist.md +0 -335
- package/autopm/.claude/agents/devops/mcp-context-manager.md +0 -319
- package/autopm/.claude/agents/devops/observability-engineer.md +0 -574
- package/autopm/.claude/agents/devops/ssh-operations-expert.md +0 -1093
- package/autopm/.claude/agents/devops/traefik-proxy-expert.md +0 -444
- package/autopm/.claude/agents/frameworks/README.md +0 -64
- package/autopm/.claude/agents/frameworks/e2e-test-engineer.md +0 -360
- package/autopm/.claude/agents/frameworks/nats-messaging-expert.md +0 -254
- package/autopm/.claude/agents/frameworks/react-frontend-engineer.md +0 -217
- package/autopm/.claude/agents/frameworks/react-ui-expert.md +0 -226
- package/autopm/.claude/agents/frameworks/tailwindcss-expert.md +0 -770
- package/autopm/.claude/agents/frameworks/ux-design-expert.md +0 -244
- package/autopm/.claude/agents/integration/message-queue-engineer.md +0 -794
- package/autopm/.claude/agents/languages/README.md +0 -50
- package/autopm/.claude/agents/languages/bash-scripting-expert.md +0 -541
- package/autopm/.claude/agents/languages/javascript-frontend-engineer.md +0 -197
- package/autopm/.claude/agents/languages/nodejs-backend-engineer.md +0 -226
- package/autopm/.claude/agents/languages/python-backend-engineer.md +0 -214
- package/autopm/.claude/agents/languages/python-backend-expert.md +0 -289
- package/autopm/.claude/agents/testing/frontend-testing-engineer.md +0 -395
- package/autopm/.claude/commands/ai/langgraph-workflow.md +0 -65
- package/autopm/.claude/commands/ai/openai-chat.md +0 -65
- package/autopm/.claude/commands/azure/COMMANDS.md +0 -107
- package/autopm/.claude/commands/azure/COMMAND_MAPPING.md +0 -252
- package/autopm/.claude/commands/azure/INTEGRATION_FIX.md +0 -103
- package/autopm/.claude/commands/azure/README.md +0 -246
- package/autopm/.claude/commands/azure/active-work.md +0 -198
- package/autopm/.claude/commands/azure/aliases.md +0 -143
- package/autopm/.claude/commands/azure/blocked-items.md +0 -287
- package/autopm/.claude/commands/azure/clean.md +0 -93
- package/autopm/.claude/commands/azure/docs-query.md +0 -48
- package/autopm/.claude/commands/azure/feature-decompose.md +0 -380
- package/autopm/.claude/commands/azure/feature-list.md +0 -61
- package/autopm/.claude/commands/azure/feature-new.md +0 -115
- package/autopm/.claude/commands/azure/feature-show.md +0 -205
- package/autopm/.claude/commands/azure/feature-start.md +0 -130
- package/autopm/.claude/commands/azure/fix-integration-example.md +0 -93
- package/autopm/.claude/commands/azure/help.md +0 -150
- package/autopm/.claude/commands/azure/import-us.md +0 -269
- package/autopm/.claude/commands/azure/init.md +0 -211
- package/autopm/.claude/commands/azure/next-task.md +0 -262
- package/autopm/.claude/commands/azure/search.md +0 -160
- package/autopm/.claude/commands/azure/sprint-status.md +0 -235
- package/autopm/.claude/commands/azure/standup.md +0 -260
- package/autopm/.claude/commands/azure/sync-all.md +0 -99
- package/autopm/.claude/commands/azure/task-analyze.md +0 -186
- package/autopm/.claude/commands/azure/task-close.md +0 -329
- package/autopm/.claude/commands/azure/task-edit.md +0 -145
- package/autopm/.claude/commands/azure/task-list.md +0 -263
- package/autopm/.claude/commands/azure/task-new.md +0 -84
- package/autopm/.claude/commands/azure/task-reopen.md +0 -79
- package/autopm/.claude/commands/azure/task-show.md +0 -126
- package/autopm/.claude/commands/azure/task-start.md +0 -301
- package/autopm/.claude/commands/azure/task-status.md +0 -65
- package/autopm/.claude/commands/azure/task-sync.md +0 -67
- package/autopm/.claude/commands/azure/us-edit.md +0 -164
- package/autopm/.claude/commands/azure/us-list.md +0 -202
- package/autopm/.claude/commands/azure/us-new.md +0 -265
- package/autopm/.claude/commands/azure/us-parse.md +0 -253
- package/autopm/.claude/commands/azure/us-show.md +0 -188
- package/autopm/.claude/commands/azure/us-status.md +0 -320
- package/autopm/.claude/commands/azure/validate.md +0 -86
- package/autopm/.claude/commands/azure/work-item-sync.md +0 -47
- package/autopm/.claude/commands/cloud/infra-deploy.md +0 -38
- package/autopm/.claude/commands/github/workflow-create.md +0 -42
- package/autopm/.claude/commands/infrastructure/ssh-security.md +0 -65
- package/autopm/.claude/commands/infrastructure/traefik-setup.md +0 -65
- package/autopm/.claude/commands/kubernetes/deploy.md +0 -37
- package/autopm/.claude/commands/playwright/test-scaffold.md +0 -38
- package/autopm/.claude/commands/pm/blocked.md +0 -28
- package/autopm/.claude/commands/pm/clean.md +0 -119
- package/autopm/.claude/commands/pm/context-create.md +0 -136
- package/autopm/.claude/commands/pm/context-prime.md +0 -170
- package/autopm/.claude/commands/pm/context-update.md +0 -292
- package/autopm/.claude/commands/pm/context.md +0 -28
- package/autopm/.claude/commands/pm/epic-close.md +0 -86
- package/autopm/.claude/commands/pm/epic-decompose.md +0 -370
- package/autopm/.claude/commands/pm/epic-edit.md +0 -83
- package/autopm/.claude/commands/pm/epic-list.md +0 -30
- package/autopm/.claude/commands/pm/epic-merge.md +0 -222
- package/autopm/.claude/commands/pm/epic-oneshot.md +0 -119
- package/autopm/.claude/commands/pm/epic-refresh.md +0 -119
- package/autopm/.claude/commands/pm/epic-show.md +0 -28
- package/autopm/.claude/commands/pm/epic-split.md +0 -120
- package/autopm/.claude/commands/pm/epic-start.md +0 -195
- package/autopm/.claude/commands/pm/epic-status.md +0 -28
- package/autopm/.claude/commands/pm/epic-sync-modular.md +0 -338
- package/autopm/.claude/commands/pm/epic-sync-original.md +0 -473
- package/autopm/.claude/commands/pm/epic-sync.md +0 -486
- package/autopm/.claude/commands/pm/help.md +0 -28
- package/autopm/.claude/commands/pm/import.md +0 -115
- package/autopm/.claude/commands/pm/in-progress.md +0 -28
- package/autopm/.claude/commands/pm/init.md +0 -28
- package/autopm/.claude/commands/pm/issue-analyze.md +0 -202
- package/autopm/.claude/commands/pm/issue-close.md +0 -119
- package/autopm/.claude/commands/pm/issue-edit.md +0 -93
- package/autopm/.claude/commands/pm/issue-reopen.md +0 -87
- package/autopm/.claude/commands/pm/issue-show.md +0 -41
- package/autopm/.claude/commands/pm/issue-start.md +0 -234
- package/autopm/.claude/commands/pm/issue-status.md +0 -95
- package/autopm/.claude/commands/pm/issue-sync.md +0 -411
- package/autopm/.claude/commands/pm/next.md +0 -28
- package/autopm/.claude/commands/pm/prd-edit.md +0 -82
- package/autopm/.claude/commands/pm/prd-list.md +0 -28
- package/autopm/.claude/commands/pm/prd-new.md +0 -55
- package/autopm/.claude/commands/pm/prd-parse.md +0 -42
- package/autopm/.claude/commands/pm/prd-status.md +0 -28
- package/autopm/.claude/commands/pm/search.md +0 -28
- package/autopm/.claude/commands/pm/standup.md +0 -28
- package/autopm/.claude/commands/pm/status.md +0 -28
- package/autopm/.claude/commands/pm/sync.md +0 -99
- package/autopm/.claude/commands/pm/test-reference-update.md +0 -151
- package/autopm/.claude/commands/pm/validate.md +0 -28
- package/autopm/.claude/commands/pm/what-next.md +0 -28
- package/autopm/.claude/commands/python/api-scaffold.md +0 -50
- package/autopm/.claude/commands/python/docs-query.md +0 -48
- package/autopm/.claude/commands/react/app-scaffold.md +0 -50
- package/autopm/.claude/commands/testing/prime.md +0 -314
- package/autopm/.claude/commands/testing/run.md +0 -125
- package/autopm/.claude/commands/ui/bootstrap-scaffold.md +0 -65
- package/autopm/.claude/commands/ui/tailwind-system.md +0 -64
- package/autopm/.claude/rules/ai-integration-patterns.md +0 -219
- package/autopm/.claude/rules/ci-cd-kubernetes-strategy.md +0 -25
- package/autopm/.claude/rules/database-management-strategy.md +0 -17
- package/autopm/.claude/rules/database-pipeline.md +0 -94
- package/autopm/.claude/rules/devops-troubleshooting-playbook.md +0 -450
- package/autopm/.claude/rules/docker-first-development.md +0 -404
- package/autopm/.claude/rules/infrastructure-pipeline.md +0 -128
- package/autopm/.claude/rules/performance-guidelines.md +0 -403
- package/autopm/.claude/rules/ui-development-standards.md +0 -281
- package/autopm/.claude/rules/ui-framework-rules.md +0 -151
- package/autopm/.claude/rules/ux-design-rules.md +0 -209
- package/autopm/.claude/rules/visual-testing.md +0 -223
- package/autopm/.claude/scripts/azure/README.md +0 -192
- package/autopm/.claude/scripts/azure/active-work.js +0 -524
- package/autopm/.claude/scripts/azure/active-work.sh +0 -20
- package/autopm/.claude/scripts/azure/blocked.js +0 -520
- package/autopm/.claude/scripts/azure/blocked.sh +0 -20
- package/autopm/.claude/scripts/azure/daily.js +0 -533
- package/autopm/.claude/scripts/azure/daily.sh +0 -20
- package/autopm/.claude/scripts/azure/dashboard.js +0 -970
- package/autopm/.claude/scripts/azure/dashboard.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-list.js +0 -254
- package/autopm/.claude/scripts/azure/feature-list.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-show.js +0 -7
- package/autopm/.claude/scripts/azure/feature-show.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-status.js +0 -604
- package/autopm/.claude/scripts/azure/feature-status.sh +0 -20
- package/autopm/.claude/scripts/azure/help.js +0 -342
- package/autopm/.claude/scripts/azure/help.sh +0 -20
- package/autopm/.claude/scripts/azure/next-task.js +0 -508
- package/autopm/.claude/scripts/azure/next-task.sh +0 -20
- package/autopm/.claude/scripts/azure/search.js +0 -469
- package/autopm/.claude/scripts/azure/search.sh +0 -20
- package/autopm/.claude/scripts/azure/setup.js +0 -745
- package/autopm/.claude/scripts/azure/setup.sh +0 -20
- package/autopm/.claude/scripts/azure/sprint-report.js +0 -1012
- package/autopm/.claude/scripts/azure/sprint-report.sh +0 -20
- package/autopm/.claude/scripts/azure/sync.js +0 -563
- package/autopm/.claude/scripts/azure/sync.sh +0 -20
- package/autopm/.claude/scripts/azure/us-list.js +0 -210
- package/autopm/.claude/scripts/azure/us-list.sh +0 -20
- package/autopm/.claude/scripts/azure/us-status.js +0 -238
- package/autopm/.claude/scripts/azure/us-status.sh +0 -20
- package/autopm/.claude/scripts/azure/validate.js +0 -626
- package/autopm/.claude/scripts/azure/validate.sh +0 -20
- package/autopm/.claude/scripts/azure/wrapper-template.sh +0 -20
- package/autopm/.claude/scripts/github/dependency-tracker.js +0 -554
- package/autopm/.claude/scripts/github/dependency-validator.js +0 -545
- package/autopm/.claude/scripts/github/dependency-visualizer.js +0 -477
- package/autopm/.claude/scripts/pm/analytics.js +0 -425
- package/autopm/.claude/scripts/pm/blocked.js +0 -164
- package/autopm/.claude/scripts/pm/blocked.sh +0 -78
- package/autopm/.claude/scripts/pm/clean.js +0 -464
- package/autopm/.claude/scripts/pm/context-create.js +0 -216
- package/autopm/.claude/scripts/pm/context-prime.js +0 -335
- package/autopm/.claude/scripts/pm/context-update.js +0 -344
- package/autopm/.claude/scripts/pm/context.js +0 -338
- package/autopm/.claude/scripts/pm/epic-close.js +0 -347
- package/autopm/.claude/scripts/pm/epic-edit.js +0 -382
- package/autopm/.claude/scripts/pm/epic-list.js +0 -273
- package/autopm/.claude/scripts/pm/epic-list.sh +0 -109
- package/autopm/.claude/scripts/pm/epic-show.js +0 -291
- package/autopm/.claude/scripts/pm/epic-show.sh +0 -105
- package/autopm/.claude/scripts/pm/epic-split.js +0 -522
- package/autopm/.claude/scripts/pm/epic-start/epic-start.js +0 -183
- package/autopm/.claude/scripts/pm/epic-start/epic-start.sh +0 -94
- package/autopm/.claude/scripts/pm/epic-status.js +0 -291
- package/autopm/.claude/scripts/pm/epic-status.sh +0 -104
- package/autopm/.claude/scripts/pm/epic-sync/README.md +0 -208
- package/autopm/.claude/scripts/pm/epic-sync/create-epic-issue.sh +0 -77
- package/autopm/.claude/scripts/pm/epic-sync/create-task-issues.sh +0 -86
- package/autopm/.claude/scripts/pm/epic-sync/update-epic-file.sh +0 -79
- package/autopm/.claude/scripts/pm/epic-sync/update-references.sh +0 -89
- package/autopm/.claude/scripts/pm/epic-sync.sh +0 -137
- package/autopm/.claude/scripts/pm/help.js +0 -92
- package/autopm/.claude/scripts/pm/help.sh +0 -90
- package/autopm/.claude/scripts/pm/in-progress.js +0 -178
- package/autopm/.claude/scripts/pm/in-progress.sh +0 -93
- package/autopm/.claude/scripts/pm/init.js +0 -321
- package/autopm/.claude/scripts/pm/init.sh +0 -178
- package/autopm/.claude/scripts/pm/issue-close.js +0 -232
- package/autopm/.claude/scripts/pm/issue-edit.js +0 -310
- package/autopm/.claude/scripts/pm/issue-show.js +0 -272
- package/autopm/.claude/scripts/pm/issue-start.js +0 -181
- package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +0 -468
- package/autopm/.claude/scripts/pm/issue-sync/gather-updates.sh +0 -460
- package/autopm/.claude/scripts/pm/issue-sync/post-comment.sh +0 -330
- package/autopm/.claude/scripts/pm/issue-sync/preflight-validation.sh +0 -348
- package/autopm/.claude/scripts/pm/issue-sync/update-frontmatter.sh +0 -387
- package/autopm/.claude/scripts/pm/lib/README.md +0 -85
- package/autopm/.claude/scripts/pm/lib/epic-discovery.js +0 -119
- package/autopm/.claude/scripts/pm/lib/logger.js +0 -78
- package/autopm/.claude/scripts/pm/next.js +0 -189
- package/autopm/.claude/scripts/pm/next.sh +0 -72
- package/autopm/.claude/scripts/pm/optimize.js +0 -407
- package/autopm/.claude/scripts/pm/pr-create.js +0 -337
- package/autopm/.claude/scripts/pm/pr-list.js +0 -257
- package/autopm/.claude/scripts/pm/prd-list.js +0 -242
- package/autopm/.claude/scripts/pm/prd-list.sh +0 -103
- package/autopm/.claude/scripts/pm/prd-new.js +0 -684
- package/autopm/.claude/scripts/pm/prd-parse.js +0 -547
- package/autopm/.claude/scripts/pm/prd-status.js +0 -152
- package/autopm/.claude/scripts/pm/prd-status.sh +0 -63
- package/autopm/.claude/scripts/pm/release.js +0 -460
- package/autopm/.claude/scripts/pm/search.js +0 -192
- package/autopm/.claude/scripts/pm/search.sh +0 -89
- package/autopm/.claude/scripts/pm/standup.js +0 -362
- package/autopm/.claude/scripts/pm/standup.sh +0 -95
- package/autopm/.claude/scripts/pm/status.js +0 -148
- package/autopm/.claude/scripts/pm/status.sh +0 -59
- package/autopm/.claude/scripts/pm/sync-batch.js +0 -337
- package/autopm/.claude/scripts/pm/sync.js +0 -343
- package/autopm/.claude/scripts/pm/template-list.js +0 -141
- package/autopm/.claude/scripts/pm/template-new.js +0 -366
- package/autopm/.claude/scripts/pm/validate.js +0 -274
- package/autopm/.claude/scripts/pm/validate.sh +0 -106
- package/autopm/.claude/scripts/pm/what-next.js +0 -660
- 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, '"')
|
|
233
|
-
.replace(/\[/g, '[')
|
|
234
|
-
.replace(/\]/g, ']')
|
|
235
|
-
.replace(/\(/g, '(')
|
|
236
|
-
.replace(/\)/g, ')')
|
|
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;
|