buildflow-dev 1.0.0 → 1.0.2

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.
@@ -1,239 +1,614 @@
1
- import chalk from 'chalk'
2
- import ora from 'ora'
3
- import { prompt } from 'enquirer'
4
- import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs'
5
- import { join } from 'path'
6
- import { execSync } from 'child_process'
7
- import { run as runInstall } from './install.js'
8
-
9
- function detectProjectInfo() {
10
- const cwd = process.cwd()
11
- const info = {
12
- appName: 'my-project',
13
- projectType: 'greenfield',
14
- framework: 'none',
15
- hasGit: existsSync(join(cwd, '.git')),
16
- hasTests: false,
17
- hasSrc: existsSync(join(cwd, 'src')),
18
- language: 'unknown',
19
- }
20
-
21
- const pkgPath = join(cwd, 'package.json')
22
- if (existsSync(pkgPath)) {
23
- try {
24
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
25
- info.appName = pkg.name || cwd.split('/').pop()
26
- info.language = 'javascript'
27
- info.projectType = 'existing'
28
-
29
- const deps = { ...pkg.dependencies, ...pkg.devDependencies }
30
- if (deps?.next) info.framework = 'Next.js'
31
- else if (deps?.react) info.framework = 'React'
32
- else if (deps?.vue) info.framework = 'Vue'
33
- else if (deps?.svelte) info.framework = 'Svelte'
34
- else if (deps?.express) info.framework = 'Express'
35
- else if (deps?.fastify) info.framework = 'Fastify'
36
- else if (deps?.nestjs) info.framework = 'NestJS'
37
- else info.framework = 'Node.js'
38
-
39
- info.hasTests = !!(deps?.jest || deps?.vitest || deps?.mocha || deps?.['@playwright/test'])
40
- } catch {}
41
- }
42
-
43
- if (existsSync(join(cwd, 'requirements.txt')) || existsSync(join(cwd, 'pyproject.toml'))) {
44
- info.language = 'python'
45
- info.projectType = 'existing'
46
- try {
47
- const req = readFileSync(join(cwd, 'requirements.txt'), 'utf8').toLowerCase()
48
- if (req.includes('django')) info.framework = 'Django'
49
- else if (req.includes('fastapi')) info.framework = 'FastAPI'
50
- else if (req.includes('flask')) info.framework = 'Flask'
51
- else info.framework = 'Python'
52
- } catch {}
53
- info.hasTests = existsSync(join(cwd, 'tests')) || existsSync(join(cwd, 'test'))
54
- }
55
-
56
- if (existsSync(join(cwd, 'Cargo.toml'))) {
57
- info.language = 'rust'
58
- info.framework = 'Rust'
59
- info.projectType = 'existing'
60
- }
61
-
62
- if (existsSync(join(cwd, 'go.mod'))) {
63
- info.language = 'go'
64
- info.framework = 'Go'
65
- info.projectType = 'existing'
66
- }
67
-
68
- if (!existsSync(join(cwd, 'src')) && !existsSync(pkgPath) && !existsSync(join(cwd, 'requirements.txt'))) {
69
- info.projectType = 'greenfield'
70
- }
71
-
72
- return info
73
- }
74
-
75
- function scaffoldBuildflow(appName, projectInfo) {
76
- const base = join(process.cwd(), '.buildflow')
77
-
78
- const dirs = [
79
- 'core', 'you', 'memory', 'phases',
80
- 'learnings', 'research', 'codebase',
81
- 'security/reports', 'security/rules',
82
- 'security/suppressions',
83
- ]
84
- for (const d of dirs) mkdirSync(join(base, d), { recursive: true })
85
-
86
- const today = new Date().toISOString().split('T')[0]
87
-
88
- writeFileSync(join(base, 'core', 'vision.md'),
89
- projectInfo.projectType === 'existing'
90
- ? `# Project Vision: ${appName}\n\n## Type\nExisting ${projectInfo.framework} project\n\n## Goals\n[Fill during /buildflow-start]\n\n---\nInitialized: ${today}\n`
91
- : `# Project Vision: ${appName}\n\n## What I'm Building\n[Fill during /buildflow-start]\n\n---\nInitialized: ${today}\n`
92
- )
93
-
94
- writeFileSync(join(base, 'core', 'state.md'),
95
- `# State\n\nProject: ${appName}\nType: ${projectInfo.projectType}\nFramework: ${projectInfo.framework}\nPhase: 0\nStatus: Initialized\nBuildFlow: 3.0\nDate: ${today}\n`
96
- )
97
-
98
- writeFileSync(join(base, 'you', 'preferences.md'),
99
- `# Preferences\n\nexperience: junior\nproject_type: ${projectInfo.projectType}\nframework: ${projectInfo.framework}\n\nlearning:\n show_explanations: true\n confidence_calibration: true\n source_citations: true\n\nsafety:\n enable_undo: true\n restore_points: true\n\nmemory:\n type: light\n retention_days: 30\n\nparallel:\n enabled: true\n max_researchers: 3\n\nsecurity:\n pre_ship_gate: true\n auto_suggest_on_sensitive: true\n`
100
- )
101
-
102
- writeFileSync(join(base, 'memory', 'light.md'),
103
- `# Light Memory\n\napp: ${appName}\ntype: ${projectInfo.projectType}\nframework: ${projectInfo.framework}\nphase: 0\nlast_session: ${today}\nbuildflow: 3.0\nonboarded: ${projectInfo.projectType === 'greenfield' ? 'n/a' : 'false'}\n\n## Style Fingerprint\n[Auto-populated after first build]\n\n## Recent Decisions\n[Auto-populated]\n`
104
- )
105
-
106
- writeFileSync(join(base, 'learnings', 'glossary.md'),
107
- `# Glossary\n\n## context-rot\nAI quality degrades as conversation grows. Avoided by fresh agents.\n\n## confidence-calibration\nAsking 1-5 before locking decisions. Triggers explanations when low.\n\n## cartographer\nAgent that maps existing codebases for other agents to use.\n\n## surgeon\nAgent that makes precise modifications to existing code.\n\n## security-auditor\nAgent that runs OWASP Top 10 checks before shipping.\n`
108
- )
109
-
110
- writeFileSync(join(base, 'learnings', 'decisions.md'),
111
- `# Decision Log\n\n## ${today} — Initial Setup\nDecision: Use BuildFlow v3.0\nType: ${projectInfo.projectType} (${projectInfo.framework})\nConfidence: 5/5\n`
112
- )
113
-
114
- writeFileSync(join(base, 'security', 'DEBT.md'),
115
- `# Security Debt\n\nTrack deferred security issues.\n\n## Active\n[None]\n`
116
- )
117
-
118
- return base
119
- }
120
-
121
- function patchGitignore() {
122
- const gitignorePath = join(process.cwd(), '.gitignore')
123
- const entry = '\n# BuildFlow security reports (may contain sensitive findings)\n.buildflow/security/reports/\n'
124
-
125
- if (existsSync(gitignorePath)) {
126
- const existing = readFileSync(gitignorePath, 'utf8')
127
- if (!existing.includes('.buildflow/security/reports')) {
128
- writeFileSync(gitignorePath, existing + entry)
129
- }
130
- } else {
131
- writeFileSync(gitignorePath, entry)
132
- }
133
- }
134
-
135
- function ensureGit() {
136
- if (!existsSync(join(process.cwd(), '.git'))) {
137
- try {
138
- execSync('git init -q', { cwd: process.cwd() })
139
- return true
140
- } catch {
141
- return false
142
- }
143
- }
144
- return false
145
- }
146
-
147
- export async function run(opts = {}) {
148
- console.log('\n' + chalk.bold.white(' BuildFlow v3.0 — Project Setup') + '\n')
149
-
150
- const spinner = ora('Analyzing project...').start()
151
- const projectInfo = detectProjectInfo()
152
- await new Promise(r => setTimeout(r, 500))
153
- spinner.stop()
154
-
155
- if (projectInfo.projectType === 'existing') {
156
- console.log(chalk.green(` ✓ Detected: ${projectInfo.framework} project`))
157
- console.log(chalk.dim(` Language: ${projectInfo.language}`))
158
- console.log(chalk.dim(` Tests: ${projectInfo.hasTests ? 'Yes' : 'Not found'}`))
159
- console.log(chalk.dim(` Git: ${projectInfo.hasGit ? 'Initialized' : 'Not found'}`))
160
- } else {
161
- console.log(chalk.cyan(' Starting fresh (greenfield project)'))
162
- }
163
- console.log('')
164
-
165
- let appName = projectInfo.appName
166
-
167
- if (!opts.yes) {
168
- const { confirmedName } = await prompt({
169
- type: 'input',
170
- name: 'confirmedName',
171
- message: 'App name:',
172
- initial: appName,
173
- })
174
- appName = confirmedName || appName
175
- }
176
-
177
- let projectType = projectInfo.projectType
178
- if (!opts.yes && !opts.greenfield && !opts.existing) {
179
- const { type } = await prompt({
180
- type: 'select',
181
- name: 'type',
182
- message: 'Project mode:',
183
- choices: [
184
- {
185
- name: 'existing',
186
- message: 'Existing codebase — Add BuildFlow to current code',
187
- hint: 'Enables /buildflow-onboard, /buildflow-modify, /buildflow-refactor',
188
- },
189
- {
190
- name: 'greenfield',
191
- message: 'Greenfield — Starting from scratch',
192
- hint: 'Enables /buildflow-start, full new project workflow',
193
- },
194
- ],
195
- initial: projectType === 'existing' ? 0 : 1,
196
- })
197
- projectType = type
198
- }
199
-
200
- let wantSecurity = true
201
- if (!opts.yes) {
202
- const { security } = await prompt({
203
- type: 'confirm',
204
- name: 'security',
205
- message: 'Enable security layer? (Recommended — OWASP Top 10 + pre-ship gate)',
206
- initial: true,
207
- })
208
- wantSecurity = security
209
- }
210
-
211
- const sp2 = ora('Setting up .buildflow/ folder...').start()
212
- scaffoldBuildflow(appName, { ...projectInfo, projectType })
213
- patchGitignore()
214
- ensureGit()
215
- await new Promise(r => setTimeout(r, 300))
216
- sp2.succeed(chalk.green(' ✓ .buildflow/ scaffold created'))
217
-
218
- console.log('')
219
- await runInstall({ ...opts })
220
-
221
- console.log(chalk.bold.green('\n ✓ BuildFlow initialized!\n'))
222
-
223
- if (projectType === 'existing') {
224
- console.log(chalk.white(' Start here:'))
225
- console.log(chalk.cyan(' /buildflow-onboard') + chalk.dim(' ← analyze your codebase (one-time)'))
226
- console.log(chalk.cyan(' /buildflow-modify') + chalk.dim(' ← change existing code safely'))
227
- } else {
228
- console.log(chalk.white(' Start here:'))
229
- console.log(chalk.cyan(' /buildflow-start') + chalk.dim(' ← begin your project'))
230
- console.log(chalk.cyan(' /buildflow-think') + chalk.dim(' ← research and discuss'))
231
- }
232
-
233
- if (wantSecurity) {
234
- console.log(chalk.dim('\n Security: Pre-ship gate enabled (/buildflow-ship auto-runs audit)'))
235
- console.log(chalk.dim(' Manual audit: /buildflow-audit'))
236
- }
237
-
238
- console.log('')
239
- }
1
+ import chalk from 'chalk'
2
+ import ora from 'ora'
3
+ import enquirer from 'enquirer'
4
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs'
5
+ import { join } from 'path'
6
+ import { execSync } from 'child_process'
7
+ import { run as runInstall } from './install.js'
8
+
9
+ const { prompt } = enquirer
10
+
11
+ function detectProjectInfo() {
12
+ const cwd = process.cwd()
13
+ const info = {
14
+ appName: 'my-project',
15
+ projectType: 'greenfield',
16
+ framework: 'none',
17
+ hasGit: existsSync(join(cwd, '.git')),
18
+ hasTests: false,
19
+ hasSrc: existsSync(join(cwd, 'src')),
20
+ language: 'unknown',
21
+ }
22
+
23
+ const pkgPath = join(cwd, 'package.json')
24
+ if (existsSync(pkgPath)) {
25
+ try {
26
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
27
+ info.appName = pkg.name || cwd.split('/').pop()
28
+ info.language = 'javascript'
29
+ info.projectType = 'existing'
30
+
31
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies }
32
+ if (deps?.next) info.framework = 'Next.js'
33
+ else if (deps?.react) info.framework = 'React'
34
+ else if (deps?.vue) info.framework = 'Vue'
35
+ else if (deps?.svelte) info.framework = 'Svelte'
36
+ else if (deps?.express) info.framework = 'Express'
37
+ else if (deps?.fastify) info.framework = 'Fastify'
38
+ else if (deps?.nestjs) info.framework = 'NestJS'
39
+ else info.framework = 'Node.js'
40
+
41
+ info.hasTests = !!(deps?.jest || deps?.vitest || deps?.mocha || deps?.['@playwright/test'])
42
+ } catch {}
43
+ }
44
+
45
+ if (existsSync(join(cwd, 'requirements.txt')) || existsSync(join(cwd, 'pyproject.toml'))) {
46
+ info.language = 'python'
47
+ info.projectType = 'existing'
48
+ try {
49
+ const req = readFileSync(join(cwd, 'requirements.txt'), 'utf8').toLowerCase()
50
+ if (req.includes('django')) info.framework = 'Django'
51
+ else if (req.includes('fastapi')) info.framework = 'FastAPI'
52
+ else if (req.includes('flask')) info.framework = 'Flask'
53
+ else info.framework = 'Python'
54
+ } catch {}
55
+ info.hasTests = existsSync(join(cwd, 'tests')) || existsSync(join(cwd, 'test'))
56
+ }
57
+
58
+ if (existsSync(join(cwd, 'Cargo.toml'))) {
59
+ info.language = 'rust'
60
+ info.framework = 'Rust'
61
+ info.projectType = 'existing'
62
+ }
63
+
64
+ if (existsSync(join(cwd, 'go.mod'))) {
65
+ info.language = 'go'
66
+ info.framework = 'Go'
67
+ info.projectType = 'existing'
68
+ }
69
+
70
+ if (!existsSync(join(cwd, 'src')) && !existsSync(pkgPath) && !existsSync(join(cwd, 'requirements.txt'))) {
71
+ info.projectType = 'greenfield'
72
+ }
73
+
74
+ return info
75
+ }
76
+
77
+ function scaffoldBuildflow(appName, projectInfo) {
78
+ const base = join(process.cwd(), '.buildflow')
79
+
80
+ const dirs = [
81
+ 'core', 'you', 'memory', 'phases',
82
+ 'learnings', 'research', 'codebase',
83
+ 'security/reports', 'security/rules',
84
+ 'security/suppressions',
85
+ ]
86
+ for (const d of dirs) mkdirSync(join(base, d), { recursive: true })
87
+
88
+ const today = new Date().toISOString().split('T')[0]
89
+ const isExisting = projectInfo.projectType === 'existing'
90
+
91
+ // ── core/vision.md ──────────────────────────────────────────────────────────
92
+ writeFileSync(join(base, 'core', 'vision.md'), isExisting
93
+ ? `# Vision — ${appName}
94
+
95
+ > **Purpose:** This file is the source of truth for what you're building.
96
+ > Every agent reads it at session start to stay aligned with your goals.
97
+ > Fill it in during your first \`/buildflow-start\` session.
98
+
99
+ ---
100
+
101
+ ## Project Type
102
+
103
+ **Existing ${projectInfo.framework} project** language: ${projectInfo.language}
104
+
105
+ ---
106
+
107
+ ## Goals for This Project
108
+
109
+ > What do you want to achieve by using BuildFlow on this codebase?
110
+ > Examples: "Add auth system", "Migrate to TypeScript", "Improve performance"
111
+
112
+ - [ ] Goal 1 — *(fill in)*
113
+ - [ ] Goal 2 — *(fill in)*
114
+
115
+ ---
116
+
117
+ ## What NOT to Change
118
+
119
+ > Any areas of the codebase that are off-limits or need special care?
120
+
121
+ *(fill in or delete this section)*
122
+
123
+ ---
124
+
125
+ ## Success Criteria
126
+
127
+ > How will you know the work is done and done well?
128
+
129
+ - [ ] *(fill in)*
130
+
131
+ ---
132
+
133
+ *Initialized: ${today} · BuildFlow v3.0*
134
+ `
135
+ : `# Vision — ${appName}
136
+
137
+ > **Purpose:** This file is the source of truth for what you're building.
138
+ > Every agent reads it at session start to stay aligned with your goals.
139
+ > Fill it in during your first \`/buildflow-start\` session.
140
+
141
+ ---
142
+
143
+ ## What I'm Building
144
+
145
+ > One paragraph: what is this product, tool, or service?
146
+
147
+ *(fill in during /buildflow-start)*
148
+
149
+ ---
150
+
151
+ ## Who It's For
152
+
153
+ > Describe the target user. Be specific — "developers using Node.js" beats "developers".
154
+
155
+ *(fill in)*
156
+
157
+ ---
158
+
159
+ ## Problem It Solves
160
+
161
+ > What exists today that's painful, broken, or missing?
162
+
163
+ *(fill in)*
164
+
165
+ ---
166
+
167
+ ## Success Criteria
168
+
169
+ > How will you know it's working? Measurable outcomes are better than vague goals.
170
+
171
+ - [ ] *(fill in)*
172
+
173
+ ---
174
+
175
+ ## Simplest Useful Version (MVP)
176
+
177
+ > What's the smallest thing you can ship that delivers real value?
178
+
179
+ *(fill in)*
180
+
181
+ ---
182
+
183
+ ## Constraints
184
+
185
+ | Constraint | Value |
186
+ |---------------|---------------|
187
+ | Target date | — |
188
+ | Team size | — |
189
+ | Stack | ${projectInfo.language !== 'unknown' ? projectInfo.language : '—'} |
190
+
191
+ ---
192
+
193
+ *Initialized: ${today} · BuildFlow v3.0*
194
+ `)
195
+
196
+ // ── core/state.md ───────────────────────────────────────────────────────────
197
+ writeFileSync(join(base, 'core', 'state.md'),
198
+ `# Project State
199
+
200
+ > **Purpose:** Tracks where you are in the BuildFlow workflow.
201
+ > Updated automatically by \`/buildflow-plan\`, \`/buildflow-ship\`, and \`/buildflow-back\`.
202
+ > Also read by \`buildflow status\` in the terminal.
203
+
204
+ ---
205
+
206
+ ## Current State
207
+
208
+ | Field | Value |
209
+ |---------------|------------------------|
210
+ | **Project** | ${appName} |
211
+ | **Type** | ${projectInfo.projectType} |
212
+ | **Framework** | ${projectInfo.framework} |
213
+ | **Phase** | 0 |
214
+ | **Status** | Initialized |
215
+ | **BuildFlow** | 3.0 |
216
+ | **Updated** | ${today} |
217
+
218
+ ---
219
+
220
+ ## Phase History
221
+
222
+ | Phase | Description | Status | Date |
223
+ |-------|-------------|------------|------|
224
+ | 0 | Setup | ✅ Complete | ${today} |
225
+
226
+ ---
227
+
228
+ ## Status Reference
229
+
230
+ | Status | Meaning |
231
+ |---------------|----------------------------------------------|
232
+ | Initialized | BuildFlow set up, ready to start |
233
+ | In Progress | Actively building a phase |
234
+ | Shipped | Phase complete and committed to git |
235
+ | Blocked | Waiting on a decision or external dependency |
236
+ `)
237
+
238
+ // ── you/preferences.md ──────────────────────────────────────────────────────
239
+ writeFileSync(join(base, 'you', 'preferences.md'),
240
+ `# Your Preferences
241
+
242
+ > **Purpose:** BuildFlow reads this at session start to adapt its behavior to you.
243
+ > Edit any value — changes take effect in the next AI session.
244
+
245
+ ---
246
+
247
+ ## Experience Level
248
+
249
+ \`\`\`yaml
250
+ experience: junior # junior | mid | senior
251
+ \`\`\`
252
+
253
+ | Value | What it changes |
254
+ |----------|------------------------------------------------------------------|
255
+ | \`junior\` | More explanations, analogies, LEARN: comments in generated code |
256
+ | \`mid\` | Balanced — assumes framework knowledge, skips basics |
257
+ | \`senior\` | Concise — assumes full-stack knowledge, no hand-holding |
258
+
259
+ ---
260
+
261
+ ## Project Context
262
+
263
+ \`\`\`yaml
264
+ project_type: ${projectInfo.projectType} # greenfield | existing
265
+ framework: ${projectInfo.framework}
266
+ \`\`\`
267
+
268
+ ---
269
+
270
+ ## Learning Aids
271
+
272
+ \`\`\`yaml
273
+ learning:
274
+ show_explanations: true # Explain WHY, not just WHAT
275
+ confidence_calibration: true # Ask confidence (1-5) before big decisions
276
+ source_citations: true # Cite research sources with trust scores (1-5)
277
+ \`\`\`
278
+
279
+ ---
280
+
281
+ ## Safety
282
+
283
+ \`\`\`yaml
284
+ safety:
285
+ enable_undo: true # /buildflow-back restores to git checkpoints
286
+ restore_points: true # Auto-commit before destructive operations
287
+ \`\`\`
288
+
289
+ ---
290
+
291
+ ## Memory
292
+
293
+ \`\`\`yaml
294
+ memory:
295
+ type: light # light (≤5K tokens) | full (more context, more cost)
296
+ retention_days: 30 # Discard session data older than this
297
+ \`\`\`
298
+
299
+ ---
300
+
301
+ ## Parallelization
302
+
303
+ \`\`\`yaml
304
+ parallel:
305
+ enabled: true # Run multiple agents simultaneously
306
+ max_researchers: 3 # Max parallel Researcher agents in /buildflow-think
307
+ \`\`\`
308
+
309
+ ---
310
+
311
+ ## Security
312
+
313
+ \`\`\`yaml
314
+ security:
315
+ pre_ship_gate: true # Run security audit before every /buildflow-ship
316
+ auto_suggest_on_sensitive: true # Flag sensitive files (auth, payments) automatically
317
+ \`\`\`
318
+ `)
319
+
320
+ // ── memory/light.md ─────────────────────────────────────────────────────────
321
+ writeFileSync(join(base, 'memory', 'light.md'),
322
+ `# Light Memory
323
+
324
+ > **Purpose:** Persists essential project context across AI sessions.
325
+ > Loaded at the start of every BuildFlow session to avoid re-detecting things.
326
+ > **Keep this file under 5,000 tokens.** Distill insights — don't log events.
327
+ > The AI updates this automatically. You can edit it too.
328
+
329
+ ---
330
+
331
+ ## Session Data
332
+
333
+ \`\`\`yaml
334
+ app: ${appName}
335
+ type: ${projectInfo.projectType}
336
+ framework: ${projectInfo.framework}
337
+ phase: 0
338
+ last_session: ${today}
339
+ buildflow: 3.0
340
+ onboarded: ${projectInfo.projectType === 'greenfield' ? 'n/a # greenfield project — no onboarding needed' : 'false # run /buildflow-onboard to analyze your codebase'}
341
+ \`\`\`
342
+
343
+ ---
344
+
345
+ ## Style Fingerprint
346
+
347
+ > Auto-populated by \`/buildflow-build\` after the first coding session.
348
+ > Captures naming conventions, import style, error handling patterns.
349
+
350
+ *(not yet populated)*
351
+
352
+ ---
353
+
354
+ ## Key Decisions
355
+
356
+ > Major architectural or technology decisions. Summarized here so agents
357
+ > don't relitigate them. Full details are in \`learnings/decisions.md\`.
358
+
359
+ *(not yet populated)*
360
+
361
+ ---
362
+
363
+ ## Current Focus
364
+
365
+ > What you're working on right now. Updated by \`/buildflow-plan\` and \`/buildflow-ship\`.
366
+
367
+ Phase 0 — Initial setup complete. Run \`/buildflow-start\` to begin.
368
+ `)
369
+
370
+ // ── learnings/glossary.md ───────────────────────────────────────────────────
371
+ writeFileSync(join(base, 'learnings', 'glossary.md'),
372
+ `# Glossary
373
+
374
+ > **Purpose:** Defines terms used across BuildFlow sessions.
375
+ > Agents reference this to stay consistent with terminology.
376
+ > Grows automatically when you use \`/buildflow-explain\`.
377
+ > Add your own project-specific terms below the BuildFlow section.
378
+
379
+ ---
380
+
381
+ ## BuildFlow Terms
382
+
383
+ | Term | Definition |
384
+ |------|------------|
385
+ | **context-rot** | AI quality degrades as conversation grows long. BuildFlow avoids this by using fresh agent sessions per task. |
386
+ | **confidence-calibration** | Asking for a 1–5 confidence score before locking major decisions. Score below 3 triggers alternatives or research. |
387
+ | **light memory** | The \`memory/light.md\` file — essential project context kept under 5K tokens, loaded at every session start. |
388
+ | **wave** | A group of tasks that can run in parallel because they have no dependencies on each other. |
389
+ | **restore point** | A git commit created before a destructive operation so \`/buildflow-back\` can undo it. |
390
+ | **blast radius** | The set of files affected by a code change — mapped before modifying anything in Surgeon mode. |
391
+
392
+ ---
393
+
394
+ ## Agent Roles
395
+
396
+ | Agent | Role |
397
+ |-------|------|
398
+ | **Strategist** | Vision, decisions, project orientation |
399
+ | **Researcher** | Web research with source trust scores (1–5) |
400
+ | **Synthesizer** | Combines parallel research into a recommendation |
401
+ | **Architect** | Maps task dependencies, creates wave-based plans |
402
+ | **Builder** | Writes code matched to your existing style |
403
+ | **Reviewer** | Quality, correctness, and security checks |
404
+ | **Cartographer** | One-time existing codebase analysis |
405
+ | **Surgeon** | Precise, minimal-footprint code modifications |
406
+ | **Security Auditor** | OWASP Top 10 scanning, pre-ship gate |
407
+
408
+ ---
409
+
410
+ ## Project Terms
411
+
412
+ > Add your project-specific jargon here so all agents use consistent language.
413
+
414
+ *(add terms as your project evolves)*
415
+ `)
416
+
417
+ // ── learnings/decisions.md ──────────────────────────────────────────────────
418
+ writeFileSync(join(base, 'learnings', 'decisions.md'),
419
+ `# Decision Log
420
+
421
+ > **Purpose:** Records major architectural and technology decisions.
422
+ > Prevents relitigating the same choices in future sessions.
423
+ > Each decision includes what was decided, why, and how confident you were.
424
+ > Updated by agents during \`/buildflow-think\` and \`/buildflow-plan\`.
425
+
426
+ ---
427
+
428
+ ## How to Read This Log
429
+
430
+ | Field | Meaning |
431
+ |-------|---------|
432
+ | **Decision** | What was chosen |
433
+ | **Alternatives** | What else was considered |
434
+ | **Rationale** | Why this option won |
435
+ | **Confidence** | 1–5 at time of decision (5 = very sure) |
436
+ | **Revisit if** | Conditions that would make this worth reconsidering |
437
+
438
+ ---
439
+
440
+ ## Log
441
+
442
+ ### ${today} — Initial Setup
443
+
444
+ | Field | Value |
445
+ |-------|-------|
446
+ | **Decision** | Use BuildFlow v3.0 for development orchestration |
447
+ | **Type** | ${projectInfo.projectType} · ${projectInfo.framework} |
448
+ | **Confidence** | 5/5 |
449
+ | **Revisit if** | — |
450
+
451
+ ---
452
+
453
+ *New decisions are appended below by \`/buildflow-think\` and \`/buildflow-plan\`.*
454
+ `)
455
+
456
+ // ── security/DEBT.md ────────────────────────────────────────────────────────
457
+ writeFileSync(join(base, 'security', 'DEBT.md'),
458
+ `# Security Debt
459
+
460
+ > **Purpose:** Tracks security issues that were found but not immediately fixed.
461
+ > Populated by \`buildflow fix\` (log to debt option) and \`/buildflow-ship\`
462
+ > when high-severity issues are found but you choose to ship anyway.
463
+ > Review this before every major release.
464
+
465
+ ---
466
+
467
+ ## Severity Reference
468
+
469
+ | Level | Icon | Action Required |
470
+ |-------|------|-----------------|
471
+ | Critical | 🔴 | Fix before next commit. Blocks \`/buildflow-ship\`. |
472
+ | High | 🟡 | Fix this sprint. Logged here when shipping despite warning. |
473
+ | Medium | 🟠 | Fix when in the area. Won't block shipping. |
474
+ | Low | 🔵 | Fix opportunistically. |
475
+
476
+ ---
477
+
478
+ ## Active Issues
479
+
480
+ > Issues that need to be addressed.
481
+
482
+ *None — clean slate.*
483
+
484
+ ---
485
+
486
+ ## Resolved Issues
487
+
488
+ > Move items here (with resolution date and fix description) when addressed.
489
+
490
+ *None yet.*
491
+ `)
492
+
493
+ return base
494
+ }
495
+
496
+ function patchGitignore() {
497
+ const gitignorePath = join(process.cwd(), '.gitignore')
498
+ const entry = '\n# BuildFlow security reports (may contain sensitive findings)\n.buildflow/security/reports/\n'
499
+
500
+ if (existsSync(gitignorePath)) {
501
+ const existing = readFileSync(gitignorePath, 'utf8')
502
+ if (!existing.includes('.buildflow/security/reports')) {
503
+ writeFileSync(gitignorePath, existing + entry)
504
+ }
505
+ } else {
506
+ writeFileSync(gitignorePath, entry)
507
+ }
508
+ }
509
+
510
+ function ensureGit() {
511
+ if (!existsSync(join(process.cwd(), '.git'))) {
512
+ try {
513
+ execSync('git init -q', { cwd: process.cwd() })
514
+ return true
515
+ } catch {
516
+ return false
517
+ }
518
+ }
519
+ return false
520
+ }
521
+
522
+ export async function run(opts = {}) {
523
+ console.log('\n' + chalk.bold.white(' BuildFlow v3.0 — Project Setup') + '\n')
524
+
525
+ const spinner = ora('Analyzing project...').start()
526
+ const projectInfo = detectProjectInfo()
527
+ await new Promise(r => setTimeout(r, 500))
528
+ spinner.stop()
529
+
530
+ if (projectInfo.projectType === 'existing') {
531
+ console.log(chalk.green(` ✓ Detected: ${projectInfo.framework} project`))
532
+ console.log(chalk.dim(` Language: ${projectInfo.language}`))
533
+ console.log(chalk.dim(` Tests: ${projectInfo.hasTests ? 'Yes' : 'Not found'}`))
534
+ console.log(chalk.dim(` Git: ${projectInfo.hasGit ? 'Initialized' : 'Not found'}`))
535
+ } else {
536
+ console.log(chalk.cyan(' Starting fresh (greenfield project)'))
537
+ }
538
+ console.log('')
539
+
540
+ let appName = projectInfo.appName
541
+
542
+ if (!opts.yes) {
543
+ const { confirmedName } = await prompt({
544
+ type: 'input',
545
+ name: 'confirmedName',
546
+ message: 'App name:',
547
+ initial: appName,
548
+ })
549
+ appName = confirmedName || appName
550
+ }
551
+
552
+ let projectType = projectInfo.projectType
553
+ if (!opts.yes && !opts.greenfield && !opts.existing) {
554
+ const { type } = await prompt({
555
+ type: 'select',
556
+ name: 'type',
557
+ message: 'Project mode:',
558
+ choices: [
559
+ {
560
+ name: 'existing',
561
+ message: 'Existing codebase — Add BuildFlow to current code',
562
+ hint: 'Enables /buildflow-onboard, /buildflow-modify, /buildflow-refactor',
563
+ },
564
+ {
565
+ name: 'greenfield',
566
+ message: 'Greenfield — Starting from scratch',
567
+ hint: 'Enables /buildflow-start, full new project workflow',
568
+ },
569
+ ],
570
+ initial: projectType === 'existing' ? 0 : 1,
571
+ })
572
+ projectType = type
573
+ }
574
+
575
+ let wantSecurity = true
576
+ if (!opts.yes) {
577
+ const { security } = await prompt({
578
+ type: 'confirm',
579
+ name: 'security',
580
+ message: 'Enable security layer? (Recommended — OWASP Top 10 + pre-ship gate)',
581
+ initial: true,
582
+ })
583
+ wantSecurity = security
584
+ }
585
+
586
+ const sp2 = ora('Setting up .buildflow/ folder...').start()
587
+ scaffoldBuildflow(appName, { ...projectInfo, projectType })
588
+ patchGitignore()
589
+ ensureGit()
590
+ await new Promise(r => setTimeout(r, 300))
591
+ sp2.succeed(chalk.green(' ✓ .buildflow/ scaffold created'))
592
+
593
+ console.log('')
594
+ await runInstall({ ...opts })
595
+
596
+ console.log(chalk.bold.green('\n ✓ BuildFlow initialized!\n'))
597
+
598
+ if (projectType === 'existing') {
599
+ console.log(chalk.white(' Start here:'))
600
+ console.log(chalk.cyan(' /buildflow-onboard') + chalk.dim(' ← analyze your codebase (one-time)'))
601
+ console.log(chalk.cyan(' /buildflow-modify') + chalk.dim(' ← change existing code safely'))
602
+ } else {
603
+ console.log(chalk.white(' Start here:'))
604
+ console.log(chalk.cyan(' /buildflow-start') + chalk.dim(' ← begin your project'))
605
+ console.log(chalk.cyan(' /buildflow-think') + chalk.dim(' ← research and discuss'))
606
+ }
607
+
608
+ if (wantSecurity) {
609
+ console.log(chalk.dim('\n Security: Pre-ship gate enabled (/buildflow-ship auto-runs audit)'))
610
+ console.log(chalk.dim(' Manual audit: /buildflow-audit'))
611
+ }
612
+
613
+ console.log('')
614
+ }