@agile-vibe-coding/avc 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/cli/index.js +28 -0
- package/cli/init.js +321 -0
- package/cli/logger.js +138 -0
- package/cli/repl-ink.js +764 -0
- package/cli/repl-old.js +353 -0
- package/cli/template-processor.js +491 -0
- package/cli/templates/project.md +62 -0
- package/cli/update-checker.js +218 -0
- package/cli/update-installer.js +184 -0
- package/cli/update-notifier.js +170 -0
- package/package.json +58 -0
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import readline from 'readline';
|
|
5
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* TemplateProcessor - Handles interactive template processing with AI suggestions
|
|
13
|
+
*
|
|
14
|
+
* Core workflow:
|
|
15
|
+
* 1. Parse template to extract variables
|
|
16
|
+
* 2. Prompt user for each variable (with singular/plural detection)
|
|
17
|
+
* 3. Generate AI suggestions for skipped variables
|
|
18
|
+
* 4. Replace variables in template
|
|
19
|
+
* 5. Enhance final document with AI
|
|
20
|
+
* 6. Write to .avc/project/doc.md
|
|
21
|
+
*/
|
|
22
|
+
class TemplateProcessor {
|
|
23
|
+
constructor(progressPath = null) {
|
|
24
|
+
// Load environment variables from project .env
|
|
25
|
+
dotenv.config({ path: path.join(process.cwd(), '.env') });
|
|
26
|
+
|
|
27
|
+
this.templatePath = path.join(__dirname, 'templates/project.md');
|
|
28
|
+
this.outputDir = path.join(process.cwd(), '.avc/project');
|
|
29
|
+
this.outputPath = path.join(this.outputDir, 'doc.md');
|
|
30
|
+
this.avcConfigPath = path.join(process.cwd(), '.avc/avc.json');
|
|
31
|
+
this.progressPath = progressPath;
|
|
32
|
+
|
|
33
|
+
// Read model configuration from avc.json
|
|
34
|
+
this.model = this.readModelConfig();
|
|
35
|
+
this.apiKey = process.env.ANTHROPIC_API_KEY;
|
|
36
|
+
this.claudeClient = null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Read model configuration from avc.json
|
|
41
|
+
*/
|
|
42
|
+
readModelConfig() {
|
|
43
|
+
try {
|
|
44
|
+
const config = JSON.parse(fs.readFileSync(this.avcConfigPath, 'utf8'));
|
|
45
|
+
return config.settings?.model || 'claude-sonnet-4-5-20250929';
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.warn('⚠️ Could not read model config, using default');
|
|
48
|
+
return 'claude-sonnet-4-5-20250929';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Extract variables from template content
|
|
54
|
+
* Returns array of variable objects with metadata
|
|
55
|
+
*/
|
|
56
|
+
extractVariables(content) {
|
|
57
|
+
const pattern = /\{\{([A-Z_]+)\}\}/g;
|
|
58
|
+
const matches = [...content.matchAll(pattern)];
|
|
59
|
+
|
|
60
|
+
return Array.from(new Set(matches.map(m => m[1]))).map(name => ({
|
|
61
|
+
name,
|
|
62
|
+
placeholder: `{{${name}}}`,
|
|
63
|
+
isPlural: this.isPlural(name),
|
|
64
|
+
displayName: this.toDisplayName(name),
|
|
65
|
+
guidance: this.getGuidance(name)
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Detect if variable expects plural values based on naming conventions
|
|
71
|
+
*/
|
|
72
|
+
isPlural(variableName) {
|
|
73
|
+
const pluralIndicators = [
|
|
74
|
+
'REQUIREMENTS', 'OBJECTIVES', 'FEATURES', 'USERS',
|
|
75
|
+
'WORKFLOWS', 'CONSIDERATIONS'
|
|
76
|
+
];
|
|
77
|
+
return pluralIndicators.some(indicator => variableName.includes(indicator));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Convert variable name to display format
|
|
82
|
+
* Example: "BUSINESS_CONTEXT" -> "Business Context"
|
|
83
|
+
*/
|
|
84
|
+
toDisplayName(variableName) {
|
|
85
|
+
return variableName
|
|
86
|
+
.split('_')
|
|
87
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
88
|
+
.join(' ');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get guidance text for each variable
|
|
93
|
+
*/
|
|
94
|
+
getGuidance(variableName) {
|
|
95
|
+
const guidance = {
|
|
96
|
+
'MISSION_STATEMENT': 'A concise statement describing the core purpose and value proposition of your application.\n Example: "Enable small businesses to manage inventory and sales through an intuitive mobile-first platform."',
|
|
97
|
+
|
|
98
|
+
'TARGET_USERS': 'Who will use this application? List different user types and their roles.\n Examples: "Small business owners", "Inventory managers", "Sales staff", "Administrators"',
|
|
99
|
+
|
|
100
|
+
'INITIAL_SCOPE': 'Describe the initial scope of your application: key features, main workflows, and core functionality.\n What will users be able to do? What are the essential capabilities?\n Example: "Users can create tasks, assign them to team members, track progress, set deadlines, and receive notifications."',
|
|
101
|
+
|
|
102
|
+
'TECHNICAL_CONSIDERATIONS': 'Technical requirements, constraints, or preferences for your application.\n Examples: "Mobile-first responsive design", "Must work offline", "Real-time data sync", "PostgreSQL database"',
|
|
103
|
+
|
|
104
|
+
'SECURITY_AND_COMPLIANCE_REQUIREMENTS': 'Security, privacy, or regulatory requirements your application must meet.\n Examples: "GDPR compliance for EU users", "PCI DSS for payment data", "Two-factor authentication", "Data encryption at rest"'
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return guidance[variableName] || '';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Create readline interface
|
|
112
|
+
*/
|
|
113
|
+
createInterface() {
|
|
114
|
+
return readline.createInterface({
|
|
115
|
+
input: process.stdin,
|
|
116
|
+
output: process.stdout
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Promisified readline question
|
|
122
|
+
*/
|
|
123
|
+
question(rl, query) {
|
|
124
|
+
return new Promise(resolve => rl.question(query, resolve));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Prompt user for singular value
|
|
129
|
+
* Returns string or null if skipped
|
|
130
|
+
*/
|
|
131
|
+
async promptSingular(name, guidance) {
|
|
132
|
+
const rl = this.createInterface();
|
|
133
|
+
|
|
134
|
+
console.log(`\n📝 ${name}`);
|
|
135
|
+
if (guidance) {
|
|
136
|
+
console.log(` ${guidance}`);
|
|
137
|
+
}
|
|
138
|
+
console.log(' Enter response (press Enter twice when done, or Enter immediately to skip):\n');
|
|
139
|
+
|
|
140
|
+
const lines = [];
|
|
141
|
+
let emptyLineCount = 0;
|
|
142
|
+
let firstInput = true;
|
|
143
|
+
|
|
144
|
+
return new Promise((resolve) => {
|
|
145
|
+
rl.on('line', (line) => {
|
|
146
|
+
// If first input is empty, user wants to skip
|
|
147
|
+
if (firstInput && line.trim() === '') {
|
|
148
|
+
rl.close();
|
|
149
|
+
resolve(null);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
firstInput = false;
|
|
154
|
+
|
|
155
|
+
if (line.trim() === '') {
|
|
156
|
+
emptyLineCount++;
|
|
157
|
+
if (emptyLineCount >= 1) {
|
|
158
|
+
rl.close();
|
|
159
|
+
resolve(lines.join('\n').trim());
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
emptyLineCount = 0;
|
|
164
|
+
lines.push(line);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
rl.on('close', () => {
|
|
169
|
+
if (lines.length === 0) {
|
|
170
|
+
resolve(null);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Prompt user for plural values (list)
|
|
178
|
+
* Returns array or null if skipped
|
|
179
|
+
*/
|
|
180
|
+
async promptPlural(name, guidance) {
|
|
181
|
+
const rl = this.createInterface();
|
|
182
|
+
|
|
183
|
+
console.log(`\n📝 ${name}`);
|
|
184
|
+
if (guidance) {
|
|
185
|
+
console.log(` ${guidance}`);
|
|
186
|
+
}
|
|
187
|
+
console.log(' Enter items one per line (empty line to finish, or Enter immediately to skip):\n');
|
|
188
|
+
|
|
189
|
+
const items = [];
|
|
190
|
+
let itemNumber = 1;
|
|
191
|
+
let firstInput = true;
|
|
192
|
+
|
|
193
|
+
return new Promise((resolve) => {
|
|
194
|
+
const promptForItem = () => {
|
|
195
|
+
rl.question(` ${itemNumber}. `, (answer) => {
|
|
196
|
+
// If first input is empty, user wants to skip
|
|
197
|
+
if (firstInput && answer.trim() === '') {
|
|
198
|
+
rl.close();
|
|
199
|
+
resolve(null);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
firstInput = false;
|
|
204
|
+
|
|
205
|
+
if (answer.trim() === '') {
|
|
206
|
+
rl.close();
|
|
207
|
+
resolve(items.length > 0 ? items : null);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
items.push(answer.trim());
|
|
212
|
+
itemNumber++;
|
|
213
|
+
promptForItem();
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
promptForItem();
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Initialize Claude client
|
|
223
|
+
*/
|
|
224
|
+
initializeClaudeClient() {
|
|
225
|
+
if (!process.env.ANTHROPIC_API_KEY) {
|
|
226
|
+
console.log('⚠️ ANTHROPIC_API_KEY not found - AI suggestions will be skipped');
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
this.claudeClient = new Anthropic({
|
|
231
|
+
apiKey: process.env.ANTHROPIC_API_KEY
|
|
232
|
+
});
|
|
233
|
+
return this.claudeClient;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Build context-aware prompt for AI suggestions
|
|
238
|
+
*/
|
|
239
|
+
buildPrompt(variableName, isPlural, context) {
|
|
240
|
+
const displayName = this.toDisplayName(variableName);
|
|
241
|
+
|
|
242
|
+
// Build context section from previously collected values
|
|
243
|
+
let contextSection = '';
|
|
244
|
+
if (Object.keys(context).length > 0) {
|
|
245
|
+
contextSection = 'Project context so far:\n\n';
|
|
246
|
+
for (const [key, value] of Object.entries(context)) {
|
|
247
|
+
const keyDisplay = this.toDisplayName(key);
|
|
248
|
+
if (Array.isArray(value)) {
|
|
249
|
+
contextSection += `${keyDisplay}:\n${value.map(v => `- ${v}`).join('\n')}\n`;
|
|
250
|
+
} else {
|
|
251
|
+
contextSection += `${keyDisplay}: ${value}\n`;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
contextSection += '\n';
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (isPlural) {
|
|
258
|
+
return `${contextSection}Suggest 3-5 appropriate values for "${displayName}".\n\nReturn only the suggestions, one per line, no numbering or bullets.`;
|
|
259
|
+
} else {
|
|
260
|
+
return `${contextSection}Suggest an appropriate value for "${displayName}".\n\nReturn only the suggestion text, concise (1-3 sentences).`;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Parse Claude's response into structured format
|
|
266
|
+
*/
|
|
267
|
+
parseClaudeResponse(response, isPlural) {
|
|
268
|
+
if (isPlural) {
|
|
269
|
+
return response.split('\n')
|
|
270
|
+
.map(line => line.trim())
|
|
271
|
+
.filter(line => line.length > 0 && !line.match(/^[0-9\-*.]+\s/));
|
|
272
|
+
}
|
|
273
|
+
return response.trim();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Generate AI suggestions for a variable
|
|
278
|
+
*/
|
|
279
|
+
async generateSuggestions(variableName, isPlural, context) {
|
|
280
|
+
if (!this.claudeClient && !this.initializeClaudeClient()) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
const prompt = this.buildPrompt(variableName, isPlural, context);
|
|
286
|
+
|
|
287
|
+
const response = await this.claudeClient.messages.create({
|
|
288
|
+
model: this.model,
|
|
289
|
+
max_tokens: isPlural ? 512 : 256,
|
|
290
|
+
messages: [{ role: "user", content: prompt }]
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
return this.parseClaudeResponse(response.content[0].text, isPlural);
|
|
294
|
+
} catch (error) {
|
|
295
|
+
console.warn(`⚠️ Could not generate suggestions: ${error.message}`);
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Prompt user for a variable value
|
|
302
|
+
* Returns { variable, value, source, skipped }
|
|
303
|
+
*/
|
|
304
|
+
async promptUser(variable, context) {
|
|
305
|
+
let value;
|
|
306
|
+
|
|
307
|
+
if (variable.isPlural) {
|
|
308
|
+
value = await this.promptPlural(variable.displayName, variable.guidance);
|
|
309
|
+
} else {
|
|
310
|
+
value = await this.promptSingular(variable.displayName, variable.guidance);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// If user skipped, try to generate AI suggestions
|
|
314
|
+
if (value === null) {
|
|
315
|
+
console.log(' ✨ Generating AI suggestion...');
|
|
316
|
+
value = await this.generateSuggestions(variable.name, variable.isPlural, context);
|
|
317
|
+
|
|
318
|
+
if (value) {
|
|
319
|
+
console.log(' ✅ AI suggestion:');
|
|
320
|
+
if (Array.isArray(value)) {
|
|
321
|
+
value.forEach((item, idx) => console.log(` ${idx + 1}. ${item}`));
|
|
322
|
+
} else {
|
|
323
|
+
console.log(` ${value}`);
|
|
324
|
+
}
|
|
325
|
+
return { variable: variable.name, value, source: 'ai', skipped: true };
|
|
326
|
+
} else {
|
|
327
|
+
// No AI available or error
|
|
328
|
+
return { variable: variable.name, value: '', source: 'empty', skipped: true };
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return { variable: variable.name, value, source: 'user', skipped: false };
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Replace variables in template with collected values
|
|
337
|
+
*/
|
|
338
|
+
replaceVariables(template, variables) {
|
|
339
|
+
let result = template;
|
|
340
|
+
|
|
341
|
+
for (const [variableName, value] of Object.entries(variables)) {
|
|
342
|
+
const placeholder = `{{${variableName}}}`;
|
|
343
|
+
|
|
344
|
+
let replacement;
|
|
345
|
+
if (Array.isArray(value)) {
|
|
346
|
+
replacement = value.map(item => `- ${item}`).join('\n');
|
|
347
|
+
} else {
|
|
348
|
+
replacement = value || '(Not specified)';
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
result = result.replace(
|
|
352
|
+
new RegExp(placeholder.replace(/[{}]/g, '\\$&'), 'g'),
|
|
353
|
+
replacement
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return result;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Generate final document with LLM enhancement
|
|
362
|
+
*/
|
|
363
|
+
async generateFinalDocument(templateWithValues) {
|
|
364
|
+
if (!this.claudeClient && !this.initializeClaudeClient()) {
|
|
365
|
+
// No API key - save template as-is
|
|
366
|
+
return templateWithValues;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
console.log('\n🤖 Enhancing document with AI...');
|
|
370
|
+
|
|
371
|
+
try {
|
|
372
|
+
const response = await this.claudeClient.messages.create({
|
|
373
|
+
model: this.model,
|
|
374
|
+
max_tokens: 4096,
|
|
375
|
+
messages: [{
|
|
376
|
+
role: "user",
|
|
377
|
+
content: `You are creating a project definition document for an Agile Vibe Coding (AVC) project.
|
|
378
|
+
|
|
379
|
+
Here is the project information with all variables filled in:
|
|
380
|
+
|
|
381
|
+
${templateWithValues}
|
|
382
|
+
|
|
383
|
+
Please review and enhance this document to ensure:
|
|
384
|
+
1. All sections are well-formatted and clear
|
|
385
|
+
2. Content is professional and actionable
|
|
386
|
+
3. Sections flow logically
|
|
387
|
+
4. Any incomplete sections are identified
|
|
388
|
+
|
|
389
|
+
Return the enhanced markdown document.`
|
|
390
|
+
}]
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
return response.content[0].text;
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.warn(`⚠️ Could not enhance document: ${error.message}`);
|
|
396
|
+
return templateWithValues;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Save progress to file
|
|
402
|
+
*/
|
|
403
|
+
saveProgress(progress) {
|
|
404
|
+
if (this.progressPath) {
|
|
405
|
+
fs.writeFileSync(this.progressPath, JSON.stringify(progress, null, 2), 'utf8');
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Write document to file
|
|
411
|
+
*/
|
|
412
|
+
async writeDocument(content) {
|
|
413
|
+
// Create .avc/project/ directory
|
|
414
|
+
if (!fs.existsSync(this.outputDir)) {
|
|
415
|
+
fs.mkdirSync(this.outputDir, { recursive: true });
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Write doc.md
|
|
419
|
+
fs.writeFileSync(this.outputPath, content, 'utf8');
|
|
420
|
+
|
|
421
|
+
console.log(`\n✅ Project document generated!`);
|
|
422
|
+
console.log(` Location: ${this.outputPath}`);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Main workflow - process template and generate document
|
|
427
|
+
*/
|
|
428
|
+
async processTemplate(initialProgress = null) {
|
|
429
|
+
console.log('\n📋 Project Setup Questionnaire\n');
|
|
430
|
+
|
|
431
|
+
// 1. Read template
|
|
432
|
+
const templateContent = fs.readFileSync(this.templatePath, 'utf8');
|
|
433
|
+
|
|
434
|
+
// 2. Extract variables
|
|
435
|
+
const variables = this.extractVariables(templateContent);
|
|
436
|
+
|
|
437
|
+
// 3. Initialize or restore progress
|
|
438
|
+
let collectedValues = {};
|
|
439
|
+
let answeredCount = 0;
|
|
440
|
+
|
|
441
|
+
if (initialProgress && initialProgress.collectedValues) {
|
|
442
|
+
collectedValues = { ...initialProgress.collectedValues };
|
|
443
|
+
answeredCount = Object.keys(collectedValues).length;
|
|
444
|
+
console.log(`Resuming with ${answeredCount}/${variables.length} questions already answered.\n`);
|
|
445
|
+
} else {
|
|
446
|
+
console.log(`Found ${variables.length} sections to complete.\n`);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// 4. Collect values with context accumulation
|
|
450
|
+
for (const variable of variables) {
|
|
451
|
+
// Skip already answered questions when resuming
|
|
452
|
+
if (collectedValues[variable.name] !== undefined) {
|
|
453
|
+
console.log(`\n✓ ${variable.displayName}`);
|
|
454
|
+
console.log(` Using previous answer: ${
|
|
455
|
+
Array.isArray(collectedValues[variable.name])
|
|
456
|
+
? `${collectedValues[variable.name].length} items`
|
|
457
|
+
: `"${collectedValues[variable.name].substring(0, 60)}${collectedValues[variable.name].length > 60 ? '...' : ''}"`
|
|
458
|
+
}`);
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const result = await this.promptUser(variable, collectedValues);
|
|
463
|
+
collectedValues[result.variable] = result.value;
|
|
464
|
+
answeredCount++;
|
|
465
|
+
|
|
466
|
+
// Save progress after each question
|
|
467
|
+
if (this.progressPath) {
|
|
468
|
+
const progress = {
|
|
469
|
+
stage: 'questionnaire',
|
|
470
|
+
totalQuestions: variables.length,
|
|
471
|
+
answeredQuestions: answeredCount,
|
|
472
|
+
collectedValues: collectedValues,
|
|
473
|
+
lastUpdate: new Date().toISOString()
|
|
474
|
+
};
|
|
475
|
+
this.saveProgress(progress);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// 5. Replace variables in template
|
|
480
|
+
console.log('\n🔄 Preparing project document...');
|
|
481
|
+
const templateWithValues = this.replaceVariables(templateContent, collectedValues);
|
|
482
|
+
|
|
483
|
+
// 6. Enhance document with LLM
|
|
484
|
+
const finalDocument = await this.generateFinalDocument(templateWithValues);
|
|
485
|
+
|
|
486
|
+
// 7. Write to file
|
|
487
|
+
await this.writeDocument(finalDocument);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export { TemplateProcessor };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
You will be helping to create a comprehensive software application definition document. This document will serve as a foundational specification that can later be broken down into domain-specific details and related prompts for development agents.
|
|
2
|
+
|
|
3
|
+
## Project Information
|
|
4
|
+
|
|
5
|
+
### Mission Statement
|
|
6
|
+
|
|
7
|
+
{{MISSION_STATEMENT}}
|
|
8
|
+
|
|
9
|
+
### Target Users
|
|
10
|
+
|
|
11
|
+
{{TARGET_USERS}}
|
|
12
|
+
|
|
13
|
+
### Initial Scope
|
|
14
|
+
|
|
15
|
+
{{INITIAL_SCOPE}}
|
|
16
|
+
|
|
17
|
+
### Technical Considerations
|
|
18
|
+
|
|
19
|
+
{{TECHNICAL_CONSIDERATIONS}}
|
|
20
|
+
|
|
21
|
+
### Security and Compliance
|
|
22
|
+
|
|
23
|
+
{{SECURITY_AND_COMPLIANCE_REQUIREMENTS}}
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
Your task is to generate a detailed, structured application definition that expands on the information provided above and creates a comprehensive project specification for AI-powered development.
|
|
28
|
+
|
|
29
|
+
Before writing your final application definition, use the scratchpad below to think through the key aspects:
|
|
30
|
+
|
|
31
|
+
<scratchpad>
|
|
32
|
+
In your scratchpad, consider:
|
|
33
|
+
- What is the core purpose and value proposition of this application?
|
|
34
|
+
- Who are the primary users/stakeholders and what are their needs?
|
|
35
|
+
- What are the main functional areas or domains this application will need to address?
|
|
36
|
+
- What are the critical features versus nice-to-have features?
|
|
37
|
+
- Are there any technical, security, or compliance considerations evident from the requirements?
|
|
38
|
+
- What integrations or external systems might be needed?
|
|
39
|
+
- What are the primary user journeys through the application?
|
|
40
|
+
</scratchpad>
|
|
41
|
+
|
|
42
|
+
Now, create a comprehensive application definition that includes the following sections:
|
|
43
|
+
|
|
44
|
+
1. **Application Overview**: A clear, concise summary of what the application does and its primary purpose
|
|
45
|
+
|
|
46
|
+
2. **Target Users and Stakeholders**: Identify the different types of users who will interact with this application, their roles, and their key needs
|
|
47
|
+
|
|
48
|
+
3. **Key Features and Functionality**: Describe the essential features organized by functional area or domain (e.g., user management, data processing, reporting, etc.)
|
|
49
|
+
|
|
50
|
+
4. **User Workflows**: Outline the primary user journeys or workflows through the application with step-by-step descriptions
|
|
51
|
+
|
|
52
|
+
5. **Technical Architecture**: Note any important technical requirements, constraints, or preferences (e.g., platform, technology stack, scalability needs, performance requirements)
|
|
53
|
+
|
|
54
|
+
6. **Integration Requirements**: Identify any external systems, APIs, or data sources the application needs to connect with
|
|
55
|
+
|
|
56
|
+
7. **Security and Compliance**: Highlight any security, privacy, or regulatory compliance requirements
|
|
57
|
+
|
|
58
|
+
8. **Success Criteria**: Define what success looks like for this application
|
|
59
|
+
|
|
60
|
+
Your final output should be a complete, well-structured application definition document that provides enough detail to serve as a foundation for creating domain-specific specifications and work items for AI agents, while remaining at a high enough level to give a comprehensive view of the entire application.
|
|
61
|
+
|
|
62
|
+
Use clear markdown formatting with headers, bullet points, and emphasis where appropriate. Do not include the scratchpad in your final output - only include the sections listed above.
|