feat: add comprehensive validation framework

Add validators package with 6 specialized validators:
- base.py: Abstract base validator with common patterns
- context_contract.py: PM mode context validation
- dep_sanity.py: Dependency consistency checks
- runtime_policy.py: Runtime policy enforcement
- security_roughcheck.py: Security vulnerability scanning
- test_runner.py: Automated test execution validation

Supports validation gates for quality assurance and risk mitigation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
kazuki
2025-10-20 03:52:40 +09:00
parent c5690e4a71
commit ca29e595fd
7 changed files with 868 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
"""Base validator classes and utilities"""
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List, Optional, Dict, Any
from enum import Enum
class ValidationStatus(Enum):
"""Validation result status"""
PASSED = "passed"
FAILED = "failed"
WARNING = "warning"
SKIPPED = "skipped"
@dataclass
class ValidationResult:
"""Result of a validation check"""
status: ValidationStatus
validator_name: str
message: str
details: Optional[Dict[str, Any]] = None
suggestions: Optional[List[str]] = None
@property
def passed(self) -> bool:
"""Check if validation passed"""
return self.status == ValidationStatus.PASSED
@property
def failed(self) -> bool:
"""Check if validation failed"""
return self.status == ValidationStatus.FAILED
def __str__(self) -> str:
"""String representation"""
symbol = {
ValidationStatus.PASSED: "",
ValidationStatus.FAILED: "",
ValidationStatus.WARNING: "⚠️",
ValidationStatus.SKIPPED: "⏭️"
}[self.status]
lines = [f"{symbol} {self.validator_name}: {self.message}"]
if self.details:
lines.append(f" Details: {self.details}")
if self.suggestions:
lines.append(" Suggestions:")
for suggestion in self.suggestions:
lines.append(f" - {suggestion}")
return "\n".join(lines)
class Validator(ABC):
"""Base validator class"""
def __init__(self, name: str):
self.name = name
@abstractmethod
def validate(self, context: Dict[str, Any]) -> ValidationResult:
"""
Validate against context.
Args:
context: Validation context (changes, contract, etc.)
Returns:
ValidationResult
"""
pass
def _pass(self, message: str, **kwargs) -> ValidationResult:
"""Create a PASSED result"""
return ValidationResult(
status=ValidationStatus.PASSED,
validator_name=self.name,
message=message,
**kwargs
)
def _fail(self, message: str, **kwargs) -> ValidationResult:
"""Create a FAILED result"""
return ValidationResult(
status=ValidationStatus.FAILED,
validator_name=self.name,
message=message,
**kwargs
)
def _warning(self, message: str, **kwargs) -> ValidationResult:
"""Create a WARNING result"""
return ValidationResult(
status=ValidationStatus.WARNING,
validator_name=self.name,
message=message,
**kwargs
)
def _skip(self, message: str, **kwargs) -> ValidationResult:
"""Create a SKIPPED result"""
return ValidationResult(
status=ValidationStatus.SKIPPED,
validator_name=self.name,
message=message,
**kwargs
)
class ValidatorChain:
"""Chain of validators that runs in sequence"""
def __init__(self, validators: List[Validator]):
self.validators = validators
def validate(self, context: Dict[str, Any]) -> List[ValidationResult]:
"""Run all validators"""
results = []
for validator in self.validators:
result = validator.validate(context)
results.append(result)
return results
def validate_with_early_stop(self, context: Dict[str, Any]) -> List[ValidationResult]:
"""Run validators until first failure"""
results = []
for validator in self.validators:
result = validator.validate(context)
results.append(result)
# Stop on first failure
if result.failed:
break
return results
@property
def all_passed(self) -> bool:
"""Check if all validations passed"""
return all(not r.failed for r in self.validate({}))