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
JavaScript
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;
}
}