-
-
Notifications
You must be signed in to change notification settings - Fork 34
BMAD Module Issues.md
Problem: BMAD module fails to initialize with the framework
Symptoms:
Error: BMAD module not found
Module 'bmad' is not registered
BMAD initialization failedSolutions:
Check module registration
// framework.config.js - Ensure BMAD is enabled
module.exports = {
modules: {
bmad: {
enabled: true,
config: {
database_prefix: 'bmad_',
canvas_autosave: true,
analytics_enabled: true
}
}
}
};Verify BMAD installation
# Check if BMAD module is installed
npm list @cursoriper/bmad
ls -la node_modules/@cursoriper/bmad/
# Reinstall BMAD module if missing
npm install @cursoriper/bmad@latest
# Verify module structure
cat node_modules/@cursoriper/bmad/package.jsonManual module registration
// src/app.js - Manual BMAD registration
const { Framework } = require('@cursoriper/core');
const BMADModule = require('@cursoriper/bmad');
const framework = new Framework();
// Register BMAD module manually
framework.registerModule('bmad', BMADModule, {
database_prefix: 'bmad_',
canvas_autosave: true
});
framework.start();Problem: BMAD database tables not created or corrupted
Symptoms:
Table 'bmad_business_models' doesn't exist
Column 'canvas_data' not found
Foreign key constraint failsSolutions:
Force schema recreation
# Run BMAD database migration
npm run bmad:migrate
# Or use framework CLI
npx @cursoriper/cli bmad:db:resetManual schema creation
-- Create BMAD tables manually
CREATE TABLE IF NOT EXISTS bmad_business_models (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
canvas_data JSON,
status VARCHAR(50) DEFAULT 'draft',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
created_by VARCHAR(36),
organization_id VARCHAR(36)
);
CREATE TABLE IF NOT EXISTS bmad_stakeholders (
id VARCHAR(36) PRIMARY KEY,
business_model_id VARCHAR(36),
name VARCHAR(255) NOT NULL,
type VARCHAR(100),
influence_level INT DEFAULT 1,
engagement_level INT DEFAULT 1,
contact_info JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (business_model_id) REFERENCES bmad_business_models(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS bmad_canvases (
id VARCHAR(36) PRIMARY KEY,
business_model_id VARCHAR(36),
canvas_type VARCHAR(50) DEFAULT 'standard',
sections JSON,
version VARCHAR(20) DEFAULT '1.0.0',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (business_model_id) REFERENCES bmad_business_models(id) ON DELETE CASCADE
);Check database permissions
// Test BMAD database access
const { Framework } = require('@cursoriper/core');
async function testBMADDatabase() {
const framework = new Framework();
await framework.initialize();
const bmadService = framework.getService('bmad');
try {
// Test database connection
const models = await bmadService.getBusinessModels();
console.log('β BMAD database accessible');
console.log(`Found ${models.length} business models`);
} catch (error) {
console.error('β BMAD database error:', error.message);
// Check specific table access
const db = framework.getDatabase();
try {
await db.query('SELECT 1 FROM bmad_business_models LIMIT 1');
console.log('β bmad_business_models table accessible');
} catch (tableError) {
console.error('β bmad_business_models table error:', tableError.message);
}
}
}
testBMADDatabase();Problem: Business model canvas data becomes corrupted or invalid
Symptoms:
Error parsing canvas JSON data
Invalid canvas structure
Canvas sections missing
Null reference exception in canvasSolutions:
Validate canvas data structure
// Canvas validation utility
class CanvasValidator {
static validateCanvas(canvasData) {
const requiredSections = [
'value_propositions',
'customer_segments',
'channels',
'customer_relationships',
'revenue_streams',
'key_resources',
'key_activities',
'key_partnerships',
'cost_structure'
];
const errors = [];
// Check if canvas data exists
if (!canvasData || typeof canvasData !== 'object') {
errors.push('Canvas data is missing or invalid');
return { valid: false, errors };
}
// Check required sections
requiredSections.forEach(section => {
if (!canvasData[section]) {
errors.push(`Missing required section: ${section}`);
} else if (!Array.isArray(canvasData[section])) {
errors.push(`Section ${section} must be an array`);
}
});
// Validate section content
Object.entries(canvasData).forEach(([section, items]) => {
if (Array.isArray(items)) {
items.forEach((item, index) => {
if (!item.id || !item.text) {
errors.push(`Invalid item at ${section}[${index}]: missing id or text`);
}
});
}
});
return {
valid: errors.length === 0,
errors
};
}
static sanitizeCanvas(canvasData) {
const requiredSections = [
'value_propositions',
'customer_segments',
'channels',
'customer_relationships',
'revenue_streams',
'key_resources',
'key_activities',
'key_partnerships',
'cost_structure'
];
const sanitized = {};
requiredSections.forEach(section => {
sanitized[section] = [];
if (canvasData[section] && Array.isArray(canvasData[section])) {
sanitized[section] = canvasData[section]
.filter(item => item && typeof item === 'object')
.map(item => ({
id: item.id || this.generateId(),
text: String(item.text || ''),
description: String(item.description || ''),
validated: Boolean(item.validated),
created_at: item.created_at || new Date().toISOString()
}));
}
});
return sanitized;
}
static generateId() {
return 'item_' + Math.random().toString(36).substr(2, 9);
}
}
// Usage
const bmadService = framework.getService('bmad');
async function repairCanvasData(businessModelId) {
try {
const model = await bmadService.getBusinessModel(businessModelId);
// Validate current canvas
const validation = CanvasValidator.validateCanvas(model.canvas_data);
if (!validation.valid) {
console.log('Canvas validation errors:', validation.errors);
// Sanitize and repair
const sanitized = CanvasValidator.sanitizeCanvas(model.canvas_data || {});
// Update model with sanitized data
await bmadService.updateBusinessModel(businessModelId, {
canvas_data: sanitized
});
console.log('Canvas data repaired successfully');
}
} catch (error) {
console.error('Canvas repair failed:', error);
}
}Problem: Canvas changes not being saved automatically
Symptoms:
Canvas changes lost after refresh
Auto-save indicator stuck
"Save failed" errorsSolutions:
Check auto-save configuration
// framework.config.js
module.exports = {
modules: {
bmad: {
enabled: true,
config: {
canvas_autosave: true,
autosave_interval: 5000, // 5 seconds
max_retries: 3,
retry_delay: 1000
}
}
}
};Implement robust auto-save
// Enhanced auto-save with error handling
class CanvasAutoSave {
constructor(bmadService, options = {}) {
this.bmadService = bmadService;
this.options = {
interval: options.interval || 5000,
maxRetries: options.maxRetries || 3,
retryDelay: options.retryDelay || 1000,
...options
};
this.pendingChanges = new Map();
this.saveTimers = new Map();
}
scheduleAutoSave(modelId, canvasData) {
// Store pending changes
this.pendingChanges.set(modelId, canvasData);
// Clear existing timer
if (this.saveTimers.has(modelId)) {
clearTimeout(this.saveTimers.get(modelId));
}
// Schedule new save
const timer = setTimeout(() => {
this.performAutoSave(modelId);
}, this.options.interval);
this.saveTimers.set(modelId, timer);
}
async performAutoSave(modelId, retryCount = 0) {
try {
const canvasData = this.pendingChanges.get(modelId);
if (!canvasData) return;
// Validate before saving
const validation = CanvasValidator.validateCanvas(canvasData);
if (!validation.valid) {
console.warn('Skipping auto-save due to validation errors:', validation.errors);
return;
}
// Perform save
await this.bmadService.updateBusinessModel(modelId, {
canvas_data: canvasData,
updated_at: new Date()
});
// Clear pending changes
this.pendingChanges.delete(modelId);
this.saveTimers.delete(modelId);
console.log(`Auto-save successful for model ${modelId}`);
} catch (error) {
console.error(`Auto-save failed for model ${modelId}:`, error);
// Retry if attempts remaining
if (retryCount < this.options.maxRetries) {
setTimeout(() => {
this.performAutoSave(modelId, retryCount + 1);
}, this.options.retryDelay * (retryCount + 1));
} else {
console.error(`Auto-save failed permanently for model ${modelId}`);
// Notify user of save failure
this.notifyUser(modelId, 'Auto-save failed. Please save manually.');
}
}
}
notifyUser(modelId, message) {
// Emit event for UI to handle
const framework = require('@cursoriper/core').getInstance();
framework.events.emit('bmad.autosave.failed', {
modelId,
message,
timestamp: new Date()
});
}
}Problem: Stakeholder information not syncing properly
Symptoms:
Stakeholder roles inconsistent
Duplicate stakeholder entries
Orphaned stakeholder recordsSolutions:
Stakeholder data cleanup
async function cleanupStakeholderData() {
const bmadService = framework.getService('bmad');
const db = framework.getDatabase();
try {
// Find orphaned stakeholders
const orphanedStakeholders = await db.query(`
SELECT s.id, s.name, s.business_model_id
FROM bmad_stakeholders s
LEFT JOIN bmad_business_models bm ON s.business_model_id = bm.id
WHERE bm.id IS NULL
`);
console.log(`Found ${orphanedStakeholders.length} orphaned stakeholders`);
// Remove orphaned records
for (const stakeholder of orphanedStakeholders) {
await db.query('DELETE FROM bmad_stakeholders WHERE id = ?', [stakeholder.id]);
console.log(`Removed orphaned stakeholder: ${stakeholder.name}`);
}
// Find duplicate stakeholders
const duplicates = await db.query(`
SELECT business_model_id, name, COUNT(*) as count
FROM bmad_stakeholders
GROUP BY business_model_id, name
HAVING COUNT(*) > 1
`);
console.log(`Found ${duplicates.length} duplicate stakeholder groups`);
// Merge duplicates
for (const duplicate of duplicates) {
await mergeStakeholderDuplicates(duplicate.business_model_id, duplicate.name);
}
console.log('Stakeholder cleanup completed');
} catch (error) {
console.error('Stakeholder cleanup failed:', error);
}
}
async function mergeStakeholderDuplicates(businessModelId, stakeholderName) {
const db = framework.getDatabase();
// Get all duplicates
const duplicates = await db.query(`
SELECT * FROM bmad_stakeholders
WHERE business_model_id = ? AND name = ?
ORDER BY created_at ASC
`, [businessModelId, stakeholderName]);
if (duplicates.length <= 1) return;
// Keep the first one, merge data from others
const primary = duplicates[0];
const toMerge = duplicates.slice(1);
// Merge contact info and other data
const mergedContactInfo = {};
const mergedData = {
type: primary.type,
influence_level: primary.influence_level,
engagement_level: primary.engagement_level
};
toMerge.forEach(stakeholder => {
// Merge contact info
if (stakeholder.contact_info) {
Object.assign(mergedContactInfo, JSON.parse(stakeholder.contact_info));
}
// Take highest influence/engagement levels
mergedData.influence_level = Math.max(mergedData.influence_level, stakeholder.influence_level);
mergedData.engagement_level = Math.max(mergedData.engagement_level, stakeholder.engagement_level);
});
// Update primary record
await db.query(`
UPDATE bmad_stakeholders
SET contact_info = ?, influence_level = ?, engagement_level = ?, updated_at = NOW()
WHERE id = ?
`, [
JSON.stringify({ ...JSON.parse(primary.contact_info || '{}'), ...mergedContactInfo }),
mergedData.influence_level,
mergedData.engagement_level,
primary.id
]);
// Delete duplicate records
for (const duplicate of toMerge) {
await db.query('DELETE FROM bmad_stakeholders WHERE id = ?', [duplicate.id]);
}
console.log(`Merged ${toMerge.length} duplicate stakeholders for: ${stakeholderName}`);
}Problem: BMAD analytics reports are empty or not updating
Symptoms:
Analytics dashboard shows no data
Reports generation fails
"No data available" messagesSolutions:
Check analytics configuration
// framework.config.js
module.exports = {
modules: {
bmad: {
enabled: true,
config: {
analytics_enabled: true,
analytics_schedule: '0 2 * * *', // Daily at 2 AM
metrics_retention_days: 90,
real_time_analytics: true
}
}
}
};Force analytics regeneration
async function regenerateAnalytics() {
const bmadService = framework.getService('bmad');
try {
// Get all business models
const models = await bmadService.getBusinessModels();
for (const model of models) {
console.log(`Generating analytics for model: ${model.name}`);
// Generate model analytics
const analytics = await bmadService.generateModelAnalytics(model.id);
console.log(`Generated ${analytics.metrics.length} metrics`);
// Generate stakeholder analytics
const stakeholderAnalytics = await bmadService.generateStakeholderAnalytics(model.id);
console.log(`Generated stakeholder analytics with ${stakeholderAnalytics.engagement_scores.length} scores`);
}
// Generate portfolio analytics
const portfolioAnalytics = await bmadService.generatePortfolioAnalytics();
console.log('Portfolio analytics generated successfully');
} catch (error) {
console.error('Analytics regeneration failed:', error);
}
}Manual analytics calculation
class BMADAnalyticsCalculator {
constructor(bmadService) {
this.bmadService = bmadService;
}
async calculateModelCompleteness(modelId) {
const model = await this.bmadService.getBusinessModel(modelId);
const canvas = model.canvas_data || {};
const requiredSections = [
'value_propositions',
'customer_segments',
'channels',
'customer_relationships',
'revenue_streams',
'key_resources',
'key_activities',
'key_partnerships',
'cost_structure'
];
let completedSections = 0;
let totalItems = 0;
let completedItems = 0;
requiredSections.forEach(section => {
if (canvas[section] && Array.isArray(canvas[section]) && canvas[section].length > 0) {
completedSections++;
totalItems += canvas[section].length;
completedItems += canvas[section].filter(item => item.validated).length;
}
});
return {
section_completeness: completedSections / requiredSections.length,
item_completeness: totalItems > 0 ? completedItems / totalItems : 0,
total_sections: requiredSections.length,
completed_sections: completedSections,
total_items: totalItems,
completed_items: completedItems
};
}
async calculateStakeholderEngagement(modelId) {
const stakeholders = await this.bmadService.getStakeholders(modelId);
if (stakeholders.length === 0) {
return { average_engagement: 0, total_stakeholders: 0 };
}
const totalEngagement = stakeholders.reduce((sum, stakeholder) =>
sum + (stakeholder.engagement_level || 0), 0);
const averageEngagement = totalEngagement / stakeholders.length;
const engagementDistribution = {
low: stakeholders.filter(s => (s.engagement_level || 0) <= 2).length,
medium: stakeholders.filter(s => (s.engagement_level || 0) > 2 && (s.engagement_level || 0) <= 4).length,
high: stakeholders.filter(s => (s.engagement_level || 0) > 4).length
};
return {
average_engagement: averageEngagement,
total_stakeholders: stakeholders.length,
engagement_distribution: engagementDistribution
};
}
}Problem: BMAD operations are slow or timing out
Symptoms:
Business model loading takes too long
Canvas save operations timeout
Stakeholder queries are slowSolutions:
Add database indexes
-- Optimize BMAD queries with indexes
CREATE INDEX idx_bmad_models_status ON bmad_business_models(status);
CREATE INDEX idx_bmad_models_created_by ON bmad_business_models(created_by);
CREATE INDEX idx_bmad_models_organization ON bmad_business_models(organization_id);
CREATE INDEX idx_bmad_models_updated ON bmad_business_models(updated_at);
CREATE INDEX idx_bmad_stakeholders_model ON bmad_stakeholders(business_model_id);
CREATE INDEX idx_bmad_stakeholders_type ON bmad_stakeholders(type);
CREATE INDEX idx_bmad_stakeholders_influence ON bmad_stakeholders(influence_level);
CREATE INDEX idx_bmad_canvases_model ON bmad_canvases(business_model_id);
CREATE INDEX idx_bmad_canvases_type ON bmad_canvases(canvas_type);
CREATE INDEX idx_bmad_canvases_updated ON bmad_canvases(updated_at);Implement query optimization
class OptimizedBMADService {
constructor(framework) {
this.db = framework.getDatabase();
this.cache = framework.getCache();
}
async getBusinessModel(modelId) {
// Check cache first
const cacheKey = `bmad:model:${modelId}`;
let model = await this.cache.get(cacheKey);
if (!model) {
// Fetch from database
model = await this.db.query(`
SELECT bm.*,
COUNT(s.id) as stakeholder_count,
MAX(s.updated_at) as last_stakeholder_update
FROM bmad_business_models bm
LEFT JOIN bmad_stakeholders s ON bm.id = s.business_model_id
WHERE bm.id = ?
GROUP BY bm.id
`, [modelId]);
if (model.length > 0) {
model = model[0];
// Cache for 5 minutes
await this.cache.set(cacheKey, model, 300);
}
}
return model;
}
async getBusinessModels(filters = {}) {
// Build optimized query
let query = `
SELECT bm.id, bm.name, bm.description, bm.status, bm.created_at, bm.updated_at,
COUNT(s.id) as stakeholder_count,
CASE
WHEN bm.canvas_data IS NOT NULL AND JSON_LENGTH(bm.canvas_data) > 0
THEN 'complete'
ELSE 'incomplete'
END as canvas_status
FROM bmad_business_models bm
LEFT JOIN bmad_stakeholders s ON bm.id = s.business_model_id
`;
const conditions = [];
const params = [];
if (filters.status) {
conditions.push('bm.status = ?');
params.push(filters.status);
}
if (filters.organization_id) {
conditions.push('bm.organization_id = ?');
params.push(filters.organization_id);
}
if (filters.created_after) {
conditions.push('bm.created_at > ?');
params.push(filters.created_after);
}
if (conditions.length > 0) {
query += ' WHERE ' + conditions.join(' AND ');
}
query += ' GROUP BY bm.id ORDER BY bm.updated_at DESC';
if (filters.limit) {
query += ` LIMIT ${parseInt(filters.limit)}`;
}
return await this.db.query(query, params);
}
async invalidateCache(modelId) {
// Invalidate related cache entries
const keys = [
`bmad:model:${modelId}`,
`bmad:stakeholders:${modelId}`,
`bmad:canvas:${modelId}`,
`bmad:analytics:${modelId}`
];
await Promise.all(keys.map(key => this.cache.delete(key)));
}
}Last Updated: June 28, 2025
Framework Version: CursorRIPER.sigma v1.0+
BMAD Module Version: 2.1.0
- ποΈ Framework Overview
- π RIPER Modes
- πΎ Memory System
- π£ Symbolic Notation
- π Phase Management
- π‘οΈ Code Protection
- π Context References
- π Permission System
- π Cross-References
- πΎ Backup System
- π Mode Transitions
- πΎ Memory Management
- π‘οΈ Protection Workflow
- π Context Management
- π₯ Team Collaboration
- π£ Symbol Reference
- β¨οΈ Command Reference
- π Mode Reference
- π Permission Matrix
- π API Reference
- π Overview
- π GitHub Integration
- π Web Search
- π Browser Automation
- π³ Docker Integration
-
Installation Issues
- Node.js Version Compatibility
- Package Installation Failures
- Framework Dependencies Missing
- Database Connection Issues
- Port Conflicts
- Environment Setup Issues
- Build and Development Issues
- Framework CLI Issues
-
Configuration & Runtime Issues
- Framework Configuration Problems
- Runtime Performance Issues
- Module Loading and Plugin Issues
- Database and Storage Issues
- Memory Leaks and High Memory Usage
- High CPU Usage
-
BMAD Module Issues
- BMAD Module Initialization Problems
- Business Model Canvas Issues
- Stakeholder Management Issues
- Analytics and Reporting Issues
- Performance Optimization
-
Database & API Issues
- Database Connection Problems
- Database Migration Issues
- API Performance and Reliability Issues
- Data Consistency Issues
- Transaction Problems
-
Performance & Memory Issues
- Memory Management
- CPU Optimization
- Database Query Performance
- Caching Issues
- Resource Monitoring
-
Security & Authentication Issues
- Authentication Failures
- Authorization Problems
- JWT Token Issues
- Session Management
- CORS and Security Headers
- SSL/TLS Configuration
-
Deployment & Production Issues
- Production Deployment Failures
- Environment Configuration
- Load Balancing Issues
- Monitoring and Logging
- Backup and Recovery
When reporting issues, please include:
- Framework version (
npm list @cursoriper/core) - Node.js version (
node --version) - Operating system and version
- Error messages and stack traces
- Steps to reproduce the issue
- Configuration files (sanitized)
- Recent changes or deployments
- Technical Support: support@cursoriper.com
- Documentation: https://docs.cursoriper.com
- Community Forum: https://community.cursoriper.com