prjct-cli 0.10.10 → 0.10.11

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,14 +1,16 @@
1
1
  /**
2
- * Architecture Generator - Transforms ideas into complete technical specifications
3
- * Uses AI-driven methodology to develop ideas through discovery, design, and planning phases
2
+ * Architecture Generator - Coordinates architecture generation
3
+ * AGENTIC: Claude generates content via templates/architect/*.md
4
+ * This file only provides structure - real content from Claude
4
5
  */
5
6
 
6
- const path = require('path');
7
- const fs = require('fs').promises;
7
+ const path = require('path')
8
+ const fs = require('fs').promises
8
9
 
9
10
  class ArchitectureGenerator {
10
11
  constructor() {
11
- this.phases = [
12
+ // AGENTIC: Phases determined by Claude via templates/architect/phases.md
13
+ this.defaultPhases = [
12
14
  'discovery',
13
15
  'user-flows',
14
16
  'domain-modeling',
@@ -16,546 +18,76 @@ class ArchitectureGenerator {
16
18
  'architecture',
17
19
  'data-design',
18
20
  'tech-stack',
19
- 'roadmap'
20
- ];
21
+ 'roadmap',
22
+ ]
21
23
  }
22
24
 
23
25
  /**
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
26
+ * Generate architecture skeleton
27
+ * AGENTIC: Claude fills in content using templates
28
+ * @param {string} idea - The initial idea
29
+ * @param {object} context - Project context
30
+ * @returns {Promise<object>} Architecture skeleton
28
31
  */
29
32
  async generateArchitecture(idea, context = {}) {
30
- const architecture = {
33
+ // Return skeleton - Claude generates actual content via templates
34
+ return {
31
35
  id: `arch-${Date.now()}`,
32
36
  idea,
33
37
  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
- });
38
+ phases: {},
39
+ // AGENTIC: Claude populates phases using templates/architect/*.md
40
+ _agenticNote: 'Use templates/architect/phases.md to determine needed phases, then templates/architect/discovery.md etc for content',
229
41
  }
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
42
  }
284
43
 
285
44
  /**
286
- * Phase 8: Implementation Roadmap
45
+ * Get template path for a phase
287
46
  */
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
- };
47
+ getPhaseTemplate(phase) {
48
+ const templateMap = {
49
+ discovery: 'templates/architect/discovery.md',
50
+ 'user-flows': 'templates/design/flow.md',
51
+ 'domain-modeling': 'templates/design/database.md',
52
+ 'api-design': 'templates/design/api.md',
53
+ architecture: 'templates/design/architecture.md',
54
+ 'data-design': 'templates/design/database.md',
55
+ 'tech-stack': 'templates/design/architecture.md',
56
+ roadmap: 'templates/commands/feature.md',
57
+ }
58
+ return templateMap[phase] || null
355
59
  }
356
60
 
357
61
  /**
358
62
  * Save architecture to files
63
+ * AGENTIC: Format determined by Claude based on content
359
64
  */
360
65
  async saveArchitecture(architecture, projectPath) {
361
- const archPath = path.join(projectPath, 'planning', 'architectures', architecture.id);
362
- await fs.mkdir(archPath, { recursive: true });
66
+ const archPath = path.join(projectPath, 'planning', 'architectures', architecture.id)
67
+ await fs.mkdir(archPath, { recursive: true })
363
68
 
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
- };
69
+ // Save summary
70
+ await fs.writeFile(path.join(archPath, 'summary.json'), JSON.stringify(architecture, null, 2))
376
71
 
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;
72
+ // AGENTIC: Claude generates and saves phase files directly
73
+ return archPath
494
74
  }
495
75
 
76
+ /**
77
+ * SQL type mapping utility
78
+ */
496
79
  sqlType(type) {
497
80
  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`;
81
+ uuid: 'UUID',
82
+ string: 'VARCHAR(255)',
83
+ text: 'TEXT',
84
+ int: 'INTEGER',
85
+ timestamp: 'TIMESTAMP',
86
+ boolean: 'BOOLEAN',
87
+ json: 'JSONB',
553
88
  }
554
-
555
- content += `## Total Estimate: ${roadmap.estimatedTotal}\n`;
556
-
557
- return content;
89
+ return typeMap[type] || 'TEXT'
558
90
  }
559
91
  }
560
92
 
561
- module.exports = ArchitectureGenerator;
93
+ module.exports = ArchitectureGenerator
@@ -98,31 +98,16 @@ class TaskAnalyzer {
98
98
 
99
99
  /**
100
100
  * Semantic analysis - understand intent
101
- *
102
- * Only detects basic intent (create, fix, improve, test).
103
- * Claude handles detailed domain analysis.
101
+ * AGENTIC: Claude uses templates/analysis/intent.md for detailed analysis
102
+ * This returns minimal structure - Claude determines actual intent
104
103
  */
105
104
  analyzeSemantics(text) {
106
- const semantic = {
107
- intent: null,
108
- requiresMultipleAgents: false
109
- }
110
-
111
- // Detect basic intent patterns (these are universal, not tech-specific)
112
- if (text.match(/\b(create|add|build|implement|make)\b/)) {
113
- semantic.intent = 'create'
114
- } else if (text.match(/\b(fix|repair|debug|resolve)\b/)) {
115
- semantic.intent = 'fix'
116
- } else if (text.match(/\b(improve|optimize|enhance|refactor)\b/)) {
117
- semantic.intent = 'improve'
118
- } else if (text.match(/\b(test|verify|validate)\b/)) {
119
- semantic.intent = 'test'
105
+ // AGENTIC: Return structure only, Claude analyzes via template
106
+ return {
107
+ intent: null, // Claude determines via templates/analysis/intent.md
108
+ requiresMultipleAgents: false, // Claude decides based on context
109
+ text: text, // Pass text for Claude to analyze
120
110
  }
121
-
122
- // No hardcoded multi-agent detection
123
- // Claude decides if multiple agents are needed based on context
124
-
125
- return semantic
126
111
  }
127
112
 
128
113
  /**
@@ -162,22 +147,12 @@ class TaskAnalyzer {
162
147
  }
163
148
 
164
149
  /**
165
- * Estimate task complexity based on intent words
150
+ * Estimate task complexity
151
+ * AGENTIC: Claude uses templates/analysis/complexity.md for real estimation
152
+ * This returns default - Claude determines actual complexity
166
153
  */
167
154
  estimateComplexity(text) {
168
- // Simple complexity indicators (universal, not tech-specific)
169
- const simpleIndicators = ['add', 'create', 'simple', 'basic', 'small']
170
- const complexIndicators = ['refactor', 'optimize', 'architecture', 'migration', 'redesign', 'overhaul']
171
-
172
- const simpleCount = simpleIndicators.filter(ind => text.includes(ind)).length
173
- const complexCount = complexIndicators.filter(ind => text.includes(ind)).length
174
-
175
- if (complexCount > simpleCount) {
176
- return 'high'
177
- } else if (simpleCount > 0 && complexCount === 0) {
178
- return 'low'
179
- }
180
-
155
+ // AGENTIC: Return default, Claude analyzes via templates/analysis/complexity.md
181
156
  return 'medium'
182
157
  }
183
158
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.10.10",
3
+ "version": "0.10.11",
4
4
  "description": "Built for Claude - Ship fast, track progress, stay focused. Developer momentum tool for indie hackers.",
5
5
  "main": "core/index.js",
6
6
  "bin": {