UNPKG

adpa-enterprise-framework-automation

Version:

Modular, standards-compliant Node.js/TypeScript automation framework for enterprise requirements, project, and data management. Provides CLI and API for BABOK v3, PMBOK 7th Edition, and DMBOK 2.0 (in progress). Production-ready Express.js API with TypeSpe

499 lines 22.6 kB
/** * Adaptive Scope Control Service * Implements intelligent scope monitoring and control mechanisms following PMBOK standards * * @class AdaptiveScopeControlService * @description Provides adaptive scope control with real-time monitoring, scope creep detection, * and automated control mechanisms aligned with PMBOK 7th Edition standards * * @version 1.0.0 * @since 3.2.0 */ import { EventEmitter } from 'events'; import { PMBOKValidator } from '../modules/pmbokValidation/PMBOKValidator.js'; import { logger } from '../utils/logger.js'; export class AdaptiveScopeControlService extends EventEmitter { pmbokValidator; monitoringIntervals = new Map(); scopeChanges = new Map(); projectSettings = new Map(); constructor() { super(); this.pmbokValidator = new PMBOKValidator(); this.initializeDefaultSettings(); } /** * Initialize monitoring for a project */ async initializeProjectMonitoring(project, settings) { try { const projectId = project._id; const controlSettings = this.mergeSettings(settings); this.projectSettings.set(projectId, controlSettings); this.scopeChanges.set(projectId, []); // Start real-time monitoring if (controlSettings.monitoringFrequency > 0) { this.startMonitoring(projectId, controlSettings.monitoringFrequency); } // Perform initial PMBOK compliance check if (controlSettings.pmbokValidationEnabled) { await this.performInitialComplianceCheck(project); } logger.info(`Adaptive scope control initialized for project: ${project.name}`); this.emit('monitoring_started', { projectId, settings: controlSettings }); } catch (error) { logger.error(`Failed to initialize scope control for project ${project._id}:`, error); throw new Error(`Scope control initialization failed: ${(error instanceof Error ? error.message : String(error))}`); } } /** * Submit a scope change request */ async submitScopeChange(change) { try { const scopeChange = { ...change, id: this.generateChangeId(), status: 'pending', riskLevel: await this.assessRiskLevel(change), pmbokCompliance: await this.validatePMBOKCompliance(change) }; // Add to project's scope changes const projectChanges = this.scopeChanges.get(change.projectId) || []; projectChanges.push(scopeChange); this.scopeChanges.set(change.projectId, projectChanges); // Analyze for scope creep const scopeCreepDetected = await this.detectScopeCreep(change.projectId, scopeChange); if (scopeCreepDetected) { await this.handleScopeCreepDetection(change.projectId, scopeChange); } // Check for auto-approval const settings = this.projectSettings.get(change.projectId); if (settings && await this.shouldAutoApprove(scopeChange, settings)) { await this.autoApproveChange(scopeChange); } logger.info(`Scope change submitted for project ${change.projectId}: ${scopeChange.id}`); this.emit('scope_change_submitted', scopeChange); return scopeChange; } catch (error) { logger.error(`Failed to submit scope change:`, error); throw new Error(`Scope change submission failed: ${(error instanceof Error ? error.message : String(error))}`); } } /** * Approve a scope change */ async approveScopeChange(changeId, approvedBy) { try { const change = await this.findScopeChange(changeId); if (!change) { throw new Error(`Scope change not found: ${changeId}`); } change.status = 'approved'; change.approvedBy = approvedBy; change.approvalDate = new Date(); // Update project compliance score await this.updateProjectComplianceScore(change.projectId); // Generate implementation plan const implementationPlan = await this.generateImplementationPlan(change); logger.info(`Scope change approved: ${changeId} by ${approvedBy}`); this.emit('scope_change_approved', { change, implementationPlan }); return change; } catch (error) { logger.error(`Failed to approve scope change ${changeId}:`, error); throw new Error(`Scope change approval failed: ${(error instanceof Error ? error.message : String(error))}`); } } /** * Detect scope creep using adaptive algorithms */ async detectScopeCreep(projectId, newChange) { try { const projectChanges = this.scopeChanges.get(projectId) || []; const settings = this.projectSettings.get(projectId); if (!settings) { return false; } // Calculate scope creep indicators const metrics = await this.calculateScopeMetrics(projectId); // Adaptive thresholds based on project characteristics const adaptiveThreshold = await this.calculateAdaptiveThreshold(projectId, metrics); // Multiple detection algorithms const creepIndicators = { changeVelocity: metrics.changeVelocity > adaptiveThreshold.velocityThreshold, impactAccumulation: metrics.impactScore > adaptiveThreshold.impactThreshold, complianceDecline: metrics.pmbokComplianceScore < adaptiveThreshold.complianceThreshold, patternAnalysis: await this.analyzeChangePatterns(projectChanges), riskEscalation: metrics.riskScore > adaptiveThreshold.riskThreshold }; const scopeCreepDetected = Object.values(creepIndicators).filter(Boolean).length >= 2; if (scopeCreepDetected) { logger.warn(`Scope creep detected for project ${projectId}:`, creepIndicators); } return scopeCreepDetected; } catch (error) { logger.error(`Failed to detect scope creep for project ${projectId}:`, error); return false; } } /** * Get comprehensive scope metrics for a project */ async getScopeMetrics(projectId) { return await this.calculateScopeMetrics(projectId); } /** * Get scope alerts for a project */ async getScopeAlerts(projectId) { try { const alerts = []; const metrics = await this.calculateScopeMetrics(projectId); const settings = this.projectSettings.get(projectId); if (!settings) { return alerts; } // Check for various alert conditions if (metrics.scopeCreepIndex > settings.scopeCreepThreshold) { alerts.push({ id: this.generateAlertId(), projectId, alertType: 'scope_creep', severity: 'critical', message: `Scope creep index (${metrics.scopeCreepIndex.toFixed(2)}) exceeds threshold (${settings.scopeCreepThreshold})`, timestamp: new Date(), actionRequired: true, recommendedActions: [ 'Review recent scope changes', 'Conduct stakeholder alignment meeting', 'Reassess project scope baseline', 'Implement stricter change control' ] }); } if (metrics.pmbokComplianceScore < 70) { alerts.push({ id: this.generateAlertId(), projectId, alertType: 'compliance_violation', severity: 'warning', message: `PMBOK compliance score (${metrics.pmbokComplianceScore}%) below acceptable threshold`, timestamp: new Date(), actionRequired: true, recommendedActions: [ 'Review PMBOK compliance requirements', 'Update scope documentation', 'Conduct compliance training', 'Implement compliance monitoring' ] }); } return alerts; } catch (error) { logger.error(`Failed to get scope alerts for project ${projectId}:`, error); return []; } } /** * Stop monitoring for a project */ stopProjectMonitoring(projectId) { const interval = this.monitoringIntervals.get(projectId); if (interval) { clearInterval(interval); this.monitoringIntervals.delete(projectId); } this.projectSettings.delete(projectId); logger.info(`Stopped scope control monitoring for project: ${projectId}`); this.emit('monitoring_stopped', { projectId }); } // Private helper methods initializeDefaultSettings() { // Default adaptive control settings } mergeSettings(settings) { const defaults = { autoApprovalThreshold: 0.2, escalationThreshold: 0.5, scopeCreepThreshold: 0.3, monitoringFrequency: 60, // 1 hour stakeholderNotificationEnabled: true, pmbokValidationEnabled: true, predictiveAnalyticsEnabled: true }; return { ...defaults, ...settings }; } startMonitoring(projectId, frequencyMinutes) { const interval = setInterval(async () => { try { await this.performPeriodicCheck(projectId); } catch (error) { logger.error(`Periodic scope check failed for project ${projectId}:`, error); } }, frequencyMinutes * 60 * 1000); this.monitoringIntervals.set(projectId, interval); } async performPeriodicCheck(projectId) { const scopeCreepDetected = await this.detectScopeCreep(projectId); if (scopeCreepDetected) { const alerts = await this.getScopeAlerts(projectId); this.emit('scope_alerts', { projectId, alerts }); } // Update metrics const metrics = await this.calculateScopeMetrics(projectId); this.emit('scope_metrics_updated', { projectId, metrics }); } async performInitialComplianceCheck(project) { try { const compliance = await this.pmbokValidator.validatePMBOKCompliance(); logger.info(`Initial PMBOK compliance check completed for project ${project.name}: ${compliance.compliance}`); } catch (error) { logger.error(`Initial compliance check failed for project ${project._id}:`, error); } } async assessRiskLevel(change) { // Risk assessment algorithm let riskScore = 0; // Schedule impact if (change.impact.scheduleImpact.percentage > 20) riskScore += 3; else if (change.impact.scheduleImpact.percentage > 10) riskScore += 2; else if (change.impact.scheduleImpact.percentage > 5) riskScore += 1; // Cost impact if (change.impact.costImpact.percentage > 15) riskScore += 3; else if (change.impact.costImpact.percentage > 10) riskScore += 2; else if (change.impact.costImpact.percentage > 5) riskScore += 1; // Critical path impact if (change.impact.scheduleImpact.criticalPath) riskScore += 2; // Quality impact if (change.impact.qualityImpact.riskToQuality) riskScore += 2; // Stakeholder impact if (change.impact.stakeholderImpact.affectedStakeholders.length > 5) riskScore += 2; else if (change.impact.stakeholderImpact.affectedStakeholders.length > 2) riskScore += 1; if (riskScore >= 8) return 'critical'; if (riskScore >= 6) return 'high'; if (riskScore >= 3) return 'medium'; return 'low'; } async validatePMBOKCompliance(change) { try { // Enhanced PMBOK compliance validation using existing validator const requiredFields = [ 'description', 'requestedBy', 'impact' ]; const hasRequiredFields = requiredFields.every(field => change[field] !== undefined && change[field] !== null); const hasImpactAnalysis = change.impact && change.impact.scheduleImpact && change.impact.costImpact && change.impact.resourceImpact; // PMBOK 7th Edition specific validations const pmbokValidations = { // 5.6.1 Control Scope - Inputs hasProjectManagementPlan: true, // Assumed from project context hasProjectDocuments: hasRequiredFields, hasWorkPerformanceData: hasImpactAnalysis, // 5.6.2 Control Scope - Tools & Techniques hasVarianceAnalysis: change.impact.scheduleImpact.percentage !== undefined, hasTrendAnalysis: true, // Will be performed by service // 5.6.3 Control Scope - Outputs hasWorkPerformanceInformation: hasImpactAnalysis, hasChangeRequests: change.changeType !== undefined, hasProjectManagementPlanUpdates: true, // Will be generated hasProjectDocumentUpdates: true // Will be generated }; // Additional PMBOK compliance checks const advancedValidations = { // Stakeholder engagement (Section 13) hasStakeholderIdentification: change.impact.stakeholderImpact.affectedStakeholders.length > 0, hasCommunicationPlan: change.impact.stakeholderImpact.communicationRequired !== undefined, // Risk management (Section 11) hasRiskAssessment: change.impact.qualityImpact.riskToQuality !== undefined, // Quality management (Section 8) hasQualityImpactAnalysis: change.impact.qualityImpact !== undefined, // Schedule management (Section 6) hasScheduleImpactAnalysis: change.impact.scheduleImpact !== undefined, // Cost management (Section 7) hasCostImpactAnalysis: change.impact.costImpact !== undefined, // Resource management (Section 9) hasResourceImpactAnalysis: change.impact.resourceImpact !== undefined }; // Calculate compliance score const basicCompliance = hasRequiredFields && hasImpactAnalysis; const pmbokScore = Object.values(pmbokValidations).filter(Boolean).length / Object.keys(pmbokValidations).length; const advancedScore = Object.values(advancedValidations).filter(Boolean).length / Object.keys(advancedValidations).length; const overallCompliance = basicCompliance && pmbokScore >= 0.8 && advancedScore >= 0.7; logger.info(`PMBOK compliance validation: Basic=${basicCompliance}, PMBOK=${pmbokScore.toFixed(2)}, Advanced=${advancedScore.toFixed(2)}, Overall=${overallCompliance}`); return overallCompliance; } catch (error) { logger.error('PMBOK compliance validation failed:', error); return false; } } async shouldAutoApprove(change, settings) { if (change.riskLevel === 'critical' || change.riskLevel === 'high') { return false; } const impactScore = this.calculateChangeImpactScore(change); return impactScore <= settings.autoApprovalThreshold && change.pmbokCompliance; } calculateChangeImpactScore(change) { const scheduleWeight = 0.3; const costWeight = 0.3; const qualityWeight = 0.2; const stakeholderWeight = 0.2; const scheduleScore = Math.min(change.impact.scheduleImpact.percentage / 100, 1); const costScore = Math.min(change.impact.costImpact.percentage / 100, 1); const qualityScore = change.impact.qualityImpact.riskToQuality ? 0.5 : 0; const stakeholderScore = Math.min(change.impact.stakeholderImpact.affectedStakeholders.length / 10, 1); return (scheduleScore * scheduleWeight) + (costScore * costWeight) + (qualityScore * qualityWeight) + (stakeholderScore * stakeholderWeight); } async autoApproveChange(change) { change.status = 'approved'; change.approvedBy = 'system_auto_approval'; change.approvalDate = new Date(); logger.info(`Scope change auto-approved: ${change.id}`); this.emit('scope_change_auto_approved', change); } async findScopeChange(changeId) { for (const [projectId, changes] of this.scopeChanges.entries()) { const change = changes.find(c => c.id === changeId); if (change) { return change; } } return null; } async updateProjectComplianceScore(projectId) { // Update project compliance score based on scope changes const metrics = await this.calculateScopeMetrics(projectId); // Implementation would update the project model } async generateImplementationPlan(change) { // Generate implementation plan for approved scope change return { changeId: change.id, implementationSteps: [ 'Update project documentation', 'Communicate changes to stakeholders', 'Update work breakdown structure', 'Adjust project schedule', 'Update resource allocation', 'Update risk register' ], estimatedDuration: change.impact.scheduleImpact.days, requiredApprovals: change.impact.stakeholderImpact.approvalRequired, riskMitigation: [] }; } async calculateScopeMetrics(projectId) { const projectChanges = this.scopeChanges.get(projectId) || []; const totalChanges = projectChanges.length; const approvedChanges = projectChanges.filter(c => c.status === 'approved').length; const rejectedChanges = projectChanges.filter(c => c.status === 'rejected').length; const pendingChanges = projectChanges.filter(c => c.status === 'pending').length; // Calculate scope creep index const recentChanges = projectChanges.filter(c => c.requestDate > new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // Last 30 days ); const scopeCreepIndex = recentChanges.length > 0 ? recentChanges.reduce((sum, c) => sum + this.calculateChangeImpactScore(c), 0) / recentChanges.length : 0; // Calculate change velocity (changes per week) const changeVelocity = totalChanges > 0 ? totalChanges / 4 : 0; // Assuming 4 weeks // Calculate average impact score const impactScore = totalChanges > 0 ? projectChanges.reduce((sum, c) => sum + this.calculateChangeImpactScore(c), 0) / totalChanges : 0; // Calculate PMBOK compliance score const compliantChanges = projectChanges.filter(c => c.pmbokCompliance).length; const pmbokComplianceScore = totalChanges > 0 ? (compliantChanges / totalChanges) * 100 : 100; // Calculate risk score const riskWeights = { low: 1, medium: 2, high: 3, critical: 4 }; const riskScore = totalChanges > 0 ? projectChanges.reduce((sum, c) => sum + riskWeights[c.riskLevel], 0) / totalChanges : 0; return { totalChanges, approvedChanges, rejectedChanges, pendingChanges, scopeCreepIndex, changeVelocity, impactScore, pmbokComplianceScore, riskScore }; } async calculateAdaptiveThreshold(projectId, metrics) { // Adaptive threshold calculation based on project characteristics return { velocityThreshold: 2.0, // changes per week impactThreshold: 0.3, // 30% impact threshold complianceThreshold: 80, // 80% compliance threshold riskThreshold: 2.5 // medium-high risk threshold }; } async analyzeChangePatterns(changes) { // Pattern analysis for scope creep detection if (changes.length < 3) return false; // Check for increasing impact trend const recentChanges = changes.slice(-5); // Last 5 changes const impactTrend = recentChanges.map(c => this.calculateChangeImpactScore(c)); // Simple trend analysis - check if impacts are generally increasing let increasingTrend = 0; for (let i = 1; i < impactTrend.length; i++) { if (impactTrend[i] > impactTrend[i - 1]) increasingTrend++; } return increasingTrend >= impactTrend.length * 0.6; // 60% of changes show increasing impact } async handleScopeCreepDetection(projectId, change) { const alert = { id: this.generateAlertId(), projectId, alertType: 'scope_creep', severity: 'warning', message: `Potential scope creep detected with change: ${change.description}`, timestamp: new Date(), actionRequired: true, recommendedActions: [ 'Review change request thoroughly', 'Assess cumulative impact of recent changes', 'Consider stakeholder realignment', 'Evaluate project scope baseline' ] }; logger.warn(`Scope creep detected for project ${projectId}:`, alert); this.emit('scope_creep_detected', { projectId, change, alert }); } generateChangeId() { return `SC-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } generateAlertId() { return `SA-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } } //# sourceMappingURL=AdaptiveScopeControlService.js.map