#!/usr/bin/env python3 """ Script to fix references to files that were moved to subdirectories. Updates relative paths in markdown files to reflect new file locations. """ import os import re from pathlib import Path # Mapping of old paths to new paths FILE_MOVES = { # Project management files 'IMPLEMENTATION_STATUS.md': 'project_management/IMPLEMENTATION_STATUS.md', 'IMPLEMENTATION_TASK_LIST.md': 'project_management/IMPLEMENTATION_TASK_LIST.md', 'IMPLEMENTATION_READINESS_REPORT.md': 'project_management/IMPLEMENTATION_READINESS_REPORT.md', 'PHASE_1_COMPLETION_SUMMARY.md': 'project_management/PHASE_1_COMPLETION_SUMMARY.md', 'PHASE_2_PLANNING.md': 'project_management/PHASE_2_PLANNING.md', 'PHASE_2_QUICK_START.md': 'project_management/PHASE_2_QUICK_START.md', 'PHASE_2_PROGRESS_REPORT.md': 'project_management/PHASE_2_PROGRESS_REPORT.md', 'PHASE_2_CONTENT_COMPLETE.md': 'project_management/PHASE_2_CONTENT_COMPLETE.md', 'PHASE_2_FINAL_SUMMARY.md': 'project_management/PHASE_2_FINAL_SUMMARY.md', 'PROJECT_STATUS.md': 'project_management/PROJECT_STATUS.md', 'FINAL_PROJECT_STATUS.md': 'project_management/FINAL_PROJECT_STATUS.md', 'COMPREHENSIVE_FINAL_STATUS.md': 'project_management/COMPREHENSIVE_FINAL_STATUS.md', 'ALL_TASKS_COMPLETE_FINAL.md': 'project_management/ALL_TASKS_COMPLETE_FINAL.md', 'COMPLETE_PROJECT_SUMMARY.md': 'project_management/COMPLETE_PROJECT_SUMMARY.md', 'PROJECT_COMPLETION_CERTIFICATE.md': 'project_management/PROJECT_COMPLETION_CERTIFICATE.md', 'FINAL_EXECUTION_READINESS.md': 'project_management/FINAL_EXECUTION_READINESS.md', 'NEXT_STEPS_EXECUTION_SUMMARY.md': 'project_management/NEXT_STEPS_EXECUTION_SUMMARY.md', 'REMAINING_TASKS_EXECUTION_SUMMARY.md': 'project_management/REMAINING_TASKS_EXECUTION_SUMMARY.md', 'COMPLETION_REPORT.md': 'project_management/COMPLETION_REPORT.md', 'FINAL_COMPLETION_SUMMARY.md': 'project_management/FINAL_COMPLETION_SUMMARY.md', 'COMPREHENSIVE_FINAL_REPORT.md': 'project_management/COMPREHENSIVE_FINAL_REPORT.md', 'PROJECT_COMPLETE_SUMMARY.md': 'project_management/PROJECT_COMPLETE_SUMMARY.md', 'ALL_TASKS_COMPLETE.md': 'project_management/ALL_TASKS_COMPLETE.md', # FAQ files 'FAQ_General.md': 'faq/FAQ_General.md', 'FAQ_Technical.md': 'faq/FAQ_Technical.md', 'FAQ_Compliance.md': 'faq/FAQ_Compliance.md', 'FAQ_Operational.md': 'faq/FAQ_Operational.md', } def get_relative_path(from_file, to_file): """Calculate relative path from one file to another.""" from_path = Path(from_file).parent to_path = Path(to_file) return os.path.relpath(to_path, from_path) def fix_links_in_file(file_path, project_root): """Fix links in a single file.""" try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() original_content = content file_dir = os.path.dirname(file_path) # Fix markdown links: [text](path/to/file.md) for old_path, new_path in FILE_MOVES.items(): # Pattern for markdown links pattern = r'(\[([^\]]+)\]\(([^)]*' + re.escape(old_path) + r'[^)]*)\))' def replace_link(match): full_match = match.group(0) link_text = match.group(2) link_path = match.group(3) # Calculate correct relative path if link_path == old_path: # Simple case: just the filename correct_path = get_relative_path(file_path, os.path.join(project_root, new_path)) elif link_path.startswith('./') or link_path.startswith('../'): # Already a relative path, need to resolve it resolved_old = os.path.normpath(os.path.join(file_dir, link_path)) if resolved_old == os.path.join(project_root, old_path): correct_path = get_relative_path(file_path, os.path.join(project_root, new_path)) else: return full_match # Don't change if path doesn't match else: # Absolute or other format if old_path in link_path: # Replace the old path with new path link_path = link_path.replace(old_path, new_path) correct_path = get_relative_path(file_path, os.path.join(project_root, link_path)) else: return full_match return f'[{link_text}]({correct_path})' content = re.sub(pattern, replace_link, content) # Also fix plain references without markdown syntax # Pattern: `old_path` or "old_path" or 'old_path' for quote in ['`', '"', "'"]: pattern = quote + re.escape(old_path) + quote correct_path = get_relative_path(file_path, os.path.join(project_root, new_path)) content = re.sub(pattern, quote + correct_path + quote, content) if content != original_content: with open(file_path, 'w', encoding='utf-8') as f: f.write(content) return True return False except Exception as e: print(f"Error processing {file_path}: {e}") return False def main(): project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Find all markdown files md_files = [] for root, dirs, files in os.walk(project_root): # Skip .git and other hidden directories dirs[:] = [d for d in dirs if not d.startswith('.')] for file in files: if file.endswith('.md'): md_files.append(os.path.join(root, file)) print(f"Found {len(md_files)} markdown files") print("Fixing references to moved files...") fixed_count = 0 for md_file in md_files: if fix_links_in_file(md_file, project_root): fixed_count += 1 print(f"Fixed: {os.path.relpath(md_file, project_root)}") print(f"\nFixed {fixed_count} files") if __name__ == '__main__': main()