convoke-agents 2.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.
- package/CHANGELOG.md +920 -0
- package/INSTALLATION.md +230 -0
- package/LICENSE +21 -0
- package/README.md +330 -0
- package/UPDATE-GUIDE.md +220 -0
- package/_bmad/bme/_vortex/README.md +150 -0
- package/_bmad/bme/_vortex/agents/contextualization-expert.md +100 -0
- package/_bmad/bme/_vortex/agents/discovery-empathy-expert.md +117 -0
- package/_bmad/bme/_vortex/agents/hypothesis-engineer.md +117 -0
- package/_bmad/bme/_vortex/agents/lean-experiments-specialist.md +118 -0
- package/_bmad/bme/_vortex/agents/learning-decision-expert.md +117 -0
- package/_bmad/bme/_vortex/agents/production-intelligence-specialist.md +117 -0
- package/_bmad/bme/_vortex/agents/research-convergence-specialist.md +117 -0
- package/_bmad/bme/_vortex/compass-routing-reference.md +312 -0
- package/_bmad/bme/_vortex/config.yaml +46 -0
- package/_bmad/bme/_vortex/contracts/hc1-empathy-artifacts.md +152 -0
- package/_bmad/bme/_vortex/contracts/hc2-problem-definition.md +125 -0
- package/_bmad/bme/_vortex/contracts/hc3-hypothesis-contract.md +112 -0
- package/_bmad/bme/_vortex/contracts/hc4-experiment-context.md +140 -0
- package/_bmad/bme/_vortex/contracts/hc5-signal-report.md +130 -0
- package/_bmad/bme/_vortex/examples/hc2-example-problem-definition.md +85 -0
- package/_bmad/bme/_vortex/examples/hc3-example-hypothesis-contract.md +103 -0
- package/_bmad/bme/_vortex/examples/hc5-example-signal-report.md +76 -0
- package/_bmad/bme/_vortex/guides/EMMA-USER-GUIDE.md +232 -0
- package/_bmad/bme/_vortex/guides/ISLA-USER-GUIDE.md +208 -0
- package/_bmad/bme/_vortex/guides/LIAM-USER-GUIDE.md +255 -0
- package/_bmad/bme/_vortex/guides/MAX-USER-GUIDE.md +213 -0
- package/_bmad/bme/_vortex/guides/MILA-USER-GUIDE.md +235 -0
- package/_bmad/bme/_vortex/guides/NOAH-USER-GUIDE.md +258 -0
- package/_bmad/bme/_vortex/guides/WADE-USER-GUIDE.md +245 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/empathy-map.template.md +143 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-01-define-user.md +60 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-02-says-thinks.md +67 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-03-does-feels.md +79 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-04-pain-points.md +87 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-05-gains.md +103 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/steps/step-06-synthesize.md +104 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/validate.md +117 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/empathy-map/workflow.md +44 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-01-define-requirements.md +85 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-02-user-flows.md +59 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-03-information-architecture.md +68 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-04-wireframe-sketch.md +97 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-05-components.md +128 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/steps/step-06-synthesize.md +83 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/wireframe.template.md +287 -0
- package/_bmad/bme/_vortex/workflows/_deprecated/wireframe/workflow.md +44 -0
- package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-01-setup.md +66 -0
- package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-02-context.md +93 -0
- package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-03-risk-mapping.md +103 -0
- package/_bmad/bme/_vortex/workflows/assumption-mapping/steps/step-04-synthesize.md +101 -0
- package/_bmad/bme/_vortex/workflows/assumption-mapping/workflow.md +49 -0
- package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-01-setup.md +81 -0
- package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-02-context.md +67 -0
- package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-03-classification.md +98 -0
- package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-04-evidence.md +100 -0
- package/_bmad/bme/_vortex/workflows/behavior-analysis/steps/step-05-synthesize.md +174 -0
- package/_bmad/bme/_vortex/workflows/behavior-analysis/workflow.md +52 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/contextualize-scope.template.md +67 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-01-list-opportunities.md +47 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-02-define-criteria.md +36 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-03-evaluate-opportunities.md +30 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-04-define-boundaries.md +32 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-05-validate-fit.md +28 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/steps/step-06-synthesize.md +36 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/validate.md +30 -0
- package/_bmad/bme/_vortex/workflows/contextualize-scope/workflow.md +59 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/empathy-map.template.md +143 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-01-define-user.md +60 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-02-says-thinks.md +67 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-03-does-feels.md +79 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-04-pain-points.md +87 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-05-gains.md +103 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/steps/step-06-synthesize.md +107 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/validate.md +117 -0
- package/_bmad/bme/_vortex/workflows/empathy-map/workflow.md +45 -0
- package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-01-setup.md +66 -0
- package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-02-context.md +77 -0
- package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-03-design.md +114 -0
- package/_bmad/bme/_vortex/workflows/experiment-design/steps/step-04-synthesize.md +128 -0
- package/_bmad/bme/_vortex/workflows/experiment-design/workflow.md +51 -0
- package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-01-setup.md +66 -0
- package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-02-context.md +80 -0
- package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-03-brainwriting.md +79 -0
- package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-04-assumption-mapping.md +102 -0
- package/_bmad/bme/_vortex/workflows/hypothesis-engineering/steps/step-05-synthesize.md +130 -0
- package/_bmad/bme/_vortex/workflows/hypothesis-engineering/workflow.md +52 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/lean-experiment.template.md +29 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-01-hypothesis.md +58 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-02-design.md +68 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-03-metrics.md +73 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-04-run.md +75 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-05-analyze.md +84 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/steps/step-06-decide.md +111 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/validate.md +30 -0
- package/_bmad/bme/_vortex/workflows/lean-experiment/workflow.md +26 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/lean-persona.template.md +163 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-01-define-job.md +72 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-02-current-solution.md +83 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-03-problem-contexts.md +90 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-04-forces-anxieties.md +98 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-05-success-criteria.md +103 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/steps/step-06-synthesize.md +129 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/validate.md +30 -0
- package/_bmad/bme/_vortex/workflows/lean-persona/workflow.md +50 -0
- package/_bmad/bme/_vortex/workflows/learning-card/learning-card.template.md +179 -0
- package/_bmad/bme/_vortex/workflows/learning-card/steps/step-01-experiment-context.md +100 -0
- package/_bmad/bme/_vortex/workflows/learning-card/steps/step-02-raw-results.md +125 -0
- package/_bmad/bme/_vortex/workflows/learning-card/steps/step-03-analysis.md +125 -0
- package/_bmad/bme/_vortex/workflows/learning-card/steps/step-04-validated-learning.md +139 -0
- package/_bmad/bme/_vortex/workflows/learning-card/steps/step-05-implications.md +134 -0
- package/_bmad/bme/_vortex/workflows/learning-card/steps/step-06-synthesize.md +121 -0
- package/_bmad/bme/_vortex/workflows/learning-card/validate.md +134 -0
- package/_bmad/bme/_vortex/workflows/learning-card/workflow.md +51 -0
- package/_bmad/bme/_vortex/workflows/mvp/mvp.template.md +40 -0
- package/_bmad/bme/_vortex/workflows/mvp/steps/step-01-riskiest-assumption.md +17 -0
- package/_bmad/bme/_vortex/workflows/mvp/steps/step-02-success-criteria.md +13 -0
- package/_bmad/bme/_vortex/workflows/mvp/steps/step-03-smallest-test.md +13 -0
- package/_bmad/bme/_vortex/workflows/mvp/steps/step-04-scope-features.md +13 -0
- package/_bmad/bme/_vortex/workflows/mvp/steps/step-05-build-measure-learn.md +13 -0
- package/_bmad/bme/_vortex/workflows/mvp/steps/step-06-synthesize.md +28 -0
- package/_bmad/bme/_vortex/workflows/mvp/validate.md +30 -0
- package/_bmad/bme/_vortex/workflows/mvp/workflow.md +36 -0
- package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-01-setup.md +102 -0
- package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-02-context.md +81 -0
- package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-03-pattern-identification.md +88 -0
- package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-04-theme-clustering.md +100 -0
- package/_bmad/bme/_vortex/workflows/pattern-mapping/steps/step-05-synthesize.md +135 -0
- package/_bmad/bme/_vortex/workflows/pattern-mapping/workflow.md +58 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/pivot-patch-persevere.template.md +201 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-01-evidence-review.md +125 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-02-hypothesis-assessment.md +132 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-03-option-analysis.md +167 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-04-stakeholder-input.md +141 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-05-decision.md +161 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/steps/step-06-action-plan.md +188 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/validate.md +159 -0
- package/_bmad/bme/_vortex/workflows/pivot-patch-persevere/workflow.md +51 -0
- package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-01-setup.md +97 -0
- package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-02-context.md +86 -0
- package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-03-jtbd-reframing.md +88 -0
- package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-04-pains-gains-revision.md +76 -0
- package/_bmad/bme/_vortex/workflows/pivot-resynthesis/steps/step-05-synthesize.md +158 -0
- package/_bmad/bme/_vortex/workflows/pivot-resynthesis/workflow.md +52 -0
- package/_bmad/bme/_vortex/workflows/product-vision/product-vision.template.md +147 -0
- package/_bmad/bme/_vortex/workflows/product-vision/steps/step-01-define-problem.md +89 -0
- package/_bmad/bme/_vortex/workflows/product-vision/steps/step-02-target-market.md +91 -0
- package/_bmad/bme/_vortex/workflows/product-vision/steps/step-03-unique-approach.md +87 -0
- package/_bmad/bme/_vortex/workflows/product-vision/steps/step-04-future-state.md +100 -0
- package/_bmad/bme/_vortex/workflows/product-vision/steps/step-05-principles.md +92 -0
- package/_bmad/bme/_vortex/workflows/product-vision/steps/step-06-synthesize.md +170 -0
- package/_bmad/bme/_vortex/workflows/product-vision/validate.md +30 -0
- package/_bmad/bme/_vortex/workflows/product-vision/workflow.md +55 -0
- package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-01-setup.md +84 -0
- package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-02-context.md +66 -0
- package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-03-monitoring.md +74 -0
- package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-04-prioritization.md +97 -0
- package/_bmad/bme/_vortex/workflows/production-monitoring/steps/step-05-synthesize.md +183 -0
- package/_bmad/bme/_vortex/workflows/production-monitoring/workflow.md +52 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/proof-of-concept.template.md +25 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-01-risk.md +79 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-02-scope.md +105 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-03-build.md +92 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-04-test.md +103 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-05-evaluate.md +114 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/steps/step-06-document.md +125 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/validate.md +30 -0
- package/_bmad/bme/_vortex/workflows/proof-of-concept/workflow.md +26 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/proof-of-value.template.md +29 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-01-value-hypothesis.md +75 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-02-validation-design.md +94 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-03-willingness.md +96 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-04-test.md +107 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-05-analyze.md +116 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/steps/step-06-document.md +147 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/validate.md +30 -0
- package/_bmad/bme/_vortex/workflows/proof-of-value/workflow.md +26 -0
- package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-01-setup.md +69 -0
- package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-02-context.md +70 -0
- package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-03-jtbd-framing.md +81 -0
- package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-04-pains-gains.md +77 -0
- package/_bmad/bme/_vortex/workflows/research-convergence/steps/step-05-synthesize.md +147 -0
- package/_bmad/bme/_vortex/workflows/research-convergence/workflow.md +50 -0
- package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-01-setup.md +68 -0
- package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-02-context.md +67 -0
- package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-03-signal-analysis.md +85 -0
- package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-04-anomaly-detection.md +93 -0
- package/_bmad/bme/_vortex/workflows/signal-interpretation/steps/step-05-synthesize.md +163 -0
- package/_bmad/bme/_vortex/workflows/signal-interpretation/workflow.md +52 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-01-discovery-scope.md +77 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-02-research-methods.md +152 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-03-research-plan.md +159 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-04-execute.md +169 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-05-organize-data.md +149 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/steps/step-06-synthesize.md +159 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/user-discovery.template.md +231 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/validate.md +153 -0
- package/_bmad/bme/_vortex/workflows/user-discovery/workflow.md +45 -0
- package/_bmad/bme/_vortex/workflows/user-interview/steps/step-01-research-goals.md +100 -0
- package/_bmad/bme/_vortex/workflows/user-interview/steps/step-02-interview-script.md +123 -0
- package/_bmad/bme/_vortex/workflows/user-interview/steps/step-03-recruitment.md +144 -0
- package/_bmad/bme/_vortex/workflows/user-interview/steps/step-04-conduct.md +154 -0
- package/_bmad/bme/_vortex/workflows/user-interview/steps/step-05-findings.md +163 -0
- package/_bmad/bme/_vortex/workflows/user-interview/steps/step-06-synthesize.md +171 -0
- package/_bmad/bme/_vortex/workflows/user-interview/user-interview.template.md +250 -0
- package/_bmad/bme/_vortex/workflows/user-interview/validate.md +142 -0
- package/_bmad/bme/_vortex/workflows/user-interview/workflow.md +51 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-01-current-state.md +56 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-02-evidence-inventory.md +70 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-03-gap-analysis.md +76 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-04-stream-evaluation.md +57 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-05-recommendation.md +65 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/steps/step-06-navigation-plan.md +72 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/validate.md +75 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/vortex-navigation.template.md +105 -0
- package/_bmad/bme/_vortex/workflows/vortex-navigation/workflow.md +54 -0
- package/index.js +56 -0
- package/package.json +77 -0
- package/scripts/README.md +226 -0
- package/scripts/convoke-doctor.js +322 -0
- package/scripts/docs-audit.js +584 -0
- package/scripts/install-all-agents.js +9 -0
- package/scripts/install-vortex-agents.js +208 -0
- package/scripts/postinstall.js +104 -0
- package/scripts/update/convoke-migrate.js +169 -0
- package/scripts/update/convoke-update.js +272 -0
- package/scripts/update/convoke-version.js +134 -0
- package/scripts/update/lib/agent-registry.js +144 -0
- package/scripts/update/lib/backup-manager.js +243 -0
- package/scripts/update/lib/config-merger.js +242 -0
- package/scripts/update/lib/migration-runner.js +367 -0
- package/scripts/update/lib/refresh-installation.js +171 -0
- package/scripts/update/lib/utils.js +96 -0
- package/scripts/update/lib/validator.js +360 -0
- package/scripts/update/lib/version-detector.js +241 -0
- package/scripts/update/migrations/1.0.x-to-1.3.0.js +128 -0
- package/scripts/update/migrations/1.1.x-to-1.3.0.js +29 -0
- package/scripts/update/migrations/1.2.x-to-1.3.0.js +29 -0
- package/scripts/update/migrations/1.3.x-to-1.5.0.js +29 -0
- package/scripts/update/migrations/1.4.x-to-1.5.0.js +29 -0
- package/scripts/update/migrations/1.5.x-to-1.6.0.js +95 -0
- package/scripts/update/migrations/1.6.x-to-1.7.0.js +29 -0
- package/scripts/update/migrations/1.7.x-to-2.0.0.js +31 -0
- package/scripts/update/migrations/registry.js +194 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const fs = require('fs-extra');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const { findProjectRoot } = require('./update/lib/utils');
|
|
9
|
+
const {
|
|
10
|
+
AGENTS, WORKFLOWS, WORKFLOW_NAMES
|
|
11
|
+
} = require('./update/lib/agent-registry');
|
|
12
|
+
|
|
13
|
+
// --- Constants (Task 1.1, 1.2) ---
|
|
14
|
+
|
|
15
|
+
/** User-facing docs to audit, relative to project root. */
|
|
16
|
+
const USER_FACING_DOCS = [
|
|
17
|
+
'docs/agents.md',
|
|
18
|
+
'docs/development.md',
|
|
19
|
+
'docs/testing.md',
|
|
20
|
+
'docs/faq.md',
|
|
21
|
+
'README.md',
|
|
22
|
+
'UPDATE-GUIDE.md',
|
|
23
|
+
'INSTALLATION.md',
|
|
24
|
+
'CHANGELOG.md',
|
|
25
|
+
'BMAD-METHOD-COMPATIBILITY.md',
|
|
26
|
+
'_bmad/bme/_vortex/guides/EMMA-USER-GUIDE.md',
|
|
27
|
+
'_bmad/bme/_vortex/guides/ISLA-USER-GUIDE.md',
|
|
28
|
+
'_bmad/bme/_vortex/guides/MILA-USER-GUIDE.md',
|
|
29
|
+
'_bmad/bme/_vortex/guides/LIAM-USER-GUIDE.md',
|
|
30
|
+
'_bmad/bme/_vortex/guides/WADE-USER-GUIDE.md',
|
|
31
|
+
'_bmad/bme/_vortex/guides/NOAH-USER-GUIDE.md',
|
|
32
|
+
'_bmad/bme/_vortex/guides/MAX-USER-GUIDE.md',
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/** Written number words to digit mapping for stale reference detection. */
|
|
36
|
+
const WORD_TO_NUM = {
|
|
37
|
+
'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5,
|
|
38
|
+
'six': 6, 'seven': 7, 'eight': 8, 'nine': 9, 'ten': 10,
|
|
39
|
+
'eleven': 11, 'twelve': 12, 'thirteen': 13, 'fourteen': 14,
|
|
40
|
+
'fifteen': 15, 'sixteen': 16, 'seventeen': 17, 'eighteen': 18,
|
|
41
|
+
'nineteen': 19, 'twenty': 20, 'twenty-one': 21, 'twenty-two': 22,
|
|
42
|
+
'twenty-three': 23, 'twenty-four': 24, 'twenty-five': 25,
|
|
43
|
+
'twenty-six': 26, 'twenty-seven': 27, 'twenty-eight': 28,
|
|
44
|
+
'twenty-nine': 29, 'thirty': 30,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// --- Check Functions ---
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Check for stale numeric references and contradictory terminology.
|
|
51
|
+
* Detects wrong agent/workflow counts (digits and written-out numbers)
|
|
52
|
+
* and contradictory word patterns ("original agents", etc.).
|
|
53
|
+
*
|
|
54
|
+
* @param {string} content - File content
|
|
55
|
+
* @param {string} filePath - Relative file path (for reporting)
|
|
56
|
+
* @returns {Array<object>} findings
|
|
57
|
+
*/
|
|
58
|
+
function checkStaleReferences(content, filePath) {
|
|
59
|
+
const findings = [];
|
|
60
|
+
const lines = content.split('\n');
|
|
61
|
+
const agentCount = AGENTS.length;
|
|
62
|
+
const workflowCount = WORKFLOWS.length;
|
|
63
|
+
|
|
64
|
+
// Build regex for written-out numbers
|
|
65
|
+
const wordKeys = Object.keys(WORD_TO_NUM).join('|');
|
|
66
|
+
|
|
67
|
+
const digitAgentRe = /\b(\d+)\s+agents?\b/gi;
|
|
68
|
+
const wordAgentRe = new RegExp(`\\b(${wordKeys})\\s+agents?\\b`, 'gi');
|
|
69
|
+
const digitWorkflowRe = /\b(\d+)\s+workflows?\b/gi;
|
|
70
|
+
const wordWorkflowRe = new RegExp(`\\b(${wordKeys})\\s+workflows?\\b`, 'gi');
|
|
71
|
+
|
|
72
|
+
// Contradictory terminology patterns
|
|
73
|
+
const contradictoryPatterns = [
|
|
74
|
+
{ re: /\boriginal\s+agents?\b/gi, expected: `current ${agentCount}-agent Vortex` },
|
|
75
|
+
{ re: /\boriginal\s+(?:four|4)\b/gi, expected: `current ${agentCount} agents` },
|
|
76
|
+
{ re: /\binitial\s+agents?\b/gi, expected: `current ${agentCount}-agent Vortex` },
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
for (let i = 0; i < lines.length; i++) {
|
|
80
|
+
const line = lines[i];
|
|
81
|
+
const lineNum = i + 1;
|
|
82
|
+
|
|
83
|
+
let m;
|
|
84
|
+
|
|
85
|
+
// Digit agent counts (e.g., "4 agents")
|
|
86
|
+
digitAgentRe.lastIndex = 0;
|
|
87
|
+
while ((m = digitAgentRe.exec(line)) !== null) {
|
|
88
|
+
const num = parseInt(m[1], 10);
|
|
89
|
+
if (num !== agentCount && num > 0 && num < 100) {
|
|
90
|
+
findings.push({
|
|
91
|
+
file: filePath, line: lineNum,
|
|
92
|
+
category: 'stale-reference',
|
|
93
|
+
current: m[0], expected: `${agentCount} agents`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Written-out agent counts (e.g., "four agents")
|
|
99
|
+
wordAgentRe.lastIndex = 0;
|
|
100
|
+
while ((m = wordAgentRe.exec(line)) !== null) {
|
|
101
|
+
const num = WORD_TO_NUM[m[1].toLowerCase()];
|
|
102
|
+
if (num !== undefined && num !== agentCount) {
|
|
103
|
+
findings.push({
|
|
104
|
+
file: filePath, line: lineNum,
|
|
105
|
+
category: 'stale-reference',
|
|
106
|
+
current: m[0], expected: `${agentCount} agents`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Digit workflow counts (e.g., "13 workflows")
|
|
112
|
+
digitWorkflowRe.lastIndex = 0;
|
|
113
|
+
while ((m = digitWorkflowRe.exec(line)) !== null) {
|
|
114
|
+
const num = parseInt(m[1], 10);
|
|
115
|
+
if (num !== workflowCount && num > 0 && num < 100) {
|
|
116
|
+
findings.push({
|
|
117
|
+
file: filePath, line: lineNum,
|
|
118
|
+
category: 'stale-reference',
|
|
119
|
+
current: m[0], expected: `${workflowCount} workflows`,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Written-out workflow counts (e.g., "thirteen workflows")
|
|
125
|
+
wordWorkflowRe.lastIndex = 0;
|
|
126
|
+
while ((m = wordWorkflowRe.exec(line)) !== null) {
|
|
127
|
+
const num = WORD_TO_NUM[m[1].toLowerCase()];
|
|
128
|
+
if (num !== undefined && num !== workflowCount) {
|
|
129
|
+
findings.push({
|
|
130
|
+
file: filePath, line: lineNum,
|
|
131
|
+
category: 'stale-reference',
|
|
132
|
+
current: m[0], expected: `${workflowCount} workflows`,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Contradictory terminology
|
|
138
|
+
for (const pattern of contradictoryPatterns) {
|
|
139
|
+
pattern.re.lastIndex = 0;
|
|
140
|
+
while ((m = pattern.re.exec(line)) !== null) {
|
|
141
|
+
findings.push({
|
|
142
|
+
file: filePath, line: lineNum,
|
|
143
|
+
category: 'stale-reference',
|
|
144
|
+
current: m[0], expected: pattern.expected,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return findings;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Check for broken internal markdown links [text](target).
|
|
155
|
+
* Excludes external URLs, anchor-only links, and mailto links.
|
|
156
|
+
*
|
|
157
|
+
* @param {string} content - File content
|
|
158
|
+
* @param {string} filePath - Relative file path (for reporting)
|
|
159
|
+
* @param {string} projectRoot - Absolute project root path
|
|
160
|
+
* @returns {Array<object>} findings
|
|
161
|
+
*/
|
|
162
|
+
function checkBrokenLinks(content, filePath, projectRoot) {
|
|
163
|
+
const findings = [];
|
|
164
|
+
const lines = content.split('\n');
|
|
165
|
+
const fileDir = path.dirname(path.resolve(projectRoot, filePath));
|
|
166
|
+
const linkRe = /\[([^\]]*)\]\(([^)]+)\)/g;
|
|
167
|
+
|
|
168
|
+
for (let i = 0; i < lines.length; i++) {
|
|
169
|
+
const line = lines[i];
|
|
170
|
+
const lineNum = i + 1;
|
|
171
|
+
|
|
172
|
+
linkRe.lastIndex = 0;
|
|
173
|
+
let m;
|
|
174
|
+
while ((m = linkRe.exec(line)) !== null) {
|
|
175
|
+
const target = m[2].trim();
|
|
176
|
+
|
|
177
|
+
// Skip external, anchor-only, mailto
|
|
178
|
+
if (/^https?:\/\//.test(target)) continue;
|
|
179
|
+
if (target.startsWith('#')) continue;
|
|
180
|
+
if (target.startsWith('mailto:')) continue;
|
|
181
|
+
|
|
182
|
+
// Strip anchor for file existence check
|
|
183
|
+
const targetPath = target.split('#')[0];
|
|
184
|
+
if (!targetPath) continue;
|
|
185
|
+
|
|
186
|
+
const resolved = path.resolve(fileDir, targetPath);
|
|
187
|
+
|
|
188
|
+
if (!fs.existsSync(resolved)) {
|
|
189
|
+
findings.push({
|
|
190
|
+
file: filePath, line: lineNum,
|
|
191
|
+
category: 'broken-link',
|
|
192
|
+
current: target, expected: 'target file should exist',
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return findings;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Check for stale path references in backtick-wrapped paths.
|
|
203
|
+
* Catches paths like `scripts/something.js` or `_bmad/path/file.md`
|
|
204
|
+
* that reference non-existent files.
|
|
205
|
+
*
|
|
206
|
+
* @param {string} content - File content
|
|
207
|
+
* @param {string} filePath - Relative file path (for reporting)
|
|
208
|
+
* @param {string} projectRoot - Absolute project root path
|
|
209
|
+
* @returns {Array<object>} findings
|
|
210
|
+
*/
|
|
211
|
+
function checkBrokenPaths(content, filePath, projectRoot) {
|
|
212
|
+
const findings = [];
|
|
213
|
+
const lines = content.split('\n');
|
|
214
|
+
|
|
215
|
+
// Match backtick-wrapped paths that start with known project directories
|
|
216
|
+
// and end with a file extension
|
|
217
|
+
const backtickPathRe = /`((?:scripts|docs|tests|\.github|_bmad)\/[^`\s*{}<>]+\.\w+)`/g;
|
|
218
|
+
|
|
219
|
+
for (let i = 0; i < lines.length; i++) {
|
|
220
|
+
const line = lines[i];
|
|
221
|
+
const lineNum = i + 1;
|
|
222
|
+
|
|
223
|
+
backtickPathRe.lastIndex = 0;
|
|
224
|
+
let m;
|
|
225
|
+
while ((m = backtickPathRe.exec(line)) !== null) {
|
|
226
|
+
const refPath = m[1];
|
|
227
|
+
|
|
228
|
+
// Skip patterns with wildcards or template variables
|
|
229
|
+
if (refPath.includes('*') || refPath.includes('{')) continue;
|
|
230
|
+
|
|
231
|
+
// Skip if this path is also in a markdown link on the same line (avoid duplicate)
|
|
232
|
+
if (line.includes(`](${refPath})`)) continue;
|
|
233
|
+
|
|
234
|
+
const resolved = path.resolve(projectRoot, refPath);
|
|
235
|
+
if (!fs.existsSync(resolved)) {
|
|
236
|
+
findings.push({
|
|
237
|
+
file: filePath, line: lineNum,
|
|
238
|
+
category: 'broken-path',
|
|
239
|
+
current: refPath, expected: 'referenced file should exist',
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return findings;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Check that every agent and workflow in the registry has at least
|
|
250
|
+
* one reference in the user-facing docs.
|
|
251
|
+
*
|
|
252
|
+
* @param {string[]} allDocsContent - Array of doc file contents
|
|
253
|
+
* @returns {Array<object>} findings
|
|
254
|
+
*/
|
|
255
|
+
function checkDocsCoverage(allDocsContent) {
|
|
256
|
+
const findings = [];
|
|
257
|
+
const combined = allDocsContent.join('\n').toLowerCase();
|
|
258
|
+
|
|
259
|
+
// Check each agent has at least one mention by name (word boundary match
|
|
260
|
+
// to avoid false negatives — e.g., "maximize" should not satisfy "Max")
|
|
261
|
+
for (const agent of AGENTS) {
|
|
262
|
+
const nameRe = new RegExp('\\b' + agent.name.toLowerCase() + '\\b');
|
|
263
|
+
if (!nameRe.test(combined)) {
|
|
264
|
+
findings.push({
|
|
265
|
+
file: 'docs/*', line: 0,
|
|
266
|
+
category: 'missing-coverage',
|
|
267
|
+
current: `agent "${agent.name}" (${agent.id}): no references found`,
|
|
268
|
+
expected: 'at least one documentation reference',
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Check each workflow has at least one mention by name
|
|
274
|
+
for (const name of WORKFLOW_NAMES) {
|
|
275
|
+
if (!combined.includes(name)) {
|
|
276
|
+
findings.push({
|
|
277
|
+
file: 'docs/*', line: 0,
|
|
278
|
+
category: 'missing-coverage',
|
|
279
|
+
current: `workflow "${name}": no references found`,
|
|
280
|
+
expected: 'at least one documentation reference',
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return findings;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Check for incomplete agent lists in markdown tables.
|
|
290
|
+
* If a table mentions 3+ agents but is missing some, flag it.
|
|
291
|
+
*
|
|
292
|
+
* @param {string} content - File content
|
|
293
|
+
* @param {string} filePath - Relative file path (for reporting)
|
|
294
|
+
* @returns {Array<object>} findings
|
|
295
|
+
*/
|
|
296
|
+
function checkIncompleteAgentTables(content, filePath) {
|
|
297
|
+
const findings = [];
|
|
298
|
+
const lines = content.split('\n');
|
|
299
|
+
const agentNames = AGENTS.map(a => a.name.toLowerCase());
|
|
300
|
+
|
|
301
|
+
// Only flag tables that appear to be agent-listing tables (one agent
|
|
302
|
+
// per row) but are missing some agents. Skip relationship tables where
|
|
303
|
+
// multiple agents appear per row (contract-flow, comparison tables).
|
|
304
|
+
const minForFlag = agentNames.length - 2; // e.g., 5 out of 7
|
|
305
|
+
|
|
306
|
+
// Find contiguous blocks of table rows (lines starting with |)
|
|
307
|
+
let tableStart = -1;
|
|
308
|
+
for (let i = 0; i <= lines.length; i++) {
|
|
309
|
+
const isTableRow = i < lines.length && /^\s*\|/.test(lines[i]);
|
|
310
|
+
|
|
311
|
+
if (isTableRow && tableStart === -1) {
|
|
312
|
+
tableStart = i;
|
|
313
|
+
} else if (!isTableRow && tableStart !== -1) {
|
|
314
|
+
const tableRows = lines.slice(tableStart, i);
|
|
315
|
+
const tableText = tableRows.join('\n').toLowerCase();
|
|
316
|
+
const found = agentNames.filter(name => {
|
|
317
|
+
const re = new RegExp('\\b' + name + '\\b');
|
|
318
|
+
return re.test(tableText);
|
|
319
|
+
});
|
|
320
|
+
const missing = agentNames.filter(name => {
|
|
321
|
+
const re = new RegExp('\\b' + name + '\\b');
|
|
322
|
+
return !re.test(tableText);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
if (found.length >= minForFlag && missing.length > 0) {
|
|
326
|
+
// Skip relationship tables: if most data rows contain 2+ agent
|
|
327
|
+
// names, this is a flow/contract table, not an agent listing.
|
|
328
|
+
// Exclude separator rows (|---|) and the header row (first non-separator).
|
|
329
|
+
const nonSeparator = tableRows.filter(r => !/^[\s|:-]+$/.test(r));
|
|
330
|
+
const dataRows = nonSeparator.slice(1); // skip header row
|
|
331
|
+
let multiAgentRows = 0;
|
|
332
|
+
for (const row of dataRows) {
|
|
333
|
+
const rowLower = row.toLowerCase();
|
|
334
|
+
const agentsInRow = agentNames.filter(name => {
|
|
335
|
+
const re = new RegExp('\\b' + name + '\\b');
|
|
336
|
+
return re.test(rowLower);
|
|
337
|
+
});
|
|
338
|
+
if (agentsInRow.length >= 2) multiAgentRows++;
|
|
339
|
+
}
|
|
340
|
+
if (multiAgentRows > dataRows.length / 2) {
|
|
341
|
+
tableStart = -1;
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const missingNames = missing.map(n => n.charAt(0).toUpperCase() + n.slice(1));
|
|
346
|
+
findings.push({
|
|
347
|
+
file: filePath,
|
|
348
|
+
line: tableStart + 1,
|
|
349
|
+
category: 'incomplete-agent-table',
|
|
350
|
+
current: `table lists ${found.length}/${agentNames.length} agents`,
|
|
351
|
+
expected: `missing: ${missingNames.join(', ')}`,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
tableStart = -1;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return findings;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Check for internal naming conventions leaking into user-facing prose.
|
|
363
|
+
* Detects `_vortex` outside backtick-wrapped text and code blocks.
|
|
364
|
+
*
|
|
365
|
+
* Scope note: Only `_vortex` is checked. `bme` almost exclusively appears
|
|
366
|
+
* inside backtick-wrapped paths and would produce false positives. `HC\d`
|
|
367
|
+
* (HC1-HC10) are intentional user-facing contract names used throughout
|
|
368
|
+
* docs/agents.md and the user guides — not internal leaks.
|
|
369
|
+
*
|
|
370
|
+
* @param {string} content - File content
|
|
371
|
+
* @param {string} filePath - Relative file path (for reporting)
|
|
372
|
+
* @returns {Array<object>} findings
|
|
373
|
+
*/
|
|
374
|
+
function checkInternalNamingLeaks(content, filePath) {
|
|
375
|
+
const findings = [];
|
|
376
|
+
const lines = content.split('\n');
|
|
377
|
+
let inCodeBlock = false;
|
|
378
|
+
|
|
379
|
+
for (let i = 0; i < lines.length; i++) {
|
|
380
|
+
const line = lines[i];
|
|
381
|
+
const lineNum = i + 1;
|
|
382
|
+
|
|
383
|
+
if (/^```/.test(line.trim())) {
|
|
384
|
+
inCodeBlock = !inCodeBlock;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (inCodeBlock) continue;
|
|
388
|
+
|
|
389
|
+
// Strip inline backtick-wrapped text and markdown link targets before checking
|
|
390
|
+
const prose = line.replace(/`[^`]+`/g, '').replace(/\[[^\]]*\]\([^)]+\)/g, '');
|
|
391
|
+
|
|
392
|
+
if (/\b_vortex\b/.test(prose)) {
|
|
393
|
+
findings.push({
|
|
394
|
+
file: filePath, line: lineNum,
|
|
395
|
+
category: 'internal-naming-leak',
|
|
396
|
+
current: '_vortex in prose',
|
|
397
|
+
expected: 'use "Vortex" or wrap in backticks as a path',
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return findings;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Check for stale product brand references (bmad-enhanced / BMAD-Enhanced).
|
|
407
|
+
* These should have been replaced with "convoke-agents" / "Convoke" during the rename.
|
|
408
|
+
*
|
|
409
|
+
* @param {string} content - File content
|
|
410
|
+
* @param {string} filePath - Relative file path (for reporting)
|
|
411
|
+
* @returns {Array<object>} findings
|
|
412
|
+
*/
|
|
413
|
+
function checkStaleBrandReferences(content, filePath) {
|
|
414
|
+
const findings = [];
|
|
415
|
+
const lines = content.split('\n');
|
|
416
|
+
const staleRe = /bmad-enhanced|BMAD-Enhanced|BMAD Enhanced/g;
|
|
417
|
+
|
|
418
|
+
for (let i = 0; i < lines.length; i++) {
|
|
419
|
+
const line = lines[i];
|
|
420
|
+
const lineNum = i + 1;
|
|
421
|
+
|
|
422
|
+
staleRe.lastIndex = 0;
|
|
423
|
+
let m;
|
|
424
|
+
while ((m = staleRe.exec(line)) !== null) {
|
|
425
|
+
findings.push({
|
|
426
|
+
file: filePath, line: lineNum,
|
|
427
|
+
category: 'stale-brand-reference',
|
|
428
|
+
current: m[0], expected: 'Convoke (product renamed)',
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return findings;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// --- Report Functions (Task 6) ---
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Format findings as a human-readable chalk-colored report.
|
|
440
|
+
* @param {Array<object>} findings
|
|
441
|
+
* @returns {string}
|
|
442
|
+
*/
|
|
443
|
+
function formatReport(findings) {
|
|
444
|
+
if (findings.length === 0) {
|
|
445
|
+
return [
|
|
446
|
+
'',
|
|
447
|
+
chalk.green.bold('Convoke Docs Audit'),
|
|
448
|
+
chalk.gray(`Registry: ${AGENTS.length} agents, ${WORKFLOWS.length} workflows`),
|
|
449
|
+
'',
|
|
450
|
+
chalk.green.bold(`\u2713 Docs audit passed \u2014 zero findings.`),
|
|
451
|
+
'',
|
|
452
|
+
].join('\n');
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Group by file
|
|
456
|
+
const byFile = {};
|
|
457
|
+
for (const f of findings) {
|
|
458
|
+
if (!byFile[f.file]) byFile[f.file] = [];
|
|
459
|
+
byFile[f.file].push(f);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Category counts
|
|
463
|
+
const categories = {};
|
|
464
|
+
for (const f of findings) {
|
|
465
|
+
categories[f.category] = (categories[f.category] || 0) + 1;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const lines = [
|
|
469
|
+
'',
|
|
470
|
+
chalk.cyan.bold('Convoke Docs Audit Report'),
|
|
471
|
+
chalk.gray(`Registry: ${AGENTS.length} agents, ${WORKFLOWS.length} workflows`),
|
|
472
|
+
'',
|
|
473
|
+
];
|
|
474
|
+
|
|
475
|
+
for (const [file, fileFindings] of Object.entries(byFile)) {
|
|
476
|
+
lines.push(chalk.yellow.bold(` ${file}`));
|
|
477
|
+
for (const f of fileFindings) {
|
|
478
|
+
const lineRef = f.line > 0 ? `L${f.line}` : '---';
|
|
479
|
+
lines.push(chalk.red(` ${lineRef} [${f.category}]`));
|
|
480
|
+
lines.push(chalk.gray(` Current: ${f.current}`));
|
|
481
|
+
lines.push(chalk.gray(` Expected: ${f.expected}`));
|
|
482
|
+
}
|
|
483
|
+
lines.push('');
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const catSummary = Object.entries(categories)
|
|
487
|
+
.map(([k, v]) => `${v} ${k}`)
|
|
488
|
+
.join(', ');
|
|
489
|
+
const fileCount = Object.keys(byFile).length;
|
|
490
|
+
|
|
491
|
+
lines.push(chalk.red.bold(
|
|
492
|
+
`Found ${findings.length} findings across ${fileCount} files (${catSummary})`
|
|
493
|
+
));
|
|
494
|
+
lines.push('');
|
|
495
|
+
|
|
496
|
+
return lines.join('\n');
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// --- Main Entry Point (Task 1.3, 1.4) ---
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Run the docs audit.
|
|
503
|
+
* @param {object} [opts] - Options
|
|
504
|
+
* @param {string} [opts.projectRoot] - Override project root (for testing)
|
|
505
|
+
* @param {boolean} [opts.json] - JSON output mode
|
|
506
|
+
* @returns {Promise<Array<object>>} findings
|
|
507
|
+
*/
|
|
508
|
+
async function runAudit(opts = {}) {
|
|
509
|
+
const projectRoot = opts.projectRoot || findProjectRoot();
|
|
510
|
+
|
|
511
|
+
if (!projectRoot) {
|
|
512
|
+
throw new Error('Could not find Convoke project root (_bmad/ directory)');
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const allFindings = [];
|
|
516
|
+
const allDocsContent = [];
|
|
517
|
+
|
|
518
|
+
for (const relPath of USER_FACING_DOCS) {
|
|
519
|
+
const absPath = path.join(projectRoot, relPath);
|
|
520
|
+
if (!fs.existsSync(absPath)) continue;
|
|
521
|
+
|
|
522
|
+
const content = fs.readFileSync(absPath, 'utf8');
|
|
523
|
+
allDocsContent.push(content);
|
|
524
|
+
|
|
525
|
+
// Skip stale-reference checks for CHANGELOG — historical entries
|
|
526
|
+
// (e.g., "Added 4 agents" in v1.0) are accurate for their time period
|
|
527
|
+
if (relPath !== 'CHANGELOG.md') {
|
|
528
|
+
allFindings.push(...checkStaleReferences(content, relPath));
|
|
529
|
+
}
|
|
530
|
+
allFindings.push(...checkBrokenLinks(content, relPath, projectRoot));
|
|
531
|
+
allFindings.push(...checkBrokenPaths(content, relPath, projectRoot));
|
|
532
|
+
allFindings.push(...checkIncompleteAgentTables(content, relPath));
|
|
533
|
+
allFindings.push(...checkInternalNamingLeaks(content, relPath));
|
|
534
|
+
allFindings.push(...checkStaleBrandReferences(content, relPath));
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Coverage check across all docs combined
|
|
538
|
+
allFindings.push(...checkDocsCoverage(allDocsContent));
|
|
539
|
+
|
|
540
|
+
return allFindings;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
async function main() {
|
|
544
|
+
const jsonMode = process.argv.includes('--json');
|
|
545
|
+
|
|
546
|
+
try {
|
|
547
|
+
const findings = await runAudit();
|
|
548
|
+
|
|
549
|
+
if (jsonMode) {
|
|
550
|
+
console.log(JSON.stringify(findings, null, 2));
|
|
551
|
+
} else {
|
|
552
|
+
console.log(formatReport(findings));
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
process.exit(findings.length > 0 ? 1 : 0);
|
|
556
|
+
} catch (err) {
|
|
557
|
+
if (jsonMode) {
|
|
558
|
+
console.log(JSON.stringify({ error: err.message }));
|
|
559
|
+
} else {
|
|
560
|
+
console.error(chalk.red(`Docs audit failed: ${err.message}`));
|
|
561
|
+
}
|
|
562
|
+
process.exit(1);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// --- Exports (for testing) ---
|
|
567
|
+
|
|
568
|
+
module.exports = {
|
|
569
|
+
USER_FACING_DOCS,
|
|
570
|
+
WORD_TO_NUM,
|
|
571
|
+
checkStaleReferences,
|
|
572
|
+
checkBrokenLinks,
|
|
573
|
+
checkBrokenPaths,
|
|
574
|
+
checkDocsCoverage,
|
|
575
|
+
checkIncompleteAgentTables,
|
|
576
|
+
checkInternalNamingLeaks,
|
|
577
|
+
checkStaleBrandReferences,
|
|
578
|
+
formatReport,
|
|
579
|
+
runAudit,
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
if (require.main === module) {
|
|
583
|
+
main();
|
|
584
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* convoke-install — Umbrella installer (delegates to Vortex installer).
|
|
5
|
+
*
|
|
6
|
+
* Future: When additional frameworks are added, this script will install
|
|
7
|
+
* all frameworks. For now it delegates to convoke-install-vortex.
|
|
8
|
+
*/
|
|
9
|
+
require('./install-vortex-agents.js');
|