claude-autopm 1.15.5 → 1.16.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.
@@ -0,0 +1,104 @@
1
+ #!/bin/bash
2
+
3
+ # Epic Status Checker
4
+ # Part of ClaudeAutoPM Framework
5
+ # Usage: ./scripts/epic-status.sh [epic-name]
6
+
7
+ EPIC_NAME=${1:-}
8
+
9
+ if [ -z "$EPIC_NAME" ]; then
10
+ echo "Usage: $0 <epic-name>"
11
+ echo ""
12
+ echo "Available epics:"
13
+ if [ -d ".claude/epics" ]; then
14
+ ls -1 .claude/epics/ 2>/dev/null || echo "No epics found"
15
+ else
16
+ echo "No .claude/epics directory found"
17
+ fi
18
+ exit 1
19
+ fi
20
+
21
+ EPIC_DIR=".claude/epics/$EPIC_NAME"
22
+
23
+ if [ ! -d "$EPIC_DIR" ]; then
24
+ echo "Error: Epic '$EPIC_NAME' not found"
25
+ echo ""
26
+ echo "Available epics:"
27
+ ls -1 .claude/epics/ 2>/dev/null
28
+ exit 1
29
+ fi
30
+
31
+ echo "Epic: $EPIC_NAME"
32
+ echo "===================="
33
+ echo ""
34
+
35
+ # Count total tasks
36
+ total_tasks=$(find "$EPIC_DIR" -maxdepth 2 -name "[0-9][0-9][0-9].md" 2>/dev/null | wc -l | tr -d ' ')
37
+
38
+ # Count completed tasks (looking for status: completed in frontmatter)
39
+ completed=0
40
+ in_progress=0
41
+ pending=0
42
+
43
+ for task_file in $(find "$EPIC_DIR" -maxdepth 2 -name "[0-9][0-9][0-9].md" 2>/dev/null); do
44
+ if grep -q "^status: completed" "$task_file" 2>/dev/null; then
45
+ completed=$((completed + 1))
46
+ elif grep -q "^status: in-progress\|^status: in_progress" "$task_file" 2>/dev/null; then
47
+ in_progress=$((in_progress + 1))
48
+ else
49
+ pending=$((pending + 1))
50
+ fi
51
+ done
52
+
53
+ # Calculate progress percentage
54
+ if [ "$total_tasks" -gt 0 ]; then
55
+ progress=$((completed * 100 / total_tasks))
56
+ else
57
+ progress=0
58
+ fi
59
+
60
+ echo "Total tasks: $total_tasks"
61
+ echo "Completed: $completed ($progress%)"
62
+ echo "In Progress: $in_progress"
63
+ echo "Pending: $pending"
64
+ echo ""
65
+
66
+ # Progress bar
67
+ if [ "$total_tasks" -gt 0 ]; then
68
+ bar_length=50
69
+ filled=$((progress * bar_length / 100))
70
+ empty=$((bar_length - filled))
71
+
72
+ printf "Progress: ["
73
+ printf "%${filled}s" | tr ' ' '='
74
+ printf "%${empty}s" | tr ' ' '-'
75
+ printf "] %d%%\n" "$progress"
76
+ echo ""
77
+ fi
78
+
79
+ # Show breakdown by sub-epic if they exist
80
+ sub_dirs=$(find "$EPIC_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l | tr -d ' ')
81
+
82
+ if [ "$sub_dirs" -gt 0 ]; then
83
+ echo "Sub-Epic Breakdown:"
84
+ echo "-------------------"
85
+
86
+ for sub_dir in "$EPIC_DIR"/*/; do
87
+ if [ -d "$sub_dir" ]; then
88
+ sub_name=$(basename "$sub_dir")
89
+ sub_count=$(find "$sub_dir" -maxdepth 1 -name "[0-9][0-9][0-9].md" 2>/dev/null | wc -l | tr -d ' ')
90
+
91
+ if [ "$sub_count" -gt 0 ]; then
92
+ # Count completed in sub-epic
93
+ sub_completed=0
94
+ for task_file in $(find "$sub_dir" -maxdepth 1 -name "[0-9][0-9][0-9].md" 2>/dev/null); do
95
+ if grep -q "^status: completed" "$task_file" 2>/dev/null; then
96
+ sub_completed=$((sub_completed + 1))
97
+ fi
98
+ done
99
+
100
+ printf " %-30s %3d tasks (%d completed)\n" "$sub_name" "$sub_count" "$sub_completed"
101
+ fi
102
+ fi
103
+ done
104
+ fi
package/bin/autopm.js CHANGED
@@ -180,6 +180,8 @@ function main() {
180
180
  .command(require('./commands/config'))
181
181
  // MCP management command
182
182
  .command(require('./commands/mcp'))
183
+ // Epic management command
184
+ .command(require('./commands/epic'))
183
185
  // Validation command
184
186
  .command('validate', 'Validate ClaudeAutoPM configuration and setup',
185
187
  (yargs) => {
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Epic Command for autopm CLI
3
+ * Manages epic status, breakdown, and analysis
4
+ */
5
+
6
+ const path = require('path');
7
+ const { execSync } = require('child_process');
8
+ const fs = require('fs');
9
+
10
+ module.exports = {
11
+ command: 'epic <action> [name]',
12
+ describe: 'Manage epics and view epic status',
13
+
14
+ builder: (yargs) => {
15
+ return yargs
16
+ .positional('action', {
17
+ describe: 'Epic action to perform',
18
+ type: 'string',
19
+ choices: ['status', 'list', 'breakdown']
20
+ })
21
+ .positional('name', {
22
+ describe: 'Epic name (for status action)',
23
+ type: 'string'
24
+ })
25
+ .option('detailed', {
26
+ alias: 'd',
27
+ describe: 'Show detailed breakdown',
28
+ type: 'boolean',
29
+ default: false
30
+ })
31
+ .example('autopm epic list', 'List all available epics')
32
+ .example('autopm epic status fullstack', 'Show status of fullstack epic')
33
+ .example('autopm epic breakdown fullstack', 'Show detailed task breakdown');
34
+ },
35
+
36
+ handler: async (argv) => {
37
+ const action = argv.action;
38
+ const name = argv.name;
39
+
40
+ try {
41
+ switch (action) {
42
+ case 'list':
43
+ listEpics();
44
+ break;
45
+
46
+ case 'status':
47
+ if (!name) {
48
+ console.error('Error: Epic name required for status action');
49
+ console.log('Usage: autopm epic status <epic-name>');
50
+ process.exit(1);
51
+ }
52
+ showEpicStatus(name);
53
+ break;
54
+
55
+ case 'breakdown':
56
+ if (!name) {
57
+ console.error('Error: Epic name required for breakdown action');
58
+ console.log('Usage: autopm epic breakdown <epic-name>');
59
+ process.exit(1);
60
+ }
61
+ showEpicBreakdown(name);
62
+ break;
63
+
64
+ default:
65
+ console.error(`Unknown action: ${action}`);
66
+ process.exit(1);
67
+ }
68
+ } catch (error) {
69
+ console.error('Error:', error.message);
70
+ process.exit(1);
71
+ }
72
+ }
73
+ };
74
+
75
+ function listEpics() {
76
+ const epicsDir = path.join(process.cwd(), '.claude', 'epics');
77
+
78
+ if (!fs.existsSync(epicsDir)) {
79
+ console.log('No epics found. Create epics with /pm:epic-split or /pm:epic-decompose');
80
+ return;
81
+ }
82
+
83
+ const epics = fs.readdirSync(epicsDir).filter(f => {
84
+ return fs.statSync(path.join(epicsDir, f)).isDirectory();
85
+ });
86
+
87
+ if (epics.length === 0) {
88
+ console.log('No epics found. Create epics with /pm:epic-split or /pm:epic-decompose');
89
+ return;
90
+ }
91
+
92
+ console.log('Available Epics:');
93
+ console.log('================\n');
94
+
95
+ epics.forEach(epic => {
96
+ console.log(` • ${epic}`);
97
+ });
98
+
99
+ console.log('');
100
+ console.log('Use: autopm epic status <epic-name> to see details');
101
+ }
102
+
103
+ function showEpicStatus(epicName) {
104
+ const scriptPath = path.join(process.cwd(), 'scripts', 'epic-status.sh');
105
+
106
+ if (!fs.existsSync(scriptPath)) {
107
+ console.error('Error: epic-status.sh script not found');
108
+ console.error('Run: autopm install to get the latest scripts');
109
+ process.exit(1);
110
+ }
111
+
112
+ try {
113
+ execSync(`bash "${scriptPath}" "${epicName}"`, {
114
+ stdio: 'inherit',
115
+ cwd: process.cwd()
116
+ });
117
+ } catch (error) {
118
+ process.exit(error.status || 1);
119
+ }
120
+ }
121
+
122
+ function showEpicBreakdown(epicName) {
123
+ const epicDir = path.join(process.cwd(), '.claude', 'epics', epicName);
124
+
125
+ if (!fs.existsSync(epicDir)) {
126
+ console.error(`Error: Epic '${epicName}' not found`);
127
+ process.exit(1);
128
+ }
129
+
130
+ console.log(`Epic Breakdown: ${epicName}`);
131
+ console.log('='.repeat(50));
132
+ console.log('');
133
+
134
+ // Find all task files
135
+ const findTasks = (dir, prefix = '') => {
136
+ const items = fs.readdirSync(dir);
137
+
138
+ items.forEach(item => {
139
+ const itemPath = path.join(dir, item);
140
+ const stat = fs.statSync(itemPath);
141
+
142
+ if (stat.isDirectory()) {
143
+ console.log(`\n${prefix}📁 ${item}`);
144
+ findTasks(itemPath, prefix + ' ');
145
+ } else if (item.match(/^\d{3}\.md$/)) {
146
+ const content = fs.readFileSync(itemPath, 'utf-8');
147
+ const titleMatch = content.match(/^#\s+(.+)$/m);
148
+ const statusMatch = content.match(/^status:\s+(.+)$/m);
149
+
150
+ const title = titleMatch ? titleMatch[1] : item;
151
+ const status = statusMatch ? statusMatch[1] : 'pending';
152
+
153
+ const icon = status === 'completed' ? '✅' : status === 'in-progress' ? '🔄' : '⚪';
154
+
155
+ console.log(`${prefix} ${icon} ${item}: ${title}`);
156
+ }
157
+ });
158
+ };
159
+
160
+ findTasks(epicDir);
161
+ }
@@ -323,7 +323,8 @@ ${this.colors.BOLD}Examples:${this.colors.NC}
323
323
  'safe-commit.sh',
324
324
  'safe-commit.js',
325
325
  'setup-hooks.sh',
326
- 'setup-hooks.js'
326
+ 'setup-hooks.js',
327
+ 'epic-status.sh'
327
328
  ];
328
329
 
329
330
  for (const script of scripts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-autopm",
3
- "version": "1.15.5",
3
+ "version": "1.16.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": {