create-sdd-project 0.2.4 → 0.3.3

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.
Files changed (43) hide show
  1. package/README.md +10 -10
  2. package/lib/config.js +1 -1
  3. package/lib/generator.js +144 -27
  4. package/lib/init-generator.js +321 -41
  5. package/lib/init-wizard.js +1 -1
  6. package/package.json +1 -1
  7. package/template/.claude/agents/backend-developer.md +1 -1
  8. package/template/.claude/agents/frontend-developer.md +1 -1
  9. package/template/.claude/settings.json +1 -1
  10. package/template/.claude/skills/bug-workflow/SKILL.md +2 -2
  11. package/template/.claude/skills/development-workflow/SKILL.md +18 -18
  12. package/template/.claude/skills/development-workflow/references/add-feature-template.md +16 -0
  13. package/template/.claude/skills/development-workflow/references/branching-strategy.md +1 -1
  14. package/template/.claude/skills/development-workflow/references/complexity-guide.md +6 -6
  15. package/template/.claude/skills/development-workflow/references/failure-handling.md +3 -3
  16. package/template/.claude/skills/development-workflow/references/pr-template.md +3 -3
  17. package/template/.claude/skills/development-workflow/references/ticket-template.md +3 -3
  18. package/template/.claude/skills/development-workflow/references/workflow-example.md +7 -7
  19. package/template/.claude/skills/project-memory/SKILL.md +9 -9
  20. package/template/.gemini/agents/backend-developer.md +1 -1
  21. package/template/.gemini/agents/frontend-developer.md +1 -1
  22. package/template/.gemini/commands/add-feature.toml +2 -0
  23. package/template/.gemini/commands/next-task.toml +2 -2
  24. package/template/.gemini/commands/show-progress.toml +2 -2
  25. package/template/.gemini/commands/start-task.toml +1 -1
  26. package/template/.gemini/skills/bug-workflow/SKILL.md +4 -4
  27. package/template/.gemini/skills/development-workflow/SKILL.md +18 -18
  28. package/template/.gemini/skills/development-workflow/references/add-feature-template.md +16 -0
  29. package/template/.gemini/skills/development-workflow/references/branching-strategy.md +1 -1
  30. package/template/.gemini/skills/development-workflow/references/complexity-guide.md +6 -6
  31. package/template/.gemini/skills/development-workflow/references/failure-handling.md +3 -3
  32. package/template/.gemini/skills/development-workflow/references/pr-template.md +3 -3
  33. package/template/.gemini/skills/development-workflow/references/ticket-template.md +3 -3
  34. package/template/.gemini/skills/development-workflow/references/workflow-example.md +7 -7
  35. package/template/.gemini/skills/project-memory/SKILL.md +8 -8
  36. package/template/AGENTS.md +6 -6
  37. package/template/CLAUDE.md +2 -2
  38. package/template/ai-specs/specs/base-standards.mdc +8 -8
  39. package/template/docs/project_notes/product-tracker.md +56 -0
  40. package/template/.claude/skills/development-workflow/references/sprint-init-template.md +0 -82
  41. package/template/.gemini/commands/init-sprint.toml +0 -2
  42. package/template/.gemini/skills/development-workflow/references/sprint-init-template.md +0 -82
  43. package/template/docs/project_notes/sprint-0-tracker.md +0 -66
@@ -35,12 +35,15 @@ function generateInit(config) {
35
35
  step('Creating ai-specs/specs/ (4 standards files)');
36
36
  ensureDir(path.join(dest, 'ai-specs', 'specs'));
37
37
 
38
- // base-standards and documentation-standards: copy as-is
39
- copyFileIfNotExists(
40
- path.join(templateDir, 'ai-specs', 'specs', 'base-standards.mdc'),
41
- path.join(dest, 'ai-specs', 'specs', 'base-standards.mdc'),
42
- skipped
43
- );
38
+ // base-standards: adapt validation references based on detected stack
39
+ const baseStdPath = path.join(dest, 'ai-specs', 'specs', 'base-standards.mdc');
40
+ if (!fs.existsSync(baseStdPath)) {
41
+ const baseTemplate = fs.readFileSync(path.join(templateDir, 'ai-specs', 'specs', 'base-standards.mdc'), 'utf8');
42
+ const adaptedBase = adaptBaseStandards(baseTemplate, scan, config);
43
+ fs.writeFileSync(baseStdPath, adaptedBase, 'utf8');
44
+ } else {
45
+ skipped.push('ai-specs/specs/base-standards.mdc');
46
+ }
44
47
  copyFileIfNotExists(
45
48
  path.join(templateDir, 'ai-specs', 'specs', 'documentation-standards.mdc'),
46
49
  path.join(dest, 'ai-specs', 'specs', 'documentation-standards.mdc'),
@@ -72,7 +75,7 @@ function generateInit(config) {
72
75
  }
73
76
 
74
77
  // 3. Copy and configure docs/
75
- step('Creating docs/project_notes/ (sprint tracker, memory)');
78
+ step('Creating docs/project_notes/ (product tracker, memory)');
76
79
  ensureDir(path.join(dest, 'docs', 'project_notes'));
77
80
  ensureDir(path.join(dest, 'docs', 'specs'));
78
81
  ensureDir(path.join(dest, 'docs', 'tickets'));
@@ -99,14 +102,14 @@ function generateInit(config) {
99
102
  skipped
100
103
  );
101
104
 
102
- // sprint-0-tracker.md — configure dates and add retrofit tasks
103
- const trackerPath = path.join(dest, 'docs', 'project_notes', 'sprint-0-tracker.md');
105
+ // product-tracker.md — configure and add retrofit tasks
106
+ const trackerPath = path.join(dest, 'docs', 'project_notes', 'product-tracker.md');
104
107
  if (!fs.existsSync(trackerPath)) {
105
- const template = fs.readFileSync(path.join(templateDir, 'docs', 'project_notes', 'sprint-0-tracker.md'), 'utf8');
106
- const configured = configureSprintTracker(template, scan);
108
+ const template = fs.readFileSync(path.join(templateDir, 'docs', 'project_notes', 'product-tracker.md'), 'utf8');
109
+ const configured = configureProductTracker(template, scan);
107
110
  fs.writeFileSync(trackerPath, configured, 'utf8');
108
111
  } else {
109
- skipped.push('docs/project_notes/sprint-0-tracker.md');
112
+ skipped.push('docs/project_notes/product-tracker.md');
110
113
  }
111
114
 
112
115
  // docs/specs/
@@ -174,6 +177,9 @@ function generateInit(config) {
174
177
  removeAgentFiles(dest, BACKEND_AGENTS, config);
175
178
  }
176
179
 
180
+ // 7b. Adapt agent/skill content to match detected stack
181
+ adaptCopiedFiles(dest, scan, config);
182
+
177
183
  // 8. Append to .gitignore
178
184
  appendGitignore(dest, skipped);
179
185
 
@@ -195,7 +201,7 @@ function generateInit(config) {
195
201
 
196
202
  // Show review notes
197
203
  console.log('');
198
- console.log(' ⚠ REVIEW BEFORE YOUR FIRST SPRINT:');
204
+ console.log(' ⚠ REVIEW BEFORE YOUR FIRST FEATURE:');
199
205
  if (config.projectType !== 'frontend') {
200
206
  console.log(' - ai-specs/specs/backend-standards.mdc — Architecture section adapted from scan');
201
207
  }
@@ -214,7 +220,7 @@ function generateInit(config) {
214
220
  } else {
215
221
  console.log(` 📝 Test coverage appears low (${fileCount} test files found).`);
216
222
  }
217
- console.log(' Consider starting Sprint 0 with retrofit testing tasks.');
223
+ console.log(' Consider adding retrofit testing as your first feature.');
218
224
  }
219
225
 
220
226
  // Prisma schema note
@@ -226,7 +232,7 @@ function generateInit(config) {
226
232
  // Done
227
233
  console.log(`\nDone! Next steps:`);
228
234
  console.log(` git add -A && git commit -m "chore: add SDD DevFlow to existing project"`);
229
- console.log(` # Open in your AI coding tool and run: init sprint 0\n`);
235
+ console.log(` # Open in your AI coding tool and run: add feature "your first feature"\n`);
230
236
  }
231
237
 
232
238
  // --- Helpers ---
@@ -288,8 +294,288 @@ function safeDelete(filePath) {
288
294
  try { fs.unlinkSync(filePath); } catch { /* ignore */ }
289
295
  }
290
296
 
297
+ // --- Adapt Copied Agent/Skill Files ---
298
+
299
+ function replaceInCopiedFile(dest, relativePath, replacements) {
300
+ const filePath = path.join(dest, relativePath);
301
+ if (!fs.existsSync(filePath)) return;
302
+ let content = fs.readFileSync(filePath, 'utf8');
303
+ for (const [from, to] of replacements) {
304
+ content = content.replaceAll(from, to);
305
+ }
306
+ fs.writeFileSync(filePath, content, 'utf8');
307
+ }
308
+
309
+ function regexReplaceInFile(filePath, replacements) {
310
+ if (!fs.existsSync(filePath)) return;
311
+ let content = fs.readFileSync(filePath, 'utf8');
312
+ for (const [from, to] of replacements) {
313
+ if (from instanceof RegExp) {
314
+ content = content.replace(from, to);
315
+ } else {
316
+ content = content.replaceAll(from, to);
317
+ }
318
+ }
319
+ fs.writeFileSync(filePath, content, 'utf8');
320
+ }
321
+
322
+ function adaptCopiedFiles(dest, scan, config) {
323
+ const orm = scan.backend.orm || 'your ORM';
324
+ const db = scan.backend.db || 'your database';
325
+
326
+ // Common Zod → generic validation replacements (all agents + skills)
327
+ // Order: most specific first, catch-all last
328
+ const zodReplacements = [
329
+ ['Zod data schemas', 'validation schemas'],
330
+ ['Zod schemas', 'validation schemas'],
331
+ ];
332
+
333
+ // ORM/DB replacements for backend agents
334
+ const ormReplacements = scan.backend.orm && scan.backend.orm !== 'Prisma'
335
+ ? [
336
+ ['Prisma ORM, and PostgreSQL', `${orm}${db !== 'your database' ? `, and ${db}` : ''}`],
337
+ ['Repository implementations (Prisma)', `Repository implementations (${orm})`],
338
+ ]
339
+ : [];
340
+
341
+ // Apply to all AI tool directories
342
+ const toolDirs = [];
343
+ if (config.aiTools !== 'gemini') toolDirs.push('.claude');
344
+ if (config.aiTools !== 'claude') toolDirs.push('.gemini');
345
+
346
+ for (const dir of toolDirs) {
347
+ // Backend agents: Zod + ORM replacements
348
+ if (scan.backend.validation !== 'Zod') {
349
+ const backendAgentReplacements = [...zodReplacements, ...ormReplacements];
350
+ replaceInCopiedFile(dest, `${dir}/agents/backend-developer.md`, backendAgentReplacements);
351
+ replaceInCopiedFile(dest, `${dir}/agents/backend-planner.md`, backendAgentReplacements);
352
+ } else if (ormReplacements.length > 0) {
353
+ // Zod detected but different ORM — only ORM replacements
354
+ replaceInCopiedFile(dest, `${dir}/agents/backend-developer.md`, ormReplacements);
355
+ replaceInCopiedFile(dest, `${dir}/agents/backend-planner.md`, ormReplacements);
356
+ }
357
+
358
+ // Multi-purpose agents: Zod replacements only
359
+ if (scan.backend.validation !== 'Zod') {
360
+ replaceInCopiedFile(dest, `${dir}/agents/spec-creator.md`, zodReplacements);
361
+ replaceInCopiedFile(dest, `${dir}/agents/production-code-validator.md`, zodReplacements);
362
+ replaceInCopiedFile(dest, `${dir}/agents/database-architect.md`, zodReplacements);
363
+ }
364
+
365
+ // Skills: Zod replacements
366
+ if (scan.backend.validation !== 'Zod') {
367
+ replaceInCopiedFile(dest, `${dir}/skills/development-workflow/SKILL.md`, zodReplacements);
368
+ replaceInCopiedFile(dest, `${dir}/skills/development-workflow/references/ticket-template.md`, zodReplacements);
369
+ }
370
+ }
371
+
372
+ // Architecture adaptation: DDD-specific content in backend agents
373
+ const arch = scan.srcStructure ? scan.srcStructure.pattern : 'ddd';
374
+ if (arch !== 'ddd') {
375
+ for (const dir of toolDirs) {
376
+ // backend-planner: adapt header, exploration paths, implementation order, rules
377
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'backend-planner.md'), [
378
+ // Header: remove DDD reference, use generic
379
+ ['specializing in Domain-Driven Design (DDD) layered architecture with deep knowledge of',
380
+ 'specializing in layered architecture with deep knowledge of'],
381
+ // Exploration paths: replace DDD-specific with generic
382
+ [/4\. Read `shared\/src\/schemas\/` \(if exists\) for current .* data schemas\n/, ''],
383
+ [/5\. Explore `backend\/src\/domain\/` for existing entities and errors\n/,
384
+ '5. Explore the codebase for existing patterns, layer structure, and reusable code\n'],
385
+ [/6\. Explore `backend\/src\/application\/services\/` for existing services\n/, ''],
386
+ [/7\. Explore `backend\/src\/application\/validators\/` for existing validators\n/, ''],
387
+ [/8\. Explore `backend\/src\/infrastructure\/` for existing repositories\n/, ''],
388
+ // Implementation Order
389
+ ['following DDD layer order: Domain > Application > Infrastructure > Presentation > Tests',
390
+ 'following the layer order defined in backend-standards.mdc'],
391
+ // Rules
392
+ ['Follow DDD layer separation: Domain > Application > Infrastructure > Presentation',
393
+ 'Follow the layer separation defined in backend-standards.mdc'],
394
+ ]);
395
+ // backend-developer: adapt frontmatter, header, exploration, implementation order, rules
396
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'backend-developer.md'), [
397
+ ['follows DDD layered architecture',
398
+ 'follows layered architecture'],
399
+ ['specializing in Domain-Driven Design (DDD) with',
400
+ 'specializing in layered architecture with'],
401
+ [/4\. Read `shared\/src\/schemas\/` \(if exists\) for current .* data schemas\n/, ''],
402
+ // Implementation Order section: replace DDD layers with generic guidance
403
+ ['Follow the DDD layer order from the plan:',
404
+ 'Follow the layer order from the plan (see backend-standards.mdc for project layers):'],
405
+ [/1\. \*\*Domain Layer\*\*: Entities, value objects, repository interfaces, domain errors\n/,
406
+ '1. **Data Layer**: Models, database operations, data access\n'],
407
+ [/2\. \*\*Application Layer\*\*: Services, validators, DTOs\n/,
408
+ '2. **Business Logic Layer**: Controllers, services, external integrations\n'],
409
+ [/3\. \*\*Infrastructure Layer\*\*: Repository implementations \([^)]*\), external integrations\n/,
410
+ '3. **Presentation Layer**: Routes, handlers, middleware\n'],
411
+ [/4\. \*\*Presentation Layer\*\*: Controllers, routes, middleware\n/,
412
+ '4. **Integration Layer**: Wiring, configuration, server registration\n'],
413
+ // Rules
414
+ ['**ALWAYS** follow DDD layer separation',
415
+ '**ALWAYS** follow the layer separation defined in backend-standards.mdc'],
416
+ ['**ALWAYS** handle errors with custom domain error classes',
417
+ '**ALWAYS** handle errors following the patterns in backend-standards.mdc'],
418
+ // Documentation
419
+ [/- \*\*MANDATORY\*\*: If modifying a DB schema → update .* schemas in `shared\/src\/schemas\/` BEFORE continuing\n/, ''],
420
+ ]);
421
+ }
422
+ }
423
+
424
+ // Agent content: remove frontend/backend-specific references for single-stack projects
425
+ if (config.projectType === 'backend') {
426
+ for (const dir of toolDirs) {
427
+ // spec-creator: remove Frontend Specifications section and UI output format
428
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'spec-creator.md'), [
429
+ [/### Frontend Specifications\n(?:- [^\n]*\n)+\n/, ''],
430
+ [/### For UI Changes\n```markdown\n(?:[^\n]*\n)*?```\n\n/, ''],
431
+ ['Data Model Changes, UI Changes, Edge Cases', 'Data Model Changes, Edge Cases'],
432
+ ]);
433
+ // production-code-validator: remove ui-components line from Spec Drift
434
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'production-code-validator.md'), [
435
+ [/- Components exported\/used that are NOT listed in `docs\/specs\/ui-components\.md`\n/, ''],
436
+ ]);
437
+ // code-review-specialist: backend-only standards ref, remove ui-components
438
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'code-review-specialist.md'), [
439
+ ['(`backend-standards.mdc` / `frontend-standards.mdc`)', '(`backend-standards.mdc`)'],
440
+ ['(`api-spec.yaml`, `ui-components.md`)', '(`api-spec.yaml`)'],
441
+ ]);
442
+ // qa-engineer: remove ui-components from specs, remove frontend test command
443
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'qa-engineer.md'), [
444
+ ['(`api-spec.yaml`, `ui-components.md`)', '(`api-spec.yaml`)'],
445
+ [/- Frontend: `cd frontend && npm test`\n/, ''],
446
+ [/- \*\*Frontend\*\*: Write tests for error states[^\n]*\n/, ''],
447
+ ]);
448
+ }
449
+ } else if (config.projectType === 'frontend') {
450
+ for (const dir of toolDirs) {
451
+ // spec-creator: remove Backend Specifications section
452
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'spec-creator.md'), [
453
+ [/### Backend Specifications\n(?:- [^\n]*\n)+\n/, ''],
454
+ [/### For API Changes\n```yaml\n(?:[^\n]*\n)*?```\n\n/, ''],
455
+ ]);
456
+ // code-review-specialist: frontend-only standards ref
457
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'code-review-specialist.md'), [
458
+ ['(`backend-standards.mdc` / `frontend-standards.mdc`)', '(`frontend-standards.mdc`)'],
459
+ ['(`api-spec.yaml`, `ui-components.md`)', '(`ui-components.md`)'],
460
+ ]);
461
+ // qa-engineer: remove api-spec from specs, remove backend test command
462
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'qa-engineer.md'), [
463
+ ['(`api-spec.yaml`, `ui-components.md`)', '(`ui-components.md`)'],
464
+ [/- Backend: `cd backend && npm test`\n/, ''],
465
+ [/- \*\*Backend\*\*: Write tests for error paths[^\n]*\n/, ''],
466
+ ]);
467
+ }
468
+ }
469
+
470
+ // Skills and templates: remove frontend/backend-specific references
471
+ if (config.projectType === 'backend') {
472
+ for (const dir of toolDirs) {
473
+ // Gemini agents have different text patterns
474
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'spec-creator.md'), [
475
+ [/\(api-spec\.yaml, ui-components\.md\)/, '(api-spec.yaml)'],
476
+ ['Data Model Changes, UI Changes, Edge Cases', 'Data Model Changes, Edge Cases'],
477
+ ]);
478
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'production-code-validator.md'), [
479
+ [/,? components not in ui-components\.md/, ''],
480
+ ]);
481
+ // SKILL.md: remove ui-components references
482
+ regexReplaceInFile(path.join(dest, dir, 'skills', 'development-workflow', 'SKILL.md'), [
483
+ [/,? `ui-components\.md`\)/, ')'],
484
+ [/- UI components → `docs\/specs\/ui-components\.md` \(MANDATORY\)\n/, ''],
485
+ ]);
486
+ // ticket-template: remove UI Changes section, ui-components from checklists
487
+ regexReplaceInFile(path.join(dest, dir, 'skills', 'development-workflow', 'references', 'ticket-template.md'), [
488
+ [/### UI Changes \(if applicable\)\n\n\[Components to add\/modify\. Reference `docs\/specs\/ui-components\.md`\.\]\n\n/, ''],
489
+ [' / `ui-components.md`', ''],
490
+ ]);
491
+ // pr-template: remove ui-components from checklist
492
+ regexReplaceInFile(path.join(dest, dir, 'skills', 'development-workflow', 'references', 'pr-template.md'), [
493
+ [' / ui-components.md', ''],
494
+ ]);
495
+ }
496
+ } else if (config.projectType === 'frontend') {
497
+ for (const dir of toolDirs) {
498
+ regexReplaceInFile(path.join(dest, dir, 'agents', 'spec-creator.md'), [
499
+ [/\(api-spec\.yaml, ui-components\.md\)/, '(ui-components.md)'],
500
+ ]);
501
+ regexReplaceInFile(path.join(dest, dir, 'skills', 'development-workflow', 'SKILL.md'), [
502
+ [/`api-spec\.yaml`,? /, ''],
503
+ [/- API endpoints → `docs\/specs\/api-spec\.yaml` \(MANDATORY\)\n/, ''],
504
+ ]);
505
+ regexReplaceInFile(path.join(dest, dir, 'skills', 'development-workflow', 'references', 'ticket-template.md'), [
506
+ [/### API Changes \(if applicable\)\n\n\[Endpoints to add\/modify\. Reference[^\]]*\]\n\n/, ''],
507
+ ['`api-spec.yaml` / ', ''],
508
+ ]);
509
+ regexReplaceInFile(path.join(dest, dir, 'skills', 'development-workflow', 'references', 'pr-template.md'), [
510
+ ['api-spec.yaml / ', ''],
511
+ ]);
512
+ }
513
+ }
514
+
515
+ // documentation-standards.mdc: remove irrelevant rows based on project type
516
+ const docStdPath = path.join(dest, 'ai-specs', 'specs', 'documentation-standards.mdc');
517
+ if (fs.existsSync(docStdPath)) {
518
+ let content = fs.readFileSync(docStdPath, 'utf8');
519
+ if (config.projectType === 'backend') {
520
+ content = content.replace(/\| `ai-specs\/specs\/frontend-standards\.mdc` \|[^\n]*\n/, '');
521
+ content = content.replace(/\| `docs\/specs\/ui-components\.md` \|[^\n]*\n/, '');
522
+ content = content.replace(/ - UI component changes → `docs\/specs\/ui-components\.md`\n/, '');
523
+ } else if (config.projectType === 'frontend') {
524
+ content = content.replace(/\| `ai-specs\/specs\/backend-standards\.mdc` \|[^\n]*\n/, '');
525
+ content = content.replace(/\| `docs\/specs\/api-spec\.yaml` \|[^\n]*\n/, '');
526
+ }
527
+ fs.writeFileSync(docStdPath, content, 'utf8');
528
+ }
529
+ }
530
+
291
531
  // --- Standards Adaptation ---
292
532
 
533
+ function adaptBaseStandards(template, scan, config) {
534
+ let content = template;
535
+
536
+ // Adapt validation recommendation based on detected library
537
+ const val = scan.backend.validation;
538
+ if (val && val !== 'Zod') {
539
+ content = content.replace(
540
+ 'Use runtime validation (Zod recommended).',
541
+ `Use runtime validation (${val}).`
542
+ );
543
+ } else if (!val) {
544
+ content = content.replace(
545
+ 'Use runtime validation (Zod recommended).',
546
+ 'Use runtime validation at system boundaries.'
547
+ );
548
+ }
549
+
550
+ // Adapt Shared Types Strategy section based on project structure
551
+ const hasSharedTypes = scan.frontend.detected && scan.backend.detected;
552
+ if (!hasSharedTypes) {
553
+ // Backend-only or frontend-only: remove entire Shared Types section
554
+ content = content.replace(
555
+ /## 5\. Shared Types Strategy\n\n<!-- CONFIG:.*?-->\n\n[\s\S]*?(?=\n## 6\.)/,
556
+ '## 5. Shared Types Strategy\n\n_Not applicable — single-stack project._\n\n'
557
+ );
558
+ } else if (val !== 'Zod') {
559
+ // Fullstack but not using Zod (or no validation detected): generalize the section
560
+ content = content.replace(
561
+ /## 5\. Shared Types Strategy\n\n<!-- CONFIG:.*?-->\n\nFor projects with backend \+ frontend, use a shared workspace for Zod schemas:\n\n```\n[\s\S]*?```\n\n\*\*Rules:\*\*\n[\s\S]*?(?=\n## 6\.)/,
562
+ `## 5. Shared Types Strategy\n\n<!-- CONFIG: Remove this section if your project has no shared types -->\n\nFor projects with backend + frontend, use a shared workspace for types:\n\n\`\`\`\nproject/\n├── shared/ ← @project/shared (npm workspace)\n│ └── src/types/ ← Shared TypeScript types\n├── backend/ ← imports @project/shared\n└── frontend/ ← imports @project/shared\n\`\`\`\n\n**Rules:**\n- Define shared types in the shared workspace\n- Both apps import from shared — never duplicate type definitions\n- Update shared types FIRST — both apps get changes automatically\n- Wire with npm workspaces + \`tsconfig.json\` paths\n\n`
563
+ );
564
+ }
565
+ // If Zod detected + fullstack: keep as-is (template default is correct)
566
+
567
+ // Remove frontend/backend references for single-stack projects
568
+ if (config.projectType === 'backend') {
569
+ content = content.replace(/ - \*\*Frontend\*\*: Update `docs\/specs\/ui-components\.md` first\.\n/, '');
570
+ content = content.replace('`backend-standards.mdc` / `frontend-standards.mdc`', '`backend-standards.mdc`');
571
+ } else if (config.projectType === 'frontend') {
572
+ content = content.replace(/ - \*\*Backend\*\*: Update `docs\/specs\/api-spec\.yaml` first\.\n/, '');
573
+ content = content.replace('`backend-standards.mdc` / `frontend-standards.mdc`', '`frontend-standards.mdc`');
574
+ }
575
+
576
+ return content;
577
+ }
578
+
293
579
  function adaptBackendStandards(template, scan) {
294
580
  let content = template;
295
581
 
@@ -367,6 +653,11 @@ function adaptBackendStandards(template, scan) {
367
653
  /## Database Patterns\n\n[\s\S]*?(?=\n## )/,
368
654
  `## Database Patterns\n\n<!-- TODO: Add database access patterns for your project. -->\n`
369
655
  );
656
+ } else if (scan.backend.orm === 'Mongoose') {
657
+ content = content.replace(
658
+ /## Database Patterns\n\n[\s\S]*?(?=\n## )/,
659
+ `## Database Patterns\n\n### Mongoose Best Practices\n- Define schemas in dedicated model files\n- Use TypeScript interfaces alongside Mongoose schemas for type safety\n- Use \`.lean()\` for read-only queries (returns plain objects, better performance)\n- Use \`.select()\` to limit returned fields on large documents\n- Add indexes for frequently queried fields (\`{ index: true }\` or compound \`schema.index()\`)\n- Use \`.populate()\` sparingly — avoid deep nesting, prefer manual joins for complex queries\n- Use middleware (pre/post hooks) for cross-cutting concerns (timestamps, audit logs)\n- Use transactions (\`session\`) for multi-document operations that must be atomic\n- Always handle \`CastError\` (invalid ObjectId) at the controller/middleware level\n\n### Schema Pattern\n\`\`\`typescript\nimport mongoose, { Schema, Document } from 'mongoose';\n\nexport interface IUser extends Document {\n email: string;\n name: string;\n role: 'user' | 'admin';\n}\n\nconst UserSchema = new Schema<IUser>({\n email: { type: String, required: true, unique: true, index: true },\n name: { type: String, required: true },\n role: { type: String, enum: ['user', 'admin'], default: 'user' },\n}, { timestamps: true });\n\nexport const User = mongoose.model<IUser>('User', UserSchema);\n\`\`\`\n\n`
660
+ );
370
661
  } else if (scan.backend.orm !== 'Prisma') {
371
662
  content = content.replace(
372
663
  /## Database Patterns\n\n[\s\S]*?(?=\n## )/,
@@ -646,40 +937,29 @@ function configureKeyFacts(template, config, scan) {
646
937
  return content;
647
938
  }
648
939
 
649
- // --- Sprint Tracker Configuration ---
940
+ // --- Product Tracker Configuration ---
650
941
 
651
- function configureSprintTracker(template, scan) {
942
+ function configureProductTracker(template, scan) {
652
943
  let content = template;
653
944
 
654
- // Set dates
655
- const today = new Date().toISOString().split('T')[0];
656
- const endDate = new Date();
657
- endDate.setDate(endDate.getDate() + 14);
658
- const end = endDate.toISOString().split('T')[0];
659
- content = content.replace(/\[YYYY-MM-DD\] to \[YYYY-MM-DD\]/, `${today} to ${end}`);
945
+ // Determine default feature type based on detected stack
946
+ const featureType = !scan.backend.detected && scan.frontend.detected
947
+ ? 'frontend'
948
+ : scan.backend.detected && scan.frontend.detected
949
+ ? 'fullstack'
950
+ : 'backend';
660
951
 
661
- // Remove irrelevant task tables based on detected stack
662
- if (!scan.frontend.detected) {
663
- content = content.replace(
664
- /\n### Frontend\n\n\| # \| Task \| Status \| Notes \|\n\|---\|------\|--------\|-------\|\n\| F0\.1 \| \[Task description\] \| ⬚ \| \|\n/,
665
- ''
666
- );
667
- }
668
- if (!scan.backend.detected) {
669
- content = content.replace(
670
- /\n### Backend\n\n\| # \| Task \| Status \| Notes \|\n\|---\|------\|--------\|-------\|\n\| B0\.1 \| \[Task description\] \| ⬚ \| \|\n/,
671
- ''
672
- );
952
+ // Update default feature type in the placeholder row
953
+ if (featureType !== 'backend') {
954
+ content = content.replace('| backend | pending', `| ${featureType} | pending`);
673
955
  }
674
956
 
675
- // Add retrofit testing tasks if coverage is low
957
+ // Add retrofit testing as first feature if coverage is low
676
958
  if (scan.tests.estimatedCoverage === 'none' || scan.tests.estimatedCoverage === 'low') {
677
- const retrofitSection = `\n### Retrofit Testing (recommended)\n\n| # | Task | Status | Notes |\n|---|------|--------|-------|\n| R0.1 | Audit existing test coverage | ⬚ | |\n| R0.2 | Add missing unit tests for critical paths | ⬚ | |\n| R0.3 | Set up CI test pipeline | ⬚ | |\n`;
678
-
679
- // Insert before Status Legend
959
+ // Use regex to match the F001 placeholder row resiliently (handles column changes)
680
960
  content = content.replace(
681
- '**Status Legend:**',
682
- `${retrofitSection}\n**Status Legend:**`
961
+ /\| F001 \|[^\n]*\n/,
962
+ `| F001 | Retrofit: audit and improve test coverage | ${featureType} | pending | — | Recommended — low test coverage detected |\n| F002 | [Feature description] | ${featureType} | pending | — | |\n`
683
963
  );
684
964
  }
685
965
 
@@ -220,7 +220,7 @@ async function runInitWizard(scanResult) {
220
220
 
221
221
  console.log('\n Files to be created:');
222
222
  console.log(' ai-specs/specs/ (4 files — standards adapted to your stack)');
223
- console.log(' docs/project_notes/ (4 files — sprint tracker, memory)');
223
+ console.log(' docs/project_notes/ (4 files — product tracker, memory)');
224
224
  console.log(' docs/specs/ (API spec, UI components)');
225
225
  console.log(' docs/tickets/ (.gitkeep)');
226
226
  if (config.aiTools !== 'gemini') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-sdd-project",
3
- "version": "0.2.4",
3
+ "version": "0.3.3",
4
4
  "description": "Create a new SDD DevFlow project with AI-assisted development workflow",
5
5
  "bin": {
6
6
  "create-sdd-project": "bin/cli.js"
@@ -57,4 +57,4 @@ Follow the DDD layer order from the plan:
57
57
  - **ALWAYS** run `npm test` after each TDD cycle to verify
58
58
  - **NEVER** skip tests for "simple" code
59
59
  - **NEVER** modify code outside the scope of the current ticket
60
- - **ALWAYS** verify implementation matches the approved spec. If a deviation is needed, document it in the sprint tracker's Active Session and ask for approval
60
+ - **ALWAYS** verify implementation matches the approved spec. If a deviation is needed, document it in the product tracker's Active Session and ask for approval
@@ -65,4 +65,4 @@ Follow the logical order from the plan:
65
65
  - **ALWAYS** run `npm test` after each TDD cycle to verify
66
66
  - **NEVER** skip tests for "simple" components
67
67
  - **NEVER** modify code outside the scope of the current ticket
68
- - **ALWAYS** verify implementation matches the approved spec. If a deviation is needed, document it in the sprint tracker's Active Session and ask for approval
68
+ - **ALWAYS** verify implementation matches the approved spec. If a deviation is needed, document it in the product tracker's Active Session and ask for approval
@@ -19,7 +19,7 @@
19
19
  "hooks": [
20
20
  {
21
21
  "type": "command",
22
- "command": "echo '{\"additionalContext\": \"Context was compacted. BEFORE doing anything else: read the sprint tracker Active Session section (docs/project_notes/sprint-*-tracker.md) for context recovery. Follow the Session Recovery protocol in CLAUDE.md.\"}'",
22
+ "command": "echo '{\"additionalContext\": \"Context was compacted. BEFORE doing anything else: read the product tracker Active Session section (docs/project_notes/product-tracker.md) for context recovery. Follow the Session Recovery protocol in CLAUDE.md.\"}'",
23
23
  "statusMessage": "Injecting recovery context..."
24
24
  }
25
25
  ]
@@ -23,7 +23,7 @@ description: "Handles bug discovery, triage, investigation, and resolution. Invo
23
23
  |----------|----------|------|
24
24
  | Critical | Immediate (<1h) | **C: Hotfix** — Confirm → Branch from main → Minimal fix → Test → Deploy → Document → Post-mortem |
25
25
  | High | Same day | **B: Standard** — Triage → Branch → Investigate → Fix (TDD) → Validate → Document → PR |
26
- | Medium | Within sprint | **A: Quick** — Triage → Investigate → Fix → Test → Document → Commit |
26
+ | Medium | Within cycle | **A: Quick** — Triage → Investigate → Fix → Test → Document → Commit |
27
27
  | Low | Backlog | **A: Quick** or escalate to backlog |
28
28
 
29
29
  **Escalate to `development-workflow`** when: >1 day work, architectural changes needed, or significant refactoring required.
@@ -99,7 +99,7 @@ Run `production-code-validator`. Ensure no debug code, proper error handling.
99
99
 
100
100
  | File | When |
101
101
  |------|------|
102
- | `sprint-X-tracker.md` | Bug being worked on (Active Session) |
102
+ | `product-tracker.md` | Bug being worked on (Active Session) |
103
103
  | `bugs.md` | Always |
104
104
  | `decisions.md` | If architectural decision made |
105
105
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: development-workflow
3
- description: "Orchestrates the complete development workflow for each task. Invoke with: 'start task B0.1', 'show sprint progress', 'next task', or 'init sprint N'."
3
+ description: "Orchestrates the complete development workflow for each feature. Invoke with: 'start task F001', 'show progress', 'next task', or 'add feature'."
4
4
  ---
5
5
 
6
6
  # Development Workflow Skill
@@ -8,7 +8,7 @@ description: "Orchestrates the complete development workflow for each task. Invo
8
8
  ## Quick Reference
9
9
 
10
10
  0. **Spec** — `spec-creator` drafts/updates specs → SPEC APPROVAL (Std/Cplx)
11
- 1. **Setup** — Branch, ticket, sprint tracker → TICKET APPROVAL (Std/Cplx)
11
+ 1. **Setup** — Branch, ticket, product tracker → TICKET APPROVAL (Std/Cplx)
12
12
  2. **Plan** — Planner agent writes implementation plan → PLAN APPROVAL (Std/Cplx)
13
13
  3. **Implement** — Developer agent, TDD, real-time spec sync
14
14
  4. **Finalize** — Tests/lint/build, `production-code-validator` → COMMIT APPROVAL
@@ -19,19 +19,19 @@ description: "Orchestrates the complete development workflow for each task. Invo
19
19
 
20
20
  ## Commands
21
21
 
22
- - `start task B0.1` — Begin working on a specific task
23
- - `next task` — Start the next pending task in current sprint
24
- - `show sprint progress` — View sprint completion status
25
- - `init sprint N` — Initialize a new sprint tracker
22
+ - `start task F001` — Begin working on a specific feature
23
+ - `next task` — Start the next pending feature from product tracker
24
+ - `show progress` — View feature completion status
25
+ - `add feature "description"` — Add a new feature to the product tracker
26
26
 
27
27
  ---
28
28
 
29
29
  ## On Skill Start
30
30
 
31
- 1. Read the sprint tracker (`docs/project_notes/sprint-X-tracker.md`) → **Active Session** section for context recovery
31
+ 1. Read the product tracker (`docs/project_notes/product-tracker.md`) → **Active Session** section for context recovery
32
32
  2. Read `CLAUDE.md` section 2 → **Autonomy Level**
33
33
  3. Read `docs/project_notes/key_facts.md` → **Branching Strategy**
34
- 4. If resuming an active task → continue from the step recorded in the tracker's Active Session
34
+ 4. If resuming an active feature → continue from the step recorded in the tracker's Active Session
35
35
 
36
36
  ---
37
37
 
@@ -47,7 +47,7 @@ Read the **Autonomy Level** from `CLAUDE.md` section 2.
47
47
  | Commit Approval (Step 4) | Required | Auto | Auto | Auto |
48
48
  | Merge Approval (Step 5) | Required | Required | Required | Auto |
49
49
 
50
- - **Auto** = proceed without asking; log in sprint tracker → "Auto-Approved Decisions" table
50
+ - **Auto** = proceed without asking; log in product tracker → "Auto-Approved Decisions" table
51
51
  - **Required** = ask user explicitly; do NOT continue without approval
52
52
  - **Quality gates always run** regardless of level (tests, lint, build, validators)
53
53
 
@@ -83,11 +83,11 @@ Ask user to classify complexity before starting. See `references/complexity-guid
83
83
 
84
84
  See `references/branching-strategy.md` for details.
85
85
 
86
- 1. Verify sprint tracker exists, no active task, dependencies met
87
- 2. Create feature branch: `feature/sprint<N>-<task-id>-<short-description>`
86
+ 1. Verify product tracker exists, no active feature, dependencies met
87
+ 2. Create feature branch: `feature/<feature-id>-<short-description>`
88
88
  3. **Std/Cplx:** Generate ticket from `references/ticket-template.md` → fill `## Spec` section
89
89
  4. **Complex:** Also review `decisions.md` for related ADRs
90
- 5. Update sprint tracker → Active Session: task, step `1/6 (Setup)`, branch, complexity
90
+ 5. Update product tracker → Active Session: feature, step `1/6 (Setup)`, branch, complexity
91
91
 
92
92
  **→ CHECKPOINT: Ticket Approval** (Std/Cplx only — Simple skips to Step 3)
93
93
 
@@ -95,7 +95,7 @@ See `references/branching-strategy.md` for details.
95
95
 
96
96
  ## Step 2: Plan (Standard/Complex only)
97
97
 
98
- 1. Use Task tool with planner agent (`backend-planner` for B*.*, `frontend-planner` for F*.*)
98
+ 1. Use Task tool with planner agent (`backend-planner` for backend features, `frontend-planner` for frontend features)
99
99
  2. Agent writes Implementation Plan into ticket's `## Implementation Plan`
100
100
  3. Update tracker: step `2/6 (Plan)`
101
101
 
@@ -115,7 +115,7 @@ See `references/branching-strategy.md` for details.
115
115
  - UI components → `docs/specs/ui-components.md` (MANDATORY)
116
116
  - Env variables → `.env.example` | ADRs → `decisions.md`
117
117
 
118
- **Spec deviation** → document in sprint tracker Active Session and ask for approval.
118
+ **Spec deviation** → document in product tracker Active Session and ask for approval.
119
119
 
120
120
  Update tracker: step `3/6 (Implement)`, context summary.
121
121
 
@@ -154,7 +154,7 @@ Update tracker: step `5/6 (Review)`
154
154
  ## Step 6: Complete
155
155
 
156
156
  1. Delete feature branch (local + remote)
157
- 2. Update sprint tracker: taskCompleted, add to Completion Log, update progress %
157
+ 2. Update product tracker: featuredone, add to Completion Log, update progress
158
158
  3. Record bugs in `bugs.md`, decisions in `decisions.md`
159
159
  4. Clear Active Session → "No active work"
160
160
 
@@ -177,18 +177,18 @@ Update tracker: step `5/6 (Review)`
177
177
  - `references/ticket-template.md` — Ticket format
178
178
  - `references/pr-template.md` — PR template
179
179
  - `references/branching-strategy.md` — Branching guide
180
- - `references/sprint-init-template.md` — New sprint initialization
180
+ - `references/add-feature-template.md` — Add feature to tracker
181
181
  - `references/complexity-guide.md` — Complexity classification
182
182
  - `references/workflow-example.md` — Full worked example
183
183
  - `references/failure-handling.md` — Recovery & rollbacks
184
184
 
185
185
  ## Constraints
186
186
 
187
- - **One task at a time** — never start a new task before completing current
187
+ - **One feature at a time** — never start a new feature before completing current
188
188
  - **TDD mandatory** — all code needs tests
189
189
  - **Type safety** — fully typed, no `any`
190
190
  - **English only** — all technical artifacts
191
191
  - **Memory first** — check `project_notes/` before changes
192
- - **Sprint tracker** — keep Active Session updated at every step
192
+ - **Product tracker** — keep Active Session updated at every step
193
193
  - **Correct agents** — Backend → `backend-planner` + `backend-developer`, Frontend → `frontend-planner` + `frontend-developer`
194
194
  - **Correct base branch** — check `key_facts.md` before creating branches
@@ -0,0 +1,16 @@
1
+ # Add Feature Template
2
+
3
+ Use this template when running `add feature "description"`.
4
+
5
+ ## How to Add a Feature
6
+
7
+ 1. Read the product tracker (`docs/project_notes/product-tracker.md`)
8
+ 2. Determine the next feature ID (F001, F002, ...)
9
+ 3. Add a row to the Features table
10
+ 4. Use `start task F001` to begin working on it
11
+
12
+ ## Feature ID Convention
13
+
14
+ - **Format:** F001, F002, F003... (sequential)
15
+ - **Type:** backend, frontend, fullstack, infra
16
+ - **Branch:** `feature/<id>-<short-desc>` (e.g., `feature/F001-external-api`)
@@ -11,7 +11,7 @@ main ────●────●────●────●────●
11
11
  \ / \ /
12
12
  \/ \/
13
13
  feature/ feature/
14
- B1.1 B1.2
14
+ F001 F002
15
15
  tag: v0.1.0
16
16
  ```
17
17