Research-Stack/0-Core-Formalism/lean/LeanGPT/otom_pipeline.py

208 lines
7.7 KiB
Python

#!/usr/bin/env python3
"""
OTOM LeanGPT Pipeline
Integrates LeanGPT framework as testing pipeline for OTOM Lean modules
Per AGENTS.md §6.1: Python shim for testing pipeline only
"""
import subprocess
import json
import logging
from pathlib import Path
from typing import Dict, List, Optional
from dataclasses import dataclass, asdict
from datetime import datetime
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("OTOMLeanGPTPipeline")
@dataclass
class LeanModule:
"""OTOM Lean module for testing"""
name: str
path: str
domain: str
theorems: int
status: str # "complete", "wip", "todo"
@dataclass
class TestResult:
"""Test result for a Lean module"""
module: str
lake_build: bool
theorems_checked: int
errors: List[str]
duration: float
timestamp: str
class OTOMLeanGPTPipeline:
"""
Integrates LeanGPT framework for testing OTOM Lean modules.
Pipeline:
1. Lake build check (compilation)
2. Theorem verification
3. AI-assisted proof generation (future)
"""
def __init__(self, lean_path: str = None, lean_gpt_path: str = None):
self.lean_path = Path(lean_path) if lean_path else Path("/home/allaun/Documents/Research Stack/0-Core-Formalism/lean/Semantics")
self.lean_gpt_path = Path(lean_gpt_path) if lean_gpt_path else Path("/home/allaun/Documents/Research Stack/0-Core-Formalism/lean/LeanGPT")
self.results: List[TestResult] = []
# OTOM v2.1 modules
self.modules = [
LeanModule("GenomicCompression", "Semantics/GenomicCompression.lean", "Compression", 4, "complete"),
LeanModule("ResearchAgent", "Semantics/ResearchAgent.lean", "Cognitive/Control", 4, "complete"),
LeanModule("CrossModalCompression", "Semantics/CrossModalCompression.lean", "Compression", 2, "complete"),
LeanModule("AgenticOrchestration", "Semantics/AgenticOrchestration.lean", "Cognitive/Control", 0, "complete"),
LeanModule("BracketShellCount", "Semantics/BracketShellCount.lean", "Braid/Algebra", 2, "wip"),
]
logger.info(f"OTOM LeanGPT Pipeline initialized")
logger.info(f"Lean path: {self.lean_path}")
logger.info(f"LeanGPT path: {self.lean_gpt_path}")
def lake_build_module(self, module: LeanModule) -> tuple[bool, List[str], float]:
"""Run lake build on the entire Semantics package"""
start_time = datetime.now()
module_path = self.lean_path / module.path
if not module_path.exists():
return False, [f"Module not found: {module_path}"], 0.0
try:
# Build the entire Semantics package
result = subprocess.run(
["lake", "build"],
cwd=self.lean_path,
capture_output=True,
text=True,
timeout=300 # 5 minute timeout for full build
)
duration = (datetime.now() - start_time).total_seconds()
success = result.returncode == 0
errors = []
if not success:
# Extract last 500 chars of stderr for error reporting
stderr_lines = result.stderr.split('\n')
error_lines = [line for line in stderr_lines if 'error:' in line.lower()]
if error_lines:
errors.append('\n'.join(error_lines[-5:])) # Last 5 error lines
else:
errors.append(result.stderr[-500:] if len(result.stderr) > 500 else result.stderr)
return success, errors, duration
except subprocess.TimeoutExpired:
duration = (datetime.now() - start_time).total_seconds()
return False, ["Build timeout after 300s"], duration
except Exception as e:
duration = (datetime.now() - start_time).total_seconds()
return False, [f"Build error: {str(e)}"], duration
def check_theorems(self, module: LeanModule) -> int:
"""
Check theorems in a module (placeholder for LeanGPT integration).
In full implementation, this would:
1. Parse the module for theorem declarations
2. Check which have proofs vs sorry
3. Use LeanGPT to attempt proof generation for sorry placeholders
"""
# Placeholder: use Grep to find theorems
# For now, return the expected count from module definition
return module.theorems
def run_test(self, module: LeanModule) -> TestResult:
"""Run full test on a module"""
logger.info(f"Testing module: {module.name}")
# Step 1: Lake build
build_success, build_errors, build_duration = self.lake_build_module(module)
# Step 2: Check theorems
theorems_checked = self.check_theorems(module)
result = TestResult(
module=module.name,
lake_build=build_success,
theorems_checked=theorems_checked,
errors=build_errors,
duration=build_duration,
timestamp=datetime.now().isoformat()
)
self.results.append(result)
logger.info(f"Test complete: {module.name} - Success: {build_success}")
return result
def run_pipeline(self) -> Dict:
"""Run full OTOM pipeline test"""
logger.info("=" * 60)
logger.info("OTOM LEANGPT PIPELINE")
logger.info("=" * 60)
for module in self.modules:
self.run_test(module)
# Summary statistics
total_modules = len(self.modules)
successful_builds = sum(1 for r in self.results if r.lake_build)
total_theorems = sum(r.theorems_checked for r in self.results)
total_errors = sum(len(r.errors) for r in self.results)
summary = {
"total_modules": total_modules,
"successful_builds": successful_builds,
"build_success_rate": successful_builds / total_modules if total_modules > 0 else 0,
"total_theorems": total_theorems,
"total_errors": total_errors,
"results": [asdict(r) for r in self.results],
"timestamp": datetime.now().isoformat()
}
# Save results
results_file = self.lean_gpt_path / "otom_test_results.json"
with open(results_file, 'w') as f:
json.dump(summary, f, indent=2)
logger.info(f"\nPipeline complete. Results saved to {results_file}")
return summary
def print_summary(self, summary: Dict):
"""Print test summary"""
print("\n" + "=" * 60)
print("OTOM LEANGPT PIPELINE RESULTS")
print("=" * 60)
print(f"Total modules: {summary['total_modules']}")
print(f"Successful builds: {summary['successful_builds']}/{summary['total_modules']}")
print(f"Build success rate: {summary['build_success_rate']:.2%}")
print(f"Total theorems: {summary['total_theorems']}")
print(f"Total errors: {summary['total_errors']}")
print("\nModule Results:")
print("-" * 60)
for result in summary['results']:
status = "" if result['lake_build'] else ""
print(f"{status} {result['module']:20} | Theorems: {result['theorems_checked']:2} | Duration: {result['duration']:6.2f}s")
if result['errors']:
for error in result['errors'][:2]:
print(f" Error: {error}")
print("=" * 60)
# CLI interface
if __name__ == "__main__":
print("=" * 60)
print("OTOM LEANGPT PIPELINE")
print("=" * 60)
pipeline = OTOMLeanGPTPipeline()
summary = pipeline.run_pipeline()
pipeline.print_summary(summary)