@iservu-inc/adf-cli 0.14.2 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +13 -13
  2. package/bin/adf.js +43 -26
  3. package/conductor/product-guidelines.md +1 -1
  4. package/conductor/product.md +2 -3
  5. package/conductor/tracks/bootstrap_agents_20260111/plan.md +5 -0
  6. package/lib/ai/ai-client.js +80 -35
  7. package/lib/ai/ai-config.js +199 -107
  8. package/lib/commands/config.js +15 -5
  9. package/lib/commands/deploy.js +5 -2
  10. package/lib/commands/init.js +14 -4
  11. package/lib/frameworks/interviewer.js +3 -3
  12. package/lib/frameworks/output-generators.js +7 -7
  13. package/lib/frameworks/questions.js +3 -3
  14. package/lib/generators/agents-md-generator.js +3 -3
  15. package/lib/generators/antigravity-generator.js +3 -3
  16. package/lib/generators/cursor-generator.js +3 -3
  17. package/lib/generators/deepagent-generator.js +5 -5
  18. package/lib/generators/gemini-cli-generator.js +5 -5
  19. package/lib/generators/index.js +15 -0
  20. package/lib/generators/vscode-generator.js +3 -3
  21. package/lib/generators/windsurf-generator.js +3 -3
  22. package/lib/templates/scripts/analyze-docs.js +14 -13
  23. package/lib/templates/scripts/config-helpers.js +1 -1
  24. package/lib/templates/shared/agents/analyst.md +1 -1
  25. package/lib/templates/shared/agents/architect.md +1 -1
  26. package/lib/templates/shared/agents/dev.md +1 -1
  27. package/lib/templates/shared/agents/pm.md +2 -2
  28. package/lib/templates/shared/agents/qa.md +1 -1
  29. package/lib/templates/shared/agents/sm.md +3 -3
  30. package/lib/templates/shared/memory/constitution.md +2 -2
  31. package/lib/templates/shared/templates/README.md +14 -14
  32. package/lib/templates/shared/templates/prd-template.md +1 -1
  33. package/lib/templates/shared/templates/spec-template.md +1 -1
  34. package/lib/utils/context-manager.js +11 -10
  35. package/lib/utils/framework-detector.js +5 -5
  36. package/lib/utils/project-detector.js +7 -7
  37. package/package.json +5 -5
@@ -4,6 +4,7 @@ const chalk = require('chalk');
4
4
  const fs = require('fs-extra');
5
5
  const path = require('path');
6
6
  const os = require('os');
7
+ const ora = require('ora');
7
8
 
8
9
  // Register autocomplete prompt
9
10
  inquirer.registerPrompt('autocomplete', autocomplete);
@@ -43,18 +44,17 @@ const AI_PROVIDERS = {
43
44
  website: 'https://ai.google.dev/',
44
45
  setup: 'Get your API key from https://aistudio.google.com/app/apikey',
45
46
  defaultModels: [
46
- // Gemini 2.0 Series (Latest - Experimental)
47
- 'gemini-2.0-flash-exp',
48
- 'gemini-2.0-flash-thinking-exp',
49
- // Gemini 1.5 Series (Stable - Recommended)
50
- 'gemini-1.5-pro',
51
- 'gemini-1.5-pro-latest',
52
- 'gemini-1.5-flash',
53
- 'gemini-1.5-flash-latest',
54
- 'gemini-1.5-flash-8b',
55
- // Gemini 1.0 Series (Legacy)
56
- 'gemini-pro',
57
- 'gemini-pro-vision'
47
+ // Gemini 3.0 Series (Latest)
48
+ 'gemini-3.0-pro',
49
+ 'gemini-3.0-flash',
50
+ 'gemini-3.0-deep-think',
51
+ // Gemini 2.5 Series (Stable)
52
+ 'gemini-2.5-pro',
53
+ 'gemini-2.5-flash',
54
+ 'gemini-2.5-flash-lite',
55
+ // Gemini 2.0 Series (Sunsetting)
56
+ 'gemini-2.0-flash',
57
+ 'gemini-2.0-pro'
58
58
  ]
59
59
  },
60
60
  OPENROUTER: {
@@ -70,6 +70,20 @@ const AI_PROVIDERS = {
70
70
  'google/gemini-pro-1.5',
71
71
  'meta-llama/llama-3.1-70b-instruct'
72
72
  ]
73
+ },
74
+ PERPLEXITY: {
75
+ id: 'perplexity',
76
+ name: 'Perplexity AI (Search + Reasoning)',
77
+ envVar: 'PERPLEXITY_API_KEY',
78
+ requiredFormat: 'pplx-',
79
+ website: 'https://www.perplexity.ai/api',
80
+ setup: 'Get your API key from https://www.perplexity.ai/settings/api',
81
+ defaultModels: [
82
+ 'sonar-pro',
83
+ 'sonar-reasoning-pro',
84
+ 'sonar',
85
+ 'sonar-deep-research'
86
+ ]
73
87
  }
74
88
  };
75
89
 
@@ -194,7 +208,7 @@ function loadEnvIntoProcess(envPath) {
194
208
  /**
195
209
  * Validate API key with provider by making a simple API call
196
210
  */
197
- async function validateAPIKeyWithProvider(provider, apiKey) {
211
+ async function validateAPIKeyWithProvider(provider, apiKey, model = null) {
198
212
  switch (provider.id) {
199
213
  case 'anthropic':
200
214
  const Anthropic = require('@anthropic-ai/sdk');
@@ -216,15 +230,28 @@ async function validateAPIKeyWithProvider(provider, apiKey) {
216
230
 
217
231
  case 'google':
218
232
  try {
219
- const { GoogleGenerativeAI } = require('@google/generative-ai');
220
- const genAI = new GoogleGenerativeAI(apiKey);
221
- // Use gemini-1.5-flash as it's the most available model for validation
222
- const model = genAI.getGenerativeModel({ model: 'gemini-1.5-flash' });
223
- // countTokens is a metadata call that validates the API key without incurring costs
224
- await model.countTokens("connectivity test");
233
+ const fetch = require('node-fetch');
234
+ // Use query param instead of header to rule out header-stripping issues
235
+ // Using v1beta endpoint as verified by user testing
236
+ const url = `https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`;
237
+
238
+ // List models is the most reliable way to validate an API key without assuming model availability
239
+ const response = await fetch(
240
+ url,
241
+ {
242
+ headers: {
243
+ 'Content-Type': 'application/json'
244
+ }
245
+ }
246
+ );
247
+
248
+ if (!response.ok) {
249
+ const errorText = await response.text();
250
+ throw new Error(`HTTP ${response.status}: ${errorText || response.statusText}`);
251
+ }
225
252
  } catch (error) {
226
- // If SDK fails, provide a clearer error message
227
- if (error.message.includes('API_KEY_INVALID') || error.message.includes('API key not found')) {
253
+ // If API call fails, provide a clearer error message
254
+ if (error.message.includes('400') || error.message.includes('API_KEY_INVALID') || error.message.includes('API key not found')) {
228
255
  throw new Error('Invalid Google API key. Please check your key at https://aistudio.google.com/app/apikey');
229
256
  }
230
257
  throw error;
@@ -264,74 +291,81 @@ async function fetchAvailableModels(provider, apiKey) {
264
291
  try {
265
292
  const Anthropic = require('@anthropic-ai/sdk');
266
293
  const anthropic = new Anthropic({ apiKey });
267
-
268
- // Try to fetch models from Anthropic API
269
- // Note: As of SDK v0.65.0, models endpoint may not be available
270
- // If it exists, it would be similar to OpenAI's API
271
- try {
272
- const response = await anthropic.models.list();
273
- const models = response.data
274
- .map(m => m.id)
275
- .sort();
276
-
277
- if (models.length > 0) {
278
- spinner.succeed(`Found ${models.length} Anthropic models`);
279
- return models;
280
- }
281
- } catch (listError) {
282
- // Models endpoint not available, use comprehensive default list
283
- spinner.warn('Model listing not available, using curated list');
294
+
295
+ const models = [];
296
+ let hasMore = true;
297
+ let afterId = undefined;
298
+
299
+ // Using pagination to fetch all models
300
+ while (hasMore) {
301
+ const response = await anthropic.models.list({
302
+ limit: 100,
303
+ ...(afterId && { after_id: afterId }),
304
+ });
305
+
306
+ models.push(...response.data);
307
+ hasMore = response.has_more;
308
+ if (hasMore && response.data.length > 0) {
309
+ afterId = response.last_id;
310
+ }
284
311
  }
285
312
 
286
- // Comprehensive list of known Anthropic models
287
- const knownModels = [
288
- // Claude 4.5 (Latest)
289
- 'claude-sonnet-4-5-20250929',
290
- 'claude-opus-4-5-20251101',
291
- // Claude 3.5
292
- 'claude-3-5-sonnet-20241022',
293
- 'claude-3-5-sonnet-20240620',
294
- 'claude-3-5-haiku-20241022',
295
- // Claude 3
296
- 'claude-3-opus-20240229',
297
- 'claude-3-sonnet-20240229',
298
- 'claude-3-haiku-20240307',
299
- // Claude 2 (Legacy)
300
- 'claude-2.1',
301
- 'claude-2.0',
302
- 'claude-instant-1.2'
303
- ];
304
-
305
- return knownModels;
313
+ if (models.length > 0) {
314
+ const modelIds = models.map(m => m.id).sort();
315
+ spinner.succeed(`Found ${modelIds.length} Anthropic models`);
316
+ return modelIds;
317
+ }
306
318
  } catch (error) {
307
- spinner.fail(`Failed to load Anthropic models: ${error.message}`);
308
- console.log(chalk.yellow(' Using default model list\n'));
309
- return provider.defaultModels;
319
+ spinner.warn(`Failed to fetch Anthropic models: ${error.message}`);
310
320
  }
321
+ console.log(chalk.yellow(' Using default model list\n'));
322
+ return provider.defaultModels;
311
323
 
312
324
  case 'openai':
313
- const OpenAI = require('openai');
314
- const openai = new OpenAI({ apiKey });
315
- const response = await openai.models.list();
316
-
317
- // Get ALL OpenAI models - DO NOT filter by prefix
318
- // This ensures we include o1, o3, and any future model families
319
- // Only filter to OpenAI-owned models to exclude fine-tuned models
320
- const allModels = response.data
321
- .filter(m => m.owned_by === 'openai' || m.owned_by === 'system' || m.owned_by === 'openai-internal')
322
- .map(m => m.id)
323
- .sort();
324
-
325
- spinner.succeed(`Found ${allModels.length} OpenAI models`);
326
- return allModels.length > 0 ? allModels : provider.defaultModels;
325
+ try {
326
+ const OpenAI = require('openai');
327
+ const openai = new OpenAI({ apiKey });
328
+ const response = await openai.models.list();
329
+
330
+ // Filter for chat-capable models and exclude audio/image models
331
+ const chatModels = response.data
332
+ .filter(m => {
333
+ const id = m.id;
334
+ // Exclude specific non-chat models
335
+ if (id.includes('dall-e') || id.includes('tts') || id.includes('whisper') ||
336
+ id.includes('embedding') || id.includes('moderation')) return false;
337
+
338
+ // Include known chat families
339
+ if (id.startsWith('gpt-') || id.startsWith('o1') || id.startsWith('o3')) return true;
340
+
341
+ return false;
342
+ })
343
+ .map(m => m.id)
344
+ .sort();
345
+
346
+ if (chatModels.length > 0) {
347
+ spinner.succeed(`Found ${chatModels.length} OpenAI chat models`);
348
+ return chatModels;
349
+ }
350
+ } catch (error) {
351
+ spinner.warn(`Failed to fetch OpenAI models: ${error.message}`);
352
+ }
353
+ console.log(chalk.yellow(' Using default model list\n'));
354
+ return provider.defaultModels;
327
355
 
328
356
  case 'google':
329
357
  try {
330
358
  const fetch = require('node-fetch');
331
359
 
332
- // Use Google's REST API to list available models
360
+ // Use Google's REST API to list available models (using stable v1 with header)
333
361
  const response = await fetch(
334
- `https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(apiKey)}`
362
+ `https://generativelanguage.googleapis.com/v1/models`,
363
+ {
364
+ headers: {
365
+ 'x-goog-api-key': apiKey,
366
+ 'Content-Type': 'application/json'
367
+ }
368
+ }
335
369
  );
336
370
 
337
371
  if (!response.ok) {
@@ -355,15 +389,40 @@ async function fetchAvailableModels(provider, apiKey) {
355
389
  return availableModels;
356
390
  }
357
391
  }
358
-
359
- // Fallback to default list
360
- spinner.warn('No models found via API, using curated list');
361
- return provider.defaultModels;
362
392
  } catch (error) {
363
- spinner.fail(`Failed to fetch Google models: ${error.message}`);
364
- console.log(chalk.yellow(' Using default model list\n'));
365
- return provider.defaultModels;
393
+ spinner.warn(`Failed to fetch Google models: ${error.message}`);
366
394
  }
395
+ console.log(chalk.yellow(' Using default model list\n'));
396
+ return provider.defaultModels;
397
+
398
+ case 'perplexity':
399
+ try {
400
+ // Perplexity doesn't have a list models endpoint, so we validate known ones
401
+ // by performing a very cheap token count or dry-run if possible,
402
+ // but for now we rely on the default list as it is static but we can try to validate
403
+ // the API key with a simple request to 'sonar' which is their fastest model.
404
+ const OpenAI = require('openai');
405
+ const client = new OpenAI({
406
+ apiKey,
407
+ baseURL: 'https://api.perplexity.ai'
408
+ });
409
+
410
+ // Simple validation check
411
+ await client.models.list(); // Some OpenAI compatible endpoints support this, let's try
412
+
413
+ // If list() works, we filter, otherwise we might fallback to defaults.
414
+ // Note: Perplexity API documentation says standard OpenAI endpoints are supported.
415
+ // If list() returns models, great. If not, we use defaults.
416
+ // However, Perplexity typically DOES NOT implement the /models endpoint fully dynamically
417
+ // like OpenAI. It often returns a static list or might error.
418
+ // Let's assume for safety we use the defaults but verified via a simple call.
419
+
420
+ spinner.succeed('Perplexity API connected');
421
+ return provider.defaultModels; // Return defaults as they are curated for the platform
422
+ } catch(error) {
423
+ spinner.warn(`Perplexity connectivity check failed: ${error.message}`);
424
+ }
425
+ return provider.defaultModels;
367
426
 
368
427
  case 'openrouter':
369
428
  try {
@@ -528,6 +587,7 @@ async function configureAIProvider(projectPath = process.cwd()) {
528
587
 
529
588
  // Check if API key exists
530
589
  let apiKey = process.env[selectedProvider.envVar] || existingEnv[selectedProvider.envVar];
590
+ let isNewKey = false;
531
591
 
532
592
  if (!apiKey) {
533
593
  console.log(chalk.yellow(`\n⚠️ ${selectedProvider.envVar} not found\n`));
@@ -553,6 +613,7 @@ async function configureAIProvider(projectPath = process.cwd()) {
553
613
  ]);
554
614
 
555
615
  apiKey = manualKey.trim();
616
+ isNewKey = true;
556
617
 
557
618
  // Save to .env file
558
619
  await saveToEnvFile(envPath, selectedProvider.envVar, apiKey);
@@ -568,32 +629,61 @@ async function configureAIProvider(projectPath = process.cwd()) {
568
629
  }
569
630
 
570
631
  // Validate API key by testing basic connectivity
571
- const ora = require('ora');
572
- const validationSpinner = ora('Validating API key...').start();
632
+ // Skip validation ONLY if we are using an existing key that matches the currently active provider
633
+ // This avoids redundant checks, but we still validate if the user explicitly switched providers
634
+ // or entered a new key.
635
+
636
+ const isActiveProvider = (process.env.ADF_CURRENT_PROVIDER === selectedProvider.id);
637
+ const shouldSkipValidation = !isNewKey && isActiveProvider;
638
+
639
+ if (shouldSkipValidation) {
640
+ console.log(chalk.gray(' Skipping validation for currently active provider...'));
641
+ } else {
642
+ const ora = require('ora');
643
+ const validationSpinner = ora('Validating API key...').start();
573
644
 
574
- try {
575
- await validateAPIKeyWithProvider(selectedProvider, apiKey);
576
- validationSpinner.succeed(chalk.green('API key validated successfully'));
577
- } catch (error) {
578
- validationSpinner.fail(chalk.red('API key validation failed'));
579
- console.log(chalk.red(`\nError: ${error.message}\n`));
580
- console.log(chalk.yellow('The API key appears to be invalid or has connectivity issues.'));
581
- console.log(chalk.gray('Please check your API key and try again.\n'));
645
+ try {
646
+ // For Google, we need to pass a model to validate properly
647
+ const validationModel = selectedProvider.id === 'google' ? 'gemini-1.5-flash' : null;
648
+ await validateAPIKeyWithProvider(selectedProvider, apiKey, validationModel);
649
+ validationSpinner.succeed(chalk.green('API key validated successfully'));
650
+ } catch (error) {
651
+ validationSpinner.fail(chalk.red('API key validation failed'));
652
+ console.log(chalk.red(`\nError: ${error.message}\n`));
653
+ console.log(chalk.yellow('The API key appears to be invalid or has connectivity issues.'));
654
+
655
+ // Check if this was a stored key (from .env or environment)
656
+ // If so, delete it immediately to prevent infinite loops and force fresh entry
657
+ console.log(chalk.yellow('\n🗑️ Removing invalid stored API key to allow re-entry...'));
658
+
659
+ // Always clear from process.env
660
+ delete process.env[selectedProvider.envVar];
661
+ process.env[selectedProvider.envVar] = ''; // Ensure it is empty string at minimum
662
+
663
+ // Always clear from .env file
664
+ if (existingEnv[selectedProvider.envVar]) {
665
+ delete existingEnv[selectedProvider.envVar];
666
+ await saveEnvFile(envPath, existingEnv);
667
+ }
668
+ console.log(chalk.green('✓ Invalid key removed.'));
582
669
 
583
- const { retry } = await inquirer.prompt([
584
- {
585
- type: 'confirm',
586
- name: 'retry',
587
- message: 'Try again with a different API key?',
588
- default: true
589
- }
590
- ]);
670
+ console.log(chalk.gray('Please check your API key and try again.\n'));
591
671
 
592
- if (retry) {
593
- return configureAIProvider(projectPath);
594
- } else {
595
- process.exit(1);
596
- }
672
+ const { retry } = await inquirer.prompt([
673
+ {
674
+ type: 'confirm',
675
+ name: 'retry',
676
+ message: 'Try again with a different API key?',
677
+ default: true
678
+ }
679
+ ]);
680
+
681
+ if (retry) {
682
+ return configureAIProvider(projectPath);
683
+ } else {
684
+ process.exit(1);
685
+ }
686
+ }
597
687
  }
598
688
 
599
689
  // Fetch available models (only after successful validation)
@@ -755,6 +845,8 @@ module.exports = {
755
845
  configureAIProvider,
756
846
  detectAvailableProviders,
757
847
  validateAPIKey,
848
+ validateAPIKeyWithProvider,
849
+ fetchAvailableModels,
758
850
  AI_PROVIDERS,
759
851
  loadEnvIntoProcess,
760
852
  getEnvFilePath,
@@ -22,8 +22,8 @@ const CONFIG_CATEGORIES = {
22
22
  value: 'ai-analysis'
23
23
  },
24
24
  IDE_DEPLOYMENT: {
25
- name: 'IDE Deployment',
26
- description: 'Deploy requirements to IDEs (Windsurf, Cursor, VSCode, etc.)',
25
+ name: 'Tool Deployment',
26
+ description: 'Deploy requirements to 12+ AI-native tools (Windsurf, Cursor, Kiro, Trae, etc.)',
27
27
  value: 'ide-deployment'
28
28
  },
29
29
  LEARNING_SYSTEM: {
@@ -206,6 +206,9 @@ async function config() {
206
206
  default:
207
207
  console.log(chalk.red('\n❌ Configuration category not implemented yet.\n'));
208
208
  }
209
+
210
+ // Safe exit to prevent hanging processes while avoiding race conditions
211
+ setTimeout(() => process.exit(0), 100);
209
212
  }
210
213
 
211
214
  /**
@@ -331,17 +334,24 @@ async function configureIDEDeploymentCategory(cwd, deploymentStatus) {
331
334
  {
332
335
  type: 'checkbox',
333
336
  name: 'tools',
334
- message: 'Select IDEs to deploy to (space to select, enter to confirm):',
337
+ message: 'Select tools to deploy to (space to select, enter to confirm):',
335
338
  choices: [
336
339
  { name: 'Windsurf', value: 'windsurf', checked: deploymentStatus.tools.includes('Windsurf') },
337
340
  { name: 'Cursor', value: 'cursor', checked: deploymentStatus.tools.includes('Cursor') },
338
341
  { name: 'VSCode/Copilot', value: 'vscode', checked: deploymentStatus.tools.includes('VSCode') },
342
+ { name: 'Kiro AI', value: 'kiro' },
343
+ { name: 'Trae AI', value: 'trae' },
344
+ { name: 'Zed Editor', value: 'zed' },
339
345
  { name: 'Claude Code', value: 'claude-code', checked: deploymentStatus.tools.includes('Claude Code') },
340
- { name: 'Gemini CLI', value: 'gemini-cli' }
346
+ { name: 'OpenCode CLI', value: 'opencode' },
347
+ { name: 'Gemini CLI', value: 'gemini-cli' },
348
+ { name: 'DeepAgent', value: 'deepagent' },
349
+ { name: 'Codex CLI', value: 'codex-cli' },
350
+ { name: 'Antigravity', value: 'antigravity' }
341
351
  ],
342
352
  validate: (answer) => {
343
353
  if (answer.length === 0) {
344
- return 'You must choose at least one IDE.';
354
+ return 'You must choose at least one tool.';
345
355
  }
346
356
  return true;
347
357
  }
@@ -324,8 +324,11 @@ async function deploy(tool, options) {
324
324
  if (options.list) {
325
325
  console.log(chalk.cyan.bold('\n📋 Available Deployment Tools:\n'));
326
326
 
327
- for (const [key, value] of Object.entries(TOOLS)) {
328
- console.log(chalk.green(` ${key.padEnd(20)}`) + chalk.gray(`${value.name} (${value.configFile})`));
327
+ const sortedTools = Object.entries(TOOLS).sort((a, b) => a[0].localeCompare(b[0]));
328
+
329
+ for (const [key, value] of sortedTools) {
330
+ const configInfo = value.configFile.endsWith('/') ? `${value.configFile}*` : value.configFile;
331
+ console.log(chalk.green(` ${key.padEnd(20)}`) + chalk.gray(`${value.name.padEnd(25)} (${configInfo})`));
329
332
  }
330
333
 
331
334
  console.log(chalk.yellow('\nUsage: adf deploy <tool>\n'));
@@ -35,8 +35,18 @@ async function init(options) {
35
35
  const hasOtherFrameworks = detectedFrameworks.filter(f => f !== 'adf').length > 0;
36
36
 
37
37
  if (hasOtherFrameworks) {
38
+ const frameworkNames = {
39
+ 'agent-native': 'Agent-Native',
40
+ 'openspec': 'OpenSpec',
41
+ 'specification-driven': 'Specification-Driven'
42
+ };
43
+
44
+ const displayNames = detectedFrameworks
45
+ .filter(f => f !== 'adf')
46
+ .map(f => frameworkNames[f] || f);
47
+
38
48
  console.log(chalk.cyan('📦 Existing Development Frameworks Detected:'));
39
- console.log(chalk.gray(` ${detectedFrameworks.join(', ')}\n`));
49
+ console.log(chalk.gray(` ${displayNames.join(', ')}\n`));
40
50
 
41
51
  const { action } = await inquirer.prompt([
42
52
  {
@@ -283,13 +293,13 @@ async function init(options) {
283
293
 
284
294
  if (options.rapid) {
285
295
  workflow = 'rapid';
286
- console.log(chalk.blue('\nUsing: PRP Framework (Rapid Development) - from --rapid flag'));
296
+ console.log(chalk.blue('\nUsing: Level 1: Rapid (Agent-Native) - from --rapid flag'));
287
297
  } else if (options.balanced) {
288
298
  workflow = 'balanced';
289
- console.log(chalk.blue('\nUsing: PRP + Spec-Kit (Balanced) - from --balanced flag'));
299
+ console.log(chalk.blue('\nUsing: Level 2: Balanced (OpenSpec) - from --balanced flag'));
290
300
  } else if (options.comprehensive) {
291
301
  workflow = 'comprehensive';
292
- console.log(chalk.blue('\nUsing: BMAD Framework (Comprehensive) - from --comprehensive flag'));
302
+ console.log(chalk.blue('\nUsing: Level 3: Comprehensive (Agent-Native) - from --comprehensive flag'));
293
303
  } else {
294
304
  // Interactive workflow selection
295
305
  workflow = await getWorkflowRecommendation(projectType);
@@ -460,9 +460,9 @@ class Interviewer {
460
460
 
461
461
  getFrameworkName() {
462
462
  const names = {
463
- rapid: 'Product Requirement Prompt (PRP)',
464
- balanced: 'Specification + Implementation Plan',
465
- comprehensive: 'BMAD Framework Document'
463
+ rapid: 'Rapid (Agent-Native)',
464
+ balanced: 'Balanced (OpenSpec)',
465
+ comprehensive: 'Comprehensive (Agent-Native)'
466
466
  };
467
467
  return names[this.framework] || 'Requirements Document';
468
468
  }
@@ -7,7 +7,7 @@ const path = require('path');
7
7
  */
8
8
 
9
9
  async function generatePRP(answers, outputPath) {
10
- const prp = `# Product Requirement Prompt (PRP)
10
+ const prp = `# Rapid (Agent-Native) Specification (PRP)
11
11
 
12
12
  **Generated:** ${new Date().toISOString()}
13
13
 
@@ -136,7 +136,7 @@ ${answers['bal-26'] || 'Not provided'}
136
136
  `;
137
137
 
138
138
  // Specification
139
- const specification = `# Specification
139
+ const specification = `# Balanced (OpenSpec) Specification
140
140
 
141
141
  **Generated:** ${new Date().toISOString()}
142
142
 
@@ -309,21 +309,21 @@ async function generateBMAD(answers, outputPath) {
309
309
  // Full BMAD implementation would include PRD, Architecture, and Stories
310
310
  await generateBalanced(answers, outputPath);
311
311
 
312
- const prd = `# Product Requirements Document
312
+ const prd = `# Comprehensive (Agent-Native) PRD
313
313
 
314
314
  **Generated:** ${new Date().toISOString()}
315
315
 
316
316
  ## Business Overview
317
- [BMAD questions would populate this section]
317
+ [Agent-Native questions would populate this section]
318
318
 
319
319
  ## Market Analysis
320
- [BMAD questions would populate this section]
320
+ [Agent-Native questions would populate this section]
321
321
 
322
322
  ## Complete Requirements
323
323
  See specification.md for detailed requirements.
324
324
  `;
325
325
 
326
- const architecture = `# Architecture Document
326
+ const architecture = `# Comprehensive (Agent-Native) Architecture
327
327
 
328
328
  **Generated:** ${new Date().toISOString()}
329
329
 
@@ -331,7 +331,7 @@ See specification.md for detailed requirements.
331
331
  See plan.md for technical architecture details.
332
332
 
333
333
  ## Advanced Architecture Considerations
334
- [BMAD-specific architecture questions would populate this]
334
+ [Agent-Native architecture questions would populate this]
335
335
  `;
336
336
 
337
337
  await fs.writeFile(path.join(outputPath, 'prd.md'), prd, 'utf-8');
@@ -1,5 +1,5 @@
1
1
  // Framework Question Definitions
2
- // PRP (Rapid), Balanced (PRP+Spec-Kit), BMAD (Comprehensive)
2
+ // Level 1: Rapid (Agent-Native), Level 2: Balanced (OpenSpec), Level 3: Comprehensive (Agent-Native)
3
3
 
4
4
  const prpQuestions = [
5
5
  // Phase 1: Goal Definition (4 questions)
@@ -258,7 +258,7 @@ const prpQuestions = [
258
258
  }
259
259
  ];
260
260
 
261
- // Balanced Framework Questions (PRP + Spec-Kit additions)
261
+ // Balanced Framework Questions (Level 2: OpenSpec)
262
262
  const balancedQuestions = [
263
263
  ...prpQuestions, // Include all PRP questions
264
264
 
@@ -631,7 +631,7 @@ const balancedQuestions = [
631
631
  }
632
632
  ];
633
633
 
634
- // BMAD Framework Questions (All Balanced + Additional 50 for BMAD = 100 total)
634
+ // Comprehensive Framework Questions (Level 3: Agent-Native)
635
635
  const bmadQuestions = [
636
636
  ...balancedQuestions, // Include all 50 Balanced questions
637
637
 
@@ -259,7 +259,7 @@ When working on this project, you MUST:
259
259
  ---
260
260
 
261
261
  *Generated by [ADF CLI](https://www.npmjs.com/package/@iservu-inc/adf-cli) v${this.getADFVersion()}*
262
- *Framework: Rapid Development (PRP) | Session: ${sessionId}*
262
+ *Framework: Rapid (Agent-Native) | Session: ${sessionId}*
263
263
  `;
264
264
  }
265
265
 
@@ -400,7 +400,7 @@ When working on this project, you MUST:
400
400
  ---
401
401
 
402
402
  *Generated by [ADF CLI](https://www.npmjs.com/package/@iservu-inc/adf-cli) v${this.getADFVersion()}*
403
- *Framework: Balanced (Specification-Driven) | Session: ${sessionId}*
403
+ *Framework: Balanced (OpenSpec) | Session: ${sessionId}*
404
404
  `;
405
405
  }
406
406
 
@@ -609,7 +609,7 @@ When working on this project, you MUST:
609
609
  ---
610
610
 
611
611
  *Generated by [ADF CLI](https://www.npmjs.com/package/@iservu-inc/adf-cli) v${this.getADFVersion()}*
612
- *Framework: BMAD Comprehensive (Enterprise) | Session: ${sessionId}*
612
+ *Framework: Comprehensive (Agent-Native) | Session: ${sessionId}*
613
613
  `;
614
614
  }
615
615
 
@@ -117,9 +117,9 @@ agents:
117
117
  */
118
118
  getFrameworkName() {
119
119
  const names = {
120
- 'rapid': 'Rapid Development (PRP)',
121
- 'balanced': 'Balanced (Specification-Driven)',
122
- 'comprehensive': 'BMAD Comprehensive (Enterprise)'
120
+ 'rapid': 'Rapid (Agent-Native)',
121
+ 'balanced': 'Balanced (OpenSpec)',
122
+ 'comprehensive': 'Comprehensive (Agent-Native)'
123
123
  };
124
124
  return names[this.framework] || this.framework;
125
125
  }
@@ -123,7 +123,7 @@ ${validation || 'See PRP for validation criteria'}
123
123
 
124
124
  ---
125
125
 
126
- *Generated by ADF CLI v${this.getADFVersion()} from PRP framework*
126
+ *Generated by ADF CLI v${this.getADFVersion()} from Rapid (Agent-Native) framework*
127
127
  *This is a .cursor/rules file. The legacy .cursorrules file is deprecated.*
128
128
  `;
129
129
  }
@@ -201,7 +201,7 @@ ${this.extractSection(plan, 'Code Style') || this.extractSection(plan, 'Coding S
201
201
 
202
202
  ---
203
203
 
204
- *Generated by ADF CLI v${this.getADFVersion()} from Balanced framework*
204
+ *Generated by ADF CLI v${this.getADFVersion()} from Balanced (OpenSpec) framework*
205
205
  *This is a .cursor/rules file. The legacy .cursorrules file is deprecated.*
206
206
  `;
207
207
  }
@@ -288,7 +288,7 @@ ${this.extractSection(architecture, 'System Overview') || this.extractSection(ar
288
288
 
289
289
  ---
290
290
 
291
- *Generated by ADF CLI v${this.getADFVersion()} from BMAD framework*
291
+ *Generated by ADF CLI v${this.getADFVersion()} from Comprehensive (Agent-Native) framework*
292
292
  *This is a .cursor/rules file. The legacy .cursorrules file is deprecated.*
293
293
  `;
294
294
  }