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
147 lines • 5.55 kB
JavaScript
/**
* File Existence Validator
*
* Validates that expected PMBOK documents exist in the file system.
* This is a fundamental check that ensures the basic generation process
* has completed successfully before running more detailed content analysis.
*
* @version 1.0.0
* @author ADPA Quality Assurance Engine Team
* @created June 2025
*/
import * as fs from 'fs/promises';
import * as path from 'path';
export class FileExistenceValidator {
name = 'File Existence Validator';
description = 'Verifies that expected PMBOK documents exist in the file system';
id = 'file-existence';
version = '1.0.0';
tags = ['basic', 'filesystem', 'pmbok'];
documentsBasePath;
// Required interface properties
applicableDocuments = []; // Apply to all documents
priority = 0; // Highest priority - check files exist first
defaultEnabled = true;
constructor(documentsBasePath = 'generated-documents') {
this.documentsBasePath = documentsBasePath;
}
isApplicable(documentTypes) {
// File existence should always be checked regardless of document types
return true;
}
getConfigSchema() {
return {};
}
async validate(config) {
const startTime = Date.now();
const issues = [];
const strengths = [];
const recommendations = [];
let score = 100;
const maxScore = 100;
console.log('📁 Validating file existence...');
// Check if base documents directory exists
try {
await fs.access(this.documentsBasePath);
strengths.push('Documents directory exists');
}
catch (error) {
issues.push(`Documents directory '${this.documentsBasePath}' does not exist`);
score = 0;
return {
validatorId: this.id,
validatorName: this.name,
passed: false,
score,
maxScore,
issues,
strengths,
severity: 'critical',
recommendations: ['Ensure document generation has completed successfully'],
executionTimeMs: Date.now() - startTime,
metadata: { basePathMissing: true }
};
}
// Expected core PMBOK documents
const expectedDocuments = [
'project-charter/project-charter.md',
'stakeholder-management/stakeholder-register.md',
'scope-management/project-scope-statement.md',
'strategic-statements/mission-vision-core-values.md'
];
let foundDocuments = 0;
const missingDocuments = [];
for (const docPath of expectedDocuments) {
const fullPath = path.join(this.documentsBasePath, docPath);
try {
await fs.access(fullPath);
foundDocuments++;
strengths.push(`Found: ${docPath}`);
}
catch (error) {
missingDocuments.push(docPath);
issues.push(`Missing document: ${docPath}`);
}
}
// Calculate score based on found documents
score = Math.round((foundDocuments / expectedDocuments.length) * 100);
// Add recommendations for missing documents
if (missingDocuments.length > 0) {
recommendations.push(`Generate missing documents: ${missingDocuments.join(', ')}`);
recommendations.push('Check document generation logs for errors');
}
// Check for additional documents that exist
try {
const allFiles = await this.findAllMarkdownFiles(this.documentsBasePath);
if (allFiles.length > expectedDocuments.length) {
strengths.push(`Found ${allFiles.length} total documents (${allFiles.length - expectedDocuments.length} additional)`);
}
}
catch (error) {
// Non-critical error
}
const passed = score >= 80; // 80% threshold for file existence
return {
validatorId: this.id,
validatorName: this.name,
passed,
score,
maxScore,
issues,
strengths,
severity: missingDocuments.length > 2 ? 'critical' : missingDocuments.length > 0 ? 'warning' : 'info',
recommendations,
executionTimeMs: Date.now() - startTime,
metadata: {
expectedCount: expectedDocuments.length,
foundCount: foundDocuments,
missingDocuments,
documentsBasePath: this.documentsBasePath
}
};
}
/**
* Recursively find all markdown files in the documents directory
*/
async findAllMarkdownFiles(dir) {
const files = [];
try {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
const subFiles = await this.findAllMarkdownFiles(fullPath);
files.push(...subFiles);
}
else if (entry.name.endsWith('.md')) {
files.push(path.relative(this.documentsBasePath, fullPath));
}
}
}
catch (error) {
// Directory might not be accessible
}
return files;
}
}
//# sourceMappingURL=FileExistenceValidator.js.map