prjct-cli 0.8.6 → 0.9.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 (47) hide show
  1. package/CHANGELOG.md +216 -0
  2. package/CLAUDE.md +34 -0
  3. package/core/agentic/agent-router.js +482 -0
  4. package/core/agentic/command-executor.js +70 -15
  5. package/core/agentic/context-builder.js +4 -3
  6. package/core/agentic/context-filter.js +545 -0
  7. package/core/agentic/prompt-builder.js +48 -38
  8. package/core/agentic/tool-registry.js +35 -0
  9. package/core/command-registry.js +104 -164
  10. package/core/commands.js +84 -0
  11. package/core/domain/agent-generator.js +55 -44
  12. package/core/domain/architecture-generator.js +561 -0
  13. package/core/domain/task-stack.js +496 -0
  14. package/core/infrastructure/legacy-installer-detector.js +546 -0
  15. package/core/infrastructure/session-manager.js +14 -2
  16. package/core/infrastructure/setup.js +29 -11
  17. package/core/utils/jsonl-helper.js +137 -0
  18. package/package.json +1 -1
  19. package/scripts/install.sh +45 -8
  20. package/scripts/postinstall.js +5 -5
  21. package/templates/agents/AGENTS.md +3 -3
  22. package/templates/commands/analyze.md +10 -53
  23. package/templates/commands/ask.md +25 -338
  24. package/templates/commands/bug.md +11 -70
  25. package/templates/commands/build.md +8 -35
  26. package/templates/commands/cleanup.md +9 -32
  27. package/templates/commands/dash.md +241 -0
  28. package/templates/commands/design.md +5 -28
  29. package/templates/commands/done.md +6 -20
  30. package/templates/commands/feature.md +12 -225
  31. package/templates/commands/help.md +26 -313
  32. package/templates/commands/idea.md +7 -25
  33. package/templates/commands/init.md +15 -191
  34. package/templates/commands/migrate-all.md +25 -84
  35. package/templates/commands/next.md +6 -26
  36. package/templates/commands/now.md +6 -25
  37. package/templates/commands/pause.md +18 -0
  38. package/templates/commands/progress.md +5 -50
  39. package/templates/commands/recap.md +5 -54
  40. package/templates/commands/resume.md +97 -0
  41. package/templates/commands/ship.md +14 -135
  42. package/templates/commands/status.md +7 -32
  43. package/templates/commands/suggest.md +36 -495
  44. package/templates/commands/sync.md +7 -24
  45. package/templates/commands/work.md +44 -0
  46. package/templates/commands/workflow.md +3 -25
  47. package/templates/planning-methodology.md +195 -0
@@ -3,71 +3,82 @@ const path = require('path')
3
3
  const os = require('os')
4
4
 
5
5
  /**
6
- * AgentGenerator - Dynamic agent generation for prjct-cli
7
- *
8
- * 100% AGENTIC - Claude decides which agents to create based on project analysis.
9
- * NO predetermined patterns, NO if/else logic, NO assumptions.
10
- *
11
- * @version 0.6.0 - Fully agentic refactor
6
+ * AgentGenerator - Universal Dynamic Agent Generation
7
+ * Optimized for minimal context usage
8
+ * @version 1.0.0
12
9
  */
13
10
  class AgentGenerator {
14
11
  constructor(projectId = null) {
15
12
  this.projectId = projectId
16
-
17
- // Agents are stored in global project directory
18
- if (projectId) {
19
- this.outputDir = path.join(os.homedir(), '.prjct-cli', 'projects', projectId, 'agents')
20
- } else {
21
- // Fallback for backwards compatibility
22
- this.outputDir = path.join(os.homedir(), '.prjct-cli', 'agents')
23
- }
13
+ this.outputDir = projectId
14
+ ? path.join(os.homedir(), '.prjct-cli', 'projects', projectId, 'agents')
15
+ : path.join(os.homedir(), '.prjct-cli', 'agents')
24
16
  }
25
17
 
26
18
  /**
27
- * Generate a single agent dynamically
28
- * Claude (the LLM) decides which agents to create based on project analysis
29
- *
30
- * @param {string} agentName - Descriptive name (e.g., 'go-backend', 'vuejs-frontend', 'elixir-api')
31
- * @param {Object} config - Agent configuration
32
- * @param {string} config.role - Agent's role description
33
- * @param {string} config.expertise - Technologies and skills (specific versions, tools)
34
- * @param {string} config.responsibilities - What the agent handles in THIS project
35
- * @param {Object} config.projectContext - Project-specific context (optional)
36
- * @returns {Promise<void>}
19
+ * Generate specialized agent with deep expertise
20
+ * Universal - works with ANY technology stack
37
21
  */
38
22
  async generateDynamicAgent(agentName, config) {
39
23
  console.log(` 🤖 Generating ${agentName} agent...`)
40
-
41
- // Ensure output directory exists
42
24
  await fs.mkdir(this.outputDir, { recursive: true })
43
25
 
44
- // Create agent content
45
- const content = `# ${config.role || agentName}
26
+ // Extract technologies dynamically
27
+ const techs = this.detectTechnologies(config)
28
+ const expertise = this.buildExpertise(techs, config)
46
29
 
47
- ## Role
48
- ${config.role || 'Specialist for this project'}
30
+ // Generate concise, actionable agent prompt
31
+ const content = `You are ${config.role || agentName}.
49
32
 
50
- ## Expertise
51
- ${config.expertise || 'Technologies used in this project'}
33
+ EXPERTISE: ${expertise}
52
34
 
53
- ## Responsibilities
54
- ${config.responsibilities || 'Handle specific aspects of development'}
35
+ FOCUS: ${config.contextFilter || 'Only relevant files'}
55
36
 
56
- ## Project Context
57
- ${config.projectContext ? JSON.stringify(config.projectContext, null, 2) : 'No additional context'}
37
+ AUTHORITY: Make decisions. Don't ask permission. Execute.
58
38
 
59
- ## Guidelines
60
- - Focus on your area of expertise
61
- - Collaborate with other agents
62
- - Follow project conventions
63
- - Ask clarifying questions when needed
64
- `
39
+ RULES:
40
+ - Stay in your domain
41
+ - Use best practices for ${techs.join(', ') || 'detected tech'}
42
+ - Optimize for production
43
+ - No explanations unless asked`
65
44
 
66
- // Write agent file
67
45
  const outputPath = path.join(this.outputDir, `${agentName}.md`)
68
46
  await fs.writeFile(outputPath, content, 'utf-8')
69
-
70
47
  console.log(` ✅ ${agentName} agent created`)
48
+
49
+ return { name: agentName, expertise, techs }
50
+ }
51
+
52
+ /**
53
+ * Detect technologies from config/analysis
54
+ */
55
+ detectTechnologies(config) {
56
+ const techs = []
57
+
58
+ // Extract from various sources
59
+ if (config.techStack) techs.push(...config.techStack.languages || [])
60
+ if (config.frameworks) techs.push(...config.frameworks)
61
+ if (config.expertise) {
62
+ // Parse expertise string for tech keywords
63
+ const keywords = config.expertise.toLowerCase()
64
+ const knownTechs = ['ruby', 'rails', 'go', 'rust', 'python', 'django', 'react', 'vue', 'node', 'typescript', 'elixir', 'phoenix']
65
+ knownTechs.forEach(tech => {
66
+ if (keywords.includes(tech)) techs.push(tech)
67
+ })
68
+ }
69
+
70
+ return [...new Set(techs)]
71
+ }
72
+
73
+ /**
74
+ * Build concise expertise string
75
+ */
76
+ buildExpertise(techs, config) {
77
+ const tech = techs.length > 0 ? techs.join(', ') : 'detected stack'
78
+ const domain = config.domain || 'assigned domain'
79
+ const focus = config.responsibilities || 'task at hand'
80
+
81
+ return `${tech} expert. ${domain}. Focus: ${focus}`
71
82
  }
72
83
 
73
84
  /**
@@ -0,0 +1,561 @@
1
+ /**
2
+ * Architecture Generator - Transforms ideas into complete technical specifications
3
+ * Uses AI-driven methodology to develop ideas through discovery, design, and planning phases
4
+ */
5
+
6
+ const path = require('path');
7
+ const fs = require('fs').promises;
8
+
9
+ class ArchitectureGenerator {
10
+ constructor() {
11
+ this.phases = [
12
+ 'discovery',
13
+ 'user-flows',
14
+ 'domain-modeling',
15
+ 'api-design',
16
+ 'architecture',
17
+ 'data-design',
18
+ 'tech-stack',
19
+ 'roadmap'
20
+ ];
21
+ }
22
+
23
+ /**
24
+ * Generate complete architecture from an idea
25
+ * @param {string} idea - The initial idea description
26
+ * @param {object} context - Project context and constraints
27
+ * @returns {Promise<object>} Complete architecture specification
28
+ */
29
+ async generateArchitecture(idea, context = {}) {
30
+ const architecture = {
31
+ id: `arch-${Date.now()}`,
32
+ idea,
33
+ createdAt: new Date().toISOString(),
34
+ phases: {}
35
+ };
36
+
37
+ // Phase 1: Discovery & Problem Definition
38
+ architecture.phases.discovery = await this.discovery(idea, context);
39
+
40
+ // Phase 2: User Flows & Journeys
41
+ architecture.phases.userFlows = await this.userFlows();
42
+
43
+ // Phase 3: Domain Modeling
44
+ architecture.phases.domainModel = await this.domainModeling();
45
+
46
+ // Phase 4: API Contract Design
47
+ architecture.phases.apiDesign = await this.apiDesign();
48
+
49
+ // Phase 5: System Architecture
50
+ architecture.phases.systemArchitecture = await this.systemArchitecture();
51
+
52
+ // Phase 6: Data Architecture
53
+ architecture.phases.dataArchitecture = await this.dataArchitecture(
54
+ architecture.phases.domainModel
55
+ );
56
+
57
+ // Phase 7: Tech Stack Decision
58
+ architecture.phases.techStack = await this.techStackDecision();
59
+
60
+ // Phase 8: Implementation Roadmap
61
+ architecture.phases.roadmap = await this.roadmap();
62
+
63
+ return architecture;
64
+ }
65
+
66
+ /**
67
+ * Phase 1: Discovery & Problem Definition
68
+ */
69
+ async discovery(idea, context) {
70
+ return {
71
+ problemStatement: {
72
+ problem: `Analyzing: ${idea}`,
73
+ currentPainPoint: 'To be determined through analysis',
74
+ impact: 'To be evaluated'
75
+ },
76
+ targetUsers: {
77
+ primary: {
78
+ persona: 'Primary User',
79
+ goals: [],
80
+ frustrations: [],
81
+ technicalProficiency: 'medium'
82
+ },
83
+ secondary: []
84
+ },
85
+ constraints: {
86
+ budget: context.budget || 'bootstrapped',
87
+ timeline: context.timeline || 'MVP in 4 weeks',
88
+ teamSize: context.teamSize || 1,
89
+ regulatory: context.regulatory || []
90
+ },
91
+ successMetrics: {
92
+ primary: 'User adoption rate',
93
+ secondary: ['engagement', 'retention'],
94
+ mvpThreshold: '100 active users'
95
+ }
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Phase 2: User Flows & Journeys
101
+ */
102
+ async userFlows() {
103
+ return {
104
+ coreJourneys: [
105
+ {
106
+ name: 'Primary User Flow',
107
+ entryPoint: 'Landing page or direct link',
108
+ steps: [
109
+ { action: 'Arrive', response: 'Show welcome', next: 'Onboarding' },
110
+ { action: 'Complete onboarding', response: 'Create account', next: 'Dashboard' },
111
+ { action: 'Use core feature', response: 'Process request', next: 'Results' }
112
+ ],
113
+ successState: 'Task completed successfully',
114
+ errorStates: ['Network error', 'Validation error', 'Permission denied']
115
+ }
116
+ ],
117
+ jobsToBeDone: [
118
+ {
119
+ situation: 'When I need to solve the core problem',
120
+ motivation: 'I want to use this solution',
121
+ expectedOutcome: 'So I can achieve my goal efficiently'
122
+ }
123
+ ]
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Phase 3: Domain Modeling
129
+ */
130
+ async domainModeling() {
131
+ return {
132
+ entities: [
133
+ {
134
+ name: 'User',
135
+ description: 'System user account',
136
+ attributes: [
137
+ { name: 'id', type: 'uuid', constraints: 'primary key' },
138
+ { name: 'email', type: 'string', constraints: 'unique, not null' },
139
+ { name: 'createdAt', type: 'timestamp', constraints: 'not null' }
140
+ ],
141
+ relationships: [],
142
+ businessRules: ['Email must be verified', 'User must accept terms'],
143
+ lifecycle: ['pending', 'active', 'suspended', 'deleted']
144
+ }
145
+ ],
146
+ boundedContexts: [
147
+ {
148
+ name: 'User Management',
149
+ entities: ['User', 'Profile', 'Session'],
150
+ dependencies: [],
151
+ eventsPublished: ['UserCreated', 'UserUpdated'],
152
+ eventsConsumed: []
153
+ }
154
+ ]
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Phase 4: API Design
160
+ */
161
+ async apiDesign() {
162
+ return {
163
+ style: 'REST',
164
+ reasoning: 'Simple CRUD operations with broad compatibility',
165
+ endpoints: [
166
+ {
167
+ name: 'Create User',
168
+ method: 'POST',
169
+ path: '/api/users',
170
+ authentication: 'Optional',
171
+ inputSchema: {
172
+ email: 'string',
173
+ password: 'string'
174
+ },
175
+ outputSchema: {
176
+ id: 'string',
177
+ email: 'string',
178
+ createdAt: 'string'
179
+ },
180
+ errorResponses: [
181
+ { code: 400, description: 'Invalid input' },
182
+ { code: 409, description: 'Email already exists' }
183
+ ]
184
+ }
185
+ ],
186
+ authentication: {
187
+ method: 'JWT',
188
+ implementation: 'Lucia',
189
+ tokenStorage: 'httpOnly cookie',
190
+ sessionDuration: '7 days'
191
+ }
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Phase 5: System Architecture
197
+ */
198
+ async systemArchitecture() {
199
+ return {
200
+ pattern: 'Modular Monolith',
201
+ reasoning: 'Fast iteration for MVP with small team',
202
+ components: {
203
+ frontend: 'Next.js App',
204
+ backend: 'Next.js API Routes',
205
+ database: 'PostgreSQL',
206
+ cache: 'Redis',
207
+ storage: 'S3-compatible'
208
+ },
209
+ deploymentModel: 'Serverless (Vercel)',
210
+ scalingStrategy: 'Horizontal with auto-scaling'
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Phase 6: Data Architecture
216
+ */
217
+ async dataArchitecture(domainModel) {
218
+ const schemas = [];
219
+
220
+ for (const entity of domainModel.entities) {
221
+ schemas.push({
222
+ table: entity.name.toLowerCase() + 's',
223
+ columns: entity.attributes,
224
+ indexes: [
225
+ { name: `idx_${entity.name.toLowerCase()}_created`, columns: ['createdAt'] }
226
+ ],
227
+ relationships: entity.relationships
228
+ });
229
+ }
230
+
231
+ return {
232
+ primaryDatabase: 'PostgreSQL',
233
+ reasoning: 'ACID compliance, complex queries, proven reliability',
234
+ schemas,
235
+ caching: {
236
+ strategy: 'Cache-aside',
237
+ ttl: {
238
+ user: 3600,
239
+ session: 1800
240
+ }
241
+ },
242
+ migration: {
243
+ tool: 'Drizzle Kit',
244
+ strategy: 'Forward-only migrations'
245
+ }
246
+ };
247
+ }
248
+
249
+ /**
250
+ * Phase 7: Tech Stack Decision
251
+ */
252
+ async techStackDecision() {
253
+ return {
254
+ frontend: {
255
+ framework: 'Next.js 14',
256
+ styling: 'Tailwind CSS',
257
+ state: 'Zustand',
258
+ forms: 'React Hook Form',
259
+ dataFetching: 'TanStack Query',
260
+ ui: 'shadcn/ui'
261
+ },
262
+ backend: {
263
+ runtime: 'Node.js',
264
+ framework: 'Next.js API Routes',
265
+ orm: 'Drizzle',
266
+ validation: 'Zod',
267
+ auth: 'Lucia',
268
+ background: 'Inngest'
269
+ },
270
+ infrastructure: {
271
+ hosting: 'Vercel',
272
+ database: 'Neon',
273
+ cache: 'Upstash Redis',
274
+ storage: 'Cloudflare R2',
275
+ monitoring: 'Sentry'
276
+ },
277
+ reasoning: {
278
+ frontend: 'Type-safe, modern DX, strong ecosystem',
279
+ backend: 'Unified codebase, serverless-first',
280
+ infrastructure: 'Cost-effective for MVP, scales well'
281
+ }
282
+ };
283
+ }
284
+
285
+ /**
286
+ * Phase 8: Implementation Roadmap
287
+ */
288
+ async roadmap() {
289
+ return {
290
+ mvpScope: {
291
+ goal: 'Validate core value proposition',
292
+ features: [
293
+ 'User authentication',
294
+ 'Core feature implementation',
295
+ 'Basic dashboard',
296
+ 'Essential API endpoints'
297
+ ],
298
+ excluded: [
299
+ 'Advanced analytics',
300
+ 'Third-party integrations',
301
+ 'Mobile app'
302
+ ],
303
+ successCriteria: {
304
+ users: 100,
305
+ retention: '40% weekly active'
306
+ }
307
+ },
308
+ phases: [
309
+ {
310
+ name: 'Phase 1: Foundation',
311
+ duration: '1 week',
312
+ tasks: [
313
+ 'Project setup and configuration',
314
+ 'Database schema and migrations',
315
+ 'Authentication system',
316
+ 'Basic UI components'
317
+ ],
318
+ deliverable: 'Working authentication and base UI'
319
+ },
320
+ {
321
+ name: 'Phase 2: Core Features',
322
+ duration: '2 weeks',
323
+ tasks: [
324
+ 'Implement core domain logic',
325
+ 'API endpoints',
326
+ 'User dashboard',
327
+ 'Data validation'
328
+ ],
329
+ deliverable: 'Functional MVP'
330
+ },
331
+ {
332
+ name: 'Phase 3: Polish & Launch',
333
+ duration: '1 week',
334
+ tasks: [
335
+ 'Error handling',
336
+ 'Performance optimization',
337
+ 'Security audit',
338
+ 'Production deployment'
339
+ ],
340
+ deliverable: 'Production-ready application'
341
+ }
342
+ ],
343
+ estimatedTotal: '4 weeks',
344
+ risks: [
345
+ {
346
+ risk: 'Scope creep',
347
+ mitigation: 'Strict MVP feature set'
348
+ },
349
+ {
350
+ risk: 'Technical complexity',
351
+ mitigation: 'Use proven patterns and libraries'
352
+ }
353
+ ]
354
+ };
355
+ }
356
+
357
+ /**
358
+ * Save architecture to files
359
+ */
360
+ async saveArchitecture(architecture, projectPath) {
361
+ const archPath = path.join(projectPath, 'planning', 'architectures', architecture.id);
362
+ await fs.mkdir(archPath, { recursive: true });
363
+
364
+ // Save each phase as a separate markdown file
365
+ const files = {
366
+ 'discovery.md': this.formatDiscovery(architecture.phases.discovery),
367
+ 'user-flows.md': this.formatUserFlows(architecture.phases.userFlows),
368
+ 'domain-model.md': this.formatDomainModel(architecture.phases.domainModel),
369
+ 'api-spec.md': this.formatApiSpec(architecture.phases.apiDesign),
370
+ 'architecture.md': this.formatArchitecture(architecture.phases.systemArchitecture),
371
+ 'database.sql': this.generateSQLSchema(architecture.phases.dataArchitecture),
372
+ 'tech-stack.md': this.formatTechStack(architecture.phases.techStack),
373
+ 'roadmap.md': this.formatRoadmap(architecture.phases.roadmap),
374
+ 'summary.json': JSON.stringify(architecture, null, 2)
375
+ };
376
+
377
+ for (const [filename, content] of Object.entries(files)) {
378
+ await fs.writeFile(path.join(archPath, filename), content);
379
+ }
380
+
381
+ return archPath;
382
+ }
383
+
384
+ // Formatting methods for each phase
385
+ formatDiscovery(discovery) {
386
+ return `# Discovery & Problem Definition
387
+
388
+ ## Problem Statement
389
+
390
+ **Problem**: ${discovery.problemStatement.problem}
391
+ **Current Pain Point**: ${discovery.problemStatement.currentPainPoint}
392
+ **Impact**: ${discovery.problemStatement.impact}
393
+
394
+ ## Target Users
395
+
396
+ ### Primary User
397
+ - **Persona**: ${discovery.targetUsers.primary.persona}
398
+ - **Technical Proficiency**: ${discovery.targetUsers.primary.technicalProficiency}
399
+
400
+ ## Constraints
401
+ - **Budget**: ${discovery.constraints.budget}
402
+ - **Timeline**: ${discovery.constraints.timeline}
403
+ - **Team Size**: ${discovery.constraints.teamSize}
404
+
405
+ ## Success Metrics
406
+ - **Primary KPI**: ${discovery.successMetrics.primary}
407
+ - **MVP Threshold**: ${discovery.successMetrics.mvpThreshold}
408
+ `;
409
+ }
410
+
411
+ formatUserFlows(userFlows) {
412
+ let content = '# User Flows & Journeys\n\n';
413
+
414
+ for (const journey of userFlows.coreJourneys) {
415
+ content += `## ${journey.name}\n\n`;
416
+ content += `**Entry Point**: ${journey.entryPoint}\n\n`;
417
+ content += '### Steps\n';
418
+ for (const step of journey.steps) {
419
+ content += `1. **${step.action}** → ${step.response} → ${step.next}\n`;
420
+ }
421
+ content += `\n**Success State**: ${journey.successState}\n\n`;
422
+ }
423
+
424
+ return content;
425
+ }
426
+
427
+ formatDomainModel(domainModel) {
428
+ let content = '# Domain Model\n\n## Entities\n\n';
429
+
430
+ for (const entity of domainModel.entities) {
431
+ content += `### ${entity.name}\n`;
432
+ content += `${entity.description}\n\n`;
433
+ content += '**Attributes**:\n';
434
+ for (const attr of entity.attributes) {
435
+ content += `- ${attr.name}: ${attr.type} (${attr.constraints})\n`;
436
+ }
437
+ content += '\n';
438
+ }
439
+
440
+ return content;
441
+ }
442
+
443
+ formatApiSpec(apiDesign) {
444
+ let content = `# API Specification\n\n`;
445
+ content += `**Style**: ${apiDesign.style}\n`;
446
+ content += `**Reasoning**: ${apiDesign.reasoning}\n\n`;
447
+ content += '## Endpoints\n\n';
448
+
449
+ for (const endpoint of apiDesign.endpoints) {
450
+ content += `### ${endpoint.name}\n`;
451
+ content += `- **Method**: ${endpoint.method}\n`;
452
+ content += `- **Path**: ${endpoint.path}\n`;
453
+ content += `- **Authentication**: ${endpoint.authentication}\n\n`;
454
+ }
455
+
456
+ return content;
457
+ }
458
+
459
+ formatArchitecture(architecture) {
460
+ return `# System Architecture
461
+
462
+ **Pattern**: ${architecture.pattern}
463
+ **Reasoning**: ${architecture.reasoning}
464
+
465
+ ## Components
466
+ - **Frontend**: ${architecture.components.frontend}
467
+ - **Backend**: ${architecture.components.backend}
468
+ - **Database**: ${architecture.components.database}
469
+ - **Cache**: ${architecture.components.cache}
470
+
471
+ ## Deployment
472
+ - **Model**: ${architecture.deploymentModel}
473
+ - **Scaling**: ${architecture.scalingStrategy}
474
+ `;
475
+ }
476
+
477
+ generateSQLSchema(dataArchitecture) {
478
+ let sql = '-- Generated Database Schema\n\n';
479
+
480
+ for (const schema of dataArchitecture.schemas) {
481
+ sql += `CREATE TABLE ${schema.table} (\n`;
482
+ for (const col of schema.columns) {
483
+ sql += ` ${col.name} ${this.sqlType(col.type)} ${col.constraints || ''},\n`;
484
+ }
485
+ sql = sql.slice(0, -2) + '\n);\n\n';
486
+
487
+ for (const index of schema.indexes) {
488
+ sql += `CREATE INDEX ${index.name} ON ${schema.table}(${index.columns.join(', ')});\n`;
489
+ }
490
+ sql += '\n';
491
+ }
492
+
493
+ return sql;
494
+ }
495
+
496
+ sqlType(type) {
497
+ const typeMap = {
498
+ 'uuid': 'UUID',
499
+ 'string': 'VARCHAR(255)',
500
+ 'text': 'TEXT',
501
+ 'int': 'INTEGER',
502
+ 'timestamp': 'TIMESTAMP',
503
+ 'boolean': 'BOOLEAN',
504
+ 'json': 'JSONB'
505
+ };
506
+ return typeMap[type] || 'TEXT';
507
+ }
508
+
509
+ formatTechStack(techStack) {
510
+ return `# Tech Stack Decision
511
+
512
+ ## Frontend
513
+ - **Framework**: ${techStack.frontend.framework}
514
+ - **Styling**: ${techStack.frontend.styling}
515
+ - **State Management**: ${techStack.frontend.state}
516
+ - **Forms**: ${techStack.frontend.forms}
517
+ - **Data Fetching**: ${techStack.frontend.dataFetching}
518
+ - **UI Library**: ${techStack.frontend.ui}
519
+
520
+ ## Backend
521
+ - **Runtime**: ${techStack.backend.runtime}
522
+ - **Framework**: ${techStack.backend.framework}
523
+ - **ORM**: ${techStack.backend.orm}
524
+ - **Validation**: ${techStack.backend.validation}
525
+ - **Auth**: ${techStack.backend.auth}
526
+
527
+ ## Infrastructure
528
+ - **Hosting**: ${techStack.infrastructure.hosting}
529
+ - **Database**: ${techStack.infrastructure.database}
530
+ - **Cache**: ${techStack.infrastructure.cache}
531
+ - **Monitoring**: ${techStack.infrastructure.monitoring}
532
+ `;
533
+ }
534
+
535
+ formatRoadmap(roadmap) {
536
+ let content = `# Implementation Roadmap\n\n`;
537
+ content += `## MVP Scope\n\n`;
538
+ content += `**Goal**: ${roadmap.mvpScope.goal}\n\n`;
539
+ content += '### Included Features\n';
540
+ for (const feature of roadmap.mvpScope.features) {
541
+ content += `- ${feature}\n`;
542
+ }
543
+ content += '\n## Development Phases\n\n';
544
+
545
+ for (const phase of roadmap.phases) {
546
+ content += `### ${phase.name}\n`;
547
+ content += `**Duration**: ${phase.duration}\n\n`;
548
+ content += '**Tasks**:\n';
549
+ for (const task of phase.tasks) {
550
+ content += `- ${task}\n`;
551
+ }
552
+ content += `\n**Deliverable**: ${phase.deliverable}\n\n`;
553
+ }
554
+
555
+ content += `## Total Estimate: ${roadmap.estimatedTotal}\n`;
556
+
557
+ return content;
558
+ }
559
+ }
560
+
561
+ module.exports = ArchitectureGenerator;