#!/usr/bin/env python3 """Audit issue 59's native non-movement AgentManager 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" / "agent_manager.rs" GESTURE = ROOT / "crates" / "libremetaverse" / "src" / "gesture.rs" DOC = ROOT / "docs" / "agent-manager.md" STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(") REQUIRED_TYPES = { "T:LibreMetaverse.AgentManager", "T:LibreMetaverse.InstantMessage", "T:LibreMetaverse.ChatSessionMember", "T:LibreMetaverse.Assets.AssetGesture", "T:LibreMetaverse.Assets.GestureStepAnimation", "T:LibreMetaverse.Assets.GestureStepChat", "T:LibreMetaverse.Assets.GestureStepEOF", "T:LibreMetaverse.Assets.GestureStepSound", "T:LibreMetaverse.Assets.GestureStepWait", } REQUIRED_MEMBERS = { "E:LibreMetaverse.AgentManager.IM", "E:LibreMetaverse.AgentManager.ChatFromSimulator", "E:LibreMetaverse.AgentManager.MuteListUpdated", "E:LibreMetaverse.AgentManager.NavMeshStatusUpdate", "M:LibreMetaverse.AgentManager.Chat(System.String,System.Int32,LibreMetaverse.ChatType,System.Boolean)", "M:LibreMetaverse.AgentManager.PlayGestureAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.RetrieveInstantMessagesAsync(System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.GetAgentPreferencesAsync(System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.GetAgentExperiencesAsync(System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.GetAttachmentResourcesAsync(System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.GetViewerBenefitsAsync(System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.RequestMuteList", "M:LibreMetaverse.AgentManager.RequestNavMeshGenerationStatusAsync(System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.RequestNavMeshRebakeAsync(System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.SendViewerStatsAsync(LibreMetaverse.Messages.Linden.ViewerStatsMessage,System.Threading.CancellationToken)", "M:LibreMetaverse.AgentManager.UpdateProfileAsync(LibreMetaverse.Avatar.AvatarProperties,System.Threading.CancellationToken)", } def require_markers(path: Path, markers: tuple[str, ...]) -> None: source = path.read_text() missing = [marker for marker in markers if marker not in source] if missing: raise SystemExit(f"{path.name}: audit evidence missing: " + ", ".join(missing)) def main() -> None: native_types = ( generate_api_shims.NATIVE_TYPES.keys() | generate_api_shims.NATIVE_DECLARATIONS.keys() ) missing_types = sorted(REQUIRED_TYPES - native_types) if missing_types: raise SystemExit("issue 59 native types missing: " + ", ".join(missing_types)) missing_members = sorted(REQUIRED_MEMBERS - generate_api_shims.NATIVE_MEMBER_BODIES.keys()) if missing_members: raise SystemExit("issue 59 native members missing: " + ", ".join(missing_members)) for path in (SOURCE, GESTURE): if STUB_RE.search(path.read_text()): raise SystemExit(f"issue 59 owned Rust stubs remain in {path.name}") require_markers( SOURCE, ( "ChatterBoxSessionAgentListUpdates", "MuteListUpdate", "NavMeshStatusUpdate", "MAX_GESTURE_ASSET_BYTES", "MAX_MUTE_LIST_BYTES", "fake_grid_serves_gesture_capability_and_observes_udp_actions", "instant_message_debug_redacts_message_and_binary_payload", "callbacks are not invoked", ), ) require_markers(GESTURE, ("gesture_v2_roundtrip_preserves_all_step_payloads", "decode")) require_markers(DOC, ("RequestXfer", "ViewerAsset", "callbacks therefore run without")) print( "issue 59 audit: native AgentManager mappings, bounded gesture/mute transfers, " "lock-free callback evidence, documentation, and offline fake-grid coverage are present" ) if __name__ == "__main__": main()