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.
@@ -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;