@iservu-inc/adf-cli 0.1.6 → 0.3.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/.project/chats/complete/2025-10-03_ADF-CLI-QUALITY-BASED-PROGRESS-AND-RESUME.md +399 -0
- package/.project/chats/current/2025-10-03_AGENTS-MD-AND-TOOL-GENERATORS.md +699 -0
- package/.project/docs/architecture/SYSTEM-DESIGN.md +369 -0
- package/.project/docs/frameworks/FRAMEWORK-METHODOLOGIES.md +449 -0
- package/.project/docs/goals/PROJECT-VISION.md +112 -0
- package/.project/docs/tool-integrations/IDE-CUSTOMIZATIONS.md +578 -0
- package/.project/docs/tool-integrations/RESEARCH-FINDINGS.md +828 -0
- package/CHANGELOG.md +292 -0
- package/jest.config.js +20 -0
- package/lib/commands/deploy.js +122 -3
- package/lib/commands/init.js +41 -113
- package/lib/frameworks/answer-quality-analyzer.js +216 -0
- package/lib/frameworks/interviewer.js +447 -0
- package/lib/frameworks/output-generators.js +345 -0
- package/lib/frameworks/progress-tracker.js +239 -0
- package/lib/frameworks/questions.js +664 -0
- package/lib/frameworks/session-manager.js +100 -0
- package/lib/generators/agents-md-generator.js +388 -0
- package/lib/generators/cursor-generator.js +374 -0
- package/lib/generators/index.js +98 -0
- package/lib/generators/tool-config-generator.js +188 -0
- package/lib/generators/vscode-generator.js +403 -0
- package/lib/generators/windsurf-generator.js +596 -0
- package/package.json +10 -5
- package/tests/agents-md-generator.test.js +245 -0
- package/tests/answer-quality-analyzer.test.js +173 -0
- package/tests/cursor-generator.test.js +326 -0
- package/tests/progress-tracker.test.js +205 -0
- package/tests/session-manager.test.js +162 -0
- package/tests/vscode-generator.test.js +436 -0
- package/tests/windsurf-generator.test.js +320 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
const ToolConfigGenerator = require('./tool-config-generator');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generator for Cursor AI configuration files
|
|
5
|
+
* Creates .cursor/rules, .cursor/mcp.json, and deprecation notices
|
|
6
|
+
*
|
|
7
|
+
* See: https://docs.cursor.com/
|
|
8
|
+
*/
|
|
9
|
+
class CursorGenerator extends ToolConfigGenerator {
|
|
10
|
+
/**
|
|
11
|
+
* Generate all Cursor configuration files
|
|
12
|
+
*/
|
|
13
|
+
async generate() {
|
|
14
|
+
await this.initialize();
|
|
15
|
+
|
|
16
|
+
const generated = {
|
|
17
|
+
rules: [],
|
|
18
|
+
mcp: [],
|
|
19
|
+
legacy: []
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Generate .cursor/rules (modern, recommended)
|
|
23
|
+
const rulesPath = await this.generateRules();
|
|
24
|
+
generated.rules.push(rulesPath);
|
|
25
|
+
|
|
26
|
+
// Generate .cursor/mcp.json (optional, advanced)
|
|
27
|
+
// Commented out for now - can be enabled later
|
|
28
|
+
// const mcpPath = await this.generateMCP();
|
|
29
|
+
// generated.mcp.push(mcpPath);
|
|
30
|
+
|
|
31
|
+
// Generate .cursorrules deprecation notice (legacy support)
|
|
32
|
+
const legacyPath = await this.generateLegacyNotice();
|
|
33
|
+
generated.legacy.push(legacyPath);
|
|
34
|
+
|
|
35
|
+
return generated;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Generate .cursor/rules (primary configuration)
|
|
40
|
+
*/
|
|
41
|
+
async generateRules() {
|
|
42
|
+
await this.ensureDir('.cursor');
|
|
43
|
+
|
|
44
|
+
const content = this.framework === 'rapid' ?
|
|
45
|
+
this.generateRulesPRP() :
|
|
46
|
+
this.framework === 'balanced' ?
|
|
47
|
+
this.generateRulesBalanced() :
|
|
48
|
+
this.generateRulesBMAD();
|
|
49
|
+
|
|
50
|
+
return await this.writeToProject('.cursor/rules', content);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
generateRulesPRP() {
|
|
54
|
+
const projectName = this.getProjectName();
|
|
55
|
+
const sections = this.outputs.sections || {};
|
|
56
|
+
|
|
57
|
+
return `# ${projectName} - Cursor Rules
|
|
58
|
+
|
|
59
|
+
You are a senior developer working on ${projectName}.
|
|
60
|
+
|
|
61
|
+
## Project Goal
|
|
62
|
+
|
|
63
|
+
${sections['1._goal_definition'] || sections['goal_definition'] || 'See PRP for details'}
|
|
64
|
+
|
|
65
|
+
## Tech Stack
|
|
66
|
+
|
|
67
|
+
${this.extractTechStack(sections)}
|
|
68
|
+
|
|
69
|
+
## Implementation Blueprint
|
|
70
|
+
|
|
71
|
+
${sections['4._implementation_blueprint'] || sections['implementation_blueprint'] || 'See PRP for details'}
|
|
72
|
+
|
|
73
|
+
## Success Criteria
|
|
74
|
+
|
|
75
|
+
${sections['5._validation'] || sections['validation'] || 'See PRP for validation criteria'}
|
|
76
|
+
|
|
77
|
+
## Before Implementing Features
|
|
78
|
+
|
|
79
|
+
1. **Read the full PRP**: \`.adf/sessions/${this.getSessionId()}/outputs/prp.md\`
|
|
80
|
+
2. **Follow the implementation blueprint** exactly as specified
|
|
81
|
+
3. **Validate against success criteria** before marking complete
|
|
82
|
+
4. **Ask clarifying questions** if requirements are unclear
|
|
83
|
+
|
|
84
|
+
## Code Standards
|
|
85
|
+
|
|
86
|
+
- Use the specified tech stack
|
|
87
|
+
- Follow the file structure in the blueprint
|
|
88
|
+
- Include error handling
|
|
89
|
+
- Write tests for new functionality
|
|
90
|
+
- Document complex logic
|
|
91
|
+
- Maintain consistency with existing code
|
|
92
|
+
|
|
93
|
+
## Testing
|
|
94
|
+
|
|
95
|
+
- Write tests for all new features
|
|
96
|
+
- Ensure tests pass before committing
|
|
97
|
+
- Follow TDD when appropriate
|
|
98
|
+
|
|
99
|
+
## What to Avoid
|
|
100
|
+
|
|
101
|
+
- Deviating from the implementation blueprint
|
|
102
|
+
- Skipping tests
|
|
103
|
+
- Ignoring success criteria
|
|
104
|
+
- Using technologies not in the tech stack
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
*Generated by ADF CLI v${this.getADFVersion()} from PRP framework*
|
|
109
|
+
*This is a .cursor/rules file. The legacy .cursorrules file is deprecated.*
|
|
110
|
+
`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
generateRulesBalanced() {
|
|
114
|
+
const projectName = this.getProjectName();
|
|
115
|
+
const constitution = this.outputs.constitution || '';
|
|
116
|
+
const specification = this.outputs.specification || '';
|
|
117
|
+
const plan = this.outputs.plan || '';
|
|
118
|
+
|
|
119
|
+
const principles = this.extractSection(constitution, 'Core Principles');
|
|
120
|
+
const constraints = this.extractSection(constitution, 'Constraints');
|
|
121
|
+
const techStack = this.extractSection(plan, 'Technology Stack');
|
|
122
|
+
|
|
123
|
+
return `# ${projectName} - Cursor Rules
|
|
124
|
+
|
|
125
|
+
You are a senior developer working on ${projectName}.
|
|
126
|
+
|
|
127
|
+
## Core Principles
|
|
128
|
+
|
|
129
|
+
${principles || 'Follow best practices'}
|
|
130
|
+
|
|
131
|
+
## Constraints (Non-Negotiable)
|
|
132
|
+
|
|
133
|
+
${constraints || 'No specific constraints'}
|
|
134
|
+
|
|
135
|
+
## Tech Stack
|
|
136
|
+
|
|
137
|
+
${techStack || 'See technical plan for details'}
|
|
138
|
+
|
|
139
|
+
## Architecture
|
|
140
|
+
|
|
141
|
+
${this.extractSection(specification, 'Architecture') || 'See specification.md for complete architecture'}
|
|
142
|
+
|
|
143
|
+
## Before Implementing
|
|
144
|
+
|
|
145
|
+
1. **Read the constitution**: \`.adf/sessions/${this.getSessionId()}/outputs/constitution.md\`
|
|
146
|
+
- Understand principles and constraints
|
|
147
|
+
2. **Review the specification**: \`.adf/sessions/${this.getSessionId()}/outputs/specification.md\`
|
|
148
|
+
- Know what needs to be built
|
|
149
|
+
3. **Check the technical plan**: \`.adf/sessions/${this.getSessionId()}/outputs/plan.md\`
|
|
150
|
+
- Follow architectural decisions
|
|
151
|
+
4. **Review tasks**: \`.adf/sessions/${this.getSessionId()}/outputs/tasks.md\`
|
|
152
|
+
- Understand implementation phases
|
|
153
|
+
|
|
154
|
+
## Code Standards
|
|
155
|
+
|
|
156
|
+
${this.extractSection(plan, 'Code Style') || this.extractSection(plan, 'Coding Standards') || 'Follow best practices'}
|
|
157
|
+
|
|
158
|
+
- Write tests first (TDD approach)
|
|
159
|
+
- Follow architecture patterns from specification
|
|
160
|
+
- Adhere to constraints (these are non-negotiable)
|
|
161
|
+
- Maintain consistency with code style
|
|
162
|
+
|
|
163
|
+
## Testing
|
|
164
|
+
|
|
165
|
+
- Comprehensive test coverage
|
|
166
|
+
- Unit tests for logic
|
|
167
|
+
- Integration tests for workflows
|
|
168
|
+
- Follow testing approach in technical plan
|
|
169
|
+
|
|
170
|
+
## What You MUST NOT Do
|
|
171
|
+
|
|
172
|
+
- Violate any constraints from constitution
|
|
173
|
+
- Deviate from architectural patterns
|
|
174
|
+
- Skip tests
|
|
175
|
+
- Ignore code standards
|
|
176
|
+
|
|
177
|
+
## Reference Files
|
|
178
|
+
|
|
179
|
+
- **Constitution**: \`.adf/sessions/${this.getSessionId()}/outputs/constitution.md\` (principles & constraints)
|
|
180
|
+
- **Specification**: \`.adf/sessions/${this.getSessionId()}/outputs/specification.md\` (detailed requirements)
|
|
181
|
+
- **Technical Plan**: \`.adf/sessions/${this.getSessionId()}/outputs/plan.md\` (architecture & decisions)
|
|
182
|
+
- **Tasks**: \`.adf/sessions/${this.getSessionId()}/outputs/tasks.md\` (implementation breakdown)
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
*Generated by ADF CLI v${this.getADFVersion()} from Balanced framework*
|
|
187
|
+
*This is a .cursor/rules file. The legacy .cursorrules file is deprecated.*
|
|
188
|
+
`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
generateRulesBMAD() {
|
|
192
|
+
const projectName = this.getProjectName();
|
|
193
|
+
const prd = this.outputs.prd || '';
|
|
194
|
+
const architecture = this.outputs.architecture || '';
|
|
195
|
+
|
|
196
|
+
return `# ${projectName} - Cursor Rules
|
|
197
|
+
|
|
198
|
+
You are a senior developer working on ${projectName}.
|
|
199
|
+
|
|
200
|
+
## Product Overview
|
|
201
|
+
|
|
202
|
+
${this.extractSection(prd, 'Executive Summary') || this.extractSection(prd, 'Overview') || 'See PRD'}
|
|
203
|
+
|
|
204
|
+
## Goals and Objectives
|
|
205
|
+
|
|
206
|
+
${this.extractSection(prd, 'Goals and Objectives') || 'See PRD'}
|
|
207
|
+
|
|
208
|
+
## Technical Requirements
|
|
209
|
+
|
|
210
|
+
${this.extractSection(prd, 'Technical Requirements') || this.extractSection(prd, 'Technical Architecture') || 'See PRD'}
|
|
211
|
+
|
|
212
|
+
## System Architecture
|
|
213
|
+
|
|
214
|
+
${this.extractSection(architecture, 'System Overview') || this.extractSection(architecture, 'Architecture Overview') || 'See architecture.md'}
|
|
215
|
+
|
|
216
|
+
## Before Implementing
|
|
217
|
+
|
|
218
|
+
1. **Read the PRD**: \`.adf/sessions/${this.getSessionId()}/outputs/prd.md\`
|
|
219
|
+
- Understand complete product vision
|
|
220
|
+
2. **Study the architecture**: \`.adf/sessions/${this.getSessionId()}/outputs/architecture.md\`
|
|
221
|
+
- Know the system design and component structure
|
|
222
|
+
3. **Review user stories**: \`.adf/sessions/${this.getSessionId()}/outputs/stories.md\`
|
|
223
|
+
- Understand user needs and acceptance criteria
|
|
224
|
+
|
|
225
|
+
## Code Quality Standards
|
|
226
|
+
|
|
227
|
+
- Maintain test coverage >= 80%
|
|
228
|
+
- Follow architectural patterns from architecture.md
|
|
229
|
+
- Implement user stories as specified in stories.md
|
|
230
|
+
- Write clean, maintainable, documented code
|
|
231
|
+
- Handle errors gracefully
|
|
232
|
+
- Consider scalability and performance
|
|
233
|
+
|
|
234
|
+
## Testing
|
|
235
|
+
|
|
236
|
+
- Write comprehensive tests
|
|
237
|
+
- Unit tests for components
|
|
238
|
+
- Integration tests for workflows
|
|
239
|
+
- E2E tests for user journeys
|
|
240
|
+
- All tests must pass before committing
|
|
241
|
+
|
|
242
|
+
## Security
|
|
243
|
+
|
|
244
|
+
- Never commit sensitive data (API keys, passwords, tokens)
|
|
245
|
+
- Use environment variables for configuration
|
|
246
|
+
- Validate all user input
|
|
247
|
+
- Follow security best practices
|
|
248
|
+
- See PRD for specific security requirements
|
|
249
|
+
|
|
250
|
+
## Performance
|
|
251
|
+
|
|
252
|
+
- Follow performance requirements in PRD
|
|
253
|
+
- Optimize critical paths
|
|
254
|
+
- Monitor resource usage
|
|
255
|
+
- See architecture.md for performance patterns
|
|
256
|
+
|
|
257
|
+
## What You MUST NOT Do
|
|
258
|
+
|
|
259
|
+
- Deviate from architectural decisions without discussion
|
|
260
|
+
- Skip tests
|
|
261
|
+
- Ignore user story acceptance criteria
|
|
262
|
+
- Commit sensitive data
|
|
263
|
+
- Make breaking changes without approval
|
|
264
|
+
|
|
265
|
+
## Reference Files
|
|
266
|
+
|
|
267
|
+
- **PRD**: \`.adf/sessions/${this.getSessionId()}/outputs/prd.md\` (complete product requirements)
|
|
268
|
+
- **Architecture**: \`.adf/sessions/${this.getSessionId()}/outputs/architecture.md\` (system design)
|
|
269
|
+
- **User Stories**: \`.adf/sessions/${this.getSessionId()}/outputs/stories.md\` (user needs & acceptance criteria)
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
*Generated by ADF CLI v${this.getADFVersion()} from BMAD framework*
|
|
274
|
+
*This is a .cursor/rules file. The legacy .cursorrules file is deprecated.*
|
|
275
|
+
`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Generate .cursor/mcp.json (Model Context Protocol servers)
|
|
280
|
+
* Optional advanced feature for custom tools
|
|
281
|
+
*/
|
|
282
|
+
async generateMCP() {
|
|
283
|
+
await this.ensureDir('.cursor');
|
|
284
|
+
|
|
285
|
+
const mcpConfig = {
|
|
286
|
+
mcpServers: {
|
|
287
|
+
"requirement-checker": {
|
|
288
|
+
command: "node",
|
|
289
|
+
args: ["./tools/requirement-checker.js"],
|
|
290
|
+
env: {
|
|
291
|
+
SESSION_PATH: `.adf/sessions/${this.getSessionId()}`
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const content = JSON.stringify(mcpConfig, null, 2);
|
|
298
|
+
return await this.writeToProject('.cursor/mcp.json', content);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Generate .cursorrules with deprecation notice
|
|
303
|
+
* Legacy support - redirect to modern .cursor/rules
|
|
304
|
+
*/
|
|
305
|
+
async generateLegacyNotice() {
|
|
306
|
+
const content = `# DEPRECATED: .cursorrules
|
|
307
|
+
|
|
308
|
+
This file format is deprecated by Cursor.
|
|
309
|
+
|
|
310
|
+
**Please use:** \`.cursor/rules\` instead
|
|
311
|
+
|
|
312
|
+
The modern \`.cursor/rules\` file provides:
|
|
313
|
+
- Better organization
|
|
314
|
+
- Project-scoped rules
|
|
315
|
+
- Enhanced functionality
|
|
316
|
+
|
|
317
|
+
## Migration
|
|
318
|
+
|
|
319
|
+
The ADF CLI has automatically generated:
|
|
320
|
+
- \`.cursor/rules\` - Your project rules (use this)
|
|
321
|
+
|
|
322
|
+
You can delete this .cursorrules file.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
*Generated by ADF CLI v${this.getADFVersion()}*
|
|
327
|
+
`;
|
|
328
|
+
|
|
329
|
+
return await this.writeToProject('.cursorrules', content);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Extract tech stack from PRP sections
|
|
334
|
+
*/
|
|
335
|
+
extractTechStack(sections) {
|
|
336
|
+
const contextualIntelligence = sections['3._contextual_intelligence'] ||
|
|
337
|
+
sections['contextual_intelligence'] || '';
|
|
338
|
+
|
|
339
|
+
const lines = contextualIntelligence.split('\n');
|
|
340
|
+
const techLines = [];
|
|
341
|
+
let inTechSection = false;
|
|
342
|
+
|
|
343
|
+
for (const line of lines) {
|
|
344
|
+
if (line.toLowerCase().includes('tech') ||
|
|
345
|
+
line.toLowerCase().includes('stack') ||
|
|
346
|
+
line.toLowerCase().includes('technology')) {
|
|
347
|
+
inTechSection = true;
|
|
348
|
+
}
|
|
349
|
+
if (inTechSection && line.trim()) {
|
|
350
|
+
techLines.push(line);
|
|
351
|
+
if (techLines.length > 10) break;
|
|
352
|
+
}
|
|
353
|
+
if (line.startsWith('##') && inTechSection && techLines.length > 0) {
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return techLines.length > 0 ? techLines.join('\n') : 'See framework outputs for tech stack';
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Get ADF CLI version
|
|
363
|
+
*/
|
|
364
|
+
getADFVersion() {
|
|
365
|
+
try {
|
|
366
|
+
const packageJson = require('../../package.json');
|
|
367
|
+
return packageJson.version;
|
|
368
|
+
} catch (error) {
|
|
369
|
+
return '0.3.0';
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
module.exports = CursorGenerator;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Configuration Generators
|
|
3
|
+
* Transform ADF framework outputs into IDE/tool-specific configurations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const AgentsMdGenerator = require('./agents-md-generator');
|
|
7
|
+
const WindsurfGenerator = require('./windsurf-generator');
|
|
8
|
+
const CursorGenerator = require('./cursor-generator');
|
|
9
|
+
const VSCodeGenerator = require('./vscode-generator');
|
|
10
|
+
const ToolConfigGenerator = require('./tool-config-generator');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generate all tool configurations for a project
|
|
14
|
+
* @param {string} sessionPath - Path to ADF session
|
|
15
|
+
* @param {string} projectPath - Path to project root
|
|
16
|
+
* @param {string} framework - Framework type (rapid/balanced/comprehensive)
|
|
17
|
+
* @param {object} options - Generation options
|
|
18
|
+
* @returns {object} Generated file paths
|
|
19
|
+
*/
|
|
20
|
+
async function generateAll(sessionPath, projectPath, framework, options = {}) {
|
|
21
|
+
const generated = {
|
|
22
|
+
universal: [],
|
|
23
|
+
windsurf: [],
|
|
24
|
+
cursor: [],
|
|
25
|
+
vscode: []
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Always generate AGENTS.md (universal standard)
|
|
29
|
+
const agentsMd = new AgentsMdGenerator(sessionPath, projectPath, framework);
|
|
30
|
+
const agentsMdPath = await agentsMd.generate();
|
|
31
|
+
generated.universal.push(agentsMdPath);
|
|
32
|
+
|
|
33
|
+
// Generate tool-specific configs based on options
|
|
34
|
+
if (options.tool === 'windsurf' || options.all) {
|
|
35
|
+
const windsurf = new WindsurfGenerator(sessionPath, projectPath, framework);
|
|
36
|
+
const windsurfPaths = await windsurf.generate();
|
|
37
|
+
generated.windsurf = windsurfPaths;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (options.tool === 'cursor' || options.all) {
|
|
41
|
+
const cursor = new CursorGenerator(sessionPath, projectPath, framework);
|
|
42
|
+
const cursorPaths = await cursor.generate();
|
|
43
|
+
generated.cursor = cursorPaths;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (options.tool === 'vscode' || options.all) {
|
|
47
|
+
const vscode = new VSCodeGenerator(sessionPath, projectPath, framework);
|
|
48
|
+
const vscodePaths = await vscode.generate();
|
|
49
|
+
generated.vscode = vscodePaths;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return generated;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Generate only AGENTS.md (universal standard)
|
|
57
|
+
*/
|
|
58
|
+
async function generateAgentsMd(sessionPath, projectPath, framework) {
|
|
59
|
+
const generator = new AgentsMdGenerator(sessionPath, projectPath, framework);
|
|
60
|
+
return await generator.generate();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Generate Windsurf configurations
|
|
65
|
+
*/
|
|
66
|
+
async function generateWindsurf(sessionPath, projectPath, framework) {
|
|
67
|
+
const generator = new WindsurfGenerator(sessionPath, projectPath, framework);
|
|
68
|
+
return await generator.generate();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Generate Cursor configurations
|
|
73
|
+
*/
|
|
74
|
+
async function generateCursor(sessionPath, projectPath, framework) {
|
|
75
|
+
const generator = new CursorGenerator(sessionPath, projectPath, framework);
|
|
76
|
+
return await generator.generate();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Generate VS Code configurations
|
|
81
|
+
*/
|
|
82
|
+
async function generateVSCode(sessionPath, projectPath, framework) {
|
|
83
|
+
const generator = new VSCodeGenerator(sessionPath, projectPath, framework);
|
|
84
|
+
return await generator.generate();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
generateAll,
|
|
89
|
+
generateAgentsMd,
|
|
90
|
+
generateWindsurf,
|
|
91
|
+
generateCursor,
|
|
92
|
+
generateVSCode,
|
|
93
|
+
AgentsMdGenerator,
|
|
94
|
+
WindsurfGenerator,
|
|
95
|
+
CursorGenerator,
|
|
96
|
+
VSCodeGenerator,
|
|
97
|
+
ToolConfigGenerator
|
|
98
|
+
};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base class for generating tool-specific configuration files
|
|
6
|
+
* Transforms ADF framework outputs into IDE/tool configurations
|
|
7
|
+
*/
|
|
8
|
+
class ToolConfigGenerator {
|
|
9
|
+
constructor(sessionPath, projectPath, framework) {
|
|
10
|
+
this.sessionPath = sessionPath;
|
|
11
|
+
this.projectPath = projectPath;
|
|
12
|
+
this.framework = framework;
|
|
13
|
+
this.outputsPath = path.join(sessionPath, 'outputs');
|
|
14
|
+
this.metadata = null;
|
|
15
|
+
this.outputs = {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Load session metadata and framework outputs
|
|
20
|
+
*/
|
|
21
|
+
async initialize() {
|
|
22
|
+
// Load metadata
|
|
23
|
+
const metadataPath = path.join(this.sessionPath, '_metadata.json');
|
|
24
|
+
if (await fs.pathExists(metadataPath)) {
|
|
25
|
+
this.metadata = await fs.readJson(metadataPath);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Load framework outputs based on type
|
|
29
|
+
await this.loadFrameworkOutputs();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Load framework-specific output files
|
|
34
|
+
*/
|
|
35
|
+
async loadFrameworkOutputs() {
|
|
36
|
+
if (this.framework === 'rapid') {
|
|
37
|
+
await this.loadPRPOutputs();
|
|
38
|
+
} else if (this.framework === 'balanced') {
|
|
39
|
+
await this.loadBalancedOutputs();
|
|
40
|
+
} else if (this.framework === 'comprehensive') {
|
|
41
|
+
await this.loadBMADOutputs();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async loadPRPOutputs() {
|
|
46
|
+
const prpPath = path.join(this.outputsPath, 'prp.md');
|
|
47
|
+
if (await fs.pathExists(prpPath)) {
|
|
48
|
+
this.outputs.prp = await fs.readFile(prpPath, 'utf-8');
|
|
49
|
+
this.outputs.sections = this.parsePRPSections(this.outputs.prp);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async loadBalancedOutputs() {
|
|
54
|
+
const files = ['constitution.md', 'specification.md', 'plan.md', 'tasks.md'];
|
|
55
|
+
for (const file of files) {
|
|
56
|
+
const filePath = path.join(this.outputsPath, file);
|
|
57
|
+
if (await fs.pathExists(filePath)) {
|
|
58
|
+
const key = file.replace('.md', '');
|
|
59
|
+
this.outputs[key] = await fs.readFile(filePath, 'utf-8');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async loadBMADOutputs() {
|
|
65
|
+
const files = ['prd.md', 'architecture.md', 'stories.md'];
|
|
66
|
+
for (const file of files) {
|
|
67
|
+
const filePath = path.join(this.outputsPath, file);
|
|
68
|
+
if (await fs.pathExists(filePath)) {
|
|
69
|
+
const key = file.replace('.md', '');
|
|
70
|
+
this.outputs[key] = await fs.readFile(filePath, 'utf-8');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Parse PRP markdown into sections
|
|
77
|
+
*/
|
|
78
|
+
parsePRPSections(content) {
|
|
79
|
+
const sections = {};
|
|
80
|
+
const lines = content.split('\n');
|
|
81
|
+
let currentSection = null;
|
|
82
|
+
let currentContent = [];
|
|
83
|
+
|
|
84
|
+
for (const line of lines) {
|
|
85
|
+
// Check for main headings (## Section)
|
|
86
|
+
const headingMatch = line.match(/^##\s+(.+)$/);
|
|
87
|
+
if (headingMatch) {
|
|
88
|
+
// Save previous section
|
|
89
|
+
if (currentSection) {
|
|
90
|
+
sections[currentSection] = currentContent.join('\n').trim();
|
|
91
|
+
}
|
|
92
|
+
// Start new section
|
|
93
|
+
currentSection = headingMatch[1].toLowerCase().replace(/\s+/g, '_');
|
|
94
|
+
currentContent = [];
|
|
95
|
+
} else if (currentSection) {
|
|
96
|
+
currentContent.push(line);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Save last section
|
|
101
|
+
if (currentSection) {
|
|
102
|
+
sections[currentSection] = currentContent.join('\n').trim();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return sections;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Extract project name from metadata or session
|
|
110
|
+
*/
|
|
111
|
+
getProjectName() {
|
|
112
|
+
if (this.metadata && this.metadata.projectName) {
|
|
113
|
+
return this.metadata.projectName;
|
|
114
|
+
}
|
|
115
|
+
// Fallback to directory name
|
|
116
|
+
return path.basename(this.projectPath);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get session ID
|
|
121
|
+
*/
|
|
122
|
+
getSessionId() {
|
|
123
|
+
return path.basename(this.sessionPath);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Replace template variables in content
|
|
128
|
+
*/
|
|
129
|
+
replaceVariables(template, variables) {
|
|
130
|
+
let result = template;
|
|
131
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
132
|
+
const regex = new RegExp(`\\{${key}\\}`, 'g');
|
|
133
|
+
result = result.replace(regex, value || '');
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Extract content between markdown headings
|
|
140
|
+
*/
|
|
141
|
+
extractSection(content, sectionName) {
|
|
142
|
+
const lines = content.split('\n');
|
|
143
|
+
let inSection = false;
|
|
144
|
+
let sectionContent = [];
|
|
145
|
+
|
|
146
|
+
for (const line of lines) {
|
|
147
|
+
if (line.startsWith('##')) {
|
|
148
|
+
if (inSection) {
|
|
149
|
+
break; // End of our section
|
|
150
|
+
}
|
|
151
|
+
if (line.toLowerCase().includes(sectionName.toLowerCase())) {
|
|
152
|
+
inSection = true;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (inSection) {
|
|
157
|
+
sectionContent.push(line);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return sectionContent.join('\n').trim();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Write file to project root
|
|
166
|
+
*/
|
|
167
|
+
async writeToProject(fileName, content) {
|
|
168
|
+
const filePath = path.join(this.projectPath, fileName);
|
|
169
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
170
|
+
return filePath;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Ensure directory exists
|
|
175
|
+
*/
|
|
176
|
+
async ensureDir(dirPath) {
|
|
177
|
+
await fs.ensureDir(path.join(this.projectPath, dirPath));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Generate all configurations (override in subclasses)
|
|
182
|
+
*/
|
|
183
|
+
async generate() {
|
|
184
|
+
throw new Error('generate() must be implemented by subclass');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
module.exports = ToolConfigGenerator;
|