Skip to main content

agent-quorum-manager

Agent skill for quorum-manager - invoke with $agent-quorum-manager

Source facts

Repository
ruvnet/ruflo
Last source activity
February 7, 2026 at 17:36
Detected SKILL.md language
English
Stars
73,469
Forks
8,725

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
agent-quorum-manager
description
Agent skill for quorum-manager - invoke with $agent-quorum-manager
--- name: quorum-manager type: coordinator color: "#673AB7" description: Implements dynamic quorum adjustment and intelligent membership management capabilities: - dynamic_quorum_calculation - membership_management - network_monitoring - weighted_voting - fault_tolerance_optimization priority: high hooks: pre: | echo "🎯 Quorum Manager adjusting: $TASK" # Assess current network conditions if [[ "$TASK" == *"quorum"* ]]; then echo "📡 Analyzing network topology and node health" fi post: | echo "⚖️ Quorum adjustment complete" # Validate new quorum configuration echo "✅ Verifying fault tolerance and availability guarantees" --- # Quorum Manager Implements dynamic quorum adjustment and intelligent membership management for distributed consensus protocols. ## Core Responsibilities 1. **Dynamic Quorum Calculation**: Adapt quorum requirements based on real-time network conditions 2. **Membership Management**: Handle seamless node addition, removal, and failure scenarios 3. **Network Monitoring**: Assess connectivity, latency, and partition detection 4. **Weighted Voting**: Implement capability-based voting weight assignments 5. **Fault Tolerance Optimization**: Balance availability and consistency guarantees ## Technical Implementation ### Core Quorum Management System ```javascript class QuorumManager { constructor(nodeId, consensusProtocol) { this.nodeId = nodeId; this.protocol = consensusProtocol; this.currentQuorum = new Map(); // nodeId -> QuorumNode this.quorumHistory = []; this.networkMonitor = new NetworkConditionMonitor(); this.membershipTracker = new MembershipTracker(); this.faultToleranceCalculator = new FaultToleranceCalculator(); this.adjustmentStrategies = new Map(); this.initializeStrategies(); } // Initialize quorum adjustment strategies initializeStrategies() { this.adjustmentStrategies.set('NETWORK_BASED', new NetworkBasedStrategy()); this.adjustmentStrategies.set('PERFORMANCE_BASED', new PerformanceBasedStrategy()); this.adjustmentStrategies.set('FAULT_TOLERANCE_BASED', new FaultToleranceStrategy()); this.adjustmentStrategies.set('HYBRID', new HybridStrategy()); } // Calculate optimal quorum size based on current conditions async calculateOptimalQuorum(context = {}) { const networkConditions = await this.networkMonitor.getCurrentConditions(); const membershipStatus = await this.membershipTracker.getMembershipStatus(); const performanceMetrics = context.performanceMetrics || await this.getPerformanceMetrics(); const analysisInput = { networkConditions: networkConditions, membershipStatus: membershipStatus, performanceMetrics: performanceMetrics, currentQuorum: this.currentQuorum, protocol: this.protocol, faultToleranceRequirements: context.faultToleranceRequirements || this.getDefaultFaultTolerance() }; // Apply multiple strategies and select optimal result const strategyResults = new Map(); for (const [strategyName, strategy] of this.adjustmentStrategies) { try { const result = await strategy.calculateQuorum(analysisInput); strategyResults.set(strategyName, result); } catch (error) { console.warn(`Strategy ${strategyName} failed:`, error); } } // Select best strategy result const optimalResult = this.selectOptimalStrategy(strategyResults, analysisInput); return { recommendedQuorum: optimalResult.quorum, strategy: optimalResult.strategy, confidence: optimalResult.confidence, reasoning: optimalResult.reasoning, expectedImpact: optimalResult.expectedImpact }; } // Apply quorum changes with validation and rollback capability async adjustQuorum(newQuorumConfig, options = {}) { const adjustmentId = `adjustment_${Date.now()}`; try { // Validate new quorum configuration await this.validateQuorumConfiguration(newQuorumConfig); // Create adjustment plan const adjustmentPlan = await this.createAdjustmentPlan( this.currentQuorum, newQuorumConfig ); // Execute adjustment with monitoring const adjustmentResult = await this.executeQuorumAdjustment( adjustmentPlan, adjustmentId, options ); // Verify adjustment success await this.verifyQuorumAdjustment(adjustmentResult); // Update current quorum this.currentQuorum = newQuorumConfig.quorum; // Record successful adjustment this.recordQuorumChange(adjustmentId, adjustmentResult); return { success: true, adjustmentId: adjustmentId, previousQuorum: adjustmentPlan.previousQuorum, newQuorum: this.currentQuorum, impact: adjustmentResult.impact }; } catch (error) { console.error(`Quorum adjustment failed:`, error); // Attempt rollback await this.rollbackQuorumAdjustment(adjustmentId); throw error; } } async executeQuorumAdjustment(adjustmentPlan, adjustmentId, options) { const startTime = Date.now(); // Phase 1: Prepare nodes for quorum change await this.prepareNodesForAdjustment(adjustmentPlan.affectedNodes); // Phase 2: Execute membership changes const membershipChanges = await this.executeMembershipChanges( adjustmentPlan.membershipChanges ); // Phase 3: Update voting weights if needed if (adjustmentPlan.weightChanges.length > 0) { await this.updateVotingWeights(adjustmentPlan.weightChanges); } // Phase 4: Reconfigure consensus protocol await this.reconfigureConsensusProtocol(adjustmentPlan.protocolChanges); // Phase 5: Verify new quorum is operational const verificationResult = await this.verifyQuorumOperational(adjustmentPlan.newQuorum); const endTime = Date.now(); return { adjustmentId: adjustmentId, duration: endTime - startTime, membershipChanges: membershipChanges, verificationResult: verificationResult, impact: await this.measureAdjustmentImpact(startTime, endTime) }; } } ``` ### Network-Based Quorum Strategy ```javascript class NetworkBasedStrategy { constructor() { this.networkAnalyzer = new NetworkAnalyzer(); this.connectivityMatrix = new ConnectivityMatrix(); this.partitionPredictor = new PartitionPredictor(); } async calculateQuorum(analysisInput) { const { networkConditions, membershipStatus, currentQuorum } = analysisInput; // Analyze network topology and connectivity const topologyAnalysis = await this.analyzeNetworkTopology(membershipStatus.activeNodes); // Predict potential network partitions const partitionRisk = await this.assessPartitionRisk(networkConditions, topologyAnalysis); // Calculate minimum quorum for fault tolerance const minQuorum = this.calculateMinimumQuorum( membershipStatus.activeNodes.length, partitionRisk.maxPartitionSize ); // Optimize for network conditions const optimizedQuorum = await this.optimizeForNetworkConditions( minQuorum, networkConditions, topologyAnalysis ); return { quorum: optimizedQuorum, strategy: 'NETWORK_BASED', confidence: this.calculateConfidence(networkConditions, topologyAnalysis), reasoning: this.generateReasoning(optimizedQuorum, partitionRisk, networkConditions), expectedImpact: { availability: this.estimateAvailabilityImpact(optimizedQuorum), performance: this.estimatePerformanceImpact(optimizedQuorum, networkConditions) } }; } async analyzeNetworkTopology(activeNodes) { const topology = { nodes: activeNodes.length, edges: 0, clusters: [], diameter: 0, connectivity: new Map() }; // Build connectivity matrix for (const node of activeNodes) { const connections = await this.getNodeConnections(node); topology.connectivity.set(node.id, connections); topology.edges += connections.length; } // Identify network clusters topology.clusters = await this.identifyNetworkClusters(topology.connectivity); // Calculate network diameter topology.diameter = await this.calculateNetworkDiameter(topology.connectivity); return topology; } async assessPartitionRisk(networkConditions, topologyAnalysis) { const riskFactors = { connectivityReliability: this.assessConnectivityReliability(networkConditions), geographicDistribution: this.assessGeographicRisk(topologyAnalysis), networkLatency: this.assessLatencyRisk(networkConditions), historicalPartitions: await this.getHistoricalPartitionData() }; // Calculate overall partition risk const overallRisk = this.calculateOverallPartitionRisk(riskFactors); // Estimate maximum partition size const maxPartitionSize = this.estimateMaxPartitionSize( topologyAnalysis, riskFactors ); return { overallRisk: overallRisk, maxPartitionSize: maxPartitionSize, riskFactors: riskFactors, mitigationStrategies: this.suggestMitigationStrategies(riskFactors) }; } calculateMinimumQuorum(totalNodes, maxPartitionSize) { // For Byzantine fault tolerance: need > 2/3 of total nodes const byzantineMinimum = Math.floor(2 * totalNodes / 3) + 1; // For network partition tolerance: need > 1/2 of largest connected component const partitionMinimum = Math.floor((totalNodes - maxPartitionSize) / 2) + 1; // Use the more restrictive requirement return Math.max(byzantineMinimum, partitionMinimum); } async optimizeForNetworkConditions(minQuorum, networkConditions, topologyAnalysis) { const optimization = { baseQuorum: minQuorum, nodes: new Map(), totalWeight: 0 }; // Select nodes for quorum based on network position and reliability const nodeScores = await this.scoreNodesForQuorum(networkConditions, topologyAnalysis); // Sort nodes by score (higher is better) const sortedNodes = Array.from(nodeScores.entries()) .sort(([,scoreA], [,scoreB]) => scoreB - scoreA); // Select top nodes for quorum let selectedCount = 0; for (const [nodeId, score] of sortedNodes) { if (selectedCount < minQuorum) { const weight = this.calculateNodeWeight(nodeId, score, networkConditions); optimization.nodes.set(nodeId, { weight: weight, score: score, role: selectedCount === 0 ? 'primary' : 'secondary' }); optimization.totalWeight += weight; selectedCount++; } } return optimization; } async scoreNodesForQuorum(networkConditions, topologyAnalysis) { const scores = new Map(); for (const [nodeId, connections] of topologyAnalysis.connectivity) { let score = 0; // Connectivity score (more connections = higher score) score += (connections.length / topologyAnalysis.nodes) * 30; // Network position score (central nodes get higher scores) const centrality = this.calculateCentrality(nodeId, topologyAnalysis); score += centrality * 25; // Reliability score based on network conditions const reliability = await this.getNodeReliability(nodeId, networkConditions); score += reliability * 25; // Geographic diversity score const geoScore = await this.getGeographicDiversityScore(nodeId, topologyAnalysis); score += geoScore * 20; scores.set(nodeId, score); } return scores; } calculateNodeWeight(nodeId, score, networkConditions) { // Base weight of 1, adjusted by score and conditions let weight = 1.0; // Adjust based on normalized score (0-1) const normalizedScore = score / 100; weight *= (0.5 + normalizedScore); // Adjust based on network latency const nodeLatency = networkConditions.nodeLatencies.get(nodeId) || 100; const latencyFactor = Math.max(0.1, 1.0 - (nodeLatency / 1000)); // Lower latency = higher weight weight *= latencyFactor; // Ensure minimum weight return Math.max(0.1, Math.min(2.0, weight)); } } ``` ### Performance-Based Quorum Strategy ```javascript class PerformanceBasedStrategy { constructor() { this.performanceAnalyzer = new PerformanceAnalyzer(); this.throughputOptimizer = new ThroughputOptimizer(); this.latencyOptimizer = new LatencyOptimizer(); } async calculateQuorum(analysisInput) { const { performanceMetrics, membershipStatus, protocol } = analysisInput; // Analyze current performance bottlenecks const bottlenecks = await this.identifyPerformanceBottlenecks(performanceMetrics); // Calculate throughput-optimal quorum size const throughputOptimal = await this.calculateThroughputOptimalQuorum( performanceMetrics, membershipStatus.activeNodes ); // Calculate latency-optimal quorum size const latencyOptimal = await this.calculateLatencyOptimalQuorum( performanceMetrics, membershipStatus.activeNodes ); // Balance throughput and latency requirements const balancedQuorum = await this.balanceThroughputAndLatency( throughputOptimal, latencyOptimal, performanceMetrics.requirements ); return { quorum: balancedQuorum, strategy: 'PERFORMANCE_BASED', confidence: this.calculatePerformanceConfidence(performanceMetrics), reasoning: this.generatePerformanceReasoning( balancedQuorum, throughputOptimal, latencyOptimal, bottlenecks ), expectedImpact: { throughputImprovement: this.estimateThroughputImpact(balancedQuorum), latencyImprovement: this.estimateLatencyImpact(balancedQuorum) } }; } async calculateThroughputOptimalQuorum(performanceMetrics, activeNodes) { const currentThroughput = performanceMetrics.throughput; const targetThroughput = performanceMetrics.requirements.targetThroughput; // Analyze relationship between quorum size and throughput const throughputCurve = await this.analyzeThroughputCurve(activeNodes); // Find quorum size that maximizes throughput while meeting requirements let optimalSize = Math.ceil(activeNodes.length / 2) + 1; // Minimum viable quorum let maxThroughput = 0; for (let size = optimalSize; size <= activeNodes.length; size++) { const projectedThroughput = this.projectThroughput(size, throughputCurve); if (projectedThroughput > maxThroughput && projectedThroughput >= targetThroughput) { maxThroughput = projectedThroughput; optimalSize = size; } else if (projectedThroughput < maxThroughput * 0.9) { // Stop if throughput starts decreasing significantly break; } } return await this.selectOptimalNodes(activeNodes, optimalSize, 'THROUGHPUT'); } async calculateLatencyOptimalQuorum(performanceMetrics, activeNodes) { const currentLatency = performanceMetrics.latency; const targetLatency = performanceMetrics.requirements.maxLatency; // Analyze relationship between quorum size and latency const latencyCurve = await this.analyzeLatencyCurve(activeNodes); // Find minimum quorum size that meets latency requirements const minViableQuorum = Math.ceil(activeNodes.length / 2) + 1; for (let size = minViableQuorum; size <= activeNodes.length; size++) { const projectedLatency = this.projectLatency(size, latencyCurve); if (projectedLatency <= targetLatency) { return await this.selectOptimalNodes(activeNodes, size, 'LATENCY'); } } // If no size meets requirements, return minimum viable with warning console.warn('No quorum size meets latency requirements'); return await this.selectOptimalNodes(activeNodes, minViableQuorum, 'LATENCY'); } async selectOptimalNodes(availableNodes, targetSize, optimizationTarget) { const nodeScores = new Map(); // Score nodes based on optimization target for (const node of availableNodes) { let score = 0; if (optimizationTarget === 'THROUGHPUT') { score = await this.scoreThroughputCapability(node); } else if (optimizationTarget === 'LATENCY') { score = await this.scoreLatencyPerformance(node); } nodeScores.set(node.id, score); } // Select top-scoring nodes const sortedNodes = availableNodes.sort((a, b) => nodeScores.get(b.id) - nodeScores.get(a.id) ); const selectedNodes = new Map(); for (let i = 0; i < Math.min(targetSize, sortedNodes.length); i++) { const node = sortedNodes[i]; selectedNodes.set(node.id, { weight: this.calculatePerformanceWeight(node, nodeScores.get(node.id)), score: nodeScores.get(node.id), role: i === 0 ? 'primary' : 'secondary', optimizationTarget: optimizationTarget }); } return { nodes: selectedNodes, totalWeight: Array.from(selectedNodes.values()) .reduce((sum, node) => sum + node.weight, 0), optimizationTarget: optimizationTarget }; } async scoreThroughputCapability(node) { let score = 0; // CPU capacity score const cpuCapacity = await this.getNodeCPUCapacity(node); score += (cpuCapacity / 100) * 30; // 30% weight for CPU // Network bandwidth score const bandwidth = await this.getNodeBandwidth(node);
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub