# Production, Progression, World & Launch

Five ruleset cells on one Unreal Engine 5 spine is an engineering achievement;
making a player invest in a Bureau operator across all five is a _progression_
problem; building a 1947 noir city, a frontier of five biomes, and 32 star
systems that each feel inhabited is a _world_ problem; and capturing the faces,
voices, and scores that dress all of it is a _production_ problem the size of a
studio. This page is the production-and-platform leg of V5's "Platform,
Compliance & Production" group: the studio-ops capacity behind the content, the
two-track progression that carries a player across cells, the open-world systems
that make the maps live, and the single machine-checked gate that decides
whether the result is allowed to ship. The honest distinction that governs every
line below is the one the rest of the V5 catalogue carries — V5 ships **zero
cooked `.uasset` binaries**; the tree is **74 C++ Source modules**, **29
`.uplugin` manifests**, and content-as-data. So the production capacity here is
real _logic and authored intent_ in machine-readable form, backed by real
verification and real C++ systems, while the scanned faces, recorded VO,
composed score, and cooked maps that would fill it are production-gated and not
in-tree. And where some V-products carry a green launch aggregate, V5's is
deliberately, _honestly_ **red** — 17 of 17 blocking gates `pending`,
`releaseBlocked: true` — because a prior revision once fabricated the green and
the remediation tore it out. Each claim below is pinned to the C++ surface, the
JSON manifest, or the Python gate that backs it, or labelled plainly where it is
declared-but-uncooked. The orientation door and stand-in conventions every path
here rides on are [./product-promise.md](./product-promise.md). The feature hub
this page belongs to is [../V5_features.md](../V5_features.md).

## What ships, honestly

**The progression, world, and production _systems_ are real C++**, not contract
scaffolds. `V5Persistence` (`V5/ue/Source/V5Persistence/`) implements the
cross-cell save router, the per-cell currency ledger, the New Game+ economy, and
Save-Slot Archaeology as deterministic Blueprint function libraries with a
backing test suite. `V5Open` implements weather, era-swap data layers,
time-of-day, World Partition streaming, population, and HLOD rules against the
real `UDataLayerManager`. `V5FaceCapture` implements the MotionScan-equivalent
facial pipeline — blendshape stacks, MetaHuman binding, take linting, and FACS
calibration — with domain-specific quality math. `V5Audio` carries the score,
VO, and broadcast production budget as real routing and manifest logic. These
are domain-specific systems a renamed-variable stub could not reproduce.

**Three honest qualifications carry through the page.** _First_, every authored
artifact those systems describe — a scanned principal's 52-blendshape face, ~90
minutes of frontier score, a 140 km² Heist City — is _declared_ by data and code
and **cooked by nothing**; there are 0 `.uasset` files, so any claim that needs
authored content is forward-looking by construction and labelled as such.
_Second_, a few builder functions set production-completion booleans
(`bRecordingComplete`, `bCastingTeamAssigned`) to `true` as manifest defaults —
those record _planned production capacity_, not recorded audio, and the
0-`.uasset` reality is the cap on them. _Third_, the **launch-readiness gate is
red on purpose**, and the machinery is built so the red cannot be forged: the
validator fails closed, and the only verified quality signal to date is a single
on-box automation run (298/298), not a green nightly pipeline.

## Production: studio ops, mocap, VO, and composer

V5's content scale is documented as real studio capacity — 4 body-mocap stages
(LA, London, Vancouver, Tokyo), a 12-camera MetaHuman face stage at LA, 28
bespoke-scanned principals, 3 composers one per cell-cluster, and 12 voiced + 4
text-only language SKUs (the Sci-Fi player character fully voiced for both
genders, ~38 000 lines each). The in-tree code is the _pipeline_ that capacity
would run through.

### The facial-capture pipeline

`V5FaceCapture` (`V5/ue/Source/V5FaceCapture/Private/V5FaceCaptureSystems.cpp`)
is the MotionScan-equivalent interrogation rig in code, and its constants are
domain-correct: `RequiredMetaHumanBlendshapes = 52` and
`RequiredFACSUnits = 16`. `UV5_FaceCapture_USDLoader::BuildBlendshapeStack`
ingests a `.usd` take at a frame rate, frame count, blendshape-name set, and
FACS-unit set; `UV5_FaceCapture_MetaHumanBind::BuildMetaHumanBind` then binds it
to a MetaHuman rig and computes a `BlendshapeCoverage` as the _min_ of
blendshape and FACS coverage, marking the bind `bCompatible` only when coverage
`≥ 0.95` **and** the stack runs at 60 fps
(`IsNearlyEqual(FrameRate, 60.0f, 0.1f)`) — exactly the "60 fps `.usd`
blendshape stacks" the features text promises. The
`UV5_FaceCapture_CalibrationTool::BuildCalibrationScript` enumerates 8 facial
action units (`AU01_BrowInnerUp` … `AU15_LipCornerDepress`) at 120 minutes each,
summing to the **16-hour FACS calibration session** the production scope names.
`UV5_FaceCapture_RetakePipeline` and `…_TellTakeLinter` score each take by a
weighted rubric (frame-rate 0.25, blendshape coverage 0.35, FACS coverage 0.30,
trim 0.10) and fail any take below the gate, and
`UV5_FaceCapture_VOSyncSubsystem::BuildVOSyncPlan` only sets `bFullLipsync` when
the facial/voice offset is within `±0.25 s` — the seam between the 4
full-lipsync SKUs and the 8 lipsync-light ones.

### The audio production budget

`V5Audio` (`V5/ue/Source/V5Audio/Private/V5AudioSystems.cpp`) carries the score,
VO, and broadcast capacity as routing and budget logic. `MakeScoreBudget` pins
**8 hours of original score per cell** with a `score.<cell>.8h` stem-pack id;
`MakeComposerEngagement` records the per-cell-cluster composer contracts;
`MakePeriodBroadcastBudget` declares the period broadcast inventory (**18 radio
stations, 140 TV channels**); and `BuildVoiceRoute` emits per-cell MetaSound
voice graphs with cell-tuned attenuation (40 m Sci-Fi, 28 m elsewhere) and
priority (Mind Palace dialogue at 90). The honest seam is
`MakeVoLanguageCoverage`, which sets `bRecordingComplete` and
`bCastingTeamAssigned` to `true` — those are _manifest defaults describing
planned coverage_, not proof of recorded sessions; no VO `.uasset` exists, and
the localization lock is a separate launch gate (it lives with
[./accessibility-localization-and-compliance.md](./accessibility-localization-and-compliance.md)).
NIL and IP clearance gate any real-person likeness, trademark, and licensed
music — documented as obligations, enforced at the clearance manifest, not yet
exercised against cooked assets.

## Progression: two tracks, account and character

V5 progression runs on two tracks — per-character inside a cell, and per-account
across cells — and `V5Persistence` plus the Bureau ledger in `V5Core` implement
both as real save state, stored per account in `Profile_<accountId>.json`.

### Bureau XP and the tier ladder

The Cross-Continuum Bureau XP ledger is the account spine.
`FV5BureauXPLedger::RecalculateTier`
(`V5/ue/Source/V5Core/Private/V5Types.cpp:42`) computes
`CurrentTier = max(1, TotalXP / 2500 + 1)` — a tier every 2 500 XP — and grants
idempotent cross-cell unlocks at the exact thresholds the features text
advertises: Tier 1 `PhotoMode.AllCells`, Tier 5 `MindPalace.CrossEraPairs`, Tier
10 `CompanionApp.FullSync`, Tier 20 `NewGamePlus`, Tier 30
`Cosmetic.BureauGear.AllCells`. The save router
(`UV5_Persist_SaveGameRouter::BuildManifest`) enforces cross-cell consistency on
every route: each cell slot must carry the current save version and point at the
right profile slot, a Mind Palace slot must exist, and the Bureau ledger's
account id must match the profile's — the manifest is only
`bCrossCellConsistent` when all of that holds.

### Per-cell currency, fail-closed

`UV5_Persist_CurrencyLedger::BuildStartingLedger` seeds the cross-cell economy
with cell-correct currencies — Urban 250 `Cash`, Period 125 `Cash`, Frontier 2
`Gold`, Hunter 80 `Crowns`, Sci-Fi 500 `Credits`, plus Bureau scrip in the Mind
Palace — and `ApplyTransaction` is an append-only journal that **rejects** any
debit that would drive a balance negative (recording the rejection rather than
silently clamping), tracking `LifetimeEarned`/`LifetimeSpent` per balance. The
public side of balance is the `balance-ledger` service
(`apps/v5/balance-ledger/contract.json`): an append-only, designer-note-linked,
telemetry-evidenced ledger on Postgres/Redis with a `public-export` capability —
real contract surface whose `publicBalanceLedgerLive` flag is honestly `false`
until the service is deployed, and which is itself a launch gate.

### New Game+ and Save-Slot Archaeology

The deepest progression code is the Year-1 New Game+ plan.
`UV5_Persist_NewGamePlus::BuildYear1Plan` requires **Bureau tier 20** and a
completed campaign, covers all five launch cells, and is validated by
`ValidateYear1Plan` against hard domain invariants: ≥2 authored story branches
per cell (≥10 total), ≥3 difficulty modifiers per cell (≥15 total), every
modifier scalar `≥ 1.0` so NG+ can _only_ raise challenge, and
`bNoPaidPowerCarryover` true. Carry-over domains are explicit (`bureauXp`,
`cosmetics`, `photoMode`, `mindPalaceOutcomesArchive`, `codex`,
`workshopEntitlements`); reset domains are equally explicit
(`criticalPathMissionState`, `cellEconomyBalances`, `wantedHeat`, `bountyDebt`,
`factionMissionLocks`) — so a second run keeps your identity and loses your
shortcuts. On top sits **Save-Slot Archaeology**
(`UV5_Persist_SaveSlotArchaeology`): 10 authored scenarios (two per cell) that
read a prior save's _ending flags_ (`ending.urban.low-collateral`,
`ending.scifi.alliance.independent`, …) and, when matched, trigger the matching
NG+ branch — your first ending literally reseeds your second beginning. Imports
must be migrated to the current save version before they validate. Underneath it
all, crash recovery (`UV5_Persist_CrashRecovery::BuildPolicy`) holds a 90-second
autosave interval, an atomic temp-write, write-before-map-travel, and three save
generations (`Current`/`Previous`/`Fallback`); replay packets carry an exact
binary SHA-256 payload digest plus an externally keyed HMAC-SHA256 signature,
expiry, and single-use nonce over every frame and security-relevant field.

## The open world: weather, eras, and streaming that bite

The maps themselves are content-gated (no cooked geometry exists), but the
_systems_ that make them live are real `V5Open` code over UE5 World Partition.
The signature maps are declared in the features text — Urban's 16 districts
across ~140 km² Heist City plus the ~22 km² Street Triad world, Period's one
1947 city seen across three eras, Frontier's 5 biomes, Sci-Fi's 32 systems with
~120 bodies (PCG planetary detail), Hunter's 4 regions — and the runtime that
would drive them is implemented now.

### Weather is gameplay, not cosmetic

`UV5_Open_Weather` (`V5/ue/Source/V5Open/Private/V5OpenWeather.cpp`) models
seven states — `Dry`, `LightRain`, `HeavyRain`, `Snow`, `Fog`, `DustStorm`,
`SolarFlare` — each binding to a World Partition data layer activated through
`UDataLayerManager::SetDataLayerRuntimeState`. Crucially, every state carries
four **gameplay** modifiers: `VisibilityScalar`, `TractionScalar`,
`CrowdDensityScalar`, and `ClueLegibilityScalar`. A `DustStorm` drops visibility
to 0.24 and crowds to 0.35; `Fog` cuts clue legibility to 0.62; `HeavyRain`
thins crowds to 0.48 and traction to 0.62 — and `GetCurrentGameplayModifiers`
**lerps** between source and target during a transition, so a clearing storm
hands visibility back gradually. This is the "weather affects visibility,
traction, NPC behavior, and sense-mode clue legibility — not purely cosmetic"
promise, implemented as numbers a feel test can assert.

### Eras, day-cycle, and streaming

`UV5_Open_DataLayer_Era` swaps the Period cell's 1930s/1947/1968 eras by
activating the matching era data layer and unloading the rest — the same
World-Partition mechanism, applied to time instead of weather, so Made Man and
Vice Squad can share one city's geometry. `UV5_Open_TimeOfDay` pins a
`DayLengthRealSeconds = 48.0f * 60.0f` constant — the **48-minute in-game day**
that drives NPC schedules and shop hours. And `UV5_Open_StreamingSubsystem`
registers World Partition streaming sources (actor- and location-anchored,
sorted by priority into `FWorldPartitionStreamingSource`s) so a seamless
open-world cell streams around the player; population and HLOD-rule modules sit
beside it. The persistent-world economy that layers over the maps is
deterministic-given-seed save state, simulated coarsely while a cell is
inactive.

## Launch readiness and exit criteria (honestly red)

§90 aggregates the entire product — cells, modes, localization, cert,
compliance, quality, online, and live-service — into one go/no-go, and it is the
page's load-bearing example of fail-loud honesty.
`V5/release/launch-readiness-manifest.json` (`schemaVersion: 2`) tracks **17
blocking gates**, and today every one reads `pending`: `passedGates: 0`,
`cellsComplete: 0`, `languagePacksLocked: 0`, `platformsCertPassed: 0`,
`releaseBlocked: true`, `greenBuildId: null`. Its `correctionNote` is blunt
about why — a prior revision fabricated a shippable game (17/17 gates passed, a
99.72% crash-free rate over 125 000 PS5 sessions, nine cert passes, a completed
accessibility audit) with no build, hardware, sessions, or external engagements
behind any of it. `V5/REMEDIATION_2026-06-12.md` reset it, moving the backlog
from 905 `[x]` to 875 `[x]` and promoting **zero** marks to done; it records
that "the only verified quality signal to date is the one-off 2026-05-31 on-box
automation run (298/298 after remediation); no green nightly pipeline exists."

### The gate cannot be hand-edited green

`V5/tools/release/validate-launch-readiness.py` (399 lines) **fails closed**,
and its core is a `require_gate_not_passed` helper that refuses a `passed`
status without backing evidence. `releaseBlocked: false` requires _every_ gate
passed **and** a real `greenBuildId`; a cert-passed platform needs
`memoryWithinBudget` plus an existing `certEvidencePath` on disk; a "complete"
accessibility audit needs a real named consultant (`"TBD"` is rejected); the
crash-free gate needs a cohort `≥ 100 000` with a rate above 99.5%; and a regex
stub-scan walks the runtime tree (`V5/ue/Source`, `V5/ue/Content`,
`apps/v5/web/src`, `apps/v5`) for
`coming soon|not implemented|lorem ipsum|todo|fixme|tbd`. It also _composes_ the
cell, performance-budget, and live-service validators, so a regression in any of
them blocks launch. `FV5LaunchReadinessManifestTest`
(`V5.Tests.LaunchReadiness`) mirrors the fail-closed logic in C++ — its own
comment records that it once hardcoded the fabricated 17/17 and now validates
internal consistency instead.

```mermaid
flowchart TB
  subgraph prod["Production & content systems"]
    face["V5FaceCapture<br/>52 blendshapes · 16 FACS · 60fps"]
    audio["V5Audio<br/>8h score/cell · 18 radio · 140 TV"]
    world["V5Open<br/>7 weather states · era swap · 48-min day"]
  end
  subgraph prog["Progression"]
    bureau["Bureau XP · tier = XP/2500+1<br/>unlocks @ 1·5·10·20·30"]
    ngplus["NG+ @ tier 20<br/>10 branches · 15 modifiers · no paid power"]
    ledger["balance-ledger service<br/>publicBalanceLedgerLive: false"]
  end
  prod --> AGG
  prog --> AGG
  manifest["launch-readiness-manifest.json<br/>17 gates · all pending"] --> AGG
  AGG{"validate-launch-readiness.py<br/>(399 lines · fail-closed)"}
  comp["composes validate-cells ·<br/>perf-budgets · live-service"] --> AGG
  AGG -->|"0 / 17 passed · no greenBuildId"| red["releaseBlocked: true (today)"]
  AGG -.->|"only with on-disk evidence<br/>+ real build id"| green["green = ship"]
  zerouasset["0 .uasset · 29 .uplugin<br/>caps every cooked claim"] -.-> red
```

### Exit criteria vs. the point-in-time gate

The §"V5 Exit Criteria" list is the _standing bar for "done"_: every § in
`V5_TODOS.md` checked against real source, a zero-hit adversarial stub-scan
across all modules, the nightly Gauntlet green for **7 consecutive days**, all 9
platforms cert-passed, all 16 language packs through localization QA, and the
cross-cell Mind Palace deduction graph validated end-to-end with the cross-era
arc playable to all endings. Launch readiness is the _point-in-time_ gate for
"ready to ship to the public." A build may meet exit criteria before every
operational launch item (event scheduling, marketing) is complete — but it may
not launch before both are satisfied. The day-one event is already authored
(`event.s01.day-one.continuum-signal`, 30 days, `scheduled`) and the
cross-validating C++/Python checks are real; what is honestly absent is the
seven-day green nightly, the cooked content, and the external evidence — and the
gate is built to keep saying so.

## Where this connects

- [./accessibility-localization-and-compliance.md](./accessibility-localization-and-compliance.md)
  — the WCAG audit, the 16 language-pack lock and per-language QA, the
  parental/age-gating and ratings reviews, and the DSAR/privacy flows that
  several of this page's launch gates (`localization.*`,
  `accessibility.audit.pass`, `compliance.*`) cross-check.
- [./product-promise.md](./product-promise.md) — the orientation door, the
  74-module / 0-`.uasset` / 29-`.uplugin` convention, and the spec-vs-disk
  discipline behind the declared-but-uncooked caveats above.
- [../architecture/observability-performance-testing-content-pipeline.md](../architecture/observability-performance-testing-content-pipeline.md)
  — the architecture companion: the performance-budget gate, the Gauntlet driver
  and feel-test catalog, the content-as-data accounting, and the same
  fail-closed launch-readiness validator read in engineering depth.
- The feature hub: [../V5_features.md](../V5_features.md).
