""" AFI conformance — same @client fixture, same Mizan IR (KDL), both adapters. Gates that mizan-django and mizan-fastapi emit byte-equivalent IR for the same registered functions. If this passes, the codegen produces identical TypeScript output regardless of backend (codegen is deterministic over IR input). Substrate-level gate, not e2e. Catches adapter symmetry problems — type-introspection divergence, ordering non-determinism — without running a real frontend or backend. """ from __future__ import annotations import os import subprocess import sys from pathlib import Path import pytest HERE = Path(__file__).parent DJANGO_MANAGE = HERE / "django_app" / "manage.py" def _fetch_django_ir() -> str: """Spawn Django's management command and parse stdout as KDL.""" result = subprocess.run( [sys.executable, str(DJANGO_MANAGE), "export_mizan_ir"], capture_output=True, text=True, check=False, env={**os.environ, "PYTHONDONTWRITEBYTECODE": "1"}, ) if result.returncode != 0: pytest.fail( f"export_mizan_ir failed:\nstdout:\n{result.stdout}\nstderr:\n{result.stderr}", ) return result.stdout def _fetch_fastapi_ir() -> str: """Build the FastAPI app inline (fresh registry) and call build_ir().""" sys.path.insert(0, str(HERE)) try: from mizan_core.registry import clear_registry from mizan_core.ir import build_ir from fastapi_app import make_app clear_registry() make_app() return build_ir() finally: sys.path.remove(str(HERE)) @pytest.fixture(scope="module") def ir_pair() -> tuple[str, str]: return _fetch_django_ir(), _fetch_fastapi_ir() class IRParityTests: """The Mizan IR is the contract — both backends must emit the same KDL.""" def test_ir_bytes_match(self, ir_pair): django, fastapi = ir_pair assert django == fastapi, ( "Django and FastAPI emit divergent Mizan IR for the same " "registered functions. Substrate gate is now red." )