|
| 1 | +"""Script to split grammar.py into modular files. |
| 2 | +
|
| 3 | +This script divides src/tnfr/operators/grammar.py (2,921 lines) into |
| 4 | +specialized modules plus a facade for backward compatibility. |
| 5 | +
|
| 6 | +CRITICAL: This is the most important file in TNFR. Handle with extreme care. |
| 7 | +""" |
| 8 | + |
| 9 | +import os |
| 10 | +import shutil |
| 11 | + |
| 12 | +# Read the original file |
| 13 | +with open("src/tnfr/operators/grammar.py", "r", encoding="utf-8") as f: |
| 14 | + lines = f.readlines() |
| 15 | + |
| 16 | +# Common header for all modules |
| 17 | +def make_header(title: str, description: str) -> list[str]: |
| 18 | + return [ |
| 19 | + f'"""TNFR Grammar: {title}\n', |
| 20 | + "\n", |
| 21 | + f"{description}\n", |
| 22 | + "\n", |
| 23 | + 'Terminology (TNFR semantics):\n', |
| 24 | + '- "node" == resonant locus (structural coherence site); kept for NetworkX compatibility\n', |
| 25 | + '- Future semantic aliasing ("locus") must preserve public API stability\n', |
| 26 | + '"""\n', |
| 27 | + "\n", |
| 28 | + "from __future__ import annotations\n", |
| 29 | + "\n", |
| 30 | + ] |
| 31 | + |
| 32 | +# Extract header (lines 1-85) |
| 33 | +header_lines = lines[0:85] |
| 34 | + |
| 35 | +# Define sections (1-indexed, inclusive ranges) |
| 36 | +sections = { |
| 37 | + "grammar_types.py": { |
| 38 | + "range": (86, 567), |
| 39 | + "title": "Types and Exceptions", |
| 40 | + "desc": "Enums, exception classes, and validation result types for TNFR grammar.", |
| 41 | + }, |
| 42 | + "grammar_context.py": { |
| 43 | + "range": (568, 699), |
| 44 | + "title": "Grammar Context", |
| 45 | + "desc": "Runtime context for grammar validation and operator application tracking.", |
| 46 | + }, |
| 47 | + "grammar_core.py": { |
| 48 | + "range": (700, 1581), |
| 49 | + "title": "Core Grammar Validator", |
| 50 | + "desc": "GrammarValidator class - central validation engine for all grammar rules U1-U6.", |
| 51 | + }, |
| 52 | + "grammar_u6.py": { |
| 53 | + "range": (1582, 1712), |
| 54 | + "title": "U6 Structural Potential Validation", |
| 55 | + "desc": "U6: STRUCTURAL POTENTIAL CONFINEMENT - Validate Δ Φ_s < 2.0 escape threshold.", |
| 56 | + }, |
| 57 | + "grammar_telemetry.py": { |
| 58 | + "range": (1765, 2011), |
| 59 | + "title": "U6 Telemetry Functions", |
| 60 | + "desc": "Phase gradient, phase curvature, and coherence length telemetry for U6 validation.", |
| 61 | + }, |
| 62 | + "grammar_application.py": { |
| 63 | + "range": (2017, 2190), |
| 64 | + "title": "Grammar Application", |
| 65 | + "desc": "Functions for applying operators with grammar enforcement at runtime.", |
| 66 | + }, |
| 67 | + "grammar_patterns.py": { |
| 68 | + "range": (2191, 2921), |
| 69 | + "title": "Sequence Pattern Recognition", |
| 70 | + "desc": "Sequence validation, parsing, pattern recognition, and optimization helpers.", |
| 71 | + }, |
| 72 | +} |
| 73 | + |
| 74 | +# Special handling: validate_grammar function (lines 1718-1759) goes in its own module |
| 75 | +sections["grammar_validate.py"] = { |
| 76 | + "range": (1713, 1759), |
| 77 | + "title": "Main Validation Entry Point", |
| 78 | + "desc": "Primary validate_grammar() function - the main public API for grammar checking.", |
| 79 | +} |
| 80 | + |
| 81 | +print("🔨 Starting grammar.py split...") |
| 82 | +print(f"📄 Original file: {len(lines)} lines\n") |
| 83 | + |
| 84 | +# Create each module |
| 85 | +for module_name, spec in sorted(sections.items()): |
| 86 | + start, end = spec["range"] |
| 87 | + title = spec["title"] |
| 88 | + desc = spec["desc"] |
| 89 | + |
| 90 | + module_lines = [] |
| 91 | + |
| 92 | + # Add header |
| 93 | + module_lines.extend(make_header(title, desc)) |
| 94 | + |
| 95 | + # Add necessary imports based on module |
| 96 | + if module_name == "grammar_types.py": |
| 97 | + module_lines.extend([ |
| 98 | + "from enum import Enum\n", |
| 99 | + "from typing import TYPE_CHECKING, Any, List, Mapping, Sequence, Tuple\n", |
| 100 | + "\n", |
| 101 | + "if TYPE_CHECKING:\n", |
| 102 | + " from ..types import NodeId, TNFRGraph, Glyph\n", |
| 103 | + " from .definitions import Operator\n", |
| 104 | + "else:\n", |
| 105 | + " NodeId = Any\n", |
| 106 | + " TNFRGraph = Any\n", |
| 107 | + " from ..types import Glyph\n", |
| 108 | + "\n", |
| 109 | + "from ..validation.base import ValidationOutcome\n", |
| 110 | + "\n", |
| 111 | + ]) |
| 112 | + elif module_name == "grammar_context.py": |
| 113 | + module_lines.extend([ |
| 114 | + "from typing import Any\n", |
| 115 | + "\n", |
| 116 | + "from .grammar_types import GrammarConfigurationError\n", |
| 117 | + "\n", |
| 118 | + ]) |
| 119 | + elif module_name == "grammar_core.py": |
| 120 | + module_lines.extend([ |
| 121 | + "from typing import TYPE_CHECKING, Any\n", |
| 122 | + "\n", |
| 123 | + "if TYPE_CHECKING:\n", |
| 124 | + " from ..types import NodeId, TNFRGraph, Glyph\n", |
| 125 | + "else:\n", |
| 126 | + " NodeId = Any\n", |
| 127 | + " TNFRGraph = Any\n", |
| 128 | + " from ..types import Glyph\n", |
| 129 | + "\n", |
| 130 | + "from .grammar_types import (\n", |
| 131 | + " StructuralGrammarError,\n", |
| 132 | + " RepeatWindowError,\n", |
| 133 | + " MutationPreconditionError,\n", |
| 134 | + " TholClosureError,\n", |
| 135 | + " TransitionCompatibilityError,\n", |
| 136 | + " StructuralPotentialConfinementError,\n", |
| 137 | + " record_grammar_violation,\n", |
| 138 | + ")\n", |
| 139 | + "from .grammar_context import GrammarContext\n", |
| 140 | + "from ..config.operator_names import (\n", |
| 141 | + " BIFURCATION_WINDOWS,\n", |
| 142 | + " CANONICAL_OPERATOR_NAMES,\n", |
| 143 | + " DESTABILIZERS_MODERATE,\n", |
| 144 | + " DESTABILIZERS_STRONG,\n", |
| 145 | + " DESTABILIZERS_WEAK,\n", |
| 146 | + " INTERMEDIATE_OPERATORS,\n", |
| 147 | + " SELF_ORGANIZATION,\n", |
| 148 | + " SELF_ORGANIZATION_CLOSURES,\n", |
| 149 | + " VALID_END_OPERATORS,\n", |
| 150 | + " VALID_START_OPERATORS,\n", |
| 151 | + ")\n", |
| 152 | + "from ..validation.compatibility import (\n", |
| 153 | + " CompatibilityLevel,\n", |
| 154 | + " get_compatibility_level,\n", |
| 155 | + ")\n", |
| 156 | + "\n", |
| 157 | + ]) |
| 158 | + else: |
| 159 | + # Other modules get minimal imports |
| 160 | + module_lines.extend([ |
| 161 | + "from typing import Any\n", |
| 162 | + "\n", |
| 163 | + ]) |
| 164 | + |
| 165 | + # Add content |
| 166 | + module_lines.extend(lines[start-1:end]) |
| 167 | + |
| 168 | + # Write module |
| 169 | + with open(f"src/tnfr/operators/{module_name}", "w", encoding="utf-8") as f: |
| 170 | + f.writelines(module_lines) |
| 171 | + |
| 172 | + print(f"✅ Created {module_name:30s} ({end-start+1:4d} lines)") |
| 173 | + |
| 174 | +# Create facade grammar.py |
| 175 | +print("\n📦 Creating facade grammar.py...") |
| 176 | + |
| 177 | +facade_lines = [] |
| 178 | +facade_lines.extend(header_lines) |
| 179 | +facade_lines.append("\n") |
| 180 | +facade_lines.append("# Re-export all grammar components for backward compatibility\n") |
| 181 | +facade_lines.append("\n") |
| 182 | +facade_lines.append("# Types and exceptions\n") |
| 183 | +facade_lines.append("from .grammar_types import (\n") |
| 184 | +facade_lines.append(" StructuralPattern,\n") |
| 185 | +facade_lines.append(" StructuralGrammarError,\n") |
| 186 | +facade_lines.append(" RepeatWindowError,\n") |
| 187 | +facade_lines.append(" MutationPreconditionError,\n") |
| 188 | +facade_lines.append(" TholClosureError,\n") |
| 189 | +facade_lines.append(" TransitionCompatibilityError,\n") |
| 190 | +facade_lines.append(" StructuralPotentialConfinementError,\n") |
| 191 | +facade_lines.append(" SequenceSyntaxError,\n") |
| 192 | +facade_lines.append(" SequenceValidationResult,\n") |
| 193 | +facade_lines.append(" GrammarConfigurationError,\n") |
| 194 | +facade_lines.append(" record_grammar_violation,\n") |
| 195 | +facade_lines.append(" glyph_function_name,\n") |
| 196 | +facade_lines.append(" function_name_to_glyph,\n") |
| 197 | +facade_lines.append(")\n") |
| 198 | +facade_lines.append("\n") |
| 199 | +facade_lines.append("# Context\n") |
| 200 | +facade_lines.append("from .grammar_context import GrammarContext\n") |
| 201 | +facade_lines.append("\n") |
| 202 | +facade_lines.append("# Core validator\n") |
| 203 | +facade_lines.append("from .grammar_core import GrammarValidator\n") |
| 204 | +facade_lines.append("\n") |
| 205 | +facade_lines.append("# U6 validation\n") |
| 206 | +facade_lines.append("from .grammar_u6 import validate_structural_potential_confinement\n") |
| 207 | +facade_lines.append("\n") |
| 208 | +facade_lines.append("# Main validation entry point\n") |
| 209 | +facade_lines.append("from .grammar_validate import validate_grammar\n") |
| 210 | +facade_lines.append("\n") |
| 211 | +facade_lines.append("# Telemetry\n") |
| 212 | +facade_lines.append("from .grammar_telemetry import (\n") |
| 213 | +facade_lines.append(" warn_phase_gradient_telemetry,\n") |
| 214 | +facade_lines.append(" warn_phase_curvature_telemetry,\n") |
| 215 | +facade_lines.append(" warn_coherence_length_telemetry,\n") |
| 216 | +facade_lines.append(")\n") |
| 217 | +facade_lines.append("\n") |
| 218 | +facade_lines.append("# Application\n") |
| 219 | +facade_lines.append("from .grammar_application import (\n") |
| 220 | +facade_lines.append(" apply_glyph_with_grammar,\n") |
| 221 | +facade_lines.append(" on_applied_glyph,\n") |
| 222 | +facade_lines.append(" enforce_canonical_grammar,\n") |
| 223 | +facade_lines.append(")\n") |
| 224 | +facade_lines.append("\n") |
| 225 | +facade_lines.append("# Pattern recognition\n") |
| 226 | +facade_lines.append("from .grammar_patterns import (\n") |
| 227 | +facade_lines.append(" validate_sequence,\n") |
| 228 | +facade_lines.append(" parse_sequence,\n") |
| 229 | +facade_lines.append(" SequenceValidationResultWithHealth,\n") |
| 230 | +facade_lines.append(" validate_sequence_with_health,\n") |
| 231 | +facade_lines.append(" recognize_il_sequences,\n") |
| 232 | +facade_lines.append(" optimize_il_sequence,\n") |
| 233 | +facade_lines.append(" suggest_il_sequence,\n") |
| 234 | +facade_lines.append(")\n") |
| 235 | +facade_lines.append("\n") |
| 236 | +facade_lines.append("__all__ = [\n") |
| 237 | +facade_lines.append(' # Types\n') |
| 238 | +facade_lines.append(' "StructuralPattern",\n') |
| 239 | +facade_lines.append(' # Exceptions\n') |
| 240 | +facade_lines.append(' "StructuralGrammarError",\n') |
| 241 | +facade_lines.append(' "RepeatWindowError",\n') |
| 242 | +facade_lines.append(' "MutationPreconditionError",\n') |
| 243 | +facade_lines.append(' "TholClosureError",\n') |
| 244 | +facade_lines.append(' "TransitionCompatibilityError",\n') |
| 245 | +facade_lines.append(' "StructuralPotentialConfinementError",\n') |
| 246 | +facade_lines.append(' "SequenceSyntaxError",\n') |
| 247 | +facade_lines.append(' "GrammarConfigurationError",\n') |
| 248 | +facade_lines.append(' # Validation\n') |
| 249 | +facade_lines.append(' "SequenceValidationResult",\n') |
| 250 | +facade_lines.append(' "validate_grammar",\n') |
| 251 | +facade_lines.append(' "validate_sequence",\n') |
| 252 | +facade_lines.append(' "parse_sequence",\n') |
| 253 | +facade_lines.append(' "validate_sequence_with_health",\n') |
| 254 | +facade_lines.append(' # U6\n') |
| 255 | +facade_lines.append(' "validate_structural_potential_confinement",\n') |
| 256 | +facade_lines.append(' # Core\n') |
| 257 | +facade_lines.append(' "GrammarContext",\n') |
| 258 | +facade_lines.append(' "GrammarValidator",\n') |
| 259 | +facade_lines.append(' # Application\n') |
| 260 | +facade_lines.append(' "apply_glyph_with_grammar",\n') |
| 261 | +facade_lines.append(' "on_applied_glyph",\n') |
| 262 | +facade_lines.append(' "enforce_canonical_grammar",\n') |
| 263 | +facade_lines.append(' # Helpers\n') |
| 264 | +facade_lines.append(' "glyph_function_name",\n') |
| 265 | +facade_lines.append(' "function_name_to_glyph",\n') |
| 266 | +facade_lines.append(' "record_grammar_violation",\n') |
| 267 | +facade_lines.append(' "SequenceValidationResultWithHealth",\n') |
| 268 | +facade_lines.append(' "recognize_il_sequences",\n') |
| 269 | +facade_lines.append(' "optimize_il_sequence",\n') |
| 270 | +facade_lines.append(' "suggest_il_sequence",\n') |
| 271 | +facade_lines.append(' # Telemetry\n') |
| 272 | +facade_lines.append(' "warn_phase_gradient_telemetry",\n') |
| 273 | +facade_lines.append(' "warn_phase_curvature_telemetry",\n') |
| 274 | +facade_lines.append(' "warn_coherence_length_telemetry",\n') |
| 275 | +facade_lines.append("]\n") |
| 276 | + |
| 277 | +# Backup original |
| 278 | +shutil.move("src/tnfr/operators/grammar.py", "src/tnfr/operators/grammar.py.old") |
| 279 | + |
| 280 | +# Write facade |
| 281 | +with open("src/tnfr/operators/grammar.py", "w", encoding="utf-8") as f: |
| 282 | + f.writelines(facade_lines) |
| 283 | + |
| 284 | +print("✅ Created grammar.py facade") |
| 285 | +print("✅ Renamed original to grammar.py.old") |
| 286 | +print("\n✨ Split complete!") |
| 287 | +print("\n⚠️ CRITICAL: Run full test suite to verify!") |
| 288 | +print(" python -m pytest tests/ -q --tb=short") |
0 commit comments