@iservu-inc/adf-cli 0.4.34 → 0.4.36

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/CHANGELOG.md CHANGED
@@ -5,6 +5,155 @@ All notable changes to `@iservu-inc/adf-cli` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.36] - 2025-10-04
9
+
10
+ ### ✨ Multi-IDE Improvements + Config Command Enhancement
11
+
12
+ **1. Added IDE Deployment to `adf config`**
13
+ - New category: "IDE Deployment"
14
+ - Deploy to multiple IDEs without re-running `adf init`
15
+ - Shows which IDEs are already deployed
16
+ - Pre-selects already deployed IDEs in checkbox
17
+ - Allows quick re-deployment or deployment to new IDEs
18
+
19
+ **New Config Menu:**
20
+ ```
21
+ ⚙️ ADF Configuration
22
+
23
+ ? Select configuration category:
24
+ > AI Provider Setup - ✓ Configured (Openai)
25
+ IDE Deployment - ✓ Deployed (Windsurf, Cursor)
26
+ Learning System - ✓ Active (5 sessions, 12 patterns)
27
+ ```
28
+
29
+ **Usage:**
30
+ ```bash
31
+ adf config
32
+ # Select "IDE Deployment"
33
+ # Choose IDEs to deploy to
34
+ # Done!
35
+ ```
36
+
37
+ **2. Improved Cursor Generator**
38
+ - Added `loadSessionAnswers()` - reads actual session data
39
+ - Added `extractTechStackFromAnswers()` - detects tech in answers
40
+ - Added `extractWhatBuildingFromAnswers()` - finds project goals
41
+ - Falls back to session answers when PRP sections empty
42
+ - Better content instead of "See PRP for details"
43
+
44
+ **3. Improved VSCode/Copilot Generator**
45
+ - Same answer extraction improvements as Cursor
46
+ - Better Copilot instructions with real content
47
+ - Falls back to session answers
48
+ - Improved tech stack detection
49
+
50
+ **Code Changes:**
51
+ - config.js:18-27 - Added IDE_DEPLOYMENT category
52
+ - config.js:221-331 - IDE deployment configuration logic
53
+ - cursor-generator.js:41-51 - Made generateRules async
54
+ - cursor-generator.js:53-129 - Enhanced generateRulesPRP with answer extraction
55
+ - cursor-generator.js:373-424 - Added helper methods
56
+ - vscode-generator.js:40-50 - Made generateCopilotInstructions async
57
+ - vscode-generator.js:52-124 - Enhanced generateCopilotPRP with answer extraction
58
+ - vscode-generator.js:402-451 - Added helper methods
59
+
60
+ **Impact:**
61
+ - ✅ `adf config` now lets you deploy to IDEs
62
+ - ✅ Cursor files now have real content
63
+ - ✅ VSCode Copilot instructions have real content
64
+ - ✅ All generators use session answers as fallback
65
+ - ✅ No more "See PRP for details" placeholders
66
+
67
+ ---
68
+
69
+ ## [0.4.35] - 2025-10-04
70
+
71
+ ### 🔧 MAJOR FIX: Windsurf Configuration - Activation Modes & Content Generation
72
+
73
+ **Fixed: Empty/Useless Windsurf Files**
74
+ - **Problem:** Generated Windsurf files had wrong activation modes and empty content
75
+ - **Issues:**
76
+ 1. Rules had `Manual` activation (useless) instead of `Always On`
77
+ 2. Workflows had no activation mode frontmatter
78
+ 3. Content showed "Not provided" instead of actual answers
79
+ 4. Not reading session data to extract meaningful information
80
+
81
+ **Solution:**
82
+ 1. **Added Proper Frontmatter with Activation Modes:**
83
+ - Rules: `trigger: always_on` (default for most rules)
84
+ - Workflows: `trigger: manual` with descriptions
85
+ - Follows Windsurf best practices
86
+
87
+ 2. **Reads Actual Session Answers:**
88
+ - New `loadSessionAnswers()` loads `_progress.json`
89
+ - Extracts real answers from interview session
90
+ - Falls back gracefully if data unavailable
91
+
92
+ 3. **Intelligent Content Parsing:**
93
+ - New `parseImplementationBlueprint()` extracts structured sections
94
+ - New `extractSubsection()` finds content by keywords
95
+ - New `extractTechStackFromAnswers()` finds tech mentions
96
+ - New `extractWhatBuildingFromAnswers()` finds project goals
97
+
98
+ **Before v0.4.35 (Broken):**
99
+ ```markdown
100
+ # Architecture - adf-test-project
101
+
102
+ ## Implementation Blueprint
103
+ Not provided
104
+
105
+ ## Data Model
106
+ Not provided
107
+ ```
108
+
109
+ **After v0.4.35 (Fixed):**
110
+ ```markdown
111
+ ---
112
+ trigger: always_on
113
+ ---
114
+
115
+ # Architecture - adf-test-project
116
+
117
+ ## Implementation Blueprint
118
+
119
+ ### Implementation Steps
120
+ **Project Goal:**
121
+ A performance website with nextjs frontend, postgres database...
122
+
123
+ ### Technical Approach
124
+ **Tech Stack:**
125
+ Next.js for frontend and backend, PostgreSQL for database...
126
+ ```
127
+
128
+ **Code Changes:**
129
+ - windsurf-generator.js:217-289 - Added frontmatter to project-context rule
130
+ - windsurf-generator.js:296-359 - Added frontmatter & parsing to architecture rule
131
+ - windsurf-generator.js:381-437 - Added frontmatter to coding-standards rule
132
+ - windsurf-generator.js:465-545 - Added frontmatter & descriptions to workflows
133
+ - windsurf-generator.js:633-754 - NEW helper methods for answer parsing
134
+
135
+ **New Helper Methods:**
136
+ - `loadSessionAnswers()` - Reads _progress.json
137
+ - `parseImplementationBlueprint()` - Parses blueprint into sections
138
+ - `extractSubsection()` - Finds content by keyword matching
139
+ - `extractTechStackFromAnswers()` - Detects tech stack in answers
140
+ - `extractWhatBuildingFromAnswers()` - Finds project goals
141
+
142
+ **Activation Modes Guide:**
143
+ - **Always On:** Default for rules - always active
144
+ - **Glob:** For file/pattern matching (not used yet)
145
+ - **Manual:** For workflows - user must activate
146
+ - **Model Decide:** AI chooses when to activate (requires description)
147
+
148
+ **Impact:**
149
+ - ✅ Windsurf rules now work properly with `Always On` activation
150
+ - ✅ Files contain actual project information, not placeholders
151
+ - ✅ Workflows have proper frontmatter with descriptions
152
+ - ✅ Better content extraction from session answers
153
+ - ✅ Fallback to PRP/specification if answers unavailable
154
+
155
+ ---
156
+
8
157
  ## [0.4.34] - 2025-10-04
9
158
 
10
159
  ### ✨ Feature: Multi-Tool Deployment Selection
@@ -15,14 +15,16 @@ const CONFIG_CATEGORIES = {
15
15
  description: 'Configure AI provider (Anthropic, OpenAI, Google Gemini, OpenRouter)',
16
16
  value: 'ai-provider'
17
17
  },
18
+ IDE_DEPLOYMENT: {
19
+ name: 'IDE Deployment',
20
+ description: 'Deploy requirements to IDEs (Windsurf, Cursor, VSCode, etc.)',
21
+ value: 'ide-deployment'
22
+ },
18
23
  LEARNING_SYSTEM: {
19
24
  name: 'Learning System',
20
25
  description: 'Manage interview learning data and preferences',
21
26
  value: 'learning'
22
27
  }
23
- // Future config categories can be added here:
24
- // PROJECT_SETTINGS: { name: 'Project Settings', description: '...', value: 'project' },
25
- // DEPLOYMENT: { name: 'Deployment Preferences', description: '...', value: 'deployment' },
26
28
  };
27
29
 
28
30
  /**
@@ -118,6 +120,7 @@ async function config() {
118
120
 
119
121
  // Check configuration status for all categories
120
122
  const aiStatus = await isAIConfigured(cwd);
123
+ const deploymentStatus = await getDeploymentStatus(cwd);
121
124
  const learningStatus = await getLearningStatus(cwd);
122
125
 
123
126
  // Build choices with status indicators
@@ -127,6 +130,11 @@ async function config() {
127
130
  value: CONFIG_CATEGORIES.AI_PROVIDER.value,
128
131
  short: CONFIG_CATEGORIES.AI_PROVIDER.name
129
132
  },
133
+ {
134
+ name: `${CONFIG_CATEGORIES.IDE_DEPLOYMENT.name} - ${displayDeploymentStatus(deploymentStatus)}`,
135
+ value: CONFIG_CATEGORIES.IDE_DEPLOYMENT.value,
136
+ short: CONFIG_CATEGORIES.IDE_DEPLOYMENT.name
137
+ },
130
138
  {
131
139
  name: `${CONFIG_CATEGORIES.LEARNING_SYSTEM.name} - ${displayLearningStatus(learningStatus)}`,
132
140
  value: CONFIG_CATEGORIES.LEARNING_SYSTEM.value,
@@ -160,11 +168,14 @@ async function config() {
160
168
  await configureAIProviderCategory(cwd, aiStatus);
161
169
  break;
162
170
 
171
+ case 'ide-deployment':
172
+ await configureIDEDeploymentCategory(cwd, deploymentStatus);
173
+ break;
174
+
163
175
  case 'learning':
164
176
  await configureLearningCategory(cwd, learningStatus);
165
177
  break;
166
178
 
167
- // Future categories will be handled here
168
179
  default:
169
180
  console.log(chalk.red('\n❌ Configuration category not implemented yet.\n'));
170
181
  }
@@ -207,6 +218,118 @@ async function configureAIProviderCategory(cwd, aiStatus) {
207
218
  }
208
219
  }
209
220
 
221
+ /**
222
+ * Check deployment status
223
+ */
224
+ async function getDeploymentStatus(projectPath = process.cwd()) {
225
+ const adfDir = path.join(projectPath, '.adf');
226
+
227
+ if (!await fs.pathExists(adfDir)) {
228
+ return { hasSession: false, tools: [] };
229
+ }
230
+
231
+ // Check for latest session
232
+ const sessionsDir = path.join(adfDir, 'sessions');
233
+ if (!await fs.pathExists(sessionsDir)) {
234
+ return { hasSession: false, tools: [] };
235
+ }
236
+
237
+ const sessions = await fs.readdir(sessionsDir);
238
+ if (sessions.length === 0) {
239
+ return { hasSession: false, tools: [] };
240
+ }
241
+
242
+ // Check which IDE tools have been deployed
243
+ const deployedTools = [];
244
+ const ideMarkers = [
245
+ { name: 'Windsurf', path: '.windsurf/rules' },
246
+ { name: 'Cursor', path: '.cursor/rules' },
247
+ { name: 'VSCode', path: '.github/copilot-instructions.md' },
248
+ { name: 'Claude Code', path: '.claude/commands' }
249
+ ];
250
+
251
+ for (const marker of ideMarkers) {
252
+ if (await fs.pathExists(path.join(projectPath, marker.path))) {
253
+ deployedTools.push(marker.name);
254
+ }
255
+ }
256
+
257
+ return {
258
+ hasSession: true,
259
+ sessionCount: sessions.length,
260
+ tools: deployedTools
261
+ };
262
+ }
263
+
264
+ /**
265
+ * Display deployment status
266
+ */
267
+ function displayDeploymentStatus(status) {
268
+ if (status.hasSession && status.tools.length > 0) {
269
+ return `${chalk.green('✓ Deployed')} ${chalk.gray(`(${status.tools.join(', ')})`)}`;
270
+ } else if (status.hasSession) {
271
+ return chalk.yellow('○ Session exists, not deployed');
272
+ } else {
273
+ return chalk.gray('○ No sessions yet');
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Configure IDE Deployment category
279
+ */
280
+ async function configureIDEDeploymentCategory(cwd, deploymentStatus) {
281
+ const { deployToTool } = require('./deploy');
282
+
283
+ console.log(chalk.gray('\n' + '─'.repeat(60) + '\n'));
284
+
285
+ if (!deploymentStatus.hasSession) {
286
+ console.log(chalk.yellow('⚠️ No ADF sessions found.\n'));
287
+ console.log(chalk.gray('You need to run `adf init` first to create requirements.'));
288
+ console.log(chalk.gray('Then you can deploy them to your IDE.\n'));
289
+ return;
290
+ }
291
+
292
+ console.log(chalk.cyan(`Found ${deploymentStatus.sessionCount} session(s)\n`));
293
+
294
+ if (deploymentStatus.tools.length > 0) {
295
+ console.log(chalk.green('✓ Already deployed to:'));
296
+ deploymentStatus.tools.forEach(tool => {
297
+ console.log(chalk.gray(` • ${tool}`));
298
+ });
299
+ console.log('');
300
+ }
301
+
302
+ // Ask which tools to deploy to
303
+ const { tools } = await inquirer.prompt([
304
+ {
305
+ type: 'checkbox',
306
+ name: 'tools',
307
+ message: 'Select IDEs to deploy to (space to select, enter to confirm):',
308
+ choices: [
309
+ { name: 'Windsurf', value: 'windsurf', checked: deploymentStatus.tools.includes('Windsurf') },
310
+ { name: 'Cursor', value: 'cursor', checked: deploymentStatus.tools.includes('Cursor') },
311
+ { name: 'VSCode/Copilot', value: 'vscode', checked: deploymentStatus.tools.includes('VSCode') },
312
+ { name: 'Claude Code', value: 'claude-code', checked: deploymentStatus.tools.includes('Claude Code') },
313
+ { name: 'Gemini CLI', value: 'gemini-cli' }
314
+ ],
315
+ validate: (answer) => {
316
+ if (answer.length === 0) {
317
+ return 'You must choose at least one IDE.';
318
+ }
319
+ return true;
320
+ }
321
+ }
322
+ ]);
323
+
324
+ // Deploy to each selected tool
325
+ for (const tool of tools) {
326
+ console.log('');
327
+ await deployToTool(tool, { silent: false });
328
+ }
329
+
330
+ console.log(chalk.green.bold('\n✅ Deployment complete!\n'));
331
+ }
332
+
210
333
  /**
211
334
  * Configure Learning System category
212
335
  */
@@ -42,7 +42,7 @@ class CursorGenerator extends ToolConfigGenerator {
42
42
  await this.ensureDir('.cursor');
43
43
 
44
44
  const content = this.framework === 'rapid' ?
45
- this.generateRulesPRP() :
45
+ await this.generateRulesPRP() :
46
46
  this.framework === 'balanced' ?
47
47
  this.generateRulesBalanced() :
48
48
  this.generateRulesBMAD();
@@ -50,9 +50,27 @@ class CursorGenerator extends ToolConfigGenerator {
50
50
  return await this.writeToProject('.cursor/rules', content);
51
51
  }
52
52
 
53
- generateRulesPRP() {
53
+ async generateRulesPRP() {
54
54
  const projectName = this.getProjectName();
55
55
  const sections = this.outputs.sections || {};
56
+ const answers = await this.loadSessionAnswers();
57
+
58
+ // Extract content with fallback to answers
59
+ let goal = sections['1._goal_definition'] || sections['goal_definition'];
60
+ let techStack = this.extractTechStack(sections);
61
+ let blueprint = sections['4._implementation_blueprint'] || sections['implementation_blueprint'];
62
+ let validation = sections['5._validation'] || sections['validation'];
63
+
64
+ // Fallback to extracted answers if sections are empty
65
+ if (!goal || goal.length < 20) {
66
+ const whatBuilding = this.extractWhatBuildingFromAnswers(answers);
67
+ if (whatBuilding) goal = whatBuilding;
68
+ }
69
+
70
+ if (!techStack || techStack.includes('See framework')) {
71
+ const techFromAnswers = this.extractTechStackFromAnswers(answers);
72
+ if (techFromAnswers) techStack = techFromAnswers;
73
+ }
56
74
 
57
75
  return `# ${projectName} - Cursor Rules
58
76
 
@@ -60,19 +78,19 @@ You are a senior developer working on ${projectName}.
60
78
 
61
79
  ## Project Goal
62
80
 
63
- ${sections['1._goal_definition'] || sections['goal_definition'] || 'See PRP for details'}
81
+ ${goal || 'See PRP for complete details'}
64
82
 
65
83
  ## Tech Stack
66
84
 
67
- ${this.extractTechStack(sections)}
85
+ ${techStack || 'See PRP for tech stack details'}
68
86
 
69
87
  ## Implementation Blueprint
70
88
 
71
- ${sections['4._implementation_blueprint'] || sections['implementation_blueprint'] || 'See PRP for details'}
89
+ ${blueprint || 'See PRP for implementation details'}
72
90
 
73
91
  ## Success Criteria
74
92
 
75
- ${sections['5._validation'] || sections['validation'] || 'See PRP for validation criteria'}
93
+ ${validation || 'See PRP for validation criteria'}
76
94
 
77
95
  ## Before Implementing Features
78
96
 
@@ -369,6 +387,59 @@ You can delete this .cursorrules file.
369
387
  return '0.3.0';
370
388
  }
371
389
  }
390
+
391
+ /**
392
+ * Load session answers from _progress.json
393
+ */
394
+ async loadSessionAnswers() {
395
+ const fs = require('fs-extra');
396
+ const path = require('path');
397
+ const progressPath = path.join(this.sessionPath, '_progress.json');
398
+
399
+ try {
400
+ if (await fs.pathExists(progressPath)) {
401
+ const progress = await fs.readJson(progressPath);
402
+ return progress.answers || {};
403
+ }
404
+ } catch (error) {
405
+ // Fall back to empty if can't load
406
+ }
407
+
408
+ return {};
409
+ }
410
+
411
+ /**
412
+ * Extract tech stack from any answer
413
+ */
414
+ extractTechStackFromAnswers(answers) {
415
+ for (const [questionId, answer] of Object.entries(answers)) {
416
+ if (typeof answer === 'string') {
417
+ const lower = answer.toLowerCase();
418
+ if (lower.includes('react') || lower.includes('vue') || lower.includes('angular') ||
419
+ lower.includes('node') || lower.includes('python') || lower.includes('next') ||
420
+ lower.includes('postgres') || lower.includes('mongo') || lower.includes('mysql')) {
421
+ return answer;
422
+ }
423
+ }
424
+ }
425
+ return null;
426
+ }
427
+
428
+ /**
429
+ * Extract "what are you building" from any answer
430
+ */
431
+ extractWhatBuildingFromAnswers(answers) {
432
+ for (const [questionId, answer] of Object.entries(answers)) {
433
+ if (questionId.toLowerCase().includes('goal') ||
434
+ questionId.toLowerCase().includes('building') ||
435
+ questionId.toLowerCase().includes('project')) {
436
+ if (typeof answer === 'string' && answer.length > 20) {
437
+ return answer;
438
+ }
439
+ }
440
+ }
441
+ return null;
442
+ }
372
443
  }
373
444
 
374
445
  module.exports = CursorGenerator;
@@ -41,7 +41,7 @@ class VSCodeGenerator extends ToolConfigGenerator {
41
41
  await this.ensureDir('.github');
42
42
 
43
43
  const content = this.framework === 'rapid' ?
44
- this.generateCopilotPRP() :
44
+ await this.generateCopilotPRP() :
45
45
  this.framework === 'balanced' ?
46
46
  this.generateCopilotBalanced() :
47
47
  this.generateCopilotBMAD();
@@ -49,23 +49,41 @@ class VSCodeGenerator extends ToolConfigGenerator {
49
49
  return await this.writeToProject('.github/copilot-instructions.md', content);
50
50
  }
51
51
 
52
- generateCopilotPRP() {
52
+ async generateCopilotPRP() {
53
53
  const projectName = this.getProjectName();
54
54
  const sections = this.outputs.sections || {};
55
+ const answers = await this.loadSessionAnswers();
56
+
57
+ // Extract content with fallback to answers
58
+ let goal = sections['1._goal_definition'] || sections['goal_definition'];
59
+ let techStack = this.extractTechStack(sections);
60
+ let blueprint = sections['4._implementation_blueprint'] || sections['implementation_blueprint'];
61
+ let validation = sections['5._validation'] || sections['validation'];
62
+
63
+ // Fallback to extracted answers if sections are empty
64
+ if (!goal || goal.length < 20) {
65
+ const whatBuilding = this.extractWhatBuildingFromAnswers(answers);
66
+ if (whatBuilding) goal = whatBuilding;
67
+ }
68
+
69
+ if (!techStack || techStack.includes('See framework')) {
70
+ const techFromAnswers = this.extractTechStackFromAnswers(answers);
71
+ if (techFromAnswers) techStack = techFromAnswers;
72
+ }
55
73
 
56
74
  return `# Copilot Instructions for ${projectName}
57
75
 
58
76
  ## Project Overview
59
77
 
60
- ${sections['1._goal_definition'] || sections['goal_definition'] || 'Software development project'}
78
+ ${goal || 'Software development project'}
61
79
 
62
80
  ## Tech Stack
63
81
 
64
- ${this.extractTechStack(sections)}
82
+ ${techStack || 'See PRP for tech stack'}
65
83
 
66
84
  ## Implementation Blueprint
67
85
 
68
- ${sections['4._implementation_blueprint'] || sections['implementation_blueprint'] || 'See PRP for details'}
86
+ ${blueprint || 'See PRP for implementation details'}
69
87
 
70
88
  ## Code Style
71
89
 
@@ -91,7 +109,7 @@ ${sections['4._implementation_blueprint'] || sections['implementation_blueprint'
91
109
 
92
110
  ## Success Criteria
93
111
 
94
- ${sections['5._validation'] || sections['validation'] || 'See PRP'}
112
+ ${validation || 'See PRP for validation criteria'}
95
113
 
96
114
  Ensure all code meets these criteria before considering it complete.
97
115
 
@@ -398,6 +416,57 @@ ${this.extractSection(prd, 'Performance') || '- Optimize critical paths\n- Monit
398
416
  return '0.3.0';
399
417
  }
400
418
  }
419
+
420
+ /**
421
+ * Load session answers from _progress.json
422
+ */
423
+ async loadSessionAnswers() {
424
+ const progressPath = path.join(this.sessionPath, '_progress.json');
425
+
426
+ try {
427
+ if (await fs.pathExists(progressPath)) {
428
+ const progress = await fs.readJson(progressPath);
429
+ return progress.answers || {};
430
+ }
431
+ } catch (error) {
432
+ // Fall back to empty if can't load
433
+ }
434
+
435
+ return {};
436
+ }
437
+
438
+ /**
439
+ * Extract tech stack from any answer
440
+ */
441
+ extractTechStackFromAnswers(answers) {
442
+ for (const [questionId, answer] of Object.entries(answers)) {
443
+ if (typeof answer === 'string') {
444
+ const lower = answer.toLowerCase();
445
+ if (lower.includes('react') || lower.includes('vue') || lower.includes('angular') ||
446
+ lower.includes('node') || lower.includes('python') || lower.includes('next') ||
447
+ lower.includes('postgres') || lower.includes('mongo') || lower.includes('mysql')) {
448
+ return answer;
449
+ }
450
+ }
451
+ }
452
+ return null;
453
+ }
454
+
455
+ /**
456
+ * Extract "what are you building" from any answer
457
+ */
458
+ extractWhatBuildingFromAnswers(answers) {
459
+ for (const [questionId, answer] of Object.entries(answers)) {
460
+ if (questionId.toLowerCase().includes('goal') ||
461
+ questionId.toLowerCase().includes('building') ||
462
+ questionId.toLowerCase().includes('project')) {
463
+ if (typeof answer === 'string' && answer.length > 20) {
464
+ return answer;
465
+ }
466
+ }
467
+ }
468
+ return null;
469
+ }
401
470
  }
402
471
 
403
472
  module.exports = VSCodeGenerator;
@@ -214,7 +214,11 @@ ${this.extractSection(this.outputs.architecture || '', 'System Overview') || 'Se
214
214
  let content;
215
215
  if (this.framework === 'rapid') {
216
216
  const sections = this.outputs.sections || {};
217
- content = `# Project Context - ${projectName}
217
+ content = `---
218
+ trigger: always_on
219
+ ---
220
+
221
+ # Project Context - ${projectName}
218
222
 
219
223
  ## Goal
220
224
 
@@ -235,7 +239,11 @@ All requirements are documented in: \`.adf/sessions/${this.getSessionId()}/outpu
235
239
  Read this file before implementing any features.
236
240
  `;
237
241
  } else if (this.framework === 'balanced') {
238
- content = `# Project Context - ${projectName}
242
+ content = `---
243
+ trigger: always_on
244
+ ---
245
+
246
+ # Project Context - ${projectName}
239
247
 
240
248
  ## Overview
241
249
 
@@ -257,7 +265,11 @@ Review these files before implementing:
257
265
  - Technical Plan: \`.adf/sessions/${this.getSessionId()}/outputs/plan.md\`
258
266
  `;
259
267
  } else {
260
- content = `# Project Context - ${projectName}
268
+ content = `---
269
+ trigger: always_on
270
+ ---
271
+
272
+ # Project Context - ${projectName}
261
273
 
262
274
  ## Product Overview
263
275
 
@@ -282,21 +294,52 @@ Review these files before implementing:
282
294
  async generateArchitectureRule() {
283
295
  const projectName = this.getProjectName();
284
296
 
297
+ // Load actual session answers for better content
298
+ const answers = await this.loadSessionAnswers();
299
+
285
300
  let content;
286
301
  if (this.framework === 'rapid') {
287
302
  const sections = this.outputs.sections || {};
288
- content = `# Architecture - ${projectName}
303
+ const blueprint = sections['4._implementation_blueprint'] || sections['implementation_blueprint'];
304
+
305
+ // Parse blueprint into structured sections
306
+ const parsed = this.parseImplementationBlueprint(blueprint || '', answers);
307
+
308
+ content = `---
309
+ trigger: always_on
310
+ ---
311
+
312
+ # Architecture - ${projectName}
289
313
 
290
314
  ## Implementation Blueprint
291
315
 
292
- ${sections['4._implementation_blueprint'] || sections['implementation_blueprint'] || 'See PRP'}
316
+ ### Implementation Steps
317
+ ${parsed.steps || 'Not provided'}
318
+
319
+ ### Data Model
320
+ ${parsed.dataModel || 'Not provided'}
321
+
322
+ ### API Design
323
+ ${parsed.apiDesign || 'Not provided'}
324
+
325
+ ### Edge Cases & Error Handling
326
+ ${parsed.errorHandling || 'Not provided'}
327
+
328
+ ### Technical Approach
329
+ ${parsed.technicalApproach || 'Not provided'}
330
+
331
+ ---
293
332
 
294
333
  ## Reference
295
334
 
296
335
  Full implementation details: \`.adf/sessions/${this.getSessionId()}/outputs/prp.md\`
297
336
  `;
298
337
  } else if (this.framework === 'balanced') {
299
- content = `# Architecture - ${projectName}
338
+ content = `---
339
+ trigger: always_on
340
+ ---
341
+
342
+ # Architecture - ${projectName}
300
343
 
301
344
  ${this.extractSection(this.outputs.specification || '', 'Architecture') || 'See specification'}
302
345
 
@@ -309,7 +352,11 @@ ${this.extractSection(this.outputs.plan || '', 'Architecture') || 'See technical
309
352
  Full architecture: \`.adf/sessions/${this.getSessionId()}/outputs/specification.md\`
310
353
  `;
311
354
  } else {
312
- content = `# Architecture - ${projectName}
355
+ content = `---
356
+ trigger: always_on
357
+ ---
358
+
359
+ # Architecture - ${projectName}
313
360
 
314
361
  ${this.extractSection(this.outputs.architecture || '', 'System Overview') || 'See architecture.md'}
315
362
 
@@ -331,7 +378,11 @@ Full architecture: \`.adf/sessions/${this.getSessionId()}/outputs/architecture.m
331
378
 
332
379
  let content;
333
380
  if (this.framework === 'rapid') {
334
- content = `# Coding Standards - ${projectName}
381
+ content = `---
382
+ trigger: always_on
383
+ ---
384
+
385
+ # Coding Standards - ${projectName}
335
386
 
336
387
  ## General Guidelines
337
388
 
@@ -346,7 +397,11 @@ Full architecture: \`.adf/sessions/${this.getSessionId()}/outputs/architecture.m
346
397
  See implementation blueprint in: \`.adf/sessions/${this.getSessionId()}/outputs/prp.md\`
347
398
  `;
348
399
  } else if (this.framework === 'balanced') {
349
- content = `# Coding Standards - ${projectName}
400
+ content = `---
401
+ trigger: always_on
402
+ ---
403
+
404
+ # Coding Standards - ${projectName}
350
405
 
351
406
  ${this.extractSection(this.outputs.plan || '', 'Code Style') || this.extractSection(this.outputs.plan || '', 'Coding Standards') || ''}
352
407
 
@@ -359,7 +414,11 @@ ${this.extractSection(this.outputs.constitution || '', 'Core Principles') || 'Fo
359
414
  Full standards: \`.adf/sessions/${this.getSessionId()}/outputs/plan.md\`
360
415
  `;
361
416
  } else {
362
- content = `# Coding Standards - ${projectName}
417
+ content = `---
418
+ trigger: always_on
419
+ ---
420
+
421
+ # Coding Standards - ${projectName}
363
422
 
364
423
  ${this.extractSection(this.outputs.prd || '', 'Code Quality') || ''}
365
424
 
@@ -403,7 +462,12 @@ Full requirements: \`.adf/sessions/${this.getSessionId()}/outputs/prd.md\`
403
462
  let content;
404
463
 
405
464
  if (this.framework === 'rapid') {
406
- content = `# Review Requirements
465
+ content = `---
466
+ trigger: manual
467
+ description: Review project requirements before implementing
468
+ ---
469
+
470
+ # Review Requirements
407
471
 
408
472
  Use this workflow to review requirements before implementing.
409
473
 
@@ -424,7 +488,12 @@ Use this workflow to review requirements before implementing.
424
488
  - How will success be measured?
425
489
  `;
426
490
  } else if (this.framework === 'balanced') {
427
- content = `# Review Requirements
491
+ content = `---
492
+ trigger: manual
493
+ description: Review project requirements before implementing
494
+ ---
495
+
496
+ # Review Requirements
428
497
 
429
498
  Use this workflow to review requirements before implementing.
430
499
 
@@ -447,7 +516,12 @@ Use this workflow to review requirements before implementing.
447
516
  - Are there any dependencies?
448
517
  `;
449
518
  } else {
450
- content = `# Review Requirements
519
+ content = `---
520
+ trigger: manual
521
+ description: Review project requirements before implementing
522
+ ---
523
+
524
+ # Review Requirements
451
525
 
452
526
  Use this workflow to review requirements before implementing.
453
527
 
@@ -477,7 +551,12 @@ Use this workflow to review requirements before implementing.
477
551
  let content;
478
552
 
479
553
  if (this.framework === 'balanced') {
480
- content = `# Implement Feature
554
+ content = `---
555
+ trigger: manual
556
+ description: Workflow for implementing a new feature
557
+ ---
558
+
559
+ # Implement Feature
481
560
 
482
561
  Use this workflow when implementing a feature.
483
562
 
@@ -511,7 +590,12 @@ Use this workflow when implementing a feature.
511
590
  - Tasks: \`.adf/sessions/${this.getSessionId()}/outputs/tasks.md\`
512
591
  `;
513
592
  } else {
514
- content = `# Implement User Story
593
+ content = `---
594
+ trigger: manual
595
+ description: Workflow for implementing a user story
596
+ ---
597
+
598
+ # Implement User Story
515
599
 
516
600
  Use this workflow when implementing a user story.
517
601
 
@@ -591,6 +675,132 @@ Use this workflow when implementing a user story.
591
675
  return '0.3.0';
592
676
  }
593
677
  }
678
+
679
+ /**
680
+ * Load session answers from _progress.json
681
+ */
682
+ async loadSessionAnswers() {
683
+ const fs = require('fs-extra');
684
+ const progressPath = path.join(this.sessionPath, '_progress.json');
685
+
686
+ try {
687
+ if (await fs.pathExists(progressPath)) {
688
+ const progress = await fs.readJson(progressPath);
689
+ return progress.answers || {};
690
+ }
691
+ } catch (error) {
692
+ // Fall back to empty if can't load
693
+ }
694
+
695
+ return {};
696
+ }
697
+
698
+ /**
699
+ * Parse implementation blueprint into structured sections
700
+ */
701
+ parseImplementationBlueprint(blueprint, answers) {
702
+ const parsed = {
703
+ steps: null,
704
+ dataModel: null,
705
+ apiDesign: null,
706
+ errorHandling: null,
707
+ technicalApproach: null
708
+ };
709
+
710
+ // If blueprint exists, parse it
711
+ if (blueprint && blueprint.length > 20) {
712
+ parsed.steps = this.extractSubsection(blueprint, ['implementation steps', 'steps to implement', 'development steps']);
713
+ parsed.dataModel = this.extractSubsection(blueprint, ['data model', 'database schema', 'data structure']);
714
+ parsed.apiDesign = this.extractSubsection(blueprint, ['api design', 'api endpoints', 'routes']);
715
+ parsed.errorHandling = this.extractSubsection(blueprint, ['error handling', 'edge cases']);
716
+ parsed.technicalApproach = this.extractSubsection(blueprint, ['technical approach', 'architecture', 'approach']);
717
+ }
718
+
719
+ // If still empty, try to extract from answers
720
+ if (!parsed.steps && answers) {
721
+ // Look for tech stack, implementation details in any answer
722
+ const techStack = this.extractTechStackFromAnswers(answers);
723
+ const whatBuilding = this.extractWhatBuildingFromAnswers(answers);
724
+
725
+ if (techStack) {
726
+ parsed.technicalApproach = `**Tech Stack:**\n${techStack}`;
727
+ }
728
+
729
+ if (whatBuilding) {
730
+ parsed.steps = `**Project Goal:**\n${whatBuilding}`;
731
+ }
732
+ }
733
+
734
+ return parsed;
735
+ }
736
+
737
+ /**
738
+ * Extract subsection from content by looking for keywords
739
+ */
740
+ extractSubsection(content, keywords) {
741
+ const lines = content.split('\n');
742
+ let inSection = false;
743
+ let sectionContent = [];
744
+
745
+ for (let i = 0; i < lines.length; i++) {
746
+ const line = lines[i];
747
+ const lowerLine = line.toLowerCase();
748
+
749
+ // Check if this line is a heading matching our keywords
750
+ if (line.match(/^#{2,4}\s+/)) {
751
+ const headingText = line.replace(/^#{2,4}\s+/, '').toLowerCase();
752
+
753
+ if (keywords.some(kw => headingText.includes(kw))) {
754
+ inSection = true;
755
+ continue;
756
+ } else if (inSection) {
757
+ // Hit a new heading, stop
758
+ break;
759
+ }
760
+ }
761
+
762
+ if (inSection && line.trim()) {
763
+ sectionContent.push(line);
764
+ }
765
+ }
766
+
767
+ const result = sectionContent.join('\n').trim();
768
+ return result.length > 10 ? result : null;
769
+ }
770
+
771
+ /**
772
+ * Extract tech stack from any answer
773
+ */
774
+ extractTechStackFromAnswers(answers) {
775
+ for (const [questionId, answer] of Object.entries(answers)) {
776
+ if (typeof answer === 'string') {
777
+ const lower = answer.toLowerCase();
778
+ // Look for mentions of frameworks, languages, databases
779
+ if (lower.includes('react') || lower.includes('vue') || lower.includes('angular') ||
780
+ lower.includes('node') || lower.includes('python') || lower.includes('next') ||
781
+ lower.includes('postgres') || lower.includes('mongo') || lower.includes('mysql')) {
782
+ return answer;
783
+ }
784
+ }
785
+ }
786
+ return null;
787
+ }
788
+
789
+ /**
790
+ * Extract "what are you building" from any answer
791
+ */
792
+ extractWhatBuildingFromAnswers(answers) {
793
+ for (const [questionId, answer] of Object.entries(answers)) {
794
+ if (questionId.toLowerCase().includes('goal') ||
795
+ questionId.toLowerCase().includes('building') ||
796
+ questionId.toLowerCase().includes('project')) {
797
+ if (typeof answer === 'string' && answer.length > 20) {
798
+ return answer;
799
+ }
800
+ }
801
+ }
802
+ return null;
803
+ }
594
804
  }
595
805
 
596
806
  module.exports = WindsurfGenerator;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iservu-inc/adf-cli",
3
- "version": "0.4.34",
3
+ "version": "0.4.36",
4
4
  "description": "CLI tool for AgentDevFramework - AI-assisted development framework with multi-provider AI support",
5
5
  "main": "index.js",
6
6
  "bin": {