Skip to content

Versioned Release Export

off-cmd edited this page Sep 16, 2026 · 1 revision

Versioned Release Export

Relevant source files

The following files were used as context for generating this wiki page:

Purpose and Scope

This page details the implementation of versioned family and profile exports within the clarity pipeline, defined primarily in clarity/packaging/release.py. The release module takes processed and packaged Penumbra textures, validates them against source database states, applies profile and generation tier policies, structures them into a hierarchical CATALOG taxonomy, and writes immutable versioned distribution bundles protected by staging directories (.building) and release version keys.

Sources: clarity/packaging/release.py:1-16


7.2.1 CATALOG Taxonomy and Hierarchy

The release exporter structures texture outputs into a hierarchical catalog taxonomy defined by the CATALOG constant in clarity/packaging/release.py. The taxonomy groups family codes into broad human-readable categories (Human, Gear, Monsters and Demihumans, World, UI and HUD) and sub-families with descriptive UI titles.

Title: Catalog Taxonomy to Code Entity Mapping
graph TD
    CAT["CATALOG Taxonomy Tuple\n(clarity/packaging/release.py)"] --> Human["Human Category\n- human-face\n- human-body\n- human-zear\n- human-tail"]
    CAT --> Gear["Gear Category\n- equipment\n- accessory\n- weapon"]
    CAT --> Monsters["Monsters Category\n- monster\n- demihuman"]
    CAT --> World["World Category\n- bg, bgcommon, bg-hou\n- bg-ind, bgcommon-hou, bgcommon-mji"]
    CAT --> UI["UI and HUD Category\n- ui-icon, ui-uld, ui-other, common"]
    
    Human --> RT["requested_tier(family, role, path, profile)\nclarity/packaging/release.py:81-92"]
    Gear --> RT
    Monsters --> RT
    World --> RT
    UI --> RT
Loading

Sources: clarity/packaging/release.py:17-56


7.2.2 Profiles, Target Tiers and Generation Logic

Target tier resolution handles how individual assets match requested user profiles (everyday, native, 2x, 4x, legacy). The function requested_tier() determines whether an asset should remain at native resolution or scale up based on rules governing specularity and structural roles.

Title: Profile and Tier Resolution Architecture
graph TD
    Input["Asset Row\n(family, role, path, profile)"] --> CheckProfile{Profile Type?}
    
    CheckProfile -->|native / 2x / 4x| DirectReturn["Return Profile Directly\nrequested_tier()"]
    CheckProfile -->|everyday / legacy| CheckSpec{Is Specular/Normal & Equipment/Weapon/BG?}
    
    CheckSpec -->|Yes| Native["Return 'native'\nclarity/packaging/release.py:87-90"]
    CheckSpec -->|No| Default2X["Return '2x'\nclarity/packaging/release.py:91"]
    
    Default2X --> GT["generation_tier()\nclarity/packaging/release.py:94-109"]
    Native --> GT
    
    GT --> ScaleCheck{Scale & Caps Check\nroles.POLICY & TIER_SCALE}
    ScaleCheck --> FinalTier["Final Output Tier\n('native', '2x', '4x')"]
Loading

The function generation_tier() queries roles.POLICY to enforce family-specific resolution caps and limit output generation according to maximum edge bounds (roles.MAX_EDGE_OUT).

Sources: clarity/packaging/release.py:81-109, tests/test_release.py:135-146


7.2.3 Source Verification, Staging, and Immutability Guards

When executing an export via export(), the target release directory is strictly protected against partial writes and version regressions.

  1. Version Ordering Check: The exporter scans existing release folders for release.json files and parses their versions via version_key(). It asserts that the new release strictly succeeds existing versions.
  2. Staging Directory (.building): All output files are written to a temporary .building directory adjacent to the final path.
  3. Atomic Renaming: Once all assets are hardlinked or copied and release.json is successfully flushed, the .building directory is atomically renamed to the target version. If an exception occurs mid-export, no incomplete directory blocks subsequent execution.

Sources: clarity/packaging/release.py:140-172, tests/test_release.py:183-223


7.2.4 Product Selection and Fallback Rules

When packaging artifacts for distribution, select_product() discovers the highest available pre-encoded product tier that does not exceed the target profile requirement. It prevents upward fallback (e.g., using a 4x texture when native or 2x was requested and is missing).

def select_product(row, root, profile):
    target = requested_tier(row["family"], row["role"], row["path"], profile)
    available = set((row["tiers"] or "").split(","))
    for tier in reversed(["native", "2x", "4x"][: ["native", "2x", "4x"].index(target) + 1]):
        p = root / pack.mod_for_family(row["family"]) / pack.file_rel(tier, row["path"])
        if tier in available and p.is_file():
            return tier, p
    return None, None

Sources: clarity/packaging/release.py:125-132


7.2.5 Versioning, Previews vs. Stable Releases

Release identifiers follow strict semantic strings incorporating game patch versions, internal revisions, and optional preview markers.

  • version_for(): Combines game patch targets (e.g. 7.56), revision integers, and preview indices into canonical tags like 7.56.0-preview.1.
  • version_key(): Deconstructs version strings using regular expression matching into a sortable tuple (major, minor, revision, is_stable, preview_number). This ensures that preview builds sort strictly below their corresponding stable release.

Sources: clarity/packaging/release.py:60-78, tests/test_release_cli.py:26-59

Clone this wiki locally