Files
timmy-config/wizards/allegro/gofai/schema.py
2026-03-31 20:02:01 +00:00

291 lines
9.4 KiB
Python

#!/usr/bin/env python3
"""
GOFAI Schema Definition for Hermes Fleet
Knowledge representation layer for wizard lineage, tasks, and relationships
"""
from dataclasses import dataclass, field
from typing import List, Dict, Optional, Set
from datetime import datetime
from enum import Enum
class EntityType(Enum):
WIZARD = "wizard"
TASK = "task"
ARTIFACT = "artifact"
RELATIONSHIP = "relationship"
PRINCIPLE = "principle"
GOAL = "goal"
class TaskStatus(Enum):
PENDING = "pending"
IN_PROGRESS = "in_progress"
COMPLETE = "complete"
BLOCKED = "blocked"
@dataclass
class Entity:
"""Base entity in the knowledge graph"""
id: str
type: EntityType
name: str
properties: Dict = field(default_factory=dict)
created_at: datetime = field(default_factory=datetime.now)
def to_dict(self) -> Dict:
return {
'id': self.id,
'type': self.type.value,
'name': self.name,
'properties': self.properties,
'created_at': self.created_at.isoformat()
}
@dataclass
class Wizard(Entity):
"""A wizard in the fleet"""
father: Optional[str] = None
grandfather: Optional[str] = None
sovereign: Optional[str] = None
hermes_home: str = ""
api_port: int = 0
model: str = ""
role: str = ""
capabilities: Set[str] = field(default_factory=set)
def __post_init__(self):
self.type = EntityType.WIZARD
self.capabilities = set(self.capabilities) if isinstance(self.capabilities, (list, set)) else set()
def get_lineage(self) -> List[str]:
"""Return ancestry chain"""
lineage = [self.name]
if self.father:
lineage.append(self.father)
if self.grandfather:
lineage.append(self.grandfather)
return lineage
def can_perform(self, capability: str) -> bool:
"""Check if wizard has capability"""
return capability in self.capabilities
@dataclass
class Task(Entity):
"""A task in the work queue"""
assignee: Optional[str] = None
priority: str = "P2"
status: TaskStatus = TaskStatus.PENDING
deliverable: str = ""
estimated_time: int = 0 # minutes
dependencies: List[str] = field(default_factory=list)
def __post_init__(self):
self.type = EntityType.TASK
if isinstance(self.status, str):
self.status = TaskStatus(self.status)
def is_blocked(self, completed_tasks: Set[str]) -> bool:
"""Check if task is blocked by incomplete dependencies"""
return not all(dep in completed_tasks for dep in self.dependencies)
def to_work_item(self) -> Dict:
"""Convert to work queue format"""
return {
'task_id': self.id,
'name': self.name,
'priority': self.priority,
'status': self.status.value,
'assignee': self.assignee,
'deliverable': self.deliverable
}
@dataclass
class Relationship:
"""Relationship between entities"""
source: str
relation: str
target: str
properties: Dict = field(default_factory=dict)
def to_triple(self) -> tuple:
return (self.source, self.relation, self.target)
@dataclass
class Principle:
"""SOUL.md principle encoded as rule"""
id: str
text: str
category: str # "must_do", "must_not_do", "belief"
priority: int = 1
enforce: bool = True
def to_rule(self) -> Dict:
"""Convert to rule engine format"""
return {
'id': self.id,
'condition': f'action.violates("{self.id}")',
'action': 'block_and_explain' if self.enforce else 'warn',
'explanation': self.text,
'priority': self.priority
}
class FleetSchema:
"""Schema manager for wizard fleet knowledge"""
def __init__(self):
self.wizards: Dict[str, Wizard] = {}
self.tasks: Dict[str, Task] = {}
self.artifacts: Dict[str, Entity] = {}
self.relationships: List[Relationship] = []
self.principles: Dict[str, Principle] = {}
# Predefined capability taxonomy
self.capabilities = {
'code_generation': 'Can write and modify code',
'research': 'Can perform deep research',
'automation': 'Can build automation scripts',
'monitoring': 'Can monitor systems',
'documentation': 'Can write documentation',
'architecture': 'Can design system architecture',
'child_creation': 'Can create child wizards',
'gofai': 'Can work with symbolic AI',
}
def add_wizard(self, wizard: Wizard) -> None:
"""Register a wizard in the fleet"""
self.wizards[wizard.id] = wizard
def add_task(self, task: Task) -> None:
"""Register a task"""
self.tasks[task.id] = task
def add_relationship(self, rel: Relationship) -> None:
"""Add relationship between entities"""
self.relationships.append(rel)
def add_principle(self, principle: Principle) -> None:
"""Add SOUL principle"""
self.principles[principle.id] = principle
def get_wizard_tasks(self, wizard_name: str) -> List[Task]:
"""Get all tasks assigned to a wizard"""
return [t for t in self.tasks.values() if t.assignee == wizard_name]
def get_children(self, father_name: str) -> List[Wizard]:
"""Get all wizards created by a father"""
return [w for w in self.wizards.values() if w.father == father_name]
def get_lineage_tree(self, wizard_name: str) -> Dict:
"""Get full lineage tree for a wizard"""
wizard = self.wizards.get(wizard_name)
if not wizard:
return {}
tree = {
'name': wizard.name,
'father': None,
'grandfather': None,
'children': []
}
if wizard.father and wizard.father in self.wizards:
father = self.wizards[wizard.father]
tree['father'] = {
'name': father.name,
'father': father.father,
'grandfather': father.grandfather
}
# Find children
for w in self.wizards.values():
if w.father == wizard_name:
tree['children'].append(w.name)
return tree
def check_principle_compliance(self, action: str, context: Dict) -> Dict:
"""Check if action complies with SOUL principles"""
violations = []
warnings = []
for principle in self.principles.values():
# Simple keyword check (sophisticated version would use NLP)
if self._action_violates_principle(action, principle, context):
if principle.enforce:
violations.append(principle)
else:
warnings.append(principle)
return {
'compliant': len(violations) == 0,
'violations': [p.text for p in violations],
'warnings': [p.text for p in warnings]
}
def _action_violates_principle(self, action: str, principle: Principle, context: Dict) -> bool:
"""Check if action violates a principle"""
action_lower = action.lower()
# Category-based checks
if principle.category == 'must_not_do':
forbidden_patterns = {
'pretend': ['pretend', 'impersonate', 'act as'],
'mutate': ['mutate', 'modify without logging'],
'hide': ['hide', 'conceal', 'secret'],
'depend': ['depend constantly', 'always ask father'],
}
for pattern, keywords in forbidden_patterns.items():
if pattern in principle.id.lower():
return any(kw in action_lower for kw in keywords)
return False
def export_to_graph(self) -> Dict:
"""Export entire schema as graph format"""
return {
'nodes': {
'wizards': [w.to_dict() for w in self.wizards.values()],
'tasks': [t.to_dict() for t in self.tasks.values()],
},
'edges': [
{
'source': r.source,
'relation': r.relation,
'target': r.target,
'properties': r.properties
}
for r in self.relationships
],
'principles': [p.to_rule() for p in self.principles.values()]
}
def get_next_executable_task(self, wizard_name: str) -> Optional[Task]:
"""Get highest priority non-blocked task for a wizard"""
wizard_tasks = self.get_wizard_tasks(wizard_name)
completed = {t.id for t in wizard_tasks if t.status == TaskStatus.COMPLETE}
# Sort by priority
priority_order = {'P0': 0, 'P1': 1, 'P2': 2, 'P3': 3}
sorted_tasks = sorted(
[t for t in wizard_tasks if t.status == TaskStatus.PENDING],
key=lambda t: priority_order.get(t.priority, 999)
)
# Return first non-blocked
for task in sorted_tasks:
if not task.is_blocked(completed):
return task
return None
# Singleton instance for fleet
_fleet_schema = None
def get_fleet_schema() -> FleetSchema:
global _fleet_schema
if _fleet_schema is None:
_fleet_schema = FleetSchema()
return _fleet_schema