CHARACTER_FACTORY_PLAYBOOK.md

npcs/CHARACTER_FACTORY_PLAYBOOK.md

THE CHARACTER FACTORY PLAYBOOK

Chartered by Josh, 2026-08-07: *"track what the trends were and what we did to make these
better… this pipeline needs to be automated… we have a lot of shit to create."*
What this is. The protagonist's end-to-end journey, distilled into the pipeline every other
living asset runs — companions, supporting cast, NPCs, bosses, creatures where humanoid. One
character was carried from a blank prompt to four approved exemplar plates and a measured 3D
route over roughly thirty-six hours of graded iteration. That run produced a set of recipes that
work and a longer set of things that do not, each of them measured. **This document is the
extraction: the winning recipe per stage, the named traps with their numbers, the instruments,
and the exact points where Josh's eye is the gate.** It is the driver spec for the automation.
Status: ACTIVE v1.0 · Tier T99 operational — it sets no canon and changes none. Where it
states a design fact it cites the ruling that made it.
Citation form: path plus an exact quoted string or JSON key, never a line number. Gate 46
line_citations records the line-range backlog as an Option-A worklist that *must shrink*, and a
new playbook is a poor reason to mint two hundred fragile pointers into a shared tree. Every claim
below is greppable.
Honest tier: EXTRACTION. Nothing here is a new capability. Every recipe cited as WINNING has a
landed record and, where the record says so, a Josh grade. Every stage marked BUILD is named
as unbuilt rather than described as if it ran.

---

§0 THE HEADLINE — the seven things this run actually taught

Read these first; every stage below is one of them applied.

1. THE SIMPLEST FAITHFUL OPERATION BEATS EVERY ENGINEERED CHAIN. The merge that Josh approved is

the *control arm*: the raw exemplar head aligned onto the picked body, minimal processing. Four

engineered passes — exposure match, head rescale, body restore, membrane heal — were each built to

close a defect an instrument reported, and none survived his eye. His words on the winner:

*"if youre seeing defects it might be your math thats wrong"*

(docs/spine/DECISIONS_PENDING_JOSH.md :: RAWHEAD CONTROL APPROVED). Instruments recalibrate

against approved cells as ground truth; defect maths that scores an approved cell down is wrong by

definition.

2. THE EYE OUTRANKS THE INSTRUMENT, AND THE LAW IS NOW WRITTEN. The DIRECTOR EYE-PASS LAW: no

gradeable reaches Josh without the director's own per-tile sighted audit recorded first; a lane's

gate table is an input, never the pass (DECISIONS :: JOSH GRADES THE AGE LADDER - HORRIBLE). Its

3D twin: *"no 3D stage advances on instrument numbers alone"* (DECISIONS :: 3D UNGATED FROM

IN-BETWEENS + DIRECTOR SIGHTED 3D LAW).

3. IDENTITY DOES NOT TRAVEL ACROSS AN AGE GAP, AND AGE DOES NOT TRAVEL BETWEEN TWO REFERENCES.

Both directions are measured. A full-strength reference sets the AGE as well as the face; and two

references over one canvas produce a ghost, not a midpoint. Every age rung conditions on a

reference already at its age (build/art/characters/face_evidence/inbetween/AGING_METHOD_RESEARCH.md

§1).

4. GEOMETRY IS SOLVED BEFORE ANY GENERATIVE PASS, NEVER AFTER. A head-unit ratio says nothing

about where the chin sits; solving on it set four neck lengths +20/+25/+26/+5 percent long

(DECISIONS :: MERGE LANDED — GEOMETRY FIRST, IDENTITY MEASURED).

5. THE MISSING STAGE WAS A BASE MESH, NOT A BETTER MODEL. Every 3D defect Josh named —

*"scoliosis… doesn't look like actual 3D models"* — followed from assembling lofted parts and

solving proportions onto the assembly. The rejected chain was nearly perfectly symmetric and

still read bent, because the defect was part seams (build/3d/PIPELINE_RESEARCH_AUG2026.md,

"The finding that reframes the whole problem").

6. AN INSTRUMENT THAT HAS NOT BEEN MUTATED IS NOT ARMED. Three separate instruments in this run

were wrong in a way that nearly inverted a verdict, and each was caught by a positive control, not

by review. The rule is in §5.

7. PROPORTION TRUTH IS RESEARCH, NOT INTUITION. The single most damaging artefact of a scaled

adult is an identical leg-to-trunk ratio at every age; the cormic index actually falls to a minimum

at 13 and rises again (build/3d/characters/body_specs/AGE_PROPORTION_RESEARCH.md §3).

---

§1 THE STAGE LIST — one table, fourteen stages, the whole factory

Every character is stamped from this chain. EXISTS = a proven tool with a landed record.

BUILD = specified, not built. The architecture is ratified: ONE BARE MESH, PARTITIONED — geometric

merging of independently generated parts is BANNED, with the head↔body bridge as the single named

RETIRING exception (DECISIONS :: THE PARTITION IS RATIFIED; brief at

docs/pipeline_review/BODY_ASSEMBLY_ARCHITECTURE_BRIEF_2026-08-06.md §6).

#StageWinning recipe lives atStateHuman gate
0Reference & concept intakebuild/art/characters/CHAR_0001_CANON_SHEET.md · the canon rowEXISTSJosh supplies floor references
1Face exemplar — bracket → pick → per-age directharness/asset_factory/keystone_direct.py, keystone_wave2.pyEXISTSJOSH PICKS the cell, per age
1bBare / bald conditioning derivativesharness/asset_factory/bare_derivative.py, bald_derivative.pyEXISTSverify-only
2Body — anthropometry solve → physique bracketbuild/3d/characters/body_specs/BODY_AGE_*.json, body_keystone_lane.pyEXISTSJOSH PICKS the physique bracket point
32D merge — face onto body (the rawhead recipe)build/3d/characters/body_specs/merge_route_a_v8.py, merge_identity_v6.pyEXISTSJOSH APPROVES the merged keystone
4Aging ladder — keystones first, landmark-warp in-betweensharness/asset_factory/aging_ladder.py, face_landmark_warp.py, inbetween_faces.pyEXISTSJOSH PICKS each in-between
5Cage source decision + wrap/conformbuild/3d/cage/CAGE_PICK.json (Lane S2 picked)EXISTSdirector; blend-proof blocker CLOSED as an instrument-reference defect (blend_fix/BLEND_G4_REFERENCE_FINDING.json, 869ba32f; superseded in place 2026-08-10)
63D mesh generation — image-to-3D as base sculptHi3DGen (live default); TRELLIS.2 arm pending a gateEXISTSdirector sighted, every artifact
7Cleanup — shell removal, symmetrize on the fitted planebuild/3d/bakeoff/measure_mesh.py + the fitting stagePARTIAL
8Lattice-fit to spec — raised-cosine girth drivebuild/3d/bakeoff/fit_girth_lattice.pyEXISTS
9Region partition + doll-underwear standardsthe partition ruling; R05_PELVIC_GIRDLE carve-outBUILD
10Texture — 6-view MV-Adapter, chunk-by-chunk, SeedVR2 detailharness/asset_factory/mv_texture_bake.py, seedvr2_refine.pyEXISTS / weights oweddirector sighted
11Rig + bind + ROM calisthenicsbl_skin_to_mannequin.py; ROM unbuiltPARTIAL
12Turntable acceptance — every angle, iterate to identicalbuild/3d/cage/render_turntable.py, docs/LOOKDEV_STANDARD.md §4EXISTSdirector sighted; Josh on the final
13Game import + the swap gauntletemit_manifest_from_landed.py; HumanityGarmentComponentPARTIALin-engine capture

Critical path: 5 → 8 → 9 → 11. Everything downstream of the cage is blocked on the cage. Stages 1,

2, 3, 4, 6 and 10 run in parallel today on tools that already work.

---

§2 THE STAGES IN DETAIL

Stage 0 — Reference and concept intake

THE RECIPE. A character enters the factory with three things on disk before a pixel is generated:

its canon row (registries/T0_Character_Index [ACTIVE v1.1]), a canon sheet naming what is fixed

(build/art/characters/CHAR_0001_CANON_SHEET.md, CHAR_0002_CANON_SHEET.md), and a **floor

reference** — Josh's own panel, which is the minimum bar and never the target.

THE FLOOR/EXEMPLAR DISTINCTION IS LOAD-BEARING AND WAS RULED TWICE. *"These are the floor"* then

*"Floor is not exemplar"* — the panels are the MINIMUM; the exemplar must EXCEED them: the panel's

appeal, warmth and charm RETAINED with photographic fidelity ADDED ON TOP. A cell that merely

reproduces the painted panel fails on fidelity; a cell that trades the panel's charm for fidelity

fails on appeal (DECISIONS :: CONFIRMATION / CLARIFICATION, 2026-08-06 night).

Landed floors for CHAR_0001: build/art/characters/CHAR_0001_AGE_BAND_FLOOR_JOSH_20260806.png

(age 7), CHAR_0001_AGE11_FLOOR_JOSH_20260806.png, CHAR_0001_AGE14_FLOOR_JOSH_20260806.png, and

CHAR_0001_AGE18_PROPORTION_REF_JOSH_20260806.jpeg — the last of which is explicitly not a floor:

Josh named the identity mismatch himself and gave it proportions-and-age-read status only.

THE TRAP — THE FLOOR'S OWN OVERSHOOT. Josh's original ChatGPT ladder is the beauty floor but its

adult panels overshoot: *"the age 18-24 looked like 20s to mid 30s."* Adult keystones take the floor's

CHARM read, never its literal adult age read (DECISIONS :: THE KEYSTONE AGING METHOD + TOOL FREEDOM).

---

Stage 1 — Face exemplar: bracket → pick → per-age direct

THE WINNING RECIPE, verbatim from the record (build/3d/characters/CHAR_0001_KEYSTONE_7.json

:: wave2_josh_fixes.recipe_unchanged):

FLUX.2-klein-4B, M1's preserved first-contact graph, 1344 / 28 steps / cfg 4.0 / euler-simple,
cleaned reference VAE-encoded full size through ReferenceLatent at full strength, start latent
EMPTY. Only clauses and refine strength move in this wave.

The age-7 pick that validated it is BRACKET_B_HEAD_D22_S1 — a klein refine over the graded base's

own pixels at denoise 0.22, at the base's own generation seed 972000. Josh: *"on the

protagonist face, yes tile 4 i agree this is perfect"* (DECISIONS :: THE PICK). Every asset in the

record carries its sha256: the conditioning plate 37cafb4e…, the pick c29e34db…, the prompt string

3b6c15e3….

THE GRAPH, node for node (harness/asset_factory/bench_face_models.py, graph_flux2_first_contact;

checkpoints flux-2-klein-base-4b.safetensors / clip qwen_3_4b.safetensors type flux2 / vae

flux2-vae.safetensors): UNETLoader → CLIPLoader → VAELoader; CLIPTextEncode(prompt) and

CLIPTextEncode(""); EmptyFlux2LatentImage(1344,1344); `LoadImage(reference) → VAEEncode →

ReferenceLatent(conditioning, latent)KSamplerVAEDecode → SaveImage`. **The reference is

VAE-encoded at FULL SIZE with no megapixel rescale**, and the start latent is EMPTY. When reference

strength drops below 1.0 a ConditioningAverage is spliced in; at full strength it is not.

THE BRACKET SHAPE, exactly as it ran (build/3d/model_survey/face_2026_08_06/BRACKET_VERDICT.json).

HELD: the prompt, the base's own pixels as start latent, the anchor's recipe/sampler/steps/size. SWEPT:

denoise 0.22 / 0.26 / 0.30 / 0.34 / 0.38 × seeds 972000-972003 = 20 cells, **plus 4 NULL cells at

denoise 0.02 (the instrument's own noise floor) and one generation-side anchor cell — 25 total**.

Preceding waves in the same survey: BENCH (2 candidates A/B) → TUNE (cfg 3.5/5.0/7.0 × reference

strength) → SURFACE_SWEEP → REFINE → BRACKET. Gate thresholds are measured, not chosen:

aspect_delta_abs_max 0.004877, hair_mass_delta_abs_max 0.006799, identity_copy_to_M1_min 0.9558,

iou_sanity_band 0.938 of 20 cells failed.

THE SEED IS THE LEVER, and the record refuses to rank on the axis its instrument cannot separate.

Seed 972000 lands 1.34–1.40× the anchor's detail at *every* denoise; the other three seeds land

1.08–1.14× — no overlap anywhere in the bracket. Meanwhile denoise 0.22/0.26/0.30/0.34 give

1.392/1.396/1.373/1.369, a 2% spread inside the NULL cells' own 0.047 noise floor, so

*"THE DETAIL INSTRUMENT CANNOT SEPARATE THEM, and this record refuses to rank them on it."*

THE ANCHOR GATE, and the drift it caught. BRACKET_ANCHOR must reproduce BENCH_B_HEAD_M1 at

silhouette IoU 1.0000 before any cell counts. It fired: graph_flux2 had been silently rewritten to

the vendor template's shape (SamplerCustomAdvanced + CFGGuider + Flux2Scheduler + a 1 MP reference

rescale), so *"the 'anchor' was running a different graph and calling itself the anchor"* — measured at

IoU 0.930, detail 1.19×, hair flipped SILVER→warm. **That is the second time in this programme a control

has caught a recipe drifting under a record's feet.**

THE PROMPT IS ONE FUNCTION, PROVEN BY REPRODUCTION. fullprompt_control(P) (sha256

72f611a0…, 6,114 chars) is called by both the refine and the bracket so the prompt cannot drift,

and the byte-verbatim claim is proven by reproducing the string rather than asserted from a hash. Its

clause stack is imported byte-verbatim from the generation-1/2/3 plate lanes (COMPLEXION, EAR_SWEEP,

EAR_ANATOMY, EAR_TRANSLUCENCE, EAR_SKIN, CATCHLIGHT, EYE_SURFACE_G3, IRIS, LASH_LINE,

LIGHT, REGISTER_RH, STAGING_PRE, STAGING_POST, TEXTURE_RH, NOSE, ORIENT, SKIN,

FRAMING, EXPRESSION) — clauses are imported, never retyped.

THE PER-AGE DIRECT RECIPE — and it supersedes the transform chain. Four iterations of deriving

11/14/18 from the age-7 pick by transform all degraded identity AND fidelity. RULED: each age keystone

is generated directly from its own Josh reference — clean/upres the reference → identity-condition

on it → photographic direction → refine at its own seed → judge against the floor. Cross-age

continuity is enforced by CHECKS against the pick, never by transform chains (DECISIONS :: THE

PER-AGE DIRECT RECIPE + SEPARATE CONTEXT WINDOWS). It is the first thing in the programme Josh graded

*"these turned out really well."*

Implementation: harness/asset_factory/keystone_direct.py — `RECIPE = dict(CANDIDATES["B"], steps=28,

cfg=4.0, size=1344, scheduler="simple", path="first_contact_ksampler"), SEEDS = [972000, 972001]`

(two candidates per age), cleaned references at `build/art/characters/face_cond_keystones/

CHAR_0001_FLOOR{n}_clean_1344.png` — *"head-and-shoulders on a flat mid-grey field at 1344"*, the keeper

step of the age-7 recipe. The judging is deliberately not the script's: *"the two-axis

exceed-the-floor verdict — the floor's charm/warmth RETAINED, photographic fidelity ADDED — is the

director's sighted read."* Wave-2 successor: keystone_wave2.py; winners in

build/art/characters/face_evidence/KEYSTONE_WAVE2_WINNERS.json (W2_7FX18N, W2_11W2R_GEN_S1,

W2_14W2_RL18_S1, W2_18FX18), with rung 7's winner being **the pick held as its own reference and

refined over its own pixels at seed 972000, denoise 0.18.**

THE THREE MEASURED FINDINGS THAT DROVE WAVE 2, each of which now binds every future age rung

(KEYSTONE_WAVE2_VERDICT.md):

on the age-7 pick returned the age-7 pick — and still did at ConditioningAverage blend weights 0.35

*and* 0.55 (copy-to-pick 0.9958 at both). So identity never travels across an age gap.

whenever the base was a reference; only an EMPTY-latent generation came back without it.

THE NAMED TRAPS.

clause had already demonstrated: *"if you state that its going to be too over conservative… youll

force the model to focus on that only and losing significant context token value that needs to be

spent on keeping to the identity and fidelity."* RULED: coverage/register is **removed from prompt

text entirely**, implemented as framing defaults and sighted post-checks at zero prompt cost

(DECISIONS :: THE REGISTER MOVES OUT OF THE PROMPT). The same law killed per-lane recitation of

rules and hard lines: *"remove the existing rules and hard lines! youre wasting context tokens."*

model to preserve the very proportions the edit exists to move. Wave 2 holds identity FEATURES and

releases the proportions in as many words.

on sheets come from a sighted read (DECISIONS :: JOSH GRADES THE AGE LADDER - HORRIBLE).

alignment carries it back up. Measured cost across four rungs: figure micro-texture 48.9→41.3,

103.7→84.8, 74.9→61.7, 77.6→65.7 — 16 to 18 percent, spent on a resample that buys nothing. The

busts are 1344², already a clean latent shape: remove the node (DECISIONS :: THE BLUR HAS A

MEASURED CAUSE AND A PERMANENT FIX).

and the 18 robe are on the face defect list; face plates are bare-base head-and-shoulders at

every age (DECISIONS :: SUPERSESSION - 95821f11 WAS A DIRECTOR MISREAD).

THE HUMAN GATE. Josh picks the cell, per age, from the contact sheet. Four picks are locked:

age 7 BRACKET_B_HEAD_D22_S1, age 11 KEY11D_REF_S2, age 14 W2_14W2_RL18_S1, age 18 W2_18FX18

(DECISIONS :: KEYSTONE PICKS LOCKED). Faces were subsequently closed: *"the four bare keystones are

'perfect faces'"*.

---

Stage 1b — Bare and bald conditioning derivatives

Two derivative stages exist because the geometry lift must never see a garment or a mass of hair.

BARE DERIVATIVE (harness/asset_factory/bare_derivative.py; four-keystone driver

bare_keystones.py). The picked plate's garment region is inpainted to bare shoulders/upper chest at

the pick's own seed 972000, denoise 1.0 inside the mask, with the pick composited back everywhere

the mask is zero. Byte identity outside the mask: max abs difference exactly 0 on all four rungs —

age 7 1,322,496 of 1,806,336 px untouched, age 14 1,399,104, age 18 1,252,608; age 11 was already bare

and passed VERIFY-only (docs/PIPELINE_LEDGER.md :: FACE LANE — THE FOUR KEYSTONE BARE BASES).

THE ARCHITECTURAL CLAIM, in the tool's own words: *"identity is held by a MASK rather than by a low

denoise: the latent noise mask confines every changed pixel to the garment band … the denoise inside

the band can go to 1.0 without touching the thing Josh graded."*

Constants: GARMENT_MARGIN = 0.08 (required mean(R−B) separation, skin vs cloth) ·

SKIN_PROBE = (0.78, 0.845) / CLOTH_PROBE = (0.88, 0.98) as fractions of subject height ·

MASK_TOP_MAX_FRAC = 0.55 · MASK_LIFTS = {TIGHT 0.02, MID 0.045, ROOM 0.07} — the three-cell mask

bracket, and ROOM landed at both 14 and 18 · FEATHER_FRAC = 0.012 of frame height ·

NULL_DENOISE = 0.02 · DEF_SEED = 972000. Landed masks: age 14 top y=1066 (25.5% regenerated),

age 18 top y=958 (33.5%). The mask is full-width by design — *"a bare shoulder is NARROWER than

a clothed one, so the pass must be free to paint background where the tunic used to be."*

Graph: the img2img graph plus LoadImageMask(channel="red")SetLatentNoiseMask, feeding the

sampler's latent input.

THE COMPOSITE IS NOT OPTIONAL, AND THE REASON IS MEASURED. *"The latent noise mask holds the

unmasked LATENT, not the unmasked PIXELS: the whole frame is still VAE-decoded at the end, and that

re-decode moves the face box by about 2.9 levels of 255 against a null-cell floor of 1.0."* So

the output is recomposited under the same feathered mask, with hard_top = mask_top_y − 3×feather_px,

and max_abs_diff == 0 above hard_top is asserted.

BALD DERIVATIVE (harness/asset_factory/bald_derivative.py) — the same method inverted, a

top-anchored mask, closing the pre-texture blocker D-W1 at its cause. **Identity is held by the MASK,

not by a low denoise**, and the record says why: a refine strong enough to delete a heavy tousled mane

is strong enough to redraw the face — three of four bracket cells failed the identity leg at denoise

0.38. Byte identity outside the mask over 1,119,558 px, 61.98% of the frame. In-game hair is a separate

groom stage, so the bald source costs the pipeline nothing.

THE TRAP — THE SEGMENTER IS REPORTED, NEVER THE LANDMARK. The pixel segmenter puts the age-14

tunic's top edge 142 rows low (y=1302 against a sighted y=1160), and on the bald pass it also

catches the eye apertures, both lash lines and the lip line because those are dark, cool and busy. So

the mask landmark is SIGHTED and declared, with the segmenter's own answer recorded beside it.

The colour-only garment instrument likewise cannot separate skin from a warm-toned garment (age-14

red-gold tunic, ‖d′‖ 0.287), which is why a texture axis (local luminance std) was added and armed

two-sided per plate: 14 d′ +1.28, 18 +0.83, 7 +0.13, **11 −0.29 — and that refusal IS the age-11

verification**, because the same instrument unchanged arms on the other three.

---

Stage 2 — Body: anthropometry spec, then the physique bracket

THE SPLIT IS THE RULING. Face and body generate on separate axes, in separate context windows:

FACE lanes see face references and face canon only; BODY lanes see ONLY the age-agnostic anatomical

proportion descriptions (feet to shoulders) and physique specs, never face material. Cross-axis context

contamination is a named defect (DECISIONS :: THE FACE/BODY SPLIT · THE PER-AGE DIRECT RECIPE +

SEPARATE CONTEXT WINDOWS). The evidence: *"face identity succeeded wherever references drove it;

failures clustered where body and face competed in one generation."*

BODIES NEVER CONDITION ON A REFERENCE IMAGE. Josh: *"if these are the ones that look like reference

images they arent minimalistic, their identity doesnt match our protagonists life."* Bodies generate

from descriptions — the BG3/CP2077 parametric pattern (DECISIONS :: BODY LADDER RULING).

THE SPEC LAYER. build/3d/characters/body_specs/BODY_AGE_{7,9,11,12.5,14,16,18}.json, emitted by

emit_body_specs.py against BODY_PROPORTION_METHOD.json. Its own words: *"the body ladder

INSTANTIATED at age N — every number derived by BODY_PROPORTION_METHOD.json, none typed in."*

33 top-level keys, including 18 segment_lengths_cm (foot length/breadth, ankle, knee, trochanter,

biacromial, biiliac, chest breadth, hand length/breadth, upper arm, forearm, acromion, thigh, shank,

elbow, wrist, across-shoulder soft tissue), 14 girths_cm (neck_base, chest, underbust, waist,

hip_max, thigh, knee, calf, ankle, bicep, elbow, forearm, wrist, hand circumference), 5 age_biases,

training_clock, segment_mass_fraction / _kg / mass_closure_kg, subcutaneous_fat_scalar,

metahuman_conformance, and 14 regions.

791112.5141618
stature cm123.213133.929145.610155.361166.720177.758180.544
head height cm19.15520.08921.10721.54522.05522.78922.974
head-units6.43266.66686.89857.21097.55927.80027.8586
hip fraction0.54170.55560.56940.57750.58090.58540.5899
mass kg23.68329.23736.04444.17154.47966.67173.667
roleKEYbetweenKEYbetweenKEYbetweenKEY

THE GIRTH TABLES are BODY_PROPORTION_METHOD.json :: girth_coefficients — one row per girth

carrying k, a_muscularity, a_adiposity, an age_shape_bias at the four keystones and an

age_shape_bias_derived at the three in-betweens. E.g. neck_base `k 0.2077, a_m 0.08, a_f 0.04,

bias {7: 0.8333, 11: 0.90, 14: 0.95, 18: 1.00}; chest k 0.516, a_m 0.12, a_f 0.06; waist_natural`

k 0.4321, a_m 0.04, a_f 0.14. The solve, in one line:

G = k · H · S · B · (1 + a_muscularity·m_n) · (1 + a_adiposity·f_n)

with H(age) anchored on the CDC-50 curve between a measured age-8 child anchor (stature 129.0,

head_units 6.567, 63,448 verts sampled) and the adult engine anchor (180.544, 7.8586); slenderness

S = sqrt[(M/M_adult)/(H/H_adult)³]; segment L = fraction_of_H · age_bias · H; **acromion height is

DERIVED, never fractioned**; physique axes ride MetaHuman's own units (muscularity ±2.323, adiposity

±2.753); and the anti_chisel_gate caps surface_definition_index at 0.62 with a declared failure

band of [0.7, 1.0]. Citations on the record: WINTER2009, DRILLIS1966, DEMPSTER1955, CDC2000.

THE ANTHROPOMETRY IS RESEARCHED, NOT INTUITED — Josh's order after rejecting the clay lineup:

*"exam photos online of what each and every age range looks like and also scientific research…

build those proportions at every angle, and then alter it for our exemplar bodies."* The research is

build/3d/characters/body_specs/AGE_PROPORTION_RESEARCH.md, machine half

AGE_PROPORTION_TARGETS.json, field-level diff AGE_PROPORTION_REBUILD_REPORT.json. Its four

load-bearing findings:

grows only 8.5% from 7 to 18 while stature grows 44% and biacromial breadth 52%.

hu); the artistic canon measures to the hair silhouette (adult 7.5). This pipeline measures in

the hair convention and must target it — the rejected lineup's whole defect.

13** → 0.5215 at 18. A thirteen-year-old's legs are proportionally longer than a grown man's. A

monotone leg-length curve cannot have that phase, and the rejected lineup's was monotone.

years; head breadth over shoulder breadth moves 29% (0.529 → 0.376). There is no other reference

in the silhouette.

THE PHYSIQUE BRACKET — THE HUMAN GATE. The 18 rung ping-ponged three times on physique, so V5

stopped guessing and delivered a 3-cell physique BRACKET per graded rung around the target, so Josh

picks the calibration point (DECISIONS :: BODY V5 GRADES + FACES ON). He picked the TARGET column at

every age: BodyV5_A7_TARGET_a0, BodyV5_A11_TARGET_a1, BodyV5_A14_TARGET_a1,

BodyV5_A18_TARGET_a0 (DECISIONS :: BODY PICKS LOCKED). **This is the pattern for every future

character: a bracket, not a single-point guess, the moment an axis oscillates twice.**

THE PHYSIQUE LAW — THE TRAINING CLOCK, not a generic age chart. *"11 should have some tone and some

ab definition yes, weve already lived in the human world for 4 years at this time."* The body at every

age shows what the spine's lived history has earned by that chapter. Final calibration after the curve

was steepened: real tone at 7, defined at 11, sharply athletic at 14, genuinely chiselled at 18 — with

18 lean-chiselled, a swimmer/climber cut, not bulk (DECISIONS :: TONE CURVE STEEPENED ·

AGE-18 PHYSIQUE CALIBRATION). The surviving kill criterion is the age read: an 18 that reads 40

fails regardless of physique quality.

THE NAMED TRAPS.

trainingwear → blank doll → chunked photoreal → true photoreal → clothed → reverted. The clothed

ruling was a director misread of which sheet Josh was pointing at and is VOID. The settled state:

true photoreal at every rung, the in-game minimal-underwear swap layer worn at 7/11/14, tasteful

minimal at 18, the crotch never photoreal anywhere. **The lesson generalises: confirm which artifact a

grade refers to before deriving a ruling from it.**

reported zero clamps on every constraint at every rung and still returned an unusable source at

the young ones: at age 7, 11 of 21 requested constraints sat outside the model's own windows, the

solved bideltoid span came back 2.11× the rung's, and the conform then squeezed it laterally by

0.474×. BODY_AGE_7.json :: metahuman_conformance had written the warning down before any of it ran

and nobody had read it as a capability limit.

ON.** conform_true_base.py's per-part centre curve had a second-difference std of 4.27 cm on the leg

parts. A vertex moves to c + (v−c)·s, so an error in c displaces it by (1−s)·error — about 2 mm

at A14 where s≈1, and ~1.5 cm of ringed corrugation down the thigh and shin at age 7 where

s≈0.65.

7.859** — forbidden by the file's own law. Cause: stature interpolated on the violently concave CDC

curve while head-size bias was read linearly in age. Two curvatures over one span, and head-units

is one divided into the other. Fixed at cause; the BETWEENNESS tooth caught it on its first run.

through an ellipse — measured wrong by about 30%. A thorax is not an ellipse and the error is not

a rounding error. Three sibling traps ride with it: breadth is taken at maximum inspiration and depth

at quiet respiration (two numbers from one table are not from the same breath); calliper breadths

compress soft tissue and tape girths do not; and a skeletal landmark (biacromial) must never be

fed into a soft-tissue envelope site (bideltoid), because a mesh cross-section measures an

envelope (AGE_PROPORTION_RESEARCH.md §9, "FOUR METHOD TRAPS").

failed. The researched whole-body proportion truth is the solve target, not a site list

(DECISIONS :: CLAY LINEUP REJECTED).

NIST AnthroKids numbers, not its measurement-position plates; the recommended visual reference is

museum sculpture, because the silhouette masses are already resolved in three dimensions — the

Spinario against the Getty Victorious Youth is exactly our 12.5→18 delta

(AGE_PROPORTION_RESEARCH.md §7).

---

Stage 3 — The 2D merge: the approved three-step rawhead recipe

THE APPROVED CHAIN, ENTIRE, verbatim from the ruling (DECISIONS :: THE KEYSTONE MERGE CLOSES ON

THE SIMPLEST CHAIN):

the picked V5 TARGET cell on the canvas merge_identity_v6.place() solves; ONE Qwen-Image-Edit-2511
head replacement at that cell's own seed, exemplar bust at full 1344 px as image2, the body as image1
AND the start latent, denoise 1.0; ONE similarity alignment into the picked plate's frame. **Nothing
else.**

Tooling: build/3d/characters/body_specs/merge_identity_v6.py (the canvas solve, place()),

merge_route_a_v8.py (prepare()align()finish()) and merge_race_a14.graph_qwen_edit().

The edit runs **euler / simple, 40 steps, cfg 4.0, ModelSamplingAuraFlow shift 3.1, CFGNorm,

TextEncodeQwenImageEditPlus**, on qwen_image_edit_2511_fp8mixed.safetensors with clip

qwen_2.5_vl_7b_fp8_scaled.safetensors. The path that runs the graded chain and nothing else is

--approved-only: *"THE JOSH-GRADED CHAIN AND NOTHING ELSE: canvas, edit, align, save."* The aligned

plate is written before any post-pass — *"until this line moved, one did."*

agearmseedscaledx / dyiouplaced head pxseam rowcanvas
7CONTROL_RAWHEAD_s095072111.049711 / 280.98625223.8306832×1440
11CONTROL_RAWHEAD_s095112421.05497−2 / 90.98592191.8269832×1416
14CONTROL_RAWHEAD_s095142421.052801 / 70.98661171.1246832×1416
18BIGHEAD_s095182111.048851 / 380.97330174.7253832×1456

Rung 18's final is ALIGNED_BIGHEAD_s0_A18; 7/11/14 are frozen on the aligned-rawhead cells. Josh

closed the axis: *"yes the v3 sheet is exemplar for 7, 11, 14, and 18."*

FOUR PASSES WERE BUILT AND EXCLUDED BY THE GRADE. The record states it flatly: *"NOT APPLIED:

exposure match, head rescale, body restore, membrane heal — all four were built this sitting against

instrument readings and all four are excluded by the grade."*

passfunctionwhy it was builtwhy it is out
exposure matchmatch_backdrop()a join between two photographs; a backdrop-only fit left a visible step in the skin, so the fit also takes shoulders and upper chestexcluded by the grade — the graded cell is the raw aligned plate
head rescaleresize_head() via measure_head()the instrument said the head was off-specdriven off a neck minimum that lands on the jaw; it GREW rung 14's head 4.6% when it needed shrinking, and Josh on the scale-ups: *"deformed proportions - abandon them"*
body restorethe restore in finish()route A redraws the physique below the join; this puts the picked cell's pixels back byte-exactexcluded by the grade
membrane healone_sided_membrane(), JOIN_FEATHER = 8, MEMBRANE_BAND = 56removes the join tone step in the gradient domainexcluded by the grade

A future lane must not re-add them without a grade that asks for them. One ordering lesson is kept

in the source even though the passes are out: exposure match first, then head fit, then body

restore — running the exposure match last *"printed a horizontal band across the whole frame."*

THE NAMED TRAPS.

and blend — and the visible paste was its direct consequence (Josh: *"i dont think youre able to just

copy and paste them on there"*). RULED: the 2D merge is GENERATIVE; face identity is **PROVEN BY

MEASUREMENT** (copy-index ≥ 0.99 against the exemplar plus a sighted 1:1), never frozen by hash

(DECISIONS :: MERGE FIX - IDENTITY-LOCK REPLACES BYTE-LOCK).

the panels looked** — the signature of a detector correlated with the thing it was supposed to

measure independently.

sighted chin at 229, so crown-to-neck under-measures the head by a sixth, and a rescale driven off

it GREW that head 4.6% when it needed shrinking. Good chin landmark, useless head-height one.

own docstring already records as an instrument failure. Both instruments are **advisory; neither

gates** (DECISIONS :: TWO INSTRUMENTS ARE WRONG ON THESE PLATES).

a body-sized canvas fixes the head size (183 px against a 174 px target) and returns **a different

boy**: identity 0.848 scaled and 0.820 native against the raw bust's 0.968. A head at final size is a

~170 px face inside a 1 MP frame and carries almost no identity for the vision encoder to copy. **The

solved head-unit ratio cannot be delivered on the reference side.** On rung 7 a split reference (bust

for WHO, composite for HOW BIG) recovered 0.971; on 14/18 the plain raw bust was already right.

(merge_perimeter_v6b.py) shrank face protection to exactly the inner-face rectangle — brow to

just above the chin, inside the cheeks — which is precisely the window the identity gate measures, so

the identity number could not move and the sighted read was the only real one. The lane said so on

its own face. That is the correct posture and the correct disclosure; it is not a passing gate. The

same defect had killed V6 from the other side: *"the inner-face metric went vacuous while everything

outside it regenerated — the exemplar drifted."*

refused every age-11 perimeter rung. Its ranking was still right at the extreme (the genuinely broken

d0.76 rung, which grew a ghost second face, scored worst), so the threshold was relaxed **for

perimeter passes only** and the eye decides inside it.

would have taken denoise 0.52; the eye took 0.40 (0.64 restyles the hair lighter and enlarges the

ears; 0.76 grew a ghost face on the cheek). On A18 auto would have taken 0.76 purely on a blob score;

the eye took 0.52 (0.40 is fringe-clean but carries a blue-teal temple streak).

left a pass record containing only 18 — the same class as a gate reporting a clean pass on an empty

set. The log now merges.

THE PERIMETER PASS, as it actually ran. Protection = the inner_face_box rectangle, alpha-ramped

by PROTECT_FEATHER = 16 px on a distance transform; crop padded 0.30 of the head-column span

horizontally and 0.16 of head height vertically, extending to seam + 1.1 × head_px, rounded to

multiples of 8; denoise ladder [0.40, 0.52, 0.64, 0.76]; seed = the unification pass's seed + 401 + i.

agekept denoisecopy-index (inner face)largest blobmicro-texture
70.640.993450.00747106.7
110.400.992580.03474164.72
140.400.993710.00511106.0
180.520.991160.00470113.32

Note age 11's blob at 0.03474 against the guard's SILHOUETTE_BLOB_MAX = 0.012 — that is the

mis-calibrated guard being overridden by the eye, on the record.

MEASURED OUTCOME OF THE MERGE LANE (the bar every future character inherits): identity

0.99116–0.99371 against the ruled 0.99 floor; body fidelity 0.970–0.983 against Josh's picked

cells; micro-texture 106–165 against a 75.1 photoreal floor.

THE REFERENCE HIERARCHY, ruled after the merge landed. *"Exemplar Face Picks + Exemplar Body Picks

Exemplar Full Body. Exemplar Full Body loses some detail."* The SOURCE PICKS are the detail ground

truth — faces reference the KEYSTONE_BARE busts, bodies the BodyV5 TARGET cells, at full fidelity.

The merged full-body plates are composition reference only (head-on-body proportion, framing, the

approved whole). This binds 3D face wraps, chunk-photoreal texture comparisons, palette sampling,

in-between bridging and every polish pass (DECISIONS :: REFERENCE HIERARCHY).

---

Stage 4 — The aging ladder: keystones, then landmark-warp in-betweens

THE LADDER IS SEVEN AGES: 7, 9, 11, 12.5, 14, 16, 18 — keystones plus in-betweens (DECISIONS ::

MERGE DISCIPLINE + SEVEN AGES; this supersedes the 12-age framing that

BODY_ASSEMBLY_ARCHITECTURE_BRIEF_2026-08-06.md §6.1 stage 5 still carries).

THE KEYSTONE ORDER IS JOSH'S OWN, and it is the largest jumps first: anchor ages 7, 11, 14, 18

built first — 7→18 the extremes, then 11 (prepubescent) → 14 (postpubescent) across the puberty

boundary — then interpolate between keystones. **Fill ages derive from graded keystones, never the

reverse** (DECISIONS :: THE KEYSTONE AGING METHOD + TOOL FREEDOM).

WHAT FAILED FIRST, AND WHY IT WAS A CATEGORY ERROR. Dual-anchor conditioning — both adjacent

approved busts through FLUX.2's chained ReferenceLatentdoes not average. It picks one. Three

cells settle it: IB_9_BR_S1 (7 then 11, seed 972000) copy→7 0.9964 / copy→11 0.458;

IB_9_BR_S2 (same order, seed 972001) 0.4333 / 0.9947; IB_9_RB_S1 (reversed order, seed 972000)

0.9954 / 0.4582. Opposite orders at the same seed land on the same anchor; the same order at

different seeds lands on opposite anchors. **The seed decides, which is another way of saying the model

never mixes them. Nothing lands between at any setting. The mechanism: ReferenceLatent appends**

to the conditioning's reference list — it concatenates, it does not interpolate — and two whole-frame

references over one canvas are two mutually inconsistent spatial priors, so the model satisfies both by

drawing both. **The registered 50/50 pixel blend returned exactly what Josh named: a double-exposure

ghost, two ear sets, overlaid hair shells.** Ruled out permanently

(AGING_METHOD_RESEARCH.md §1).

**THE RESEARCH SAYS THE SAME THING, which is what makes Josh's replacement the endorsed method rather

than a fallback.** All four production and research families — parametric blendshape age morphs (DAZ

Genesis, Reallusion CC, Unreal/Blender shape keys), Disney's FRAN, **StyleGAN latent age

directions (SAM and the 2025 Idiap SVR successor), and diffusion age editors (TimeMachine**, MAE

3.84 y across 10–70 against SAM's 5.34) — condition on ONE face and move it along an age axis.

None is shown two photographs of the same person at two ages, because that is compositing, and

compositing two faces is the ghost.

TWO RESEARCH FINDINGS THAT CHANGED HOW THE LADDER RUNS. TimeMachine's ablation (drop age control →

MAE 20.52; drop identity control → similarity 0.06) means **age and identity are separate control

channels and both are named outright** in every instruction. REED-VAE's measurement that encode/decode

alone accumulates visible artifacts within 5–10 iterations means **chained candidates are judged on

micro-texture, not only on the age read** — and it happened here, in both directions: A9_FWD7_1Y1Y

(7→8→9) and A9_REV11_1Y1Y (11→10→9) both came back with darkened speckled freckles, which the ruled

freckle clause forbids in as many words. **The cost is direction-independent, which is exactly what a

VAE round-trip cost should be.**

ROUTE S (instruction edit) IS REFUTED FOR STRUCTURE — measured, not preferred. Wave 2 rebuilt it

properly (age direction carried as named anatomy — *"the midface lengthens, the cheek fat pads

recede, the jaw takes an angle at its rear corner"* — plus a corrected hold clause and an emphatic arm).

At 12.5 it moves nothing: struct_pos −0.005 measured and −0.031 emphatic forward; +0.915

and +0.946 reverse — and the emphatic arm moved LESS than the measured one in both directions,

which is saturation reproducing under the strongest phrasing the lane could write. At 16 it costs

44% of the anchor's micro-texture (3142–3239 against 5724) and the emphatic reverse plate scored

ratio_pos +1.483 — it aged him *past eighteen* when asked to de-age him to sixteen. A single

Route-S edit costs ~37% of micro-texture.

ROUTE W IS THE WINNING RECIPE, AND IT CANNOT GHOST BY CONSTRUCTION. Dense landmarks on both anchors;

the other anchor's set brought into this plate's frame by full similarity; the sets averaged at the age

fraction; and ONE anchor image's own pixels warped onto the result by a thin-plate-spline backward

map with fixed border control points. One image's pixels are moved, and a pixel between two positions

is one pixel. Tooling: harness/asset_factory/face_landmark_warp.py (warp + instruments) and

aging_ladder_w2.py (driver + heal).

Exact parameters. PAIRS = {12.5: (11, 14), 16: (14, 18)}; WARPS runs both directions at

fraction 0.5 — A12H_W_F11_RAW (11's pixels), A12H_W_R14_RAW (14's pixels), A16_W_F14_RAW,

A16_W_R18_RAW. Landmarks: MediaPipe FaceMesh, `static_image_mode=True, max_num_faces=1,

refine_landmarks=True, min_detection_confidence=0.3` — 478 points detected, 468 used, the ten iris

points excluded because *"a boy looking a millimetre left is not a boy with a different skull."* Warp:

RBFInterpolator(dst, src−dst, kernel="thin_plate_spline", smoothing=0.0) evaluated on a coarse grid

and bilinearly raised, with 9 fixed border control points per edge, resampled by cv2.remap at

Lanczos-4 with BORDER_REPLICATE. Heal: one pass at HEAL_DENOISE = 0.30 on the RAW warp —

*"the warp decides the structure and the heal only removes warp artifacts."* The lane runs in a pinned

3.12 venv because mediapipe and OpenCV have no 3.14 wheels.

warps score struct_pos +0.403 / +0.604 at 12.5 and +0.504 / +0.563 at 16, with ratio_pos

agreeing — **both instruments agreeing in both directions at both ages, which no other route

managed.**

anchor's own detail_index (6310 against 6389; 5639 against 5724).

15% of micro-texture. Both plates ship so Josh prices the trade.

JOSH'S FROM-OLDER-ANCHOR PATTERN IS THE DEFAULT PRIOR. Every in-between he has picked derives from

the OLDER anchor: age 9 = A9_REV11_3Y (the approved 11 reverse-aged three years); age 12.5 =

A12H_W_R14_HEAL (the reverse-from-14 landmark warp, healed). And his rejection of the 16 candidates

states the principle directly: *"the A14 ones you pushed to 16 had smaller jaw structures than even

their A14 which isnt right especially if were trying to be the in between to A18"* — **a rung must

progress toward the older anchor's structure, never regress it.** Wave 3 builds 16 from the 18 side

(DECISIONS :: AGE-9 EXEMPLAR PICKED · AGE-12.5 PICKED + 16 REJECTED AGAIN). **Default the generator to

the older-anchor derivation and offer the younger-anchor arm as the alternate.**

THE PRESENTATION SPEC IS JOSH'S OWN AND IT IS A GATE. *18 candidate-context ladders + the final* —

ladders 1-6 slot each age-9 candidate into [7, 9c, 11, 14, 18]; 7-12 each 12.5 candidate into

[7, 11, 12.5c, 14, 18]; 13-18 each 16 candidate into [7, 11, 14, 16c, 18]; ladder 19 is the final

[7, 9, 11, 12.5, 14, 16, 18] from his picks. **Every candidate is judged IN PROGRESSION CONTEXT, never

as a tile** (DECISIONS :: FROZEN FINALS STAND + THE 19-LADDER SPEC). The companion law: every keystone

cell is judged in a side-by-side against Josh's own reference for that age, inline on the sheet —

*"a sheet without the references inline is un-DONE"* (DECISIONS :: THE SIDE-BY-SIDE LAW).

THE IDENTITY CURVES THAT RIDE THE LADDER (canon, four fixed points, read at the target age rather

than picked): hair silver-blonde at 7 (fairy realm) → visibly warm sandy-blond by 11 → dirty blonde

through 14–18; freckles — the pattern is permanent identity, the INTENSITY fades, pronounced at 7 →

minimal by 18, never dark and never speckled; warmth — the age-7 keystone's warm skin and light

read carry through every age, and a shiny/waxy/metallic glow is a named defect class.

THE IN-BETWEEN BODIES DO NOT GET 2D PLATES. They build directly in 3D from the landed specs

(solve → conform on the picked S2 route), textured chunk-by-chunk against the adjacent approved

keystone plates' palette (interpolated), reviewed as turntables. In-between FACES do get portraits —

head-and-shoulders only, bridged from the approved busts — and they anchor the 3D face wrap at those

ages (DECISIONS :: IN-BETWEEN PATH REVISED - 3D-DIRECT).

---

Stage 5 — Cage source and wrap/conform

THE DERIVATION DIRECTION IS THE WHOLE ARCHITECTURE. The cage conforms to the plates; it never

derives from them. A complete template body is wrapped onto the plate-derived shape:

topology, regions and UVs are the cage's; form is the plates'. Anatomical completeness comes from

the cage — parametric, complete by construction — so **the plate never needs to depict what the mesh

must contain** (DECISIONS :: THE CAGE REVIEW STACK + THE SWAP GAUNTLET · THE TWO-REGISTER BARE).

THE TWO REGISTERS OF "BARE", never conflated. The plates are 2D grading surfaces in the

tasteful-minimal display register. The 3D base mesh is dev-only and TRUE BARE — anatomically

complete under everything — because per-region suppression and the swap floor only work over a complete

substrate, and the game's historical cultural apparel (minimal-coverage wraps, open dress across regions

and eras) demands a base that is correct wherever gear does not cover.

THE WRAP RECIPE PICKED: Lane S2, the numpy landmark-NRICP (build/3d/cage/CAGE_PICK.json,

RACE_CLOSE.md). Ranked max over both targets: S2 p95 0.01749 / mean 0.003678 / landmark 0.17602

against S1's 0.04965 / 0.017915 / 0.18718 and a do-nothing FLOOR of 0.05232 / 0.018373 / 0.17905. **S2

is 2.84× better than S1 and 3.0× better than doing nothing — while S1 is only 5.4% better than doing

nothing.** S1 wins wall-clock alone (16.29 s against 351.46 s), which the spec ranks last.

**THE BLOCKER, CLOSED BY ITS OWN REFERENCE (superseded in place 2026-08-10, director-rows wave;

originally: "S2's blend proof fails — 3 of 30,540 faces, min normal agreement −0.620 vs the −0.5

bar").** The failure was the INSTRUMENT'S, not the recipe's: bench_cage.blend() judged G4 against

PARENT A while gate_G4's own _why names THE CAGE as the reference — proven by four controls

(t=1.0 is parent B bit-for-bit and reads 23 flips vs parent A but 0 vs the cage; the bite and mirror

mutations still FAIL against the cage, so the corrected reference did not go soft). Re-referenced,

the blend proof PASSES; verdict and controls in

build/3d/cage/blend_fix/BLEND_G4_REFERENCE_FINDING.json (landed 869ba32f), diagnosis in

BLEND_FLIP_DIAGNOSIS.json. All seven WRAP_A*_V3Q.obj exist under solver_nricp/. **The

seven-age lane's release gate is CLEAR on this axis.**

THE FLOOR ROW IS WHY THE PICK COULD BE READ AT ALL. Without a do-nothing arm in the table, S1's

0.04965 would have looked like a result. It was 5.4% better than not running. **Every future bake-off

carries a do-nothing floor row.**

BE PRECISE ABOUT WHAT EXISTS AT THIS STAGE, because three different things are easy to conflate.

mh_true_base.py (frame map, weld, measure) → TRUE_BARE_BASE.json (partition + UDIM + material

slots). It welded 32,334 UV-split vertices onto 30,455 positions, adopted a stature of

155.292 cm from two independent anchors that agree (knee 155.292 against trochanter 151.377,

spread 0.025 — *"Two anchors that agree are a measurement, one is an assumption"*), and reads all six

girth sites plus a neck base measured **on the open neck rim as a closed polyline of 92 boundary

edges**.

genuinely absent — a proportion-correct symmetric base to inherit topology from: CC0 assets, copyleft

binding the tool and not the output, no revenue threshold, no engine coupling, and *"the only option

that takes proportions in real centimetres."*

brief calls it *"the highest-value thing this brief can point at."* Anny is corroborated at

**13,380 v / 13,378 quads / 163 bones, Apache-2.0 + CC0, WHO-calibrated infant→elder, 2.7 mm fit on

child scans** — with a second source disagreeing at 13,718 v / 104 bones, which is itself worth knowing

before a GPU hour is spent. Its proof is specified: a blind A/B plus a child-proportion read against

the canon 6.567 head-units, with both arms re-rendered by the SAME instrument.

Tooling options are priced: Faceform WrapCmd is genuinely headless and batchable at Indie $570;

Blender gives Surface Deform and Shrinkwrap but not landmark-constrained coarse-to-fine NICP, which

is the real cost delta. Acceptance is specified — same vertex count and order as the cage, surface

deviation under a stated tolerance, the ear retained (the one morphological elven marker) — with a

per-vertex deviation heat-map on a fixed colour scale as the proof image. **The named failure band is

child-vs-adult proportion for wrap without landmarks**, which is precisely why the cage choice should

prefer something already parametric over something that must be wrapped into the child band.

WHY THE WRAP IS NON-NEGOTIABLE, in one measured line: *"two age states generated independently

CANNOT be blended — there is no vertex correspondence to blend along."* Identically-topologised wraps

are blendshapes of each other; independently generated ones are seven different assets. **That single

fact is what makes a Tier-A age ladder affordable, and it is gated entirely on this stage.**

THE TRAP THAT PRECEDED THE COMPARISON — an instrument scoring emit conventions, not wraps. Two of

five defects in build/3d/cage/instrument_fix/ROOT_CAUSE.json scored a lane on its choice of OUTPUT

FRAME: the alignment optimised an untrimmed mean over a similarity including scale **with no lower

bound, whose global optimum is scale zero — and it took it, at 0.057 of the honest unit ratio**; and the

flipped-face criterion compared normals in two different frames, moving the same geometry between 0 and

20,694 flipped faces in two files. One lane emitted in centimetres and the other at target scale, and

the spec never named a unit. **A pick from those numbers would have been a pick between emit

conventions.** The patch was applied only after all twelve existing self-test arms still bit — the

condition being that it had to take nothing away.

THE FINDING THAT OUTLIVED THE LANE: there was no nude base anywhere in the lineage. Measured

vertex-for-vertex on identical topology, 26,196 of 63,448 vertices are garment-covered and **16,279 of

them — 62.1% — did not move at all** in the ruled de-merge to bare (below the knee 96% unmoved, torso

82%, head and neck 100%). The mesh passed as --nude renders as a sleeveless tunic and shorts. So the

doll crotch and the no-collision underwear had no skin to sit on, and the 3D asset and the 2D plates

were not showing the same body. **Order corrected: nude base first, then keystone faces in 3D, then the

blend-proof blocker, then the rungs. The general law: verify that the artifact named bare is

bare, on the pixels, before anything conditions on it.**

THE FOUR REVIEW LAYERS Josh set for the cage — (1) the cage source, judged on anatomical

correctness, articulation-ready topology, child-through-adult range and licence; (2) conform correctness

per character and age against the plate-derived shape on the ruled axes; (3) ROM calisthenics on the

rigged result; (4) THE SWAP GAUNTLET (stage 13).

---

Stage 6 — 3D mesh generation

THE REFRAME FIRST, because it is the whole finding. The rejected chain was not losing on model

quality — it had no base mesh under it, so it assembled lofted parts and solved proportions onto the

assembly. Measured: the rejected chain is the only genuinely multi-part mesh (**4 connected components,

70.6% of faces in the largest, against 99%+ for every generated arm) and the lumpiest (0.0104**,

~2×) — while being **nearly perfectly bilaterally symmetric because it is mirror-built by

construction.** So the "scoliosis" was never asymmetry: it was part seams and head-to-yoke integration,

and a lane that had gone chasing symmetry would have fixed nothing and reported success.

TWO ROUTES ARE LIVE AND THEIR STATUS DIFFERS — state it precisely, because they are easy to confuse.

RATIFIED PRODUCTION GEOMETRY: TripoSG. `TRIPOSG_SETTINGS = {seed: 42, steps: 50, guidance: 7.0,

faces: 250000, octree: 9}, invoked gen3d.py --image <ref> --out <raw> --save-cond <cond> --faces

250000`. 21.63 s mean (n=13, 14.6–44.4) at 5.31 GiB peak (5.16–6.09), manifest DL_0005, MIT code

and weights with RMBG-1.4 deliberately not used. It is not an unreviewed default: it won a blind

A/B, and the arm that lost — arm f, Hi3DGen used as a MULTI-VIEW geometry conditioner — regressed

at silhouette −0.89 and form_identity −1.00 across nine items with **four ties, four

regressions, zero improvements, including a regressed CONTROL**, which is the signature of a route

that is worse in general rather than worse on hard cases. Its mechanism was diagnosed, not guessed:

*"i2mv INHERITS THE PLATE'S STAGING"* — a plate whose six views are not a turnaround of one object

collapsed to 1/1, while a clean turnaround tied 5/5. **The bound the record itself sets: only

UNREGISTERED views feeding a stochastic multi-image sampler lose on thin multi-part subjects.**

RECOMMENDED FOR CHARACTERS, PROPOSAL TIER: Hi3DGen / Stable3DGen single-image (weights

Stable-X/trellis-normal-v0-1, MIT, already installed). Constants: `seed 42, ss_steps 50, slat_steps 6,

cfg_strength 3 on both samplers, with a StableNormal_turbo normal bridge (yoso-normal-v1-8-1`),

preprocess at 1024 and normals at 768. Measured on the A14 plate: `t_load 20.36 s + t_normal_load

7.43 + t_normal 0.45 + t_geometry 23.3 = 59.15 s total, peak_vram_alloc 10,849 MiB / reserved

12,104 MiB`, 86,322 verts / 172,674 faces, not watertight (euler −17), on torch 2.9.0+cu128 at

compute capability 12.0. Across nine bench items: 25.26 s mean geometry, 10.99 GiB mean peak

with the caveat carried on its own record that *"includes a per-call cold WSL model load; a batch would

amortise it (t_geometry alone measured 4.3–6.5 s)."*

It wins every symmetry and straightness column of the bake-off outright — sym p95 0.0022 / drift

0.0029 / width-asym 0.0035 against the rejected chain's 0.0052 / 0.0051 / 0.0072 and TripoSG's

0.0060 / 0.0115 / 0.0231 — and wins them against an arm that is symmetric by construction. It puts

99.1% of its faces in one body and is the only arm with defined knees, a real garment, separated

fingers and a face with structure. The bake-off is PROPOSAL tier and adopts nothing; its own

recommendation is to run generation as the stage with Hi3DGen as the live default for characters and

re-run the bake-off with TRELLIS.2 as a fourth arm the moment the gate opens.

THE BLACKWELL LANDMINE, solved: XFORMERS_DISABLED=1. Hi3DGen's crash was not its own attention

backend — it honours ATTN_BACKEND=sdpa, and the run log confirms Using backend: sdpa — but

DINOv2 auto-detecting xformers independently, and xformers has no sm_120 kernel. One environment

variable, prefixed on the WSL invocation; then 59 seconds.

THE REAL 3D DEFECT WAS THE CANDIDATE SET, NOT THE CHOICE — the benchmark's own words:

"only_one_multiview_model_was_available".

THE TRELLIS.2 ARM IS SUBMITTED AND AWAITING REVIEW. TRELLIS.2-4B is installed on the box with 16.2

GB of weights (D:\assetgen\models\TRELLIS2, 22 files) and is one click from running: its image

encoder facebook/dinov3-vitl16-pretrain-lvd1689m is a GATED Hugging Face repo whose terms **the

account holder must accept**. The DINOv3 licence does permit commercial use; the gate is a

contact-information agreement, and accepting an agreement is Josh's to do, not a lane's. The

instrument, conditioning and sheet builder are all written, so the arm is a minutes-long re-run once it

opens.

The install recipe is build/3d/bakeoff/install_trellis2_win.ps1 — venv D:\assetgen\venv_trellis2_win,

python 3.12, torch==2.8.0+cu128, with prebuilt cp312 wheels for cumesh, flex_gemm and o_voxel

— after upstream's pinned torch 2.6.0+cu124 (no Blackwell kernels at all) and its six source-built CUDA

extensions took the WSL VM down twice with Wsl/Service/E_UNEXPECTED and no OOM in dmesg.

nvdiffrast and nvdiffrec_render are deliberately NOT installed, and the script says why in a

comment: *"NVIDIA Source Code Licence, which is NON-COMMERCIAL — installing them would make an

MIT-headlined pipeline unshippable in fact."* The verify log's `MISS o_voxel ModuleNotFoundError No

module named 'nvdiffrast'` is therefore the expected, correct output — it is the licence boundary

showing up as a clean import failure on the export path only.

THE LICENCE READS THAT BIND THIS STAGE.

excluding the European Union, United Kingdom and South Korea; §2 grants rights for the Territory

only; §4.c bars use or display of the OUTPUT outside it, and §1.h defines Output to include the

generated meshes. A worldwide Steam release violates that by definition. It was installed and run for

evidence (watertight, 60 s, 8.65 GB, visibly softer with mitten hands) and struck on the sheet's own

face so no later lane re-tries it. Note hy3dshape/minimal_demo.py still carries a stale

NON-COMMERCIAL header; the LICENSE file governs.

TRELLIS.2's render/preview side, not its generation side, and both it and nvdiffrec are opt-in

setup flags. With a find_spec guard and a positive control proving the guard bites,

trellis2.pipelines imports cleanly without nvdiffrast and o_voxel does not — so the geometry

path is licence-clean and the taint sits in the GLB exporter, which is the substitution point for the

already-proven Blender-headless route (the same substitution already ratified for MV-Adapter).

THE HAIR-FREE CONDITIONING SOURCE IS ROUTE-AGNOSTIC AND BELONGS HERE. Any image-to-3D generator

handed CHAR_0001_KEYSTONE_BARE_14_BALD.png sees a skull instead of a mass of separated strands. The

A/B that produced it had already relocated the defect: --scalp-policy skin_only was worse, which

proved the crust is not the scalp's but the fringe band's, where strand hair overhangs skin — so the

fix is upstream, in the conditioning plate, and not a solver parameter.

GENERATIVE 3D IS A BASE SCULPT AND A BLOCKOUT, NOT A SHIPPABLE ASSET — and the vendors say so

themselves: Meshy's documentation concedes fused fingers and asymmetric faces and calls DCC repair

standard practice; Tripo's own blog notes auto-retopology has no concept of where an elbow bends. A

controlled academic comparison put AI at 238 minutes against 716 for hand work and concluded the

contribution is ideation and early prototyping. That is the correct job description, and it is

exactly the job the rejected chain was doing badly by hand.

---

Stage 7 — Cleanup

BOTH PASSES IN THIS STAGE ARE CHARTERED AND UNBUILT — say so rather than describing them as running.

connected components at 99.1%" means (TripoSG is worse in count: 18 components at 99.8%). *"A

shell-cleanup pass belongs in the fitting stage."* No script implements it.

surveyed: bpy.ops.mesh.symmetrize(direction='NEGATIVE_X', threshold=0.0001) when one side is

authoritative and topological symmetry is required; `symmetry_snap(..., threshold=0.05, factor=0.5,

use_center=True)` when a near-symmetric generated mesh should keep detail from both sides; and the

ordering rule that decides correctness — **transform the mesh so the fitted plane becomes the world

YZ plane through the origin FIRST, then call the operator.**

WHAT DOES EXIST. finish_mesh2 with FINISH_SETTINGS = {pre: 60000, quads: 6000}, per-item

overridable (the serpent used 24,000); and a second-chance --volume-fallback that voxelises when

surface repair leaves the mesh open, still judged by the battery's 3% silhouette threshold.

THE FORMAT ADAPTER THAT DELIBERATELY DOES NOTHING ELSE. condition_generated.py carries its own

scope in its header: *"no smoothing, no decimation, no symmetry, no proportion fitting. Those are later

stages and they must not be allowed to hide inside a format conversion."* Its axis map

[[-1,0,0],[0,0,1],[0,1,0]] is asserted to have determinant +1 so no arm's asymmetry is silently

mirrored.

THE TRAP — A REFERENCE PLANE FITTED TO THE FEET. measure_mesh.py's first draft referenced band

drift to *"the median x of the lowest 6% of the figure"* — the feet. With a figure standing with its

feet APART that median lands inside whichever foot carries more vertices, so the reference plane sat

half a stance off centre: **every generated arm scored ~0.30 width asymmetry and the mirror-built arm

scored near perfect. The fix is a symmetry plane fitted per mesh** by minimising the mirror residual

over offset and yaw, applied identically to every arm including the one already centred on x=0. **It

nearly produced the opposite verdict.**

---

Stage 8 — Lattice-fit to specs

THE MEASUREMENT STACK SURVIVES THE MOVE TO GENERATED GEOMETRY — tested, not asserted. Read with the

house instrument (build/3d/cage/body_stage/body_probe.cross_section — the same exact triangle-plane

perimeter proportion_review.py uses, so the test is not circular), the Hi3DGen output already

lands within a few percent of the A14 spec at every readable site with no fitting at all: knee +2.5%,

waist −3.3%, hip +5.5%, chest −1.4%. That is because the plate was built to the spec and

generation preserves it.

**THE WINNING RECIPE: a raised-cosine radial lattice, C1 at both band edges so no crease and no seam is

introduced.** build/3d/bakeoff/fit_girth_lattice.py: weight w = 0 beyond the band, else

0.5·(1 + cos(π·d)) where d = |V_z − z| / band; scale s = 1 + (k−1)·w; k solved by secant from a

circular first guess k = target/g0, breaking at relative residual < 1e-4; --band default 22.0 cm,

--iters default 4. Its own docstring: *"A linear ramp would be C0 and would leave a visible ring — the

exact class of artefact the rejected chain shows."*

ONE iteration** (FIT_GIRTH_HI3DGEN_waist.json).

two iterations, residual 0.16 ppm — the "before" figure is itself the trap below.

Non-circularity is structural: girth_at() imports body_probe and calls BP.cross_section +

BP.loop_stats, the same functions proportion_review.py uses — the fitter does not carry a

measurement of its own.

THE INSTRUMENT. body_probe.cross_section — *"Every triangle straddling the plane contributes

exactly one segment. Segments are welded on their endpoints and walked into loops; an unclosed chain is

returned as an open polyline and reported, never silently closed."* PROFILE_STEP = 0.25 cm,

WELD_TOL = 1e-7. Its own justification for existing: *"the chin detector was wrong on 4 of 4 busts…

A planar cross-section is not a heuristic: the triangle-plane intersection is exact, the loop count at a

height is an integer."*

THE TRAP — THE NAIVE LARGEST-LOOP SITE PICKER IS WRONG ON GENERATED GEOMETRY. At chest height it

selected a spurious 111 cm loop over the true 80.8 cm torso. It is not a bake-off curiosity: in

the field the same picker read a hip at 152.1 cm against an 82.9 cm target because the section was

enclosing both forearms — the trochanter sits at 87.0 cm while the wrist sits at 80.8 cm at age 14.

The GIRTH_SITES table in proportion_review.py carries that derivation inline and marks the row

*"Confounded, published, not scored."* **The house confound logic must come across with the

measurement, never be reimplemented.** Two working replacements exist and should be preferred:

build_true_bare_base.py picks the loop nearest the midline for torso sites (plus a pelvic-window

guard, because a section at the crotch is closing over two thighs and reads a hip that is two legs), and

proportion_review_v2.py anchors on topological transitions instead — z_crotch from the loop-count

2→ transition, z_arm_hi from the longest run of three loops. A sibling instance of the same class:

cross-section topology refused itself on the assembly pose because the thighs were in contact and the

legs read as merged from 40 cm — which is a knee.

---

Stage 9 — Region partition and the doll-underwear standards

THE RATIFIED ARCHITECTURE. ONE bare mesh, partitioned into real anatomical regions — each with its

own proportions, physical values (density / weight / failure semantics), record, UV block, and

material slot for per-region suppression under gear. Expressing the partition in the UV layout as

well as in material slots is an authoring-time decision that cannot be retrofitted cheaply: UV blocks

are what Mutable's RemoveMeshBlocks and MetaHuman's Body Hidden Face Map both consume.

THE PARTITION IS BUILT AND GATED — 14 REGIONS, R01–R14.

build/3d/characters/body_specs/BODY_REGION_PARTITION.json: R01_FOOT, R02_LOWER_LEG, R03_KNEE,

R04_THIGH, R05_PELVIC_GIRDLE, R06_ABDOMEN, R07_THORAX, R08_SHOULDER, R09_UPPER_ARM, R10_ELBOW,

R11_FOREARM, R12_WRIST, R13_HAND, R14_NECK_SEAM. Each carries bilateral, proximal/distal extents,

governing_girths[], mass_segment, surface_area_fraction (R07 thorax 0.171 largest, R03 knee 0.026

smallest), mechanics_class, palette_zones[] and an enhancement_spec pointer. Its stated law:

*"REGIONS OF ONE MESH. A region pass writes back into the shared mesh; it never merges geometry."*

PER-REGION PHYSICAL VALUES ARE REAL FILES WITH A REAL GATE. Fourteen specs at

build/3d/characters/body_specs/regions/R*.json, every number carrying _basis

(measurement / derived / calibrated) and _cite[]. R05 for example: density 1.03 g/cm³ (WINTER2009,

DEMPSTER1955); mass 4.026 / 6.085 / 8.229 kg at ages 11 / 14 / 18; skin Young's modulus 0.25–0.42 →

0.42–0.75 MPa across the same ages; gluteal muscle 8–20 kPa relaxed / 50–100 contracted; pelvic cortical

16–20 GPa; sacroiliac motion 2–4°. An adipose value is declared a PROXY on its own face rather than

passed off as measured. The gate is check_region_specs.pyREGION_SPEC_GATE.json: 14 expected / 14

present, per-region citation and unmeasured counts, ladder values restated and checked, findings [],

verdict PASS.

UV BLOCKS AND MATERIAL SLOTS ARE ALLOCATED, ONE PER REGION. TRUE_BARE_BASE.json gives each region

one UDIM tile and one material slot — R01 → 1001 / M_BODY_R01_FOOT, R02 → 1002, and so on — with

R05 → udim 1005 / M_BODY_MANNEQUIN, which is the doll slot.

THE STANDARDS THAT ARE ABSOLUTE.

photoreal pass, at any age, permanently. This is structural — it is its own UV block and its own

material slot, so a texturing pass cannot address it even by mistake."* The chunk-enhancement

roster in body_ladder_v3.py correspondingly has no R05 entry: no crop band, no prompt, no

submission. Geometry-side, the median raphe, perianal radial folds and perineal rugae are absent

while staying curvature-continuous with surrounding anatomy — and the spec states why that is

geometry and not a texture trick: *"a texture cannot make geometry absent."*

build/3d/cage/body_stage/DOLL_UNDERWEAR_{SPEC.md,PARAMS.json}. Its topology is a conforming shell

whose vertices are the cage's vertices displaced along cage normals, so *"skin weights inherited

vertex-for-vertex from the cage. No transfer, no nearest-neighbour search, no error term."* Thickness

ships at ¾ of budget in every zone — waistband-over-crest 0.45 of 0.60 mm, waistband-flank 1.50 of

2.00, gluteal panel 1.50 of 2.00, leg-opening band 1.13 of 1.50, front panel and gusset 1.50 of 2.00 —

against a cloth collision proxy of 2.0 mm, a rigid-plate standoff of 3.0 mm at 120° hip flexion, and

0.6 mm over bone. Per-age patterns are solved (waistband seat 68.59 / 84.68 / 98.68 / 108.33 cm at 7 /

11 / 14 / 18), and the seat re-derivation agreeing with R05's stated heights to 0.02 cm at 11 and 18

is itself a tooth in the parameter file. The four-part no-collision contract: a thickness budget; a

compression inheritance (*"its collision proxy is the body's, never its own"*); a visibility contract

(a gear piece masks the garment's UV block, never deletes it); and the end state — *"at unequip-all

the scene holds exactly two meshes, body and garment, at a constant positive offset, with zero rigid

colliders."*

a parameter file… It is not a mesh, and it is not evidence that any built mesh matches it."* Three

named gaps ride on its face, including that R05 carries ages 11/14/18 only, so **age-7 cleft length and

inguinal offset are declared extrapolations.**

equipment swaps the visible state to the minimal underwear layer; attempt-to-unequip-below-floor is a

tested refusal, not an assumption. The counterweight has equal force: the floor never forces

coverage onto culturally-accurate dress — minimal-coverage wraps, loincloths and open dress render

authentic to their culture and era.

alone isnt illegal, but we still dont want to publish that to our game since its not necessary."* Not

a legal requirement, not a care obligation. Future content questions cite this as a chosen line, never

as evidence of a conservatism mandate.

presentation gate does its work at the player boundary. Generated imagery of the minor rungs keeps the

tasteful-minimal register **at zero pipeline cost, because mesh completeness at every age comes from

the parametric cage, never from generated imagery.** The architecture already separated these; the

ruling only names it.

THE MERGE BAN, restated because it is the partition's whole point: geometric merging of

independently generated parts is BANNED. A partition has zero seams by construction, which is what

satisfies Josh's five if-modular conditions without a modular route. "Remerge" in the pass loop means a

region pass writes back into the shared mesh.

BUDGETS ARE TEETH, NOT NOTES. Character-class meshes take the NPC row of docs/asset_budgets.json,

which inherits Creatures: LOD0 24,000 / 60,000 / 120,000 triangles (Steam-Deck minimum / mid-range

PC / high-end PC) and 4 / 4 / 3 LOD chain steps, with A1_vertex_tri_ratio_max = 2.0. Enforced at

the LOD stage by GATE 75 asset_budgets. **Named gap: material_slot_cap reads NOT_DECLARED for the

NPC class** — the gate prints it under DECLARED NOT-ARMED with its arming condition rather than

inventing a threshold, and a character factory that stamps hundreds needs that number declared. The

reason the gate exists at all: the hood measured 5.59× over floor with no gate anywhere.

---

Stage 10 — Texture

THE RATIFIED COLOUR ROUTE: MV-Adapter ig2mv 6-view + harness/asset_factory/mv_texture_bake.py,

superseding the v1 single orthographic projection on real blind evidence (surface +1.89 per item

against a measured 1.125 judge-noise floor — and the noise floor is a tooth: *"an aggregate texture

win inside the measured judge-noise floor refuses the emit"*).

Generation params: seed 42, steps 50, guidance 3.0, res 768, ref_scale 1.0, negative *"watermark,

ugly, deformed, noisy, blurry, low contrast"*. ig2mv camera set: elevation [0,0,0,0,+90,−90],

azimuth [−90,0,90,180,90,90], distance 1.8, ortho scale 1.1. Merge params: --facing-power 3.0,

--facing-floor 0.05 (*"views more grazing than this contribute nothing"*), depth bias radius/200,

hole fill by nearest-valid push at max 64 dilate rounds. Bake res 1024 for the v2 route (the stage

tool defaults to 2048).

TWO CONSTRUCTION CHOICES THAT ARE WHY IT WORKS. The conditioning images and the merge's

world_to_camera matrices come from the SAME camera objects, exported once to JSON, *"so generated

colour cannot land on the wrong texels."* And the mesh is normalised `vertices / max(abs(vertices)) ×

0.5 about the ORIGIN before conditioning, because positions are encoded pos+0.5` into [0,1] and *"a

mesh outside [−0.5, 0.5] clips to a flat block and the model is conditioned on garbage."*

nvdiffrast is absent by design and the guard is mutation-proven. `import_nvdiffrast_result:

ModuleNotFoundError; the loader raises SystemExit if 'nvdiffrast' in sys.modules`, and injecting a

fake module makes it fire — *"a check that has never been seen to fire is decoration, not a tooth."*

Rasterisation is Blender-headless instead.

Measured: 26.0 s generate / 48.12 s total (n=9), 20.49 GiB allocated but 29.06 GiB RESERVED — and

the reserved figure is the one that governs scheduling: *"~29.6 GiB reserved on a 32 GiB card means this

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

plan the batch as: all geometry first (shareable), then the texture pass alone."* The honest price is

stated too: the route *"replaces a 2.25 s bake with a 26.0 s generation, so the per-asset machine cost

rises from about 57.5 s to about 81.3 s. That is the honest price of surface +1.89."*

COVERAGE. The v1 projection was measured observing 30.3% of the surface (253,435 of 837,130

texels observed; 583,695 hole-filled) and inventing the rest; the 6-view route observes 0.516–0.794

across the nine bench cells, mean 0.61, and reports holes rather than inventing them — the

record emits observed_fraction, texels_hole_filled and per-view contribution counts, because *"a

hole that got filled is still a texel nobody observed."* Real production batches run higher: equipment

11 items mean 0.8375, serpent 0.9883. A 24-view geometric ceiling exists for comparison (0.986).

Population tooth over 254 landed assets: median untextured fraction 0.24, worst 0.7395 — declared

"REPORTS, does not reject."

CHUNK BY CHUNK, AND THE ORDER IS RULED. Proportion the whole first → enhance region by region

pre-merge → merge on the cage → verify the caged whole (photoreal / proportion / anatomy / physics) →

layer → gauntlet (DECISIONS :: THE PASS DISCIPLINE · PRE-MERGE ENHANCEMENT PASSES). Photoreal texture

is applied per chunk on the partition's UV blocks and material slots — full photoreal on every visible

region at every age — **because texturing is per-chunk on the mesh and never requires a full-body bare

photoreal render to exist.**

THE FREE WIN, AND THE CORRECTION THE AUDIT OWED ITSELF. xatlas.parametrize() was called bare, so

the library defaults applied — padding=0, bruteForce=False, blockAlign=False, max_iterations=1

and islands touch, so every asset we have ever baked carries bake bleed at every seam. Measured at

bake resolution on landed meshes: CR_0001 12 touching island pairs, EQS_0013 19, WPN_001 8, with

59 / 79 / 36 four-by-four mip blocks holding more than one chart. *"That is the seam bleed, it is a

property of the ATLAS, and no work in the bake or the texture route can remove it."*

**THE AUDIT'S PRESCRIBED FIX DOES NOT WORK ON THE INSTALLED BINDING, and this is exactly why the call

sites 'forgot' to pass options. Installed xatlas is 0.0.11**, whose signature is

parametrize(positions, indices, normals=None, uvs=None)it accepts no options at all. Options

reach xatlas only through the class API: Atlas.generate(chart_options=..., pack_options=...). Landed

at harness/asset_factory/uv_pack_options.py.

ADOPTED: UV_PADDING_TEXELS = 2 (scaled: padding_for(res) = max(1, round(2 × res/1024)), so 4 at

2048), UV_BRUTE_FORCE = True, UV_BLOCK_ALIGN = True, UV_CHART_MAX_ITERATIONS = 1. Result: **zero

2×2 and zero 4×4 blocks hold two charts, against 6/11/1 and 59/79/36 before** — and it is *"STRICTLY

DOMINANT… it removes every touching pair and every contaminated mip block while RAISING

uv_area_utilization by +3.2% / +2.3% / +8.0%"*, at ~0.2 s per asset. blockAlign is also **6×

faster** (1.0 s against 6.0 s on CR_0001) and prevents a BC block straddling two islands.

DECLINED, with the numbers rather than by taste: padding=3 buys a 5-texel gap and costs 1.7% texel

density; max_iterations=2..4 consolidates charts (CR_0001 246 → 212) but costs utilisation −5.2% /

−6.1% / −4.5% — *"trading it away for a chart count no gate reads is a regression, not a win."* A

--uv-legacy-defaults flag reproduces the pre-fix atlas for historical measurement only. And both the

requested and the realised gutter are recorded (gutter_realised_at_bake_res), because *"recording

both is what stops a caller claiming a padding it did not get."*

**PBR IS THE WORST CAPABILITY GAP IN THE STACK, and it is a missing physical quantity rather than a

stale model.** Every equipment generation.json reads *"No texture-generation model used"*, and

emit_manifest_from_landed.py writes the ORM contract as *"R = REAL baked AO; G and B = DECLARED

CONSTANTS, not maps."* **A 2026 AAA surface is not reachable from constants and no amount of geometry

work closes it. Named replacement: Material Anything** (MIT) as a decomposition pass bolted onto the

existing bake — albedo + roughness + metallic + bump, PyTorch3D + Blender, no nvdiffrast. THIN EVIDENCE

on maintenance: verify before adopting.

THE DETAIL / REFINEMENT STAGE: SeedVR2, wired at harness/asset_factory/seedvr2_refine.py. The slot

was positive-controlled EMPTY — *"12 files use ComfyUI scaling node params, 0 load any upscale model"* —

while the face lane asked in writing for *"an upscaler/refiner with its own conditioning"* for four

generations. SeedVR2 synthesizes hair, skin and fabric texture rather than resampling, which is

exactly the missing top-octave energy the judge measured. It is Apache-2.0 and its **nodes are native in

the installed ComfyUI 0.29.0**.

this box and re-verified against the RUNNING server's /object_info:

`LoadImage → ImageScaleBy → SeedVR2Preprocess → VAEEncodeTiled → SeedVR2Conditioning → KSampler →

VAEDecodeTiled → SeedVR2PostProcessing → SaveImage, with VAELoader and UNETLoader` feeding in.

Widget values carried verbatim: steps 1 (*"SeedVR2 is a one-step restoration sampler"*),

cfg 1.0, euler / simple, denoise 1.0, tile 512 / overlap 128, --scale 2.0,

--color-correction lab. One substitution is declared in-file (ImageScaleBy lanczos for the

template's dynamic-combo node, identical maths).

input, link target and output slot against the live server (11 nodes, 0 findings); --self-test

MUTATES the real graph five ways and requires all five to go red (5/5 caught).

and the negative conditioning out of the input's own VAE latent — **there is no text encoder in the

graph at all** — so it has nothing to drift toward. That is the opposite of the Qwen refine ladder,

which bought sharpness and paid identity monotonically every rung: head-band micro 598.16 → 433.87 →

398.14 → 391.67 while exemplar_match fell 0.91889 → 0.90621 → 0.89790 → 0.88914.

— so the model is never credited for pixel count a resampler already gives.

WEIGHTS: seedvr2_3b_int8_convrot.safetensors (3.46 GB) + seedvr2_ema_vae_fp16.safetensors (0.50 GB)

from Comfy-Org/SeedVR2 (Apache-2.0), 3.96 GB total. Under the blanket install authorization

(§7) this proceeds.

LOOKDEV IS THE LIGHT UNDER WHICH POLISH IS JUDGED. Renders are Cycles at view transform

Standard, look None, exposure 0.0, gamma 1.0, world strength 1.0 — not AgX, because

AgX deliberately does not round-trip a known sRGB value and the chart is only a pipeline check if a

known input can be compared to a measured output. **A beauty pass under AgX is a different artifact and

must say so on its face.** De-light is mandatory on any basecolor that is captured, photographed,

plate-derived or generated; the 30–240 sRGB dielectric band is a lighting detector wearing a colour

check, because a basecolor with lighting baked in carries the capture's shadow terminator and specular

highlight as pigment (docs/LOOKDEV_STANDARD.md §§4-6). **A/B arms are re-rendered by the instrument

doing the comparing** — a bench once compared one lane's cavity-shaded clay against another lane's flat

turnaround and read backwards.

---

Stage 11 — Rig, bind, ROM

WHAT EXISTS. Bind on the whole body, never a partial mesh (bl_skin_to_mannequin.py). Landed

figures for CHAR_0001: bind stature 150.877 UE-cm at component scale 0.855 → rendered 129.0 cm, coord

fit worst residual 9.94e-07 Blender units, export verify **worst bone error 0.000186 cm over 88

bones; four LODs at 21,154 / 11,622 / 6,340 / 3,170 tris with unweighted_vertices: 0**, influences

pruned 10 → 4, worst weight-sum error 0.0, orphan vertices 0, max drift 0.065%. Honest tier declared

on its own face: PREVIZ-AUTOSKIN — *"bone heat on a welded copy… Not a hand-painted weightmap;

joints will pinch under extreme flexion."*

A SPLIT-BIND FINDING THAT GENERALISES. Outfit pieces bind on the WHOLE set and are split by

material afterwards, because *"binding each piece alone HARD FAILED that control on the chest (derived

yaw 0, best measured 180)… The control is not weakened; the bind moved to where it is valid."*

THE ONLY DETERMINISTIC RIGGER IN THIS REPO IS THE LIMBLESS ONE.

harness/asset_factory/bl_limbless_rig.py, anatomy-law bound at 22–64 deform bones with a **25°

per-joint lateral cap** — and the floor is derived, not chosen: *"a coiled serpent bind pose that wraps

1.5 turns needs 540° of cumulative lateral curvature. At the measured 25°-per-joint ceiling that is 21.6

joints, so 22 is the floor."* On CR_0002 it produced 38 bones, mean length 12.6 cm, cumulative curvature

439.32°, joints over cap: 0 — because joint spacing is solved against the cap by bisection

(k = 1.30994, max turn 28.257° → 25.0°) rather than placed at equal arc, which *"passed on the mean

and put six joints over the cap, because the neck's reverse bend carries a third of the body's curvature

in a tenth of its length."* Weights are **authored geodesic-arc blends, ≤2 influences, partition of

unity by construction** (weight_coverage 1.0, min and max weight sums both exactly 1.0) — and the

record states the alternative's measured cost: bone heat produced an 11.73× tear because *"on a body

that folds back toward itself the two sides are surface-far and space-near, heat leaks across, and one

bone ends up owning skin on both sides."*

WHAT IS MISSING ON THE HUMANOID SIDE. The installed previz rigger offers quadruped / serpentine /

spine-only and has no biped mode at all; UniRig is the ruled auto-rigger and is NOT INSTALLED.

So the humanoid path is a MANUAL BIND to SKM_Manny_SimpleCHAR_0001_CLOTHED_SKIN_CLOSURE.json

says it verbatim: *"MANUAL BIND, not UniRig."* Named replacement: MetaHuman 5.8 Mesh-to-MetaHuman,

which now conforms a full body from arbitrary topology (the docs name Meshy/Tripo meshes as valid

input), free and UE-native.

WHAT IS UNBUILT. ROM / calisthenics: 0 authored, creatures and humanoids alike. The JOINT-ROM

CORRECTNESS LAW is a rider on every auto-rig above. **The unpriced line item nobody names: no learned

auto-rigger emits archetype-named joints.** Archetype tables say glenohumeral, rigs say spine_02,

and nothing joins them — so adopting SkinTokens or MetaHuman costs a naming map per body plan. Price

it in the same change.

THE SHAPE THE ROM WORK SHOULD TAKE, from the research: no product takes a rigged character and emits

validated joint limits, and the published work is about *pose-conditioned* limits (Akhter & Black CVPR

2015 — elbow ROM depends on shoulder orientation). So: **hand-author one ROM/constraint profile per

archetype against a biomechanical reference, and let a shared cage transfer it to every character by

construction**, with a learned pose prior used only as a QA gate. The same argument makes rigging itself

collapse from a per-character authoring task into a vertex-index lookup once the cage is fixed.

SkinTokens is a Josh-tier licence read, not a lane's. MIT code and weights, +98–133% skinning

accuracy over UniRig — **but trained 70% ArticulationXL2.0 / 20% VRoid Hub / 10% ModelsResource (ripped

game models). An MIT weight licence does not launder the training corpus.** It is also blocked on a

flash-attn wheel for torch 2.9 / cp312 / cu12.

---

Stage 12 — Turntable acceptance

THE BAR IS JOSH'S OWN AND IT IS A LOOP, NOT A CHECK: *a PROPORTION REVIEW AT EVERY ANGLE — turntable

renders, iterated until perfect — and a PHOTOREAL PASS ON EVERY POINT with comparison to the reference

plates, identical-identical.* The acceptance loop is **render → compare → fix, per angle and per region,

evidence imaged each iteration** (DECISIONS :: 3D ACCEPTANCE BAR).

THE INSTRUMENT. build/3d/cage/render_turntable.py — one instrument for every arm, every figure

conditioned to a common height by build/3d/bakeoff/condition_generated.py, **whose axis map is

asserted to be a rotation rather than a mirror so no arm's asymmetry is silently flipped.**

--res 1100.

is computed ONCE from the figure and held for all eight passes. The sibling instrument normalises

each mesh to a fixed bbox diagonal so two different meshes frame identically — *"that is right for

comparing wraps and wrong here: a turntable of ONE asset wants the same camera at every angle so the

silhouette can be compared across the sheet."*

light STUDIO, color_type SINGLE at (0.60, 0.60, 0.62), show_cavity True with `cavity_type

BOTH and ridge/valley factors 1.0, render_aa 8, world background (0.30, 0.30, 0.33)`,

film_transparent False. Azimuth 0 is the face; the turn goes to the subject's right.

camera block — so a sheet can be proven to be the sheet it claims to be.

(X right, Y front, Z up, cm), and *"a mesh that is not will render wrong and this note is the only

warning there is."*

THE MEASURED HALF RUNS AT THE SAME EIGHT AZIMUTHS, proportion_review.py, *"on the geometry rather

than off the pixels, so a reading and its picture are the same angle by construction."* Three readings

in descending order of what they can prove: girths, silhouette width per azimuth at the rung's landmark

heights, then head-units — and head-units is declared a control, not a discovery: chin and crown are

placed by construction, so *"a non-zero residual here means the assembly step is broken."* The only

spec-scorable silhouette width is the acromion at azimuth 0/180 against across_shoulder_soft_tissue,

because that is the only breadth the spec states in soft tissue. No pass/fail threshold is encoded —

the VERDICT block publishes scored_girth_sites, worst_scored_girth_residual_frac,

stature_residual_cm and head_units_residual, and the eye decides.

The presentation deliverable is the lookdev sheet: every declared environment × 8 turntable views,

laid out 4 per row so it reads on a phone in one vertical scroll, with a header carrying the calibration

lock (view transform, look, exposure, gamma, renderer, samples, device, triangle count) and a footer

carrying the Guerrilla rule and the honest tier.

WHAT AN ACCEPTED ASSEMBLY LOOKS LIKE, from the one that passed at structure tier: stature exact to

0.000 cm, head-units residual under 0.0002 at all eight angles, neck-join clearance +0.029 cm

on the contract's side of zero, exact bilateral symmetry, and topology and UVs untouched **so an age rung

is a morph and not a different asset.** The conform's ladder assumption was tested rather than asserted —

predicted biacromial 31.434 cm against the mesh's measured 31.264, 0.54% apart.

**FOUR DEFECTS THE ASSEMBLY LOOP FOUND IN ITSELF, each carrying a number, each invisible to a topology

gate:** a per-axis least-squares fit let the rim's own saddle set the vertical scale and returned

scale_z 0.515, crushing the collar to a 17.0 cm neck; the zipper laid its band inside out at **305

winding defects** while reporting zero boundary edges, zero non-manifold edges and exactly three

components — all intended — which is why winding_defects is now measured and why the traversal is

READ off each surface's own directed boundary instead of guessed; a front anchor got into an np.interp

whose x must ascend, so D1 came back at 10.10 cm mean against a true 3.27 and closed the neck ring to

a 0.10 cm point — a defect no topology gate can see, because **collapsing a ring breaks no manifold

rule**; and the head is now clipped ON the plane rather than by face centroid, retiring a 200-vertex cut

ring whose polyline was 96.04 cm around a 32.39 cm neck.

THE STRUCTURAL LESSON: a Hermite filling surface cannot carry a clavicle. A cubic between two rings

has one degree of freedom per azimuth and per height, so it can bulge but cannot carry a ridge that runs

ACROSS azimuth — which is exactly what a clavicle is, and why three tangent gains were A/B'd and the eye

refused all three. The fix was to use the solved MetaHuman face half's own neck-and-shoulder geometry

warped onto the body's rim through a 92↔92 correspondence paired BY AZIMUTH, licensed by a

monotonicity control: index-for-index measures 16.58 cm mean against 2.79 for the paired one, so a

file that assumed shared indexing would have shipped a twisted collar. The bottom seam became a

WELD, not a zip — same index, max deviation 0.0 cm, zero triangles contributed. And the defect it

closed (D-V3, neck_base +7.7% → +0.3%) closed itself with no taper change of any kind: **the excess

was the Hermite's own flare, not the head's.**

---

Stage 13 — Game import and the swap gauntlet

WHAT PROVES AN ASSET IS WIRED. DescribeAssemblyJson() read-back proves what is on the body; a swap

test proves hide/restore is exactly reversible at every LOD index; and the ruling requires both

the read-back JSON (what it IS) and the frame (what it looks like). Add ULODSyncComponent so the body

and every gear component switch LOD together — MetaHuman ships it by default and we have nothing.

THE LANDING GATE IS BUILT AND HAS NINE TEETH. harness/asset_factory/verify_landed.py, last full

run 254 checked / 254 clean / 0 findings: T1 id tooth (record id == directory name; every media

filename is SM_<id> or T_<id>_*) · T2 media presence *and* non-zero size · T3 registry join

through an id-namespace prefix map, with every recorded cell re-compared against the live CSV · T4

battery re-measurement from the lane's own finish/export records using the same imported battery(),

not a copy · T5 licence pairing · T5b no care-gated asset ever reaches READY_FOR_IMPORT ·

T6 withdrawn is never importable *and* never still in candidates · T7 anatomy vs spec on rigged

imports (roster / segment count / required bones / ROM / centreline) · T8 phys-profile present.

Two meta-controls make the gate trustworthy rather than decorative: a VACUITY CONTROL — zero

candidates matched raises *"a checker that cannot find anything must not report a clean bill"* — and a

RULER-ROT CONTROL: T7 and T8 re-run their own mutation self-tests first, and a failure there exits

as a SETUP failure, never as a finding.

THE MANIFEST IS RE-DERIVED FROM DISK, NOT REMEMBERED, and the reason is a real loss: a slice-creature

run landed 142 candidates and produced no manifest because *"the GPU producer thread died mid-run on a

UnicodeEncodeError raised by a species name with a diacritic."* The fix is architectural —

*"a run is a process and a process can die, but the candidates it already landed are FILES and files

survive"* — so emit_manifest_from_landed.py reads the landed records and **no batch result and no run

summary at all**: *"a manifest that depends on a process surviving is not a manifest."* It also enforces

that landing is not permission to import: only ids still on the current worklist's route appear, and

care-gated rows land as PREVIZ_HOLD.

PATHS. Props follow /Game/Meshes/<class>/SM_<id>, the same string the runtime resolver prints.

Characters land off-convention at /Game/Characters/CHAR_0001/…, with the landed body at

/Game/Meshes/Characters/SK_CHAR_0001_CHILD and an engine seam that *"prefers the asset, falls back to

SKM_Manny_Simple; withdrawal is a file move and was proven by performing one."* Every shipped file is

pinned by bytes + sha256 per LOD and per texture in the import manifest. Named gap: there is no

.uasset package-bytes verifier in this repo — that proof lives in the game repo's QA bench, which this

lane treats as read-only, since the sole-writer slot belongs to the engine wave.

THE SWAP GAUNTLET is the collision answer and it is a named gate. Garments are **fitted on the cage

body**, sharing its surface definition — the BG3 pattern, which eliminates collision by construction —

and factory-complete additionally requires the **full equip/unequip cycle IN-ENGINE across all 16 slots,

their combinations, and every age state**: suppressed regions render nothing; garment inner surfaces show

ZERO penetration of visible body, measured not eyeballed; unequip-all lands on the swap floor;

captures imaged per the every-pass law. No character is factory-complete without passing the gauntlet

(DECISIONS :: THE CAGE REVIEW STACK + THE SWAP GAUNTLET).

AT SCALE, THE GAUNTLET IS A BATCH INSTRUMENT — all slots × all bodies × all ages, mechanical collision

proof per asset, so quality and collision-freedom survive the multiplication to tens of thousands

(DECISIONS :: THE SCALE MANDATE + FOUR ENHANCEMENTS, item 3).

THE PUBLISH GATE. A factory's output populates the review book ONLY when that factory is COMPLETE

through the full chain — Josh-graded exemplar → built asset → wired in-game (package-bytes verified) →

full motion where the class carries motion. Until then its pages show canon text and the honest empty

state. Building never pauses; only publishing waits (DECISIONS :: THE FACTORY-COMPLETE PUBLISH

GATE).

---

§3 THE AGING DIMENSION FOR THE CAST

The protagonist's ladder is not a protagonist feature. Supporting characters age too, because the

player revisits places across story years — and the policy below is derived from the spine's own

measured clock rather than assumed.

3.1 The story clock, measured

From registries/T0_Chapter_Index [ACTIVE v1.2] (protagonist_age / protagonist_age_end /

age_stage), across all 79 nodes:

Adulthood 40.

· Ch 8 = 10→11 · Ch 9 = 11 · Ch 10 = 11→12 · Ch 11 = 12 · Ch 12 = 12→13 · Ch 13 = 13. **The vertical

slice alone (Prologue→Ch 13) consumes ages 7 through 13.**

**The consequence for the factory is exact: age-variant cost is concentrated in the slice, and 41 of the

last chapters share a single adult state.** A cast member introduced in the modern arc needs one age.

3.2 Who actually recurs, measured two ways

Counting actors: lines across all 79 docs/spine/CH_*.md nodes: **130 distinct staged character ids,

of which exactly 7 appear as actors in more than one chapter.**

idwhochaptersages seenspan
CHAR_0005the Elven King / father57, 1811 y
CHAR_0017Ana229, 16, 189 y
CHAR_0002Ntala, the healer's child569, 13, 14, 15, 16, 17, 189 y
CHAR_0056Binti Hassan210, 144 y
CHAR_0003the Architect214, 184 y
CHAR_0009Elder Rato27, 92 y
CHAR_0071Kxao211, 132 y

Cross-checked against T0_Chapter_Index.seed_npc_ids: 114 distinct seeded NPC ids, **9 in more than one

chapter**, max span 9 years, and 105 of 114 single-chapter. The two filters disagree in membership and

agree in shape — recurrence is rare and the spans are bounded.

3.3 THE AGE-VARIANT POLICY

The driving fact is biological, not budgetary: **an 11-year span barely moves an adult and completely

rebuilds a child.** So the policy keys on the entity's own age band at first appearance, crossed with its

measured revisit span.

TierWhoAge variantsMethod
A — FULL LADDERThe protagonist. Any companion or cast member who is a minor and recurs across ≥ 4 story years7 rungs (his: 7, 9, 11, 12.5, 14, 16, 18); a companion's ladder spans only the chapters they are presentKeystones by the direct recipe at each Josh reference; in-betweens by Route W landmark warp from the older anchor
B — KEYSTONES ONLYA minor who recurs across 2–3 story years; an adolescent who crosses the puberty boundary2–3 rungs at the band edgesDirect recipe at each rung; no in-betweens — the gap is too small to read
C — ONE VARIANTAn adult who recurs across any span up to ~12 years; every rooted teacher, elder or contact1 base + 1 optional late variant (grey/weathering pass only, no proportion change)Base exemplar; the late variant is a texture/groom pass on the same mesh, never a new solve
D — SINGLE AGEEveryone met once — 105 of 114 seeded NPCs, the modern-arc cast, every crowd tier1Base exemplar, or the variant engine (§3.5)

Companions inherit ALL of it. Josh's ruling is unqualified: *"Every companion needs to follow the same

rulings across all ages"* — the same keystone method, the same bars, the same physique and identity laws

(DECISIONS :: THE KEYSTONE AGING METHOD + TOOL FREEDOM).

The named consumer today: CHAR_0002 Ntala. She recurs across 56 chapters and 9 story years, which

is Tier A. Her prep package already adjudicates a keystone set of 13 pick / 18 / 14, fills 15-17, with

the 9-12 low band contingent and reveal-gated because the pre-Ch-13 watcher is a HELD reveal

(build/art/characters/CHAR_0002_EXEMPLAR_PREP.md §2). That is Tier A with the ladder correctly clipped to

her presence window — the pattern for every companion.

3.4 What the engine does with a variant

The age swap is a discrete state change on the chapter clock, with no runtime interpolation: the

engine swaps age states at the chapter boundary and garments refit per state. The acceptance image is the

same in-engine camera across consecutive age states as a strip, **so the step reads as gradual rather

than as a jump** (BODY_ASSEMBLY_ARCHITECTURE_BRIEF_2026-08-06.md §6.1 stage 12).

Because every rung is a morph target on one cage with identical topology and UVs, an age variant is

not a different asset — it is a blendshape. That is the property the whole cage programme exists for,

and it is what makes Tier A affordable at cast scale.

3.5 The variant engine — how Tier D scales

Companion-grade MASTERS per cultural region, then parametric variation in the cage morph space plus

palette and feature ranges grounded in that region's REAL population anthropometry (accuracy as

respect: bodies per region drawn from real proportion data), plus per-NPC unique details via the persona

system. Tens of thousands of lawful faces from graded masters, zero per-individual grading

(DECISIONS :: THE SCALE MANDATE + FOUR ENHANCEMENTS, item 1). Its companion library is **cultural dress

per region and era**, zone-catalog grounded and research-cited — loincloth to full armor, every piece on

the cage, suppression-mapped, *historically true because the bare base underneath is anatomically true.*

The anthropometry caveat that binds it. AGE_PROPORTION_RESEARCH.md §6 states its own population

scope: the cormic index varies **47.3 to 55.8 between populations — a 7-point swing that dwarfs the entire

7→18 age signal of 1.5 points. The landed targets are US/European-descent medians. A regional master's

proportions are a per-region research input, not a recolour of the protagonist's numbers.**

3.6 The owed schema

registries/T0_Character_Index [ACTIVE v1.1] carries mesh_id_ref, mesh_pipeline_type,

generation_status, generation_tier, regeneration_trigger, ue_asset_path and binding_kind — and

no age-variant column at all. Measured today: 167 rows, generation_status = pending on 167/167,

and mesh_pipeline_type / generation_tier / binding_kind empty on 167 of 167. That is the honest

state of the cast factory: zero characters have entered the pipeline.

FINDING FOR THE DIRECTOR (this playbook may not change a registry): the driver in §4 needs an

age_variant_tier (A/B/C/D) and an age_rungs list per character row, or the policy above lives only in

prose. Recommended as a registry_extensions-declared column pair on T0_Character_Index, derivable

mechanically for every row from the two measurements in §3.2.

---

§4 AUTOMATION ARCHITECTURE — the per-character driver

The shape is already proven in this repo. harness/asset_factory/standing_batch.py is the precedent:

a pipelined driver over a proven stack that does not reimplement a single rung and does not edit one

the lane's tools are called as subprocesses exactly as the serial runner calls them, *"so this runner and

that one cannot drift apart in what they actually execute."* The character driver is its sibling.

4.1 The contract

python harness/asset_factory/character_factory.py \
    --character CHAR_0002 --config build/art/characters/CHAR_0002_FACTORY.json \
    [--stage face|body|merge|ladder|lift|fit|partition|texture|rig|turntable|import] \
    [--age 7|9|11|12.5|14|16|18|all] [--resume] [--limit N] [--dry-run]

the Josh reference per rung, the locked recipe ids, the physique clause set, the region partition

profile, and the licence records for every model touched. Nothing is typed at the call site.

id, seed, denoise, every input's sha256, wall-clock, VRAM peak, and the instrument readings — the shape

the existing keystone/body/merge records already carry.

its data, on a named instrument. A pass without its image is un-DONE — this is a hard ruling, not

a convention.

still match. A recipe change is a hash change, so it re-runs by itself.

4.2 Human gates are explicit pause points, not review requests

The driver stops and emits a review artifact. It never advances past a gate on its own.

GateArtifact the driver emitsWho
G1 FACE BRACKETper-age contact sheet, every cell labelled with lineage + detail_index + copy_to_pick, Josh's own reference inline beside each tileJosh picks a cell
G2 PHYSIQUE BRACKETthe 3-cell bracket per graded rung around the targetJosh picks the calibration point
G3 MERGED KEYSTONEthe keystone sheet, all rungs, at 1:1Josh approves / rejects
G4 IN-BETWEEN LADDERSthe 18 candidate-context ladders + the final (§ stage 4)Josh picks per age
G5 3D TURNTABLE8-view lookdev sheet per environment, plus the plate comparisondirector sighted every artifact; Josh on the final
G6 IN-ENGINEequip/unequip frames at a fixed camera, hem close-ups, one frame per LOD border, plus the read-back JSONdirector; Josh at factory-complete

Before G1/G3/G4 the driver runs the DIRECTOR EYE-PASS: a per-tile sighted audit recorded to disk. A

lane's gate table and its own eye-calls are inputs, never the pass.

The default priors the driver ships with, each of them Josh's established pattern rather than a guess:

in-betweens derive from the OLDER anchor; a bracket replaces a single-point guess the moment an axis

oscillates twice; candidates are judged in progression context, never as a tile; the lane **does not

down-select** — it labels and ships every cell.

4.3 Batch orchestration at cast scale

Inherited wholesale from standing_batch.py, because the constraints are identical:

bake for characters already through the card. The serial runner leaves ~40% of every asset's wall-clock

on the table.

ComfyUI queue-depth check before every submit. This lane YIELDS. It never assumes the card, it never

calls ComfyUI's /free (which would evict another lane's loaded model), and if the card is busy it

waits instead of OOMing — *a self-inflicted OOM reads as a real hardware trigger and costs the other

lane its run too.* The face lane's own runner already does this: it submits, waits its turn, backs off,

kills nothing. MV-Adapter's 29.06 GiB makes this binding on a 32 GiB card.

class named**, because rejects are cheap and the class is the lesson.

is theirs.

context; BODY lanes receive only the age-agnostic proportion spec; CHUNK lanes receive only their chunk's

spec and palette. Contamination is a named defect, so the driver passes disjoint context sets.

an int and loads BODY_AGE_%d.json. Rather than edit files another lane holds open, import them as

MODULES with SPECS/HERE pointed at a generated alias directory keyed on age × 10, then rewrite the

emitted age/spec fields back to the true rung and **declare every rewrite in the record's own alias

block.** Proven in lineup7_build.py.

4.4 The teeth the driver carries

Every one of these exists because its absence cost a run:

a MISSING baseline FAILS rather than passes, because an unverifiable claim is not a satisfied one.

real method defect on its first run (§ stage 2).

two-sided on the plate's own bands before its verdict counts.

acquire_exemplar.py runs 37/37. A checker that cannot fail is not a checker.

---

§5 THE INSTRUMENTS, AND THE LAW THAT GOVERNS THEM

InstrumentWhat it measuresWhereStanding
identity copy-index (merge_identity_v6.copy_index)Pearson correlation of two crops reduced to 64×64 grey (LANCZOS)merge / ladderCOPY_FLOOR = 0.99; vacuous when protection equals its own window
exemplar_match (merge_route_a_v8.measure_headmerge_race_a14.find_face)FFT normalised cross-correlation to LOCATE, then the 64×64 copy-index to SCORE, searched only inside the figure maskmergeceiling is 0.98994, not 1.0 — a 1344 px bust against a ~170 px placed head — *"a raw 0.99 floor on this instrument is not a bar any route can clear"*
struct_pos (face_landmark_warp.py)full-Procrustes position on the young→old shape axis; ⟨S_c−S_y, S_o−S_y⟩ / ‖S_o−S_y‖². 0 = young anchor's bone structure, 1 = old anchor's, 0.5 = a true in-betweenin-between facesgates the ladder. --selftest runs before every build and refuses unless anchors score exactly 0 and 1 (±1e-9), a 50/50 landmark blend reads 0.500 ±0.02, and a 90/10 reads 0.900 ±0.02 "or the axis is not linear." Full Procrustes is what stops the age-11 plate's known framing difference (41.7 px/cm against 48) masquerading as growth
ratio_pos (same file)the median of four scale-free skeletal proportions over interocular distancein-between facesrides beside struct_pos because *"struct_pos projects onto the WHOLE shape difference… including expression."* Median not meanface_w_over_iod reads temple-to-temple where hair crosses the landmark and on one plate scored −1.11, dragging a four-value mean from ~0.32 to 0.02 on its own
detail_index (face_overcopy_g4.detail_index)std(box − gaussian(box, σ=1.2)) × 1000 on the central 50%faces / ladderthe chained-pass cost meter
micro-texture (body_ladder_v3.micro_texture, wrapped by merge_identity_v6.micro)Laplacian variance over figure pixelsmerge / bodyfloor 75.1 — and it is the *geometric mean of the two measured arms* (doll 40.0, real 141.0), because an earlier borrowed constant of 190.0 killed every real plate
girth tables (body_probe.cross_section + loop_stats)exact triangle-plane perimeter at named sites; PROFILE_STEP 0.25 cm, WELD_TOL 1e-7; an unclosed chain is reported, never silently closedbody / fitthe house instrument; its confound logic must come across, never be reimplemented
measure_mesh.py (fit_symmetry_plane, symmetry_residual, band_profile, surface_quality)sym p95, drift range (not mean — *"a figure standing off-centre is merely translated and that is not a defect"*), width asym, components / largest share, lumpiness3D bake-offplane fitted per mesh by coarse-to-fine search over ±8% offset and ±12° yaw, 5 refinement rounds. Declares its own bound: a lower bound on point-to-surface, *"so a bad score is trustworthy and a good score also asserts dense sampling."* Reports; encodes no threshold
landing batterywatertight, manifold, max_bodies 8, max_deviation_pct 3.0, uv_in_unit_square, min_uv_utilization 0.18, tris 1,200–60,000, normal_baked, ao_mean_range [0.05, 0.98]landingthe armed threshold set (build/3d/verify_all.json)
texel_coverage_tooth.pyobserved texel fractiontexturemean 0.61 (0.52–0.79) on bench; declared "REPORTS, does not reject"
winding_defectsinside-out bands that pass every manifold checkassemblyreads 0 on the prior path too — that control is what proves the number is not merely reporting new code
garment / hair segmenterscoverage estimatesderivativesREPORTED, NEVER THE LANDMARK — the landmark is sighted and declared
find_face, silhouette neck-finder, chin detector, crown-only hair reader, silhouette blob guard, containment (for facing)NAMED WRONG on these subjects. Advisory only; none gates

THE SIGHTED-GATE LAW

**The eye outranks the instrument, and an instrument that scores an approved cell down is wrong by

definition.** Four independent proofs from this run, listed because one would be an anecdote:

1. Four engineered merge passes each closed an instrument-reported defect and none survived his eye.

2. The auto-picker and the eye disagreed on both perimeter rungs, and the eye's pick was right both

times.

3. find_face collapsed to 0.58–0.60 on the two plates Josh called great.

4. The metric ranking put the composite route first (0.971/0.943) while Josh graded the instruction edit

best by eye (0.952/0.946) — **and the gap is the finding: nothing in the stack was scoring "reads as one

photograph."**

The corollaries, which are the operational half:

face rather than reporting a pass.

operation only, and let the eye decide inside it.

THE CONTAINMENT LAW — a score that establishes less than it appears to

In the rig (this factory's own instance). The containment score — mean bone-to-nearest-vertex

distance over all deform bones, sampled at all four right-angle yaws — was the instrument used to

establish a character's facing. It cannot. A body is near front-back symmetric in that metric, so **0°

and 180° land within a fraction of a centimetre of each other** while both beat 90/270 by centimetres:

*"Containment therefore establishes the LATERAL axis and nothing more, and a flip that survives it would

ship a character walking backwards through every clip"*

(build/3d/characters/bl_skin_to_mannequin.py). What actually gates the flip is containment **for the

lateral axis only, plus the rig's own clavicle_l/clavicle_r derivation, plus two rendered witness

frames — and a disagreement between derived and best-measured yaw is a hard fail, not a shrug.** Mean

is used deliberately over max, because *"a max is one outlying finger away from being uninformative."*

Two flip instruments were retired on their own calibration and named so they are not revived:

face_vs_occiput_cm (reads the modelled hair mass at the occiput, not the nose — the bare-headed

mannequin calibration does not transfer) and toe_vs_heel_cm (mannequin margin 0.98 cm against a 2.0 cm

bar — uninformative).

**In a matcher (the same class, caught in the audio lane, imported here because the character factory

will need identity and variant matchers).** Scored on RAW substrings in both directions at a flat 0.90,

FINAL FANTASY V is a substring of FINAL FANTASY VI — **a match across a token boundary, v being a

prefix of the token vi, never that token — and a wrong cue attached at total 0.91, past every bar**

(docs/PIPELINE_LEDGER.md :: THE CONTAINMENT POISON CLOSES). The fix: **containment requires a

contiguous TOKEN RUN and is scored ASYMMETRICALLY** — shorthand earns the credit, a strict subset earns

nothing — plus a sequel veto. And the arming proof matters more than the fix: reading every

strict subset as a refusal — the naive reading — reddened the control by flagging seventeen landed rows.

**That is why the rule is asymmetric rather than blanket, and why the mutation control is the tooth

rather than the rule.**

The law both instances teach: a score that separates one axis is not evidence about the axes it does

not separate. Write down what an instrument establishes and what it does not, on its own face.

FOUR MORE INSTRUMENT TRAPS FROM THE 3D SIDE, each with its number

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

a GLB that looked fine at a glance."* Cause: the view renderer runs inside WSL and recorded /mnt/d/…

paths, so the Windows-side merge failed os.path.exists on all six. **Why it was caught: because the

merge REPORTS holes instead of hiding them. A merge that silently nearest-filled would have shipped

this.** A cell whose bake observed nothing is now FAILED and never reaches a blind sheet.

Four of six views of a flat weapon rendered a featureless dot or hairline strip. The fix is a ratio

gate at 1.6, not a class list, because at 1.6 it fires on exactly the three long thin subjects

(8.85 / 3.38 / 6.57) and leaves the near-equidimensional ones (1.01–1.07) authored.

defect.** The weapon class ships round-sectioned rods for canon-flat blades (flatness 0.99–1.79 against

a real flat blade's 3–7); *"a textured rod shot at 23° elevation from four cardinal azimuths reads as a

paddle"*, and *"WPN_036 photographed down its own long axis is a CIRCLE."* The bound the record then

places on itself: the routing table may not claim weapon IDENTITY is solved.

happened once, on two near-identical proportions. Declared impact NONE, and the fix named for the next

benchmark: show the judge the canon row id and its morphology text per cell.

wrong for a body metres long: *"the serpent rebuild landed 4,712 tris over a 4.8 m animal — a facet

roughly every 10 cm — visible in its own silhouette render."*

reuse on purpose, because *"a cached raw glb carries no record of whether the plate behind it was

judged."* A staleness check additionally discards a cached reference made from a different subject,

*"or the fix would have changed nothing."*

every reader thread on a UnicodeDecodeError and returned EMPTY output. *"The runs happened to succeed

and wrote their records to disk, which is the only reason it was visible at all — a FAILING run would

have been reported with no tail to diagnose it from."* Same family: a diacritic in a species name

killed a producer thread and cost 142 landed candidates their manifest.

report full coverage."* Count weighted vertices.

Weld by position and keep both arrays: *"the welded one is what topology is measured on, the UV-split

one is what ships."*

in the lowest tenth of the figure the heel reached 0.1117 against the forefoot's 0.0982, *"so the

control that demanded a markedly asymmetric extreme fired correctly and the answer was not taken."*

Replaced by a band-by-band depth-profile correlation that refuses below |corr| 0.90 — because *"a

heuristic that quietly returns the wrong sign is exactly the failure class the merge lane's chin

detector already cost this programme."*

the wrist sits at 80.8 cm and the waistband at 98.7, so the forearms and hands pass straight through

the band and the garment shell **grew arm vertices, reaching ±22.2 cm on a pelvis about half that

wide.** Fix: take the largest patch containing the midline.

therefore a 4.8 m animal at one third of its length"*; and for orientation, *"a tilted S reads 129 cm

tall on a body 30 cm thick."* Scale the traced centreline arc length, never the bbox.

---

§6 SCALE ECONOMICS — the measured numbers

Wall-clock and VRAM as recorded, not estimated. Where a figure is an estimate the row says so.

6.1 Per-stage, measured (build/3d/V2_ROUTING_RATIFIED.json :: costs_measured unless noted)

StagenmeanrangeVRAM
2D plate per candidate165.44 s5.31–5.64null — declared unmeasurable (runs inside a shared ComfyUI)
Instruction edit (Qwen-2511, 20B fp8)2 m 17 s steady state; ~7 min first cell (model load)24 cells ≈ 1 h on the shared queuenot recorded
Landmark warp (Route W)no diffusion pass at allnegligible
TripoSG geometry1321.63 s14.6–44.45.31 GiB (5.16–6.09)
Hi3DGen geometry925.26 s22.5–33.9810.99 GiB (10.59–13.78)
Hi3DGen, single full A14 run159.15 s (20.4 load + 7.4 normal-load + 23.3 geometry)10,849 MiB alloc / 12,104 reserved
Hunyuan3D-2.1 (struck on licence)84.0 s @ octree 256 / 77.9 s @ 5127.63 / 8.65 GiB
finish_mesh23111.87 s4.52–32.05
v1 single-projection bake (superseded)222.25 s1.93–2.62
MV-Adapter generate926.0 s23.97–29.1520.49 GiB alloc
MV-Adapter total948.12 s41.25–52.9929.06 GiB RESERVED — serialises the card
Cage wrap — Lane S2 (picked)351.46 sCPU / numpy
Cage wrap — Lane S1 (lost)16.29 s
Girth lattice fit1 iteration to 8.3 ppm2 iterations on a confounded sitenegligible
SeedVR2 3B detailnot yet run (weights owed)3B int8 3.46 GB + VAE 0.50
LOD chain119,994 / 59,996 / 29,998 / 11,998 tri, ear retained 99.20%
Local LLM (prompt-assembly fallback)qwen3:14b 53.9 t/s; phi4 146.8; 4b 361.1; 1.7b 479.714,388 MiB peak

The VRAM method is declared, and it matters: *"torch.cuda.max_memory_allocated inside each model's

own process — a running maximum, never an nvidia-smi sample."* And the plate generator's VRAM is

recorded as null with its reason rather than filled with a plausible number.

6.2 The per-asset model, and what real batches actually cost

The ratified per-asset figure is 81.3 machine-seconds, or 103.1 with one replate

(plates ×4 21.8 + TripoSG 21.63 + finish_mesh2 11.87 + MV-Adapter texture 26.0). Two costs are

deliberately not in it: the judged PICK (attended) and queue wait — *"this lane yields the card to

three other lanes and the yield is unbounded by design."* The replate budget is evidence-based: a

defining feature appeared in 3 of 8 canon-keyed candidates, so *"a one-shot text conditioning had

roughly a 50% chance of shipping the wrong object."*

Production batches, end to end (build/3d/batch_result_*.json):

batchattemptedpassedrecycledwall clockper asset
weapons (the clean reference)727202,161.2 s30.0 s
flores props4226162,820.2 s67.1 s
slice creatures9541,275.8 s141.8 s
equipment14113359.6 s25.7 s

finish_mesh2 is the variance source, not generation — its per-item maximum reached 1,222.3 s on

slice creatures and 106.5 s on equipment, against an 11.87 s mean. Multi-view texture passes run

~50–75 s/item in production (equipment 11 items in 547.7 s) with one 749.3 s outlier on the serpent.

6.3 What this says about cast scale

The GPU-bound stages are texture (29.06 GiB reserved, serialising) and the instruction editor

(~2 m 17 s per cell). **But everything that made the protagonist expensive was ITERATION COUNT, not

per-unit cost** — the 18 rung's physique oscillated three times, the face ladder ran four generations,

the body register changed six times in one night, and the merge produced four passes that the grade then

excluded. **The bracket-instead-of-guess rule, the older-anchor default, and the do-not-down-select rule

all exist to cut iteration count, and that is where this factory's economics actually live.**

one turntable — order of a card-hour, zero human iteration.

(which are nearly free) — and its 3D age rungs are morph targets on one cage, not seven assets.

---

§7 OPS

**BLANKET INSTALL AUTHORIZATION (Josh, 2026-08-07, relayed by the director this sitting; OWED a

DECISIONS_PENDING_JOSH.md entry so it is citable from the record rather than from this file).**

Downloads and installs proceed as needed — weights, node packs, wheels, tools — without a per-item ask.

The SeedVR2 3.96 GB acquisition and the TRELLIS.2 wheel set are the immediate consumers.

LICENCES ARE STILL CHECKED PER ITEM, and the Hunyuan3D lesson is why. The authorization removes the

*permission* step, never the *licence read*. Hunyuan3D-2.1 was installed, run, benched and struck — its

territory clause excludes the EU, UK and South Korea and binds the OUTPUT, which a worldwide Steam release

violates by definition, and nobody had written that down until the read was performed against the

licence file already pinned in our own repo. The standing posture: **face-value reads, flag only explicitly

triggered prohibitions** — and record the read so it is not re-litigated. Every licence-blocked tool of this

cycle is named once so a bench day is never spent on it again: SUPIR (weights rights withheld),

NVIDIA PiD v1.5 (NSCLv1 weights — and it ships a decoder trained *specifically* for our own

Z-Image-Turbo), PartUV (Apache core, non-commercial NVIDIA checkpoint), Krea 2 (revenue-triggered

cessation, mandatory filter, mandatory name prefix), SkinTokens (MIT weights over a partly-ripped

training corpus — a Josh-tier read), XTTS-v2 (CPML non-commercial and Coqui dissolved, so nobody can

sell a commercial licence — the MPL-2.0 *code* licence is the trap).

TOOL FREEDOM IS STANDING. *"you dont always have to use claude and should always use whats best suited

for achieving our AAAAA quality across everyything"* — survey and adopt whatever model or open-source tool

does a task best, then alter, enhance and polish on our locked recipes. The licence bar and the

identity/provenance laws are unchanged (DECISIONS :: THE KEYSTONE AGING METHOD + TOOL FREEDOM).

THE ANTI-ORPHAN RULE, restated because this stack already lost 872 lines to it.

build/3d/research/LOCAL_MODELS_AUG2026.md — fully cited, carrying the working Windows install recipe that

later unblocked TRELLIS.2 — sat **untracked, unregistered in DOC_MAP, absent from the ledger, and consumed

by nothing.** *"The stack did not fall behind because nobody looked. It fell behind because what someone

found never reached a decision."* Every artifact this playbook's stages produce gets a record, a DOC_MAP

row and a named consumer in the same commit.

GATE STATE at the time of writing, attributed rather than smoothed. python harness/run_gates.py

exits 1 at HEAD on two failures that predate this document and belong to other lanes: ledger (a DANGLING

DOC_MAP entry for records_B/DIAGNOSE_BEFORE.json, plus ORPHAN GROWTH at 68 against a baseline of 66) and

line_citations (two NEW line-range citations in an untracked bestiary sheet). This document adds a

DOC_MAP row and mints zero line-range citations, so it moves neither number — which is the check that

neither is ours.

---

§8 WHAT IS OPEN

Named so the gaps are on the artifact's face rather than discovered later. Ranked by what blocks most.

downstream depends on it: age morphs (which are only cheap because identically-topologised wraps are

blendshapes of each other), the region partition on a shared vertex order, the swap gauntlet, and the

whole Tier-A economics. Priced: Faceform WrapCmd, headless and batchable at Indie $570, or build

landmark-constrained coarse-to-fine NICP, which Blender does not provide.

UNDECIDED AND THE BLEND PROOF FAILS").** The blend-proof half CLOSED as an instrument-reference

defect — G4 was judged against parent A while its own _why names the cage; re-referenced with

four controls holding, the proof PASSES (build/3d/cage/blend_fix/BLEND_G4_REFERENCE_FINDING.json,

869ba32f), so the seven-age lane's release gate is clear on this axis. The Anny-vs-MHR

PARAMETRIC-PRIOR question remains live and is now owned by charter row S4 (the prior lands as a

BOUND, never a target; the pose-and-prior wave ed40161d is executing it); MPFB2 remains not

installed.

facebook/dinov3-vitl16-pretrain-lvd1689m's gated terms. Submitted and awaiting review. Minutes to

re-run once open; the instrument, conditioning and sheet builder are all written.

full AFTER measurement path is dry-run green against a lanczos stand-in. Proceeds under §7. Minor

residue: the validate/self-test result exists in prose in the ledger, not as a JSON artifact.

Material Anything (MIT) is the named replacement; verify its maintenance status first.

ordering rule are already researched, so these are build items, not research ones.

remaining work is re-baking the corpus through it, which improves every existing asset.

18 side with the pair-cohesion problem (the 18 anchor's three-quarter pose and scar making

derivatives read disjoint) solved structurally.

every auto-rig migration carries an unpriced joint-naming map per body plan. Two mechanical

residues ride with it: verify_landed's rig-truth glob points at build/3d/rigs/, **which does not

exist**; and the one armed ROM instrument reads deflection as the angle between consecutive bone

direction vectors from component-space positions, convention-free by construction, *"because half

the false ROM findings in rigging come from reading a local Euler as if it were a joint angle."*

A registry change, and therefore a director's call, not this document's (§3.6).

anatomy schemas needs its own cage on the same partition principles. **One cage per archetype, never

one per project** — a quadruped and a serpent cannot share a vertex order. Census: 187 rows —

QUADRUPED 62, NEEDS_CANON_BODY_PLAN 42, WINGED 32, AQUATIC 20, LIMBLESS 13, ARBOREAL_PRIMATE 11,

SPRAWLING_QUADRUPED 4, MULTI_LEGGED 3.

commercially usable is human-shaped. Plan creature motion as AUTHORED and procedural against our

own archetype rigs, rather than waiting for a tool that is not coming.

4% at every derived rung and inside 0.2% at 14, published with their spread as the uncertainty. It is

not wired into AGE_PROPORTION_TARGETS.json, and the reason is a tool gap rather than a data gap:

conform_true_base.py's lateral field is ISOTROPIC, so there is no lever that can set a depth

independently of a breadth. OWED: an anisotropic lateral field (separate sx(z) and sy(z)),

after which those four rows become solve targets.

(16–18% of figure micro-texture) because *"the shared ComfyUI queue interrupted this sitting's native

run mid-sampler and Josh selected the plate that existed."* Never-degrade beats restore — the

native regeneration should make the refine pass unnecessary rather than compensate for it.

---

§9 WHERE THIS IS CONSUMED

C4 (companions), E1 (creature plates), G1 (rig + ROM), I5 (factory enhancement stages).

register and §4's conditioning plan take their stage list and their gate points from here.

playbook operationalises (and whose §6.1 stage-5 "12 morph targets" is superseded by the seven-age ruling).

docs/asset_budgets.json — the four factory-enhancement stages this chain calls.

licence reads every stage above inherits.

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