v2 — assembly defect cleared (acceptance candidate) 2026-09-19
Left (v1): the component assembly had two floating "wispy spray" fragments beside the body —
root-caused to the two component articulated-hand shells (a recovery-artifact source) bone-parented at the
wrist bones; they did not fit the rest rig and floated outboard of the arms. Right (v2): the misfitting hand
shells are dropped and the region falls back to the preserved rigged/animated core body's own gunmetal clawed hands
(which also read closer to the concept's dark clawed hands). Fragments gone across all four canonical views
(own-vision verified). Concept-match (CLIP, front vs concept) 0.716→0.725, silhouette IoU steady, no
region regression. Fix lives in the assembler (assemble_a01_components.py --drop-components hand), not an
in-place mesh edit — Blender re-export of the assembled glb explodes the bone-parented shells and is a verified
dead-end. Still a review candidate (authored mating sockets, palette weathering toward rust-orange, and
animation/runtime validation remain before freeze).
Palette — ACCEPTED path: codex grey-dominant driver + GPU paint 2026-09-19
The concept is grey-dominant gunmetal + rust-orange accents, not a solid accent colour. Codex (image_gen edit-mode) regenerated the a01 part drivers grey-dominant; re-painting the shape with a grey-dominant driver transfers correctly (thorax shown — gunmetal with rust-orange striping/weathering). This is the accepted palette path, superseding the whole-part CPU recolor below (which still read as a solid accent). Note: an earlier paint from a saturated rust-orange driver failed (yellow + blue) — the driver must be grey-dominant. Full-mech re-assembly (v4) is in progress; a mirrored-shell re-import bug (right side reverts to yellow) is being fixed before v4 is promoted.
Full-assembly grey-DOMINANT + PBR surface — v3 (passes the full-PBR gate)
Surface now passes the hard full-PBR gate (art-gen/aaa_surface_gate.py, exit 0):
the v3 build was albedo-only (the flat/washed-out cause) — added a spatial metallic-roughness map
derived from the albedo (exposed gunmetal → metallic/reflective; painted → dielectric) on all 12/12
materials, so metal now reflects the IBL environment instead of reading flat. Honest residual: reads
a touch bright/light-chrome vs the concept's dark weathered gunmetal (a darken + higher-roughness pass is
the next refinement); normal + AO maps are warnings (the ~147k shells have no separate high-poly to bake
from). Renders below are under the king_tier_render ProceduralSky IBL.
v3 re-aligns the a01 palette to the concept's grey-dominant gunmetal (in-engine,
king_tier_render). Pipeline: codex grey-dominant drivers → GPU paint → recolor_shell_palette.py
(residual-yellow → rust, then a --desaturate pass pulling the warm panels to grey) →
assembler metallic clamp (0.15; painted armour is near-dielectric, so full metallic bloomed warm texels to
a chrome sheen) → base-body core desaturate (the last yellow source, on the chest-centre + thigh accents
showing between shells). Construction-yellow is gone across ALL views incl. the head close-up (an earlier
pass over-claimed this — the full-body front had hidden residual yellow; verified close-up now). CLIP
concept-match is hue-insensitive (~0.72), so the metric can't score the palette; this is the user-directed
accepted direction. Honest residual: reads a touch cleaner / less-weathered than the concept — the
desaturation removed most rust-accent weathering; a light accent pass could restore it. Supersedes v2.
Palette fork — yellow vs rust-orange (superseded by the codex grey-rust path above)
Left: v2 as committed (construction-yellow shells). Right (v3): a CPU
texture-recolor of the shell base-colours (yellow→weathered rust-orange, gunmetal untouched) via
art-gen/recolor_shell_palette.py + re-assembly — closer to the concept's rust-orange story.
Measured concept-match is identical (0.725 vs 0.723; CLIP can't tell the hues apart), so this is a
taste / art-direction fork, not a measured win. Pick a direction and the shoulder-cowl band (which
shifted less than the torso) gets a harder pass. v3 held in scratch pending the call.
Palette method — why paint fails, recolor works
Left: re-painting the thorax with a correct rust-orange driver via Hunyuan3D-Paint → wrong: bright yellow armor + blue-tinted internals. Paint does not transfer a driver/concept palette. Right: the CPU texture recolor → correct rust-orange armor, gunmetal preserved. Palette must come from a correct driver or a CPU recolor, confirmed on real pixels.
Interactive candidate (rotate / zoom)
Method comparison — concept vs CPU recolor vs GPU paint
Left: concept (grey + rust-orange). Centre: CPU recolor (rigged) — this candidate, palette matched. Right: GPU re-paint from the concept — Hunyuan3D-Paint does not transfer a specific concept palette, so it comes back yellow. Palette must come from correct drivers or a CPU recolor, not from paint.
Where the earlier build stood
The earlier component build (right two panels) was white + bright yellow with a detached hand — rejected on palette and assembly. The recolor above supersedes it for colour direction.
Concept-match, per region
| region | silhouette IoU | perceptual | score |
|---|---|---|---|
| head | 0.855 | 0.817 | 0.836 ← worst |
| shoulders | 0.853 | 0.849 | 0.851 |
| torso | 1.000 | 0.925 | 0.962 |
| arms | 0.927 | 0.917 | 0.922 |
| legs | 0.999 | 0.926 | 0.962 |
| feet | 0.907 | 0.932 | 0.919 |
Scored with art-gen/concept_match.py (candidate front render vs a01_coherent_fullbody.png).
The silhouette IoU is partly depressed because the concept is a posed hero shot while the render is a rest pose. The
head is the clearest remaining divergence and is the next correction target.