Implement appearance baking pipeline (#66)
Some checks failed
Native code generation / deterministic (push) Failing after 2m18s
Imaging and meshing gate / native (push) Failing after 1m28s
Native Rust workspace compile / compile (push) Failing after 58s

This commit is contained in:
2026-08-10 10:33:29 +00:00
parent a9927fcfcb
commit b1f60db3d6
17 changed files with 3487 additions and 249 deletions

View File

@@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""Audit issue 66's appearance baking and initial-outfit boundary."""
from __future__ import annotations
from pathlib import Path
import re
import generate_api_shims
ROOT = Path(__file__).resolve().parents[1]
APPEARANCE = ROOT / "crates" / "libremetaverse" / "src" / "appearance_manager.rs"
BAKER = ROOT / "crates" / "libremetaverse" / "src" / "appearance_baker.rs"
PROVIDER = ROOT / "crates" / "libremetaverse" / "src" / "baking_texture_provider.rs"
OUTFIT = ROOT / "crates" / "libremetaverse" / "src" / "initial_outfit.rs"
ASSETS = ROOT / "crates" / "libremetaverse" / "src" / "asset_models.rs"
BAKER_TESTS = ROOT / "crates" / "libremetaverse" / "src" / "appearance_baker_semantics.rs"
VISUAL_TESTS = ROOT / "crates" / "libremetaverse" / "tests" / "generated_catalogs.rs"
COMPAT = ROOT / "tests" / "compat" / "tests" / "appearance_semantics.rs"
DOC = ROOT / "docs" / "appearance.md"
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
REQUIRED_TYPES = {
"T:LibreMetaverse.AppearanceManager",
"T:LibreMetaverse.Appearance.InitialOutfit",
"T:LibreMetaverse.Appearance.InitialOutfit.InitialOutfitProgress",
"T:LibreMetaverse.Appearance.InitialOutfitHandler",
"T:LibreMetaverse.GridClientBakingTextureProvider",
"T:LibreMetaverse.Imaging.Baker",
}
REQUIRED_MEMBERS = {
"M:LibreMetaverse.AppearanceManager.DecodeWearableParams(LibreMetaverse.AppearanceManager.WearableData,LibreMetaverse.AppearanceManager.TextureData[]@)",
"M:LibreMetaverse.AppearanceManager.MakeAppearancePacket",
"M:LibreMetaverse.AppearanceManager.RequestCachedBakes",
"M:LibreMetaverse.AppearanceManager.RequestSetAppearance(System.Boolean)",
"M:LibreMetaverse.AppearanceManager.ServerBakingRegion",
"M:LibreMetaverse.GridClientBakingTextureProvider.RequestTextureAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)",
"M:LibreMetaverse.Imaging.Baker.Bake",
"M:LibreMetaverse.Imaging.Baker.LoadResourceLayer(System.String)",
"M:LibreMetaverse.Appearance.InitialOutfit.CopyFolderAsync(LibreMetaverse.InventoryFolder,LibreMetaverse.UUID,System.Threading.CancellationToken,System.IProgress{LibreMetaverse.Appearance.InitialOutfit.InitialOutfitProgress})",
"M:LibreMetaverse.Appearance.InitialOutfit.SetInitialOutfitAsync(System.String,System.Threading.CancellationToken,System.IProgress{LibreMetaverse.Appearance.InitialOutfit.InitialOutfitProgress})",
}
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 = set(generate_api_shims.NATIVE_TYPES) | set(generate_api_shims.NATIVE_DECLARATIONS)
missing_types = sorted(REQUIRED_TYPES - native)
if missing_types:
raise SystemExit("issue 66 native types missing: " + ", ".join(missing_types))
missing_members = sorted(REQUIRED_MEMBERS - set(generate_api_shims.NATIVE_MEMBER_BODIES))
if missing_members:
raise SystemExit("issue 66 native members missing: " + ", ".join(missing_members))
for source in (APPEARANCE, BAKER, PROVIDER, OUTFIT, ASSETS):
if STUB_RE.search(source.read_text()):
raise SystemExit(f"issue 66 owned Rust stubs remain in {source.name}")
require_markers(APPEARANCE, (
"baked_texture_hash", "wearable_bake_map", "AgentCachedTextureResponse",
"AgentWearablesRequest", "AgentWearablesUpdate", "MAX_COF_ENTRIES",
"RebakeAvatarTextures", "tokio::sync::Semaphore::new(5)",
"tokio::sync::Semaphore::new(6)", "native_server_bake",
"old_visual_parameters", "appearance_packet_contains_all_bakes",
"legacy_wearables_packet_preserves_valid_item_asset_and_type_fields",
))
require_markers(BAKER, (
"CLASSIC_BAKE_SIZE", "EYE_BAKE_SIZE", "self.textures.len() >= 60", "head_color.tga",
"head_skingrain.tga", "apply_parameter_mask", "output.bump",
"native_deep_clone", '#[cfg(feature = "jpeg2000")]',
))
require_markers(PROVIDER, ("ClientWeakHandle", "request_image", "native_decode_image"))
require_markers(OUTFIT, (
"MAX_FOLDERS", "Phase::Counting", "Phase::Copying", "Phase::Applying",
"cleanup_folder", "compare_exchange", "native_replace_outfit",
"handler_dispose_is_idempotent",
))
require_markers(ASSETS, (
"native_from_asset", "parameters ", "textures ",
"wearable_parser_preserves_parameters_and_texture_indices",
))
require_markers(BAKER_TESTS, ("parity-case", "image.red[0]", "image.bump[0]"))
require_markers(VISUAL_TESTS, ("visual_catalog_matches_the_pinned_character_fixture", "672", "253"))
require_markers(COMPAT, ("baked_texture_hash", "wearable_bake_map", "texture_provider"))
require_markers(DOC, (
"all 11", "downloads and six baked-texture uploads",
"Counting`, `Copying`, `Applying`, then `Complete", "256-node",
"big-endian", "218 normal or 251", "UpdateAvatarAppearance",
))
print(
"issue 66 audit: native bake composition, bounded texture transport, cache/server/local "
"appearance paths, transactional initial outfit, documentation, and focused evidence are present"
)
if __name__ == "__main__":
main()