claude-autopm 1.24.0 → 1.24.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.
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Epic Sync Tasks - Create GitHub issues for all tasks in an epic
4
+ *
5
+ * Modern Node.js replacement for bash scripts that had parsing issues.
6
+ * Uses simple, testable code instead of complex shell heredocs.
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const { execSync } = require('child_process');
12
+
13
+ /**
14
+ * Parse task file frontmatter and content
15
+ */
16
+ function parseTaskFile(filePath) {
17
+ const content = fs.readFileSync(filePath, 'utf8');
18
+ const lines = content.split('\n');
19
+
20
+ let inFrontmatter = false;
21
+ let frontmatterLines = [];
22
+ let bodyLines = [];
23
+ let frontmatterCount = 0;
24
+
25
+ for (const line of lines) {
26
+ if (line === '---') {
27
+ frontmatterCount++;
28
+ if (frontmatterCount === 1) {
29
+ inFrontmatter = true;
30
+ continue;
31
+ } else if (frontmatterCount === 2) {
32
+ inFrontmatter = false;
33
+ continue;
34
+ }
35
+ }
36
+
37
+ if (inFrontmatter) {
38
+ frontmatterLines.push(line);
39
+ } else if (frontmatterCount === 2) {
40
+ bodyLines.push(line);
41
+ }
42
+ }
43
+
44
+ // Parse frontmatter
45
+ const frontmatter = {};
46
+ for (const line of frontmatterLines) {
47
+ const match = line.match(/^(\w+):\s*(.+)$/);
48
+ if (match) {
49
+ const [, key, value] = match;
50
+ frontmatter[key] = value;
51
+ }
52
+ }
53
+
54
+ return {
55
+ frontmatter,
56
+ body: bodyLines.join('\n').trim(),
57
+ title: frontmatter.name || 'Untitled Task'
58
+ };
59
+ }
60
+
61
+ /**
62
+ * Create GitHub issue for a task
63
+ */
64
+ function createTaskIssue(taskData, epicIssueNumber, epicPath, taskNumber) {
65
+ const { title, body } = taskData;
66
+
67
+ // Create issue body with epic reference
68
+ const issueBody = `
69
+ Part of Epic #${epicIssueNumber}
70
+
71
+ ---
72
+
73
+ ${body}
74
+
75
+ ---
76
+
77
+ **Epic Path:** \`${epicPath}\`
78
+ **Task Number:** ${taskNumber}
79
+ `.trim();
80
+
81
+ // Escape quotes for shell
82
+ const escapedTitle = title.replace(/"/g, '\\"');
83
+ const escapedBody = issueBody.replace(/"/g, '\\"').replace(/`/g, '\\`');
84
+
85
+ // Create GitHub issue
86
+ try {
87
+ const result = execSync(
88
+ `gh issue create --title "${escapedTitle}" --body "${escapedBody}" --label "task"`,
89
+ { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
90
+ );
91
+
92
+ const issueMatch = result.match(/https:\/\/github\.com\/[^\/]+\/[^\/]+\/issues\/(\d+)/);
93
+ if (issueMatch) {
94
+ return parseInt(issueMatch[1]);
95
+ }
96
+
97
+ return null;
98
+ } catch (error) {
99
+ console.error(`❌ Failed to create issue for task ${taskNumber}:`, error.message);
100
+ return null;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Update task file with GitHub issue number
106
+ */
107
+ function updateTaskFrontmatter(filePath, issueNumber) {
108
+ const content = fs.readFileSync(filePath, 'utf8');
109
+ const updatedContent = content.replace(
110
+ /^github:.*$/m,
111
+ `github: "#${issueNumber}"`
112
+ );
113
+ fs.writeFileSync(filePath, updatedContent, 'utf8');
114
+ }
115
+
116
+ /**
117
+ * Main function
118
+ */
119
+ function main() {
120
+ const args = process.argv.slice(2);
121
+
122
+ if (args.length < 2) {
123
+ console.error('Usage: epicSyncTasks.js <epic-path> <epic-issue-number>');
124
+ console.error('Example: epicSyncTasks.js fullstack/01-infrastructure 2');
125
+ process.exit(1);
126
+ }
127
+
128
+ const [epicPath, epicIssueNumber] = args;
129
+ const epicDir = path.join(process.cwd(), '.claude/epics', epicPath);
130
+
131
+ if (!fs.existsSync(epicDir)) {
132
+ console.error(`❌ Epic directory not found: ${epicDir}`);
133
+ process.exit(1);
134
+ }
135
+
136
+ // Find all task files (numbered .md files)
137
+ const taskFiles = fs.readdirSync(epicDir)
138
+ .filter(f => /^\d+\.md$/.test(f))
139
+ .sort();
140
+
141
+ if (taskFiles.length === 0) {
142
+ console.error(`❌ No task files found in ${epicDir}`);
143
+ process.exit(1);
144
+ }
145
+
146
+ console.log(`📋 Creating ${taskFiles.length} task issues for epic #${epicIssueNumber}`);
147
+ console.log(`📂 Epic path: ${epicPath}\n`);
148
+
149
+ let successCount = 0;
150
+ let failCount = 0;
151
+
152
+ for (const taskFile of taskFiles) {
153
+ const taskNumber = taskFile.replace('.md', '');
154
+ const taskPath = path.join(epicDir, taskFile);
155
+
156
+ console.log(`[${successCount + failCount + 1}/${taskFiles.length}] Creating issue for task ${taskNumber}...`);
157
+
158
+ try {
159
+ const taskData = parseTaskFile(taskPath);
160
+ const issueNumber = createTaskIssue(taskData, epicIssueNumber, epicPath, taskNumber);
161
+
162
+ if (issueNumber) {
163
+ updateTaskFrontmatter(taskPath, issueNumber);
164
+ console.log(` ✅ Created issue #${issueNumber}: ${taskData.title}`);
165
+ successCount++;
166
+ } else {
167
+ console.log(` ⚠️ Issue created but number not found`);
168
+ failCount++;
169
+ }
170
+ } catch (error) {
171
+ console.error(` ❌ Error: ${error.message}`);
172
+ failCount++;
173
+ }
174
+ }
175
+
176
+ console.log(`\n📊 Summary:`);
177
+ console.log(` ✅ Success: ${successCount}`);
178
+ console.log(` ❌ Failed: ${failCount}`);
179
+ console.log(` 📝 Total: ${taskFiles.length}`);
180
+
181
+ if (failCount > 0) {
182
+ process.exit(1);
183
+ }
184
+ }
185
+
186
+ if (require.main === module) {
187
+ main();
188
+ }
189
+
190
+ module.exports = { parseTaskFile, createTaskIssue, updateTaskFrontmatter };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-autopm",
3
- "version": "1.24.0",
3
+ "version": "1.24.2",
4
4
  "description": "Autonomous Project Management Framework for Claude Code - Advanced AI-powered development automation",
5
5
  "main": "bin/autopm.js",
6
6
  "bin": {