PIPE_3D_2026-07-29.md

pipelines/PIPE_3D_2026-07-29.md

PIPE_3D — The 3D Asset + Worldgen Lane Dossier

Research date 2026-07-29. Every model/tool below is VERIFIED (fetched live this pass, URL inline) or

marked CARRIED (verified 2026-07-15 in the repo brief, not re-fetched this pass) or

UNVERIFIED-EXCLUDED. Licence-read-before-first-GPU-hour is honoured: no tool enters the stack

without its licence named.

**SUPERSEDED IN PART — 2026-08-05, the material-property law. Josh ruled (verbatim): "...some
crush, some bend, some are flexible, some are fragile, some are hard, some are heavy, some are
light."** This dossier specifies how a mesh is GENERATED and says nothing about what the object
is MADE OF once it exists. The mesh lane's own subject-composition rule already reads a material
clause off the registry row; nothing downstream could read a physical PROPERTY off anything,
because no such column existed.
- Five columns now land on all seven prop-bearing registries (431 rows)mass_class,
hardness, fragility, flexibility and derived_from — emitted by
harness/asset_factory/emit_phys_profiles.py, with the citable default table in
build/3d/schema/material_defaults.json (48 keys; Ashby, Wegst and Ashby, Klein and Dutrow,
the USDA Wood Handbook, Liese, Currey).
- Three modes, and the third is the discipline. DERIVED where canon states the property,
DEFAULTED where canon states the material, UNMEASURABLE where neither — declared with a
reason and never guessed. 50 of 431 land UNMEASURABLE on mass, and that count is a deliverable:
27 environment features canon declares massless (effect volumes, permanently correct) and 23
equipment rows that state a FORM and no material (a canon debt made countable).
- THE TOOTH: harness/asset_factory/check_phys_profile.py, wired into verify_landed.py as
T8, mutation-proven both directions on every invocation (11 fixtures). A prop reaching a
staging manifest whose row leaves a column blank, carries an off-enum value, cites a canon cell
that no longer exists, or resolves mass_class=UNMEASURABLE while shipping mesh media is
REFUSED. The manifests this dossier's lane emits are exactly the surface it guards.
- A rigged creature answers to a second law. See the anatomy supersession on
PIPE_ANIMATION_2026-07-29.md and build/3d/schema/anatomy_reference/: tooth T7 measures a
rigged import against its archetype's bone roster, segment count and per-joint ROM, and its
must-fire fixture is this lane's own CR_0002 straight-rod previz rig.
Nothing in the generation stack below is retracted. What is superseded is the assumption that a
mesh plus a texture is a finished object: an object that cannot say whether it crushes, bends or
shatters is not finished, it is only modelled.

0. THE HEADLINE — the ruled stack does not install as published on this machine

Every 3D-gen repo in the ruled roster pins a pre-Blackwell CUDA. Verified live today:

TRELLIS.2 pytorch 2.6.0 with CUDA 12.4 (github.com/microsoft/TRELLIS.2, Linux-only, 24GB floor,

nvdiffrast+nvdiffrec still in setup.sh flags); Hunyuan3D-2.1 `Python 3.10 and PyTorch

2.5.1+cu124; Direct3D-S2 CUDA 12.1 / torch==2.5.1+cu121`; ComfyUI-3D-Pack Windows prebuilds

Python 3.12, CUDA 12.4, torch 2.5.1+cu124 with zero Blackwell/50-series note in its docs.

The RTX 5090 is sm_120 and requires ≥ PyTorch 2.7.0 + cu128 — 2.7.0 was the first stable release

shipping sm_120 kernels (verified: pytorch forums, SaladCloud RTX-5090 guide, vLLM issue #13306).

**Consequence: the install plan is not "follow the README." It is "rebuild every CUDA extension

against cu128."** This is the single biggest unbudgeted item in the lane and it lands on top of D-1,

not instead of it. The runbook's CUDA-12.4 pin for TRELLIS.2 is CONFIRMED as the repo's published

requirement and simultaneously CONFIRMED as unrunnable on sm_120 — both are true; the pin must be

read as "the version the authors tested," not "the version we install."

**SUPERSEDED IN PART — 2026-08-05, generation-pipeline-v2 multi-view install, measured on
Milks5090 (RTX 5090, sm_120, WSL2 Ubuntu-24.04, torch 2.9.0+cu128).** The blanket claim
"rebuild EVERY CUDA extension against cu128" is **REFUTED for the Hi3DGen route and UPHELD for
the Direct3D-S2 route.** The dossier was right that the READMEs do not install; it was wrong
that compilation is therefore unavoidable. What decides it is not the repo's pinned CUDA but
whether a prebuilt wheel exists for the exact (torch, python, cuda) triple — and for the
sparse-conv and attention extensions, two do.
- Hi3DGen: ZERO compilation. xformers==0.0.33.post1 and spconv-cu126==2.3.8 both run on
sm_120 on a box with no nvcc and no MSVC installed at all. Verified by EXECUTING kernels,
not by importing them: xops.memory_efficient_attention returned (1,64,8,64) and a
spconv.pytorch.SubMConv3d returned (128,8), both on the 5090. Note the spconv wheel is a
cu126 build running against a cu128 runtime — the CUDA minor version in a wheel name is
not the constraint the dossier assumed it was.
- The pin that actually bites is torch-to-xformers, not CUDA. xformers==0.0.35 requires
torch>=2.10 and ships a py3.10 build; installing it silently upgraded torch to 2.11.0 and
then refused to load its own C++/CUDA extensions against py3.12. 0.0.33.post1 is the build
pinned to torch==2.9.0. Install it with --no-deps so it can never move torch off the
sm_120-proven pin.
- Direct3D-S2 still needs the compiler, and the reason is an import, not a CUDA pin.
torchsparse is avoidable (SPARSE_BACKEND=spconv), but
direct3d_s2/modules/sparse/attention/__init__.py unconditionally imports the
SpatialSparseAttention module, which does a module-level
from flash_attn import flash_attn_varlen_func. ATTN_BACKEND=xformers does not dodge
it — the import runs before any backend switch is read. Dao-AILab publishes no
torch2.9/cp312/cu12/linux wheel (three release pages checked, zero matches), so flash-attn
must be compiled, which is what forces the CUDA 12.8 toolkit (DL_0025).
- Two cheap ways out were tried and ruled out by measurement. nvidia-cuda-nvcc-cu12
12.8.93 from PyPI ships nvvm, libdevice, headers and ptxas but **no bin/nvcc compiler
driver** — it is for JIT consumers like Triton. Ubuntu's own nvidia-cuda-toolkit is
12.0-era and cannot target sm_120.
- Build-resource note for whoever runs it next: MAX_JOBS=12 on flash-attn is OOM-killed
on a 61 GB box — dmesg shows cicc invoking the OOM killer. Use MAX_JOBS=4.
The practical rule this replaces the headline with: **probe for a prebuilt wheel at the exact
triple first, and treat "needs nvcc" as a per-repo property driven by unconditional imports —
not as a property of the whole lane.**

1. THE VERIFIED STACK

Licence law applied throughout: a licence that restricts output/use is a ship-blocker; a licence

that restricts the tool's own code (GPL/CGAL-class) is not, because we run those as external

executables and never redistribute them — Blender's output has never been GPL. That distinction is

what separates the trap set below from the finishing set.

JobPRIMARYFALLBACKLicence · source
Geometry (weapons/props/vril sites)TRELLIS.2-4BDirect3D-S2MIT / MIT. TRELLIS.2 · Direct3D-S2 — S2 verified today: MIT, no nvdiffrast, 10GB@512 / 24GB@1024, OBJ out
Sharp-geometry hero silhouettesHi3DGen (MIT)TripoSG (MIT)~~CARRIED from repo brief; no new release found~~ SUPERSEDED 2026-08-05: INSTALLED AND PROVEN. Repo is Stable-X/Stable3DGen @ c29f668, MIT body re-fetched (copyright reads Bytedance Inc.). It is a TRELLIS derivative with the NVIDIA libraries stripped — the same lineage whose textured path this table bans for nvdiffrast taint, minus the taint. Throwaway: 67.3 s end to end, peak 14.1 GiB allocated / 17.0 GiB reserved, 1,053,224 faces, watertight. Rows DL_0019DL_0023
Finished textured PBRHunyuan3D-2.1Hunyuan paint stage + ArmorLabTencent Community Licence — 1M MAU cap, EU/UK/South Korea excluded, AI-label required. VERIFIED live: repo still tops out at 2.1; 2.5/3.x remain closed
TRELLIS.2 textured outputBANNED from any shipped pathnvdiffrast/nvdiffrec = NVIDIA 1-Way Commercial, non-commercial-only. Issue #22 re-fetched today: still open, still no maintainer response (opened 2025-12-18). Geometry path is MIT and clean; the bake path is previz-only
Quad retopologyAutoRemesher (MIT, CLI: --input --output --target-quads --edge-scaling, Win/Mac/Linux, OBJ-in/OBJ-out)MeshAnything V2 (MIT, ~1600-face cap)github.com/huxingyi/autoremesher · CG Channel 2026-07 coverage. Does NOT generate UVs — pair it with xatlas
UV unwrap/packxatlas (MIT, C++11, no external deps, Python bindings)Blender Smart UV headlessgithub.com/jpcy/xatlas — actively maintained, 1223 commits
Finishing pipeline hostBlender 5.2 LTS (released 2026-07-14, supported to 2028, Python 3.13)Blender 4.5 LTSGPL tool, output unencumbered. --background --python
Auto-rigging (132 creatures / 22 familiars)UniRig (VAST+Tsinghua, SIGGRAPH 2025)Blender RigifyMIT verified today, 8GB VRAM, Python 3.11 / torch ≥2.3.1, exports FBX. Caveat the repo itself raises: checkpoint trained on Articulation-XL2.0 — read that dataset's terms before ship. UniRig
Part decompositionPartCrafter (ships inside ComfyUI-3D-Pack)SimArt (Apache 2.0, URDF-targeted)CARRIED + verified present in the 3D-Pack node list
Worldgen / scene-scaleHY-World 2.0 — NEW, not in any repo briefHunyuanWorld-1.0Verified today: releases Apr–May 2026, outputs meshes / 3DGS / point clouds / depth / normals, "directly importable into Unity / Unreal Engine", CUDA 12.8 recommended, Python 3.11+ — the only item in this lane that ships Blackwell-native. License.txt present, name not readable via fetch → LICENCE READ REQUIRED before first GPU hour. HY-World-2.0
3DGS capture→meshgsplat / Nerfstudio (Apache 2.0, commercial-clean; 2DGS now integrated)OpenSplatTRAP: the original Inria graphdeco-inria/gaussian-splatting reference impl is NON-COMMERCIAL ("may be used non-commercially... research and/or evaluation purposes only"), and SuGaR derives from it. Route the whole 3DGS lane through gsplat, never the Inria tree
Terrain chainOpenTopography Global DEM API → GDAL/rasterio → 16-bit PNG → UE LandscapeAWS Open Data bulk COGsChain CARRIED from GEODATA_TERRAIN_CHAIN.md. NEW CONSTRAINT VERIFIED TODAY: the free API key is rate-limited to 50 calls / 24h for non-academics (250 for academics). 69 regions × 3 datasets ≈ 207 calls = 4+ days of API budget, or an OpenTopography Plus subscription, or the AWS bulk mirror. The repo brief said "free, issued instantly" and missed the ceiling
Landcover / biomesESA WorldCover 10m → weightmaps → PCG Biome CoreSentinel-2 L2A drapeCARRIED
Motion (creature/NPC locomotion)ARDY (NVIDIA, SIGGRAPH 2026, released 2026-07-10)Kimodo (NVIDIA, 2026-03-16)Josh's leads CONFIRMED, both real. ARDY: code Apache-2.0, weights NVIDIA Open Model Licence (commercial permitted), tested on 4090, text encoder ~14GB VRAM (CPU-offloadable), outputs .npz joints/rotations + .csv MuJoCo qpos. nv-tlabs/ardy · nv-tlabs/kimodo. LICENCE FLAG: SMPL/SMPL-X variants — the Max Planck SMPL-X model licence is academic-only, "any use for commercial purposes is prohibited," commercial routes through Meshcapade. Use the non-SMPL skeleton variants, or retarget joint rotations onto our own rig and never ship SMPL-X mesh data. This is a licence read Josh's lane owner must make before ARDY touches a shipped animation

KILLED / EXCLUDED this pass: Sparc3D (no weights, no licence — CARRIED). Ubisoft CHORD

(Research-Only Copyleft — previz only, CARRIED). Pixal3D (MIT code but installs TRELLIS.2 first,

inherits the nvdiffrast chain — bench it instrumented, never assume clean; CARRIED). SATO (code

still unreleased — CARRIED, re-check post-SIGGRAPH). Meshy/Tripo/Rodin (closed SaaS — reference

tier only, per the standing Josh ruling). **NVIDIA Cosmos 3 — real and verified (weights 2026-05-31)

but EXCLUDED from this lane**: it emits video/image/audio/action, not meshes or USD; both

NVIDIA_WORLDGEN.md and COSMOS3_DEEP_DIVE.md reached that independently and nothing today

overturns it. NVIDIA's SIGGRAPH-2026 Omniverse drop (ovrtx, ovphysx, CAD-to-SimReady) is real

but is sim/robotics asset prep, not game-mesh generation — no licence taint found, no adoption case.

2. INSTALL PLAN

Environment lane (per D-1). Confirm option (a) WSL2 Ubuntu 24.04 + the Puget Docker App Pack

as the generation host, with (b) ComfyUI-on-Windows demoted to the image lane only. The rider's

own evidence now carries decisive weight: the Puget comfy_ui image is

nvidia/cuda:12.8.0-runtime-ubuntu24.04 + cu128 torch — i.e. the vendor already assembled the exact

sm_120 stack that §0 says every repo lacks. Do not use ComfyUI-3D-Pack's Windows prebuilds: they

are cu124/torch-2.5.1 and will not load on sm_120. Fork the pack, pin torch==2.9.0+cu128.

Disk placement (per the RULED layout). Gen4 4TB slot-3 = the whole lane: WSL2 vhdx, model

weights, ComfyUI models/, Blender, the generated-asset staging cache. Gen5 4TB stays UE hot

path + DDC — nothing from this lane touches it. 8TB SATA = the raw-GLB archive + every DEM/WorldCover

GeoTIFF (those are re-downloadable but rate-limited, so archive them once).

Install ORDER (dependency-forced, not preference):

1. WSL2 Ubuntu 24.04 + NVIDIA Container Toolkit via the Puget pack's setup.sh (hand-finish the

driver step — the pack hard-fails its own driver install under WSL2's passthrough model).

2. Pin the base env: Python 3.11, torch==2.9.0+cu128. Verify sm_120 before anything else:

python -c "import torch;print(torch.cuda.get_device_capability())" must return (12, 0).

3. Build the CUDA extensions from source against cu128 — flash-attn, spconv, torch_scatter,

torch_cluster, torchsparse, and TRELLIS.2's cumesh/o-voxel/flexgemm. **This is the

half-day-to-two-day item.** UniRig's own README warns flash-attn install commonly fails.

4. TRELLIS.2 geometry-only: run setup.sh WITHOUT --nvdiffrast --nvdiffrec. If the shape path

won't import without them, install them into a separate trellis2-previz env that is firewalled

from the shipped-asset path by construction, not by discipline.

5. Direct3D-S2 (clean-geometry control, no nvdiffrast) — the A/B partner that tells us whether we

need TRELLIS.2 at all.

6. Hunyuan3D-2.1 (the textured-PBR lane).

7. CPU-only finishing set — needs no GPU, no CUDA, install anywhere: Blender 5.2 LTS, AutoRemesher,

xatlas (pip install xatlas), GDAL/rasterio.

8. UniRig, then HY-World 2.0 (already cu128-native), then ARDY/Kimodo last.

Thursday-night download list. Sizes marked [M] measured/quoted, [E] estimated from parameter

count — measure at download and correct the runbook, do not carry [E] figures forward as facts.

BY MEASUREMENT 2026-08-05: peak 5.16–6.09 GiB allocated (n=13, median 5.19), read from each

cell's own .gen.json. See §10.** Hi3DGen's runtime peak likewise measures 10.6–13.8 GiB

allocated across nine cells, against this row's ~5 GB download-size estimate — the two figures

are different quantities and the [E] was never a VRAM claim; §10 carries the runtime numbers

[M, quoted]. The 80B panorama tower is far outside a 32GB card. Pull WorldMirror-2 only (~3 GB [E])

until the benchmark says otherwise.

re-downloadable, so a partial night is recoverable.

VRAM / RAM budget and scheduling class — the concurrency law applied. This lane splits cleanly

into two halves with different scheduling classes, and that split is the whole answer to GPU

contention:

Hunyuan3D-2.1 combined 29 GB of 32 GB [M, repo-quoted] is the ceiling case and admits nothing

else on the card — not a resident 14B, not a UE editor. TRELLIS.2 24 GB floor [M]. Direct3D-S2

10 GB@512 / 24 GB@1024 [M]. HY-World unmeasured. UniRig 8 GB [M]. ARDY ~14 GB [M] with a

CPU-offload switch. **Rule: one GPU job at a time, serialized by a queue, and the queue holds

while UE holds the GPU.** An OOM from our own co-residency sloppiness would be a false trigger on

HARDWARE_DECISION's upgrade trigger #1.

retopo/UV/bake/export, AutoRemesher, xatlas, GDAL/rasterio, the DEM chain, FBX/glTF conversion,

Nanite-prep validation. Budget ~8 threads of the 9950X3D's 32 and ~32 GB of the 128 GB, leaving

the rest to UE compiles and the DDC. This is the lane's real throughput win: the finishing

pass is the bottleneck (§2 of the repo brief: no open AI does retopo+UV+LOD+collision end-to-end),

and it never needs the contested resource.

3. THE INTEGRATION CONTRACT

Every generated asset enters canon through DR-2 (docs/ASSET_DROPIN_CONTRACT.md) and nowhere else.

never chooses a path. Default drop is path takeover at the ratified convention

/Game/Meshes/<class>/SM_<mesh_id_ref> (item 3 RULED: path takeover is the default; manifest

re-point via ue_asset_path is reserved for licensed/MetaHuman off-convention assets).

import + apply_*_writeback, ue_asset_path + last_generated_timestamp written, complete.

QA rejection writes rejected and the id stays on its placeholder — a failed generation never

produces a broken build, only an unchanged one. regeneration_required re-enters the queue.

generation_tier (fidelity: background · region_standard · region_hero · realm · apex),

presentation_tier_ref (mastery variant), decay_stage (place condition, two frozen endpoint

values). All three are folded into generation_prompt_hash, so a tier or stage change

self-triggers regeneration_required (clause 6.3). A bare tier column is banned.

convention for skeletal/rigged, FBX or glTF for static. Textures out as separate PBR channels

(basecolor / normal / ORM). UniRig emits FBX natively, which is the reason it beats hand-rigging

at 132-creature volume.

ENGINE_OPTIMIZATION_DOCTRINE.md **R-01 rules Nanite-first static world with NO authored LOD

chains for world geometry**; density is controlled by placement (PCG + HLOD), not by cull knobs.

So the finishing pass does not build _LOD0.._LOD3 for world/static meshes — it exports the

dense mesh and lets Nanite cluster it. What the finishing pass DOES owe Nanite: opaque/masked

materials only (no translucency, no two-sided), clean manifold topology, no single-plane cards, a

collision hull, and WPO Disable Distance metadata on any WPO material (R-11). **R-02 bans

alpha-card and WPO-driven foliage as INPUTS to the Nanite-foliage path, and R-02b** requires

every hero_vegetation asset to resolve a conventional instanced route as well — so the

vegetation branch of this lane exports two routes and the validator asserts both.

Nanite skeletal is beta as of 5.7 and reworked in 5.8 (Epic docs; 5.7 crash repros gone) — so the

older brief's "Nanite has no skeletal support" line is stale and should be corrected at source.

model gate): mesh_id_ref resolves through the resolver (QT-8); the asset loads and is

non-placeholder; manifold/watertight check; triangle and material-slot budget; UV coverage and

overlap from xatlas; opaque/masked-only material check; collision hull exists. **Only assets that

pass the deterministic teeth are shown to an image critic**, which reads captures against the

concept-art reference and the realm charter's art-hook family (palette_law · silhouette_law ·

impossible_architecture_budget · signature_phenomenon). The RB-RLM-PROVENANCE before-state

line applies to any decay-bearing surface: shown a frame, the critic must be able to say what the

place looked like BEFORE, or decay_law has failed on the art side even where the data passes.

4. THE AUTONOMY CONTRACT

registry rows where generation_status IN (pending, regeneration_required), ordered by

generation_tier, and the queue runner takes them one at a time. Work-lists are script-emitted,

never hand-typed (standing rule). The prompt composer reads the row's canon fields + tier axes;

it never invents subject matter.

§5.2 benchmark on that class and its licence clears for that class's intended commercial use.

It is DEMOTED automatically on: a licence change, a deterministic-tooth pass-rate below the class

floor over a rolling window, or an image-critic rejection rate above the class ceiling. The

per-class default lives in one config file, so a demote is a one-line change and every subsequent

dispatch follows it. TRELLIS.2's textured path is permanently demoted to previz by licence and

that entry is a constant, not a benchmark output.

deterministic teeth, the whole DEM/WorldCover/GDAL chain, registry writeback via the sanctioned

writer with fidelity_baseline.json refreshed in the same commit. Failures write rejected and

move on — the queue never blocks on one bad asset.

first asset of a new class or a newly-promoted model; every §17.1 care-gated id — DR-2 item 4

RULED that the in_progresscomplete transition for a care-gated id is blocked until the

capture-rights/authenticity audit signs off. Real living-heritage architecture is never

raw-generated, full stop; the generator's role there is massing blockout only.

model. Any run that would co-reside with UE on the GPU.

5. JOSH-MINIMUM

1. D-1 ratification — confirm WSL2+Puget-pack as the generation host and ComfyUI-Windows as the

image lane only. The evidence now points one way; it needs the word.

2. The Puget burn-in/benchmark sheet — his account, his rep, not auto-delivered. Only

pre-arrival thermal/power baseline for this exact machine.

3. OpenTopography — free non-academic key is 50 calls/24h. Either accept a ~4-day spread across

69 regions, or he buys OpenTopography Plus, or we take the AWS bulk-COG route (no account, no

limit, more engineering). His call because it is a spend/schedule fork, not a technical one.

4. Two licence reads that need a human decision, not an agent's: (a) Hunyuan3D-2.1's EU/UK/South

Korea exclusion — does it block *us* using the model, or block *distributing outputs into* those

territories, or both; this decides whether the textured-PBR lane can ship at all. (b) whether the

SMPL-X-derived ARDY/Kimodo variants are avoidable in favour of the non-SMPL skeletons, or whether

a Meshcapade licence is wanted.

5. Nothing else. No account creation, no purchase, no credential in this lane is agent-work.

6. BENCHMARK-DAY QUESTIONS

1. Does the cu128 rebuild actually produce working TRELLIS.2 / Hunyuan3D-2.1 / Direct3D-S2 on

sm_120 — and how many hours did it cost? (This number decides whether Direct3D-S2 replaces

TRELLIS.2 outright as the geometry primary; S2 is MIT, nvdiffrast-free, and would collapse the

whole previz-firewall problem if its quality holds.)

2. Real 5090 wall-clock and observed peak VRAM per model per class — replacing every [E] in §2

and every H100/4090 figure in the repo briefs.

3. Minutes-of-manual-work-to-game-ready per class, per generator — the only number that actually

schedules the 72-weapon / 132-creature / region-architecture volume. Generation speed is noise

next to it.

4. Does AutoRemesher + xatlas + Blender-headless clear the deterministic teeth unattended, and at

what pass rate? If that rate is low, the whole volume thesis needs re-planning, because no AI

closes this gap today.

5. Does UniRig produce UE-importable FBX rigs on non-humanoid creature anatomy at acceptable

quality — or does the 132-creature roster need a paid point-solution after all?

6. HY-World 2.0: what does WorldMirror-2 actually emit at region scale, what does it cost in VRAM,

and what does its License.txt say — this is the one genuinely new, Blackwell-native,

mesh-emitting worldgen candidate and it is entirely unassessed.

7. Instrument Pixal3D's process at runtime: does its textured output route through nvdiffrec in

practice? Trust the syscalls, not the NOTICE file.

8. Nanite ingest: what dense-mesh triangle count does the finishing pass hand UE before Nanite

VisBuffer cost breaks the doctrine's 2.25 ms budget line?

7. COMPARATOR-PIPELINE ADDENDUM — CREATURE ASSET + RIG PRODUCTION INFRASTRUCTURE (2026-08-05)

APPEND-ONLY addendum under the pipe-dossiers-bind law, from the 2026-08-05 comparator-pipeline research

(Josh: "what about their pipelines?"). This section covers how Capcom actually BUILDS a creature — rig

order, tool chain, automation — against our 132-creature roster. The moveset/telegraph cadence lands on

PIPE_ANIMATION_2026-07-29.md §7; the ability-VFX authoring structure on PIPE_ART_2026-07-29.md §7.

Single primary source for this section, cited per fact:

https://blogs.autodesk.com/media-and-entertainment/2026/04/23/the-production-infrastructure-behind-capcoms-monster-hunter-wilds/

It is a vendor-published production feature, not a first-party conference talk — treat the tool list as

reliable and the framing as promotional. Nothing here is repo canon until the director lands it.

7.1 Scale calibration, stated honestly

Monster Hunter Wilds ran a character section of roughly 60 people; the background section managed 4,500+

assets with external collaborators; hundreds of developers total. **NO-ADOPT — this is the number that

must NOT be transferred.** It is recorded here so that any future claim of "we do what Capcom does" is

read against it. What transfers from this source is automation and ORDER, never headcount.

7.2 The rig order — ADOPT the order, NO-ADOPT the tool

Capcom's technical artists build the skeleton structure FIRST, then simulate muscle movement (Ziva VFX),

then output the simulation result INCLUDING skin and fat to RE ENGINE. Fictional creatures were designed

against real animal anatomy references.

ADOPTED: (a) skeleton-before-deformation as the ruled order for our creature rigs — our UniRig lane

already emits a skeleton, so the adoption is that the deformation/corrective pass is a DECLARED second

stage, not an afterthought; (b) the real-anatomy reference rule, which our creature briefs should carry

per row (a fictional creature still cites the animal its motion is built from).

NO-ADOPT: Ziva VFX itself — Maya-bound, paid, and outside this lane's ruled Blender-headless chain.

Our substitute for the muscle pass is a corrective-shape / secondary-motion pass declared per creature.

This is a real quality delta and it should be named as one, not papered over: their skin slides over

simulated muscle; ours will not, and the honest register for our creature deliverables says so.

7.3 The tool chain, mapped onto ours — one genuine GAP found

Capcom (Wilds)JobOur ruled counterpart (§1)Verdict
Mayaauthoring hostBlender 5.2 LTS headlessequivalent, ADOPTED already
SimplygonLOD / decimation(none declared)GAP — see below
Quad RemesherretopologyAutoRemesher (MIT)equivalent, ADOPTED already
ngSkinToolsskin-weight authoring/repair(none declared)GAP — the real one
Ziva VFXmuscle/fat simulationnone (corrective pass)NO-ADOPT, delta declared §7.2
MotionBuildermocap data processingARDY/Kimodo NPZ → BVH/FBX chainequivalent in role
Houdini Engine inside Mayafur reduction, alpha optimisationnoneNO-ADOPT this cycle
In-house Anim ToolMaya↔engine FBX exchange, rig/weapon switching(ad hoc)ADOPT the pattern — §7.4
Flow Production Tracking (ShotGrid)asset metadata/thumbnailsregistries + generation_lifecycle.jsonequivalent, ours is stronger

THE GAP, named: our chain (UniRig → FBX) has NO declared skin-weight repair step, and ngSkinTools

exists in their chain precisely because auto-generated weights on non-humanoid anatomy are not shippable

raw. This dossier's own §6 benchmark question 5 already asks whether UniRig produces acceptable rigs on

non-humanoid creature anatomy — **the comparator answer is that even hand-built rigs need a dedicated

weight-painting tool, so the honest expectation is that UniRig output requires a weight pass regardless

of how question 5 resolves.** Route: add a weight-repair stage to the creature finishing chain (Blender's

own weight tools are the free counterpart) and make it a declared rung, not an implicit one. The LOD gap

is softer — UE Nanite plus our existing decimation covers most of Simplygon's role for our target.

7.4 The single-tool engine exchange — ADOPT, highest leverage in this section

Capcom built an in-house "Anim Tool" that automates FBX exchange between Maya and RE ENGINE and owns the

complex cases: weapon switching, transformation controls, rig switching. Background assets link to the

engine through custom tools that automatically transfer asset IDs, thumbnail images, polygon counts,

shader names and collision data. Secondary motion is handled by a custom Maya implementation using

Position-Based Dynamics, and a skirt-animation template prevents foot penetration using auxiliary bones

and leg movement vectors.

ADOPTED AND ROUTED: (a) ONE scripted Blender↔UE exchange tool owning rig-switch and attachment cases,

rather than per-asset manual export — this is the same discipline as our ASSET_DROPIN_CONTRACT id rule,

extended to the exchange itself. (b) The engine-side auto-transfer of asset ID, poly count, shader name

and collision is a comparator PRECEDENT for extending our drop-in manifest beyond the id: the metadata

that the audit tooth wants should arrive with the asset, not be re-derived later.

ADOPTED AS A CLASS, not as tools: appendage/cloth penetration is solved by a per-costume TEMPLATE

(their skirt template), never by per-shot fixes. Our creature roster has the same class problem in

tails, wings, mandibles and hanging cloth; a template per appendage class is the cheap answer.

7.5 Nightly automation — ADOPT verbatim, it fits our box exactly

Capcom runs nightly mayapy automation for texture baking, LOD creation and asset commits.

ADOPTED AND ROUTED — this is the highest-value, lowest-cost adoption in the whole researcher-B lane.

The 5090 box is live 24/7/365 and compute-clean; the identical loop in our chain is nightly

blender --background --python doing bake, LOD, and the deterministic finishing teeth, committing what

passes and emitting a worklist for what does not. It needs no new model, no new licence and no GPU

budget negotiation, and it converts the "minutes-of-manual-work-to-game-ready" question (§6 item 3) from

a scheduling risk into a measured nightly number.

7.6 Honest limits

documents this chain, and the GDC Vault MHW postmortem

(https://www.gdcvault.com/play/1024981/-Monster-Hunter-World-Postmortem) was NOT watched. What the

written coverage of that postmortem does add: monsters were placed inside a food-pyramid structure

chosen from the player experience and level curve wanted, and at least one monster (Lagiacrus) was

prototyped and cut — i.e. the roster itself was iterated, not fixed at design time

(https://www.gamedeveloper.com/design/how-capcom-designed-i-monster-hunter-world-i-to-feel-approachable-and-alive ·

https://www.siliconera.com/monster-hunter-world-developers-show-off-prototype-lagiacrus-gdc-2018/).

our own already-ruled tools, and none of them introduces a new dependency.

8. GENERATION PIPELINE V2 — the multi-view routes (APPENDED IN PLACE 2026-08-05)

Charter: docs/FACTORY_CONTINUATION.md tail, "JOSH CALLS THE PIPELINE". This section is the

dossier half of pillars 2 and 3. Pillar 1 (concept-first) and pillar 4 (the routing table) are

policy and live in the charter; this is what was installed, measured, and built.

8.1 Geometry candidates — status

CandidateLicenceStatus 2026-08-05Evidence
Hi3DGen (Stable3DGen)MIT (body pinned, docs/licence_records/stable3dgen/LICENSE)INSTALLED, PROVEN on the throwaway67.3 s · peak 14.1 GiB alloc / 17.0 GiB reserved · 526,630 v / 1,053,224 f · watertight · own venv /root/mv3d/venv
Direct3D-S2MIT (at LICENSE.txt; the conventional LICENSE path 404s)INSTALL INCOMPLETE — blocked on the flash-attn compile, mechanism fully diagnosed in §0's supersessionrepo a1cf235 cloned, own venv /root/mv3d/venv_d3ds2, torch/spconv/CUDA 12.8 in place, flash-attn wheel building at MAX_JOBS=4 after an OOM at 12
MV-Adapter (the natural pillar-3 view generator)Apache-2.0 adapter, openrail++ SDXL baseNOT INSTALLED — flagged for ruling (DL_0026)see §8.4

VRAM is reported as torch.cuda.max_memory_allocated/reserved, a true running maximum held by the

allocator — not a post-hoc nvidia-smi sample. The card is shared with three other lanes, so an

nvidia-smi total would measure the neighbours as much as the model.

8.2 The multi-view texture route — BUILT AND MEASURED

Two committed tools, slotting into the existing chain at exactly the seam bl_finish2.py occupies

(same xatlas-UV'd mesh in, same T_<id>_BC.png out):

the UV atlas plus a coverage MASK, and renders per-view linear depth (and optional unlit albedo).

Writes views.json carrying the world-to-camera matrices actually used, so the merge stage

consumes matrices rather than re-deriving cameras from angles. A duplicated convention would fail

as a texture subtly wrong everywhere and obviously wrong nowhere.

that is the product of frustum × visibility (depth test) × facing (n·v)^p. Colour is the

weight-normalised sum; texels no view can see are reported as HOLES, not invented.

What v1 was doing, now measured. Positive control on MN_0001 (a landed asset whose basecolor

is known, so reconstruction error has ground truth). The ablation runs the *same code* at N views,

so N=1 reproduces the v1 single-projection path and isolates the multi-view contribution from any

bug in the merge:

viewstexels observednever observedMAE (8-bit)PSNR
1 (= the v1 path)30.3 %583,69530.3313.50 dB
255.5 %372,88213.0118.46 dB
491.0 %75,2724.2526.83 dB
892.8 %60,3894.1527.14 dB
2498.6 %11,7873.2429.92 dB

So bl_finish2.py's own docstring concession — "the far side carries stretched front pixels" — is

now a number: **on this asset the single front projection genuinely observes 30 % of the surface and

invents the other 70 %.** That is the white-shell and blur class, quantified. Twenty-four views

recover it to 98.6 % observed at 29.9 dB.

Look at it, do not just read the table: build/3d/v2_mvtex/MV_TEXTURE_PROOF.png is the

reference atlas, the N=1/N=4/N=24 reconstructions and the N=1 vs N=24 coverage maps on one sheet.

N=1 is visibly blotched with flat mis-toned blocks where front pixels were stretched around the

object and its coverage map is mostly dark; N=24 is near-indistinguishable from the reference and

its coverage map is nearly solid white. The numbers and the picture agree.

8.3 Two defects this route caught in itself (kept, because both are easy to repeat)

original Principled BSDF into an unlit scene; a Principled BSDF with nothing lighting it is

black, so all 24 views were black, the atlas came back mean 0,0,0, and the control reported

MAE 49.7 / PSNR 11 dB — a number that reads as a broken projection and was a broken light rig.

Fix: clone each material to an Emission fed by its Base Color.

margin=0 while POSITION/NORMAL keep a gutter. Position and normal want the gutter for filtering;

the mask defines "this texel is really on the surface" and must not.

8.4 Open, and honestly open

1. Direct3D-S2 is not yet proven, and the last blocker is PROCESS LIFETIME, not the build.

In place and verified: repo a1cf235 in its own venv /root/mv3d/venv_d3ds2, torch

2.9.0+cu128 on sm_120, spconv-cu126 (so SPARSE_BACKEND=spconv retires torchsparse), and

nvcc 12.8.93 at /usr/local/cuda-12.8. Missing: the flash-attn wheel, and after that

third_party/voxelize and pip install -e ..

The compile was attempted four times and died four times at exactly

Building wheel for flash-attn (pyproject.toml): started. **Two DIFFERENT causes, and only

the first is a real engineering constraint:** (a) at MAX_JOBS=12 it was genuinely

OOM-killed — dmesg shows cicc invoking the OOM killer on a 61 GB box; (b) at

MAX_JOBS=4 there was no new OOM entry, and the build died anyway when its invoking

wsl.exe wrapper ended — this agent session cannot hold a WSL process alive long enough

for a flash-attn compile, and anchoring the distro with a long sleep did not survive

either. This is the same class as the standing "agents background the final gate step"

lesson: the work is not hard, the process just has to outlive the agent.

Resume in one command from a session that owns a durable shell (expect tens of minutes):

   MAX_JOBS=4 CUDA_HOME=/usr/local/cuda-12.8 PATH=$CUDA_HOME/bin:$PATH \
     TORCH_CUDA_ARCH_LIST=12.0 FLASH_ATTENTION_FORCE_BUILD=TRUE \
     /root/mv3d/venv_d3ds2/bin/pip install --no-build-isolation flash-attn==2.8.3

then pip install --no-build-isolation ./third_party/voxelize and pip install -e ., and

run with SPARSE_BACKEND=spconv.

A fifth attempt used a PERSISTENT source tree at /root/mv3d/flash-attention (v2.8.3) so

ninja objects survive between bounded runs — the right shape for a resumable build, and it

is left in place for the next session. **Measured rate: 1 object in the first ~8-minute

window**, so budget hours, not minutes, and run it somewhere it will not be cut off. Note

the trim env vars set on that attempt (FLASH_ATTENTION_DISABLE_FP8 /

_DISABLE_HDIM256 / _DISABLE_BACKWARD) are unverified for the 2.8.x line — they are

documented for FA3/hopper and may simply be ignored here, in which case the full kernel

matrix is being built and the estimate should assume that. Weights are wushuang98/Direct3D-S2 @

8b04a8eddb7a56a0f4e89fe5f5b840c7d5610c00 (MIT), 10 GB VRAM at 512 / ~24 GB at 1024 per the

repo — note the card is shared, so the 1024 path needs the free-VRAM backoff the standing

lane already uses.

2. The throwaway's coverage ceiling is NOT explained. The Hi3DGen dragon saturates at

52 % observed at 24 views and 54.7 % at 80 — resolution-invariant (512/1024/2048 all ~52 %)

and threshold-invariant (8× depth bias and zero facing floor buy 2.4 points). Three hypotheses

were tested and killed: interior shells (26 components, but the largest holds 99.2 % of volume

and 98 % of area), depth aliasing, and my own thresholds. What remains untested is the **UV

layout**: the throwaway used the Smart-UV-Project fallback, which produces thousands of

micro-islands, where MN_0001 used a production xatlas atlas and reached 98.6 %. **Do not quote

52 % as a fact about generated geometry** — re-run coverage on an xatlas layout of the same mesh

before drawing any conclusion. That is the next measurement this lane owes.

3. The turnaround view GENERATOR is unratified. The route was deliberately built to take views

as (image, camera-matrix) pairs from any source, so nothing is blocked; but the benchmark A/B

the charter asks for needs a ruled generator. MV-Adapter is the obvious candidate and its

adapter is Apache-2.0 — but it is inert without an SDXL base, and SDXL is openrail++.

**The V2 charter says "MIT/permissive weights only"; the standing licence law says face-value

reads and flag only explicit triggered prohibitions, and OpenRAIL++-M permits commercial use,

claims no rights over output, and restricts uses this game does not make.** Those two rules

genuinely disagree. That is a ruling, not an executor's call, so it is surfaced rather than

quietly taken either way (DL_0026).

4. The benchmark set is still blind. The throwaway is Stable3DGen/assets/example_image/0.png,

a coiled dragon figurine shipped with the MIT repo — deliberately NOT one of the charter's

benchmark items (macuahuitl / woomera / madu / nunchaku, the naga, a shelled fauna, the two prop

controls, the garmented body), so the blind A/B still has an unspent set to judge on. It was

chosen because a coil is structurally the same failure class as the documented naga.

---

9. THE V2 BENCHMARK — RESULT (APPENDED IN PLACE 2026-08-05)

**This section supersedes §8's four open items 2 and 3 in part, and answers §6's

benchmark-day questions with numbers.** Full record:

build/3d/V2_BENCHMARK_RESULT.json; work products in D:/assetgen/v2/bench/**;

tools in harness/asset_factory/v2_bench_*.py.

The set and the arms. Nine items, thirty-one item-arm cells, all drawn from

documented failures or documented controls: the four identity-failed weapons

(macuahuitl, nunchaku, madu, woomera), the Khmer Naga, the Sumatran orangutan, obsidian

and native sulfur as controls, and the garmented child body. Arms: (a) the current stack

as shipped, (b) current stack on a canon-keyed picked plate, (c) Hi3DGen on that same

plate with the same single-projection bake, (d) Hi3DGen with the multi-view texture

route. Arm b is deliberately NOT run on the five items whose existing picked plate

already passes an identity read — their arm-b input would be byte-identical to arm a's,

and a duplicate in a blind sheet inflates whichever label wins the coin flip.

Only one multi-view model could be benchmarked. Direct3D-S2's install is still

incomplete (flash-attn compile; no published wheel for torch 2.9 / cp312 / cu12 / linux),

and MV-Adapter remains uninstalled pending the §8 item-3 licence ruling.

THE HEADLINE: the plate is the identity fix; the geometry model is not. Across the

four identity-failed weapons the blind identity mean runs **2.00 (a) → 4.25 (b) → 4.00

(c)**. Arm b changes only the conditioning plate and the surface constants. Arm c changes

the geometry model on top of that plate and moves identity by −0.25. Per item: WPN_036

2→4, WPN_042 2→5, WPN_045 2→5, WPN_072 2→3. **Pillar 1 (concept-first) is the

load-bearing pillar for the identity class; pillar 2 buys geometry, not identity.**

§8 item 2 is CLOSED — the Smart-UV hypothesis is dead. Every cell here carries a

production xatlas atlas from finish_mesh2, and the Hi3DGen meshes still measure

0.517–0.826 observed at 24 views while TripoSG meshes through the identical chain

measure 0.957–1.000. The variable is not the UV layout and not the remesh path (three

TripoSG cells took the tri-fallback and still measure 0.95–0.99): it is RUGOSITY,

surface area over convex-hull area — TripoSG median 0.88, Hi3DGen median 1.47,

Pearson r = −0.7303 over all 31 cells. Hi3DGen models concave relief that TripoSG

smooths away, and an exterior camera ring cannot see into it. **A low coverage number on

a Hi3DGen mesh is evidence of detail, not of a defect** — and the multi-view texture route

will need more than an exterior ring for detailed geometry.

Coverage is not a quality proxy, and this section will not let it become one. The

judged surface score correlates only r = 0.29 with 1-view coverage and r = 0.16

with 24-view coverage. How bad a white shell LOOKS depends on the object: a uniform

wooden baton smears invisibly, a two-tone obsidian smears catastrophically. Report

coverage as coverage.

The instrument was positive-controlled before any arm was scored by it: the shipped,

already-landed MN_0001 atlas measures 0.99937 observed at 24 views through the

identical invocation (records/POSCTRL_MN_0001_shipped_cov24.json).

Arm d ran its geometric half on every cell and its colour half on none. The merge

needs one colour image per view and nothing installed produces a generated turnaround —

Hi3DGen's shipped weights carry only slat_decoder_mesh (read from

weights/trellis-normal-v0-1/pipeline.json, not assumed), so there is no radiance-field

decoder to render colour views from. Re-rendering the v1 atlas from 24 angles and merging

it back would have reconstructed the v1 texture without adding information — a circular

measurement that would have looked like a result — so it was not done. **Cost is not the

blocker: the 24-view stage runs in 2.3 s against the single-projection bake's 2.25 s.**

**Controls: no regression from the multi-view geometry — but the controls did not

reproduce themselves on the current stack.** Arm c improved both (MN_0001 identity 2→4,

surface 1→2; MN_0002 identity 3→4, surface 2→4). Arm a's own fresh re-runs came out worse

than the landed artefacts: MN_0002__a is a negative-volume mesh (inconsistent

winding, 41 raw bodies) whose 24-view coverage is 0.156, the worst cell in the benchmark,

and MN_0001__a lost the obsidian's conchoidal relief entirely. Both passed

finish_mesh2's watertight-and-manifold check. That is the withdrawn-identity lesson

repeating on a new axis: **a healthy mesh census says nothing about whether the object is

the thing it is named.** "The current stack aced the compact-prop class" is a statement

about two landed artefacts, not a reproducible property of the stack.

Silhouette differentiates nothing (every arm within 0.25 of every other, per class),

and the naga's documented silhouette failure did not reproduce on either model — both

built the coil correctly. That failure needs re-attribution.

ROUTING, as the evidence supports it today. Concept-first is ratified for the

identity-bearing classes: a judged, picked plate keyed to the row's own mesh_tags.

Multi-view geometry is a HOLD — on a single-projection bake its extra relief is a net

loss (weapons surface 3.25 → 2.25). Pillars 2 and 3 cannot be bought separately: Hi3DGen's

geometry win only becomes visible through a texture route that can see the geometry it

wins, and that route's gating item is a licensed multi-view colour generator — i.e.

§8 item 3's ruling.

---

10. THE RATIFIED ROUTING TABLE (APPENDED IN PLACE 2026-08-05; TEXTURE COLUMN SUPERSEDED IN PLACE 2026-08-05b)

**This section RATIFIES §9's result into law and supersedes §9's closing "ROUTING, as the evidence

supports it today" paragraph — that paragraph was a recommendation; this is the table the emitter

and the runner now read.** Machine-readable record: build/3d/V2_ROUTING_RATIFIED.json, emitted by

harness/asset_factory/v2_ratify.py, which DERIVES every arm mean from the blind join and refuses

to emit if a route's evidence condition stops holding. Independent cold verifies:

build/3d/v2_bench/RATIFY_COLD_VERIFY.json and build/3d/v2_mva/RATIFY_COLD_VERIFY_MVA.json.

WHAT CHANGED IN THE 2026-08-05b PASS. The TEXTURE column previously read "v1 single

projection" on four rows and BLOCKED on the fifth. The multi-view colour generator that row was

blocked on is now installed, benchmarked and ratified, so every texture cell below is superseded.

Geometry and conditioning are unchanged — the multi-view geometry arm was run separately and

LOST. Texture conditions are evaluated against the MVA blind join

(build/3d/v2_mva/MVA_UNBLINDED.json), never against the earlier session's numbers, because judge

calibration drifts between sessions by more than the differences at stake.

THE LICENCE BAR, CORRECTED. Josh ruled 2026-08-05: the bar is COMMERCIAL USE PERMITTED. The

V2 charter's "MIT-only" phrasing is STRUCK — it was a self-inflicted tightening of the standing

face-value licence law, and it blocked a working route on a bar nobody had set. Full chain in §11.1;

the one genuine exclusion is nvdiffrast, on its own body.

10.1 The table

Class (consumers)ConditioningGeometryTextureStatusEvidence
weapon, equipmentCONCEPT_FIRST — n≥4 plates keyed to the row's own mesh_tags, judged, picked seed liftedTripoSG as shippedMULTI-VIEW (arm e) — MV-Adapter ig2mv 6 views → mv_texture_bake + texel-coverage toothRATIFIED (texture RATIFIED)identity 2.00 (a) → 4.25 (b), n=4; arm c moves identity −0.25 on the same plate. Texture: surface +2.25, n=4, no weapon regressed
creature (folklore/named)CONCEPT_FIRSTTripoSG; Hi3DGen a lead, not a switchMULTI-VIEW (arm e)LEAD (texture RATIFIED, n=1)n=1 (CR_0161): identity/silhouette tie 5/5. Texture: surface 3 → 5 — the far flank and coil interior now carry scale colour
creature (real fauna)CONCEPT_FIRSTTripoSG — no measured deltaMULTI-VIEW (arm e) — *was BLOCKED, the block is LIFTED*RATIFIED (texture RATIFIED, n=1)n=1 (CR_0026): geometry a genuine tie on every axis. Texture: surface 2 → 5, identity 4 → 5 — the white shell was a texture-route defect and the texture route fixed it
mineral, compact env propplate already picked; no plate arm was run for this classTripoSG — HOLDMULTI-VIEW (arm e)HOLD (texture RATIFIED)arm c wins both cells but MN_0002's arm-a baseline is a negative-volume mesh. Texture: identity +1.00, surface +1.50 — these are the CONTROLS and they moved UP
character bodyCONCEPT_FIRSTneither single-pass arm — the two-pass composed body remains the routeMULTI-VIEW (arm e)HOLD (texture ADOPTED ON A TIE, n=1)tie at 4/4/4/3 on both arms. Texture: +0 on both axes — the one class the texture route did not move, recorded as a tie rather than folded into the mean

**The texture headline: surface +1.89 per item across nine items, wins or ties every class,

regresses none. Two teeth hold it there: T6** refuses the emit if any routed class regresses on

arm e, and T7 refuses it if the aggregate falls inside the measured judge-noise floor (1.0,

derived from a mean absolute axis-score change of 1.125 between the two independently shuffled

scoring sessions). A route may not be ratified on drift.

The geometry half was tested and REJECTED. Arm f (Hi3DGen conditioned on six generated views)

scored silhouette −0.89 and form_identity −1.00 across nine items — four ties, four

regressions, zero improvements — and it regressed a control. Mechanism in §11.3, corroborated

in §10.6 by an instrument with no eye in it. Multi-view is a texture win and a geometry loss, and

the two halves are not bought together.

**The headline in one line: pillar 1 is the load-bearing pillar, and pillar 2 is not the identity

fix. Multi-view geometry is a HOLD across every class** — on a single-projection bake its extra

relief is a net loss (weapons surface 3.25 → 2.25), because rugosity is exactly what an exterior

camera ring cannot see into (TripoSG median 0.88, Hi3DGen 1.47, r = −0.7303 over 31 cells). Pillars

2 and 3 cannot be bought separately.

The confound, named and answered. Arm b changed the plate *and* the surface constants together,

and identity was scored on the textured sheet — so the identity axis alone does not isolate the

plate. The clay sheet carries no material at all and still moves form_identity 2.00 → 4.00

on the same change. A shading constant cannot produce a clay-sheet delta, so the geometry changed

because the conditioning image changed. Ratified on that isolation, not on the identity axis alone.

10.2 What is armed, and where

refuses any identity-bearing row that carries no concept_ref — satisfied only by a judged pick

record on disk (<ID>__pick.json) or a declared mesh_pipeline_type = PLATE_CONDITIONED. The

refusal class is NO_CONCEPT_REF and there is deliberately no override flag; the way through

is the re-key worklist the emitter itself emits. Scope is READ from

V2_ROUTING_RATIFIED.json's per-class identity_bearing field so the table and the law cannot

drift — the first version of the law inferred scope from the table's consumer classes and so

gated minerals, a class for which no plate arm was ever run.

an identity-bearing item with no picked seed. Without this the emitter's mark was a promise: run

a batch without --picks and picks.get(cid) returns None, the runner falls through to a

fresh objref, and the id is lifted on an unpicked first sample — the measured 2.00 route, with no

flag needed to reach it. The refusal sits before the --resume reuse on purpose: a cached raw

GLB carries no record of whether its plate was judged.

ratified record and refuses to bake if it is missing, and the route lands on every

generation.json. Shipped route is the v1 single projection; the reason it is not the multi-view

route is the colour source, not cost (24-view stage 2.30 s vs the v1 bake's 2.25 s).

Mutation proofs, all run: v2_ratify.py --mutate {T1,T2,T3,T4,T5,T6,T7} each exit 1 (T6/T7

added 2026-08-05b and re-proven alongside the original five);

emit_standing_worklist.py --mutate strip_route drops the weapons batch 22 → 0 while leaving the

43 non-identity props untouched; --mutate law_source exits 1 on the inert-law positive control;

gpu_stage returns CONCEPT_REF_MISSING for an identity-bearing id, stays silent for a mineral,

and returns the *different* class PICKED_REF_MISSING once a pick is supplied — proving the law

lets a compliant item through rather than refusing everything.

10.3 What batch 3 runs with, and what it costs

**The stack, per identity-bearing asset (SUPERSEDED IN PLACE 2026-08-05b — the texture stage

changed):** 4 canon-keyed plates → judged pick → TripoSG (shipped constants) → finish_mesh2

(xatlas atlas) → MV-Adapter ig2mv 6-view turnaround → mv_texture_bake merge → texel-coverage

tooth. Hi3DGen is not in batch 3, and neither is the multi-view *geometry* arm.

StageMeasuredn
Plate, per candidate5.44 s (5.31–5.64)16
TripoSG geometry, end to end26.2 s (14.6–44.4)13
finish_mesh211.9 s (4.5–32.1)31
MV-Adapter texture route, marginal26.0 s (23.97–29.15)9
~~v1 bake~~ *(superseded; still the fallback where no plate exists)*2.25 s (1.93–2.62)22
Machine total per asset≈ 81 s, ≈ 103 s with one replate
Peak VRAM (TripoSG)5.16–6.09 GiB, median 5.1913
Peak VRAM (MV-Adapter, RESERVED)≈ 29.1 GiB (29.01–29.10)9
Peak VRAM (Hi3DGen, not shipping)10.6–13.8 GiB9
Observed texel fraction (measured, not judged)0.61 mean (0.52–0.79)9
Plate-generator VRAMunmeasured, reported as null — it runs inside the shared ComfyUI process this lane submits to rather than owns, and an nvidia-smi sample on a card shared with three lanes would measure the neighbours

The honest cost of the texture win: ≈ 62 s → ≈ 81 s per asset. A 2.25 s bake became a 26 s

generation, and that buys surface +1.89. It is reported rather than absorbed.

VRAM is now the scheduling constraint, and this is the operationally important line. TripoSG

peaks near 6 GiB and shares the card comfortably. The texture stage reserves ≈ 29 GiB of 32, so

it cannot run beside a second heavy lane and the driver waits for ~24 GiB free before it starts.

**Batch 3 must therefore be staged, not interleaved: run all geometry first (shareable), then the

texture pass alone.** On a box that yields the card to three other lanes, a texture pass scheduled

against a busy neighbour does not run slowly — it waits.

The 61 % coverage is a view-count limit, not a merge defect. The 24-view ablation on a

production atlas reached 98.6 % observed and 30.3 % at one view; six views land where six views

should. Raising the count is the next measurable lever, but the checkpoint is *trained* at six, so

it is an experiment with an answer rather than a free win.

The replate row is budgeted, not treated as an exception. WPN_072's defining peg appeared in

3 of 8 canon-keyed candidates, so n=4 has a real miss rate — and one-shot text conditioning had

roughly a coin-flip chance of shipping the wrong object on that item. **The judged pick is an

attended step and is not in the 62 s**, and neither is queue wait: this lane yields the card to

three others and the yield is unbounded by design.

10.4 The honest cost of arming the law — 154 rows refused today

Re-running the emitter under the law: weapons 70 → 22 kept (48 refused, all

mesh_pipeline_type = TEXT_OBJREF), slice creatures 106 → 0 kept (all refused, the column is

blank across T0_Creature_Roster), flores props 43 kept, 0 refused (correctly out of scope).

That is the law working, not the law misfiring: every refused row is an identity-bearing asset

whose registry still declares the one-shot route the benchmark measured at identity 2.00. The

emitter writes the re-key worklist into its own output (concept_first_law.rekey_worklist),

script-emitted and never hand-typed. **The re-key itself is a registry write and is deliberately

NOT taken here** — the weapon rows are owned by the in-flight remediation lane, and two lanes

writing one registry is the collision class this project retired by construction.

Scope honesty on the extension. Only the weapon class was measured against a one-shot arm.

Creature and character rows are gated by *extension* — the mechanism (thin text-to-image coverage

for a specific named form) is identical for a Khmer Naga, and the charter's pillar 1 is a law

rather than a weapons-only fix. Real fauna is gated deliberately over-wide: an orangutan has

broad coverage and scored identity 5, but the emitter's class token does not separate fauna from a

named folklore being, and of the two available errors — a 5.4 s plate that was not needed, or a

wrong-identity asset landed — the cheap one is chosen on purpose. Minerals and flora are **out of

scope**, because no plate arm was run for the prop class and a law with no measurement behind it is

not a law.

10.5 Two findings the ratification pass added

1. finish_mesh2 has no sign-of-volume or winding test. MN_0002__a declares

watertight: true, manifold: true in its own finish record while census_final.volume is

−1.367 and census_final.winding_consistent is false — an inside-out solid that every

downstream numeric tooth reads as healthy. Re-derived here with trimesh, outside the benchmark's

own tooling. Boarded, not fixed in this pass.

2. TripoSG's peak VRAM was measured 13 times and never reached the record. Every cell's

.gen.json carries peak_vram_gb; §9's cost block reported only Hi3DGen. §2's ~3 GB [E] is

superseded above by the measured 5.16–6.09 GiB band.

10.6 What the 2026-08-05b ratification pass added

Record: build/3d/v2_mva/RATIFY_COLD_VERIFY_MVA.json. This pass re-derived the MV-Adapter result

off the shipped artifacts in a fresh context, with instruments the benchmark did not use, before

any of it became law.

Confirmed. The blind keys re-derive exactly from their seeds over the sorted cell list —

40/40 clay and 31/31 tex — which rules out a key rewritten after scoring to flatter a winner. The

headline deltas recompute exactly from the raw scores joined to the keys. Four arm-e assets

re-rendered from their shipped GLBs at azimuth 45/135/225/315 and elevation 0.75, plus two low

raking views at 0.10 — no angle shared with the benchmark's 0/90/180/270 at 0.42 — and CR_0026's

white shell is genuinely gone, MN_0001 the control shows no regression, WPN_045's surface 1 → 5 is

real.

Arm f's rejection is corroborated by a second, eyeless instrument. PCA principal extents on the

shipped meshes: WPN_045 arm f is a flat pancake (flatness 8.88, length/width 0.90) where arm c

is two slender batons (1.38, 3.38); WPN_072 arm f collapses to length/width 1.11 from arm

c's 8.39. The blind judge and the ruler agree.

THE FINDING THAT BOUNDS THIS TABLE — the flat-profile weapon class fails on every arm. The

macuahuitl question was put as a binary and the answer is *yes on the material, no on the

morphology*. WPN_036 ships as a hardwood body carrying a continuous row of black stone blades —

correct — but photographed down its own long axis it is a circle, and its blades sit in a

single median channel rather than along both long edges. The canon row says "a flat broad

paddle of hardwood … both long edges channelled". Measured flatness (width/thickness):

WeaponCanon cross-sectionabc/df
WPN_036 macuahuitlflat (real ≈ 3–4)0.991.791.021.61
WPN_072 woomeraflat (real ≈ 5–7)1.171.810.861.35
WPN_042 maduplanar2.668.516.982.34
WPN_045 nunchuksround1.013.111.388.88

The madu reaches 6.98 correctly and the nunchuks sits at 1.38 correctly, so the instrument is not

calling everything round — the defect is specific. No arm in the programme fixes it. The blind

identity axis could not price it in because a textured rod shot at 23° from four cardinal azimuths

reads as a paddle.

This does not touch the texture ratification — arm e's geometry *is* arm c's, byte-identical,

so the defect sits on both sides of every texture delta and cancels. What it does is **bound the

claim**: conditioning fixed *which object* gets made; it did not fix cross-section fidelity to the

canon row. The table may not claim weapon identity is solved. Boarded, not fixed here.

A methodology defect, for the next benchmark. The blind sheet is arm-blind *and* target-blind,

so the judge must infer which roster item each cell was meant to be before scoring "is this the

NAMED object". Cell T17 (WPN_072 woomera, arm b) was read as "a broad wooden leaf-blade … the

defining inset teeth are absent" — inset teeth are the *macuahuitl's* criterion, so a woomera was

scored against the wrong canon row. Arm b's two objects are near-identical in proportion (1.79/4.50

against 1.81/4.85), which is how they became confusable. Impact on the conclusions: none — T17

is an arm-b cell, enters no headline, and correcting it would raise arm b rather than lower it. The

fix is to show the judge the canon row id and its morphology text per cell: that keeps the A/B

blind, which is the only blinding the comparison needs, while making the identity axis well-defined

instead of a guess.

One scoring disagreement, recorded because it moves the treatment arm DOWN. The cold verify

re-scored WPN_042's arm b at identity 4, not the recorded 5: the canon row's most specific

clause — two horns pointing in OPPOSITE directions — is not realised, the mesh puts both horns

in a V. Cold arm-b mean 4.00 against the recorded 4.25. Either figure clears the ratification

threshold by a wide margin and the winner is unchanged.

---

11. MV-ADAPTER — THE TURNAROUND GENERATOR, INSTALLED AND BENCHMARKED (APPENDED IN PLACE 2026-08-05)

**This section closes §8.4 item 3 and supersedes §9's "only one multi-view model could be

benchmarked".** Full records: build/3d/v2_mva/INSTALL_RECORD.json (install, licence route,

throwaway) and build/3d/v2_mva/V2_MVA_RESULT.json (the two arms, blind-scored). Tools:

harness/asset_factory/mva_views.py, run_hi3dgen_mv.py, bl_apply_bc.py, v2_mva_arms.py,

v2_mva_blind.py, v2_mva_unblind.py, plus `bl_mv_stage.py --cameras --render-pos-normal

--upright --mva-normalize`.

11.1 The licence question is RULED, and it excludes one thing rather than nothing

Josh ruled 2026-08-05, verbatim: *"This doesnt matter to me.. why would it? If you need the

license that permits commercial use than get that one?"* The bar is COMMERCIAL USE PERMITTED.

The V2 charter's "MIT/permissive weights only" was a self-inflicted tightening of the standing

face-value licence law and is STRUCK. Every body below was fetched over the wire this pass and

is pinned by sha256, because a model-card summary is not a licence.

ArtifactLicenceClassRow
MV-Adapter (adapter code + weights)Apache-2.0, body c71d239d…shippableDL_0026 (superseded in place from LICENCE-READ-ONLY)
stabilityai/stable-diffusion-xl-base-1.0 @ 462165984030CreativeML Open RAIL++-M, body 19b6998b…shippableDL_0027
huanngzh/mv-adapter @ 6de4033df6b5 (both checkpoints)Apache-2.0shippableDL_0028
nvdiffrastNvidia Source Code License (1-Way Commercial), body ce20436c…EXCLUDEDDL_0029
madebyollin/sdxl-vae-fp16-fix @ 207b116dae70MITshippableDL_0030 (upstream card: docs/licence_records/sdxl_base/sdxl_vae_fp16_fix_README.md)

The OpenRAIL++-M body, read at face value: §III says the licensor "claims no rights in the Output

You generate", there is no non-commercial clause anywhere in it, and Attachment A restricts uses

this game does not make. It clears the bar. **nvdiffrast — pinned in MV-Adapter's own

requirements.txt — does not:** its body grants use only where the work "may be used or intended

for use non-commercially", defined as "research or evaluation purposes only". That is the same

taint §1 already banned TRELLIS.2's textured path for, and the ruling excludes it.

Excluding it costs nothing, and the diagnosis is precise. mvadapter.pipelines.* — the actual

diffusion pipelines — import CLEAN on a box with no nvdiffrast. What is tainted is the whole

mvadapter.utils package, because its __init__ imports mesh_utils.camera,

mesh_utils/__init__.py imports .mesh and .render unconditionally, and even

mesh_utils/utils.py — whose job is to hold the type alias LIST_TYPE — imports nvdiffrast at

module level. **Same failure class as Direct3D-S2's flash-attn blocker in §0: an unconditional

module-level import in a package __init__ makes an optional dependency mandatory for code that

never calls it.** mva_views.py therefore loads the two pure-math helpers from their own files by

path under a synthetic package supplying only LIST_TYPE — MV-Adapter's own Apache-2.0 code,

unmodified, nothing vendored, no stub impersonating nvdiffrast — and **refuses to run if

nvdiffrast ever appears in sys.modules** (mutation-proven both directions: clean interpreter

passes, an injected ModuleType makes it fire). The rasterization it would have done is done by

Blender headless, whose output is unencumbered.

11.2 Install and throwaway

Own venv /root/mv3d/venv_mva on the same sm_120-proven pin as Hi3DGen (torch 2.9.0+cu128,

diffusers 0.31.0) — deliberately, because an independent venv on a different torch would make every

cross-arm timing and VRAM comparison meaningless. The proven Hi3DGen venv was re-checked after the

install and is unchanged. Throwaway (i2mv on the MIT example plate, not a benchmark item):

46.3 s end to end, peak 21.0 GiB allocated / 29.6 GiB reserved by the allocator's own running

maximum, six views consistent in palette, horns, crest and base, **view 3 a real modelled BACK

rather than a smear of the front**. build/3d/v2_mva/THROWAWAY_i2mv_GRID.png.

29.6 GiB reserved on a 32 GiB card is the scheduling fact: this model needs most of the card

and cannot run beside a second heavy lane.

11.3 THE RESULT: multi-view is a TEXTURE win and a GEOMETRY loss

Two arms, each a clean single-variable pair against a cell that already existed, re-scored blind

alongside all 53 pre-existing cells in one session under a fresh shuffle (seeds 20260812/13 — not

the original, whose key is on disk).

ArmAgainstWhat differssilhouetteform_ididentitysurfaceVerdict
e — MV-Adapter ig2mv views merged by mv_texture_bakearm cthe texture route ONLY (mesh byte-identical)+0.44+1.89ARM E WINS
f — Hi3DGen run_multi_image on i2mv viewsarm cthe conditioning ONLY (1 plate vs 6 views)−0.89−1.00ARM C WINS

Arm e wins or ties every class and regresses nowhere. Per class: weapons +0.25/+2.25, fauna

+1/+3, naga 0/+2, controls +1/+1.5, child tie. The cleanest single result is CR_0026 — the

white-shell fauna item §9 named as the best evidence for pillar 3 and against expecting pillar 2 to

fix it: surface 2 → 5, identity 4 → 5. The white shell was a texture-route defect and the

texture route fixed it. Biggest mover overall is WPN_045, surface 1 → 5 ("a thin wood stripe on

one side and white everywhere else" → "full wood grain on all four views, dark end caps, the cord

itself textured"). Contamination sensitivity: the executor had seen a labelled a/c/e comparison of

WPN_036; dropping that item entirely leaves the verdict unchanged and the win slightly larger

(+0.5/+2.0).

Arm f loses, and the mechanism is diagnosed, not guessed.

build/3d/v2_mva/ARM_F_MECHANISM_i2mv_views.png shows WPN_045's six i2mv views (which collapsed to

silhouette 1 / form-identity 1 — read blind as "a scatter of loose disconnected sticks and a

separate blob; no single object at all", against arm c's 5/5) beside WPN_042's (which tied at

5/5). WPN_045's views are not a turnaround of one object: different arrangements, different

counts, different scales, lying on a surface with cast shadows, one view a spoon entirely.

WPN_042's are a clean consistent turnaround. **The rule: i2mv INHERITS THE PLATE'S STAGING. A plate

that stages the object in a scene produces views of a scene, and a scene cannot be reconstructed as

one object.** run_multi_image in stochastic mode hands each denoising step a different view, so

inconsistent views are conflicting evidence and the sampler resolves them into fused sheets or

loose fragments. Every bulky, single-piece, already-upright subject ties.

What is NOT claimed: that multi-view geometry conditioning is worthless. What is measured is

that *unregistered i2mv views feeding a stochastic multi-image sampler* are worse than one good

plate on thin multi-part subjects and neutral elsewhere. A geometry model that consumes views

with their cameras — which run_multi_image does not — is a different experiment.

11.4 Two defects found by measurement, both kept

four of six MV-Adapter views were a featureless dot or a hairline strip — most of the

conditioning budget spent on nothing. bl_mv_stage.py --upright RATIO stands the longest axis up.

The gate is a ratio, not a class list: at 1.6 it fires on exactly the three long thin weapons

(8.85 / 3.38 / 6.57) and leaves the naga and child (already Z-longest) and the

near-equidimensional minerals and orangutan (1.01–1.07) authored. **Found by LOOKING at control

images, not by a failing assert.**

views_used 0, observed_fraction 0.0, 673,692 texels hole-filled — and still wrote an atlas

and a GLB that looked fine at a glance. Cause: mva_views.py runs in WSL and records /mnt/d

paths the Windows merge cannot stat, so all six views were correctly refused as "no colour

image". It was caught only because mv_texture_bake.py REPORTS holes instead of hiding them.

Fixed by path translation plus a refusal: a cell whose bake observed nothing is marked FAILED and

never reaches a blind sheet.

11.5 Open, and honestly open

1. The 60% coverage ceiling is a VIEW-COUNT limit, not a merge defect. Observed texel fraction

runs 0.516–0.794, mean 0.613, against the ablation's 30.3% at one view and 98.6% at 24 on a

production xatlas atlas. Six views land where six views should. MV-Adapter's adapter is

initialised with num_views, so more are constructible — but the checkpoint is **trained at

six**, so raising it is an experiment with a measurable answer, not a free win.

2. Judge noise is now quantified and it is not small. Re-scoring the 53 pre-existing cells under

an independent shuffle reproduced 74 axis-scores exactly and changed 32, mean |change| 1.125.

A one-point difference on a single item is inside the noise floor — which is why every result

above is a class mean over multiple items, and why the two headline effects (+1.89 surface,

−1.00 form identity) are reported as real: they are larger than the drift. The earlier session's

headline survives the re-score.

3. The staging finding generalises past this arm. A concept plate that stages its subject in a

SCENE rather than isolated degrades every downstream generator conditioned on it. That is the

objref doctrine with a second independent piece of evidence.

SUPERSESSION 2026-08-06 -- the FITTED-GARMENT class leaves the TripoSG route (in place, per the dossier law)

RULED by the director on the CHAR_0001 arrival-outfit rebuild, as a CLASS rule and not an exception.

Anything whose binding constraint is FIT AGAINST A SPECIFIC SOLVED BODY -- garments, armour worn over

a body, gloves, boots -- routes to FIT-FIRST AUTHORED GEOMETRY, with the picked concept plate

conditioning the REGISTER, the material and the ornament rather than the silhouette. The silhouette

belongs to the body.

The reason is evidential rather than architectural: image-to-3D produces a garment on its own body at

its own proportions, and no amount of conditioning makes that garment fit a mesh it has never seen.

Identity, which is what the concept-first law was ratified to protect, is not this class's hard

problem -- a fitted top and fitted trousers are trivially pinned by text.

Measured on the first asset through it, against the body the game boots, on the AUTO rule's own

instrument (char_cloth_thickness.signed_thickness):

penetratingworstp01
face-extraction (the rejected layer)11.996 %-5.876 mm-3.460 mm
fit-first authored2.230 %-7.822 mm-1.544 mm

5.4x fewer penetrating vertices and a p01 tail less than half as deep; the deeper single worst case

is a 0.017 % residue (23 vertices) at the collar.

THE FREE-STANDING IDENTITY CLASSES ARE UNTOUCHED -- weapons, props, creatures and minerals keep

TripoSG. Scope follows the evidence, exactly as the original ratification did. The machine-readable

row is routing.fitted_garment in build/3d/V2_ROUTING_RATIFIED.json.

Generated by harness/site/structure_site.py — the URL path is the repo path. review root