create-sdd-project 0.1.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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +204 -0
  3. package/bin/cli.js +44 -0
  4. package/lib/config.js +106 -0
  5. package/lib/generator.js +313 -0
  6. package/lib/wizard.js +224 -0
  7. package/package.json +41 -0
  8. package/template/.claude/agents/backend-developer.md +60 -0
  9. package/template/.claude/agents/backend-planner.md +65 -0
  10. package/template/.claude/agents/code-review-specialist.md +65 -0
  11. package/template/.claude/agents/database-architect.md +68 -0
  12. package/template/.claude/agents/frontend-developer.md +68 -0
  13. package/template/.claude/agents/frontend-planner.md +65 -0
  14. package/template/.claude/agents/production-code-validator.md +102 -0
  15. package/template/.claude/agents/qa-engineer.md +70 -0
  16. package/template/.claude/agents/spec-creator.md +72 -0
  17. package/template/.claude/commands/.gitkeep +0 -0
  18. package/template/.claude/hooks/quick-scan.sh +111 -0
  19. package/template/.claude/settings.json +29 -0
  20. package/template/.claude/skills/bug-workflow/SKILL.md +108 -0
  21. package/template/.claude/skills/development-workflow/SKILL.md +194 -0
  22. package/template/.claude/skills/development-workflow/references/branching-strategy.md +59 -0
  23. package/template/.claude/skills/development-workflow/references/complexity-guide.md +89 -0
  24. package/template/.claude/skills/development-workflow/references/failure-handling.md +174 -0
  25. package/template/.claude/skills/development-workflow/references/pr-template.md +80 -0
  26. package/template/.claude/skills/development-workflow/references/sprint-init-template.md +82 -0
  27. package/template/.claude/skills/development-workflow/references/ticket-template.md +71 -0
  28. package/template/.claude/skills/development-workflow/references/workflow-example.md +87 -0
  29. package/template/.claude/skills/project-memory/SKILL.md +152 -0
  30. package/template/.claude/skills/project-memory/references/bugs_template.md +41 -0
  31. package/template/.claude/skills/project-memory/references/decisions_template.md +67 -0
  32. package/template/.claude/skills/project-memory/references/key_facts_template.md +81 -0
  33. package/template/.env.example +17 -0
  34. package/template/.gemini/agents/backend-developer.md +31 -0
  35. package/template/.gemini/agents/backend-planner.md +34 -0
  36. package/template/.gemini/agents/code-review-specialist.md +44 -0
  37. package/template/.gemini/agents/database-architect.md +35 -0
  38. package/template/.gemini/agents/frontend-developer.md +31 -0
  39. package/template/.gemini/agents/frontend-planner.md +34 -0
  40. package/template/.gemini/agents/production-code-validator.md +32 -0
  41. package/template/.gemini/agents/qa-engineer.md +23 -0
  42. package/template/.gemini/agents/spec-creator.md +24 -0
  43. package/template/.gemini/settings.json +5 -0
  44. package/template/.gemini/styles/default.md +19 -0
  45. package/template/AGENTS.md +67 -0
  46. package/template/CLAUDE.md +19 -0
  47. package/template/GEMINI.md +10 -0
  48. package/template/ai-specs/specs/backend-standards.mdc +214 -0
  49. package/template/ai-specs/specs/base-standards.mdc +157 -0
  50. package/template/ai-specs/specs/documentation-standards.mdc +68 -0
  51. package/template/ai-specs/specs/frontend-standards.mdc +226 -0
  52. package/template/docs/project_notes/bugs.md +18 -0
  53. package/template/docs/project_notes/decisions.md +18 -0
  54. package/template/docs/project_notes/key_facts.md +52 -0
  55. package/template/docs/project_notes/pending-improvements.md +50 -0
  56. package/template/docs/project_notes/sprint-0-tracker.md +66 -0
  57. package/template/docs/specs/api-spec.yaml +114 -0
  58. package/template/docs/specs/ui-components.md +77 -0
  59. package/template/docs/tickets/.gitkeep +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FiveGuays
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,204 @@
1
+ # SDD DevFlow
2
+
3
+ **Spec-Driven Development workflow template for AI-assisted coding.**
4
+
5
+ A development methodology designed for Claude Code and Gemini that combines specialized AI agents, workflow orchestration with human checkpoints, and institutional memory. Built for creating robust, maintainable, and scalable TypeScript projects.
6
+
7
+ ## What is SDD?
8
+
9
+ SDD DevFlow combines three proven practices:
10
+
11
+ 1. **Spec-Driven Development** — Write specifications before code. Specs are the contract between planning and implementation.
12
+ 2. **Test-Driven Development** — Red-Green-Refactor cycle for every feature. Tests define expected behavior before implementation.
13
+ 3. **Human-in-the-Loop** — Strategic checkpoints (spec, ticket, plan, commit, merge) with configurable autonomy levels that reduce human intervention as trust increases.
14
+
15
+ ## What's Inside
16
+
17
+ ### 9 Specialized Agents
18
+
19
+ | Agent | Role | Step |
20
+ |-------|------|------|
21
+ | `spec-creator` | Draft/update specifications | 0 |
22
+ | `backend-planner` / `frontend-planner` | Create implementation plans | 2 |
23
+ | `backend-developer` / `frontend-developer` | TDD implementation | 3 |
24
+ | `production-code-validator` | Pre-commit quality scan | 4 |
25
+ | `code-review-specialist` | Pre-merge code review | 5 |
26
+ | `qa-engineer` | Edge cases, spec verification | 5 |
27
+ | `database-architect` | Schema design, optimization | Any |
28
+
29
+ ### Workflow (Steps 0–6)
30
+
31
+ ```
32
+ 0. SPEC → spec-creator drafts specs → Spec Approval (Std/Cplx)
33
+ 1. SETUP → Branch, ticket, sprint tracker → Ticket Approval (Std/Cplx)
34
+ 2. PLAN → Planner creates implementation plan → Plan Approval (Std/Cplx)
35
+ 3. IMPLEMENT → Developer agent, TDD
36
+ 4. FINALIZE → Tests/lint/build, validator → Commit Approval
37
+ 5. REVIEW → PR, code review, QA → Merge Approval
38
+ 6. COMPLETE → Clean up, update tracker
39
+ ```
40
+
41
+ **Step flow by complexity:**
42
+ - **Simple**: 1 → 3 → 4 → 5 → 6
43
+ - **Standard**: 0 → 1 → 2 → 3 → 4 → 5 (+QA) → 6
44
+ - **Complex**: 0 → 1 (+ADR) → 2 → 3 → 4 → 5 (+QA) → 6
45
+
46
+ ### 3 Complexity Tiers
47
+
48
+ | Tier | Spec | Ticket | Plan | QA |
49
+ |------|:----:|:------:|:----:|:--:|
50
+ | Simple | Skip | Skip | Skip | Skip |
51
+ | Standard | Yes | Yes | Yes | Yes |
52
+ | Complex | Yes | Yes + ADR | Yes | Yes |
53
+
54
+ ### 4 Autonomy Levels
55
+
56
+ Control how many human approval checkpoints are active:
57
+
58
+ | Level | Name | Human Checkpoints | Best For |
59
+ |-------|------|-------------------|----------|
60
+ | L1 | Full Control | All 5 | First sprint, learning SDD |
61
+ | L2 | Trusted | Plan + Merge | Normal development **(default)** |
62
+ | L3 | Autopilot | Merge only | Well-defined, repetitive tasks |
63
+ | L4 | Full Auto | None (CI/CD gates only) | Bulk simple tasks |
64
+
65
+ Quality gates (tests, lint, build, validators) **always run** regardless of level.
66
+
67
+ ### Branching Strategy
68
+
69
+ Configurable per-project in `key_facts.md`:
70
+
71
+ - **GitHub Flow** (default): `main` + `feature/*` + `hotfix/*`. Best for MVPs.
72
+ - **GitFlow** (scaled): `main` + `develop` + `feature/*` + `release/*` + `hotfix/*`. For larger projects.
73
+
74
+ ### Project Memory
75
+
76
+ Tracks institutional knowledge across sessions in `docs/project_notes/`:
77
+
78
+ - **sprint-X-tracker.md** — Sprint progress + Active Session (context recovery after compaction)
79
+ - **bugs.md** — Bug log with solutions and prevention notes
80
+ - **decisions.md** — Architectural Decision Records (ADRs)
81
+ - **key_facts.md** — Project configuration, ports, URLs, branching strategy
82
+
83
+ ### Automated Hooks (Claude Code)
84
+
85
+ - **Quick Scan** — After developer agents finish, a fast grep-based scan (~2s, no API calls) checks for debug code, secrets, and TODOs. Critical issues block; warnings pass through.
86
+ - **Compaction Recovery** — After context compaction, injects a reminder to read the sprint tracker for context recovery.
87
+ - **Notifications** — Personal notification hooks (macOS/Linux) in `.claude/settings.local.json`.
88
+
89
+ ### Multi-Tool Support
90
+
91
+ - **Claude Code**: Full support with agents, skills, hooks, and settings (`.claude/`)
92
+ - **Gemini**: Adapted agent format (`.gemini/`), same methodology via `ai-specs/specs/`
93
+ - **Other tools**: `AGENTS.md` provides universal instructions readable by 21+ AI coding tools
94
+
95
+ ## Quick Start
96
+
97
+ ### 1. Copy the template
98
+
99
+ ```bash
100
+ cp -r template/ /path/to/your-project/
101
+ ```
102
+
103
+ ### 2. Configure for your project
104
+
105
+ Look for `<!-- CONFIG: ... -->` comments in these files:
106
+
107
+ | File | What to configure |
108
+ |------|-------------------|
109
+ | `CLAUDE.md` / `GEMINI.md` | Autonomy level (1-4) |
110
+ | `ai-specs/specs/backend-standards.mdc` | Backend tech stack |
111
+ | `ai-specs/specs/frontend-standards.mdc` | Frontend tech stack |
112
+ | `docs/project_notes/key_facts.md` | Project name, ports, URLs, branching strategy |
113
+ | `docs/specs/api-spec.yaml` | Server URLs |
114
+ | `AGENTS.md` | Monorepo layout |
115
+
116
+ ### 3. Initialize and start
117
+
118
+ ```
119
+ init sprint 0
120
+ start task B0.1
121
+ ```
122
+
123
+ The workflow skill will guide you through each step with checkpoints based on your autonomy level.
124
+
125
+ ## Template Structure
126
+
127
+ ```
128
+ project/
129
+ ├── AGENTS.md # Universal AI instructions (all tools)
130
+ ├── CLAUDE.md # Claude Code config (autonomy, recovery)
131
+ ├── GEMINI.md # Gemini config (autonomy)
132
+ ├── .env.example # Environment variables template
133
+ ├── .gitignore # Git ignore with secrets protection
134
+
135
+ ├── .claude/
136
+ │ ├── agents/ # 9 specialized agents
137
+ │ ├── skills/
138
+ │ │ ├── development-workflow/ # Main task workflow (Steps 0-6)
139
+ │ │ │ └── references/ # Templates, guides, examples
140
+ │ │ ├── bug-workflow/ # Bug triage and resolution
141
+ │ │ └── project-memory/ # Memory system setup
142
+ │ ├── hooks/quick-scan.sh # Post-developer quality scan
143
+ │ ├── settings.json # Shared hooks (git-tracked)
144
+ │ └── settings.local.json # Personal hooks (gitignored)
145
+
146
+ ├── .gemini/
147
+ │ ├── agents/ # 9 agents (Gemini format)
148
+ │ ├── settings.json # Gemini configuration
149
+ │ └── styles/default.md # Response style
150
+
151
+ ├── ai-specs/specs/
152
+ │ ├── base-standards.mdc # Constitution + methodology
153
+ │ ├── backend-standards.mdc # Backend patterns (DDD, Express, Prisma)
154
+ │ ├── frontend-standards.mdc # Frontend patterns (Next.js, Tailwind, Radix)
155
+ │ └── documentation-standards.mdc # Documentation update rules
156
+
157
+ └── docs/
158
+ ├── project_notes/ # Project memory
159
+ │ ├── sprint-0-tracker.md # Sprint tracker template
160
+ │ ├── key_facts.md # Project configuration
161
+ │ ├── bugs.md # Bug log
162
+ │ └── decisions.md # ADRs
163
+ ├── specs/
164
+ │ ├── api-spec.yaml # OpenAPI spec (backend)
165
+ │ └── ui-components.md # Component spec (frontend)
166
+ └── tickets/ # Task tickets (generated by workflow)
167
+ ```
168
+
169
+ ## Default Tech Stack
170
+
171
+ The template defaults to (configurable via `<!-- CONFIG -->` comments):
172
+
173
+ - **Backend**: Node.js + Express + Prisma + PostgreSQL
174
+ - **Frontend**: Next.js (App Router) + Tailwind CSS + Radix UI + Zustand
175
+ - **Shared Types**: Zod schemas in `shared/` workspace → `z.infer<>` for TypeScript types
176
+ - **Testing**: Jest (unit) + Playwright (e2e)
177
+ - **Methodology**: TDD + DDD + Spec-Driven Development
178
+
179
+ ## Constitution (Immutable Principles)
180
+
181
+ These 6 principles apply to ALL tasks, ALL agents, ALL complexity levels:
182
+
183
+ 1. **Spec First** — No implementation without an approved specification
184
+ 2. **Small Tasks** — Work in baby steps, one at a time
185
+ 3. **Test-Driven Development** — Write tests before implementation
186
+ 4. **Type Safety** — Strict TypeScript, no `any`, runtime validation with Zod
187
+ 5. **English Only** — All code, comments, docs, commits, and tickets in English
188
+ 6. **Reuse Over Recreate** — Always check existing code before proposing new files
189
+
190
+ ## Prerequisites
191
+
192
+ - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) and/or [Gemini](https://gemini.google.com/)
193
+ - Node.js 18+
194
+ - `jq` (for quick-scan hook): `brew install jq` (macOS) or `apt install jq` (Linux)
195
+
196
+ ## Roadmap
197
+
198
+ - **Agent Teams**: Parallel execution of independent tasks (waiting for Claude Code Agent Teams to stabilize)
199
+ - **PM Agent + L5 Autonomous**: AI-driven sprint orchestration with human review at sprint boundaries
200
+ - **Setup Script + npx**: Interactive installer (`npx create-sdd-project`) for automated setup
201
+
202
+ ## License
203
+
204
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const { runWizard, buildDefaultConfig } = require('../lib/wizard');
6
+ const { generate } = require('../lib/generator');
7
+
8
+ const args = process.argv.slice(2);
9
+ const projectName = args.find((a) => !a.startsWith('-'));
10
+ const useDefaults = args.includes('--yes') || args.includes('-y');
11
+
12
+ async function main() {
13
+ let config;
14
+
15
+ if (useDefaults) {
16
+ if (!projectName) {
17
+ console.error('Error: Project name required with --yes flag.');
18
+ console.error('Usage: create-sdd-project <project-name> --yes');
19
+ process.exit(1);
20
+ }
21
+ config = buildDefaultConfig(projectName);
22
+ console.log(`\nCreating SDD DevFlow project with defaults in ./${projectName}...\n`);
23
+ } else {
24
+ config = await runWizard(projectName);
25
+ console.log(`\nCreating SDD DevFlow project in ${config.projectDir}...\n`);
26
+ }
27
+
28
+ // Check if destination already exists
29
+ if (fs.existsSync(config.projectDir)) {
30
+ const entries = fs.readdirSync(config.projectDir);
31
+ if (entries.length > 0) {
32
+ console.error(`Error: Directory ${config.projectDir} is not empty.`);
33
+ console.error('Please choose a different directory or remove existing files.');
34
+ process.exit(1);
35
+ }
36
+ }
37
+
38
+ generate(config);
39
+ }
40
+
41
+ main().catch((err) => {
42
+ console.error('\nError:', err.message);
43
+ process.exit(1);
44
+ });
package/lib/config.js ADDED
@@ -0,0 +1,106 @@
1
+ 'use strict';
2
+
3
+ const DEFAULTS = {
4
+ projectName: '',
5
+ projectDir: '',
6
+ description: '',
7
+ businessContext: '',
8
+ projectType: 'fullstack', // 'fullstack' | 'backend' | 'frontend'
9
+ backendStack: 'express-prisma-pg',
10
+ frontendStack: 'nextjs-tailwind-radix',
11
+ aiTools: 'both', // 'both' | 'claude' | 'gemini'
12
+ autonomyLevel: 2,
13
+ branching: 'github-flow',
14
+ backendPort: 3010,
15
+ frontendPort: 3000,
16
+ dbPort: 5432,
17
+ };
18
+
19
+ const PROJECT_TYPES = [
20
+ { key: 'fullstack', label: 'Backend + Frontend (monorepo)', default: true },
21
+ { key: 'backend', label: 'Backend only' },
22
+ { key: 'frontend', label: 'Frontend only' },
23
+ ];
24
+
25
+ const BACKEND_STACKS = [
26
+ {
27
+ key: 'express-prisma-pg',
28
+ label: 'Node.js + Express + Prisma + PostgreSQL',
29
+ default: true,
30
+ db: 'PostgreSQL',
31
+ orm: 'Prisma',
32
+ framework: 'Express',
33
+ runtime: 'Node.js',
34
+ dbPort: 5432,
35
+ databaseUrl: 'postgresql://user:password@localhost:5432/dbname',
36
+ needsStandardsUpdate: false,
37
+ },
38
+ {
39
+ key: 'express-mongo-mongoose',
40
+ label: 'Node.js + Express + MongoDB + Mongoose',
41
+ db: 'MongoDB',
42
+ orm: 'Mongoose',
43
+ framework: 'Express',
44
+ runtime: 'Node.js',
45
+ dbPort: 27017,
46
+ databaseUrl: 'mongodb://localhost:27017/dbname',
47
+ needsStandardsUpdate: true,
48
+ },
49
+ {
50
+ key: 'custom',
51
+ label: 'Custom (enter your own)',
52
+ needsStandardsUpdate: true,
53
+ },
54
+ ];
55
+
56
+ const FRONTEND_STACKS = [
57
+ {
58
+ key: 'nextjs-tailwind-radix',
59
+ label: 'Next.js + Tailwind CSS + Radix UI + Zustand',
60
+ default: true,
61
+ framework: 'Next.js (App Router)',
62
+ styling: 'Tailwind CSS',
63
+ components: 'Radix UI',
64
+ state: 'Zustand',
65
+ needsStandardsUpdate: false,
66
+ },
67
+ {
68
+ key: 'custom',
69
+ label: 'Custom (enter your own)',
70
+ needsStandardsUpdate: true,
71
+ },
72
+ ];
73
+
74
+ const AI_TOOLS = [
75
+ { key: 'both', label: 'Claude Code + Gemini', default: true },
76
+ { key: 'claude', label: 'Claude Code only' },
77
+ { key: 'gemini', label: 'Gemini only' },
78
+ ];
79
+
80
+ const AUTONOMY_LEVELS = [
81
+ { level: 1, name: 'Full Control', desc: 'Human approves every checkpoint (first sprint, learning SDD)' },
82
+ { level: 2, name: 'Trusted', desc: 'Human reviews plans + merges only (default, normal development)', default: true },
83
+ { level: 3, name: 'Autopilot', desc: 'Human only approves merges (well-defined, repetitive tasks)' },
84
+ { level: 4, name: 'Full Auto', desc: 'No human checkpoints, CI/CD gates only (bulk simple tasks)' },
85
+ ];
86
+
87
+ const BRANCHING_STRATEGIES = [
88
+ { key: 'github-flow', label: 'GitHub Flow', desc: 'main + feature branches (recommended for MVPs)', default: true },
89
+ { key: 'gitflow', label: 'GitFlow', desc: 'main + develop + feature/release/hotfix branches (larger projects)' },
90
+ ];
91
+
92
+ // Agent files categorized by scope
93
+ const FRONTEND_AGENTS = ['frontend-developer.md', 'frontend-planner.md'];
94
+ const BACKEND_AGENTS = ['backend-developer.md', 'backend-planner.md', 'database-architect.md'];
95
+
96
+ module.exports = {
97
+ DEFAULTS,
98
+ PROJECT_TYPES,
99
+ BACKEND_STACKS,
100
+ FRONTEND_STACKS,
101
+ AI_TOOLS,
102
+ AUTONOMY_LEVELS,
103
+ BRANCHING_STRATEGIES,
104
+ FRONTEND_AGENTS,
105
+ BACKEND_AGENTS,
106
+ };
@@ -0,0 +1,313 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const {
6
+ BACKEND_STACKS,
7
+ FRONTEND_STACKS,
8
+ AUTONOMY_LEVELS,
9
+ FRONTEND_AGENTS,
10
+ BACKEND_AGENTS,
11
+ } = require('./config');
12
+
13
+ function generate(config) {
14
+ const templateDir = path.join(__dirname, '..', 'template');
15
+ const dest = config.projectDir;
16
+
17
+ // 1. Copy entire template
18
+ step('Copying template files');
19
+ fs.cpSync(templateDir, dest, { recursive: true });
20
+
21
+ // 2. Configure key_facts.md
22
+ step(`Configuring project: ${config.projectName}`);
23
+ updateKeyFacts(dest, config);
24
+
25
+ // 3. Update tech stack references
26
+ if (config.projectType !== 'frontend') {
27
+ const bPreset = config.backendPreset || BACKEND_STACKS[0];
28
+ step(`Setting backend: ${bPreset.label || config.customBackend || 'Custom'}`);
29
+ updateBackendConfig(dest, config);
30
+ }
31
+ if (config.projectType !== 'backend') {
32
+ const fPreset = config.frontendPreset || FRONTEND_STACKS[0];
33
+ step(`Setting frontend: ${fPreset.label || config.customFrontend || 'Custom'}`);
34
+ }
35
+
36
+ // 4. Set autonomy level
37
+ step(`Setting autonomy level: L${config.autonomyLevel} (${config.autonomyName})`);
38
+ updateAutonomy(dest, config);
39
+
40
+ // 5. Set branching strategy
41
+ step(`Setting branching: ${config.branching}`);
42
+ updateBranching(dest, config);
43
+
44
+ // 6. Set sprint dates
45
+ step('Setting sprint dates to today');
46
+ updateSprintDates(dest);
47
+
48
+ // 7. Remove agents/specs based on project type
49
+ if (config.projectType === 'backend') {
50
+ step('Removing frontend agents (backend only)');
51
+ removeFrontendFiles(dest, config);
52
+ } else if (config.projectType === 'frontend') {
53
+ step('Removing backend agents (frontend only)');
54
+ removeBackendFiles(dest, config);
55
+ }
56
+
57
+ // 8. Remove AI tool config if single tool selected
58
+ if (config.aiTools === 'claude') {
59
+ step('Removing Gemini config (Claude only)');
60
+ fs.rmSync(path.join(dest, '.gemini'), { recursive: true, force: true });
61
+ safeDelete(path.join(dest, 'GEMINI.md'));
62
+ } else if (config.aiTools === 'gemini') {
63
+ step('Removing Claude config (Gemini only)');
64
+ fs.rmSync(path.join(dest, '.claude'), { recursive: true, force: true });
65
+ safeDelete(path.join(dest, 'CLAUDE.md'));
66
+ }
67
+
68
+ // Show notes
69
+ const notes = collectNotes(config);
70
+ if (notes.length > 0) {
71
+ console.log('');
72
+ notes.forEach((n) => console.log(` 📝 ${n}`));
73
+ }
74
+
75
+ // Done
76
+ console.log(`\nDone! Next steps:`);
77
+ console.log(` cd ${path.relative(process.cwd(), dest)}`);
78
+ console.log(` git init && git add -A && git commit -m "chore: initialize SDD DevFlow project"`);
79
+ console.log(` # Open in your AI coding tool and run: init sprint 0\n`);
80
+ }
81
+
82
+ // --- Helpers ---
83
+
84
+ function step(msg) {
85
+ console.log(` ✓ ${msg}`);
86
+ }
87
+
88
+ function safeDelete(filePath) {
89
+ try {
90
+ fs.unlinkSync(filePath);
91
+ } catch {
92
+ // ignore if not found
93
+ }
94
+ }
95
+
96
+ function replaceInFile(filePath, replacements) {
97
+ if (!fs.existsSync(filePath)) return;
98
+ let content = fs.readFileSync(filePath, 'utf8');
99
+ for (const [search, replace] of replacements) {
100
+ if (search instanceof RegExp) {
101
+ content = content.replace(search, replace);
102
+ } else {
103
+ content = content.split(search).join(replace);
104
+ }
105
+ }
106
+ fs.writeFileSync(filePath, content, 'utf8');
107
+ }
108
+
109
+ function updateKeyFacts(dest, config) {
110
+ const file = path.join(dest, 'docs', 'project_notes', 'key_facts.md');
111
+ const bPreset = config.backendPreset || BACKEND_STACKS[0];
112
+ const fPreset = config.frontendPreset || FRONTEND_STACKS[0];
113
+
114
+ const replacements = [
115
+ ['[Your project name]', config.projectName],
116
+ ];
117
+
118
+ // Branching
119
+ // The template has: github-flow <!-- Options: ... -->
120
+ replacements.push([
121
+ /github-flow <!-- Options:.*?-->/,
122
+ `${config.branching} <!-- Options: github-flow | gitflow — See .claude/skills/development-workflow/references/branching-strategy.md -->`,
123
+ ]);
124
+
125
+ // Technology Stack
126
+ if (config.projectType !== 'frontend' && bPreset.key !== 'custom') {
127
+ replacements.push(['[Framework, runtime, version]', `${bPreset.framework}, ${bPreset.runtime}`]);
128
+ replacements.push(['[Type, host, port]', `${bPreset.db}, localhost, ${bPreset.dbPort}`]);
129
+ replacements.push(['[Name, version]', bPreset.orm]);
130
+ } else if (config.projectType !== 'frontend' && config.customBackend) {
131
+ replacements.push(['[Framework, runtime, version]', config.customBackend]);
132
+ }
133
+
134
+ if (config.projectType !== 'backend' && fPreset.key !== 'custom') {
135
+ replacements.push(['[Framework, version]', `${fPreset.framework}, ${fPreset.styling}, ${fPreset.components}, ${fPreset.state}`]);
136
+ } else if (config.projectType !== 'backend' && config.customFrontend) {
137
+ replacements.push(['[Framework, version]', config.customFrontend]);
138
+ }
139
+
140
+ // Ports
141
+ if (config.projectType !== 'frontend') {
142
+ replacements.push(['[e.g., 3010]', String(config.backendPort)]);
143
+ replacements.push(['[e.g., 5432]', bPreset.key !== 'custom' ? String(bPreset.dbPort) : '[e.g., 5432]']);
144
+ replacements.push(['[e.g., http://localhost:3010/api]', `http://localhost:${config.backendPort}/api`]);
145
+ }
146
+ if (config.projectType !== 'backend') {
147
+ replacements.push(['[e.g., 3000]', String(config.frontendPort || 3000)]);
148
+ }
149
+
150
+ replaceInFile(file, replacements);
151
+
152
+ // Add business context section if provided
153
+ if (config.businessContext) {
154
+ let content = fs.readFileSync(file, 'utf8');
155
+ const contextSection = `\n## Project Information\n\n${config.businessContext}\n`;
156
+ // Insert before ## Technology Stack
157
+ content = content.replace('## Technology Stack', `${contextSection}\n## Technology Stack`);
158
+ // Add description if provided
159
+ if (config.description) {
160
+ content = content.replace(
161
+ `- **Project Name**: ${config.projectName}`,
162
+ `- **Project Name**: ${config.projectName}\n- **Description**: ${config.description}`
163
+ );
164
+ }
165
+ fs.writeFileSync(file, content, 'utf8');
166
+ } else if (config.description) {
167
+ replaceInFile(file, [
168
+ [`- **Project Name**: ${config.projectName}`, `- **Project Name**: ${config.projectName}\n- **Description**: ${config.description}`],
169
+ ]);
170
+ }
171
+ }
172
+
173
+ function updateBackendConfig(dest, config) {
174
+ const bPreset = config.backendPreset || BACKEND_STACKS[0];
175
+
176
+ // .env.example
177
+ const envFile = path.join(dest, '.env.example');
178
+ const replacements = [];
179
+
180
+ if (config.backendPort !== 3010) {
181
+ replacements.push(['PORT=3010', `PORT=${config.backendPort}`]);
182
+ replacements.push([
183
+ 'NEXT_PUBLIC_API_URL=http://localhost:3010/api',
184
+ `NEXT_PUBLIC_API_URL=http://localhost:${config.backendPort}/api`,
185
+ ]);
186
+ }
187
+
188
+ if (bPreset.databaseUrl) {
189
+ replacements.push([
190
+ 'DATABASE_URL=postgresql://user:password@localhost:5432/dbname',
191
+ `DATABASE_URL=${bPreset.databaseUrl}`,
192
+ ]);
193
+ }
194
+
195
+ if (replacements.length > 0) {
196
+ replaceInFile(envFile, replacements);
197
+ }
198
+
199
+ // api-spec.yaml
200
+ const apiSpec = path.join(dest, 'docs', 'specs', 'api-spec.yaml');
201
+ const apiReplacements = [
202
+ ['title: Project API', `title: ${config.projectName} API`],
203
+ ];
204
+ if (config.backendPort !== 3010) {
205
+ apiReplacements.push([
206
+ 'http://localhost:3010/api',
207
+ `http://localhost:${config.backendPort}/api`,
208
+ ]);
209
+ }
210
+ replaceInFile(apiSpec, apiReplacements);
211
+ }
212
+
213
+ function updateAutonomy(dest, config) {
214
+ const levelInfo = AUTONOMY_LEVELS.find((l) => l.level === config.autonomyLevel);
215
+ const newLine = `**Autonomy Level: ${config.autonomyLevel} (${levelInfo.name})**`;
216
+
217
+ // CLAUDE.md
218
+ replaceInFile(path.join(dest, 'CLAUDE.md'), [
219
+ [/\*\*Autonomy Level: \d+ \([^)]+\)\*\*/, newLine],
220
+ ]);
221
+
222
+ // GEMINI.md
223
+ replaceInFile(path.join(dest, 'GEMINI.md'), [
224
+ [/\*\*Autonomy Level: \d+ \([^)]+\)\*\*/, newLine],
225
+ ]);
226
+ }
227
+
228
+ function updateBranching(dest, config) {
229
+ // key_facts.md is already handled in updateKeyFacts
230
+ // Nothing else to update — branching is read from key_facts.md at runtime
231
+ }
232
+
233
+ function updateSprintDates(dest) {
234
+ const file = path.join(dest, 'docs', 'project_notes', 'sprint-0-tracker.md');
235
+ const today = new Date().toISOString().split('T')[0];
236
+ // Calculate 2-week sprint end
237
+ const endDate = new Date();
238
+ endDate.setDate(endDate.getDate() + 14);
239
+ const end = endDate.toISOString().split('T')[0];
240
+
241
+ replaceInFile(file, [
242
+ [/\[YYYY-MM-DD\] to \[YYYY-MM-DD\]/, `${today} to ${end}`],
243
+ ]);
244
+ }
245
+
246
+ function removeFrontendFiles(dest, config) {
247
+ // Remove frontend agents
248
+ for (const agent of FRONTEND_AGENTS) {
249
+ safeDelete(path.join(dest, '.claude', 'agents', agent));
250
+ safeDelete(path.join(dest, '.gemini', 'agents', agent));
251
+ }
252
+ // Remove frontend spec
253
+ safeDelete(path.join(dest, 'docs', 'specs', 'ui-components.md'));
254
+
255
+ // Remove frontend from .env.example
256
+ replaceInFile(path.join(dest, '.env.example'), [
257
+ [/\n# Frontend\nNEXT_PUBLIC_API_URL=.*\n/, '\n'],
258
+ ]);
259
+
260
+ // Remove frontend from AGENTS.md project structure
261
+ replaceInFile(path.join(dest, 'AGENTS.md'), [
262
+ ['├── frontend/ ← Frontend (has its own package.json)\n', ''],
263
+ ]);
264
+
265
+ // Remove frontend tasks from sprint tracker
266
+ const trackerFile = path.join(dest, 'docs', 'project_notes', 'sprint-0-tracker.md');
267
+ replaceInFile(trackerFile, [
268
+ [/\n### Frontend\n\n\|.*\n\|.*\n\|.*\n/, '\n'],
269
+ ]);
270
+ }
271
+
272
+ function removeBackendFiles(dest, config) {
273
+ // Remove backend agents + database-architect
274
+ for (const agent of BACKEND_AGENTS) {
275
+ safeDelete(path.join(dest, '.claude', 'agents', agent));
276
+ safeDelete(path.join(dest, '.gemini', 'agents', agent));
277
+ }
278
+ // Remove backend spec
279
+ safeDelete(path.join(dest, 'docs', 'specs', 'api-spec.yaml'));
280
+
281
+ // Remove backend from .env.example
282
+ replaceInFile(path.join(dest, '.env.example'), [
283
+ [/# Backend\nNODE_ENV=.*\nPORT=.*\nDATABASE_URL=.*\n\n/, ''],
284
+ ]);
285
+
286
+ // Remove backend from AGENTS.md project structure
287
+ replaceInFile(path.join(dest, 'AGENTS.md'), [
288
+ ['├── backend/ ← Backend (has its own package.json)\n', ''],
289
+ ]);
290
+
291
+ // Remove backend tasks from sprint tracker
292
+ const trackerFile = path.join(dest, 'docs', 'project_notes', 'sprint-0-tracker.md');
293
+ replaceInFile(trackerFile, [
294
+ [/\n### Backend\n\n\|.*\n\|.*\n\|.*\n/, '\n'],
295
+ ]);
296
+ }
297
+
298
+ function collectNotes(config) {
299
+ const notes = [];
300
+ const bPreset = config.backendPreset;
301
+ const fPreset = config.frontendPreset;
302
+
303
+ if (bPreset && bPreset.needsStandardsUpdate) {
304
+ notes.push('Update ai-specs/specs/backend-standards.mdc with your backend stack patterns.');
305
+ }
306
+ if (fPreset && fPreset.needsStandardsUpdate) {
307
+ notes.push('Update ai-specs/specs/frontend-standards.mdc with your frontend stack patterns.');
308
+ }
309
+
310
+ return notes;
311
+ }
312
+
313
+ module.exports = { generate };