Meta_Hackathon / validate_project.py
parthpethia's picture
Add Email Triage OpenEnv environment - production-ready with 3 graded tasks and Flask API
fee8744
#!/usr/bin/env python3
"""Comprehensive project validation script"""
import os
import sys
from pathlib import Path
print("="*70)
print("COMPREHENSIVE PROJECT VALIDATION")
print("="*70)
issues = []
warnings = []
# 1. Check all required files exist
print("\n[CHECK 1] Required Files")
required_files = [
"environment/__init__.py",
"environment/types.py",
"environment/env.py",
"environment/data_generator.py",
"environment/graders.py",
"app.py",
"Dockerfile",
"requirements.txt",
"inference.py",
"openenv.yaml",
"README.md"
]
for file in required_files:
if Path(file).exists():
size = Path(file).stat().st_size
print(f" [OK] {file:35} ({size:>6} bytes)")
else:
print(f" [ERROR] {file:35} MISSING")
issues.append(f"Missing file: {file}")
# 2. Check Python syntax
print("\n[CHECK 2] Python Syntax")
python_files = [
"environment/types.py",
"environment/env.py",
"environment/data_generator.py",
"environment/graders.py",
"app.py",
"inference.py"
]
for file in python_files:
try:
with open(file, 'r') as f:
code = f.read()
compile(code, file, 'exec')
print(f" [OK] {file:35} syntax valid")
except SyntaxError as e:
print(f" [ERROR] {file:35} {e}")
issues.append(f"Syntax error in {file}")
# 3. Check imports
print("\n[CHECK 3] Import Validation")
try:
from environment.types import Observation, Action, Reward, State
print(f" [OK] environment.types imports")
except ImportError as e:
print(f" [ERROR] environment.types: {e}")
issues.append(f"Import error in types")
try:
from environment.env import EmailTriageEnv
print(f" [OK] environment.env imports")
except ImportError as e:
print(f" [ERROR] environment.env: {e}")
issues.append(f"Import error in env")
try:
from environment.data_generator import DataGenerator
print(f" [OK] environment.data_generator imports")
except ImportError as e:
print(f" [ERROR] environment.data_generator: {e}")
issues.append(f"Import error in data_generator")
try:
from environment.graders import SpamDetectionGrader
print(f" [OK] environment.graders imports")
except ImportError as e:
print(f" [ERROR] environment.graders: {e}")
issues.append(f"Import error in graders")
# 4. Check environment functionality
print("\n[CHECK 4] Environment Functionality")
try:
from environment import EmailTriageEnv, Action, EmailCategory, Team
for task in ["spam_detection", "multi_class_routing", "context_aware_triage"]:
env = EmailTriageEnv(task)
obs = env.reset()
assert obs is not None
action = Action(classification=EmailCategory.NORMAL, team=Team.SUPPORT, priority=1)
obs, reward, done, info = env.step(action)
assert 0 <= reward.value <= 1
print(f" [OK] {task:30} works")
except Exception as e:
print(f" [ERROR] {e}")
issues.append(f"Environment error: {str(e)[:50]}")
# 5. Check Flask app
print("\n[CHECK 5] Flask App")
try:
from app import app
print(f" [OK] Flask app loads")
routes = [rule.rule for rule in app.url_map.iter_rules()]
required = ['/health', '/reset', '/step', '/state', '/tasks']
for route in required:
if route in routes:
print(f" [OK] {route:20} endpoint")
else:
warnings.append(f"Missing route: {route}")
except Exception as e:
print(f" [ERROR] Flask: {e}")
issues.append(f"Flask error")
# 6. Check openenv.yaml
print("\n[CHECK 6] openenv.yaml")
try:
import yaml
with open('openenv.yaml', 'r') as f:
spec = yaml.safe_load(f)
if 'tasks' in spec and len(spec['tasks']) >= 3:
print(f" [OK] {len(spec['tasks'])} tasks defined")
else:
warnings.append("Less than 3 tasks")
if 'action_space' in spec:
print(f" [OK] action_space defined")
if 'observation_space' in spec:
print(f" [OK] observation_space defined")
if 'reward' in spec:
print(f" [OK] reward defined")
except Exception as e:
print(f" [ERROR] openenv.yaml: {e}")
issues.append(f"YAML error")
# 7. Check inference.py format
print("\n[CHECK 7] Inference Format")
try:
with open('inference.py', 'r') as f:
code = f.read()
if '[START]' in code and '[STEP]' in code and '[END]' in code:
print(f" [OK] Logging format correct")
if 'OpenAI' in code:
print(f" [OK] Uses OpenAI client")
if all(x in code for x in ['OPENAI_API_KEY', 'MODEL_NAME', 'API_BASE_URL']):
print(f" [OK] All env vars handled")
except Exception as e:
print(f" [ERROR] inference.py: {e}")
issues.append(f"Inference error")
# 8. Check Dockerfile
print("\n[CHECK 8] Dockerfile")
try:
with open('Dockerfile', 'r') as f:
df = f.read()
if 'python:3.11' in df:
print(f" [OK] Python 3.11 base")
if '7860' in df:
print(f" [OK] Port 7860 exposed")
if 'HEALTHCHECK' in df:
print(f" [OK] Health check set")
except Exception as e:
print(f" [ERROR] Dockerfile: {e}")
issues.append(f"Dockerfile error")
# 9. Check requirements.txt
print("\n[CHECK 9] requirements.txt")
try:
with open('requirements.txt', 'r') as f:
reqs = f.read().lower()
for pkg in ['pydantic', 'flask', 'openai', 'pyyaml']:
if pkg in reqs:
print(f" [OK] {pkg:20} listed")
except Exception as e:
print(f" [ERROR] requirements.txt: {e}")
issues.append(f"Requirements error")
# 10. Check documentation
print("\n[CHECK 10] Documentation")
doc_files = {
"README.md": 5000,
"DEPLOYMENT_CHECKLIST.md": 2000,
"START_HERE.md": 1000,
"SUBMISSION_CHECKLIST.md": 5000,
}
docs_ok = 0
for doc, min_size in doc_files.items():
if Path(doc).exists():
size = Path(doc).stat().st_size
if size >= min_size:
print(f" [OK] {doc:35}")
docs_ok += 1
else:
warnings.append(f"{doc} too small ({size} bytes)")
else:
warnings.append(f"Missing: {doc}")
# Summary
print("\n" + "="*70)
print("VALIDATION RESULTS")
print("="*70)
print(f"\nCritical Issues: {len(issues)}")
print(f"Warnings: {len(warnings)}")
if issues:
print(f"\nCRITICAL ISSUES TO FIX:")
for issue in issues:
print(f" - {issue}")
sys.exit(1)
else:
print(f"\n[SUCCESS] All critical checks passed!")
if warnings:
print(f"\nMinor warnings ({len(warnings)}):")
for w in warnings:
print(f" - {w}")
print("\n[READY] Project is ready for deployment!")