Workflow·Cloud & DevOps

Quorum Manager

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

You say
Buy it · $59 Read it before you buy $59 Written by ruvnet · unverified publisher
Context cost
7k tokensestimated from the bundle, loaded when it triggers
Bundle
1 file · 28.1 kBtext throughout, nothing executable
Licence
MITpaid listing
Last change
no release on file
Servers it uses
Noneruns standalone

What it does

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

Installed, it changes the agent in these ways.

What this skill changes about the agent is not written down here yet. The listing was collected from its source, and the description is in its own SKILL.md.

Workflow

Runs a procedure end to end.

cloudagent
Filed under

Cloud & DevOps

The skill itself

This is the whole product. A skill is instructions the model reads, so there is nothing behind the listing you cannot see first — the front matter loads with every session, and the body below it loads when the skill triggers.

SKILL.md28.1 kB · 828 lines
--- name: agent-quorum-manager description: Agent skill for quorum-manager - invoke with $agent-quorum-manager ---
6---
7name: quorum-manager
8type: coordinator
9color: "#673AB7"
10description: Implements dynamic quorum adjustment and intelligent membership management
11capabilities:
12 - dynamic_quorum_calculation
13 - membership_management
14 - network_monitoring
15 - weighted_voting
16 - fault_tolerance_optimization
17priority: high
18hooks:
19 pre: |
20 echo "🎯 Quorum Manager adjusting: $TASK"
21 # Assess current network conditions
22 if [[ "$TASK" == *"quorum"* ]]; then
23 echo "📡 Analyzing network topology and node health"
24 fi
25 post: |
26 echo "⚖️ Quorum adjustment complete"
27 # Validate new quorum configuration
28 echo "✅ Verifying fault tolerance and availability guarantees"
29---
30
31# Quorum Manager
32
33Implements dynamic quorum adjustment and intelligent membership management for distributed consensus protocols.
34
35## Core Responsibilities
36
371. **Dynamic Quorum Calculation**: Adapt quorum requirements based on real-time network conditions
382. **Membership Management**: Handle seamless node addition, removal, and failure scenarios
393. **Network Monitoring**: Assess connectivity, latency, and partition detection
404. **Weighted Voting**: Implement capability-based voting weight assignments
415. **Fault Tolerance Optimization**: Balance availability and consistency guarantees
42
43## Technical Implementation
44
45### Core Quorum Management System
46```javascript
47class QuorumManager {
48 constructor(nodeId, consensusProtocol) {
49 this.nodeId = nodeId;
50 this.protocol = consensusProtocol;
51 this.currentQuorum = new Map(); // nodeId -> QuorumNode
52 this.quorumHistory = [];
53 this.networkMonitor = new NetworkConditionMonitor();
54 this.membershipTracker = new MembershipTracker();
55 this.faultToleranceCalculator = new FaultToleranceCalculator();
56 this.adjustmentStrategies = new Map();
57
58 this.initializeStrategies();
59 }
60
61 // Initialize quorum adjustment strategies
62 initializeStrategies() {
63 this.adjustmentStrategies.set('NETWORK_BASED', new NetworkBasedStrategy());
64 this.adjustmentStrategies.set('PERFORMANCE_BASED', new PerformanceBasedStrategy());
65 this.adjustmentStrategies.set('FAULT_TOLERANCE_BASED', new FaultToleranceStrategy());
66 this.adjustmentStrategies.set('HYBRID', new HybridStrategy());
67 }
68
69 // Calculate optimal quorum size based on current conditions
70 async calculateOptimalQuorum(context = {}) {
71 const networkConditions = await this.networkMonitor.getCurrentConditions();
72 const membershipStatus = await this.membershipTracker.getMembershipStatus();
73 const performanceMetrics = context.performanceMetrics || await this.getPerformanceMetrics();
74
75 const analysisInput = {
76 networkConditions: networkConditions,
77 membershipStatus: membershipStatus,
78 performanceMetrics: performanceMetrics,
79 currentQuorum: this.currentQuorum,
80 protocol: this.protocol,
81 faultToleranceRequirements: context.faultToleranceRequirements || this.getDefaultFaultTolerance()
82 };
83
84 // Apply multiple strategies and select optimal result
85 const strategyResults = new Map();
86
87 for (const [strategyName, strategy] of this.adjustmentStrategies) {
88 try {
89 const result = await strategy.calculateQuorum(analysisInput);
90 strategyResults.set(strategyName, result);
91 } catch (error) {
92 console.warn(Strategy ${strategyName} failed:, error);
93 }
94 }
95
96 // Select best strategy result
97 const optimalResult = this.selectOptimalStrategy(strategyResults, analysisInput);
98
99 return {
100 recommendedQuorum: optimalResult.quorum,
101 strategy: optimalResult.strategy,
102 confidence: optimalResult.confidence,
103 reasoning: optimalResult.reasoning,
104 expectedImpact: optimalResult.expectedImpact
105 };
106 }
107
108 // Apply quorum changes with validation and rollback capability
109 async adjustQuorum(newQuorumConfig, options = {}) {
110 const adjustmentId = adjustment_${Date.now()};
111
112 try {
113 // Validate new quorum configuration
114 await this.validateQuorumConfiguration(newQuorumConfig);
115
116 // Create adjustment plan
117 const adjustmentPlan = await this.createAdjustmentPlan(
118 this.currentQuorum, newQuorumConfig
119 );
120
121 // Execute adjustment with monitoring
122 const adjustmentResult = await this.executeQuorumAdjustment(
123 adjustmentPlan, adjustmentId, options
124 );
125
126 // Verify adjustment success
127 await this.verifyQuorumAdjustment(adjustmentResult);
128
129 // Update current quorum
130 this.currentQuorum = newQuorumConfig.quorum;
131
132 // Record successful adjustment
133 this.recordQuorumChange(adjustmentId, adjustmentResult);
134
135 return {
136 success: true,
137 adjustmentId: adjustmentId,
138 previousQuorum: adjustmentPlan.previousQuorum,
139 newQuorum: this.currentQuorum,
140 impact: adjustmentResult.impact
141 };
142
143 } catch (error) {
144 console.error(Quorum adjustment failed:, error);
145
146 // Attempt rollback
147 await this.rollbackQuorumAdjustment(adjustmentId);
148
149 throw error;
150 }
151 }
152
153 async executeQuorumAdjustment(adjustmentPlan, adjustmentId, options) {
154 const startTime = Date.now();
155
156 // Phase 1: Prepare nodes for quorum change
157 await this.prepareNodesForAdjustment(adjustmentPlan.affectedNodes);
158
159 // Phase 2: Execute membership changes
160 const membershipChanges = await this.executeMembershipChanges(
161 adjustmentPlan.membershipChanges
162 );
163
164 // Phase 3: Update voting weights if needed
165 if (adjustmentPlan.weightChanges.length > 0) {
166 await this.updateVotingWeights(adjustmentPlan.weightChanges);
167 }
168
169 // Phase 4: Reconfigure consensus protocol
170 await this.reconfigureConsensusProtocol(adjustmentPlan.protocolChanges);
171
172 // Phase 5: Verify new quorum is operational
173 const verificationResult = await this.verifyQuorumOperational(adjustmentPlan.newQuorum);
174
175 const endTime = Date.now();
176
177 return {
178 adjustmentId: adjustmentId,
179 duration: endTime - startTime,
180 membershipChanges: membershipChanges,
181 verificationResult: verificationResult,
182 impact: await this.measureAdjustmentImpact(startTime, endTime)
183 };
184 }
185}
186```
187
188### Network-Based Quorum Strategy
189```javascript
190class NetworkBasedStrategy {
191 constructor() {
192 this.networkAnalyzer = new NetworkAnalyzer();
193 this.connectivityMatrix = new ConnectivityMatrix();
194 this.partitionPredictor = new PartitionPredictor();
195 }
196
197 async calculateQuorum(analysisInput) {
198 const { networkConditions, membershipStatus, currentQuorum } = analysisInput;
199
200 // Analyze network topology and connectivity
201 const topologyAnalysis = await this.analyzeNetworkTopology(membershipStatus.activeNodes);
202
203 // Predict potential network partitions
204 const partitionRisk = await this.assessPartitionRisk(networkConditions, topologyAnalysis);
205
206 // Calculate minimum quorum for fault tolerance
207 const minQuorum = this.calculateMinimumQuorum(
208 membershipStatus.activeNodes.length,
209 partitionRisk.maxPartitionSize
210 );
211
212 // Optimize for network conditions
213 const optimizedQuorum = await this.optimizeForNetworkConditions(
214 minQuorum,
215 networkConditions,
216 topologyAnalysis
217 );
218
219 return {
220 quorum: optimizedQuorum,
221 strategy: 'NETWORK_BASED',
222 confidence: this.calculateConfidence(networkConditions, topologyAnalysis),
223 reasoning: this.generateReasoning(optimizedQuorum, partitionRisk, networkConditions),
224 expectedImpact: {
225 availability: this.estimateAvailabilityImpact(optimizedQuorum),
226 performance: this.estimatePerformanceImpact(optimizedQuorum, networkConditions)
227 }
228 };
229 }
230
231 async analyzeNetworkTopology(activeNodes) {
232 const topology = {
233 nodes: activeNodes.length,
234 edges: 0,
235 clusters: [],
236 diameter: 0,
237 connectivity: new Map()
238 };
239
240 // Build connectivity matrix
241 for (const node of activeNodes) {
242 const connections = await this.getNodeConnections(node);
243 topology.connectivity.set(node.id, connections);
244 topology.edges += connections.length;
245 }
246
247 // Identify network clusters
248 topology.clusters = await this.identifyNetworkClusters(topology.connectivity);
249
250 // Calculate network diameter
251 topology.diameter = await this.calculateNetworkDiameter(topology.connectivity);
252
253 return topology;
254 }
255
256 async assessPartitionRisk(networkConditions, topologyAnalysis) {
257 const riskFactors = {
258 connectivityReliability: this.assessConnectivityReliability(networkConditions),
259 geographicDistribution: this.assessGeographicRisk(topologyAnalysis),
260 networkLatency: this.assessLatencyRisk(networkConditions),
261 historicalPartitions: await this.getHistoricalPartitionData()
262 };
263
264 // Calculate overall partition risk
265 const overallRisk = this.calculateOverallPartitionRisk(riskFactors);
266
267 // Estimate maximum partition size
268 const maxPartitionSize = this.estimateMaxPartitionSize(
269 topologyAnalysis,
270 riskFactors
271 );
272
273 return {
274 overallRisk: overallRisk,
275 maxPartitionSize: maxPartitionSize,
276 riskFactors: riskFactors,
277 mitigationStrategies: this.suggestMitigationStrategies(riskFactors)
278 };
279 }
280
281 calculateMinimumQuorum(totalNodes, maxPartitionSize) {
282 // For Byzantine fault tolerance: need > 2/3 of total nodes
283 const byzantineMinimum = Math.floor(2 * totalNodes / 3) + 1;
284
285 // For network partition tolerance: need > 1/2 of largest connected component
286 const partitionMinimum = Math.floor((totalNodes - maxPartitionSize) / 2) + 1;
287
288 // Use the more restrictive requirement
289 return Math.max(byzantineMinimum, partitionMinimum);
290 }
291
292 async optimizeForNetworkConditions(minQuorum, networkConditions, topologyAnalysis) {
293 const optimization = {
294 baseQuorum: minQuorum,
295 nodes: new Map(),
296 totalWeight: 0
297 };
298
299 // Select nodes for quorum based on network position and reliability
300 const nodeScores = await this.scoreNodesForQuorum(networkConditions, topologyAnalysis);
301
302 // Sort nodes by score (higher is better)
303 const sortedNodes = Array.from(nodeScores.entries())
304 .sort(([,scoreA], [,scoreB]) => scoreB - scoreA);
305
306 // Select top nodes for quorum
307 let selectedCount = 0;
308 for (const [nodeId, score] of sortedNodes) {
309 if (selectedCount < minQuorum) {
310 const weight = this.calculateNodeWeight(nodeId, score, networkConditions);
311 optimization.nodes.set(nodeId, {
312 weight: weight,
313 score: score,
314 role: selectedCount === 0 ? 'primary' : 'secondary'
315 });
316 optimization.totalWeight += weight;
317 selectedCount++;
318 }
319 }
320
321 return optimization;
322 }
323
324 async scoreNodesForQuorum(networkConditions, topologyAnalysis) {
325 const scores = new Map();
326
327 for (const [nodeId, connections] of topologyAnalysis.connectivity) {
328 let score = 0;
329
330 // Connectivity score (more connections = higher score)
331 score += (connections.length / topologyAnalysis.nodes) * 30;
332
333 // Network position score (central nodes get higher scores)
334 const centrality = this.calculateCentrality(nodeId, topologyAnalysis);
335 score += centrality * 25;
336
337 // Reliability score based on network conditions
338 const reliability = await this.getNodeReliability(nodeId, networkConditions);
339 score += reliability * 25;
340
341 // Geographic diversity score
342 const geoScore = await this.getGeographicDiversityScore(nodeId, topologyAnalysis);
343 score += geoScore * 20;
344
345 scores.set(nodeId, score);
346 }
347
348 return scores;
349 }
350
351 calculateNodeWeight(nodeId, score, networkConditions) {
352 // Base weight of 1, adjusted by score and conditions
353 let weight = 1.0;
354
355 // Adjust based on normalized score (0-1)
356 const normalizedScore = score / 100;
357 weight *= (0.5 + normalizedScore);
358
359 // Adjust based on network latency
360 const nodeLatency = networkConditions.nodeLatencies.get(nodeId) || 100;
361 const latencyFactor = Math.max(0.1, 1.0 - (nodeLatency / 1000)); // Lower latency = higher weight
362 weight *= latencyFactor;
363
364 // Ensure minimum weight
365 return Math.max(0.1, Math.min(2.0, weight));
366 }
367}
368```
369
370### Performance-Based Quorum Strategy
371```javascript
372class PerformanceBasedStrategy {
373 constructor() {
374 this.performanceAnalyzer = new PerformanceAnalyzer();
375 this.throughputOptimizer = new ThroughputOptimizer();
376 this.latencyOptimizer = new LatencyOptimizer();
377 }
378
379 async calculateQuorum(analysisInput) {
380 const { performanceMetrics, membershipStatus, protocol } = analysisInput;
381
382 // Analyze current performance bottlenecks
383 const bottlenecks = await this.identifyPerformanceBottlenecks(performanceMetrics);
384
385 // Calculate throughput-optimal quorum size
386 const throughputOptimal = await this.calculateThroughputOptimalQuorum(
387 performanceMetrics, membershipStatus.activeNodes
388 );
389
390 // Calculate latency-optimal quorum size
391 const latencyOptimal = await this.calculateLatencyOptimalQuorum(
392 performanceMetrics, membershipStatus.activeNodes
393 );
394
395 // Balance throughput and latency requirements
396 const balancedQuorum = await this.balanceThroughputAndLatency(
397 throughputOptimal, latencyOptimal, performanceMetrics.requirements
398 );
399
400 return {
401 quorum: balancedQuorum,
402 strategy: 'PERFORMANCE_BASED',
403 confidence: this.calculatePerformanceConfidence(performanceMetrics),
404 reasoning: this.generatePerformanceReasoning(
405 balancedQuorum, throughputOptimal, latencyOptimal, bottlenecks
406 ),
407 expectedImpact: {
408 throughputImprovement: this.estimateThroughputImpact(balancedQuorum),
409 latencyImprovement: this.estimateLatencyImpact(balancedQuorum)
410 }
411 };
412 }
413
414 async calculateThroughputOptimalQuorum(performanceMetrics, activeNodes) {
415 const currentThroughput = performanceMetrics.throughput;
416 const targetThroughput = performanceMetrics.requirements.targetThroughput;
417
418 // Analyze relationship between quorum size and throughput
419 const throughputCurve = await this.analyzeThroughputCurve(activeNodes);
420
421 // Find quorum size that maximizes throughput while meeting requirements
422 let optimalSize = Math.ceil(activeNodes.length / 2) + 1; // Minimum viable quorum
423 let maxThroughput = 0;
424
425 for (let size = optimalSize; size <= activeNodes.length; size++) {
426 const projectedThroughput = this.projectThroughput(size, throughputCurve);
427
428 if (projectedThroughput > maxThroughput && projectedThroughput >= targetThroughput) {
429 maxThroughput = projectedThroughput;
430 optimalSize = size;
431 } else if (projectedThroughput < maxThroughput * 0.9) {
432 // Stop if throughput starts decreasing significantly
433 break;
434 }
435 }
436
437 return await this.selectOptimalNodes(activeNodes, optimalSize, 'THROUGHPUT');
438 }
439
440 async calculateLatencyOptimalQuorum(performanceMetrics, activeNodes) {
441 const currentLatency = performanceMetrics.latency;
442 const targetLatency = performanceMetrics.requirements.maxLatency;
443
444 // Analyze relationship between quorum size and latency
445 const latencyCurve = await this.analyzeLatencyCurve(activeNodes);
446
447 // Find minimum quorum size that meets latency requirements
448 const minViableQuorum = Math.ceil(activeNodes.length / 2) + 1;
449
450 for (let size = minViableQuorum; size <= activeNodes.length; size++) {
451 const projectedLatency = this.projectLatency(size, latencyCurve);
452
453 if (projectedLatency <= targetLatency) {
454 return await this.selectOptimalNodes(activeNodes, size, 'LATENCY');
455 }
456 }
457
458 // If no size meets requirements, return minimum viable with warning
459 console.warn('No quorum size meets latency requirements');
460 return await this.selectOptimalNodes(activeNodes, minViableQuorum, 'LATENCY');
461 }
462
463 async selectOptimalNodes(availableNodes, targetSize, optimizationTarget) {
464 const nodeScores = new Map();
465
466 // Score nodes based on optimization target
467 for (const node of availableNodes) {
468 let score = 0;
469
470 if (optimizationTarget === 'THROUGHPUT') {
471 score = await this.scoreThroughputCapability(node);
472 } else if (optimizationTarget === 'LATENCY') {
473 score = await this.scoreLatencyPerformance(node);
474 }
475
476 nodeScores.set(node.id, score);
477 }
478
479 // Select top-scoring nodes
480 const sortedNodes = availableNodes.sort((a, b) =>
481 nodeScores.get(b.id) - nodeScores.get(a.id)
482 );
483
484 const selectedNodes = new Map();
485
486 for (let i = 0; i < Math.min(targetSize, sortedNodes.length); i++) {
487 const node = sortedNodes[i];
488 selectedNodes.set(node.id, {
489 weight: this.calculatePerformanceWeight(node, nodeScores.get(node.id)),
490 score: nodeScores.get(node.id),
491 role: i === 0 ? 'primary' : 'secondary',
492 optimizationTarget: optimizationTarget
493 });
494 }
495
496 return {
497 nodes: selectedNodes,
498 totalWeight: Array.from(selectedNodes.values())
499 .reduce((sum, node) => sum + node.weight, 0),
500 optimizationTarget: optimizationTarget
501 };
502 }
503
504 async scoreThroughputCapability(node) {
505 let score = 0;
506
507 // CPU capacity score
508 const cpuCapacity = await this.getNodeCPUCapacity(node);
509 score += (cpuCapacity / 100) * 30; // 30% weight for CPU
510
511 // Network bandwidth score
512 const bandwidth = await this.getNodeBandwidth(node);
513 score += (bandwidth / 1000) * 25; // 25% weight for bandwidth (Mbps)
514
515 // Memory capacity score
516 const memory = await this.getNodeMemory(node);
517 score += (memory / 8192) * 20; // 20% weight for memory (MB)
518
519 // Historical throughput performance
520 const historicalPerformance = await this.getHistoricalThroughput(node);
521 score += (historicalPerformance / 1000) * 25; // 25% weight for historical performance
522
523 return Math.min(100, score); // Normalize to 0-100
524 }
525
526 async scoreLatencyPerformance(node) {
527 let score = 100; // Start with perfect score, subtract penalties
528
529 // Network latency penalty
530 const avgLatency = await this.getAverageNodeLatency(node);
531 score -= (avgLatency / 10); // Subtract 1 point per 10ms latency
532
533 // CPU load penalty
534 const cpuLoad = await this.getNodeCPULoad(node);
535 score -= (cpuLoad / 2); // Subtract 0.5 points per 1% CPU load
536
537 // Geographic distance penalty (for distributed networks)
538 const geoLatency = await this.getGeographicLatency(node);
539 score -= (geoLatency / 20); // Subtract 1 point per 20ms geo latency
540
541 // Consistency penalty (nodes with inconsistent performance)
542 const consistencyScore = await this.getPerformanceConsistency(node);
543 score *= consistencyScore; // Multiply by consistency factor (0-1)
544
545 return Math.max(0, score);
546 }
547}
548```
549
550### Fault Tolerance Strategy
551```javascript
552class FaultToleranceStrategy {
553 constructor() {
554 this.faultAnalyzer = new FaultAnalyzer();
555 this.reliabilityCalculator = new ReliabilityCalculator();
556 this.redundancyOptimizer = new RedundancyOptimizer();
557 }
558
559 async calculateQuorum(analysisInput) {
560 const { membershipStatus, faultToleranceRequirements, networkConditions } = analysisInput;
561
562 // Analyze fault scenarios
563 const faultScenarios = await this.analyzeFaultScenarios(
564 membershipStatus.activeNodes, networkConditions
565 );
566
567 // Calculate minimum quorum for fault tolerance requirements
568 const minQuorum = this.calculateFaultTolerantQuorum(
569 faultScenarios, faultToleranceRequirements
570 );
571
572 // Optimize node selection for maximum fault tolerance
573 const faultTolerantQuorum = await this.optimizeForFaultTolerance(
574 membershipStatus.activeNodes, minQuorum, faultScenarios
575 );
576
577 return {
578 quorum: faultTolerantQuorum,
579 strategy: 'FAULT_TOLERANCE_BASED',
580 confidence: this.calculateFaultConfidence(faultScenarios),
581 reasoning: this.generateFaultToleranceReasoning(
582 faultTolerantQuorum, faultScenarios, faultToleranceRequirements
583 ),
584 expectedImpact: {
585 availability: this.estimateAvailabilityImprovement(faultTolerantQuorum),
586 resilience: this.estimateResilienceImprovement(faultTolerantQuorum)
587 }
588 };
589 }
590
591 async analyzeFaultScenarios(activeNodes, networkConditions) {
592 const scenarios = [];
593
594 // Single node failure scenarios
595 for (const node of activeNodes) {
596 const scenario = await this.analyzeSingleNodeFailure(node, activeNodes, networkConditions);
597 scenarios.push(scenario);
598 }
599
600 // Multiple node failure scenarios
601 const multiFailureScenarios = await this.analyzeMultipleNodeFailures(
602 activeNodes, networkConditions
603 );
604 scenarios.push(...multiFailureScenarios);
605
606 // Network partition scenarios
607 const partitionScenarios = await this.analyzeNetworkPartitionScenarios(
608 activeNodes, networkConditions
609 );
610 scenarios.push(...partitionScenarios);
611
612 // Correlated failure scenarios
613 const correlatedFailureScenarios = await this.analyzeCorrelatedFailures(
614 activeNodes, networkConditions
615 );
616 scenarios.push(...correlatedFailureScenarios);
617
618 return this.prioritizeScenariosByLikelihood(scenarios);
619 }
620
621 calculateFaultTolerantQuorum(faultScenarios, requirements) {
622 let maxRequiredQuorum = 0;
623
624 for (const scenario of faultScenarios) {
625 if (scenario.likelihood >= requirements.minLikelihoodToConsider) {
626 const requiredQuorum = this.calculateQuorumForScenario(scenario, requirements);
627 maxRequiredQuorum = Math.max(maxRequiredQuorum, requiredQuorum);
628 }
629 }
630
631 return maxRequiredQuorum;
632 }
633
634 calculateQuorumForScenario(scenario, requirements) {
635 const totalNodes = scenario.totalNodes;
636 const failedNodes = scenario.failedNodes;
637 const availableNodes = totalNodes - failedNodes;
638
639 // For Byzantine fault tolerance
640 if (requirements.byzantineFaultTolerance) {
641 const maxByzantineNodes = Math.floor((totalNodes - 1) / 3);
642 return Math.floor(2 * totalNodes / 3) + 1;
643 }
644
645 // For crash fault tolerance
646 return Math.floor(availableNodes / 2) + 1;
647 }
648
649 async optimizeForFaultTolerance(activeNodes, minQuorum, faultScenarios) {
650 const optimizedQuorum = {
651 nodes: new Map(),
652 totalWeight: 0,
653 faultTolerance: {
654 singleNodeFailures: 0,
655 multipleNodeFailures: 0,
656 networkPartitions: 0
657 }
658 };
659
660 // Score nodes based on fault tolerance contribution
661 const nodeScores = await this.scoreFaultToleranceContribution(
662 activeNodes, faultScenarios
663 );
664
665 // Select nodes to maximize fault tolerance coverage
666 const selectedNodes = this.selectFaultTolerantNodes(
667 activeNodes, minQuorum, nodeScores, faultScenarios
668 );
669
670 for (const [nodeId, nodeData] of selectedNodes) {
671 optimizedQuorum.nodes.set(nodeId, {
672 weight: nodeData.weight,
673 score: nodeData.score,
674 role: nodeData.role,
675 faultToleranceContribution: nodeData.faultToleranceContribution
676 });
677 optimizedQuorum.totalWeight += nodeData.weight;
678 }
679
680 // Calculate fault tolerance metrics for selected quorum
681 optimizedQuorum.faultTolerance = await this.calculateFaultToleranceMetrics(
682 selectedNodes, faultScenarios
683 );
684
685 return optimizedQuorum;
686 }
687
688 async scoreFaultToleranceContribution(activeNodes, faultScenarios) {
689 const scores = new Map();
690
691 for (const node of activeNodes) {
692 let score = 0;
693
694 // Independence score (nodes in different failure domains get higher scores)
695 const independenceScore = await this.calculateIndependenceScore(node, activeNodes);
696 score += independenceScore * 40;
697
698 // Reliability score (historical uptime and performance)
699 const reliabilityScore = await this.calculateReliabilityScore(node);
700 score += reliabilityScore * 30;
701
702 // Geographic diversity score
703 const diversityScore = await this.calculateDiversityScore(node, activeNodes);
704 score += diversityScore * 20;
705
706 // Recovery capability score
707 const recoveryScore = await this.calculateRecoveryScore(node);
708 score += recoveryScore * 10;
709
710 scores.set(node.id, score);
711 }
712
713 return scores;
714 }
715
716 selectFaultTolerantNodes(activeNodes, minQuorum, nodeScores, faultScenarios) {
717 const selectedNodes = new Map();
718 const remainingNodes = [...activeNodes];
719
720 // Greedy selection to maximize fault tolerance coverage
721 while (selectedNodes.size < minQuorum && remainingNodes.length > 0) {
722 let bestNode = null;
723 let bestScore = -1;
724 let bestIndex = -1;
725
726 for (let i = 0; i < remainingNodes.length; i++) {
727 const node = remainingNodes[i];
728 const additionalCoverage = this.calculateAdditionalFaultCoverage(
729 node, selectedNodes, faultScenarios
730 );
731
732 const combinedScore = nodeScores.get(node.id) + (additionalCoverage * 50);
733
734 if (combinedScore > bestScore) {
735 bestScore = combinedScore;
736 bestNode = node;
737 bestIndex = i;
738 }
739 }
740
741 if (bestNode) {
742 selectedNodes.set(bestNode.id, {
743 weight: this.calculateFaultToleranceWeight(bestNode, nodeScores.get(bestNode.id)),
744 score: nodeScores.get(bestNode.id),
745 role: selectedNodes.size === 0 ? 'primary' : 'secondary',
746 faultToleranceContribution: this.calculateFaultToleranceContribution(bestNode)
747 });
748
749 remainingNodes.splice(bestIndex, 1);
750 } else {
751 break; // No more beneficial nodes
752 }
753 }
754
755 return selectedNodes;
756 }
757}
758```
759
760## MCP Integration Hooks
761
762### Quorum State Management
763```javascript
764// Store quorum configuration and history
765await this.mcpTools.memory_usage({
766 action: 'store',
767 key: quorum_config_${this.nodeId},
768 value: JSON.stringify({
769 currentQuorum: Array.from(this.currentQuorum.entries()),
770 strategy: this.activeStrategy,
771 networkConditions: this.lastNetworkAnalysis,
772 adjustmentHistory: this.quorumHistory.slice(-10)
773 }),
774 namespace: 'quorum_management',
775 ttl: 3600000 // 1 hour
776});
777
778// Coordinate with swarm for membership changes
779const swarmStatus = await this.mcpTools.swarm_status({
780 swarmId: this.swarmId
781});
782
783await this.mcpTools.coordination_sync({
784 swarmId: this.swarmId
785});
786```
787
788### Performance Monitoring Integration
789```javascript
790// Track quorum adjustment performance
791await this.mcpTools.metrics_collect({
792 components: [
793 'quorum_adjustment_latency',
794 'consensus_availability',
795 'fault_tolerance_coverage',
796 'network_partition_recovery_time'
797 ]
798});
799
800// Neural learning for quorum optimization
801await this.mcpTools.neural_patterns({
802 action: 'learn',
803 operation: 'quorum_optimization',
804 outcome: JSON.stringify({
805 adjustmentType: adjustment.strategy,
806 performanceImpact: measurementResults,
807 networkConditions: currentNetworkState,
808 faultToleranceImprovement: faultToleranceMetrics
809 })
810});
811```
812
813### Task Orchestration for Quorum Changes
814```javascript
815// Orchestrate complex quorum adjustments
816await this.mcpTools.task_orchestrate({
817 task: 'quorum_adjustment',
818 strategy: 'sequential',
819 priority: 'high',
820 dependencies: [
821 'network_analysis',
822 'membership_validation',
823 'performance_assessment'
824 ]
825});
826```
827
828This Quorum Manager provides intelligent, adaptive quorum management that optimizes for network conditions, performance requirements, and fault tolerance needs while maintaining the safety and liveness properties of distributed consensus protocols.
In the file
SKILL.md2,465 words
Files1
LicenceMIT
Why you can read it

Nothing in a skill executes. The client loads the text and the model follows it, so a skill can be audited the way a runbook is — by reading it.

What it costs in context

Skills are not billed by the call. They are paid for in context: every token the instructions occupy is a token your code, your diff and your conversation cannot use. Here is what this one takes and when it takes it.

≈30
always loaded
The name and description, so the model knows the skill exists and when to reach for it.
6,995
on trigger
The instruction body, read only when the skill fires.
3.5%
of a 200k window
Ten skills this size would take about 35% of the window before you open a file.
050k100k150k200k context window

7k tokens, estimated from the bundle at four bytes to the token, held for the rest of the session once it triggers. Heavy. Teams tend to install this one per project rather than globally, and load it only when the job comes up.

Servers bill, skills cost

A server charges by the month. A skill charges once per session, in context, and then keeps charging it for as long as the session lives.

Before and after

The same question, put to the same model twice: once as it comes, and once with these instructions loaded.

No worked example has been published for this skill yet.

Adoption
Installsnone yet
Ratingno reviews yet

The procedure it runs

The procedure has not been published here. It is in the skill’s own SKILL.md, which its author has not sent to the marketplace yet.

Prose, not code

These steps are written for a model to follow, not executed by a runtime. It can still be told to skip one, and it will say so when it does.

Servers it uses

None. This skill calls no MCP servers at all.

Everything it needs is in the instructions, so it works in a project with nothing connected — the model reads the file and changes how it works with what it can already reach.

It writes no files and reaches no network. All it changes is how the model reasons and writes.

What it asks for
Writes filesno
Network accessno

Read from the allowed-tools line of this skill’s own SKILL.md. A skill grants no permissions of its own — it can only ask for tools your client already has.

What it will not do

Every skill is narrow, and the useful ones say where they stop. These are the jobs this one is the wrong tool for.

What this skill is not for has not been published here. Nothing is implied by that: it is a section the author has not filled in.

What is in the bundle

1 file, 28.1 kB on disk. A bundle is text throughout: the instructions the model reads, plus the templates it fills in.

  • SKILL.md28.1 kB
What is not in it

No dependencies and nothing executable: a skill is text the agent reads, so the bundle is 1 file you can review in full before installing. The MIT licence covers the templates and examples as well as the instructions.

Install

Installing copies the bundle into your project. Nothing runs at install time — the files sit on disk until the model reads them.

$59 once
Quorum Manager · MIT · ruvnet
one-time
Price$59 once
LicenceMIT — the author’s, unchanged by this purchase
Paid throughStripe, once, on the card you add at the checkout
Keeps workingfor good — the files are yours once they are on disk
Updatesevery update its author ships, delivered through this account

You can read the whole bundle before paying — the SKILL.md above is the product, not a preview of it. What the money buys is the delivery: the folder packaged and handed to your machine by key, every update its author ships, and our support if it does not do what this listing says. The terms of use are MIT, set by the author and unchanged by buying it here.

Payment runs through Stripe, on a page like this one rather than a redirect. Once there is an account it joins the same mcprush invoice as everything else you run, so there is never a second card to enter.

Which clients pick it up on their own

A skill is a folder of text. A client with a skills folder reads it without being told; everywhere else the same text works, it is just handed to the model rather than found.

Claude Code.claude/skills/
Claude Desktop
ChatGPT
Cursor.cursor/skills/
VS Code.github/skills/
Codex CLI.agents/skills/
Gemini CLI.gemini/skills/
Grok.grok/skills/
Zed.agents/skills/
Windsurf.windsurf/skills/
Agent SDK.claude/skills/
HTTP / API
This release
Versionnot versioned
Publishedno release date on file
Price$59
Referenceruvnet/quorum-manager

Versions

Its author publishes no version number, so there is nothing here to pin to: what you install is the folder as it stands today. Instructions change more often than APIs do — a skill can be rewritten entirely without anything it depends on moving.

v
  • No earlier releases have been published to the marketplace.
Pinning

Nothing to pin to: this skill carries no version number of its own. What you install is what the folder holds on the day you install it.

Reviews

no reviews yet · no installs yet

Nobody has reviewed this skill yet. The rating is the mean of the reviews written here, so there is none until somebody writes the first.

Who can post

Only accounts that have had the skill installed for fourteen days, so a review is written after living with it rather than after reading it. Publishers may reply once.

Publisher
Servers0