convoke-agents 2.3.1 → 3.0.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/INSTALLATION.md +109 -86
  3. package/README.md +236 -104
  4. package/UPDATE-GUIDE.md +63 -23
  5. package/_bmad/bme/_enhance/config.yaml +8 -0
  6. package/_bmad/bme/_enhance/extensions/bmm-pm.yaml +9 -0
  7. package/_bmad/bme/_enhance/guides/.gitkeep +0 -0
  8. package/_bmad/bme/_enhance/guides/ENHANCE-GUIDE.md +252 -0
  9. package/_bmad/bme/_enhance/workflows/initiatives-backlog/SKILL.md +6 -0
  10. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/.gitkeep +0 -0
  11. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-01-init.md +106 -0
  12. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-02-gather.md +136 -0
  13. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-03-score.md +146 -0
  14. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-c/step-c-04-prioritize.md +181 -0
  15. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/.gitkeep +0 -0
  16. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-01-load.md +120 -0
  17. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-02-rescore.md +141 -0
  18. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-r/step-r-03-update.md +154 -0
  19. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/.gitkeep +0 -0
  20. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-01-ingest.md +86 -0
  21. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-02-extract.md +169 -0
  22. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-03-score.md +147 -0
  23. package/_bmad/bme/_enhance/workflows/initiatives-backlog/steps-t/step-t-04-update.md +155 -0
  24. package/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/backlog-format-spec.md +219 -0
  25. package/_bmad/bme/_enhance/workflows/initiatives-backlog/templates/rice-scoring-guide.md +154 -0
  26. package/_bmad/bme/_enhance/workflows/initiatives-backlog/workflow.md +88 -0
  27. package/_bmad/bme/_gyre/README.md +100 -0
  28. package/_bmad/bme/_gyre/agents/.gitkeep +0 -0
  29. package/_bmad/bme/_gyre/agents/model-curator.md +128 -0
  30. package/_bmad/bme/_gyre/agents/readiness-analyst.md +127 -0
  31. package/_bmad/bme/_gyre/agents/review-coach.md +130 -0
  32. package/_bmad/bme/_gyre/agents/stack-detective.md +125 -0
  33. package/_bmad/bme/_gyre/compass-routing-reference.md +168 -0
  34. package/_bmad/bme/_gyre/config.yaml +22 -0
  35. package/_bmad/bme/_gyre/contracts/.gitkeep +0 -0
  36. package/_bmad/bme/_gyre/contracts/gc1-stack-profile.md +152 -0
  37. package/_bmad/bme/_gyre/contracts/gc2-capabilities-manifest.md +189 -0
  38. package/_bmad/bme/_gyre/contracts/gc3-findings-report.md +197 -0
  39. package/_bmad/bme/_gyre/contracts/gc4-feedback-loop.md +209 -0
  40. package/_bmad/bme/_gyre/guides/ATLAS-USER-GUIDE.md +177 -0
  41. package/_bmad/bme/_gyre/guides/COACH-USER-GUIDE.md +172 -0
  42. package/_bmad/bme/_gyre/guides/LENS-USER-GUIDE.md +181 -0
  43. package/_bmad/bme/_gyre/guides/SCOUT-USER-GUIDE.md +158 -0
  44. package/_bmad/bme/_gyre/workflows/.gitkeep +0 -0
  45. package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-01-select-repos.md +55 -0
  46. package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-02-run-validation.md +78 -0
  47. package/_bmad/bme/_gyre/workflows/accuracy-validation/steps/step-03-score-results.md +143 -0
  48. package/_bmad/bme/_gyre/workflows/accuracy-validation/workflow.md +41 -0
  49. package/_bmad/bme/_gyre/workflows/delta-report/steps/step-01-load-history.md +63 -0
  50. package/_bmad/bme/_gyre/workflows/delta-report/steps/step-02-compute-delta.md +72 -0
  51. package/_bmad/bme/_gyre/workflows/delta-report/steps/step-03-present-delta.md +143 -0
  52. package/_bmad/bme/_gyre/workflows/delta-report/workflow.md +34 -0
  53. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-01-initialize.md +68 -0
  54. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-02-detect-stack.md +49 -0
  55. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-03-generate-model.md +52 -0
  56. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-04-analyze-gaps.md +42 -0
  57. package/_bmad/bme/_gyre/workflows/full-analysis/steps/step-05-review-findings.md +128 -0
  58. package/_bmad/bme/_gyre/workflows/full-analysis/workflow.md +39 -0
  59. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-01-load-manifest.md +70 -0
  60. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-02-observability-analysis.md +110 -0
  61. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-03-deployment-analysis.md +87 -0
  62. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-04-cross-domain-correlation.md +105 -0
  63. package/_bmad/bme/_gyre/workflows/gap-analysis/steps/step-05-present-findings.md +172 -0
  64. package/_bmad/bme/_gyre/workflows/gap-analysis/workflow.md +38 -0
  65. package/_bmad/bme/_gyre/workflows/model-generation/steps/step-01-load-profile.md +74 -0
  66. package/_bmad/bme/_gyre/workflows/model-generation/steps/step-02-generate-capabilities.md +116 -0
  67. package/_bmad/bme/_gyre/workflows/model-generation/steps/step-03-web-enrichment.md +89 -0
  68. package/_bmad/bme/_gyre/workflows/model-generation/steps/step-04-write-manifest.md +122 -0
  69. package/_bmad/bme/_gyre/workflows/model-generation/workflow.md +40 -0
  70. package/_bmad/bme/_gyre/workflows/model-review/steps/step-01-load-context.md +86 -0
  71. package/_bmad/bme/_gyre/workflows/model-review/steps/step-02-walkthrough.md +116 -0
  72. package/_bmad/bme/_gyre/workflows/model-review/steps/step-03-apply-amendments.md +92 -0
  73. package/_bmad/bme/_gyre/workflows/model-review/steps/step-04-capture-feedback.md +107 -0
  74. package/_bmad/bme/_gyre/workflows/model-review/steps/step-05-summary.md +60 -0
  75. package/_bmad/bme/_gyre/workflows/model-review/workflow.md +41 -0
  76. package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-01-scan-filesystem.md +176 -0
  77. package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-02-classify-stack.md +111 -0
  78. package/_bmad/bme/_gyre/workflows/stack-detection/steps/step-03-guard-questions.md +117 -0
  79. package/_bmad/bme/_gyre/workflows/stack-detection/workflow.md +42 -0
  80. package/_bmad/bme/_vortex/config.yaml +1 -1
  81. package/package.json +7 -2
  82. package/scripts/archive.js +304 -0
  83. package/scripts/convoke-doctor.js +146 -132
  84. package/scripts/docs-audit.js +21 -5
  85. package/scripts/install-gyre-agents.js +140 -0
  86. package/scripts/install-vortex-agents.js +0 -0
  87. package/scripts/update/lib/agent-registry.js +70 -0
  88. package/scripts/update/lib/refresh-installation.js +290 -29
  89. package/scripts/update/lib/validator.js +281 -1
@@ -44,6 +44,9 @@ async function validateInstallation(preMigrationData = {}, projectRoot) {
44
44
  // 7. Workflow step structure validation (P17 count + P20 filenames)
45
45
  checks.push(await validateWorkflowStepStructure(projectRoot));
46
46
 
47
+ // 8. Enhance module validation (optional — passes if not installed)
48
+ checks.push(await validateEnhanceModule(projectRoot));
49
+
47
50
  const allPassed = checks.every(c => c.passed);
48
51
 
49
52
  return {
@@ -348,6 +351,278 @@ async function validateWorkflowStepStructure(projectRoot) {
348
351
  return check;
349
352
  }
350
353
 
354
+ /**
355
+ * Validate Enhance module installation (optional — passes if not installed)
356
+ * Performs 5-point verification: directory, entry point, menu patch, config, filesystem consistency
357
+ * @param {string} projectRoot - Absolute path to project root
358
+ * @returns {Promise<object>} Validation check result
359
+ */
360
+ async function validateEnhanceModule(projectRoot) {
361
+ const check = {
362
+ name: 'Enhance module',
363
+ passed: false,
364
+ error: null
365
+ };
366
+
367
+ try {
368
+ const enhanceDir = path.join(projectRoot, '_bmad/bme/_enhance');
369
+
370
+ // Check 1: Directory exists — if not, Enhance is simply not installed (optional)
371
+ if (!fs.existsSync(enhanceDir)) {
372
+ check.passed = true;
373
+ check.info = 'Enhance module not installed (optional)';
374
+ return check;
375
+ }
376
+
377
+ const failures = [];
378
+
379
+ // Check 4 (first — needed by checks 2, 3, 5): Config valid
380
+ const configPath = path.join(enhanceDir, 'config.yaml');
381
+ let config = null;
382
+
383
+ if (!fs.existsSync(configPath)) {
384
+ failures.push('config.yaml not found');
385
+ } else {
386
+ try {
387
+ config = yaml.load(fs.readFileSync(configPath, 'utf8'));
388
+ } catch (err) {
389
+ failures.push(`config.yaml parse error: ${err.message}`);
390
+ }
391
+
392
+ if (config) {
393
+ const missing = [];
394
+ if (!config.name) missing.push('name');
395
+ if (!config.version) missing.push('version');
396
+ if (!config.description) missing.push('description');
397
+ if (!Array.isArray(config.workflows) || config.workflows.length === 0) {
398
+ missing.push('workflows (must be non-empty array)');
399
+ } else {
400
+ config.workflows.forEach((wf, i) => {
401
+ const wfMissing = [];
402
+ if (!wf.name) wfMissing.push('name');
403
+ if (!wf.entry) wfMissing.push('entry');
404
+ if (!wf.target_agent) wfMissing.push('target_agent');
405
+ if (!wf.menu_patch_name) wfMissing.push('menu_patch_name');
406
+ if (wfMissing.length > 0) {
407
+ missing.push(`workflows[${i}] missing: ${wfMissing.join(', ')}`);
408
+ }
409
+ });
410
+ }
411
+ if (missing.length > 0) {
412
+ failures.push(`config missing fields: ${missing.join('; ')}`);
413
+ }
414
+ }
415
+ }
416
+
417
+ // Checks 2, 3, 5 require a valid config with workflows
418
+ if (config && Array.isArray(config.workflows)) {
419
+ for (const wf of config.workflows) {
420
+ // Check 2: Workflow entry point resolves
421
+ if (wf.entry) {
422
+ const entryPath = path.join(enhanceDir, wf.entry);
423
+ if (!fs.existsSync(entryPath)) {
424
+ failures.push(`workflow entry point not found: ${wf.entry}`);
425
+ }
426
+ }
427
+
428
+ // Check 3: Menu patch present in target agent
429
+ if (wf.target_agent) {
430
+ const agentPath = path.join(projectRoot, '_bmad', wf.target_agent);
431
+ if (fs.existsSync(agentPath)) {
432
+ const agentContent = fs.readFileSync(agentPath, 'utf8');
433
+ const patchName = wf.menu_patch_name || wf.name;
434
+ if (!agentContent.includes(patchName)) {
435
+ failures.push(`menu patch "${patchName}" not found in ${wf.target_agent}`);
436
+ }
437
+ }
438
+ // If agent file doesn't exist, that's already caught by agent validation — not an Enhance-specific failure
439
+ }
440
+
441
+ // Check 5: Config-to-filesystem consistency — workflow directory exists
442
+ if (wf.name) {
443
+ const wfDir = path.join(enhanceDir, 'workflows', wf.name);
444
+ if (!fs.existsSync(wfDir)) {
445
+ failures.push(`workflow directory not found for registered workflow: ${wf.name}`);
446
+ }
447
+ }
448
+
449
+ // Check 6: Skill wrapper exists for workflow
450
+ if (wf.name) {
451
+ const skillWrapperPath = path.join(projectRoot, '.claude', 'skills', `bmad-enhance-${wf.name}`, 'SKILL.md');
452
+ if (!fs.existsSync(skillWrapperPath)) {
453
+ failures.push(`skill wrapper not found: .claude/skills/bmad-enhance-${wf.name}/SKILL.md`);
454
+ }
455
+ }
456
+ }
457
+ }
458
+
459
+ if (failures.length > 0) {
460
+ check.error = `Enhance: ${failures.join('; ')}`;
461
+ } else {
462
+ check.passed = true;
463
+ }
464
+ } catch (error) {
465
+ check.error = error.message;
466
+ }
467
+
468
+ return check;
469
+ }
470
+
471
+ /**
472
+ * Validate a SKILL.md file has required frontmatter fields
473
+ * @param {string} skillMdPath - Absolute path to SKILL.md file
474
+ * @returns {Promise<object>} Validation result { valid, errors }
475
+ */
476
+ async function validateSkillMd(skillMdPath) {
477
+ const errors = [];
478
+
479
+ if (!fs.existsSync(skillMdPath)) {
480
+ errors.push(`SKILL.md not found: ${skillMdPath}`);
481
+ return { valid: false, errors };
482
+ }
483
+
484
+ const content = fs.readFileSync(skillMdPath, 'utf8');
485
+
486
+ // Extract YAML frontmatter between --- delimiters
487
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
488
+ if (!fmMatch) {
489
+ errors.push('SKILL.md missing YAML frontmatter (--- delimiters)');
490
+ return { valid: false, errors };
491
+ }
492
+
493
+ let frontmatter;
494
+ try {
495
+ frontmatter = yaml.load(fmMatch[1]);
496
+ } catch (err) {
497
+ errors.push(`SKILL.md frontmatter parse error: ${err.message}`);
498
+ return { valid: false, errors };
499
+ }
500
+
501
+ if (!frontmatter || typeof frontmatter !== 'object') {
502
+ errors.push('SKILL.md frontmatter is empty or not an object');
503
+ return { valid: false, errors };
504
+ }
505
+
506
+ if (!frontmatter.name || typeof frontmatter.name !== 'string') {
507
+ errors.push('SKILL.md missing required field: name');
508
+ }
509
+
510
+ if (!frontmatter.description || typeof frontmatter.description !== 'string') {
511
+ errors.push('SKILL.md missing required field: description');
512
+ }
513
+
514
+ return { valid: errors.length === 0, errors };
515
+ }
516
+
517
+ /**
518
+ * Validate step files in a skill directory follow sequential numbering
519
+ * @param {string} skillDir - Absolute path to skill directory
520
+ * @returns {Promise<object>} Validation result { valid, errors }
521
+ */
522
+ async function validateStepFiles(skillDir) {
523
+ const errors = [];
524
+
525
+ if (!fs.existsSync(skillDir)) {
526
+ errors.push(`Skill directory not found: ${skillDir}`);
527
+ return { valid: false, errors };
528
+ }
529
+
530
+ // Collect step files from skill dir and steps/ subdirectory
531
+ const stepFiles = [];
532
+ const entries = fs.readdirSync(skillDir);
533
+
534
+ for (const entry of entries) {
535
+ if (/^step-\d+-/.test(entry) && entry.endsWith('.md')) {
536
+ stepFiles.push(entry);
537
+ }
538
+ }
539
+
540
+ const stepsSubdir = path.join(skillDir, 'steps');
541
+ if (fs.existsSync(stepsSubdir)) {
542
+ const subEntries = fs.readdirSync(stepsSubdir);
543
+ for (const entry of subEntries) {
544
+ if (/^step-\d+-/.test(entry) && entry.endsWith('.md')) {
545
+ stepFiles.push(entry);
546
+ }
547
+ }
548
+ }
549
+
550
+ if (stepFiles.length === 0) {
551
+ // No step files is valid — some skills are single-file (agent-activation type)
552
+ return { valid: true, errors };
553
+ }
554
+
555
+ // Extract step numbers and check for sequential numbering
556
+ const stepNumbers = stepFiles
557
+ .map(f => {
558
+ const match = f.match(/^step-(\d+)-/);
559
+ return match ? parseInt(match[1], 10) : null;
560
+ })
561
+ .filter(n => n !== null)
562
+ .sort((a, b) => a - b);
563
+
564
+ // Remove duplicates (same step number in root and steps/)
565
+ const uniqueSteps = [...new Set(stepNumbers)];
566
+
567
+ // Check for gaps in sequence
568
+ for (let i = 0; i < uniqueSteps.length - 1; i++) {
569
+ if (uniqueSteps[i + 1] - uniqueSteps[i] > 1) {
570
+ errors.push(
571
+ `Step numbering gap: step-${String(uniqueSteps[i]).padStart(2, '0')} to step-${String(uniqueSteps[i + 1]).padStart(2, '0')} (missing step-${String(uniqueSteps[i] + 1).padStart(2, '0')})`
572
+ );
573
+ }
574
+ }
575
+
576
+ return { valid: errors.length === 0, errors };
577
+ }
578
+
579
+ /**
580
+ * Validate skill cohesion — workflow.md exists if step files exist
581
+ * @param {string} skillDir - Absolute path to skill directory
582
+ * @returns {Promise<object>} Validation result { valid, errors }
583
+ */
584
+ async function validateSkillCohesion(skillDir) {
585
+ const errors = [];
586
+
587
+ if (!fs.existsSync(skillDir)) {
588
+ errors.push(`Skill directory not found: ${skillDir}`);
589
+ return { valid: false, errors };
590
+ }
591
+
592
+ const entries = fs.readdirSync(skillDir);
593
+ const hasStepFiles = entries.some(e => /^step-\d+-/.test(e) && e.endsWith('.md'));
594
+ const hasStepsSubdir = fs.existsSync(path.join(skillDir, 'steps'));
595
+ const hasWorkflow = entries.includes('workflow.md');
596
+
597
+ // If step files or steps/ subdirectory exist, workflow.md should too
598
+ if ((hasStepFiles || hasStepsSubdir) && !hasWorkflow) {
599
+ errors.push('Skill has step files but no workflow.md');
600
+ }
601
+
602
+ return { valid: errors.length === 0, errors };
603
+ }
604
+
605
+ /**
606
+ * Validate a complete skill package (SKILL.md + step files + cohesion)
607
+ * @param {string} skillDir - Absolute path to skill directory
608
+ * @returns {Promise<object>} Validation result { valid, errors }
609
+ */
610
+ async function validateSkill(skillDir) {
611
+ const allErrors = [];
612
+
613
+ const skillMdPath = path.join(skillDir, 'SKILL.md');
614
+ const skillMdResult = await validateSkillMd(skillMdPath);
615
+ allErrors.push(...skillMdResult.errors);
616
+
617
+ const stepResult = await validateStepFiles(skillDir);
618
+ allErrors.push(...stepResult.errors);
619
+
620
+ const cohesionResult = await validateSkillCohesion(skillDir);
621
+ allErrors.push(...cohesionResult.errors);
622
+
623
+ return { valid: allErrors.length === 0, errors: allErrors };
624
+ }
625
+
351
626
  module.exports = {
352
627
  validateInstallation,
353
628
  validateConfigStructure,
@@ -356,5 +631,10 @@ module.exports = {
356
631
  validateManifest,
357
632
  validateUserDataIntegrity,
358
633
  validateDeprecatedWorkflows,
359
- validateWorkflowStepStructure
634
+ validateWorkflowStepStructure,
635
+ validateEnhanceModule,
636
+ validateSkillMd,
637
+ validateStepFiles,
638
+ validateSkillCohesion,
639
+ validateSkill
360
640
  };