claude-autopm 2.12.0 → 2.12.1
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/package.json +1 -1
- package/packages/plugin-pm/commands/pm:blocked.md +4 -0
- package/packages/plugin-pm/commands/pm:context.md +4 -0
- package/packages/plugin-pm/commands/pm:epic-list.md +4 -0
- package/packages/plugin-pm/commands/pm:epic-show.md +4 -0
- package/packages/plugin-pm/commands/pm:epic-split.md +12 -1
- package/packages/plugin-pm/commands/pm:epic-status.md +4 -0
- package/packages/plugin-pm/commands/pm:help.md +4 -0
- package/packages/plugin-pm/commands/pm:in-progress.md +4 -0
- package/packages/plugin-pm/commands/pm:init.md +4 -0
- package/packages/plugin-pm/commands/pm:next.md +4 -0
- package/packages/plugin-pm/commands/pm:prd-list.md +4 -0
- package/packages/plugin-pm/commands/pm:prd-status.md +4 -0
- package/packages/plugin-pm/commands/pm:search.md +4 -0
- package/packages/plugin-pm/commands/pm:standup.md +4 -0
- package/packages/plugin-pm/commands/pm:status.md +4 -0
- package/packages/plugin-pm/commands/pm:validate.md +4 -0
- package/packages/plugin-pm/commands/pm:what-next.md +4 -0
- package/packages/plugin-pm/package.json +1 -1
- package/scripts/fix-command-instructions.js +221 -0
package/package.json
CHANGED
|
@@ -117,4 +117,15 @@ If the automatic split isn't perfect, you can:
|
|
|
117
117
|
1. Edit the generated epic files
|
|
118
118
|
2. Adjust dependencies in meta.yaml
|
|
119
119
|
3. Merge or split epics further
|
|
120
|
-
4. Update time estimates
|
|
120
|
+
4. Update time estimates
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Instructions
|
|
125
|
+
|
|
126
|
+
Run `node .claude/scripts/pm/epic-split.js $ARGUMENTS` using the Bash tool and show me the complete output.
|
|
127
|
+
|
|
128
|
+
- You MUST display the complete output.
|
|
129
|
+
- DO NOT truncate.
|
|
130
|
+
- DO NOT collapse.
|
|
131
|
+
- DO NOT abbreviate.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudeautopm/plugin-pm",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Complete project management plugin with PM workflows, epic management, issue tracking, and release automation for ClaudeAutoPM",
|
|
5
5
|
"main": "plugin.json",
|
|
6
6
|
"type": "module",
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs').promises;
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Fix PM commands missing proper ## Instructions sections
|
|
8
|
+
*
|
|
9
|
+
* This script:
|
|
10
|
+
* 1. Scans all PM commands
|
|
11
|
+
* 2. Identifies commands with corresponding .js scripts
|
|
12
|
+
* 3. Adds proper ## Instructions sections where missing
|
|
13
|
+
* 4. Fixes malformed instruction sections
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const colors = {
|
|
17
|
+
reset: '\x1b[0m',
|
|
18
|
+
green: '\x1b[32m',
|
|
19
|
+
yellow: '\x1b[33m',
|
|
20
|
+
red: '\x1b[31m',
|
|
21
|
+
cyan: '\x1b[36m',
|
|
22
|
+
gray: '\x1b[90m'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Template for Instructions section
|
|
26
|
+
function generateInstructionsSection(scriptName, commandName) {
|
|
27
|
+
return `
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Instructions
|
|
32
|
+
|
|
33
|
+
Run \`node .claude/scripts/pm/${scriptName}.js $ARGUMENTS\` using the Bash tool and show me the complete output.
|
|
34
|
+
|
|
35
|
+
- You MUST display the complete output.
|
|
36
|
+
- DO NOT truncate.
|
|
37
|
+
- DO NOT collapse.
|
|
38
|
+
- DO NOT abbreviate.`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Check if file has proper ## Instructions section
|
|
42
|
+
async function hasProperInstructions(filePath) {
|
|
43
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
44
|
+
|
|
45
|
+
// Check for ## Instructions header
|
|
46
|
+
const hasHeader = /^## Instructions$/m.test(content);
|
|
47
|
+
|
|
48
|
+
// Check for node .claude/scripts/pm/ call
|
|
49
|
+
const hasNodeCall = /node \.claude\/scripts\/pm\//.test(content);
|
|
50
|
+
|
|
51
|
+
return { hasHeader, hasNodeCall, content };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Fix command file by adding Instructions section
|
|
55
|
+
async function fixCommandFile(commandPath, scriptName, dryRun = false) {
|
|
56
|
+
const { hasHeader, hasNodeCall, content } = await hasProperInstructions(commandPath);
|
|
57
|
+
|
|
58
|
+
if (hasHeader && hasNodeCall) {
|
|
59
|
+
return { status: 'ok', message: 'Already has proper Instructions section' };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let newContent = content;
|
|
63
|
+
|
|
64
|
+
if (!hasHeader && !hasNodeCall) {
|
|
65
|
+
// No instructions at all - add at the end
|
|
66
|
+
const commandName = path.basename(commandPath, '.md').replace('pm:', '');
|
|
67
|
+
const instructions = generateInstructionsSection(scriptName, commandName);
|
|
68
|
+
newContent = content.trimEnd() + instructions + '\n';
|
|
69
|
+
|
|
70
|
+
if (!dryRun) {
|
|
71
|
+
await fs.writeFile(commandPath, newContent);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { status: 'added', message: 'Added missing Instructions section' };
|
|
75
|
+
} else if (hasNodeCall && !hasHeader) {
|
|
76
|
+
// Has instructions but no proper header - fix structure
|
|
77
|
+
// Find where the node call is and add header before it
|
|
78
|
+
const nodeCallMatch = content.match(/(Run `node \.claude\/scripts\/pm\/.*?`)/);
|
|
79
|
+
if (nodeCallMatch) {
|
|
80
|
+
const nodeCallLine = nodeCallMatch[0];
|
|
81
|
+
newContent = content.replace(
|
|
82
|
+
nodeCallLine,
|
|
83
|
+
`---\n\n## Instructions\n\n${nodeCallLine}`
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if (!dryRun) {
|
|
87
|
+
await fs.writeFile(commandPath, newContent);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { status: 'fixed', message: 'Added missing ## Instructions header' };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return { status: 'skip', message: 'No action needed' };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function main() {
|
|
98
|
+
const dryRun = process.argv.includes('--dry-run');
|
|
99
|
+
const targetDir = process.argv.find(arg => !arg.startsWith('--') && arg !== process.argv[0] && arg !== process.argv[1]);
|
|
100
|
+
|
|
101
|
+
console.log(`${colors.cyan}🔧 Fixing PM Command Instructions Sections${colors.reset}`);
|
|
102
|
+
console.log(`Mode: ${dryRun ? colors.yellow + 'DRY RUN' : colors.green + 'LIVE'}${colors.reset}\n`);
|
|
103
|
+
|
|
104
|
+
// Determine project root
|
|
105
|
+
let projectRoot;
|
|
106
|
+
if (targetDir) {
|
|
107
|
+
projectRoot = path.resolve(targetDir);
|
|
108
|
+
} else {
|
|
109
|
+
// Try to auto-detect: check if we're in AUTOPM dev project or installed project
|
|
110
|
+
const cwd = process.cwd();
|
|
111
|
+
if (await fs.access(path.join(cwd, 'autopm', '.claude')).then(() => true).catch(() => false)) {
|
|
112
|
+
projectRoot = cwd; // AUTOPM dev project
|
|
113
|
+
} else {
|
|
114
|
+
projectRoot = cwd; // Installed project (commands are in .claude/)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Detect project structure
|
|
119
|
+
let commandsDir, scriptsDir;
|
|
120
|
+
|
|
121
|
+
// Try plugin structure first (packages/plugin-pm/)
|
|
122
|
+
if (await fs.access(path.join(projectRoot, 'commands')).then(() => true).catch(() => false)) {
|
|
123
|
+
commandsDir = path.join(projectRoot, 'commands');
|
|
124
|
+
scriptsDir = path.join(projectRoot, 'scripts', 'pm');
|
|
125
|
+
}
|
|
126
|
+
// Try dev project (autopm/.claude/)
|
|
127
|
+
else if (await fs.access(path.join(projectRoot, 'autopm', '.claude', 'commands')).then(() => true).catch(() => false)) {
|
|
128
|
+
commandsDir = path.join(projectRoot, 'autopm', '.claude', 'commands');
|
|
129
|
+
scriptsDir = path.join(projectRoot, 'autopm', '.claude', 'scripts', 'pm');
|
|
130
|
+
}
|
|
131
|
+
// Try installed project (.claude/)
|
|
132
|
+
else {
|
|
133
|
+
commandsDir = path.join(projectRoot, '.claude', 'commands');
|
|
134
|
+
scriptsDir = path.join(projectRoot, '.claude', 'scripts', 'pm');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
console.log(`${colors.gray}Commands dir: ${commandsDir}${colors.reset}`);
|
|
138
|
+
console.log(`${colors.gray}Scripts dir: ${scriptsDir}${colors.reset}\n`);
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
// Get all PM scripts
|
|
142
|
+
const scriptFiles = await fs.readdir(scriptsDir);
|
|
143
|
+
const scripts = scriptFiles
|
|
144
|
+
.filter(f => f.endsWith('.js'))
|
|
145
|
+
.map(f => path.basename(f, '.js'));
|
|
146
|
+
|
|
147
|
+
console.log(`${colors.gray}Found ${scripts.length} PM scripts${colors.reset}\n`);
|
|
148
|
+
|
|
149
|
+
let stats = {
|
|
150
|
+
ok: 0,
|
|
151
|
+
added: 0,
|
|
152
|
+
fixed: 0,
|
|
153
|
+
skip: 0,
|
|
154
|
+
error: 0
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// Process each script
|
|
158
|
+
for (const scriptName of scripts) {
|
|
159
|
+
const commandFile = `pm:${scriptName}.md`;
|
|
160
|
+
const commandPath = path.join(commandsDir, commandFile);
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
// Check if command file exists
|
|
164
|
+
await fs.access(commandPath);
|
|
165
|
+
|
|
166
|
+
// Fix the command file
|
|
167
|
+
const result = await fixCommandFile(commandPath, scriptName, dryRun);
|
|
168
|
+
stats[result.status]++;
|
|
169
|
+
|
|
170
|
+
const statusIcon = {
|
|
171
|
+
ok: '✅',
|
|
172
|
+
added: '➕',
|
|
173
|
+
fixed: '🔧',
|
|
174
|
+
skip: '⏭️',
|
|
175
|
+
error: '❌'
|
|
176
|
+
}[result.status];
|
|
177
|
+
|
|
178
|
+
const statusColor = {
|
|
179
|
+
ok: colors.green,
|
|
180
|
+
added: colors.cyan,
|
|
181
|
+
fixed: colors.yellow,
|
|
182
|
+
skip: colors.gray,
|
|
183
|
+
error: colors.red
|
|
184
|
+
}[result.status];
|
|
185
|
+
|
|
186
|
+
console.log(`${statusIcon} ${statusColor}${commandFile.padEnd(30)}${colors.reset} ${result.message}`);
|
|
187
|
+
|
|
188
|
+
} catch (error) {
|
|
189
|
+
if (error.code === 'ENOENT') {
|
|
190
|
+
console.log(`${colors.gray}⚠️ ${commandFile.padEnd(30)} No command file found${colors.reset}`);
|
|
191
|
+
} else {
|
|
192
|
+
stats.error++;
|
|
193
|
+
console.log(`${colors.red}❌ ${commandFile.padEnd(30)} Error: ${error.message}${colors.reset}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Summary
|
|
199
|
+
console.log(`\n${colors.cyan}═══════════════════════════════════════════════════${colors.reset}`);
|
|
200
|
+
console.log(`${colors.green}✅ OK:${colors.reset} ${stats.ok} commands already correct`);
|
|
201
|
+
console.log(`${colors.cyan}➕ Added:${colors.reset} ${stats.added} commands had Instructions section added`);
|
|
202
|
+
console.log(`${colors.yellow}🔧 Fixed:${colors.reset} ${stats.fixed} commands had header added`);
|
|
203
|
+
console.log(`${colors.gray}⏭️ Skip:${colors.reset} ${stats.skip} commands skipped`);
|
|
204
|
+
if (stats.error > 0) {
|
|
205
|
+
console.log(`${colors.red}❌ Errors:${colors.reset} ${stats.error} commands had errors`);
|
|
206
|
+
}
|
|
207
|
+
console.log(`${colors.cyan}═══════════════════════════════════════════════════${colors.reset}`);
|
|
208
|
+
|
|
209
|
+
if (dryRun) {
|
|
210
|
+
console.log(`\n${colors.yellow}This was a dry run. Run without --dry-run to apply changes.${colors.reset}`);
|
|
211
|
+
} else {
|
|
212
|
+
console.log(`\n${colors.green}✅ All fixes applied successfully!${colors.reset}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error(`${colors.red}Fatal error: ${error.message}${colors.reset}`);
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
main();
|