# Tier-1 UE5 Client: Modules, Game Feature Plugins, and Platforms

The Tier-1 client is the canonical V3 ("Lilith") runtime: one Unreal Engine 5.5
project at `V3/ue/` that drives every premium surface — native desktop, console,
mobile, VR, **and** the browser (the same binary, server-rendered over Pixel
Streaming). It is the high-fidelity end of the
[tiered client stack](./product-promise-and-architecture.md): Lumen GI, Nanite
geometry, MetaHuman-class avatars, and Sequencer-driven concerts can only run
inside UE5, so rather than fork a per-platform client, V3 ships a single project
that the build pipeline cooks eleven different ways and a Game Feature plugin
system that hot-loads tenants and event modes without an engine rebuild. The
shape of that project is not aspirational prose: `V3/ue/V3.uproject` pins
`"EngineAssociation": "5.5"` and `"DisableEnginePluginsByDefault": true`,
declares **17 C++ modules** with explicit loading phases, and enables the exact
plugin set the design needs (PixelStreaming, GameplayAbilities, Niagara,
Metasound, Mover/PoseSearch, the Iris replication system,
OpenXR/OpenXRHandTracking, OnlineServicesEOS, Gauntlet). This page is the
module-, plugin-, and platform-level map of that client; the section hub is
[../V3_ARCHITECTURE.md](../V3_ARCHITECTURE.md).

The reason the client is organised this way is operational. A metaverse that
must boot a cold editor in ≤ 25 s, cook for phones and an Apple Vision Pro from
one source tree, and load a "Saraswati concert" or a "Tara live class" as a
self-contained content bundle cannot be a monolith of always-on code. So V3
splits its concerns into narrow modules (each with its own `*.Build.cs` and a
small `FV3…ModuleContract` identity), declares everything tenant- or
event-specific as an **`ExplicitlyLoaded` Game Feature plugin** that ships in
the `Registered` state and only activates on join, and centralises the
platform-matrix knowledge in one validated registry of cook profiles in
`V3Core`. The same source even produces a _second_ build target —
`V3PixelStreamingWorker.Target.cs`, a monolithic headless cook — so the browser
tier is literally this client running server-side. Everything below is grounded
in that tree.

## What ships, honestly

The **module split, the platform cook-profile registry, the Game Feature plugin
pipeline, and the cross-language wire codec are real and tested.** The 17
modules all build into both the `V3` game target and the
`V3PixelStreamingWorker` target (`V3/ue/Source/V3.Target.cs`,
`V3PixelStreamingWorker.Target.cs`); `V3Core` is the
`IMPLEMENT_PRIMARY_GAME_MODULE` (`V3/ue/Source/V3Core/Private/V3Core.cpp:852`)
and carries a real eleven-platform cook-target registry whose per-platform
`Validate()` enforces RHI, shader-format, resolution, FPS, and XR-runtime rules;
the Game Feature generator and verifier are real editor commandlets; and `V3Net`
is a hand-written Protobuf varint/zig-zag codec that agrees byte-for-byte with
the TypeScript and Rust bindings of the same `.proto`. There are **32 automation
specs** under `V3/ue/Source/V3Tests/`, and they assert specific values (e.g.
"Win64 shader format is SM6", "Quest 3 per-eye 90 fps budget"), not just
truthiness.

But the client is a **logic-and-manifest skeleton, not a content-complete
game.** This is the part the monolith's prose overstates, and the honest
position matters:

- **Six of the 17 modules are module-contract stubs.** `V3Gameplay`,
  `V3Animation`, `V3Cinematics`, `V3Persistence`, `V3Telemetry`, and `V3VFX` are
  each ~49 lines — a `DECLARE_LOG_CATEGORY`, an `FV3…ModuleContract`, and an
  `IMPLEMENT_MODULE`. The monolith's "GAS abilities (interaction, asana lock,
  gesture, applause), attribute sets" for `V3Gameplay` is **not implemented in
  C++**; the only ability references in the repo are asset-path strings inside
  Game Feature manifests (e.g. `/Game/Saraswati/Abilities/AS_ConcertAudience`),
  and those `.uasset` ability sets are not committed.
- **There is no `UV3NetDriver`, no `UV3WorldSubsystem`, and no `V3NetTransport`
  cxx-bridge.** The monolith's "World-Server ↔ UE Network Integration" section
  describes a `UNetDriver` subclass and a local-mirror world subsystem; a grep
  of `V3/ue/Source` finds none of those symbols. What exists is the wire
  **codec** (`V3Net`) and a voice **client model** (`V3Voice`); wiring them to
  live actors is not in the tree. Treat that section as design intent. See
  [Netcode Protocol and Physics](./netcode-protocol-and-physics.md).
- **Zero `.umap` files are committed.** Every cook profile targets
  `/Game/World/Atrium/L_LilithCommonsAtrium`, but that map exists only as a JSON
  scene descriptor
  (`V3/ue/Content/World/Atrium/L_LilithCommonsAtrium.v3scene.json`), not an
  authored level. The committed binary content is **generated**: 21
  `GameFeatureData.uasset` (one per plugin, machine-built from manifests), ~107
  design-token Slate brush/style assets (built by a second commandlet), and one
  `ConcertMaster.uasset` Saraswati template.

So: the **buildable engineering scaffold** — modules, targets, cook profiles,
plugin registration, the wire codec, the VR/avatar/UI subsystems with real logic
— is genuinely here and under test. The **authored game content** — levels,
ability blueprints, Niagara systems, MetaSound graphs, avatar meshes — is
declared in manifests and scene descriptors but largely not committed. Where a
module is a stub or a claim is unbacked, this page says so.

## The 17-module split

Each module owns one concern, builds with its own `*.Build.cs`, and exposes a
tiny `FV3…ModuleContract` (`GetModuleName` / `GetOwnedSurfaceTag` /
`SupportsRuntimeLoad`) so the split is introspectable. The runtime fifteen are
listed in `V3.Target.cs` `ExtraModuleNames`; `V3Editor` (Editor type) and
`V3Tests` (DeveloperTool) round out the seventeen in `V3.uproject`. The table
maps each module to what is _actually in the tree_ today, not the aspirational
charter:

| Module               | Files | State        | What the code actually contains                                                                                                         |
| -------------------- | ----- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| **V3Core**           | 9     | substantive  | Primary game module, 120 fps bootstrap frame policy, 11-platform cook-profile registry, `UV3GameFeatureData`, `AV3LilithGameMode/Pawn`. |
| **V3Gameplay**       | 3     | **skeleton** | Module contract only (~49 LOC). No GAS classes, abilities, or attribute sets in C++.                                                    |
| **V3World**          | 5     | thin         | Cold-join phase-budget fixtures, Atrium placeholder-scene validation, `V3InWorldCameraProp`. Not a replicated world subsystem.          |
| **V3Avatar**         | 12    | substantive  | `FV3MetaHumanRetargetTable` (Oshun60 bindings), OpenXR hand-IK, `V3HandIkSolver`, `V3PostureStateMachine`, `V3TaraEyesOpenPolicy`.      |
| **V3Animation**      | 3     | **skeleton** | Module contract only (~49 LOC).                                                                                                         |
| **V3Input**          | 9     | substantive  | `V3HandGestureRegistry`, `V3VrFloorRecalibration`, `V3VrTimewarp` (the `[V3.OpenXR]` runtime module).                                   |
| **V3Net**            | 4     | substantive  | Hand-written Protobuf wire codec (`FV3NetMultiplayerProtocolCodec`); packet structs for snapshot-delta, presence, voice, interaction.   |
| **V3Voice**          | 4     | substantive  | `FV3VoiceRealtimeGatewayClient` SFU model — Opus 24 kbps, DTLS-SRTP, Resonance spatialization, mouth-to-ear budget.                     |
| **V3UI**             | 15    | substantive  | `V3DesignTokenLibrary`, `V3AvatarNameplateLod`, `V3ActivityState`, VR comfort/calibration, the Tara physical-adjustment consent dialog. |
| **V3Audio**          | 5     | partial      | `V3SteamAudioVr` spatialization (~200 LOC) atop the module contract.                                                                    |
| **V3VFX**            | 3     | **skeleton** | Module contract only (~49 LOC).                                                                                                         |
| **V3Cinematics**     | 3     | **skeleton** | Module contract only (~49 LOC).                                                                                                         |
| **V3Persistence**    | 3     | **skeleton** | Module contract only (~49 LOC).                                                                                                         |
| **V3OnlineServices** | 3     | substantive  | EOS / V1-identity model packed into the module file (~403 LOC); covered by `V3OnlineServicesIdentityTests`.                             |
| **V3Telemetry**      | 3     | **skeleton** | Module contract only (~49 LOC).                                                                                                         |
| **V3Editor**         | 11    | substantive  | The Game Feature + design-token authoring commandlets and the token-reloader widget.                                                    |
| **V3Tests**          | 35    | substantive  | 32 automation specs: cook profiles, net codec, voice latency, OpenXR, avatar, VR comfort.                                               |

The honest reading of this table: the **client-side subsystems that have nothing
to do with authored 3D content** — networking codec, voice routing, VR comfort,
avatar retarget math, design tokens, identity — are real and tested, while the
modules that exist mainly to _host_ authored gameplay/animation/VFX/cinematics
content are still empty shells waiting on that content.

### Module loading order and the primary game module

`V3.uproject` assigns loading phases deliberately: `V3Core` and `V3Gameplay`
load `PreDefault` (so the cook policy and gameplay tags are up before world
actors), everything else loads `Default`, `V3Editor` is `Editor`-only, and
`V3Tests` is a `DeveloperTool`. `V3Core`'s module is the project's
`IMPLEMENT_PRIMARY_GAME_MODULE(FV3CoreModule, V3Core, "V3")`. On startup it
applies a frame policy — `t.MaxFPS = 120`, `bUseFixedFrameRate = false`, and a
re-application on `OnPostEngineInit` so a late device-profile cannot clobber it
(`V3Core.cpp:808`–`831`) — matching `DefaultEngine.ini`'s `t.MaxFPS=120`. The
default game mode is wired in config, not code: `DefaultEngine.ini` sets
`GlobalDefaultGameMode=/Script/V3Core.V3LilithGameMode`, and that
`AV3LilithGameMode` simply sets
`DefaultPawnClass = AV3LilithPawn::StaticClass()` with no HUD
(`V3LilithGameMode.cpp`).

The ≤ 25 s cold-start budget is enforced from two directions. `V3.uproject` sets
`DisableEnginePluginsByDefault: true` so _nothing_ loads unless explicitly
enabled, and `DefaultEngine.ini` then carries a long `+DisabledPlugins=` block
(Android\*, AppleARKit, Bridge, the DMX family, nDisplay,
VirtualProductionUtilities, WebBrowser\*) plus a `[V3.EditorPerformance]`
section with `ColdStartBudgetSeconds=25` and
`DisablePluginListSource=V3.UE.ModuleSplit`. The OpenXR posture is config-pinned
too: `[V3.OpenXR]` names `RuntimeModule=V3Input` and `+RequiredBackends=` Quest3
/ VisionPro / PSVR2 / ValveIndex / ViveFocus3.

### The wire codec, concretely

`V3Net` is the one place the Tier-1 client touches the world server, and it is a
genuine engineering artifact rather than a placeholder. `V3NetProtocol.cpp`
implements Protobuf wire format by hand — `WriteVarint`, `ZigZagEncode32`,
length-delimited keys — with no dependency on a protobuf runtime (the
`V3Net.Build.cs` deps are just `Core`/`CoreUObject`/`Engine`/`GameplayTags`/
`V3Core`). Transforms are packed for the bandwidth budget: position in
millimetres (`FV3NetVector3Mm`), rotation in milli-degrees
(`FV3NetRotationMilliDegrees`), expression intensity in basis points — which is
how the "≤ 32 bytes per avatar" target is met. The codec encodes and decodes
snapshot-delta, presence, voice-control, interaction, and client/server
envelopes, and `BuildInEngineProtocolExchangeReport()` produces the fixture that
`V3NetProtocolTests` checks against the canonical hex. That same `.proto` is
implemented three times (TS, Rust, this C++), and the cross-language golden-hex
parity test is the guard — see
[Netcode Protocol and Physics](./netcode-protocol-and-physics.md) and
[World Server and Gateway](./world-server-and-gateway.md).

## Game Feature Plugins: tenants and event modes

Everything tenant- or event-specific is shipped as a **Game Feature plugin** so
it can be hot-loaded on join, unloaded on leave, and included or excluded per
platform/region at cook time without an engine rebuild. There are **21 plugins**
under `V3/ue/Plugins/GameFeatures/` — **3 tenants** and **18 event modes**:

| Kind      | Plugins                                                                                                                                                                                                                                                 |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Tenant    | `V3Tenant_TaraStudio`, `V3Tenant_SaraswatiStage`, `V3Tenant_LilithCommons`                                                                                                                                                                              |
| Tara      | `V3Mode_TaraLiveClass`, `V3Mode_TaraOnDemand`, `V3Mode_TaraPrivate`, `V3Mode_TaraCohort`                                                                                                                                                                |
| Saraswati | `V3Mode_SaraswatiConcert`, `V3Mode_SaraswatiClub`, `V3Mode_SaraswatiListening`, `V3Mode_SaraswatiDrop`, `V3Mode_SaraswatiFestival`                                                                                                                      |
| Commons   | `V3Mode_CommonsAtrium`, `V3Mode_CommonsObservatory`, `V3Mode_CommonsDebateHall`, `V3Mode_CommonsLectureHall`, `V3Mode_CommonsStacks`, `V3Mode_CommonsRitualRoom`, `V3Mode_CommonsAretAtrium`, `V3Mode_CommonsLanternHall`, `V3Mode_CommonsSolitaryCell` |

Every `*.uplugin` carries the same three flags that make hot-loading work:
`"EnabledByDefault": false`, `"ExplicitlyLoaded": true`, and
`"BuiltInInitialFeatureState": "Registered"` (verified across the tenant and
mode plugins). `Registered` means the plugin's assets are discoverable but inert
until the Game Features subsystem transitions it to `Active`; `ExplicitlyLoaded`
keeps it out of the default mount so cold start stays cheap. Each plugin also
declares `"Plugins": [GameFeatures, ModularGameplay]` as dependencies.

### The manifest → asset → runtime pipeline

The interesting part is that the registration data is **authored as JSON and
compiled into a UAsset by a commandlet**, so the source of truth is reviewable
text and the binary is reproducible. Each plugin ships a
`Content/<Plugin>/GameFeatureData_<Plugin>.v3asset.json` manifest. For
`V3Mode_SaraswatiConcert` it reads:

```json
{
  "assetType": "GameFeatureData",
  "plugin": "V3Mode_SaraswatiConcert",
  "activation": "join-saraswati-concert",
  "gameplayTags": [
    "Mode.Saraswati.Concert",
    "Saraswati.Sequencer",
    "Audience.BandedSeating"
  ],
  "abilitySets": [
    "/Game/Saraswati/Abilities/AS_ConcertAudience",
    "/Game/Saraswati/Abilities/AS_ConcertOperator"
  ],
  "worldTemplates": [
    "/Game/Venues/Saraswati/Concert/LVL_SaraswatiConcert_Template"
  ],
  "niagaraSystems": [
    "/Game/VFX/Saraswati/NS_ConcertStage",
    "/Game/VFX/Saraswati/NS_AudienceLightWave"
  ],
  "metaSounds": [
    "/Game/Audio/Saraswati/MS_ConcertMainMix",
    "/Game/Audio/Saraswati/MS_AudienceBandMix"
  ]
}
```

The target of that compilation is `UV3GameFeatureData`
(`V3/ue/Source/V3Core/Public/V3GameFeatureData.h`), a `UGameFeatureData`
subclass with seven `EditDefaultsOnly` fields — `FeatureName`,
`ActivationPolicy`, and arrays of gameplay tags, ability-set ids, world-template
ids, Niagara-system ids, and MetaSound ids. Its
`HasCompleteRegistrationManifest()` refuses an incomplete manifest
field-by-field ("Game Feature manifest is missing required field: {0}"), and
under `WITH_EDITOR` that check is wired into `IsDataValid()` so a malformed Game
Feature fails Data Validation rather than shipping inert.

```mermaid
flowchart TB
    json["GameFeatureData_*.v3asset.json<br/><sub>authored manifest (per plugin)</sub>"]
    gen["V3GenerateGameFeatureDataCommandlet<br/><sub>editor commandlet</sub>"]
    tags["Config/Tags/*Tags.ini<br/><sub>generated gameplay tags</sub>"]
    asset["Content/GameFeatureData.uasset<br/><sub>UV3GameFeatureData (committed)</sub>"]
    verify["V3VerifyGameFeaturesCommandlet<br/><sub>load → Active → unload → Registered</sub>"]
    runtime["GameFeaturesSubsystem<br/><sub>activates on join</sub>"]

    json --> gen
    gen --> tags
    gen --> asset
    asset --> verify
    verify -->|round-trip passes| runtime
```

`V3GenerateGameFeatureDataCommandlet::Main` (`V3/ue/Source/V3Editor/Private/`)
walks every `*.uplugin` under `Plugins/GameFeatures`, reads and strictly
validates the JSON (every array must be non-empty; `assetType` must equal
`GameFeatureData`; the manifest's `plugin` must match the descriptor filename),
writes a `<Plugin>Tags.ini` of `GameplayTagList=` entries, then idempotently
creates-or-updates the `GameFeatureData.uasset` via `SavePackage` — re-running
is a no-op when `AssetMatchesManifest` holds. That is why all **21** plugins
have a committed `Tags.ini` _and_ a committed `GameFeatureData.uasset` that
exactly mirror their manifests.

The companion `V3VerifyGameFeaturesCommandlet` proves the plugins actually
hot-load. For each descriptor it drives the real
`UGameFeaturesSubsystem::ChangeGameFeatureTargetState` to `Active`, ticks the
editor while polling for completion (10 s timeout), asserts
`IsGameFeaturePluginActive`, then transitions back to `Registered` — a genuine
load/unload round-trip per plugin, not a flag check. **Caveat:** because the
manifests point at `/Game/...` abilities, levels, Niagara, and MetaSounds that
are not committed, this verifier exercises the _registration and
activation-state machinery_, not a fully-populated feature.

## Platform cook target profiles

The platform matrix lives in one validated registry in `V3Core`:
`FV3CookTargetProfileRegistry` (`V3Core.h` / `V3Core.cpp`) exposes a `Build…`
factory for each of **eleven** `EV3CookPlatform` values and a
`BuildCookRunCommand` that renders the profile's argument vector into a
`RunUAT BuildCookRun …` string. Each profile is a `FV3CookTargetProfile` whose
`Validate(OutReason)` is a real gate, and the rules are platform-aware rather
than generic:

| Profile (factory)                      | RHI / shader                    | Target res / FPS         | Reference HW          | Renderer rule enforced by `Validate()`                                           |
| -------------------------------------- | ------------------------------- | ------------------------ | --------------------- | -------------------------------------------------------------------------------- |
| `BuildWin64LumenNaniteProfile`         | DX12 / PCD3D_SM6                | 2560×1440 @ 60           | RTX 3060              | Lumen + Nanite + VSM **required**; HW ray tracing on.                            |
| `BuildMacAppleSiliconProfile`          | Metal / SF_METAL_SM6            | 2560×1440 @ 60           | M2 Pro                | Lumen + Nanite + VSM; HW RT off; `arm64`.                                        |
| `BuildLinuxLumenNaniteProfile`         | Vulkan / SF_VULKAN_SM6          | 2560×1440 @ 60           | RTX 3060              | Desktop renderer; `x64`.                                                         |
| `BuildSteamDeckMobileProfile`          | Vulkan / SF_VULKAN_SM5          | 1280×720 @ 40            | Steam Deck LCD        | Desktop renderer features **must be off**; 720p/40 fps floor.                    |
| `BuildIosForwardPlusProfile`           | Metal / SF_METAL                | 2556×1179 @ 60           | iPhone 15 Pro         | Mobile shaders; Lumen/Nanite/VSM off.                                            |
| `BuildAndroidVulkanForwardPlusProfile` | Vulkan / SF_VULKAN_ES31_ANDROID | 2992×1344 @ 60           | Pixel 8 Pro           | Mobile Vulkan ES3.1; ASTC cook flavor.                                           |
| `BuildQuest3OpenXrProfile`             | Vulkan / SF_VULKAN_ES31_ANDROID | 2064×2208 @ 90 (per eye) | Quest 3 dev kit       | Android Vulkan + **XR runtime profile** (hand tracking, foveation, passthrough). |
| `BuildVisionProOpenXrProfile`          | Metal / SF_METAL                | 3660×3200 @ 90 (per eye) | Vision Pro simulator  | visionOS Metal + XR profile (hand + **eye gaze**, foveation).                    |
| `BuildPsvr2OpenXrProfile`              | GNM / SF_PS5                    | 2000×2040 @ 90 (per eye) | PSVR 2 dev kit        | Nanite on, Lumen/VSM/RT off; XR profile (eye gaze, foveation).                   |
| `BuildPs5LumenNaniteProfile`           | GNM / SF_PS5                    | 3840×2160 @ 60           | PS5 dev kit           | 4K60; HW RT off; **must** carry a PSVR2 90 fps secondary target.                 |
| `BuildXboxSeriesXLumenNaniteProfile`   | D3D12 / SF_XSX                  | 3840×2160 @ 60           | Xbox Series X dev kit | 4K60; HW RT off for the post-GA budget.                                          |

The validator is not cosmetic. A desktop profile that drops Lumen, Nanite, or
virtual shadow maps fails; a "constrained mobile" profile (Steam Deck, iOS,
Android, Quest 3, Vision Pro) that _enables_ any desktop-only feature fails; an
XR profile that targets < 90 fps, omits per-eye dimensions, or claims a required
capability without the matching input profile fails via
`FV3CookXrRuntimeProfile::Validate` (e.g. "XR runtime profile must drive avatar
hand IK", "must enable foveated rendering"). Every profile must cook the Atrium
map, declare archive + manifest paths, and supply a `BuildCookRunArgs` vector of
at least eight tokens. These rules are the subject of one automation spec per
platform under `V3/ue/Source/V3Tests/` (e.g. `V3Win64CookProfileTests.cpp`
asserting `Rendering.ShaderFormat == "PCD3D_SM6"`, render dimensions, and that
the rendered command contains `-platform=Win64` and the Atrium `-map=`).

The whole project is built with deterministic floating point — `V3.Target.cs`
appends `/fp:strict /fp:except-` on Win64 and `-fno-fast-math -ffp-contract=off`
elsewhere, with `bUseUnityBuild = false` and `bBuildDeveloperTools = false`,
plus `ProjectDefinitions` `V3_LILITH=1` and `V3_ENGINE_UE55=1`.

### The Pixel Streaming worker is the same client, server-side

The browser tier is not a separate codebase: `V3PixelStreamingWorker.Target.cs`
compiles the _identical_ fifteen runtime modules as a **monolithic, headless,
shipping-with-logging** target (`LinkType = Monolithic`,
`bBuildWithEditorOnlyData = false`, `bUseLoggingInShipping = true`) and adds the
defines `V3_PIXEL_STREAMING_WORKER=1`, `V3_HEADLESS_PIXEL_STREAMING=1`, and (on
Win64) `V3_PIXEL_STREAMING_WIN_WORKER=1`. A GPU worker runs this build, renders
frames, and streams them over WebRTC to a browser that sends input back — so a
browser attendee is, from the world server's perspective, just another Tier-1
client. How sessions are matched to workers and POPs, and how that tier is
chosen, belongs to
[Tier Routing and Pixel Streaming](./tier-routing-and-pixel-streaming.md); the
point here is that the _client binary_ is shared, and the only delta is a target
file plus four cook profiles' worth of headless flags.

## How the client connects to its neighbours

- **To the world server / gateway.** `V3Net`'s codec speaks the
  `@oshun/multiplayer-protocol` wire format (the canonical `.proto` lives in
  `libs/v3/multiplayer-protocol/`); the Rust world server and gateway are the
  authority. See [World Server and Gateway](./world-server-and-gateway.md) and
  [Netcode Protocol and Physics](./netcode-protocol-and-physics.md).
- **Voice.** `V3Voice`'s `FV3VoiceRealtimeGatewayClient` models a
  LiveKit-compatible SFU at
  `wss://lilith-realtime-gateway.internal/v3/realtime/sfu` — Opus 24 kbps mono,
  DTLS-SRTP with replay protection, an 80 ms mouth-to-ear budget, and
  Resonance-Audio spatialization gated behind an honest
  `IsResonanceAudioRuntimeAvailable()` capability check. Detail lives in
  [Avatar, Animation, and Audio](./avatar-animation-and-audio.md).
- **Identity.** `AV3LilithPawn` carries the V1 bridge at the actor level:
  `ApplyV1IdentityNameplate` runs `SanitizeV1DisplayNameForNameplate` (trim,
  collapse whitespace, 32-char clamp, `"Guest"` fallback) and flips
  `bBoundToV1Identity`. The TypeScript side is `@oshun/lilith-identity-bridge`
  (`libs/v3/lilith-identity-bridge/`). See
  [V1 Integration and Identity Bridge](./v1-integration-and-identity-bridge.md).
- **Avatars and UI.** `V3Avatar` holds the Oshun60 MetaHuman retarget table and
  posture/hand-IK/eyes-open logic (note its deps are engine-only — the retarget
  is a _binding-and-validation model_, not a live MetaHumanRuntime rig); `V3UI`
  carries the design-token Slate library (built into the ~107 brush/style
  `.uasset` by `V3GenerateDesignTokenAssetsCommandlet`), avatar-nameplate LOD,
  VR comfort/calibration, and the Tara physical-adjustment consent dialog. These
  feed [Tara Classes, Aja, and Commons](./tara-classes-aja-and-commons.md) and
  the [Saraswati Stage Pipeline](./saraswati-stage-pipeline.md).
- **Contracts.** The launch-decision, tenant, and event-mode contracts the
  client honours are typed in `libs/contracts/src/v3/` (`lilith.ts`,
  `saraswati.ts`, `commons.ts`, `tara.ts`) — the same registry the
  [glossary and layout](./subsystem-glossary-and-layout.md) catalogues.

## Related

- [Product Promise and Architecture](./product-promise-and-architecture.md) and
  [Subsystem Glossary and Layout](./subsystem-glossary-and-layout.md) — the why
  and the where of the tiered stack
- [Tier Routing and Pixel Streaming](./tier-routing-and-pixel-streaming.md) and
  [Tier-2 Fallback Web Client](./tier2-fallback-web-client.md) — the other tiers
- [World Server and Gateway](./world-server-and-gateway.md),
  [Netcode Protocol and Physics](./netcode-protocol-and-physics.md) — the
  authority and wire this client speaks to
- [Avatar, Animation, and Audio](./avatar-animation-and-audio.md),
  [Saraswati Stage Pipeline](./saraswati-stage-pipeline.md),
  [Tara Classes, Aja, and Commons](./tara-classes-aja-and-commons.md),
  [Authoring and Content Pipeline](./authoring-and-content-pipeline.md) — what
  the Game Feature plugins load
- [Data, Tenancy, and Residency](./data-tenancy-and-residency.md),
  [V1 Integration and Identity Bridge](./v1-integration-and-identity-bridge.md),
  [Persona Policy, Provenance, and Rights](./persona-policy-provenance-and-rights.md),
  [Commerce and Royalties](./commerce-and-royalties.md),
  [Observability, Performance, Security, and Launch](./observability-performance-security-and-launch.md)
- The section hub: [../V3_ARCHITECTURE.md](../V3_ARCHITECTURE.md)
