Initial commit: Claude Code Hooks with Diátaxis documentation
✨ Features: - 🧠 Shadow learner that builds intelligence from command patterns - 🛡️ Smart command validation with safety checks - 💾 Automatic context monitoring and backup system - 🔄 Session continuity across Claude restarts 📚 Documentation: - Complete Diátaxis-organized documentation - Learning-oriented tutorial for getting started - Task-oriented how-to guides for specific problems - Information-oriented reference for quick lookup - Understanding-oriented explanations of architecture 🚀 Installation: - One-command installation script - Bootstrap prompt for installation via Claude - Cross-platform compatibility - Comprehensive testing suite 🎯 Ready for real-world use and community feedback! 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
162ca67098
34 changed files with 5904 additions and 0 deletions
198
lib/models.py
Normal file
198
lib/models.py
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Data models for Claude Code Hooks system"""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional, Any
|
||||
import json
|
||||
|
||||
|
||||
@dataclass
|
||||
class ToolExecution:
|
||||
"""Single tool execution record"""
|
||||
timestamp: datetime
|
||||
tool: str
|
||||
parameters: Dict[str, Any]
|
||||
success: bool
|
||||
error_message: Optional[str] = None
|
||||
execution_time: float = 0.0
|
||||
context: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"timestamp": self.timestamp.isoformat(),
|
||||
"tool": self.tool,
|
||||
"parameters": self.parameters,
|
||||
"success": self.success,
|
||||
"error_message": self.error_message,
|
||||
"execution_time": self.execution_time,
|
||||
"context": self.context
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> 'ToolExecution':
|
||||
return cls(
|
||||
timestamp=datetime.fromisoformat(data["timestamp"]),
|
||||
tool=data["tool"],
|
||||
parameters=data["parameters"],
|
||||
success=data["success"],
|
||||
error_message=data.get("error_message"),
|
||||
execution_time=data.get("execution_time", 0.0),
|
||||
context=data.get("context", {})
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Pattern:
|
||||
"""Learned pattern with confidence scoring"""
|
||||
pattern_id: str
|
||||
pattern_type: str # "command_failure", "tool_sequence", "context_error"
|
||||
trigger: Dict[str, Any] # What triggers this pattern
|
||||
prediction: Dict[str, Any] # What we predict will happen
|
||||
confidence: float # 0.0 to 1.0
|
||||
evidence_count: int # How many times we've seen this
|
||||
last_seen: datetime
|
||||
success_rate: float = 0.0
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"pattern_id": self.pattern_id,
|
||||
"pattern_type": self.pattern_type,
|
||||
"trigger": self.trigger,
|
||||
"prediction": self.prediction,
|
||||
"confidence": self.confidence,
|
||||
"evidence_count": self.evidence_count,
|
||||
"last_seen": self.last_seen.isoformat(),
|
||||
"success_rate": self.success_rate
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> 'Pattern':
|
||||
return cls(
|
||||
pattern_id=data["pattern_id"],
|
||||
pattern_type=data["pattern_type"],
|
||||
trigger=data["trigger"],
|
||||
prediction=data["prediction"],
|
||||
confidence=data["confidence"],
|
||||
evidence_count=data["evidence_count"],
|
||||
last_seen=datetime.fromisoformat(data["last_seen"]),
|
||||
success_rate=data.get("success_rate", 0.0)
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class HookResult:
|
||||
"""Result of hook execution"""
|
||||
allow: bool
|
||||
message: str = ""
|
||||
warning: bool = False
|
||||
metadata: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
@classmethod
|
||||
def success(cls, message: str = "Operation allowed") -> 'HookResult':
|
||||
return cls(allow=True, message=message)
|
||||
|
||||
@classmethod
|
||||
def blocked(cls, reason: str) -> 'HookResult':
|
||||
return cls(allow=False, message=reason)
|
||||
|
||||
@classmethod
|
||||
def allow_with_warning(cls, warning: str) -> 'HookResult':
|
||||
return cls(allow=True, message=warning, warning=True)
|
||||
|
||||
def to_claude_response(self) -> Dict[str, Any]:
|
||||
"""Convert to Claude Code hook response format"""
|
||||
response = {
|
||||
"allow": self.allow,
|
||||
"message": self.message
|
||||
}
|
||||
if self.metadata:
|
||||
response.update(self.metadata)
|
||||
return response
|
||||
|
||||
|
||||
@dataclass
|
||||
class ValidationResult:
|
||||
"""Result of validation operations"""
|
||||
allowed: bool
|
||||
reason: str = ""
|
||||
severity: str = "info" # info, warning, medium, high, critical
|
||||
suggestions: List[str] = field(default_factory=list)
|
||||
|
||||
@property
|
||||
def is_critical(self) -> bool:
|
||||
return self.severity == "critical"
|
||||
|
||||
@property
|
||||
def is_blocking(self) -> bool:
|
||||
return not self.allowed
|
||||
|
||||
|
||||
@dataclass
|
||||
class BackupDecision:
|
||||
"""Decision about whether to trigger backup"""
|
||||
should_backup: bool
|
||||
reason: str
|
||||
urgency: str = "medium" # low, medium, high
|
||||
metadata: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass
|
||||
class BackupResult:
|
||||
"""Result of backup operation"""
|
||||
success: bool
|
||||
backup_id: str = ""
|
||||
backup_path: str = ""
|
||||
error: str = ""
|
||||
git_success: bool = False
|
||||
fallback_performed: bool = False
|
||||
components: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass
|
||||
class GitBackupResult:
|
||||
"""Result of git backup operation"""
|
||||
success: bool
|
||||
commit_id: str = ""
|
||||
message: str = ""
|
||||
error: str = ""
|
||||
|
||||
|
||||
class PatternDatabase:
|
||||
"""Fast lookup database for learned patterns"""
|
||||
|
||||
def __init__(self):
|
||||
self.command_patterns: Dict[str, Pattern] = {}
|
||||
self.sequence_patterns: List[Pattern] = []
|
||||
self.context_patterns: Dict[str, Pattern] = {}
|
||||
self.execution_history: List[ToolExecution] = []
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"command_patterns": {k: v.to_dict() for k, v in self.command_patterns.items()},
|
||||
"sequence_patterns": [p.to_dict() for p in self.sequence_patterns],
|
||||
"context_patterns": {k: v.to_dict() for k, v in self.context_patterns.items()},
|
||||
"execution_history": [e.to_dict() for e in self.execution_history[-100:]] # Keep last 100
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> 'PatternDatabase':
|
||||
db = cls()
|
||||
|
||||
# Load command patterns
|
||||
for k, v in data.get("command_patterns", {}).items():
|
||||
db.command_patterns[k] = Pattern.from_dict(v)
|
||||
|
||||
# Load sequence patterns
|
||||
for p in data.get("sequence_patterns", []):
|
||||
db.sequence_patterns.append(Pattern.from_dict(p))
|
||||
|
||||
# Load context patterns
|
||||
for k, v in data.get("context_patterns", {}).items():
|
||||
db.context_patterns[k] = Pattern.from_dict(v)
|
||||
|
||||
# Load execution history
|
||||
for e in data.get("execution_history", []):
|
||||
db.execution_history.append(ToolExecution.from_dict(e))
|
||||
|
||||
return db
|
||||
Loading…
Add table
Add a link
Reference in a new issue