#!/usr/bin/env python3 """Audit issue 63's native AISv3 capability and reconciliation boundary.""" from __future__ import annotations from pathlib import Path import re import generate_api_shims ROOT = Path(__file__).resolve().parents[1] SOURCE = ROOT / "crates" / "libremetaverse" / "src" / "inventory_ais.rs" HTTP = ROOT / "crates" / "libremetaverse" / "src" / "caps_http.rs" INVENTORY = ROOT / "crates" / "libremetaverse" / "src" / "inventory.rs" NATIVE_TESTS = ROOT / "crates" / "libremetaverse" / "src" / "inventory_ais_internal_semantics.rs" COMPAT_TESTS = ROOT / "tests" / "compat" / "tests" / "inventory_ais_semantics.rs" DOC = ROOT / "docs" / "inventory.md" MAPPING = ROOT / "api" / "RUST-MAPPING.tsv" STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(") 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.name}: audit evidence missing: " + ", ".join(missing)) def main() -> None: native_types = generate_api_shims.NATIVE_TYPES | generate_api_shims.NATIVE_DECLARATIONS for type_id in ("T:LibreMetaverse.AISResponseMeta", "T:LibreMetaverse.InventoryAISClient"): if type_id not in native_types: raise SystemExit(f"issue 63 native type missing: {type_id}") mapped = generate_api_shims.NATIVE_MEMBER_BODIES required = set() for row in MAPPING.read_text().splitlines()[1:]: doc_id = row.split("\t", 1)[0] if doc_id.startswith(("M:LibreMetaverse.InventoryAISClient.", "P:LibreMetaverse.InventoryAISClient.")): required.add(doc_id) missing = sorted(required - mapped.keys()) if missing: raise SystemExit("issue 63 native members missing: " + ", ".join(missing)) for member in ( "P:LibreMetaverse.GridClient.AisClient", "P:LibreMetaverse.GridClient.AisClient#set", ): if member not in mapped: raise SystemExit(f"issue 63 GridClient member missing: {member}") if STUB_RE.search(SOURCE.read_text()): raise SystemExit("issue 63 owned Rust stubs remain in inventory_ais.rs") require_markers( SOURCE, ( '"COPY"', '"Destination"', '"application/llsd+xml"', "MAX_FOLDER_DEPTH_REQUEST", "MAX_AIS_OBJECTS", "Error::Cancelled", "parse_meta_map", "native_reconcile_ais", ), ) require_markers(HTTP, ("send_custom", "send_with_headers")) require_markers(INVENTORY, ("native_apply_ais_batch", "detached candidate")) require_markers( NATIVE_TESTS, ( "records_exact_ais_verbs_paths_headers_and_llsd_payloads", "malformed_and_cancelled_responses_leave_store_unchanged", "partially_valid_response_is_rejected_before_any_reconciliation", "response_metadata_reconciles_removals_and_folder_versions_together", ), ) require_markers( COMPAT_TESTS, ( "parse_links_object_asset_results_in_attachment_type_and_parses_fields", "parse_embedded_combines_items_and_links", "move_category_links_returns_completed_future", ), ) require_markers( DOC, ( "Inventory API v3", "InventoryAPIv3", "LibraryAPIv3", "Destination", "atomically", "UDP fallback", ), ) print( "issue 63 audit: AIS endpoints, LLSD parsing, COPY headers, bounded atomic " "reconciliation, documentation, and focused tests are present" ) if __name__ == "__main__": main()