claude-autopm 1.17.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +159 -0
  2. package/autopm/.claude/agents/core/mcp-manager.md +1 -1
  3. package/autopm/.claude/commands/pm/context.md +11 -0
  4. package/autopm/.claude/commands/pm/epic-decompose.md +25 -2
  5. package/autopm/.claude/commands/pm/epic-oneshot.md +13 -0
  6. package/autopm/.claude/commands/pm/epic-start.md +19 -0
  7. package/autopm/.claude/commands/pm/epic-sync-modular.md +10 -10
  8. package/autopm/.claude/commands/pm/epic-sync.md +14 -14
  9. package/autopm/.claude/commands/pm/issue-start.md +50 -5
  10. package/autopm/.claude/commands/pm/issue-sync.md +15 -15
  11. package/autopm/.claude/commands/pm/what-next.md +11 -0
  12. package/autopm/.claude/mcp/MCP-REGISTRY.md +1 -1
  13. package/autopm/.claude/scripts/azure/active-work.js +2 -2
  14. package/autopm/.claude/scripts/azure/blocked.js +13 -13
  15. package/autopm/.claude/scripts/azure/daily.js +1 -1
  16. package/autopm/.claude/scripts/azure/dashboard.js +1 -1
  17. package/autopm/.claude/scripts/azure/feature-list.js +2 -2
  18. package/autopm/.claude/scripts/azure/feature-status.js +1 -1
  19. package/autopm/.claude/scripts/azure/next-task.js +1 -1
  20. package/autopm/.claude/scripts/azure/search.js +1 -1
  21. package/autopm/.claude/scripts/azure/setup.js +15 -15
  22. package/autopm/.claude/scripts/azure/sprint-report.js +2 -2
  23. package/autopm/.claude/scripts/azure/sync.js +1 -1
  24. package/autopm/.claude/scripts/azure/us-list.js +1 -1
  25. package/autopm/.claude/scripts/azure/us-status.js +1 -1
  26. package/autopm/.claude/scripts/azure/validate.js +13 -13
  27. package/autopm/.claude/scripts/lib/frontmatter-utils.sh +42 -7
  28. package/autopm/.claude/scripts/lib/logging-utils.sh +20 -16
  29. package/autopm/.claude/scripts/lib/validation-utils.sh +1 -1
  30. package/autopm/.claude/scripts/pm/context.js +338 -0
  31. package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +3 -3
  32. package/autopm/.claude/scripts/pm/lib/README.md +85 -0
  33. package/autopm/.claude/scripts/pm/lib/logger.js +78 -0
  34. package/autopm/.claude/scripts/pm/next.js +25 -1
  35. package/autopm/.claude/scripts/pm/what-next.js +660 -0
  36. package/bin/autopm.js +25 -0
  37. package/bin/commands/team.js +86 -0
  38. package/package.json +1 -1
  39. package/lib/agentExecutor.js.deprecated +0 -101
  40. package/lib/azure/cache.js +0 -80
  41. package/lib/azure/client.js +0 -77
  42. package/lib/azure/formatter.js +0 -177
  43. package/lib/commandHelpers.js +0 -177
  44. package/lib/context/manager.js +0 -290
  45. package/lib/documentation/manager.js +0 -528
  46. package/lib/github/workflow-manager.js +0 -546
  47. package/lib/helpers/azure-batch-api.js +0 -133
  48. package/lib/helpers/azure-cache-manager.js +0 -287
  49. package/lib/helpers/azure-parallel-processor.js +0 -158
  50. package/lib/helpers/azure-work-item-create.js +0 -278
  51. package/lib/helpers/gh-issue-create.js +0 -250
  52. package/lib/helpers/interactive-prompt.js +0 -336
  53. package/lib/helpers/output-manager.js +0 -335
  54. package/lib/helpers/progress-indicator.js +0 -258
  55. package/lib/performance/benchmarker.js +0 -429
  56. package/lib/pm/epic-decomposer.js +0 -273
  57. package/lib/pm/epic-syncer.js +0 -221
  58. package/lib/prdMetadata.js +0 -270
  59. package/lib/providers/azure/index.js +0 -234
  60. package/lib/providers/factory.js +0 -87
  61. package/lib/providers/github/index.js +0 -204
  62. package/lib/providers/interface.js +0 -73
  63. package/lib/python/scaffold-manager.js +0 -576
  64. package/lib/react/scaffold-manager.js +0 -745
  65. package/lib/regression/analyzer.js +0 -578
  66. package/lib/release/manager.js +0 -324
  67. package/lib/tailwind/manager.js +0 -486
  68. package/lib/traefik/manager.js +0 -484
  69. package/lib/utils/colors.js +0 -126
  70. package/lib/utils/config.js +0 -317
  71. package/lib/utils/filesystem.js +0 -316
  72. package/lib/utils/logger.js +0 -135
  73. package/lib/utils/prompts.js +0 -294
  74. package/lib/utils/shell.js +0 -237
  75. package/lib/validators/email-validator.js +0 -337
  76. package/lib/workflow/manager.js +0 -449
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
+ const MCPHandler = require('../../scripts/mcp-handler.js');
5
6
 
6
7
  // Paths
7
8
  const projectRoot = process.cwd();
@@ -68,6 +69,69 @@ function validateAgentFiles(agents, projectRoot) {
68
69
  return missingAgents;
69
70
  }
70
71
 
72
+ // Helper function to validate MCP dependencies for agents
73
+ function validateAgentMCPDependencies(agents, projectRoot) {
74
+ const warnings = [];
75
+
76
+ try {
77
+ const mcpHandler = new MCPHandler();
78
+ const config = mcpHandler.loadConfig();
79
+ const activeServers = config.mcp?.activeServers || [];
80
+
81
+ // Track all required MCP servers across all agents
82
+ const requiredServers = new Map(); // server -> [agents that need it]
83
+
84
+ agents.forEach(agentPath => {
85
+ // Extract agent name from path
86
+ // Handle both "core/test-runner.md" and "test-runner.md" formats
87
+ let agentName = agentPath;
88
+ if (agentName.endsWith('.md')) {
89
+ agentName = agentName.slice(0, -3); // Remove .md extension
90
+ }
91
+ // Get just the filename without directory
92
+ agentName = path.basename(agentName);
93
+
94
+ // Get MCP dependencies for this agent
95
+ const agentMCP = mcpHandler.getAgentMCP(agentName);
96
+
97
+ if (agentMCP.found && agentMCP.mcpServers.length > 0) {
98
+ agentMCP.mcpServers.forEach(serverName => {
99
+ if (!requiredServers.has(serverName)) {
100
+ requiredServers.set(serverName, []);
101
+ }
102
+ requiredServers.get(serverName).push(agentName);
103
+ });
104
+ }
105
+ });
106
+
107
+ // Check which required servers are missing or inactive
108
+ requiredServers.forEach((agentNames, serverName) => {
109
+ const isActive = activeServers.includes(serverName);
110
+ const serverExists = mcpHandler.getServer(serverName);
111
+
112
+ if (!serverExists) {
113
+ warnings.push({
114
+ type: 'not_installed',
115
+ server: serverName,
116
+ agents: agentNames
117
+ });
118
+ } else if (!isActive) {
119
+ warnings.push({
120
+ type: 'not_active',
121
+ server: serverName,
122
+ agents: agentNames
123
+ });
124
+ }
125
+ });
126
+
127
+ } catch (error) {
128
+ // If MCP validation fails, just warn but don't block
129
+ console.warn('āš ļø Warning: Could not validate MCP dependencies');
130
+ }
131
+
132
+ return warnings;
133
+ }
134
+
71
135
  // Helper function to generate agent include list in Markdown format
72
136
  function generateAgentIncludes(agents) {
73
137
  return agents
@@ -216,6 +280,28 @@ const commands = {
216
280
  });
217
281
  }
218
282
 
283
+ // Validate MCP dependencies
284
+ const mcpWarnings = validateAgentMCPDependencies(agents, projectRoot);
285
+ if (mcpWarnings.length > 0) {
286
+ console.warn('\nāš ļø MCP Dependency Warnings:\n');
287
+
288
+ mcpWarnings.forEach(warning => {
289
+ if (warning.type === 'not_installed') {
290
+ console.warn(`āŒ MCP server '${warning.server}' is NOT INSTALLED`);
291
+ console.warn(` Required by: ${warning.agents.join(', ')}`);
292
+ console.warn(` Fix: autopm mcp install ${warning.server}`);
293
+ } else if (warning.type === 'not_active') {
294
+ console.warn(`⚪ MCP server '${warning.server}' is NOT ACTIVE`);
295
+ console.warn(` Required by: ${warning.agents.join(', ')}`);
296
+ console.warn(` Fix: autopm mcp enable ${warning.server}`);
297
+ }
298
+ console.warn('');
299
+ });
300
+
301
+ console.warn('šŸ’” Tip: Run "autopm mcp list" to see all MCP servers');
302
+ console.warn('šŸ’” Tip: Run "autopm mcp setup" for interactive configuration\n');
303
+ }
304
+
219
305
  // Update CLAUDE.md with the new agent list
220
306
  updateClaudeMd(agents);
221
307
  console.log('āœ“ Updated CLAUDE.md with team agents');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-autopm",
3
- "version": "1.17.0",
3
+ "version": "1.20.0",
4
4
  "description": "Autonomous Project Management Framework for Claude Code - Advanced AI-powered development automation",
5
5
  "main": "bin/autopm.js",
6
6
  "bin": {
@@ -1,101 +0,0 @@
1
- /**
2
- * Agent Executor Module
3
- * Handles execution of AI agents with prompts
4
- */
5
-
6
- const fs = require('fs-extra');
7
- const path = require('path');
8
- const { spawn } = require('child_process');
9
- const colors = require('./utils/colors');
10
-
11
- class AgentExecutor {
12
- constructor() {
13
- this.agentsPath = path.join(__dirname, '../autopm/.claude/agents');
14
- }
15
-
16
- /**
17
- * Execute an agent with the given prompt
18
- * @param {string} agentType - The type of agent to execute
19
- * @param {string} prompt - The prompt to send to the agent
20
- * @param {Object} context - Additional context for the agent
21
- * @returns {Promise<Object>} The result of the agent execution
22
- */
23
- async run(agentType, prompt, context = {}) {
24
- console.log(colors.blue(`šŸ¤– Preparing ${agentType} agent...`));
25
-
26
- try {
27
- // Replace $ARGUMENTS in prompt with actual arguments
28
- let finalPrompt = prompt;
29
- if (context.arguments) {
30
- finalPrompt = prompt.replace(/\$ARGUMENTS/g, context.arguments);
31
- }
32
-
33
- // Check if we're in Claude Code environment
34
- const isClaudeCode = process.env.CLAUDE_CODE === 'true' ||
35
- process.env.ANTHROPIC_WORKSPACE === 'true';
36
-
37
- if (isClaudeCode) {
38
- // If in Claude Code, use the Task tool
39
- console.log(colors.cyan('šŸ“‹ Executing via Claude Code Task tool...'));
40
- console.log(colors.gray('Prompt:'), finalPrompt.substring(0, 200) + '...');
41
-
42
- // Claude Code should handle this through its Task tool
43
- // This would be invoked by Claude when running the command
44
- return {
45
- status: 'success',
46
- agent: agentType,
47
- message: 'Agent should be executed via Claude Code Task tool',
48
- prompt: finalPrompt,
49
- context: context
50
- };
51
- }
52
-
53
- // Not in Claude Code - show instructions
54
- console.log();
55
- console.log(colors.yellow('āš ļø This command requires Claude Code'));
56
- console.log();
57
- console.log(colors.cyan('To use AI-powered commands:'));
58
- console.log();
59
- console.log(colors.green('1. Open your project in Claude Code'));
60
- console.log(colors.gray('2. Run commands directly in chat:'));
61
- console.log(colors.gray(` /pm:prd-new ${context.arguments || 'feature-name'}`));
62
- console.log();
63
- console.log(colors.blue('Why Claude Code?'));
64
- console.log(colors.gray('• Interactive brainstorming sessions'));
65
- console.log(colors.gray('• Intelligent context understanding'));
66
- console.log(colors.gray('• Real-time Q&A during PRD creation'));
67
- console.log();
68
- console.log(colors.cyan('šŸ“ What this command would do:'));
69
- console.log(colors.gray('─'.repeat(60)));
70
-
71
- // Show a summary of the command intent
72
- if (agentType === 'pm-specialist' && context.arguments) {
73
- console.log(colors.white(`Create PRD for: ${context.arguments}`));
74
- console.log();
75
- console.log('The AI agent would:');
76
- console.log('1. Ask clarifying questions about the feature');
77
- console.log('2. Help define user stories and requirements');
78
- console.log('3. Generate comprehensive PRD document');
79
- console.log(`4. Save to: .claude/prds/${context.arguments}.md`);
80
- } else {
81
- console.log(finalPrompt.substring(0, 300) + '...');
82
- }
83
- console.log(colors.gray('─'.repeat(60)));
84
-
85
- return {
86
- status: 'claude-required',
87
- agent: agentType,
88
- message: 'Claude Code required for AI-powered commands',
89
- prompt: finalPrompt,
90
- context: context
91
- };
92
-
93
- } catch (error) {
94
- console.error(colors.red(`āŒ Agent execution failed: ${error.message}`));
95
- throw error;
96
- }
97
- }
98
-
99
- }
100
-
101
- module.exports = new AgentExecutor();
@@ -1,80 +0,0 @@
1
- /**
2
- * Simple cache implementation for Azure DevOps API responses
3
- * Uses LRU (Least Recently Used) eviction policy
4
- */
5
-
6
- class AzureCache {
7
- constructor(options = {}) {
8
- this.ttl = options.ttl || 5 * 60 * 1000; // 5 minutes default
9
- this.maxSize = options.maxSize || 100;
10
- this.cache = new Map();
11
- this.stats = { hits: 0, misses: 0 };
12
- }
13
-
14
- get(key) {
15
- const item = this.cache.get(key);
16
-
17
- if (!item) {
18
- this.stats.misses++;
19
- return null;
20
- }
21
-
22
- if (this.isExpired(item)) {
23
- this.cache.delete(key);
24
- this.stats.misses++;
25
- return null;
26
- }
27
-
28
- // Move to end (most recently used)
29
- this.cache.delete(key);
30
- this.cache.set(key, item);
31
-
32
- this.stats.hits++;
33
- return item.value;
34
- }
35
-
36
- set(key, value) {
37
- // Remove oldest item if at capacity
38
- if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
39
- const firstKey = this.cache.keys().next().value;
40
- this.cache.delete(firstKey);
41
- }
42
-
43
- this.cache.set(key, {
44
- value,
45
- timestamp: Date.now()
46
- });
47
- }
48
-
49
- isExpired(item) {
50
- return Date.now() - item.timestamp > this.ttl;
51
- }
52
-
53
- clear() {
54
- this.cache.clear();
55
- this.stats = { hits: 0, misses: 0 };
56
- }
57
-
58
- getStats() {
59
- const total = this.stats.hits + this.stats.misses;
60
- const hitRate = total > 0 ? (this.stats.hits / total * 100).toFixed(2) : 0;
61
-
62
- return {
63
- ...this.stats,
64
- hitRate: `${hitRate}%`,
65
- size: this.cache.size,
66
- maxSize: this.maxSize
67
- };
68
- }
69
-
70
- // Clean up expired entries
71
- cleanup() {
72
- for (const [key, item] of this.cache.entries()) {
73
- if (this.isExpired(item)) {
74
- this.cache.delete(key);
75
- }
76
- }
77
- }
78
- }
79
-
80
- module.exports = AzureCache;
@@ -1,77 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Azure DevOps Client
5
- * Wrapper for Azure DevOps REST API
6
- */
7
-
8
- class AzureDevOpsClient {
9
- constructor(options = {}) {
10
- this.organization = options.organization;
11
- this.project = options.project;
12
- this.token = options.token;
13
- this.baseUrl = `https://dev.azure.com/${this.organization}`;
14
- }
15
-
16
- /**
17
- * Create work item
18
- */
19
- async createWorkItem(options) {
20
- // This would make actual API call
21
- console.log(`Creating ${options.type} work item`);
22
- return {
23
- id: Math.floor(Math.random() * 10000),
24
- fields: options.fields,
25
- url: `${this.baseUrl}/${this.project}/_workitems/edit/${Math.floor(Math.random() * 10000)}`
26
- };
27
- }
28
-
29
- /**
30
- * Update work item
31
- */
32
- async updateWorkItem(options) {
33
- console.log(`Updating work item ${options.id}`);
34
- return {
35
- id: options.id,
36
- fields: options.fields
37
- };
38
- }
39
-
40
- /**
41
- * Get work item
42
- */
43
- async getWorkItem(options) {
44
- console.log(`Getting work item ${options.id}`);
45
- return {
46
- id: options.id,
47
- fields: {
48
- 'System.Title': 'Work Item',
49
- 'System.State': 'Active'
50
- }
51
- };
52
- }
53
- }
54
-
55
- /**
56
- * Create client instance
57
- */
58
- function createClient(options) {
59
- return new AzureDevOpsClient(options);
60
- }
61
-
62
- /**
63
- * Get default client
64
- */
65
- function getClient() {
66
- return createClient({
67
- organization: process.env.AZURE_DEVOPS_ORG,
68
- project: process.env.AZURE_DEVOPS_PROJECT,
69
- token: process.env.AZURE_DEVOPS_PAT
70
- });
71
- }
72
-
73
- module.exports = {
74
- AzureDevOpsClient,
75
- createClient,
76
- getClient
77
- };
@@ -1,177 +0,0 @@
1
- /**
2
- * Azure DevOps Output Formatter
3
- * Formats work items and sprint data for console display
4
- */
5
-
6
- const Table = require('table').table;
7
- const chalk = require('chalk');
8
-
9
- class AzureFormatter {
10
- static formatWorkItems(items, options = {}) {
11
- if (!items || items.length === 0) {
12
- return chalk.yellow('No work items found.');
13
- }
14
-
15
- const headers = this.getHeaders(options);
16
- const rows = items.map(item => this.formatWorkItem(item, options));
17
-
18
- const tableConfig = {
19
- header: {
20
- alignment: 'center',
21
- content: chalk.cyan.bold('Work Items')
22
- }
23
- };
24
-
25
- return Table([headers, ...rows], tableConfig);
26
- }
27
-
28
- static getHeaders(options) {
29
- const headers = [
30
- chalk.bold('ID'),
31
- chalk.bold('Type'),
32
- chalk.bold('Title'),
33
- chalk.bold('State'),
34
- chalk.bold('Assigned To')
35
- ];
36
-
37
- if (options.showRemaining) {
38
- headers.push(chalk.bold('Remaining'));
39
- }
40
-
41
- if (options.showPriority) {
42
- headers.push(chalk.bold('Priority'));
43
- }
44
-
45
- return headers;
46
- }
47
-
48
- static formatWorkItem(item, options) {
49
- const fields = item.fields || {};
50
- const row = [
51
- chalk.blue(item.id),
52
- this.getTypeIcon(fields['System.WorkItemType']),
53
- this.truncate(fields['System.Title'], 50),
54
- this.getStateColor(fields['System.State']),
55
- this.getAssignedTo(fields['System.AssignedTo'])
56
- ];
57
-
58
- if (options.showRemaining) {
59
- row.push(fields['Microsoft.VSTS.Scheduling.RemainingWork'] || '-');
60
- }
61
-
62
- if (options.showPriority) {
63
- row.push(fields['Microsoft.VSTS.Common.Priority'] || '-');
64
- }
65
-
66
- return row;
67
- }
68
-
69
- static getTypeIcon(type) {
70
- const icons = {
71
- 'Task': 'šŸ“‹ Task',
72
- 'Bug': 'šŸ› Bug',
73
- 'User Story': 'šŸ“– Story',
74
- 'Feature': 'šŸŽÆ Feature',
75
- 'Epic': 'šŸ”ļø Epic'
76
- };
77
- return icons[type] || type;
78
- }
79
-
80
- static getStateColor(state) {
81
- const colors = {
82
- 'New': chalk.gray(state),
83
- 'Active': chalk.blue(state),
84
- 'In Progress': chalk.yellow(state),
85
- 'Resolved': chalk.green(state),
86
- 'Closed': chalk.dim(state),
87
- 'Done': chalk.green(state),
88
- 'Removed': chalk.strikethrough(state)
89
- };
90
- return colors[state] || state;
91
- }
92
-
93
- static getAssignedTo(assignedTo) {
94
- if (!assignedTo) return chalk.gray('Unassigned');
95
- const name = assignedTo.displayName || assignedTo.uniqueName || assignedTo;
96
- return this.truncate(name, 20);
97
- }
98
-
99
- static truncate(text, length) {
100
- if (!text) return '';
101
- if (text.length <= length) return text;
102
- return text.substring(0, length - 3) + '...';
103
- }
104
-
105
- static formatSummary(items) {
106
- if (!items || items.length === 0) {
107
- return '';
108
- }
109
-
110
- const states = {};
111
- const types = {};
112
- let totalRemaining = 0;
113
-
114
- items.forEach(item => {
115
- const fields = item.fields || {};
116
- const state = fields['System.State'];
117
- const type = fields['System.WorkItemType'];
118
- const remaining = fields['Microsoft.VSTS.Scheduling.RemainingWork'] || 0;
119
-
120
- states[state] = (states[state] || 0) + 1;
121
- types[type] = (types[type] || 0) + 1;
122
- totalRemaining += remaining;
123
- });
124
-
125
- const lines = [];
126
- lines.push(chalk.bold('\nšŸ“Š Summary:'));
127
- lines.push(`Total items: ${chalk.cyan(items.length)}`);
128
-
129
- if (Object.keys(types).length > 0) {
130
- lines.push('\nBy Type:');
131
- Object.entries(types).forEach(([type, count]) => {
132
- lines.push(` ${this.getTypeIcon(type)}: ${count}`);
133
- });
134
- }
135
-
136
- if (Object.keys(states).length > 0) {
137
- lines.push('\nBy State:');
138
- Object.entries(states).forEach(([state, count]) => {
139
- lines.push(` ${this.getStateColor(state)}: ${count}`);
140
- });
141
- }
142
-
143
- if (totalRemaining > 0) {
144
- lines.push(`\nTotal Remaining Work: ${chalk.yellow(totalRemaining + ' hours')}`);
145
- }
146
-
147
- return lines.join('\n');
148
- }
149
-
150
- static formatSprintInfo(sprint) {
151
- if (!sprint) {
152
- return chalk.yellow('No active sprint found.');
153
- }
154
-
155
- const attributes = sprint.attributes || {};
156
- const startDate = attributes.startDate ? new Date(attributes.startDate).toLocaleDateString() : 'N/A';
157
- const endDate = attributes.finishDate ? new Date(attributes.finishDate).toLocaleDateString() : 'N/A';
158
-
159
- return chalk.cyan.bold(`\nšŸƒ Current Sprint: ${sprint.name}\n`) +
160
- ` Start: ${startDate}\n` +
161
- ` End: ${endDate}\n`;
162
- }
163
-
164
- static formatError(error) {
165
- return chalk.red(`\nāŒ Error: ${error.message}\n`);
166
- }
167
-
168
- static formatSuccess(message) {
169
- return chalk.green(`\nāœ… ${message}\n`);
170
- }
171
-
172
- static formatWarning(message) {
173
- return chalk.yellow(`\nāš ļø ${message}\n`);
174
- }
175
- }
176
-
177
- module.exports = AzureFormatter;