Initial commit
This commit is contained in:
245
commands/validation-orchestrator/.scripts/validation-dispatcher.py
Executable file
245
commands/validation-orchestrator/.scripts/validation-dispatcher.py
Executable file
@@ -0,0 +1,245 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
============================================================================
|
||||
Validation Dispatcher Script
|
||||
============================================================================
|
||||
Purpose: Route validation requests and aggregate results from multiple layers
|
||||
Version: 1.0.0
|
||||
Usage: ./validation-dispatcher.py --mode=<mode> [options]
|
||||
Returns: 0=success, 1=error
|
||||
============================================================================
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ValidationMode(Enum):
|
||||
"""Validation dispatch modes"""
|
||||
ROUTE = "route" # Route to appropriate validator
|
||||
AGGREGATE = "aggregate" # Aggregate results from multiple validators
|
||||
|
||||
|
||||
class ValidationResult:
|
||||
"""Validation result structure"""
|
||||
|
||||
def __init__(self):
|
||||
self.layers: Dict[str, Dict[str, Any]] = {}
|
||||
self.overall_score = 0
|
||||
self.critical_issues = 0
|
||||
self.warnings = 0
|
||||
self.recommendations = 0
|
||||
|
||||
def add_layer(self, name: str, result: Dict[str, Any]):
|
||||
"""Add a validation layer result"""
|
||||
self.layers[name] = result
|
||||
|
||||
# Aggregate counts
|
||||
if 'critical_issues' in result:
|
||||
self.critical_issues += result['critical_issues']
|
||||
if 'warnings' in result:
|
||||
self.warnings += result['warnings']
|
||||
if 'recommendations' in result:
|
||||
self.recommendations += result['recommendations']
|
||||
|
||||
def calculate_overall_score(self):
|
||||
"""Calculate overall quality score from all layers"""
|
||||
if not self.layers:
|
||||
return 0
|
||||
|
||||
total_score = 0
|
||||
layer_count = 0
|
||||
|
||||
for layer, result in self.layers.items():
|
||||
if 'score' in result:
|
||||
total_score += result['score']
|
||||
layer_count += 1
|
||||
|
||||
if layer_count > 0:
|
||||
self.overall_score = total_score // layer_count
|
||||
else:
|
||||
# Fallback calculation based on issues
|
||||
self.overall_score = max(0, 100 - (self.critical_issues * 20) -
|
||||
(self.warnings * 10) - (self.recommendations * 5))
|
||||
|
||||
return self.overall_score
|
||||
|
||||
def get_rating(self) -> str:
|
||||
"""Get quality rating based on score"""
|
||||
score = self.overall_score
|
||||
if score >= 90:
|
||||
return "Excellent"
|
||||
elif score >= 75:
|
||||
return "Good"
|
||||
elif score >= 60:
|
||||
return "Fair"
|
||||
elif score >= 40:
|
||||
return "Needs Improvement"
|
||||
else:
|
||||
return "Poor"
|
||||
|
||||
def get_stars(self) -> str:
|
||||
"""Get star rating"""
|
||||
score = self.overall_score
|
||||
if score >= 90:
|
||||
return "⭐⭐⭐⭐⭐"
|
||||
elif score >= 75:
|
||||
return "⭐⭐⭐⭐"
|
||||
elif score >= 60:
|
||||
return "⭐⭐⭐"
|
||||
elif score >= 40:
|
||||
return "⭐⭐"
|
||||
else:
|
||||
return "⭐"
|
||||
|
||||
def is_publication_ready(self) -> str:
|
||||
"""Determine publication readiness"""
|
||||
if self.critical_issues > 0:
|
||||
return "Not Ready"
|
||||
elif self.overall_score >= 75:
|
||||
return "Ready"
|
||||
else:
|
||||
return "Needs Work"
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert to dictionary"""
|
||||
return {
|
||||
"overall_score": self.overall_score,
|
||||
"rating": self.get_rating(),
|
||||
"stars": self.get_stars(),
|
||||
"publication_ready": self.is_publication_ready(),
|
||||
"critical_issues": self.critical_issues,
|
||||
"warnings": self.warnings,
|
||||
"recommendations": self.recommendations,
|
||||
"layers": self.layers
|
||||
}
|
||||
|
||||
|
||||
class ValidationDispatcher:
|
||||
"""Dispatcher for validation routing and aggregation"""
|
||||
|
||||
def __init__(self, mode: ValidationMode):
|
||||
self.mode = mode
|
||||
self.result = ValidationResult()
|
||||
|
||||
def route(self, target_type: str, target_path: str, level: str) -> Dict[str, Any]:
|
||||
"""Route to appropriate validator based on target type"""
|
||||
routing = {
|
||||
"marketplace": {
|
||||
"quick": "/validate-quick",
|
||||
"comprehensive": "/validate-marketplace"
|
||||
},
|
||||
"plugin": {
|
||||
"quick": "/validate-quick",
|
||||
"comprehensive": "/validate-plugin"
|
||||
}
|
||||
}
|
||||
|
||||
if target_type not in routing:
|
||||
return {
|
||||
"error": f"Unknown target type: {target_type}",
|
||||
"supported": list(routing.keys())
|
||||
}
|
||||
|
||||
command = routing[target_type].get(level, routing[target_type]["comprehensive"])
|
||||
|
||||
return {
|
||||
"target_type": target_type,
|
||||
"target_path": target_path,
|
||||
"validation_level": level,
|
||||
"command": command,
|
||||
"invocation": f"{command} {target_path}"
|
||||
}
|
||||
|
||||
def aggregate(self, layer_results: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||
"""Aggregate results from multiple validation layers"""
|
||||
for layer_data in layer_results:
|
||||
layer_name = layer_data.get('layer', 'unknown')
|
||||
self.result.add_layer(layer_name, layer_data)
|
||||
|
||||
self.result.calculate_overall_score()
|
||||
|
||||
return self.result.to_dict()
|
||||
|
||||
def format_output(self, data: Dict[str, Any]) -> str:
|
||||
"""Format output for console display"""
|
||||
if self.mode == ValidationMode.ROUTE:
|
||||
return json.dumps(data, indent=2)
|
||||
elif self.mode == ValidationMode.AGGREGATE:
|
||||
# Pretty print aggregated results
|
||||
lines = []
|
||||
lines.append("=" * 60)
|
||||
lines.append("AGGREGATED VALIDATION RESULTS")
|
||||
lines.append("=" * 60)
|
||||
lines.append(f"Overall Score: {data['overall_score']}/100 {data['stars']}")
|
||||
lines.append(f"Rating: {data['rating']}")
|
||||
lines.append(f"Publication Ready: {data['publication_ready']}")
|
||||
lines.append("")
|
||||
lines.append(f"Critical Issues: {data['critical_issues']}")
|
||||
lines.append(f"Warnings: {data['warnings']}")
|
||||
lines.append(f"Recommendations: {data['recommendations']}")
|
||||
lines.append("")
|
||||
lines.append("Layer Results:")
|
||||
for layer, result in data['layers'].items():
|
||||
status = result.get('status', 'unknown')
|
||||
lines.append(f" - {layer}: {status}")
|
||||
lines.append("=" * 60)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main execution"""
|
||||
parser = argparse.ArgumentParser(description="Validation dispatcher")
|
||||
parser.add_argument("--mode", required=True, choices=["route", "aggregate"],
|
||||
help="Dispatch mode")
|
||||
parser.add_argument("--target-type", help="Target type for routing")
|
||||
parser.add_argument("--target-path", default=".", help="Target path")
|
||||
parser.add_argument("--level", default="comprehensive",
|
||||
choices=["quick", "comprehensive"],
|
||||
help="Validation level")
|
||||
parser.add_argument("--results", help="JSON file with layer results for aggregation")
|
||||
parser.add_argument("--json", action="store_true", help="Output JSON format")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
mode = ValidationMode(args.mode)
|
||||
dispatcher = ValidationDispatcher(mode)
|
||||
|
||||
try:
|
||||
if mode == ValidationMode.ROUTE:
|
||||
if not args.target_type:
|
||||
print("Error: --target-type required for route mode", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
result = dispatcher.route(args.target_type, args.target_path, args.level)
|
||||
|
||||
elif mode == ValidationMode.AGGREGATE:
|
||||
if not args.results:
|
||||
print("Error: --results required for aggregate mode", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
with open(args.results, 'r') as f:
|
||||
layer_results = json.load(f)
|
||||
|
||||
result = dispatcher.aggregate(layer_results)
|
||||
|
||||
# Output results
|
||||
if args.json:
|
||||
print(json.dumps(result, indent=2))
|
||||
else:
|
||||
print(dispatcher.format_output(result))
|
||||
|
||||
return 0
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user