claude-autopm 1.27.0 → 1.28.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,365 @@
1
+ ---
2
+ id: {{id}}
3
+ title: {{title}}
4
+ type: prd
5
+ status: draft
6
+ priority: {{priority}}
7
+ created: {{timestamp}}
8
+ author: {{author}}
9
+ timeline: {{timeline}}
10
+ ---
11
+
12
+ # PRD: {{title}}
13
+
14
+ ## Executive Summary
15
+
16
+ Design and implement {{title}} - a {{component_type}} component for {{feature_purpose}}.
17
+
18
+ **Component Type**: {{component_type}}
19
+ **Target Platform**: {{platform}}
20
+
21
+ ## Problem Statement
22
+
23
+ ### Background
24
+ {{problem}}
25
+
26
+ ### User Need
27
+ Users need to {{user_need}} in order to {{user_goal}}.
28
+
29
+ ### Current Pain Points
30
+ {{#if pain_points}}
31
+ {{#each pain_points}}
32
+ - {{this}}
33
+ {{/each}}
34
+ {{/if}}
35
+
36
+ ## User Stories (INVEST Criteria)
37
+
38
+ Following INVEST principles (Independent, Negotiable, Valuable, Estimable, Small, Testable):
39
+
40
+ - As a **{{user_role}}**, I want to **{{user_action}}** so that **{{user_benefit}}**
41
+
42
+ {{#if additional_stories}}
43
+ {{#each additional_stories}}
44
+ - As a **{{role}}**, I want to **{{action}}** so that **{{benefit}}**
45
+ {{/each}}
46
+ {{/if}}
47
+
48
+ ## UI/UX Requirements
49
+
50
+ ### Component Specifications
51
+ - **Type**: {{component_type}} (Page/Modal/Widget/Form/Dashboard)
52
+ - **Location**: {{component_location}}
53
+ - **Interaction Pattern**: {{interaction_pattern}}
54
+ - **Responsive Breakpoints**: Mobile (320px+), Tablet (768px+), Desktop (1024px+)
55
+
56
+ ### Design Assets
57
+ - **Wireframes**: {{wireframe_link}} <!-- e.g. https://figma.com/file/xyz or /assets/wireframes/homepage.png -->
58
+ - **Mockups**: {{design_link}} <!-- e.g. https://invisionapp.com/mockup/abc or /assets/mockups/modal.jpg -->
59
+ - **Design System**: {{design_system}} <!-- e.g. https://company.com/design-system or /docs/design-system.md -->
60
+ - **Brand Guidelines**: {{brand_guidelines}} <!-- e.g. https://company.com/brand-guidelines.pdf or /assets/brand-guidelines.pdf -->
61
+
62
+ ### Accessibility (WCAG 2.1 Level AA - 2025 Compliance)
63
+
64
+ #### Perceivable
65
+ - [ ] **Text Alternatives**: All non-text content has alt text
66
+ - [ ] **Color Contrast**: Minimum 4.5:1 ratio for normal text, 3:1 for large text
67
+ - [ ] **Resize Text**: Content readable at 200% zoom
68
+ - [ ] **Images of Text**: Avoided unless essential
69
+
70
+ #### Operable
71
+ - [ ] **Keyboard Accessible**: All functionality via keyboard (no mouse required)
72
+ - [ ] **Focus Indicators**: Visible focus states (outline, highlight)
73
+ - [ ] **No Keyboard Trap**: Focus can move away from component
74
+ - [ ] **Skip Links**: Skip to main content option
75
+ - [ ] **Tab Order**: Logical navigation flow
76
+
77
+ #### Understandable
78
+ - [ ] **Clear Labels**: Form inputs have associated labels
79
+ - [ ] **Error Identification**: Errors clearly described
80
+ - [ ] **Consistent Navigation**: UI patterns consistent across app
81
+ - [ ] **Predictable**: Components behave as expected
82
+
83
+ #### Robust
84
+ - [ ] **Valid HTML**: Semantic markup, no errors
85
+ - [ ] **ARIA Labels**: Proper ARIA attributes where needed
86
+ - [ ] **Screen Reader Testing**: NVDA, JAWS, VoiceOver compatible
87
+ - [ ] **Browser Compatibility**: Chrome, Firefox, Safari, Edge
88
+
89
+ ### Responsive Design
90
+
91
+ **Mobile First Approach** (320px - 767px):
92
+ - [ ] Touch-friendly targets (min 44x44px)
93
+ - [ ] Single column layout
94
+ - [ ] Simplified navigation
95
+ - [ ] Optimized images
96
+
97
+ **Tablet** (768px - 1023px):
98
+ - [ ] Two column layout where appropriate
99
+ - [ ] Enhanced navigation
100
+ - [ ] Adaptive components
101
+
102
+ **Desktop** (1024px+):
103
+ - [ ] Multi-column layouts
104
+ - [ ] Full feature set
105
+ - [ ] Hover states
106
+ - [ ] Advanced interactions
107
+
108
+ ## Technical Requirements
109
+
110
+ ### Frontend Stack
111
+ - **Framework**: {{frontend_framework}} (React 18+/Vue 3+/Angular 17+)
112
+ - **State Management**: {{state_management}} (Redux/Zustand/Pinia/NgRx)
113
+ - **Styling**: {{styling_approach}} (CSS-in-JS/Sass/Tailwind/CSS Modules)
114
+ - **Build Tool**: {{build_tool}} (Vite/Webpack 5/Parcel)
115
+
116
+ ### Component Architecture
117
+
118
+ ```
119
+ {{component_name}}/
120
+ ├── index.jsx/tsx # Main component
121
+ ├── styles.module.css # Component styles
122
+ ├── hooks/
123
+ │ ├── useComponentState.js
124
+ │ └── useComponentEffects.js
125
+ ├── utils/
126
+ │ └── helpers.js
127
+ ├── types/
128
+ │ └── index.ts # TypeScript definitions
129
+ ├── __tests__/
130
+ │ ├── index.test.jsx
131
+ │ ├── integration.test.jsx
132
+ │ └── a11y.test.jsx # Accessibility tests
133
+ └── README.md
134
+ ```
135
+
136
+ ### API Integration
137
+ - **Endpoints**: {{api_endpoints}}
138
+ - **Loading States**:
139
+ - Skeleton loaders for content
140
+ - Spinners for actions
141
+ - Progress indicators for long operations
142
+ - **Error Handling**:
143
+ - Toast notifications
144
+ - Inline error messages
145
+ - Fallback UI components
146
+ - **Caching Strategy**: {{cache_strategy}}
147
+
148
+ ### Performance Requirements
149
+
150
+ **Core Web Vitals (2025 Standards)**:
151
+ - [ ] **LCP (Largest Contentful Paint)**: < 2.5s
152
+ - [ ] **FID (First Input Delay)**: < 100ms
153
+ - [ ] **CLS (Cumulative Layout Shift)**: < 0.1
154
+ - [ ] **INP (Interaction to Next Paint)**: < 200ms
155
+ - [ ] **TTFB (Time to First Byte)**: < 600ms
156
+
157
+ **Bundle Size**:
158
+ - [ ] Component bundle: < 50KB (gzipped)
159
+ - [ ] Total page size: < 500KB (initial load)
160
+ - [ ] Code splitting implemented
161
+ - [ ] Lazy loading for routes
162
+
163
+ **Runtime Performance**:
164
+ - [ ] 60 FPS scrolling
165
+ - [ ] Smooth animations (requestAnimationFrame)
166
+ - [ ] Debounced inputs (300ms)
167
+ - [ ] Virtualized lists (for 100+ items)
168
+
169
+ **Lighthouse Scores (Mobile)**:
170
+ - Performance: > 90
171
+ - Accessibility: 100
172
+ - Best Practices: > 95
173
+ - SEO: > 90
174
+
175
+ ## Testing Requirements (TDD Approach)
176
+
177
+ ### Unit Tests (Jest/Vitest)
178
+ - [ ] Component rendering (all states)
179
+ - [ ] User interactions (click, input, submit)
180
+ - [ ] State management (updates, side effects)
181
+ - [ ] Edge cases (empty states, errors)
182
+ - [ ] Utility functions (pure logic)
183
+ - **Coverage Target**: 100% for new code
184
+
185
+ ### Integration Tests
186
+ - [ ] API integration (success/error flows)
187
+ - [ ] Navigation flow (routing)
188
+ - [ ] Form submission (validation, submission)
189
+ - [ ] State persistence (localStorage/sessionStorage)
190
+
191
+ ### Accessibility Tests
192
+ - [ ] axe-core automated testing
193
+ - [ ] Keyboard navigation testing
194
+ - [ ] Screen reader testing (NVDA, JAWS, VoiceOver)
195
+ - [ ] Color contrast validation
196
+ - [ ] ARIA attributes validation
197
+
198
+ ### E2E Tests (Playwright/Cypress)
199
+ - [ ] User journey (complete flow)
200
+ - [ ] Cross-browser (Chrome, Firefox, Safari, Edge)
201
+ - [ ] Responsive design (mobile, tablet, desktop)
202
+ - [ ] Performance profiling
203
+ - [ ] Visual regression testing
204
+
205
+ ### Visual Testing
206
+ - [ ] Chromatic/Percy visual regression
207
+ - [ ] Storybook component documentation
208
+ - [ ] Design system adherence
209
+
210
+ ## Internationalization (i18n)
211
+
212
+ {{#if i18n_required}}
213
+ - [ ] Text externalized to language files
214
+ - [ ] RTL (Right-to-Left) support
215
+ - [ ] Date/time localization
216
+ - [ ] Number/currency formatting
217
+ - [ ] Pluralization rules
218
+ - **Languages**: {{supported_languages}}
219
+ {{/if}}
220
+
221
+ ## Success Metrics (SMART Goals)
222
+
223
+ - **Usability**: {{usability_score}}/100 SUS (System Usability Scale) score
224
+ - **Adoption**: {{adoption_target}}% user engagement within {{adoption_timeframe}}
225
+ - **Performance**: {{lighthouse_target}}/100 Lighthouse score
226
+ - **Accessibility**: 100% WCAG 2.1 AA compliance
227
+ - **Error Rate**: < {{error_rate}}%
228
+ - **User Satisfaction**: {{nps_target}} NPS score
229
+
230
+ ## User Feedback Collection
231
+
232
+ - [ ] Analytics integration (GA4/Mixpanel)
233
+ - [ ] Heatmap tracking (Hotjar/FullStory)
234
+ - [ ] User surveys (post-interaction)
235
+ - [ ] A/B testing framework
236
+ - [ ] Session replay analysis
237
+
238
+ ## Implementation Plan
239
+
240
+ ### Phase 1: Design & Setup (Week 1)
241
+ - [ ] UI/UX review and approval
242
+ - [ ] Component architecture design
243
+ - [ ] API contracts finalized
244
+ - [ ] Accessibility audit plan
245
+ - [ ] Development environment setup
246
+
247
+ ### Phase 2: Development (Week 2-3)
248
+ - [ ] Write failing tests (TDD Red)
249
+ - [ ] Implement component logic (TDD Green)
250
+ - [ ] Apply styling and responsive design
251
+ - [ ] Accessibility implementation
252
+ - [ ] Code review and refactoring
253
+
254
+ ### Phase 3: Testing (Week 4)
255
+ - [ ] Unit test completion (100% coverage)
256
+ - [ ] Integration testing
257
+ - [ ] Accessibility testing (manual + automated)
258
+ - [ ] Cross-browser testing
259
+ - [ ] Performance optimization
260
+ - [ ] Visual regression testing
261
+
262
+ ### Phase 4: Release (Week 5)
263
+ - [ ] Staging deployment
264
+ - [ ] QA validation
265
+ - [ ] Usability testing
266
+ - [ ] Documentation finalization
267
+ - [ ] Production deployment
268
+ - [ ] Monitoring setup
269
+ - [ ] User feedback collection
270
+
271
+ ## Browser & Device Support
272
+
273
+ ### Desktop Browsers
274
+ - Chrome (latest 2 versions)
275
+ - Firefox (latest 2 versions)
276
+ - Safari (latest 2 versions)
277
+ - Edge (latest 2 versions)
278
+
279
+ ### Mobile Browsers
280
+ - iOS Safari (latest 2 versions)
281
+ - Chrome Mobile (latest version)
282
+ - Samsung Internet (latest version)
283
+
284
+ ### Device Testing
285
+ - [ ] iPhone (12, 13, 14, 15)
286
+ - [ ] iPad (9th gen, Pro)
287
+ - [ ] Android phones (Samsung, Pixel)
288
+ - [ ] Desktop (1920x1080, 2560x1440)
289
+
290
+ ## Monitoring & Analytics
291
+
292
+ ### Performance Monitoring
293
+ - Real User Monitoring (RUM)
294
+ - Core Web Vitals tracking
295
+ - Error tracking (Sentry/Rollbar)
296
+ - Bundle size monitoring
297
+
298
+ ### User Analytics
299
+ - User flow tracking
300
+ - Feature usage metrics
301
+ - Conversion funnels
302
+ - Drop-off points
303
+
304
+ ### Alerts
305
+ - Performance degradation (LCP > 3s)
306
+ - Error rate spike (> {{error_threshold}}%)
307
+ - Accessibility violations
308
+ - Browser compatibility issues
309
+
310
+ ## Rollback Plan
311
+
312
+ ### Rollback Triggers
313
+ - Accessibility compliance failure
314
+ - Critical UI bug affecting {{user_percentage}}% users
315
+ - Performance degradation > {{perf_degradation}}%
316
+ - Cross-browser compatibility issues
317
+
318
+ ### Rollback Procedure
319
+ 1. Feature flag toggle (immediate disable)
320
+ 2. Revert deployment to previous version
321
+ 3. Notify affected users
322
+ 4. Root cause analysis
323
+ 5. Fix and re-deploy
324
+
325
+ ## Risks and Mitigation
326
+
327
+ ### Technical Risks
328
+ | Risk | Impact | Probability | Mitigation |
329
+ |------|--------|-------------|------------|
330
+ | Browser compatibility issues | High | Medium | Cross-browser testing early |
331
+ | Performance degradation | High | Low | Performance budgets, monitoring |
332
+ | Accessibility violations | Critical | Low | Automated + manual testing |
333
+
334
+ ### UX Risks
335
+ | Risk | Impact | Probability | Mitigation |
336
+ |------|--------|-------------|------------|
337
+ | Poor usability | High | Medium | User testing, feedback loops |
338
+ | Confusing navigation | Medium | Medium | A/B testing, analytics |
339
+
340
+ ## Open Questions
341
+
342
+ - [ ] {{question_1}}
343
+ - [ ] {{question_2}}
344
+ - [ ] {{question_3}}
345
+
346
+ ## Appendix
347
+
348
+ ### Design Resources
349
+ - Design system: {{design_system_link}}
350
+ - Component library: {{component_library_link}}
351
+ - Icon library: {{icon_library}}
352
+
353
+ ### References
354
+ - [WCAG 2.1 Guidelines](https://www.w3.org/TR/WCAG21/)
355
+ - [Web Vitals](https://web.dev/vitals/)
356
+ - [Accessibility Testing Guide](https://www.w3.org/WAI/test-evaluate/)
357
+ - [React Best Practices 2025](https://react.dev/learn)
358
+
359
+ ### Changelog
360
+ - {{timestamp}}: Initial PRD created by {{author}}
361
+
362
+ ---
363
+
364
+ *UI Feature PRD - Generated from template: ui-feature*
365
+ *Template follows 2025 best practices: WCAG 2.1 AA compliance, Core Web Vitals, TDD methodology, Mobile-first design*
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Template Engine - Pure Node.js Implementation
3
+ *
4
+ * NO external dependencies - uses only built-in Node.js modules
5
+ *
6
+ * Features:
7
+ * - Variable substitution: {{variable}}
8
+ * - Conditionals: {{#if variable}}...{{/if}}
9
+ * - Loops: {{#each items}}...{{/each}}
10
+ * - Auto-generated variables: id, timestamp, author, date
11
+ * - Template discovery: user custom overrides built-in
12
+ *
13
+ * @example Basic Usage
14
+ * ```javascript
15
+ * const TemplateEngine = require('./lib/template-engine');
16
+ * const engine = new TemplateEngine();
17
+ *
18
+ * // Find template
19
+ * const templatePath = engine.findTemplate('prds', 'api-feature');
20
+ *
21
+ * // Render with variables
22
+ * const rendered = engine.renderFile(templatePath, {
23
+ * title: 'User Authentication API',
24
+ * priority: 'P0',
25
+ * problem: 'Users cannot login securely'
26
+ * });
27
+ * ```
28
+ *
29
+ * @example Advanced Features
30
+ * ```javascript
31
+ * // Template with conditionals and loops
32
+ * const template = `
33
+ * # {{title}}
34
+ *
35
+ * {{#if description}}
36
+ * ## Description
37
+ * {{description}}
38
+ * {{/if}}
39
+ *
40
+ * ## Features
41
+ * {{#each features}}
42
+ * - {{this}}
43
+ * {{/each}}
44
+ * `;
45
+ *
46
+ * const result = engine.render(template, {
47
+ * title: 'My Feature',
48
+ * description: 'Feature description',
49
+ * features: ['Auth', 'API', 'UI']
50
+ * });
51
+ * ```
52
+ *
53
+ * @module TemplateEngine
54
+ * @version 1.0.0
55
+ * @since v1.28.0
56
+ */
57
+
58
+ const fs = require('fs');
59
+ const path = require('path');
60
+
61
+ class TemplateEngine {
62
+ constructor(builtInDir, userDir) {
63
+ // For testing, allow custom built-in directory and user directory
64
+ // In production, use autopm/.claude/templates and .claude/templates
65
+ this.builtInDir = builtInDir || path.join(__dirname, '..', 'autopm', '.claude', 'templates');
66
+ this.userDir = userDir || path.join('.claude', 'templates');
67
+ }
68
+
69
+ /**
70
+ * Find template by name
71
+ * Priority: user templates > built-in templates
72
+ *
73
+ * @param {string} type - Template type (prds/epics/tasks)
74
+ * @param {string} name - Template name (without .md extension)
75
+ * @returns {string|null} - Path to template or null if not found
76
+ */
77
+ findTemplate(type, name) {
78
+ const userPath = path.resolve(this.userDir, type, `${name}.md`);
79
+ const builtInPath = path.resolve(this.builtInDir, type, `${name}.md`);
80
+
81
+ if (fs.existsSync(userPath)) return userPath;
82
+ if (fs.existsSync(builtInPath)) return builtInPath;
83
+ return null;
84
+ }
85
+
86
+ /**
87
+ * List all available templates of a given type
88
+ *
89
+ * @param {string} type - Template type (prds/epics/tasks)
90
+ * @returns {Array<{name: string, custom: boolean}>}
91
+ */
92
+ listTemplates(type) {
93
+ const templates = [];
94
+
95
+ // Built-in templates
96
+ const builtInPath = path.join(this.builtInDir, type);
97
+ if (fs.existsSync(builtInPath)) {
98
+ const files = fs.readdirSync(builtInPath)
99
+ .filter(f => f.endsWith('.md'))
100
+ .map(f => ({ name: f.replace('.md', ''), custom: false }));
101
+ templates.push(...files);
102
+ }
103
+
104
+ // User custom templates
105
+ const userPath = path.join(this.userDir, type);
106
+ if (fs.existsSync(userPath)) {
107
+ const files = fs.readdirSync(userPath)
108
+ .filter(f => f.endsWith('.md'))
109
+ .map(f => ({ name: f.replace('.md', ''), custom: true }));
110
+ templates.push(...files);
111
+ }
112
+
113
+ return templates;
114
+ }
115
+
116
+ /**
117
+ * Generate auto variables
118
+ *
119
+ * @returns {Object} - Auto-generated variables
120
+ */
121
+ generateAutoVariables() {
122
+ const now = new Date();
123
+ return {
124
+ id: '', // Will be set by generateId()
125
+ timestamp: now.toISOString(),
126
+ date: now.toISOString().split('T')[0],
127
+ author: process.env.USER || process.env.USERNAME || 'unknown'
128
+ };
129
+ }
130
+
131
+ /**
132
+ * Generate sequential ID
133
+ *
134
+ * @param {string} prefix - ID prefix (prd/epic/task)
135
+ * @param {string} directory - Directory to scan for existing IDs
136
+ * @returns {string} - Next sequential ID
137
+ */
138
+ generateId(prefix, directory) {
139
+ if (!fs.existsSync(directory)) {
140
+ return `${prefix}-001`;
141
+ }
142
+
143
+ const files = fs.readdirSync(directory)
144
+ .filter(f => f.startsWith(`${prefix}-`) && f.endsWith('.md'));
145
+
146
+ if (files.length === 0) {
147
+ return `${prefix}-001`;
148
+ }
149
+
150
+ // Extract numbers and find max
151
+ const numbers = files
152
+ .map(f => {
153
+ const match = f.match(new RegExp(`${prefix}-(\\d+)\\.md`));
154
+ return match ? parseInt(match[1], 10) : 0;
155
+ })
156
+ .filter(n => !isNaN(n));
157
+
158
+ const maxNum = Math.max(...numbers);
159
+ const nextNum = maxNum + 1;
160
+
161
+ return `${prefix}-${String(nextNum).padStart(3, '0')}`;
162
+ }
163
+
164
+ /**
165
+ * Render template with variables
166
+ *
167
+ * @param {string} template - Template string
168
+ * @param {Object} variables - Variables to substitute
169
+ * @returns {string} - Rendered template
170
+ */
171
+ render(template, variables) {
172
+ // Auto-generate variables
173
+ const autoVars = this.generateAutoVariables();
174
+
175
+ // Generate ID if not provided
176
+ if (!variables.id && !autoVars.id) {
177
+ // Try to infer type and directory from variables
178
+ const type = variables.type || 'item';
179
+ const directory = `.claude/${type}s`;
180
+ autoVars.id = this.generateId(type, directory);
181
+ }
182
+
183
+ const allVars = { ...autoVars, ...variables };
184
+
185
+ let content = template;
186
+
187
+ // Process loops first ({{#each}}...{{/each}})
188
+ content = this.processLoops(content, allVars);
189
+
190
+ // Process conditionals ({{#if}}...{{/if}})
191
+ content = this.processConditionals(content, allVars);
192
+
193
+ // Simple variable substitution ({{variable}})
194
+ for (const [key, value] of Object.entries(allVars)) {
195
+ const regex = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
196
+ content = content.replace(regex, value || '');
197
+ }
198
+
199
+ // Replace any remaining {{variables}} that weren't in allVars with empty string
200
+ content = content.replace(/\{\{(\w+)\}\}/g, '');
201
+
202
+ return content;
203
+ }
204
+
205
+ /**
206
+ * Render template from file
207
+ *
208
+ * @param {string} templatePath - Path to template file
209
+ * @param {Object} variables - Variables to substitute
210
+ * @returns {string} - Rendered template
211
+ */
212
+ renderFile(templatePath, variables) {
213
+ const template = fs.readFileSync(templatePath, 'utf8');
214
+ return this.render(template, variables);
215
+ }
216
+
217
+ /**
218
+ * Process conditionals {{#if var}}...{{/if}}
219
+ *
220
+ * @param {string} content - Template content
221
+ * @param {Object} vars - Variables
222
+ * @returns {string} - Processed content
223
+ */
224
+ processConditionals(content, vars) {
225
+ // Match {{#if variable}}...{{/if}} - process from inside out for nested conditionals
226
+ const ifRegex = /\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/;
227
+
228
+ let result = content;
229
+ let changed = true;
230
+ let iterations = 0;
231
+ const maxIterations = 100;
232
+
233
+ // Keep processing until no more conditionals found (handles nesting)
234
+ while (changed && iterations < maxIterations) {
235
+ iterations++;
236
+ changed = false;
237
+
238
+ const match = result.match(ifRegex);
239
+ if (match) {
240
+ const [fullMatch, varName, innerContent] = match;
241
+ const varValue = vars[varName];
242
+
243
+ // If variable is truthy, keep inner content; otherwise remove
244
+ const replacement = varValue ? innerContent : '';
245
+ result = result.replace(fullMatch, replacement);
246
+ changed = true;
247
+ }
248
+ }
249
+
250
+ return result;
251
+ }
252
+
253
+ /**
254
+ * Process loops {{#each items}}...{{/each}}
255
+ *
256
+ * @param {string} content - Template content
257
+ * @param {Object} vars - Variables
258
+ * @returns {string} - Processed content
259
+ */
260
+ processLoops(content, vars) {
261
+ // Match {{#each variable}}...{{/each}}
262
+ // Limit inner content to 10,000 characters to prevent ReDoS
263
+ const eachRegex = /\{\{#each\s+(\w+)\}\}([\s\S]{0,10000}?)\{\{\/each\}\}/g;
264
+
265
+ let result = content;
266
+ let match;
267
+
268
+ // Safety counter
269
+ let iterations = 0;
270
+ const maxIterations = 100;
271
+
272
+ while ((match = eachRegex.exec(content)) !== null && iterations < maxIterations) {
273
+ iterations++;
274
+ const [fullMatch, varName, template] = match;
275
+ const items = vars[varName];
276
+
277
+ if (!Array.isArray(items)) {
278
+ // Not an array, remove the loop
279
+ result = result.replace(fullMatch, '');
280
+ continue;
281
+ }
282
+
283
+ // Render each item
284
+ let rendered = '';
285
+ for (const item of items) {
286
+ if (typeof item === 'object' && item !== null) {
287
+ // Object: replace {{property}} with object properties
288
+ let itemRendered = template;
289
+ for (const [key, value] of Object.entries(item)) {
290
+ const regex = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
291
+ itemRendered = itemRendered.replace(regex, value || '');
292
+ }
293
+ rendered += itemRendered;
294
+ } else {
295
+ // Primitive: replace {{this}} with the value
296
+ rendered += template.replace(/\{\{this\}\}/g, item);
297
+ }
298
+ }
299
+
300
+ result = result.replace(fullMatch, rendered);
301
+ }
302
+
303
+ return result;
304
+ }
305
+
306
+ /**
307
+ * Validate template
308
+ *
309
+ * @param {string} template - Template string
310
+ * @returns {Object} - {valid: boolean, errors: string[]}
311
+ */
312
+ validate(template) {
313
+ const errors = [];
314
+
315
+ // Check frontmatter
316
+ if (!template.startsWith('---')) {
317
+ errors.push('Missing frontmatter');
318
+ }
319
+
320
+ // Check required variables
321
+ const requiredVars = ['id', 'title', 'type'];
322
+ for (const varName of requiredVars) {
323
+ if (!template.includes(`{{${varName}}}`)) {
324
+ errors.push(`Missing required variable: {{${varName}}}`);
325
+ }
326
+ }
327
+
328
+ return {
329
+ valid: errors.length === 0,
330
+ errors
331
+ };
332
+ }
333
+
334
+ /**
335
+ * Ensure template directory exists
336
+ *
337
+ * @param {string} type - Template type (prds/epics/tasks)
338
+ */
339
+ ensureTemplateDir(type) {
340
+ const dir = path.join(this.userDir, type);
341
+ if (!fs.existsSync(dir)) {
342
+ fs.mkdirSync(dir, { recursive: true });
343
+ }
344
+ }
345
+ }
346
+
347
+ module.exports = TemplateEngine;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-autopm",
3
- "version": "1.27.0",
3
+ "version": "1.28.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": {