#!/usr/bin/env python3 """ Script de synchronisation pour Cursor AI Génère automatiquement le contexte et les prompts optimisés """ import json import yaml import os from pathlib import Path from datetime import datetime import subprocess import sys class CursorSync: def __init__(self): self.project_root = Path.cwd() self.cursor_config = self.project_root / ".cursor" self.veza_config = self.project_root / ".veza" def load_architecture(self): """Charge les informations d'architecture""" try: with open(self.project_root / "docs/arch/current.mmd", "r") as f: return { "type": "mermaid", "content": f.read() } except FileNotFoundError: return { "type": "hexagonal", "description": "Architecture hexagonale avec core backend et features modulaires" } def scan_features(self): """Scanne toutes les features du projet""" features = {} # Core backend if (self.project_root / "veza-backend-api").exists(): features["core"] = { "status": "stable", "version": "1.0.0", "location": "veza-backend-api/", "language": "go" } # Chat server if (self.project_root / "veza-chat-server").exists(): features["chat-server"] = { "status": "stable", "version": "1.0.0", "location": "veza-chat-server/", "language": "rust" } # Stream server if (self.project_root / "veza-stream-server").exists(): features["stream-server"] = { "status": "stable", "version": "1.0.0", "location": "veza-stream-server/", "language": "rust" } # Documentation if (self.project_root / "veza-docs").exists(): features["docs"] = { "status": "stable", "version": "1.0.0", "location": "veza-docs/", "language": "javascript" } return features def load_contracts(self): """Charge les contrats d'interface""" contracts = {} contracts_dir = self.project_root / "veza-backend-api/internal/core/contracts" if contracts_dir.exists(): for contract_file in contracts_dir.glob("*.go"): contracts[contract_file.stem] = { "file": str(contract_file.relative_to(self.project_root)), "type": "interface" } return contracts def analyze_dependencies(self): """Analyse les dépendances du projet""" dependencies = {} # Go dependencies go_mod = self.project_root / "veza-backend-api/go.mod" if go_mod.exists(): dependencies["go"] = { "file": "veza-backend-api/go.mod", "framework": "gin" } # Rust dependencies for rust_project in ["veza-chat-server", "veza-stream-server"]: cargo_toml = self.project_root / rust_project / "Cargo.toml" if cargo_toml.exists(): dependencies[rust_project] = { "file": f"{rust_project}/Cargo.toml", "language": "rust" } return dependencies def load_tasks(self): """Charge les tâches en cours""" tasks = [] # Vérifier s'il y a des branches en cours try: result = subprocess.run( ["git", "branch", "--show-current"], capture_output=True, text=True, cwd=self.project_root ) if result.returncode == 0: current_branch = result.stdout.strip() if current_branch != "main" and current_branch != "develop": tasks.append({ "type": "feature_development", "name": f"Working on branch: {current_branch}", "status": "in_progress" }) except: pass return tasks def load_validation_rules(self): """Charge les règles de validation""" return [ "version_compatibility", "interface_contracts", "event_consistency", "commit_format", "test_coverage" ] def generate_context_file(self): """Génère un fichier de contexte pour Cursor AI""" context = { "project": "Veza", "architecture": self.load_architecture(), "features": self.scan_features(), "contracts": self.load_contracts(), "dependencies": self.analyze_dependencies(), "current_tasks": self.load_tasks(), "validation_rules": self.load_validation_rules(), "last_updated": datetime.now().isoformat() } self.cursor_config.mkdir(exist_ok=True) with open(self.cursor_config / "context.json", "w") as f: json.dump(context, f, indent=2) print(f"✅ Context file generated: {self.cursor_config / 'context.json'}") def create_implementation_prompt(self): """Crée un prompt optimisé pour l'implémentation""" return """ En tant qu'assistant Cursor AI pour le projet Veza: 1. TOUJOURS vérifier la compatibilité avec le core avant d'implémenter 2. RESPECTER les contrats définis dans internal/core/contracts/ 3. SUIVRE la structure modulaire dans features/ 4. UTILISER les types et interfaces du core 5. GÉNÉRER les tests en parallèle de l'implémentation 6. DOCUMENTER chaque fonction publique 7. VALIDER avec le script check-compatibility.sh 8. SUIVRE le format de commit: [SCOPE][TYPE] Description Contexte actuel: {context} Feature en cours: {current_feature} Dépendances: {dependencies} Architecture: Hexagonale avec core immutable Patterns: Repository, Service, Handler Validation: Tests unitaires + intégration obligatoires """ def create_testing_prompt(self): """Crée un prompt optimisé pour les tests""" return """ Pour les tests dans Veza: 1. TOUJOURS tester les contrats d'interface 2. COUVRIR les cas d'erreur et edge cases 3. UTILISER testify pour Go, built-in pour Rust 4. MOCKER les dépendances externes 5. TESTER l'intégration entre features 6. VALIDER la compatibilité des versions Scope: {scope} Feature: {feature} Framework: {framework} """ def create_compatibility_prompt(self): """Crée un prompt pour la vérification de compatibilité""" return """ Vérification de compatibilité Veza: 1. VÉRIFIER les versions des dépendances 2. CONTRÔLER les interfaces exposées 3. VALIDER les événements publiés/souscrits 4. TESTER l'intégration entre modules 5. DOCUMENTER les changements breaking Features: {features} Contracts: {contracts} Events: {events} """ def create_documentation_prompt(self): """Crée un prompt pour la documentation""" return """ Documentation Veza: 1. DOCUMENTER toutes les interfaces publiques 2. EXPLIQUER les patterns d'architecture 3. FOURNIR des exemples d'utilisation 4. MAINTENIR la cohérence avec l'architecture 5. METTRE À JOUR les diagrammes si nécessaire Type: {doc_type} Scope: {scope} Format: Markdown """ def generate_prompts(self): """Génère des prompts optimisés pour Cursor""" prompts = { "implementation": self.create_implementation_prompt(), "testing": self.create_testing_prompt(), "compatibility": self.create_compatibility_prompt(), "documentation": self.create_documentation_prompt() } self.cursor_config.mkdir(exist_ok=True) with open(self.cursor_config / "prompts.yaml", "w") as f: yaml.dump(prompts, f, default_flow_style=False) print(f"✅ Prompts generated: {self.cursor_config / 'prompts.yaml'}") def update_manifest(self): """Met à jour le manifeste des features""" if not self.veza_config.exists(): self.veza_config.mkdir(exist_ok=True) manifest_file = self.veza_config / "feature-manifest.yaml" if not manifest_file.exists(): # Créer un manifeste de base base_manifest = { "version": "1.0.0", "last_updated": datetime.now().isoformat(), "features": self.scan_features(), "compatibility_matrix": {}, "validation_rules": self.load_validation_rules() } with open(manifest_file, "w") as f: yaml.dump(base_manifest, f, default_flow_style=False) print(f"✅ Base manifest created: {manifest_file}") else: print(f"ℹ️ Manifest already exists: {manifest_file}") def sync_all(self): """Synchronise tout le contexte Cursor""" print("🔄 Synchronizing Cursor AI context...") self.generate_context_file() self.generate_prompts() self.update_manifest() print("✅ Cursor AI synchronization completed!") def main(): """Fonction principale""" try: sync = CursorSync() sync.sync_all() except Exception as e: print(f"❌ Error during synchronization: {e}") sys.exit(1) if __name__ == "__main__": main()