claude-autopm 1.27.0 ā 1.29.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.
- package/README.md +72 -0
- package/autopm/.claude/scripts/pm/analytics.js +425 -0
- package/autopm/.claude/scripts/pm/prd-new.js +292 -2
- package/autopm/.claude/scripts/pm/sync-batch.js +337 -0
- package/autopm/.claude/scripts/pm/template-list.js +119 -0
- package/autopm/.claude/scripts/pm/template-new.js +344 -0
- package/autopm/.claude/templates/prds/README.md +334 -0
- package/autopm/.claude/templates/prds/api-feature.md +306 -0
- package/autopm/.claude/templates/prds/bug-fix.md +413 -0
- package/autopm/.claude/templates/prds/data-migration.md +483 -0
- package/autopm/.claude/templates/prds/documentation.md +439 -0
- package/autopm/.claude/templates/prds/ui-feature.md +365 -0
- package/lib/README-FILTER-SEARCH.md +285 -0
- package/lib/analytics-engine.js +689 -0
- package/lib/batch-processor-integration.js +366 -0
- package/lib/batch-processor.js +278 -0
- package/lib/burndown-chart.js +415 -0
- package/lib/dependency-analyzer.js +466 -0
- package/lib/filter-engine.js +414 -0
- package/lib/query-parser.js +322 -0
- package/lib/template-engine.js +347 -0
- package/package.json +5 -4
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Template List - Show available templates
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* autopm template:list
|
|
7
|
+
* autopm template:list prd
|
|
8
|
+
* autopm template:list epic
|
|
9
|
+
* autopm template:list task
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
// Dynamically resolve template engine path
|
|
15
|
+
let TemplateEngine;
|
|
16
|
+
try {
|
|
17
|
+
TemplateEngine = require(path.join(__dirname, '..', '..', '..', '..', 'lib', 'template-engine'));
|
|
18
|
+
} catch (err) {
|
|
19
|
+
try {
|
|
20
|
+
TemplateEngine = require(path.join(process.cwd(), 'lib', 'template-engine'));
|
|
21
|
+
} catch (err2) {
|
|
22
|
+
TemplateEngine = require('../../../lib/template-engine');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class TemplateLister {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.templateEngine = new TemplateEngine();
|
|
29
|
+
this.descriptions = {
|
|
30
|
+
// PRD templates
|
|
31
|
+
'api-feature': 'REST/GraphQL API development',
|
|
32
|
+
'ui-feature': 'Frontend component/page',
|
|
33
|
+
'bug-fix': 'Bug resolution workflow',
|
|
34
|
+
'data-migration': 'Database schema changes',
|
|
35
|
+
'documentation': 'Documentation updates',
|
|
36
|
+
|
|
37
|
+
// Epic templates (future)
|
|
38
|
+
'sprint': 'Sprint planning',
|
|
39
|
+
'release': 'Release epic',
|
|
40
|
+
|
|
41
|
+
// Task templates (future)
|
|
42
|
+
'development': 'Development task',
|
|
43
|
+
'testing': 'Testing task'
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
list(type = null) {
|
|
48
|
+
const types = type ? [type] : ['prds', 'epics', 'tasks'];
|
|
49
|
+
|
|
50
|
+
console.log('\nš Available Templates\n');
|
|
51
|
+
console.log('ā'.repeat(60));
|
|
52
|
+
|
|
53
|
+
for (const templateType of types) {
|
|
54
|
+
const templates = this.templateEngine.listTemplates(templateType);
|
|
55
|
+
|
|
56
|
+
if (templates.length === 0) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const typeName = templateType.charAt(0).toUpperCase() + templateType.slice(1);
|
|
61
|
+
console.log(`\n${typeName} Templates:`);
|
|
62
|
+
|
|
63
|
+
const builtIn = templates.filter(t => !t.custom);
|
|
64
|
+
const custom = templates.filter(t => t.custom);
|
|
65
|
+
|
|
66
|
+
if (builtIn.length > 0) {
|
|
67
|
+
console.log('\nBuilt-in:');
|
|
68
|
+
builtIn.forEach(t => {
|
|
69
|
+
const desc = this.descriptions[t.name] || 'Template';
|
|
70
|
+
console.log(` ⢠${t.name.padEnd(20)} - ${desc}`);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (custom.length > 0) {
|
|
75
|
+
console.log('\nCustom:');
|
|
76
|
+
custom.forEach(t => {
|
|
77
|
+
console.log(` ⢠${t.name.padEnd(20)} - [Custom Template]`);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log('\n' + 'ā'.repeat(60));
|
|
83
|
+
console.log('\nUsage:');
|
|
84
|
+
console.log(' autopm prd:new --template <name> "<title>"');
|
|
85
|
+
console.log(' autopm prd:new -t api-feature "User Authentication API"');
|
|
86
|
+
console.log('\nCreate custom template:');
|
|
87
|
+
console.log(' autopm template:new prd my-custom-template\n');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
run(args) {
|
|
91
|
+
const type = args[0]; // Optional: 'prd', 'epic', 'task'
|
|
92
|
+
const validTypes = ['prd', 'prds', 'epic', 'epics', 'task', 'tasks'];
|
|
93
|
+
|
|
94
|
+
if (type && !validTypes.includes(type)) {
|
|
95
|
+
console.error(`ā Invalid type: ${type}`);
|
|
96
|
+
console.log('Valid types: prd, epic, task');
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Normalize type
|
|
101
|
+
let normalizedType = null;
|
|
102
|
+
if (type) {
|
|
103
|
+
if (type === 'prd') normalizedType = 'prds';
|
|
104
|
+
else if (type === 'epic') normalizedType = 'epics';
|
|
105
|
+
else if (type === 'task') normalizedType = 'tasks';
|
|
106
|
+
else normalizedType = type;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this.list(normalizedType);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Main execution
|
|
114
|
+
if (require.main === module) {
|
|
115
|
+
const lister = new TemplateLister();
|
|
116
|
+
lister.run(process.argv.slice(2));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = TemplateLister;
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Template New - Create custom template
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* autopm template:new prd my-custom-template
|
|
7
|
+
* autopm template:new epic my-sprint-template
|
|
8
|
+
* autopm template:new task my-task-template
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const { execSync } = require('child_process');
|
|
14
|
+
|
|
15
|
+
// Dynamically resolve template engine path
|
|
16
|
+
let TemplateEngine;
|
|
17
|
+
try {
|
|
18
|
+
TemplateEngine = require(path.join(__dirname, '..', '..', '..', '..', 'lib', 'template-engine'));
|
|
19
|
+
} catch (err) {
|
|
20
|
+
try {
|
|
21
|
+
TemplateEngine = require(path.join(process.cwd(), 'lib', 'template-engine'));
|
|
22
|
+
} catch (err2) {
|
|
23
|
+
TemplateEngine = require('../../../lib/template-engine');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class TemplateCreator {
|
|
28
|
+
constructor() {
|
|
29
|
+
this.templateEngine = new TemplateEngine();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get base template for type
|
|
34
|
+
*/
|
|
35
|
+
getBaseTemplate(type) {
|
|
36
|
+
const templates = {
|
|
37
|
+
prd: `---
|
|
38
|
+
id: {{id}}
|
|
39
|
+
title: {{title}}
|
|
40
|
+
type: prd
|
|
41
|
+
status: draft
|
|
42
|
+
priority: {{priority}}
|
|
43
|
+
created: {{timestamp}}
|
|
44
|
+
author: {{author}}
|
|
45
|
+
timeline: {{timeline}}
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
# PRD: {{title}}
|
|
49
|
+
|
|
50
|
+
## Executive Summary
|
|
51
|
+
|
|
52
|
+
{{executive_summary}}
|
|
53
|
+
|
|
54
|
+
## Problem Statement
|
|
55
|
+
|
|
56
|
+
### Background
|
|
57
|
+
{{problem_background}}
|
|
58
|
+
|
|
59
|
+
### Current State
|
|
60
|
+
{{current_state}}
|
|
61
|
+
|
|
62
|
+
### Desired State
|
|
63
|
+
{{desired_state}}
|
|
64
|
+
|
|
65
|
+
## Target Users
|
|
66
|
+
|
|
67
|
+
{{target_users}}
|
|
68
|
+
|
|
69
|
+
## Key Features
|
|
70
|
+
|
|
71
|
+
### Must Have (P0)
|
|
72
|
+
{{#if must_have_features}}
|
|
73
|
+
{{#each must_have_features}}
|
|
74
|
+
- [ ] {{this}}
|
|
75
|
+
{{/each}}
|
|
76
|
+
{{/if}}
|
|
77
|
+
|
|
78
|
+
### Should Have (P1)
|
|
79
|
+
{{#if should_have_features}}
|
|
80
|
+
{{#each should_have_features}}
|
|
81
|
+
- [ ] {{this}}
|
|
82
|
+
{{/each}}
|
|
83
|
+
{{/if}}
|
|
84
|
+
|
|
85
|
+
## Success Metrics
|
|
86
|
+
|
|
87
|
+
{{success_metrics}}
|
|
88
|
+
|
|
89
|
+
## Technical Requirements
|
|
90
|
+
|
|
91
|
+
{{technical_requirements}}
|
|
92
|
+
|
|
93
|
+
## Implementation Plan
|
|
94
|
+
|
|
95
|
+
### Phase 1: Design (Week 1)
|
|
96
|
+
- [ ] Requirements finalized
|
|
97
|
+
- [ ] Technical design review
|
|
98
|
+
- [ ] Development environment setup
|
|
99
|
+
|
|
100
|
+
### Phase 2: Development (Week 2-3)
|
|
101
|
+
- [ ] Implement core features
|
|
102
|
+
- [ ] Write tests (TDD)
|
|
103
|
+
- [ ] Code review
|
|
104
|
+
|
|
105
|
+
### Phase 3: Testing (Week 4)
|
|
106
|
+
- [ ] Integration testing
|
|
107
|
+
- [ ] User acceptance testing
|
|
108
|
+
- [ ] Performance testing
|
|
109
|
+
|
|
110
|
+
### Phase 4: Release (Week 5)
|
|
111
|
+
- [ ] Documentation
|
|
112
|
+
- [ ] Deployment
|
|
113
|
+
- [ ] Monitoring setup
|
|
114
|
+
|
|
115
|
+
## Risks and Mitigation
|
|
116
|
+
|
|
117
|
+
{{risks_and_mitigation}}
|
|
118
|
+
|
|
119
|
+
## Open Questions
|
|
120
|
+
|
|
121
|
+
- [ ] {{open_question_1}}
|
|
122
|
+
- [ ] {{open_question_2}}
|
|
123
|
+
|
|
124
|
+
## Appendix
|
|
125
|
+
|
|
126
|
+
### Changelog
|
|
127
|
+
- {{timestamp}}: Initial PRD created by {{author}}
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
*Custom PRD Template*
|
|
132
|
+
`,
|
|
133
|
+
epic: `---
|
|
134
|
+
id: {{id}}
|
|
135
|
+
title: {{title}}
|
|
136
|
+
type: epic
|
|
137
|
+
status: planning
|
|
138
|
+
priority: {{priority}}
|
|
139
|
+
created: {{timestamp}}
|
|
140
|
+
author: {{author}}
|
|
141
|
+
start_date: {{start_date}}
|
|
142
|
+
end_date: {{end_date}}
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
# Epic: {{title}}
|
|
146
|
+
|
|
147
|
+
## Overview
|
|
148
|
+
|
|
149
|
+
{{overview}}
|
|
150
|
+
|
|
151
|
+
## Goals
|
|
152
|
+
|
|
153
|
+
{{#each goals}}
|
|
154
|
+
- {{this}}
|
|
155
|
+
{{/each}}
|
|
156
|
+
|
|
157
|
+
## User Stories
|
|
158
|
+
|
|
159
|
+
{{#each user_stories}}
|
|
160
|
+
- As a {{role}}, I want to {{action}}, so that {{benefit}}
|
|
161
|
+
{{/each}}
|
|
162
|
+
|
|
163
|
+
## Tasks
|
|
164
|
+
|
|
165
|
+
{{#each tasks}}
|
|
166
|
+
- [ ] {{this}}
|
|
167
|
+
{{/each}}
|
|
168
|
+
|
|
169
|
+
## Success Criteria
|
|
170
|
+
|
|
171
|
+
{{success_criteria}}
|
|
172
|
+
|
|
173
|
+
## Dependencies
|
|
174
|
+
|
|
175
|
+
{{dependencies}}
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
*Custom Epic Template*
|
|
180
|
+
`,
|
|
181
|
+
task: `---
|
|
182
|
+
id: {{id}}
|
|
183
|
+
title: {{title}}
|
|
184
|
+
type: task
|
|
185
|
+
status: todo
|
|
186
|
+
priority: {{priority}}
|
|
187
|
+
created: {{timestamp}}
|
|
188
|
+
author: {{author}}
|
|
189
|
+
assigned_to: {{assigned_to}}
|
|
190
|
+
estimated_hours: {{estimated_hours}}
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
# Task: {{title}}
|
|
194
|
+
|
|
195
|
+
## Description
|
|
196
|
+
|
|
197
|
+
{{description}}
|
|
198
|
+
|
|
199
|
+
## Acceptance Criteria
|
|
200
|
+
|
|
201
|
+
{{#each acceptance_criteria}}
|
|
202
|
+
- [ ] {{this}}
|
|
203
|
+
{{/each}}
|
|
204
|
+
|
|
205
|
+
## Technical Details
|
|
206
|
+
|
|
207
|
+
{{technical_details}}
|
|
208
|
+
|
|
209
|
+
## Testing
|
|
210
|
+
|
|
211
|
+
{{testing_notes}}
|
|
212
|
+
|
|
213
|
+
## Notes
|
|
214
|
+
|
|
215
|
+
{{notes}}
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
*Custom Task Template*
|
|
220
|
+
`
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
return templates[type] || templates.prd;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Create new template
|
|
228
|
+
*/
|
|
229
|
+
create(type, name) {
|
|
230
|
+
console.log(`\nš Creating Custom Template`);
|
|
231
|
+
console.log(`${'ā'.repeat(50)}\n`);
|
|
232
|
+
|
|
233
|
+
// Validate type
|
|
234
|
+
const validTypes = ['prd', 'epic', 'task'];
|
|
235
|
+
if (!validTypes.includes(type)) {
|
|
236
|
+
console.error(`ā Invalid type: ${type}`);
|
|
237
|
+
console.log(`Valid types: ${validTypes.join(', ')}`);
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Ensure template directory exists
|
|
242
|
+
const typeDir = type === 'prd' ? 'prds' : type === 'epic' ? 'epics' : 'tasks';
|
|
243
|
+
this.templateEngine.ensureTemplateDir(typeDir);
|
|
244
|
+
|
|
245
|
+
const templatePath = path.join('.claude', 'templates', typeDir, `${name}.md`);
|
|
246
|
+
|
|
247
|
+
// Check if template already exists
|
|
248
|
+
if (fs.existsSync(templatePath)) {
|
|
249
|
+
console.error(`ā Template already exists: ${templatePath}`);
|
|
250
|
+
console.log(`š” Edit file directly or choose a different name`);
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Get base template
|
|
255
|
+
const baseTemplate = this.getBaseTemplate(type);
|
|
256
|
+
|
|
257
|
+
// Write template file
|
|
258
|
+
fs.writeFileSync(templatePath, baseTemplate);
|
|
259
|
+
|
|
260
|
+
console.log(`ā
Template created: ${templatePath}`);
|
|
261
|
+
console.log(`\nš Template Structure:`);
|
|
262
|
+
console.log(` - Frontmatter: Define metadata variables`);
|
|
263
|
+
console.log(` - Variables: Use {{variable_name}} for substitution`);
|
|
264
|
+
console.log(` - Conditionals: {{#if var}}...{{/if}}`);
|
|
265
|
+
console.log(` - Loops: {{#each items}}...{{/each}}`);
|
|
266
|
+
|
|
267
|
+
console.log(`\nš ļø Next Steps:`);
|
|
268
|
+
console.log(` 1. Edit template: nano ${templatePath}`);
|
|
269
|
+
console.log(` 2. Add custom variables and sections`);
|
|
270
|
+
console.log(` 3. Test template: autopm ${type}:new --template ${name} "Test"`);
|
|
271
|
+
|
|
272
|
+
// Try to open in editor
|
|
273
|
+
this.openInEditor(templatePath);
|
|
274
|
+
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Open template in editor
|
|
280
|
+
*/
|
|
281
|
+
openInEditor(templatePath) {
|
|
282
|
+
const editors = ['code', 'nano', 'vim', 'vi'];
|
|
283
|
+
|
|
284
|
+
for (const editor of editors) {
|
|
285
|
+
try {
|
|
286
|
+
// Check if editor exists
|
|
287
|
+
execSync(`which ${editor}`, { stdio: 'ignore' });
|
|
288
|
+
|
|
289
|
+
console.log(`\nš Opening in ${editor}...`);
|
|
290
|
+
console.log(` Edit the template, save, and exit`);
|
|
291
|
+
|
|
292
|
+
// Open editor (blocking)
|
|
293
|
+
execSync(`${editor} ${templatePath}`, { stdio: 'inherit' });
|
|
294
|
+
|
|
295
|
+
// Validate template after editing
|
|
296
|
+
const content = fs.readFileSync(templatePath, 'utf8');
|
|
297
|
+
const validation = this.templateEngine.validate(content);
|
|
298
|
+
|
|
299
|
+
if (!validation.valid) {
|
|
300
|
+
console.log(`\nā ļø Template validation warnings:`);
|
|
301
|
+
validation.errors.forEach(err => console.log(` - ${err}`));
|
|
302
|
+
console.log(`\nš” These are suggestions. Template will still work.`);
|
|
303
|
+
} else {
|
|
304
|
+
console.log(`\nā
Template is valid!`);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return true;
|
|
308
|
+
} catch (err) {
|
|
309
|
+
// Editor not found, try next
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// No editor found
|
|
315
|
+
console.log(`\nš” Edit manually: ${templatePath}`);
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
run(args) {
|
|
320
|
+
if (args.length < 2) {
|
|
321
|
+
console.error('ā Usage: autopm template:new <type> <name>');
|
|
322
|
+
console.log('\nExamples:');
|
|
323
|
+
console.log(' autopm template:new prd my-custom-prd');
|
|
324
|
+
console.log(' autopm template:new epic my-sprint');
|
|
325
|
+
console.log(' autopm template:new task my-development-task');
|
|
326
|
+
console.log('\nTypes: prd, epic, task');
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const type = args[0];
|
|
331
|
+
const name = args[1];
|
|
332
|
+
|
|
333
|
+
const success = this.create(type, name);
|
|
334
|
+
process.exit(success ? 0 : 1);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Main execution
|
|
339
|
+
if (require.main === module) {
|
|
340
|
+
const creator = new TemplateCreator();
|
|
341
|
+
creator.run(process.argv.slice(2));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
module.exports = TemplateCreator;
|