Complete second-pass refinement integrating all wizard house contributions: **Three-House Architecture:** - Ezra (Archivist): Read-before-write, evidence over vibes, citation discipline - Bezalel (Artificer): Build-from-plans, proof over speculation, test discipline - Timmy (Sovereign): Final judgment, telemetry, sovereignty preservation **Core Components:** - harness.py: House-aware execution with policy enforcement - router.py: Intelligent task routing to appropriate house - task_router_daemon.py: Full three-house Gitea workflow - tests/test_v2.py: Comprehensive test suite **Key Features:** - Provenance tracking with content hashing - House-specific policy enforcement - Sovereignty telemetry logging - Cross-house workflow orchestration - Evidence-level tracking per execution Honors canon from specs/timmy-ezra-bezalel-canon-sheet.md: - Distinct house identities - No authority blending - Artifact-flow unidirectional - Full provenance and telemetry
473 lines
16 KiB
Python
473 lines
16 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Uni-Wizard Harness v2 — The Three-House Architecture
|
|
|
|
Integrates:
|
|
- Timmy: Sovereign local conscience, final judgment, telemetry
|
|
- Ezra: Archivist pattern — read before write, evidence over vibes
|
|
- Bezalel: Artificer pattern — build from plans, proof over speculation
|
|
|
|
Usage:
|
|
harness = UniWizardHarness(house="ezra") # Archivist mode
|
|
harness = UniWizardHarness(house="bezalel") # Artificer mode
|
|
harness = UniWizardHarness(house="timmy") # Sovereign mode
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import time
|
|
import hashlib
|
|
from typing import Dict, Any, Optional, List
|
|
from pathlib import Path
|
|
from dataclasses import dataclass, asdict
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
|
|
# Add tools to path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
from tools import registry
|
|
|
|
|
|
class House(Enum):
|
|
"""The three canonical wizard houses"""
|
|
TIMMY = "timmy" # Sovereign local conscience
|
|
EZRA = "ezra" # Archivist, reader, pattern-recognizer
|
|
BEZALEL = "bezalel" # Artificer, builder, proof-maker
|
|
|
|
|
|
@dataclass
|
|
class Provenance:
|
|
"""Trail of evidence for every action"""
|
|
house: str
|
|
tool: str
|
|
started_at: str
|
|
completed_at: Optional[str] = None
|
|
input_hash: Optional[str] = None
|
|
output_hash: Optional[str] = None
|
|
sources_read: List[str] = None
|
|
evidence_level: str = "none" # none, partial, full
|
|
confidence: float = 0.0
|
|
|
|
def to_dict(self):
|
|
return asdict(self)
|
|
|
|
|
|
@dataclass
|
|
class ExecutionResult:
|
|
"""Result with full provenance"""
|
|
success: bool
|
|
data: Any
|
|
provenance: Provenance
|
|
error: Optional[str] = None
|
|
execution_time_ms: float = 0.0
|
|
|
|
def to_json(self) -> str:
|
|
return json.dumps({
|
|
'success': self.success,
|
|
'data': self.data,
|
|
'provenance': self.provenance.to_dict(),
|
|
'error': self.error,
|
|
'execution_time_ms': self.execution_time_ms
|
|
}, indent=2)
|
|
|
|
|
|
class HousePolicy:
|
|
"""Policy enforcement per house"""
|
|
|
|
POLICIES = {
|
|
House.TIMMY: {
|
|
"requires_provenance": True,
|
|
"evidence_threshold": 0.7,
|
|
"can_override": True,
|
|
"telemetry": True,
|
|
"motto": "Sovereignty and service always"
|
|
},
|
|
House.EZRA: {
|
|
"requires_provenance": True,
|
|
"evidence_threshold": 0.8,
|
|
"must_read_before_write": True,
|
|
"citation_required": True,
|
|
"motto": "Read the pattern. Name the truth. Return a clean artifact."
|
|
},
|
|
House.BEZALEL: {
|
|
"requires_provenance": True,
|
|
"evidence_threshold": 0.6,
|
|
"requires_proof": True,
|
|
"test_before_ship": True,
|
|
"motto": "Build the pattern. Prove the result. Return the tool."
|
|
}
|
|
}
|
|
|
|
@classmethod
|
|
def get(cls, house: House) -> Dict:
|
|
return cls.POLICIES.get(house, cls.POLICIES[House.TIMMY])
|
|
|
|
|
|
class SovereigntyTelemetry:
|
|
"""Timmy's sovereignty tracking — what you measure, you manage"""
|
|
|
|
def __init__(self, log_dir: Path = None):
|
|
self.log_dir = log_dir or Path.home() / "timmy" / "logs"
|
|
self.log_dir.mkdir(parents=True, exist_ok=True)
|
|
self.telemetry_log = self.log_dir / "uni_wizard_telemetry.jsonl"
|
|
self.session_id = hashlib.sha256(
|
|
f"{time.time()}{id(self)}".encode()
|
|
).hexdigest()[:16]
|
|
|
|
def log_execution(self, house: str, tool: str, result: ExecutionResult):
|
|
"""Log every execution with full provenance"""
|
|
entry = {
|
|
"session_id": self.session_id,
|
|
"timestamp": datetime.utcnow().isoformat(),
|
|
"house": house,
|
|
"tool": tool,
|
|
"success": result.success,
|
|
"execution_time_ms": result.execution_time_ms,
|
|
"evidence_level": result.provenance.evidence_level,
|
|
"confidence": result.provenance.confidence,
|
|
"sources_count": len(result.provenance.sources_read or []),
|
|
}
|
|
|
|
with open(self.telemetry_log, 'a') as f:
|
|
f.write(json.dumps(entry) + '\n')
|
|
|
|
def get_sovereignty_report(self, days: int = 7) -> Dict:
|
|
"""Generate sovereignty metrics report"""
|
|
# Read telemetry log
|
|
entries = []
|
|
if self.telemetry_log.exists():
|
|
with open(self.telemetry_log) as f:
|
|
for line in f:
|
|
try:
|
|
entries.append(json.loads(line))
|
|
except:
|
|
continue
|
|
|
|
# Calculate metrics
|
|
total = len(entries)
|
|
by_house = {}
|
|
by_tool = {}
|
|
avg_confidence = 0.0
|
|
|
|
for e in entries:
|
|
house = e.get('house', 'unknown')
|
|
by_house[house] = by_house.get(house, 0) + 1
|
|
|
|
tool = e.get('tool', 'unknown')
|
|
by_tool[tool] = by_tool.get(tool, 0) + 1
|
|
|
|
avg_confidence += e.get('confidence', 0)
|
|
|
|
if total > 0:
|
|
avg_confidence /= total
|
|
|
|
return {
|
|
"total_executions": total,
|
|
"by_house": by_house,
|
|
"top_tools": sorted(by_tool.items(), key=lambda x: -x[1])[:10],
|
|
"avg_confidence": round(avg_confidence, 2),
|
|
"session_id": self.session_id
|
|
}
|
|
|
|
|
|
class UniWizardHarness:
|
|
"""
|
|
The Uni-Wizard Harness v2 — Three houses, one consciousness.
|
|
|
|
House-aware execution with provenance tracking:
|
|
- Timmy: Sovereign judgment, telemetry, final review
|
|
- Ezra: Archivist — reads before writing, cites sources
|
|
- Bezalel: Artificer — builds with proof, tests before shipping
|
|
"""
|
|
|
|
def __init__(self, house: str = "timmy", telemetry: bool = True):
|
|
self.house = House(house)
|
|
self.registry = registry
|
|
self.policy = HousePolicy.get(self.house)
|
|
self.history: List[ExecutionResult] = []
|
|
|
|
# Telemetry (Timmy's sovereignty tracking)
|
|
self.telemetry = SovereigntyTelemetry() if telemetry else None
|
|
|
|
# Evidence store (Ezra's reading cache)
|
|
self.evidence_cache: Dict[str, Any] = {}
|
|
|
|
# Proof store (Bezalel's test results)
|
|
self.proof_cache: Dict[str, Any] = {}
|
|
|
|
def _hash_content(self, content: str) -> str:
|
|
"""Create content hash for provenance"""
|
|
return hashlib.sha256(content.encode()).hexdigest()[:16]
|
|
|
|
def _check_evidence(self, tool_name: str, params: Dict) -> tuple:
|
|
"""
|
|
Ezra's pattern: Check evidence level before execution.
|
|
Returns (evidence_level, confidence, sources)
|
|
"""
|
|
sources = []
|
|
|
|
# For git operations, check repo state
|
|
if tool_name.startswith("git_"):
|
|
repo_path = params.get("repo_path", ".")
|
|
sources.append(f"repo:{repo_path}")
|
|
# Would check git status here
|
|
return ("full", 0.9, sources)
|
|
|
|
# For system operations, check current state
|
|
if tool_name.startswith("system_") or tool_name.startswith("service_"):
|
|
sources.append("system:live")
|
|
return ("full", 0.95, sources)
|
|
|
|
# For network operations, depends on external state
|
|
if tool_name.startswith("http_") or tool_name.startswith("gitea_"):
|
|
sources.append("network:external")
|
|
return ("partial", 0.6, sources)
|
|
|
|
return ("none", 0.5, sources)
|
|
|
|
def _verify_proof(self, tool_name: str, result: Any) -> bool:
|
|
"""
|
|
Bezalel's pattern: Verify proof for build artifacts.
|
|
"""
|
|
if not self.policy.get("requires_proof", False):
|
|
return True
|
|
|
|
# For git operations, verify the operation succeeded
|
|
if tool_name.startswith("git_"):
|
|
# Check if result contains success indicator
|
|
if isinstance(result, dict):
|
|
return result.get("success", False)
|
|
if isinstance(result, str):
|
|
return "error" not in result.lower()
|
|
|
|
return True
|
|
|
|
def execute(self, tool_name: str, **params) -> ExecutionResult:
|
|
"""
|
|
Execute a tool with full house policy enforcement.
|
|
|
|
Flow:
|
|
1. Check evidence (Ezra pattern)
|
|
2. Execute tool
|
|
3. Verify proof (Bezalel pattern)
|
|
4. Record provenance
|
|
5. Log telemetry (Timmy pattern)
|
|
"""
|
|
start_time = time.time()
|
|
started_at = datetime.utcnow().isoformat()
|
|
|
|
# 1. Evidence check (Ezra's archivist discipline)
|
|
evidence_level, confidence, sources = self._check_evidence(tool_name, params)
|
|
|
|
if self.policy.get("must_read_before_write", False):
|
|
if evidence_level == "none" and tool_name.startswith("git_"):
|
|
# Ezra must read git status before git commit
|
|
if tool_name == "git_commit":
|
|
return ExecutionResult(
|
|
success=False,
|
|
data=None,
|
|
provenance=Provenance(
|
|
house=self.house.value,
|
|
tool=tool_name,
|
|
started_at=started_at,
|
|
evidence_level="none"
|
|
),
|
|
error="Ezra policy: Must read git_status before git_commit",
|
|
execution_time_ms=0
|
|
)
|
|
|
|
# 2. Execute tool
|
|
try:
|
|
raw_result = self.registry.execute(tool_name, **params)
|
|
success = True
|
|
error = None
|
|
data = raw_result
|
|
except Exception as e:
|
|
success = False
|
|
error = f"{type(e).__name__}: {str(e)}"
|
|
data = None
|
|
|
|
execution_time_ms = (time.time() - start_time) * 1000
|
|
completed_at = datetime.utcnow().isoformat()
|
|
|
|
# 3. Proof verification (Bezalel's artificer discipline)
|
|
if success and self.policy.get("requires_proof", False):
|
|
proof_valid = self._verify_proof(tool_name, data)
|
|
if not proof_valid:
|
|
success = False
|
|
error = "Bezalel policy: Proof verification failed"
|
|
|
|
# 4. Build provenance record
|
|
input_hash = self._hash_content(json.dumps(params, sort_keys=True))
|
|
output_hash = self._hash_content(json.dumps(data, default=str)) if data else None
|
|
|
|
provenance = Provenance(
|
|
house=self.house.value,
|
|
tool=tool_name,
|
|
started_at=started_at,
|
|
completed_at=completed_at,
|
|
input_hash=input_hash,
|
|
output_hash=output_hash,
|
|
sources_read=sources,
|
|
evidence_level=evidence_level,
|
|
confidence=confidence if success else 0.0
|
|
)
|
|
|
|
result = ExecutionResult(
|
|
success=success,
|
|
data=data,
|
|
provenance=provenance,
|
|
error=error,
|
|
execution_time_ms=execution_time_ms
|
|
)
|
|
|
|
# 5. Record history
|
|
self.history.append(result)
|
|
|
|
# 6. Log telemetry (Timmy's sovereignty tracking)
|
|
if self.telemetry:
|
|
self.telemetry.log_execution(self.house.value, tool_name, result)
|
|
|
|
return result
|
|
|
|
def execute_plan(self, plan: List[Dict]) -> Dict[str, ExecutionResult]:
|
|
"""
|
|
Execute a sequence with house policy applied at each step.
|
|
|
|
Plan format:
|
|
[
|
|
{"tool": "git_status", "params": {"repo_path": "/path"}},
|
|
{"tool": "git_commit", "params": {"message": "Update"}}
|
|
]
|
|
"""
|
|
results = {}
|
|
|
|
for step in plan:
|
|
tool_name = step.get("tool")
|
|
params = step.get("params", {})
|
|
|
|
result = self.execute(tool_name, **params)
|
|
results[tool_name] = result
|
|
|
|
# Stop on failure (Bezalel: fail fast)
|
|
if not result.success and self.policy.get("test_before_ship", False):
|
|
break
|
|
|
|
return results
|
|
|
|
def review_for_timmy(self, results: Dict[str, ExecutionResult]) -> Dict:
|
|
"""
|
|
Generate a review package for Timmy's sovereign judgment.
|
|
Returns structured review data with full provenance.
|
|
"""
|
|
review = {
|
|
"house": self.house.value,
|
|
"policy": self.policy,
|
|
"executions": [],
|
|
"summary": {
|
|
"total": len(results),
|
|
"successful": sum(1 for r in results.values() if r.success),
|
|
"failed": sum(1 for r in results.values() if not r.success),
|
|
"avg_confidence": 0.0,
|
|
"evidence_levels": {}
|
|
},
|
|
"recommendation": ""
|
|
}
|
|
|
|
total_confidence = 0
|
|
for tool, result in results.items():
|
|
review["executions"].append({
|
|
"tool": tool,
|
|
"success": result.success,
|
|
"error": result.error,
|
|
"evidence_level": result.provenance.evidence_level,
|
|
"confidence": result.provenance.confidence,
|
|
"sources": result.provenance.sources_read,
|
|
"execution_time_ms": result.execution_time_ms
|
|
})
|
|
total_confidence += result.provenance.confidence
|
|
|
|
level = result.provenance.evidence_level
|
|
review["summary"]["evidence_levels"][level] = \
|
|
review["summary"]["evidence_levels"].get(level, 0) + 1
|
|
|
|
if results:
|
|
review["summary"]["avg_confidence"] = round(
|
|
total_confidence / len(results), 2
|
|
)
|
|
|
|
# Generate recommendation
|
|
if review["summary"]["failed"] == 0:
|
|
if review["summary"]["avg_confidence"] >= 0.8:
|
|
review["recommendation"] = "APPROVE: High confidence, all passed"
|
|
else:
|
|
review["recommendation"] = "CONDITIONAL: Passed but low confidence"
|
|
else:
|
|
review["recommendation"] = "REJECT: Failures detected"
|
|
|
|
return review
|
|
|
|
def get_capabilities(self) -> str:
|
|
"""List all capabilities with house annotations"""
|
|
lines = [f"\n🏛️ {self.house.value.upper()} HOUSE CAPABILITIES"]
|
|
lines.append(f" Motto: {self.policy.get('motto', '')}")
|
|
lines.append(f" Evidence threshold: {self.policy.get('evidence_threshold', 0)}")
|
|
lines.append("")
|
|
|
|
for category in self.registry.get_categories():
|
|
cat_tools = self.registry.get_tools_by_category(category)
|
|
lines.append(f"\n📁 {category.upper()}")
|
|
for tool in cat_tools:
|
|
lines.append(f" • {tool['name']}: {tool['description']}")
|
|
|
|
return "\n".join(lines)
|
|
|
|
def get_telemetry_report(self) -> str:
|
|
"""Get sovereignty telemetry report"""
|
|
if not self.telemetry:
|
|
return "Telemetry disabled"
|
|
|
|
report = self.telemetry.get_sovereignty_report()
|
|
|
|
lines = ["\n📊 SOVEREIGNTY TELEMETRY REPORT"]
|
|
lines.append(f" Session: {report['session_id']}")
|
|
lines.append(f" Total executions: {report['total_executions']}")
|
|
lines.append(f" Average confidence: {report['avg_confidence']}")
|
|
lines.append("\n By House:")
|
|
for house, count in report.get('by_house', {}).items():
|
|
lines.append(f" {house}: {count}")
|
|
lines.append("\n Top Tools:")
|
|
for tool, count in report.get('top_tools', []):
|
|
lines.append(f" {tool}: {count}")
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
def get_harness(house: str = "timmy") -> UniWizardHarness:
|
|
"""Factory function to get configured harness"""
|
|
return UniWizardHarness(house=house)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Demo the three houses
|
|
print("=" * 60)
|
|
print("UNI-WIZARD HARNESS v2 — Three House Demo")
|
|
print("=" * 60)
|
|
|
|
# Ezra mode
|
|
print("\n" + "=" * 60)
|
|
ezra = get_harness("ezra")
|
|
print(ezra.get_capabilities())
|
|
|
|
# Bezalel mode
|
|
print("\n" + "=" * 60)
|
|
bezalel = get_harness("bezalel")
|
|
print(bezalel.get_capabilities())
|
|
|
|
# Timmy mode with telemetry
|
|
print("\n" + "=" * 60)
|
|
timmy = get_harness("timmy")
|
|
print(timmy.get_capabilities())
|
|
print(timmy.get_telemetry_report())
|