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

1,087 lines (1,048 loc) • 46.8 kB
// ...existing code... // ...existing code... /** * Document Generator Module for Requirements Gathering Agent * * Core document generation engine that creates comprehensive PMBOK-compliant * project documentation based on project context and AI analysis. * * @version 2.1.3 * @author Requirements Gathering Agent Team * @created 2024 * @updated June 2025 * * Key Features: * - Comprehensive PMBOK 7.0 compliant document generation * - AI-powered content creation and analysis * - Organized file structure and directory management * - Validation and quality assessment integration * - Batch processing and error handling * * @filepath c:\Users\menno\Source\Repos\requirements-gathering-agent\src\modules\documentGenerator\DocumentGenerator.ts */ import * as fs from 'fs/promises'; import * as path from 'path'; import { join } from 'path'; import process from 'process'; import { writeFile } from 'fs/promises'; import { PMBOKValidator } from '../pmbokValidation/PMBOKValidator.js'; import { ComplianceValidationService } from '../../services/ComplianceValidationService.js'; import { createProcessor } from './ProcessorFactory.js'; import { createDirectoryStructure, saveDocument, generateIndexFile, cleanupOldFiles, } from '../fileManager.js'; import { AIProcessor } from '../ai/AIProcessor.js'; import { ConfigurationManager } from '../ai/ConfigurationManager.js'; // Import all processor functions import * as processors from '../ai/processors/index.js'; import { readFileSync } from 'fs'; // Load processor-config.json at runtime to avoid import assertions under ESM const processorConfig = JSON.parse(readFileSync(new URL('./processor-config.json', import.meta.url), 'utf8')); import { DOCUMENT_CONFIG } from '../fileManager.js'; import { GENERATION_TASKS, getTaskByKey } from './generationTasks.js'; /** * Class responsible for generating project documentation */ export class DocumentGenerator { options; context; results; aiProcessor; configManager; complianceService; // ...existing code... constructor(context, options = {}, aiProcessor, configManager) { this.context = context; this.aiProcessor = aiProcessor || AIProcessor.getInstance(); this.configManager = configManager || ConfigurationManager.getInstance(); this.options = { includeCategories: options.includeCategories || [], excludeCategories: options.excludeCategories || [], maxConcurrent: options.maxConcurrent || 1, delayBetweenCalls: options.delayBetweenCalls || 500, continueOnError: options.continueOnError ?? true, generateIndex: options.generateIndex ?? true, cleanup: options.cleanup ?? true, outputDir: options.outputDir || 'generated-documents', // Default output directory format: options.format || 'markdown' // Default format }; this.results = { success: false, message: 'Document generation starting...', successCount: 0, failureCount: 0, skippedCount: 0, generatedFiles: [], errors: [], duration: 0 }; // Initialize compliance validation service const complianceConfig = ComplianceValidationService.getDefaultConfig(); this.complianceService = new ComplianceValidationService(complianceConfig); } /** * Generate Data Governance Framework document * @param context Project context */ async generateDataGovernanceFramework(context) { // Find the task by key const taskKey = 'data-governance-framework'; const task = getTaskByKey(taskKey); if (!task) { console.error(`āŒ Unknown document key: ${taskKey}`); return false; } // Setup directory structure if needed createDirectoryStructure(); console.log(`šŸš€ Generating single document: ${task.name}...`); try { const success = await this.generateSingleDocument(task); if (success) { console.log(`āœ… Successfully generated: ${task.name}`); } else { console.log(`āŒ Failed to generate: ${task.name}`); } return success; } catch (error) { console.error(`āŒ Error generating ${task.name}: ${error.message}`); return false; } } /** * Generate Data Governance Plan document * @param context Project context */ async generateDataGovernancePlan(context) { try { const processor = await createProcessor('data-governance-plan'); const output = await processor.process(context); await saveDocument('data-governance-plan', output); return true; } catch (error) { console.error('Error generating Data Governance Plan:', error); return false; } } /** * Save document output to file * @param output Document output to save * @param fileName Optional custom file name (without extension) */ async saveDocumentOutput(output, fileName = 'data-lifecycle-management') { try { const fs = await import('fs/promises'); const path = await import('path'); // Ensure output directory exists await fs.mkdir(this.options.outputDir, { recursive: true }); const filePath = path.join(this.options.outputDir, `${fileName}.${this.options.format}`); await fs.writeFile(filePath, output, 'utf-8'); // Add to generated files list this.results.generatedFiles.push(filePath); this.results.successCount++; } catch (error) { console.error(`āŒ Error saving document output: ${error.message}`); this.results.failureCount++; this.results.errors.push({ task: fileName, error: error.message }); throw error; // Re-throw to be caught by the calling method } } /** * Generate Data Lifecycle Management document * @param context Project context */ async generateDataLifecycleManagement(context) { try { const processor = new (await import('../documentTemplates/dmbok/DataLifecycleManagementProcessor.js')).DataLifecycleManagementProcessor(); const output = await processor.process(context); await this.saveDocumentOutput(output, 'data-lifecycle-management'); console.log('āœ… Successfully generated Data Lifecycle Management document'); return true; } catch (error) { console.error('āŒ Error generating Data Lifecycle Management document:', error.message); return false; } } /** * Generate Master Data Management Strategy document * @param context Project context */ async generateMasterDataManagementStrategy(context) { // Find the task by key const taskKey = 'master-data-management-strategy'; const task = getTaskByKey(taskKey); if (!task) { console.error(`āŒ Unknown document key: ${taskKey}`); return false; } // Setup directory structure if needed createDirectoryStructure(); console.log(`šŸš€ Generating single document: ${task.name}...`); try { const success = await this.generateSingleDocument(task); if (success) { console.log(`āœ… Successfully generated: ${task.name}`); } else { console.log(`āŒ Failed to generate: ${task.name}`); } return success; } catch (error) { console.error(`āŒ Error generating ${task.name}: ${error.message}`); return false; } } // ...rest of the class methods... async getAiUserStories(context) { return await processors.getAiUserStories(context) ?? ''; } async getAiUserPersonas(context) { return await processors.getAiUserPersonas(context) ?? ''; } async getAiKeyRolesAndNeeds(context) { return await processors.getAiKeyRolesAndNeeds(context) ?? ''; } async getAiProjectCharter(context) { return await processors.getAiProjectCharter(context) ?? ''; } // Core Analysis Documents async getAiProjectStatementOfWork(context) { return await processors.getAiProjectStatementOfWork(context) ?? ''; } async getAiBusinessCase(context) { return await processors.getAiBusinessCase(context) ?? ''; } // Strategic Statements async getAiMissionVisionAndCoreValues(context) { return await processors.getMissionVisionAndCoreValues(context) ?? ''; } async getAiProjectPurpose(context) { return await processors.getProjectPurpose(context) ?? ''; } // Project Management Plans async getAiProjectManagementPlan(context) { return await processors.getAiProjectManagementPlan(context) ?? ''; } // PMBOK Process Functions async getAiDirectAndManageProjectWorkProcess(context) { return await processors.getAiDirectAndManageProjectWorkProcess(context) ?? ''; } async getAiPerformIntegratedChangeControlProcess(context) { return await processors.getAiPerformIntegratedChangeControlProcess(context) ?? ''; } async getAiDmbokDataManagementStrategy(context) { if (processors.getAiDmbokDataManagementStrategy) { return await processors.getAiDmbokDataManagementStrategy(context) ?? ''; } // Fallback: try to use the template processor directly try { const { DataManagementStrategyTemplate } = await import('../documentTemplates/dmbok/dataManagementStrategyTemplate.js'); const template = new DataManagementStrategyTemplate(); return template.buildPrompt({ projectName: context }); } catch { return ''; } } async getAiCloseProjectOrPhaseProcess(context) { return await processors.getAiCloseProjectOrPhaseProcess(context) ?? ''; } async getAiPlanScopeManagement(context) { return await processors.getAiPlanScopeManagement(context) ?? ''; } async getAiRequirementsManagementPlan(context) { return await processors.getAiRequirementsManagementPlan(context) ?? ''; } async getAiCollectRequirementsProcess(context) { return await processors.getAiCollectRequirementsProcess(context) ?? ''; } async getAiRequirementsDocumentation(context) { return await processors.getAiRequirementsDocumentation(context) ?? ''; } async getAiRequirementsTraceabilityMatrix(context) { return await processors.getAiRequirementsTraceabilityMatrix(context) ?? ''; } async getAiDefineScopeProcess(context) { return await processors.getAiDefineScopeProcess(context) ?? ''; } async getAiProjectScopeStatement(context) { return await processors.getAiProjectScopeStatement(context) ?? ''; } async getAiCreateWbsProcess(context) { return await processors.getAiCreateWbsProcess(context) ?? ''; } async getAiScopeBaseline(context) { return await processors.getAiScopeBaseline(context) ?? ''; } async getAiValidateScopeProcess(context) { return await processors.getAiValidateScopeProcess(context) ?? ''; } async getAiControlScopeProcess(context) { return await processors.getAiControlScopeProcess(context) ?? ''; } async getAiWorkPerformanceInformationScope(context) { return await processors.getAiWorkPerformanceInformationScope(context) ?? ''; } // Management Plans async getAiScopeManagementPlan(context) { return await processors.getAiScopeManagementPlan(context) ?? ''; } async getAiRiskManagementPlan(context) { return await processors.getAiRiskManagementPlan(context) ?? ''; } async getAiCostManagementPlan(context) { return await processors.getAiCostManagementPlan(context) ?? ''; } async getAiQualityManagementPlan(context) { return await processors.getAiQualityManagementPlan(context) ?? ''; } async getAiResourceManagementPlan(context) { return await processors.getAiResourceManagementPlan(context) ?? ''; } async getAiCommunicationManagementPlan(context) { return await processors.getAiCommunicationManagementPlan(context) ?? ''; } async getAiProcurementManagementPlan(context) { return await processors.getAiProcurementManagementPlan(context) ?? ''; } // Stakeholder Management async getAiStakeholderEngagementPlan(context) { return await processors.getAiStakeholderEngagementPlan(context) ?? ''; } async getAiStakeholderRegister(context) { return await processors.getAiStakeholderRegister(context) ?? ''; } async getAiStakeholderAnalysis(context) { return await processors.getAiStakeholderAnalysis(context) ?? ''; } // Planning Artifacts async getAiWbs(context) { return await processors.getAiWbs(context) ?? ''; } async getAiWbsDictionary(context) { return await processors.getAiWbsDictionary(context) ?? ''; } async getAiActivityList(context) { return await processors.getAiActivityList(context) ?? ''; } async getAiActivityDurationEstimates(context) { return await processors.getAiActivityDurationEstimates(context) ?? ''; } async getAiActivityResourceEstimates(context) { return await processors.getAiActivityResourceEstimates(context) ?? ''; } async getAiScheduleNetworkDiagram(context) { return await processors.getAiScheduleNetworkDiagram(context) ?? ''; } async getAiMilestoneList(context) { return await processors.getAiMilestoneList(context) ?? ''; } async getAiDevelopScheduleInput(context) { return await processors.getAiDevelopScheduleInput(context) ?? ''; } // Technical Analysis async getAiDataModelSuggestions(context) { return await processors.getAiDataModelSuggestions(context) ?? ''; } async getAiTechStackAnalysis(context) { return await processors.getAiTechStackAnalysis(context) ?? ''; } async getAiRiskAnalysis(context) { return await processors.getAiRiskAnalysis(context) ?? ''; } async getAiAcceptanceCriteria(context) { return await processors.getAiAcceptanceCriteria(context) ?? ''; } async getAiComplianceConsiderations(context) { return await processors.getAiComplianceConsiderations(context) ?? ''; } async getAiUiUxConsiderations(context) { return await processors.getAiUiUxConsiderations(context) ?? ''; } async getProjectKickoffPreparationsChecklist(context) { // Import the processor and run its process method const { ProjectKickoffPreparationsChecklistProcessor } = await import('../documentTemplates/planningArtifacts/projectKickoffPreparationsChecklistProcessor.js'); const processor = new ProjectKickoffPreparationsChecklistProcessor(); const output = await processor.process({ projectName: context }); return output.content; } /** * Filter and sort tasks based on options and dependencies */ filterTasks() { let tasks = [...GENERATION_TASKS]; // Filter by included categories if (this.options.includeCategories.length > 0) { tasks = tasks.filter(task => this.options.includeCategories.includes(task.category)); } // Filter out excluded categories if (this.options.excludeCategories.length > 0) { tasks = tasks.filter(task => !this.options.excludeCategories.includes(task.category)); } // Build map for quick lookup const taskMap = new Map(tasks.map(t => [t.key, t])); // Initialize in-degree and adjacency lists const inDegree = new Map(); const adj = new Map(); tasks.forEach(t => { inDegree.set(t.key, 0); adj.set(t.key, []); }); // Populate graph edges from dependencies tasks.forEach(t => { const deps = processorConfig[t.key]?.dependencies || []; deps.forEach(dep => { if (!taskMap.has(dep)) { throw new Error(`Processor dependency not found: ${dep} for task ${t.key}`); } adj.get(dep).push(t.key); inDegree.set(t.key, (inDegree.get(t.key) || 0) + 1); }); }); // Kahn's algorithm for topological sort, using priority to order zero-degree tasks const sorted = []; let zeroDeg = tasks.filter(t => (inDegree.get(t.key) || 0) === 0); zeroDeg.sort((a, b) => a.priority - b.priority); while (zeroDeg.length > 0) { const current = zeroDeg.shift(); sorted.push(current); adj.get(current.key).forEach(nextKey => { inDegree.set(nextKey, (inDegree.get(nextKey) || 1) - 1); if (inDegree.get(nextKey) === 0) { zeroDeg.push(taskMap.get(nextKey)); } }); zeroDeg.sort((a, b) => a.priority - b.priority); } if (sorted.length !== tasks.length) { throw new Error('Cycle detected in document processor dependencies'); } return sorted; } /** * Generate a single document * @param task Task to generate document for * @returns Whether generation was successful */ async generateSingleDocument(task) { try { console.log(`${task.emoji} Generating ${task.name}...`); // Use generic ProcessorFactory to create and run the processor const processor = await createProcessor(task.key); const output = await processor.process({ projectName: this.context }); const content = output.content; if (content && content.trim().length > 0) { const documentKey = task.key; const config = DOCUMENT_CONFIG[documentKey]; // Validate compliance before saving console.log(`šŸ” Validating compliance for ${task.name}...`); try { const complianceValidation = await this.complianceService.validateDocumentCompliance(task.key, task.category, content); // Log compliance results console.log(`šŸ“Š Compliance Score: ${complianceValidation.complianceScore}% (${complianceValidation.complianceStatus})`); // Check if compliance issues need to be addressed if (complianceValidation.issues.length > 0) { console.log(`āš ļø Found ${complianceValidation.issues.length} compliance issues:`); complianceValidation.issues.slice(0, 3).forEach(issue => { console.log(` • ${issue.description}`); }); } // Save compliance report await this.saveComplianceReport(task.key, complianceValidation); } catch (complianceError) { console.warn(`āš ļø Compliance validation failed for ${task.name}:`, complianceError); // Continue with document generation even if compliance validation fails } if (!config) { console.error(`āŒ Unknown document key: ${documentKey}`); saveDocument(documentKey, content); this.results.generatedFiles.push(`${task.category}/${documentKey}.md`); console.log(`āœ… Generated: ${task.name} (using default filename)`); return true; } saveDocument(documentKey, content); this.results.generatedFiles.push(`${task.category}/${config.filename}`); console.log(`āœ… Generated: ${task.name}`); return true; } else { console.log(`āš ļø No content generated for ${task.name}`); return false; } } catch (error) { const errorMsg = error.message || 'Unknown error'; console.error(`āŒ Error generating ${task.name}: ${errorMsg}`); this.results.errors.push({ task: task.name, error: errorMsg }); return false; } } /** * Save compliance report for a document * @param documentKey Document key * @param validation Compliance validation result */ async saveComplianceReport(documentKey, validation) { try { const reportContent = this.generateComplianceReportContent(validation); const reportPath = join(this.options.outputDir, 'compliance-reports', `${documentKey}-compliance.md`); // Ensure compliance reports directory exists const reportsDir = join(this.options.outputDir, 'compliance-reports'); await fs.mkdir(reportsDir, { recursive: true }); await writeFile(reportPath, reportContent); console.log(`šŸ“„ Compliance report saved: ${reportPath}`); } catch (error) { console.warn(`āš ļø Failed to save compliance report for ${documentKey}:`, error); } } /** * Generate compliance report content * @param validation Compliance validation result * @returns Formatted compliance report content */ generateComplianceReportContent(validation) { const timestamp = new Date().toISOString(); return `# Compliance Validation Report **Document:** ${validation.documentId} **Document Type:** ${validation.documentType} **Validation Date:** ${timestamp} **Compliance Score:** ${validation.complianceScore}% **Compliance Status:** ${validation.complianceStatus} ## Executive Summary This document has been validated against enterprise governance policies, regulatory requirements, and industry standards to ensure compliance with organizational requirements. ## Governance Policy Compliance **Overall Compliance:** ${validation.governancePolicyCompliance.overallCompliance ? 'āœ… COMPLIANT' : 'āŒ NON-COMPLIANT'} **Policy Checks:** ${validation.governancePolicyCompliance.policyChecks.length} **Policy Violations:** ${validation.governancePolicyCompliance.policyViolations.length} ${validation.governancePolicyCompliance.policyViolations.length > 0 ? ` ### Policy Violations ${validation.governancePolicyCompliance.policyViolations.map(violation => ` - **${violation.description}** - Severity: ${violation.severity} - Impact: ${violation.impact} - Remediation: ${violation.remediation} `).join('')} ` : ''} ## Regulatory Compliance **Overall Compliance:** ${validation.regulatoryCompliance.overallCompliance ? 'āœ… COMPLIANT' : 'āŒ NON-COMPLIANT'} **Applicable Regulations:** ${validation.regulatoryCompliance.applicableRegulations.length} **Compliance Gaps:** ${validation.regulatoryCompliance.complianceGaps.length} **Risk Level:** ${validation.regulatoryCompliance.riskAssessment.overallRisk} ${validation.regulatoryCompliance.complianceGaps.length > 0 ? ` ### Compliance Gaps ${validation.regulatoryCompliance.complianceGaps.map(gap => ` - **${gap.description}** - Severity: ${gap.severity} - Impact: ${gap.impact} - Remediation: ${gap.remediation} - Timeline: ${gap.timeline} `).join('')} ` : ''} ## Enterprise Standards Compliance **Overall Compliance:** ${validation.enterpriseStandardsCompliance.overallCompliance ? 'āœ… COMPLIANT' : 'āŒ NON-COMPLIANT'} **Standards Checked:** ${validation.enterpriseStandardsCompliance.standardsChecks.length} **Deviations:** ${validation.enterpriseStandardsCompliance.deviations.length} **Improvement Areas:** ${validation.enterpriseStandardsCompliance.improvementAreas.length} ${validation.enterpriseStandardsCompliance.deviations.length > 0 ? ` ### Standards Deviations ${validation.enterpriseStandardsCompliance.deviations.map(deviation => ` - **${deviation.description}** - Severity: ${deviation.severity} - Justification: ${deviation.justification} - Approved: ${deviation.approved ? 'Yes' : 'No'} `).join('')} ` : ''} ## Issues and Recommendations ### Critical Issues (${validation.issues.length}) ${validation.issues.map(issue => ` - **${issue.description}** - Category: ${issue.category} - Severity: ${issue.severity} - Impact: ${issue.impact} - Recommendation: ${issue.recommendation} `).join('')} ### Recommendations (${validation.recommendations.length}) ${validation.recommendations.map(rec => ` - **${rec.description}** - Priority: ${rec.priority} - Category: ${rec.category} - Timeline: ${rec.timeline} - Benefits: ${rec.benefits.join(', ')} `).join('')} ## Next Steps 1. **Address Critical Issues:** Review and resolve all critical compliance issues identified above 2. **Implement Recommendations:** Prioritize and implement the recommended improvements 3. **Monitor Compliance:** Establish ongoing monitoring to ensure continued compliance 4. **Regular Reviews:** Schedule periodic compliance reviews to maintain standards --- *This report was generated by the ADPA Compliance Validation Service - ensuring your documents meet the highest standards of governance, regulatory, and enterprise compliance.* `; } /** * Wait for a specified amount of time * @param ms Milliseconds to wait */ async delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Generate all documents based on options * @returns Generation result */ async generateAll() { const startTime = Date.now(); console.log('šŸ“‹ Starting document generation...'); // Setup directory structure if (this.options.cleanup) { cleanupOldFiles(); } createDirectoryStructure(); const tasks = this.filterTasks(); console.log(`šŸ“ Planning to generate ${tasks.length} documents in ${this.options.maxConcurrent} concurrent batches`); // Process tasks in batches for (let i = 0; i < tasks.length; i += this.options.maxConcurrent) { const batch = tasks.slice(i, i + this.options.maxConcurrent); const batchPromises = batch.map(async (task) => { const success = await this.generateSingleDocument(task); if (success) { this.results.successCount++; } else { this.results.failureCount++; } // Add delay between calls to avoid rate limiting if (this.options.delayBetweenCalls > 0) { await this.delay(this.options.delayBetweenCalls); } return success; }); try { await Promise.all(batchPromises); } catch (error) { if (!this.options.continueOnError) { console.error(`āŒ Batch processing failed: ${error.message}`); break; } } } // Generate documentation index if (this.options.generateIndex) { try { generateIndexFile(); console.log('šŸ“‹ Generated documentation index'); } catch (error) { console.error(`āŒ Failed to generate index: ${error.message}`); } } this.results.duration = Date.now() - startTime; this.results.success = this.results.successCount > 0; this.results.message = this.results.success ? `Successfully generated ${this.results.successCount} documents` : `Failed to generate any documents`; this.printSummary(); return this.results; } /** * Generate a single document by key * @param documentKey The key of the document to generate (e.g., 'summary', 'user-stories', 'project-charter') * @returns Whether generation was successful */ async generateOne(documentKey) { // Map common document keys to actual task keys const keyMapping = { 'summary': 'project-summary', 'user-stories': 'user-stories', 'project-charter': 'project-charter' }; // Use mapped key or original key if no mapping exists const taskKey = keyMapping[documentKey] || documentKey; // Find the task by key const task = getTaskByKey(taskKey); if (!task) { console.error(`āŒ Unknown document key: ${documentKey} (mapped to: ${taskKey})`); return false; } // Setup directory structure if needed createDirectoryStructure(); console.log(`šŸš€ Generating single document: ${task.name}...`); try { const success = await this.generateSingleDocument(task); if (success) { console.log(`āœ… Successfully generated: ${task.name}`); } else { console.log(`āŒ Failed to generate: ${task.name}`); } return success; } catch (error) { console.error(`āŒ Error generating ${task.name}: ${error.message}`); return false; } } /** * Print generation summary */ printSummary() { console.log(`\nšŸ“Š Generation Summary:`); console.log(`āœ… Successfully generated: ${this.results.successCount} documents`); console.log(`āŒ Failed to generate: ${this.results.failureCount} documents`); console.log(`ā±ļø Total duration: ${(this.results.duration / 1000).toFixed(2)}s`); console.log(`šŸ“ Documents organized in: ${this.options.outputDir}/`); if (this.results.generatedFiles.length > 0) { console.log(`šŸ“‹ Generated files:`); this.results.generatedFiles.forEach(file => { console.log(` • ${file}`); }); } if (this.results.errors.length > 0) { console.log(`\nāŒ Errors encountered:`); this.results.errors.forEach(error => { console.log(` • ${error.task}: ${error.error}`); }); } console.log(`šŸ“‹ See ${this.options.outputDir}/README.md for complete index`); } /** * Validate that all expected documents exist * @returns Validation result */ async validateGeneration() { const validation = { isComplete: true, missing: [], errors: [] }; const tasks = this.filterTasks(); // Check if all expected documents exist for (const task of tasks) { const config = DOCUMENT_CONFIG[task.key]; const expectedPath = config ? `${this.options.outputDir}/${task.category}/${config.filename}` : `${this.options.outputDir}/${task.category}/${task.key}.md`; try { await fs.access(expectedPath); console.log(`āœ… Found: ${task.name}`); } catch (error) { validation.missing.push(`${task.name} (${expectedPath})`); validation.isComplete = false; } } // Check for README.md try { await fs.access(`${this.options.outputDir}/README.md`); console.log(`āœ… Found: Documentation Index`); } catch (error) { validation.missing.push(`Documentation Index (${this.options.outputDir}/README.md)`); validation.isComplete = false; } return validation; } /** * Generate a markdown file * @param outputDir Output directory * @param fileName File name * @param title Document title * @param content Document content */ static async generateMarkdownFile(outputDir, fileName, title, content) { // Ensure the output directory exists await fs.mkdir(outputDir, { recursive: true }); const filePath = path.join(outputDir, fileName); const timestamp = new Date().toISOString(); const fileContent = `# ${title} **Generated:** ${timestamp} **Generated by:** Requirements Gathering Agent v2.1.2 --- ${content}`; await fs.writeFile(filePath, fileContent, 'utf-8'); console.log(`āœ… Generated: ${filePath}`); } // Static convenience methods for different document sets /** * Generate core documents only * @param context Project context * @returns Generation result */ static async generateCoreDocuments(context) { const generator = new DocumentGenerator(context, { includeCategories: ['core-analysis', 'project-charter', 'scope-management', 'risk-management'], delayBetweenCalls: 1000 }); return await generator.generateAll(); } /** * Generate management plans only * @param context Project context * @returns Generation result */ static async generateManagementPlans(context) { const generator = new DocumentGenerator(context, { includeCategories: ['management-plans'], delayBetweenCalls: 800 }); return await generator.generateAll(); } /** * Generate planning artifacts only * @param context Project context * @returns Generation result */ static async generatePlanningArtifacts(context) { const generator = new DocumentGenerator(context, { includeCategories: ['planning-artifacts'], delayBetweenCalls: 600 }); return await generator.generateAll(); } /** * Generate technical analysis including technical design documents * @param context Project context * @returns Generation result */ static async generateTechnicalAnalysis(context) { const generator = new DocumentGenerator(context, { includeCategories: ['technical-analysis', 'technical-design'], delayBetweenCalls: 500 }); return await generator.generateAll(); } /** * Generate stakeholder documents only * @param context Project context * @returns Generation result */ static async generateStakeholderDocuments(context) { const generator = new DocumentGenerator(context, { includeCategories: ['stakeholder-management'], delayBetweenCalls: 800, maxConcurrent: 1 }); return await generator.generateAll(); } /** * Validate PMBOK compliance across documents using the real PMBOKValidator * @returns Comprehensive compliance validation result */ async validatePMBOKCompliance() { console.log('šŸ” Running comprehensive PMBOK validation...'); try { // Initialize the real PMBOKValidator const validator = new PMBOKValidator(this.options.outputDir); // Get all available document types from the configuration const documentTypes = Object.keys(processors); // Perform comprehensive validation const validationResult = await validator.performComprehensiveValidation(documentTypes); // Extract key metrics for compatibility with existing interfaces const consistencyScore = validationResult.pmbokCompliance.consistencyScore || 0; const documentQuality = validationResult.pmbokCompliance.documentQuality || {}; // Determine overall compliance based on our enhanced criteria const compliance = this.determineOverallCompliance(validationResult); console.log(`āœ… PMBOK validation complete. Consistency Score: ${consistencyScore}/100`); return { compliance, consistencyScore, documentQuality, validationResult // Include full validation result for detailed reporting }; } catch (error) { console.error('āŒ Error during PMBOK validation:', error); // Fallback to ensure the system continues to work return { compliance: false, consistencyScore: 0, documentQuality: {}, validationResult: { error: error instanceof Error ? error.message : 'Unknown validation error' } }; } } /** * Determine overall compliance based on comprehensive validation results * @param validationResult Full validation result from PMBOKValidator * @returns Whether the documents meet compliance standards */ determineOverallCompliance(validationResult) { // More sophisticated compliance determination const consistencyScore = validationResult.pmbokCompliance?.consistencyScore || 0; const documentQuality = validationResult.pmbokCompliance?.documentQuality || {}; // Check if consistency score meets threshold if (consistencyScore < 70) { return false; } // Check if any critical documents have very low scores const criticalDocuments = ['project-charter', 'stakeholder-register', 'scope-management-plan']; for (const docType of criticalDocuments) { const quality = documentQuality[docType]; if (quality && quality.score < 60) { return false; } } // Check for critical missing documents const generationSuccess = validationResult.validation?.isComplete; if (generationSuccess === false) { return false; } return true; } // Placeholder methods removed - now using real PMBOKValidator /** * Generate all documents and validate PMBOK compliance * @param context Project context * @returns Generation and compliance result */ static async generateAllWithPMBOKValidation(context) { console.log('šŸš€ Starting Generate-and-Validate Cycle...'); console.log('šŸ“Š This is the ADPA Quality Assurance Engine in action'); const generator = new DocumentGenerator(context); // Phase 1: Generation console.log('\nšŸ”„ Phase 1: Document Generation'); const result = await generator.generateAll(); if (!result.success) { return { result: result, compliance: { score: 0, details: ['Generation failed - cannot validate'], isCompliant: false, qualityReport: null, actionableInsights: ['Fix generation errors before validation'], improvementRecommendations: ['Check configuration and context quality'] } }; } console.log(`āœ… Generated ${result.successCount} documents successfully`); // Phase 2: Comprehensive PMBOK Validation console.log('\nšŸ” Phase 2: PMBOK 7.0 Validation & Quality Assessment'); const pmbokValidation = await generator.validatePMBOKCompliance(); // Phase 3: Generate Quality Report with Actionable Insights console.log('\nšŸ“‹ Phase 3: Quality Analysis & Improvement Recommendations'); const actionableInsights = []; const improvementRecommendations = []; // Analyze document quality scores and provide specific guidance if (pmbokValidation.documentQuality) { for (const [docKey, quality] of Object.entries(pmbokValidation.documentQuality)) { const docQuality = quality; if (docQuality.score < 70) { actionableInsights.push(`🚨 ${docKey}: Score ${docQuality.score}/100 - Needs immediate attention`); // Specific recommendations based on missing elements if (docQuality.missingElements?.length > 0) { improvementRecommendations.push(`${docKey}: Add missing PMBOK elements: ${docQuality.missingElements.slice(0, 3).join(', ')}${docQuality.missingElements.length > 3 ? '...' : ''}`); } if (docQuality.structureScore < 60) { improvementRecommendations.push(`${docKey}: Improve document structure and section organization`); } if (docQuality.terminologyScore < 60) { improvementRecommendations.push(`${docKey}: Enhance PMBOK terminology usage in prompts`); } } } } // Cross-document consistency insights if (pmbokValidation.consistencyScore < 80) { actionableInsights.push(`šŸ”— Cross-document consistency needs improvement: ${pmbokValidation.consistencyScore}/100`); improvementRecommendations.push('Review project charter alignment across all documents'); improvementRecommendations.push('Ensure stakeholder information is consistent between documents'); } // Generate overall quality insights const overallScore = pmbokValidation.consistencyScore; const isCompliant = pmbokValidation.compliance && overallScore >= 75; if (!isCompliant) { actionableInsights.push('šŸŽÆ Overall PMBOK compliance below acceptable threshold'); improvementRecommendations.push('Focus on top 3 lowest-scoring documents for prompt engineering'); improvementRecommendations.push('Review PMBOK 7.0 performance domains integration'); } // Success insights if (isCompliant) { actionableInsights.push('āœ… PMBOK compliance achieved - documents meet professional standards'); } console.log('\nšŸ“Š Quality Assessment Complete'); console.log(`šŸŽÆ Overall Compliance Score: ${overallScore}/100`); console.log(`šŸ“‹ Status: ${isCompliant ? 'āœ… COMPLIANT' : 'āŒ NON-COMPLIANT'}`); if (actionableInsights.length > 0) { console.log('\nšŸ’” Key Insights:'); actionableInsights.forEach((insight, i) => console.log(` ${i + 1}. ${insight}`)); } if (improvementRecommendations.length > 0) { console.log('\nšŸ”§ Improvement Recommendations:'); improvementRecommendations.slice(0, 5).forEach((rec, i) => console.log(` ${i + 1}. ${rec}`)); } // Save comprehensive quality report const qualityReportPath = join(process.cwd(), 'generated-documents', 'quality-assessment-report.md'); const qualityReportContent = this.generateQualityReport(pmbokValidation, actionableInsights, improvementRecommendations); try { await writeFile(qualityReportPath, qualityReportContent); console.log(`\nšŸ“„ Comprehensive quality report saved: ${qualityReportPath}`); } catch (error) { console.warn('Could not save quality report:', error); } return { result: result, compliance: { score: overallScore, details: [ `PMBOK Compliance: ${pmbokValidation.compliance ? 'Compliant' : 'Non-compliant'}`, `Consistency Score: ${pmbokValidation.consistencyScore}/100`, `Documents Assessed: ${Object.keys(pmbokValidation.documentQuality || {}).length}`, `Critical Issues: ${actionableInsights.filter(i => i.includes('🚨')).length}`, `Improvement Areas: ${improvementRecommendations.length}` ], isCompliant, qualityReport: pmbokValidation, actionableInsights, improvementRecommendations } }; } /** * Generate a comprehensive quality assessment report in markdown format */ static generateQualityReport(validation, insights, recommendations) { const timestamp = new Date().toISOString(); return `# ADPA Quality Assurance Report **Generated:** ${timestamp} **System:** ADPA Quality Assurance Engine v2.0 **Standard:** PMBOK 7.0 Performance Domains ## Executive Summary **Overall Compliance Score:** ${validation.consistencyScore}/100 **Status:** ${validation.compliance ? 'āœ… COMPLIANT' : 'āŒ NON-COMPLIANT'} **Documents Assessed:** ${Object.keys(validation.documentQuality || {}).length} ## Key Quality Insights ${insights.map((insight, i) => `${i + 1}. ${insight.replace(/🚨|šŸ”—|šŸŽÆ|āœ…/g, '')}`).join('\n')} ## Document Quality Breakdown ${Object.entries(validation.documentQuality || {}).map(([key, quality]) => { return `### ${key} - **Score:** ${quality.score}/100 - **Issues Found:** ${quality.issues?.length || 0} - **Strengths:** ${quality.strengths?.length || 0} - **Status:** ${quality.score >= 70 ? 'āœ… Acceptable' : 'āŒ Needs Improvement'} ${quality.issues?.length > 0 ? `**Issues:** ${quality.issues.slice(0, 5).join(', ')}${quality.issues.length > 5 ? '...' : ''}` : ''} ${quality.strengths?.length > 0 ? `**Strengths:** ${quality.strengths.join(', ')}` : ''} `; }).join('\n')} ## Improvement Recommendations ${recommendations.map((rec, i) => `${i + 1}. ${rec}`).join('\n')} ## Cross-Document Consistency **Consistency Score:** ${validation.consistencyScore}/100 ${validation.consistencyIssues ? `**Issues Found:** ${validation.consistencyIssues.map((issue) => `- ${issue}`).join('\n')}` : 'No significant consistency issues detected.'} ## Next Steps for Quality Improvement 1. **Priority Focus:** Address documents scoring below 70/100 2. **Prompt Engineering:** Enhance prompts for low-scoring documents 3. **PMBOK Integration:** Strengthen performance domain coverage 4. **Consistency Review:** Align cross-document references and terminology 5. **Iterative Improvement:** Re-run validation after improvements --- *This report was generated by the ADPA Quality Assurance Engine - your intelligent document compliance partner.* `; } } /** * Version information */ export const documentGeneratorVersion = '2.1.3'; //# sourceMappingURL=DocumentGenerator.js.map