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,367 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const yaml = require('js-yaml');
|
|
7
|
+
const { findProjectRoot, getPackageVersion } = require('./utils');
|
|
8
|
+
const backupManager = require('./backup-manager');
|
|
9
|
+
const configMerger = require('./config-merger');
|
|
10
|
+
const validator = require('./validator');
|
|
11
|
+
const { refreshInstallation } = require('./refresh-installation');
|
|
12
|
+
const registry = require('../migrations/registry');
|
|
13
|
+
const { WORKFLOW_NAMES } = require('./agent-registry');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Migration Runner for Convoke
|
|
17
|
+
* Core orchestration: executes migration deltas, refreshes installation, handles backups and rollback.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Run migrations from current version to the current package version.
|
|
22
|
+
* @param {string} fromVersion - Current installed version
|
|
23
|
+
* @param {object} options - Options { dryRun, verbose }
|
|
24
|
+
* @returns {Promise<object>} Migration result
|
|
25
|
+
*/
|
|
26
|
+
async function runMigrations(fromVersion, options = {}) {
|
|
27
|
+
const { dryRun = false, verbose = false } = options;
|
|
28
|
+
const toVersion = getPackageVersion();
|
|
29
|
+
|
|
30
|
+
// Resolve project root
|
|
31
|
+
const projectRoot = findProjectRoot();
|
|
32
|
+
if (!projectRoot) {
|
|
33
|
+
throw new Error('Not in a Convoke project. Could not find _bmad/ directory.');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log('');
|
|
37
|
+
if (dryRun) {
|
|
38
|
+
console.log(chalk.yellow.bold('═══ DRY RUN MODE ═══'));
|
|
39
|
+
console.log(chalk.yellow('No changes will be made to your installation'));
|
|
40
|
+
console.log('');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 1. Get applicable migration deltas
|
|
44
|
+
const migrations = registry.getMigrationsFor(fromVersion);
|
|
45
|
+
|
|
46
|
+
if (migrations.length === 0) {
|
|
47
|
+
console.log(chalk.yellow('No migrations needed'));
|
|
48
|
+
return { success: true, migrations: [], skipped: true };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log(chalk.cyan(`Found ${migrations.length} migration(s) to apply:`));
|
|
52
|
+
migrations.forEach((m, i) => {
|
|
53
|
+
const icon = m.breaking ? chalk.red('⚠') : chalk.green('✓');
|
|
54
|
+
console.log(` ${i + 1}. ${icon} ${m.name} - ${m.description}`);
|
|
55
|
+
});
|
|
56
|
+
console.log('');
|
|
57
|
+
|
|
58
|
+
// If dry run, just preview
|
|
59
|
+
if (dryRun) {
|
|
60
|
+
return await previewMigrations(migrations);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 2. Acquire migration lock
|
|
64
|
+
await acquireMigrationLock(projectRoot);
|
|
65
|
+
|
|
66
|
+
let backupMetadata = null;
|
|
67
|
+
const results = [];
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
// 3. Create backup
|
|
71
|
+
console.log(chalk.cyan('[1/5] Creating backup...'));
|
|
72
|
+
backupMetadata = await backupManager.createBackup(fromVersion, projectRoot);
|
|
73
|
+
console.log(chalk.green(`✓ Backup created: ${path.basename(backupMetadata.backup_dir)}`));
|
|
74
|
+
console.log('');
|
|
75
|
+
|
|
76
|
+
// 4. Execute migration deltas sequentially
|
|
77
|
+
console.log(chalk.cyan('[2/5] Running migration deltas...'));
|
|
78
|
+
for (let i = 0; i < migrations.length; i++) {
|
|
79
|
+
const migration = migrations[i];
|
|
80
|
+
console.log(chalk.cyan(`\nMigration ${i + 1}/${migrations.length}: ${migration.name}`));
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const changes = await executeMigration(migration, projectRoot, { verbose });
|
|
84
|
+
results.push({
|
|
85
|
+
name: migration.name,
|
|
86
|
+
success: true,
|
|
87
|
+
changes
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
console.log(chalk.green(`✓ ${migration.name} completed`));
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error(chalk.red(`✗ ${migration.name} failed: ${error.message}`));
|
|
93
|
+
throw new MigrationError(migration.name, error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
console.log('');
|
|
97
|
+
console.log(chalk.green('✓ All migration deltas completed'));
|
|
98
|
+
console.log('');
|
|
99
|
+
|
|
100
|
+
// 5. Refresh installation (copy latest files from package)
|
|
101
|
+
console.log(chalk.cyan('[3/5] Refreshing installation files...'));
|
|
102
|
+
const refreshChanges = await refreshInstallation(projectRoot);
|
|
103
|
+
results.push({
|
|
104
|
+
name: 'refresh-installation',
|
|
105
|
+
success: true,
|
|
106
|
+
changes: refreshChanges
|
|
107
|
+
});
|
|
108
|
+
console.log(chalk.green('✓ Installation refreshed'));
|
|
109
|
+
console.log('');
|
|
110
|
+
|
|
111
|
+
// 6. Update migration history in config.yaml
|
|
112
|
+
console.log(chalk.cyan('[4/5] Updating configuration...'));
|
|
113
|
+
await updateMigrationHistory(projectRoot, fromVersion, toVersion, results);
|
|
114
|
+
console.log(chalk.green('✓ Migration history updated'));
|
|
115
|
+
console.log('');
|
|
116
|
+
|
|
117
|
+
// 7. Validate installation
|
|
118
|
+
console.log(chalk.cyan('[5/5] Validating installation...'));
|
|
119
|
+
const validationResult = await validator.validateInstallation(backupMetadata, projectRoot);
|
|
120
|
+
|
|
121
|
+
validationResult.checks.forEach(check => {
|
|
122
|
+
if (check.passed) {
|
|
123
|
+
console.log(chalk.green(` ✓ ${check.name}`));
|
|
124
|
+
if (check.info || check.warning) {
|
|
125
|
+
console.log(chalk.gray(` ${check.info || check.warning}`));
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
console.log(chalk.red(` ✗ ${check.name}`));
|
|
129
|
+
if (check.error) {
|
|
130
|
+
console.log(chalk.red(` Error: ${check.error}`));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
console.log('');
|
|
135
|
+
|
|
136
|
+
if (!validationResult.valid) {
|
|
137
|
+
throw new Error('Installation validation failed');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.log(chalk.green('✓ Installation validated'));
|
|
141
|
+
console.log('');
|
|
142
|
+
|
|
143
|
+
// 8. Cleanup old backups
|
|
144
|
+
const deletedCount = await backupManager.cleanupOldBackups(5, projectRoot);
|
|
145
|
+
if (deletedCount > 0) {
|
|
146
|
+
console.log(chalk.green(`✓ Cleaned up ${deletedCount} old backup(s)`));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Release lock
|
|
150
|
+
await releaseMigrationLock(projectRoot);
|
|
151
|
+
|
|
152
|
+
// Create migration log
|
|
153
|
+
await createMigrationLog(projectRoot, fromVersion, toVersion, results, backupMetadata);
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
success: true,
|
|
157
|
+
fromVersion,
|
|
158
|
+
toVersion,
|
|
159
|
+
results,
|
|
160
|
+
backupMetadata
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.error('');
|
|
165
|
+
console.error(chalk.red.bold('✗ Migration failed!'));
|
|
166
|
+
console.error('');
|
|
167
|
+
console.error(chalk.red(error.message));
|
|
168
|
+
console.error('');
|
|
169
|
+
|
|
170
|
+
// Rollback if we have a backup
|
|
171
|
+
if (backupMetadata) {
|
|
172
|
+
console.log(chalk.yellow('Restoring from backup...'));
|
|
173
|
+
try {
|
|
174
|
+
await backupManager.restoreBackup(backupMetadata, projectRoot);
|
|
175
|
+
console.log(chalk.green('✓ Installation restored from backup'));
|
|
176
|
+
console.log('');
|
|
177
|
+
} catch (restoreError) {
|
|
178
|
+
console.error(chalk.red('✗ Restore failed!'));
|
|
179
|
+
console.error(chalk.red(restoreError.message));
|
|
180
|
+
console.error('');
|
|
181
|
+
console.error(chalk.yellow(`Manual restore may be needed from: ${backupMetadata.backup_dir}`));
|
|
182
|
+
console.error('');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Release lock
|
|
187
|
+
await releaseMigrationLock(projectRoot);
|
|
188
|
+
|
|
189
|
+
// Create error log
|
|
190
|
+
await createErrorLog(projectRoot, fromVersion, toVersion, error, backupMetadata);
|
|
191
|
+
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Preview migrations without applying
|
|
198
|
+
*/
|
|
199
|
+
async function previewMigrations(migrations) {
|
|
200
|
+
const previews = [];
|
|
201
|
+
|
|
202
|
+
for (const migration of migrations) {
|
|
203
|
+
console.log(chalk.cyan(`\n${migration.name}:`));
|
|
204
|
+
console.log(chalk.gray(migration.description));
|
|
205
|
+
|
|
206
|
+
if (migration.module && migration.module.preview) {
|
|
207
|
+
const preview = await migration.module.preview();
|
|
208
|
+
console.log('');
|
|
209
|
+
console.log(chalk.white('Actions:'));
|
|
210
|
+
preview.actions.forEach(action => {
|
|
211
|
+
console.log(chalk.gray(` - ${action}`));
|
|
212
|
+
});
|
|
213
|
+
previews.push({ name: migration.name, preview });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
console.log('');
|
|
218
|
+
console.log(chalk.white('After deltas, installation will be refreshed:'));
|
|
219
|
+
console.log(chalk.gray(' - Refresh agent files'));
|
|
220
|
+
console.log(chalk.gray(` - Refresh ${WORKFLOW_NAMES.length} workflow directories`));
|
|
221
|
+
console.log(chalk.gray(' - Update config.yaml (preserving user preferences)'));
|
|
222
|
+
console.log(chalk.gray(' - Update user guides (with .bak backup)'));
|
|
223
|
+
console.log('');
|
|
224
|
+
console.log(chalk.green('To apply these changes, run:'));
|
|
225
|
+
console.log(chalk.cyan(' npx convoke-update'));
|
|
226
|
+
console.log('');
|
|
227
|
+
|
|
228
|
+
return { success: true, dryRun: true, previews };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Execute a single migration delta
|
|
233
|
+
*/
|
|
234
|
+
async function executeMigration(migration, projectRoot, options = {}) {
|
|
235
|
+
const { verbose = false } = options;
|
|
236
|
+
|
|
237
|
+
if (!migration.module || !migration.module.apply) {
|
|
238
|
+
throw new Error(`Migration ${migration.name} has no apply function`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const changes = await migration.module.apply(projectRoot);
|
|
242
|
+
|
|
243
|
+
if (verbose) {
|
|
244
|
+
changes.forEach(change => {
|
|
245
|
+
console.log(chalk.gray(` - ${change}`));
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return changes;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Update migration history in config.yaml
|
|
254
|
+
*/
|
|
255
|
+
async function updateMigrationHistory(projectRoot, fromVersion, toVersion, results) {
|
|
256
|
+
const configPath = path.join(projectRoot, '_bmad/bme/_vortex/config.yaml');
|
|
257
|
+
|
|
258
|
+
if (!fs.existsSync(configPath)) {
|
|
259
|
+
throw new Error('config.yaml not found after refresh');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
263
|
+
const config = yaml.load(configContent);
|
|
264
|
+
|
|
265
|
+
const migrationsApplied = results
|
|
266
|
+
.filter(r => r.name !== 'refresh-installation')
|
|
267
|
+
.map(r => r.name);
|
|
268
|
+
|
|
269
|
+
const updatedConfig = configMerger.addMigrationHistory(
|
|
270
|
+
config, fromVersion, toVersion, migrationsApplied
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
await configMerger.writeConfig(configPath, updatedConfig);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async function acquireMigrationLock(projectRoot) {
|
|
277
|
+
const lockFile = path.join(projectRoot, '_bmad-output/.migration-lock');
|
|
278
|
+
|
|
279
|
+
if (fs.existsSync(lockFile)) {
|
|
280
|
+
const lock = await fs.readJson(lockFile);
|
|
281
|
+
const age = Date.now() - lock.timestamp;
|
|
282
|
+
|
|
283
|
+
if (age > 5 * 60 * 1000) {
|
|
284
|
+
console.log(chalk.yellow('Removing stale migration lock'));
|
|
285
|
+
await fs.remove(lockFile);
|
|
286
|
+
} else {
|
|
287
|
+
throw new Error('Migration already in progress. Please wait and try again.');
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
await fs.ensureDir(path.join(projectRoot, '_bmad-output'));
|
|
292
|
+
await fs.writeJson(lockFile, { timestamp: Date.now(), pid: process.pid });
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async function releaseMigrationLock(projectRoot) {
|
|
296
|
+
const lockFile = path.join(projectRoot, '_bmad-output/.migration-lock');
|
|
297
|
+
if (fs.existsSync(lockFile)) {
|
|
298
|
+
await fs.remove(lockFile);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async function createMigrationLog(projectRoot, fromVersion, toVersion, results, backupMetadata) {
|
|
303
|
+
const logsDir = path.join(projectRoot, '_bmad-output/.logs');
|
|
304
|
+
await fs.ensureDir(logsDir);
|
|
305
|
+
|
|
306
|
+
const logFile = path.join(logsDir, `migration-${Date.now()}.log`);
|
|
307
|
+
const logContent = [
|
|
308
|
+
`Convoke Migration Log`,
|
|
309
|
+
`Date: ${new Date().toISOString()}`,
|
|
310
|
+
`From Version: ${fromVersion}`,
|
|
311
|
+
`To Version: ${toVersion}`,
|
|
312
|
+
'',
|
|
313
|
+
'Migrations Applied:',
|
|
314
|
+
...results.map(r => ` - ${r.name}`),
|
|
315
|
+
'',
|
|
316
|
+
'Changes:',
|
|
317
|
+
...results.flatMap(r => r.changes.map(c => ` - ${c}`)),
|
|
318
|
+
'',
|
|
319
|
+
`Backup: ${backupMetadata.backup_dir}`,
|
|
320
|
+
'',
|
|
321
|
+
'Status: SUCCESS'
|
|
322
|
+
].join('\n');
|
|
323
|
+
|
|
324
|
+
await fs.writeFile(logFile, logContent, 'utf8');
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
async function createErrorLog(projectRoot, fromVersion, toVersion, error, backupMetadata) {
|
|
328
|
+
const logsDir = path.join(projectRoot, '_bmad-output/.logs');
|
|
329
|
+
await fs.ensureDir(logsDir);
|
|
330
|
+
|
|
331
|
+
const logFile = path.join(logsDir, `migration-error-${Date.now()}.log`);
|
|
332
|
+
const logContent = [
|
|
333
|
+
`Convoke Migration Error Log`,
|
|
334
|
+
`Date: ${new Date().toISOString()}`,
|
|
335
|
+
`From Version: ${fromVersion}`,
|
|
336
|
+
`To Version: ${toVersion}`,
|
|
337
|
+
'',
|
|
338
|
+
`Error: ${error.message}`,
|
|
339
|
+
'',
|
|
340
|
+
'Stack Trace:',
|
|
341
|
+
error.stack,
|
|
342
|
+
'',
|
|
343
|
+
backupMetadata ? `Backup: ${backupMetadata.backup_dir}` : 'No backup created',
|
|
344
|
+
backupMetadata ? 'Status: ROLLED BACK' : 'Status: FAILED (no backup)',
|
|
345
|
+
'',
|
|
346
|
+
'Please report this issue at: https://github.com/amalik/convoke-agents/issues'
|
|
347
|
+
].join('\n');
|
|
348
|
+
|
|
349
|
+
await fs.writeFile(logFile, logContent, 'utf8');
|
|
350
|
+
console.log(chalk.gray(`Migration log: ${logFile}`));
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
class MigrationError extends Error {
|
|
354
|
+
constructor(migrationName, originalError) {
|
|
355
|
+
super(`Migration ${migrationName} failed: ${originalError.message}`);
|
|
356
|
+
this.name = 'MigrationError';
|
|
357
|
+
this.migrationName = migrationName;
|
|
358
|
+
this.originalError = originalError;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
module.exports = {
|
|
363
|
+
runMigrations,
|
|
364
|
+
previewMigrations,
|
|
365
|
+
executeMigration,
|
|
366
|
+
MigrationError
|
|
367
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { getPackageVersion } = require('./utils');
|
|
6
|
+
const configMerger = require('./config-merger');
|
|
7
|
+
const { AGENTS, AGENT_FILES, AGENT_IDS, WORKFLOW_NAMES, USER_GUIDES } = require('./agent-registry');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Refresh Installation for Convoke
|
|
11
|
+
*
|
|
12
|
+
* Copies latest agent files, workflows, config, and user guides from the
|
|
13
|
+
* package to the project. Called ONCE after all migration deltas have run,
|
|
14
|
+
* or directly by the install script.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Refresh all installation files from the package to the project.
|
|
19
|
+
*
|
|
20
|
+
* @param {string} projectRoot - Absolute path to project root
|
|
21
|
+
* @param {object} options
|
|
22
|
+
* @param {boolean} options.backupGuides - Create .bak of user guides before overwriting (default: true)
|
|
23
|
+
* @param {boolean} options.verbose - Log each action (default: true)
|
|
24
|
+
* @returns {Promise<Array<string>>} List of changes made
|
|
25
|
+
*/
|
|
26
|
+
async function refreshInstallation(projectRoot, options = {}) {
|
|
27
|
+
const { backupGuides = true, verbose = true } = options;
|
|
28
|
+
const changes = [];
|
|
29
|
+
const packageRoot = path.join(__dirname, '..', '..', '..');
|
|
30
|
+
const packageVortex = path.join(packageRoot, '_bmad', 'bme', '_vortex');
|
|
31
|
+
const targetVortex = path.join(projectRoot, '_bmad', 'bme', '_vortex');
|
|
32
|
+
const version = getPackageVersion();
|
|
33
|
+
|
|
34
|
+
// When running from the package's own directory (dev environment),
|
|
35
|
+
// source and destination are identical — skip file copies.
|
|
36
|
+
const isSameRoot = path.resolve(packageRoot) === path.resolve(projectRoot);
|
|
37
|
+
|
|
38
|
+
// 1. Copy agent files
|
|
39
|
+
const agentsSource = path.join(packageVortex, 'agents');
|
|
40
|
+
const agentsTarget = path.join(targetVortex, 'agents');
|
|
41
|
+
await fs.ensureDir(agentsTarget);
|
|
42
|
+
|
|
43
|
+
if (!isSameRoot) {
|
|
44
|
+
for (const file of AGENT_FILES) {
|
|
45
|
+
const src = path.join(agentsSource, file);
|
|
46
|
+
if (fs.existsSync(src)) {
|
|
47
|
+
await fs.copy(src, path.join(agentsTarget, file), { overwrite: true });
|
|
48
|
+
changes.push(`Refreshed agent: ${file}`);
|
|
49
|
+
if (verbose) console.log(` Refreshed agent: ${file}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
changes.push('Skipped agent copy (dev environment — files already in place)');
|
|
54
|
+
if (verbose) console.log(' Skipped agent copy (dev environment)');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Remove deprecated agent files if still present
|
|
58
|
+
const deprecatedAgents = ['empathy-mapper.md', 'wireframe-designer.md'];
|
|
59
|
+
for (const file of deprecatedAgents) {
|
|
60
|
+
const agentPath = path.join(agentsTarget, file);
|
|
61
|
+
if (fs.existsSync(agentPath)) {
|
|
62
|
+
await fs.remove(agentPath);
|
|
63
|
+
changes.push(`Removed deprecated agent: ${file}`);
|
|
64
|
+
if (verbose) console.log(` Removed deprecated agent: ${file}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 2. Copy workflow directories
|
|
69
|
+
const workflowsSource = path.join(packageVortex, 'workflows');
|
|
70
|
+
const workflowsTarget = path.join(targetVortex, 'workflows');
|
|
71
|
+
await fs.ensureDir(workflowsTarget);
|
|
72
|
+
|
|
73
|
+
if (!isSameRoot) {
|
|
74
|
+
for (const wf of WORKFLOW_NAMES) {
|
|
75
|
+
const src = path.join(workflowsSource, wf);
|
|
76
|
+
if (fs.existsSync(src)) {
|
|
77
|
+
await fs.copy(src, path.join(workflowsTarget, wf), { overwrite: true });
|
|
78
|
+
changes.push(`Refreshed workflow: ${wf}`);
|
|
79
|
+
if (verbose) console.log(` Refreshed workflow: ${wf}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
changes.push('Skipped workflow copy (dev environment — files already in place)');
|
|
84
|
+
if (verbose) console.log(' Skipped workflow copy (dev environment)');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 3. Update config.yaml (merge, preserving user prefs)
|
|
88
|
+
const configPath = path.join(targetVortex, 'config.yaml');
|
|
89
|
+
await fs.ensureDir(path.dirname(configPath));
|
|
90
|
+
|
|
91
|
+
const updates = {
|
|
92
|
+
agents: AGENT_IDS,
|
|
93
|
+
workflows: WORKFLOW_NAMES
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const merged = await configMerger.mergeConfig(configPath, version, updates);
|
|
97
|
+
await configMerger.writeConfig(configPath, merged);
|
|
98
|
+
changes.push(`Updated config.yaml to v${version}`);
|
|
99
|
+
if (verbose) console.log(` Updated config.yaml to v${version}`);
|
|
100
|
+
|
|
101
|
+
// 4. Regenerate agent manifest — replace only bme rows, preserve other modules
|
|
102
|
+
const manifestPath = path.join(projectRoot, '_bmad', '_config', 'agent-manifest.csv');
|
|
103
|
+
await fs.ensureDir(path.dirname(manifestPath));
|
|
104
|
+
|
|
105
|
+
function csvEscape(value) {
|
|
106
|
+
return `"${String(value).replace(/"/g, '""')}"`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const header = '"agent_id","name","title","icon","role","identity","communication_style","expertise","submodule","path"';
|
|
110
|
+
|
|
111
|
+
// Read existing non-bme rows to preserve them
|
|
112
|
+
let preservedRows = [];
|
|
113
|
+
if (fs.existsSync(manifestPath)) {
|
|
114
|
+
const existing = (await fs.readFile(manifestPath, 'utf8')).trim().split('\n');
|
|
115
|
+
// Skip header, keep rows where submodule is NOT bme
|
|
116
|
+
preservedRows = existing.slice(1).filter(row => {
|
|
117
|
+
// submodule is the 9th field (index 8) in the CSV
|
|
118
|
+
const fields = row.match(/"([^"]*(?:""[^"]*)*)"/g);
|
|
119
|
+
if (!fields || fields.length < 9) return true; // keep unrecognised rows
|
|
120
|
+
const submodule = fields[8].replace(/^"|"$/g, '');
|
|
121
|
+
return submodule !== 'bme';
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Build fresh bme rows from registry
|
|
126
|
+
const bmeRows = AGENTS.map(a => {
|
|
127
|
+
const p = a.persona;
|
|
128
|
+
return [
|
|
129
|
+
a.id, a.name, a.title, a.icon,
|
|
130
|
+
p.role, p.identity, p.communication_style, p.expertise,
|
|
131
|
+
'bme', `_bmad/bme/_vortex/agents/${a.id}.md`,
|
|
132
|
+
].map(csvEscape).join(',');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const allRows = [...preservedRows, ...bmeRows].join('\n') + '\n';
|
|
136
|
+
await fs.writeFile(manifestPath, header + '\n' + allRows, 'utf8');
|
|
137
|
+
changes.push('Regenerated agent-manifest.csv (bme rows updated, other modules preserved)');
|
|
138
|
+
if (verbose) console.log(' Regenerated agent-manifest.csv (bme rows updated, other modules preserved)');
|
|
139
|
+
|
|
140
|
+
// 5. Copy user guides (with optional backup)
|
|
141
|
+
const guidesSource = path.join(packageRoot, '_bmad', 'bme', '_vortex', 'guides');
|
|
142
|
+
const guidesTarget = path.join(projectRoot, '_bmad', 'bme', '_vortex', 'guides');
|
|
143
|
+
await fs.ensureDir(guidesTarget);
|
|
144
|
+
|
|
145
|
+
if (!isSameRoot) {
|
|
146
|
+
for (const guide of USER_GUIDES) {
|
|
147
|
+
const src = path.join(guidesSource, guide);
|
|
148
|
+
const dest = path.join(guidesTarget, guide);
|
|
149
|
+
|
|
150
|
+
if (fs.existsSync(src)) {
|
|
151
|
+
// Backup existing guide before overwriting
|
|
152
|
+
if (backupGuides && fs.existsSync(dest)) {
|
|
153
|
+
await fs.copy(dest, dest + '.bak', { overwrite: true });
|
|
154
|
+
changes.push(`Backed up ${guide} → ${guide}.bak`);
|
|
155
|
+
if (verbose) console.log(` Backed up ${guide} → ${guide}.bak`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
await fs.copy(src, dest, { overwrite: true });
|
|
159
|
+
changes.push(`Refreshed guide: ${guide}`);
|
|
160
|
+
if (verbose) console.log(` Refreshed guide: ${guide}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
changes.push('Skipped guide copy (dev environment — files already in place)');
|
|
165
|
+
if (verbose) console.log(' Skipped guide copy (dev environment)');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return changes;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
module.exports = { refreshInstallation };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Shared utilities for the Convoke update system.
|
|
8
|
+
* Single source of truth for version, comparison, project detection.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get the package version at runtime from package.json.
|
|
13
|
+
* This is the SINGLE SOURCE OF TRUTH for version - never hardcode versions elsewhere.
|
|
14
|
+
* @returns {string} e.g. "1.3.8"
|
|
15
|
+
*/
|
|
16
|
+
function getPackageVersion() {
|
|
17
|
+
const pkg = require('../../../package.json');
|
|
18
|
+
return pkg.version;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Compare two semantic version strings.
|
|
23
|
+
* @param {string} v1
|
|
24
|
+
* @param {string} v2
|
|
25
|
+
* @returns {number} -1 if v1 < v2, 0 if equal, 1 if v1 > v2
|
|
26
|
+
*/
|
|
27
|
+
function compareVersions(v1, v2) {
|
|
28
|
+
const parts1 = v1.split('.').map(Number);
|
|
29
|
+
const parts2 = v2.split('.').map(Number);
|
|
30
|
+
|
|
31
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
32
|
+
const p1 = parts1[i] || 0;
|
|
33
|
+
const p2 = parts2[i] || 0;
|
|
34
|
+
if (p1 < p2) return -1;
|
|
35
|
+
if (p1 > p2) return 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Count user data files in _bmad-output/ (excluding .backups, .logs).
|
|
43
|
+
* @param {string} projectRoot - Absolute path to project root
|
|
44
|
+
* @returns {Promise<number>}
|
|
45
|
+
*/
|
|
46
|
+
async function countUserDataFiles(projectRoot) {
|
|
47
|
+
const outputDir = path.join(projectRoot, '_bmad-output');
|
|
48
|
+
|
|
49
|
+
if (!fs.existsSync(outputDir)) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let count = 0;
|
|
54
|
+
|
|
55
|
+
async function walk(dir) {
|
|
56
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
if (entry.name === '.backups' || entry.name === '.logs') continue;
|
|
59
|
+
const full = path.join(dir, entry.name);
|
|
60
|
+
if (entry.isDirectory()) {
|
|
61
|
+
await walk(full);
|
|
62
|
+
} else if (entry.isFile()) {
|
|
63
|
+
count++;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await walk(outputDir);
|
|
69
|
+
return count;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Find the project root by walking up from cwd looking for _bmad/ directory.
|
|
74
|
+
* @returns {string|null} Absolute path to project root, or null if not found
|
|
75
|
+
*/
|
|
76
|
+
function findProjectRoot() {
|
|
77
|
+
let dir = process.cwd();
|
|
78
|
+
const root = path.parse(dir).root;
|
|
79
|
+
|
|
80
|
+
while (true) {
|
|
81
|
+
if (fs.existsSync(path.join(dir, '_bmad'))) {
|
|
82
|
+
return dir;
|
|
83
|
+
}
|
|
84
|
+
if (dir === root) break;
|
|
85
|
+
dir = path.dirname(dir);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
getPackageVersion,
|
|
93
|
+
compareVersions,
|
|
94
|
+
countUserDataFiles,
|
|
95
|
+
findProjectRoot
|
|
96
|
+
};
|