#!/usr/bin/env python3 """ Migrate schemas to markdown format with versioning. This script converts existing JSON schemas in the database to the new markdown format following the naming convention: {domain}-schema-v{major}.{minor}.md """ import json import sys from pathlib import Path # Add parent directory to path for imports sys.path.insert(0, str(Path(__file__).parent.parent)) from markitect.database import DatabaseManager from markitect.schema_loader import MarkdownSchemaLoader def migrate_schema( db_manager: DatabaseManager, old_name: str, new_filename: str, version: str, domain: str, description: str, dry_run: bool = False ): """ Migrate a single schema to new markdown format. Args: db_manager: Database manager instance old_name: Name of old schema in database new_filename: New filename following naming convention version: SemVer version (major.minor.patch) domain: Schema domain name description: Brief schema description dry_run: If True, don't save files """ print(f"\n{'[DRY RUN] ' if dry_run else ''}Migrating: {old_name} → {new_filename}") # Get old schema from database old_schema_data = db_manager.get_schema_file(old_name) if not old_schema_data: print(f" ❌ Schema not found in database: {old_name}") return None # Parse schema JSON try: schema_json = json.loads(old_schema_data['schema_content']) except json.JSONDecodeError as e: print(f" ❌ Invalid JSON: {e}") return None # Update schema metadata major, minor = version.split('.')[:2] schema_json['version'] = version schema_json['$id'] = f"https://markitect.dev/schemas/{domain}/v{major}.{minor}" # Ensure required fields if 'description' not in schema_json or not schema_json['description']: schema_json['description'] = description # Create frontmatter frontmatter = { 'schema-id': schema_json['$id'], 'version': version, 'status': 'stable', 'domain': domain, 'description': description } if dry_run: print(f" ✓ Would create: {new_filename}") print(f" Version: {version}") print(f" $id: {schema_json['$id']}") return None # Save as markdown loader = MarkdownSchemaLoader() md_path = Path(__file__).parent.parent / 'markitect' / 'schemas' / new_filename loader.save_schema( schema=schema_json, md_path=md_path, frontmatter=frontmatter ) print(f" ✅ Created: {md_path}") print(f" Version: {version}") print(f" $id: {schema_json['$id']}") return md_path def cleanup_old_schema(db_manager: DatabaseManager, schema_name: str, dry_run: bool = False): """ Remove old schema from database. Args: db_manager: Database manager instance schema_name: Name of schema to remove dry_run: If True, don't actually delete """ if dry_run: print(f" [DRY RUN] Would delete from database: {schema_name}") return success = db_manager.delete_schema_file(schema_name) if success: print(f" 🗑️ Deleted from database: {schema_name}") else: print(f" ⚠️ Failed to delete: {schema_name}") def main(): """Execute schema migration.""" import argparse parser = argparse.ArgumentParser(description='Migrate schemas to markdown format') parser.add_argument('--dry-run', action='store_true', help='Show what would be done without making changes') parser.add_argument('--db', default='markitect.db', help='Database path') args = parser.parse_args() db_manager = DatabaseManager(args.db) print("=" * 60) print("Schema Migration - Phase 4") print("=" * 60) if args.dry_run: print("\n🔍 DRY RUN MODE - No changes will be made\n") # Define migrations migrations = [ { 'old_name': 'terminology-schema.json', 'new_filename': 'terminology-schema-v1.0.md', 'version': '1.0.0', 'domain': 'terminology', 'description': 'Schema for validating terminology and glossary documents with consistent structure' }, { 'old_name': 'api-documentation', 'new_filename': 'api-documentation-schema-v1.0.md', 'version': '1.0.0', 'domain': 'api-documentation', 'description': 'Schema for API documentation structure and content validation' }, ] # Schemas to delete (duplicates and replaced) to_delete = [ 'markdown-manpage', # Duplicate 'markdown-manpage-schema.json', # Duplicate 'enhanced-manpage', # Replaced by manpage-schema-v1.0.md ] # Execute migrations print("\n📝 MIGRATING SCHEMAS") print("-" * 60) migrated_files = [] for migration in migrations: result = migrate_schema( db_manager=db_manager, dry_run=args.dry_run, **migration ) if result: migrated_files.append(result) # Clean up old schemas print("\n\n🗑️ CLEANING UP OLD SCHEMAS") print("-" * 60) for schema_name in to_delete: cleanup_old_schema(db_manager, schema_name, dry_run=args.dry_run) # Summary print("\n\n" + "=" * 60) print("MIGRATION SUMMARY") print("=" * 60) if args.dry_run: print("\n✓ Dry run completed successfully") print(f" Would migrate {len(migrations)} schemas to markdown format") print(f" Would delete {len(to_delete)} old schemas from database") else: print(f"\n✓ Migrated {len(migrated_files)} schemas to markdown format") print(f"✓ Cleaned up {len(to_delete)} old schemas") if migrated_files: print("\n📄 New schema files created:") for f in migrated_files: print(f" - {f.name}") print("\n🔍 Next steps:") print(" 1. Validate new schemas: markitect schema-validate ") print(" 2. Ingest new schemas: markitect schema-ingest ") print(" 3. Test with documents") print("\n" + "=" * 60) if __name__ == '__main__': main()