#!/usr/bin/env python3 """Audit the complete native rendering, RLV, and LSL milestone boundary.""" from __future__ import annotations import json import re import subprocess from pathlib import Path import generate_api_shims ROOT = Path(__file__).resolve().parents[1] ASSEMBLIES = { "LibreMetaverse.Rendering.Simple": (1, 6), "LibreMetaverse.Rendering.MeshFoundry": (1, 14), "LibreMetaverse.RLV": (28, 499), "LibreMetaverse.LslTools": (164, 768), } CRATES = ( "libremetaverse-rendering-simple", "libremetaverse-rendering-mesh-foundry", "libremetaverse-rlv", "libremetaverse-lsl-tools", ) RLV_GENERATED_TYPES = { "T:LibreMetaverse.RLV.IRlvActionCallbacks", "T:LibreMetaverse.RLV.IRlvQueryCallbacks", "T:LibreMetaverse.RLV.RlvAttachmentPoint", "T:LibreMetaverse.RLV.RlvGestureState", "T:LibreMetaverse.RLV.RlvGetDebugType", "T:LibreMetaverse.RLV.RlvGetEnvType", "T:LibreMetaverse.RLV.RlvPermissionsService.HoverTextLocation", "T:LibreMetaverse.RLV.RlvPermissionsService.ObjectLocation", "T:LibreMetaverse.RLV.RlvPermissionsService.TouchLocation", "T:LibreMetaverse.RLV.RlvRestrictionType", "T:LibreMetaverse.RLV.RlvWearableType", } STUB_RE = re.compile( r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(" ) PLATFORM_RE = re.compile(r"unsafe\s*\{|unsafe\s+impl|target_os\s*=\s*\"macos\"") def require_markers(path: Path, markers: tuple[str, ...]) -> None: text = path.read_text() missing = [marker for marker in markers if marker not in text] if missing: raise SystemExit(f"{path}: audit evidence missing: " + ", ".join(missing)) def catalog_assemblies() -> dict[str, dict]: catalog = json.loads((ROOT / "api" / "public-api.json").read_text()) return {assembly["identity"]["name"]: assembly for assembly in catalog["assemblies"]} def member_is_native(item: dict, member: dict) -> bool: doc_id = item["doc_id"] return ( doc_id in generate_api_shims.NATIVE_TYPES or doc_id in generate_api_shims.NATIVE_GENERATED_TYPES or ( doc_id in generate_api_shims.NATIVE_DECLARATIONS and member["kind"] in {"field", "constant"} ) or generate_api_shims.native_member_body(member["doc_id"]) is not None ) def check_catalog_ownership() -> None: assemblies = catalog_assemblies() native_types = ( set(generate_api_shims.NATIVE_TYPES) | set(generate_api_shims.NATIVE_DECLARATIONS) | set(generate_api_shims.NATIVE_GENERATED_TYPES) ) for name, expected in ASSEMBLIES.items(): assembly = assemblies[name] actual = ( len(assembly["types"]), sum(len(item["members"]) for item in assembly["types"]), ) if actual != expected: raise SystemExit(f"{name}: expected catalog counts {expected}, found {actual}") missing_types = [ item["doc_id"] for item in assembly["types"] if item["doc_id"] not in native_types ] missing_members = [ member["doc_id"] for item in assembly["types"] for member in item["members"] if not member_is_native(item, member) ] if missing_types or missing_members: raise SystemExit( f"{name}: non-native types={missing_types}, members={missing_members}" ) generated_rlv_types = { doc_id for doc_id in generate_api_shims.NATIVE_GENERATED_TYPES if doc_id.startswith("T:LibreMetaverse.RLV.") } if generated_rlv_types != RLV_GENERATED_TYPES: raise SystemExit("milestone 10 generated-native RLV declaration set changed") def check_sources_and_manifests() -> None: offenders: list[str] = [] platform_offenders: list[str] = [] for crate in CRATES: crate_root = ROOT / "crates" / crate manifest = (crate_root / "Cargo.toml").read_text() if "[features]" in manifest: raise SystemExit(f"{crate}: native implementation must be active without a feature") if re.search(r"\b(?:dotnet|csc|mcs)\b", manifest, re.IGNORECASE): raise SystemExit(f"{crate}: manifest depends on a C#/.NET tool") for source in (crate_root / "src").glob("*.rs"): text = source.read_text() if STUB_RE.search(text): offenders.append(str(source.relative_to(ROOT))) if PLATFORM_RE.search(text): platform_offenders.append(str(source.relative_to(ROOT))) if offenders: raise SystemExit("milestone 10 owned Rust stubs remain: " + ", ".join(offenders)) if platform_offenders: raise SystemExit( "milestone 10 unsafe or macOS-only sources remain: " + ", ".join(platform_offenders) ) def check_parity() -> None: catalog = json.loads((ROOT / "tests" / "upstream-tests.json").read_text()) related = [ test for test in catalog["tests"] if test["source"].startswith("LibreMetaverse.Tests/RLV/") or test["source"].startswith("LibreMetaverse.Rendering.Tests/") ] if len(related) != 691: raise SystemExit(f"milestone 10 expected 691 upstream parity cases, found {len(related)}") bad = [ test["id"] for test in related if test["status"] != "translated" or test.get("semantic_review") != "reviewed" ] if bad: raise SystemExit("milestone 10 parity cases are not reviewed: " + ", ".join(bad)) missing = sorted( { test["rust_file"] for test in related if not (ROOT / test["rust_file"]).is_file() } ) if missing: raise SystemExit("milestone 10 translated files are missing: " + ", ".join(missing)) def check_contract_evidence() -> None: require_markers( ROOT / "crates" / "libremetaverse-rendering-simple" / "src" / "simple_renderer.rs", ("MAX_FACE_VERTICES", "checked_add", "u16::try_from"), ) require_markers( ROOT / "crates" / "libremetaverse-rendering-mesh-foundry" / "src" / "mesh_foundry.rs", ("MAX_ASSET_BYTES", "MAX_TOTAL_VERTICES", "MAX_JOINTS", "checked_add"), ) require_markers( ROOT / "crates" / "libremetaverse-rlv" / "src" / "service.rs", ( "MAX_RLV_MESSAGE_BYTES", "MAX_RLV_COMMANDS", "Arc", "Arc", "throw_if_cancellation_requested", ), ) require_markers( ROOT / "crates" / "libremetaverse-lsl-tools" / "src" / "parser.rs", ("MAX_PARSER_STATES", "MAX_PARSER_STACK", "MAX_PARSER_STEPS", "MAX_RECOVERY_ERRORS"), ) require_markers( ROOT / "crates" / "libremetaverse-lsl-tools" / "src" / "lexer.rs", ("MAX_SOURCE_UNITS", "MAX_TOKEN_UNITS"), ) require_markers( ROOT / "tests" / "compat" / "tests" / "milestone_10_integration.rs", ( "native_extensions_consume_core_models_and_preserve_service_state", "SimpleRenderer", "MeshFoundry", "generated_parser", "RlvHarness", ), ) require_markers( ROOT / "docs" / "extension-milestone-gate.md", ( "Choosing an extension", "Rendering migration", "RLV host integration and teardown", "LSL tooling migration", "194 types", "1,287 members", "tools/test_milestone_10.py", "ubuntu-latest", ), ) require_markers( ROOT / "api" / "SHIM-COVERAGE.md", tuple( f"`{name}` | {types} | {members} | native implementation" for name, (types, members) in ASSEMBLIES.items() ), ) def check_generation_and_ci() -> None: subprocess.run( ["python3", "tools/generate_rust_mapping.py", "--check"], cwd=ROOT, check=True ) subprocess.run( ["python3", "tools/generate_api_shims.py", "--check"], cwd=ROOT, check=True ) subprocess.run( ["python3", "tools/generate_lsl_tables.py", "--check"], cwd=ROOT, check=True ) workflow = ROOT / ".gitea" / "workflows" / "ci.yml" require_markers( workflow, ( "required-gate", "runs-on: ubuntu-latest", ), ) if re.search(r"runs-on:\s*(?:macos|windows)", workflow.read_text(), re.IGNORECASE): raise SystemExit("milestone 10 workflow is not ubuntu-only") def main() -> None: check_catalog_ownership() check_sources_and_manifests() check_parity() check_contract_evidence() check_generation_and_ci() print( "milestone 10 audit: 194 types and 1,287 members are native; no owned " "stubs remain; bounds, callback teardown, 691 reviewed parity cases, " "integration, migration docs, deterministic generation, and ubuntu-only CI are present" ) if __name__ == "__main__": main()