UNPKG

task-master-neo-sdlc

Version:

Enhanced task management system with Neo SDLC agents and MCP tools for comprehensive, AI-driven software development lifecycle management.

136 lines (122 loc) 6.1 kB
import { KnowledgeGraph } from '../knowledge-graph'; import { AgentWorkflowSystem } from '../agent-workflow'; // Assume some rules engine or configuration for architectural constraints // import architectureRules from '../../config/architecture-rules'; export class ArchitectureValidatorAgent { constructor(knowledgeGraph, workflow) { this.knowledgeGraph = knowledgeGraph; this.workflow = workflow; // Load or define architectural rules this.rules = [ { id: 'rule-no-direct-db-from-frontend', description: 'Frontend components should not directly depend on DB schemas.', check: this.checkNoDirectDbFromFrontend.bind(this) }, { id: 'rule-api-gateway-pattern', description: 'Components should interact via defined API endpoints, not directly.', check: this.checkApiUsage.bind(this) }, // Add more rules based on project architecture ]; } /** * Validates the current system state against defined architectural rules. * @param {string[]} [ruleIds] - Optional list of specific rule IDs to check. If null, checks all rules. * @returns {Promise<object>} A validation report object. */ async validateArchitecture(ruleIds = null) { console.log('Validating architecture against rules:', ruleIds || 'All'); const applicableRules = ruleIds ? this.rules.filter(r => ruleIds.includes(r.id)) : this.rules; const violations = []; const checksPassed = []; for (const rule of applicableRules) { try { const ruleViolations = await rule.check(); if (ruleViolations.length > 0) { violations.push(...ruleViolations.map(v => ({ ruleId: rule.id, description: rule.description, details: v }))); } else { checksPassed.push(rule.id); } } catch (error) { console.error(`Error executing rule ${rule.id}:`, error); violations.push({ ruleId: rule.id, description: rule.description, details: `Error during check: ${error.message}` }); } } const reportId = `archValidation_${Date.now()}`; const report = { id: reportId, timestamp: Date.now(), rulesChecked: applicableRules.map(r => r.id), violations, passedChecks: checksPassed, isCompliant: violations.length === 0 }; // Add report to knowledge graph await this.knowledgeGraph.addNode({ id: `architectureValidation:${reportId}`, type: 'architecture_validation_report', data: report }); console.log(`Architecture validation ${reportId} completed. Compliant: ${report.isCompliant}`); return report; } // --- Example Rule Implementations --- /** * Rule Check: Frontend components should not directly depend on DB schemas. * @returns {Promise<Array<string>>} List of violation details. */ async checkNoDirectDbFromFrontend() { const violations = []; const frontendComponentNodes = await this.knowledgeGraph.findNodes({ type: 'design-component' }); // Assuming type from DesignSystemManager const dbSchemaNodes = await this.knowledgeGraph.findNodes({ type: 'db_schema' }); const dbSchemaIds = new Set(dbSchemaNodes.map(n => n.id)); for (const componentNode of frontendComponentNodes) { // Check direct edges or dependency lists in component data const edges = await this.knowledgeGraph.findEdges({ source: componentNode.id }); for (const edge of edges) { if (edge.relationship === 'depends_on' && dbSchemaIds.has(edge.target)) { violations.push(`Frontend component ${componentNode.id} directly depends on DB schema ${edge.target}`); } } // Also check dependency array if stored in node data if (componentNode.data?.dependencies) { for (const depId of componentNode.data.dependencies) { if (dbSchemaIds.has(depId)) { violations.push(`Frontend component ${componentNode.id} lists direct dependency on DB schema ${depId}`); } } } } return violations; } /** * Rule Check: Components should primarily interact via APIs, not directly. * (This is a simplified example) * @returns {Promise<Array<string>>} List of violation details. */ async checkApiUsage() { const violations = []; const componentNodes = await this.knowledgeGraph.findNodes({ type: 'design-component' }); const apiEndpointNodes = await this.knowledgeGraph.findNodes({ type: 'api_endpoint' }); const apiEndpointIds = new Set(apiEndpointNodes.map(n => n.id)); for (const componentNode of componentNodes) { // Find dependencies that are OTHER components, not APIs or basic types/libs const edges = await this.knowledgeGraph.findEdges({ source: componentNode.id, relationship: 'depends_on' }); const componentDependencies = await this.knowledgeGraph.findNodes({ ids: edges.map(e => e.target) }); for (const dependency of componentDependencies) { if (dependency.type === 'design-component' && !apiEndpointIds.has(dependency.id)) { // Check if there's an API connection between them as an alternative path const apiEdgeExists = await this.knowledgeGraph.findEdges({ source: componentNode.id, relationship: 'consumes_api', target_type: 'api_endpoint' // Assuming target_type filter exists }); const targetApiEdgeExists = await this.knowledgeGraph.findEdges({ source_type: 'api_endpoint', relationship: 'depends_on', target: dependency.id }); // Super simplified: if direct component dependency exists AND no intermediate API link found, flag it. if (!apiEdgeExists.some(edge => targetApiEdgeExists.some(tEdge => tEdge.source === edge.target))) { violations.push(`Potential direct component interaction (violates API Gateway): ${componentNode.id} -> ${dependency.id}. Consider using an API.`); } } } } return violations; } }