systems/EYE_STAGE_SPEC.md
What this is. The build spec for EYES as a standing stage of the character factory chain, per
Josh's factory-enhancement roster item 2: *"EYES as a named sub-stage: cornea/iris shading,
subsurface, and a look-at rig — the FF7R appeal at runtime is mostly eyes; currently an owed note,
now a stage."* (docs/spine/DECISIONS_PENDING_JOSH.md L4708-4709, THE FACTORY ENHANCEMENT ROSTER.)
It converts that one line into a material stack, a texture contract, a rig, an LOD ladder, and a
review law, each grounded on what the repo has already measured.
Authority. PROPOSAL-TIER, and it rules nothing. Canon, the CVD and Josh's rulings bind every
line. Where this spec and canon disagree, canon wins and this spec is the defect. It says HOW the
eye stage runs; it never says what the character looks like — the plate lineage and the T3 colour
canon already said that.
Honest tier. Every claim below about the current state is a measured read off a landed record.
No claim is made that any eye asset is shippable. *(Superseded in place 2026-08-10, director-rows
wave: this line originally carried "the count of Josh-graded-acceptable generated plates across
three generations is 0". That register is closed — the V4 body plates are generated and
Josh-approved as the exemplar set ("Yeah v4 is approved", BODY_V4_CARRY_SEVEN_AGE.json). The
shippability claim above is unchanged.)*
---
**This section originally read "nothing in this spec executes yet / every execution step below is
BLOCKED" behind two blockers. Blocker 1 is DISCHARGED BY EVENTS; blocker 2 stands. Execution has in
fact landed:** eye records exist on the ROUTE-A lineage
(build/3d/best_a14/face_pass/EYE_ALBEDO_A14_V3.json, EYE_ALBEDO_A14_V32_ANCHOR_B.json,
L11_EYE_ANCHOR_FORK_V32.json, author_eye_a14.py; the aperture probe under
build/3d/best_a14/eye_aperture/), and the remaining eye-shader work (limbus/iris parameters, the
three geometry pieces — lacrimal meniscus, caruncle blend, eyelid occlusion) is carried by the
charter's S10 row (docs/pipeline_review/CHARACTER_FACTORY_MASTER_CHARTER.md), which is now the
authoritative sequencing for it. A doc still reading "blocked" while the work is landed is the drift
class the living-source law exists to kill; hence this supersession.
build/3d/cage/CAGE_PICK.jsonPICK = S2 numpy landmark-NRICP, p95 0.01749 vs do-nothing 0.05232) and its blend-proof release
blocker closed as an instrument-reference defect, proven by four controls
(build/3d/cage/blend_fix/BLEND_G4_REFERENCE_FINDING.json, landed 869ba32f). The original
text's caution ("must not presume which cage wins") is preserved as history below and needs no
further observance.
chain has not proven first (prep/reads exempt)"*
(docs/HANDOFF_2026-08-05_ACCOUNT_SWITCH.md L1003-1005, THE CONVERGENCE TARGET). The eye stage
runs on CHAR_0001 first, at the graded keystone ages, and cascades to companions/NPCs/creatures
only after it has proven itself there.
What is NOT blocked, and is what this wave landed: this spec, the parameter-contract tool
(GAME:Tools/char/eye_material_contract.py), and its synthetic fixture proof. None of them
generate a character, a plate, or a mesh.
## 0. THE UNBLOCK TRIGGER — nothing in this spec executes yet
**This spec is SCAFFOLDING. Every execution step below is BLOCKED until both of the following
land, in this order.**
- BLOCKER 1 — THE CAGE VERDICT. The cage-source bake-off is the standing chain's stage-2 gate
and the next architecture verdict due (docs/spine/DECISIONS_PENDING_JOSH.md L4642-4644, THE
PARTITION IS RATIFIED). Facial topology is one of its judged criteria, because *"expressions
live or die on the cage's face loops"* (same file, L4704-4707, roster item 1). The eye stage
consumes the winning cage's face loops — the palpebral aperture ring, the lid margin island, the
eye-socket region of the partition — and must not presume which cage wins. The bench that
decides it is build/3d/cage/CAGE_BENCH_SPEC.md (READ-ONLY to this lane; the W-CAGE seat is
live).
---
The stage does not start from nothing. The authored head lineage already solved the geometry half
and named its own material gap in writing. **What this spec reuses is stated so the execution wave
does not rebuild it, and what it replaces is stated so nobody defends the old thing.**
build/3d/characters/char_head_author.py L815-836 builds the globe with the polar axis on +Y — the direction the eye looks — *"so the iris, the limbal ring
and the pupil are concentric rings in texture space instead of a decal that has to be aligned by
hand and drifts."* Every map in §3 below is authored against that convention. This is the single
highest-leverage thing the lineage already got right and it is not touched.
char_head_author.py L839-866 builds an eyeball plus a **separatecornea cap with its own material**, on the stated reasoning that *"the wet specular that reads as
'alive' is a SECOND surface over the iris, not a highlight painted on one."* Measured on disk:
eye_l/eye_r at 704 verts / 1,344 tris each, cornea_l/cornea_r at 320 verts / 576 tris each
(build/3d/characters/CHAR_0001_HEAD_AUTHORED_RECORD.json /geometry/counts).
lid margin projected onto the globe (which is what closes the canthal gap a constant inset
leaves open), the margin ring carrying its own UV island so the bridge paints a wet lid margin
instead of a smeared strip of cylindrical skin (CHAR_0001_HEAD_AUTHORED_RECORD.json
/geometry/eye_aperture; the cutter is char_head_author.py L573-598). Cornea apex sits
0.03 cm behind the lid plane — the solved pair that keeps the cap from poking through.
EYE_HALF_IPD = 2.72 cm (IPD 5.44 cm, a 7-to-9-year-old's) and EYE_SET_BACK = 0.34 cm (char_head_author.py L143-144), eye radius 1.14 cm,
eye-to-head-height ratio 0.1161 (CHAR_0001_HEAD_AUTHORED_RECORD.json /geometry/measured).
These are the age-7 values; §4.4 makes them a per-age curve rather than constants.
IRIS_OUTER (0.470, 0.560, 0.618), IRIS_INNER (0.632, 0.702, 0.735), LIMBAL (0.185, 0.222, 0.268),
SCLERA (0.930, 0.912, 0.892) (build/3d/characters/char_head_textures.py L129-132). The canon
line behind it is the only sentence canon carries about elven colouring: the Elven King's *"eyes
are the same color as the protagonist's but deeper — the same shade with ten thousand years of
light behind them"* (_source/03_Tier_3_Characters/T3_Core_Characters [ACTIVE v1.0].md L563).
The shared quantity is the EYE colour. It does not move on any rung, at any age, on any route.
MI_CHAR_0001_Eye and MI_CHAR_0001_Cornea already exist, already carry used_with_skeletal_mesh: True, and already survived an engine import
(CHAR_0001_HEAD_AUTHORED_RECORD.json /engine_import/materials; the importer is
GAME:Tools/char/import_char_0001_headasm.py L75-95). **They are the bind points. This stage
fills them; it does not mint new slots.**
no_glowing_eyes_or_luminous_marks: True (CHAR_0001_HEAD_AUTHORED_RECORD.json /geometry/reveal_firewall). No emissive term appears
anywhere in §2. The eye is lit; it never lights.
importer's own tier string is the honest confession — *"AUTHORED GEOMETRY, DEFAULT-LIT MATERIAL —
the refractive cornea the portraits render needs a transmissive shader; here it is a very smooth
dielectric, which gives the wet specular but not the refraction"*
(GAME:Tools/char/import_char_0001_headasm.py L83-88). §2.1 replaces it.
T_HEAD_SSS is imported, set to TC_MASKS,and the importer states plainly that it is *"NOT YET CONSUMED by the engine material: this import
wires default-lit, so the mask is landed for the subsurface-profile pass and is honestly unused
today"* (import_char_0001_headasm.py L62-65). §2.4 consumes it.
0 refractive corneas and 0 apertures; the eyes are painted on a closed surface, and the record
says *"THE ROUTE DOES NOT SOLVE THIS AND WAS NEVER GOING TO"*
(CHAR_0001_FACE_PIVOT_RECORD.json /gaps_named_not_papered_over[0], quoted at
docs/pipeline_review/AAAAA_IMPROVEMENT_REGISTER_2026-08-06.md L87, register row 14). APP-C3 is
the one rubric check the generated route structurally cannot satisfy. **The graft named in row 14
is this spec's first execution step (§7).**
Source/ and Tools/anim/ finds LookAt only as camera-aim arithmetic in HumanityQACaptureSubsystem.cpp (L565, L608,
L688, L719) — a player-controller rotation, not an eye. §4 is built from zero.
SK_Mannequin at 89 bones, read back from the engine rather than declared (GAME:QA/bench/char_0001_arrival_set_import_result.json;
quoted in the dossier at docs/pipeline_review/AAA_WORKFLOW_CORRESPONDENCE_2026-08-06.md
L558-559). The UE5 Mannequin's 89 bones carry no eye joints — MetaHuman's ≈342 do (dossier L537).
This is the load-bearing constraint on §4 and it is named rather than assumed.
---
Six surfaces, each with a stated job. **A term appears here only if it changes what a frame shows;
a stack that cannot be seen at the review distance is cost without appeal.**
Default Lit + Clear Coat. The clear coat lobe is what gives a second,tighter specular over the iris — the physical truth of a cornea over an aqueous humour, and the
thing the constant-white incumbent gets wrong by having only one lobe.
incumbent's 0.02 is the correct order and is kept as the starting value), metallic 0, base colour
black with the surface reading entirely through its specular and the shell behind it.
A true refractive cornea needs a translucent/refraction blend mode, which in UE 5.8 costs a
separate translucency pass per pixel and does not receive the same lighting path. The AAA route
for a game eye is parallax-offset iris under an opaque cornea: the cornea samples the iris map
with a view-dependent UV offset scaled by the anterior-chamber depth, which reproduces the
apparent iris displacement as the head turns at a fraction of the cost. Anterior-chamber depth is
already solved geometrically — cornea apex 0.03 cm behind the lid plane against a 1.14 cm eye
radius (CHAR_0001_HEAD_AUTHORED_RECORD.json) — so the parallax scalar is derived from the mesh,
never dialled by eye.
CORNEA_REFRACTION variant usingthe true index-of-refraction term (1.376 for corneal tissue) is authored as a **cinematic-only
material variant** for the sequencer/portrait path, where the translucency cost is affordable and
a lookdev turntable will show the difference. It is judged against the parallax variant under the
W-LOOK standard (§6) before either is called finished.
lid-margin UV island that already exists. It is a roughness modulation on the cornea's outer
ring plus a narrow specular boost — never a separate transparent shell, because a second shell at
this scale is what produces the z-fighting shimmer at LOD1.
(§1.1), so the parallax direction is radial by construction and needs no tangent frame beyond the
one the sphere already has. Depth is sampled from a dedicated T_EYE_IRIS_H height map (§3),
deepest at the pupil and rising to zero at the limbus — the physical shape of the iris's posterior
surface.
sin(theta * 46) modulated by fBm, a collarette ring lobe at t = 0.34, and a limbal ring rising
over the outer 20% of the iris radius at 0.86 strength (char_head_textures.py L406-440,
eye_map). Pupil radius 0.0619 and iris radius 0.1810 in UV, with both boundaries feathered so
no aliased ring survives at portrait resolution (same function, L436-440).
view-dependent Fresnel darkening at the limbus is the geometry — the limbal ring reads darker
and wider at grazing angles because the corneal edge is thicker there. The incumbent has the first
and not the second, and the second is what makes the eye read as a sphere rather than a disc when
the head turns.
refracted through the cornea onto the far iris wall — is faked as a scalar-parameter-driven
crescent multiplied into the iris albedo, its position derived from the dominant light vector.
It is declared OPTIONAL and its default is off: at gameplay camera distance it is invisible,
and an always-on caustic is exactly the kind of term that reads as a smudge in the general case.
It arms for the portrait/cinematic path only.
eye globe is nearly adult-sized while the palpebral aperture is small, so the visible iris fills a
much larger fraction of the visible eye than an adult's. That ratio is one of the strongest
age-read signals a face carries, and getting it wrong is a named failure mode on the record — the
age-8 tile read as *"the pick unaged with doll eyes"* and the age-11 tile as *"huge empty eyes"*
(docs/spine/DECISIONS_PENDING_JOSH.md L4404-4407, JOSH GRADES THE AGE LADDER). **The stage
therefore carries iris-to-aperture as a declared per-age value, not an emergent one**, keyed to
the four keystone ages 7/11/14/18 (L4435-4438) and interpolated between them the same way the
hair states are (docs/GROOM_STAGE_SPEC.md §4). The values are SET by the graded keystone plates
when they land; this spec fixes the mechanism and the age-7 anchor (globe radius 1.14 cm, IPD
5.44 cm) and refuses to invent the other three.
Subsurface Profile. The sclera is a thin white shell over vasculature; adefault-lit sclera is the tell that reads as "plastic eye" at any distance. The profile runs a
short scatter radius with a warm-red tint, because what is scattering is blood.
iris radius at 0.30 strength, plus a graded darkening toward the corners
(char_head_textures.py L415-419). Vessel density is an authored per-character value, not a
constant — an old or a wounded character carries more, a child carries very few.
(0.930, 0.912, 0.892) — warm andunder 1.0 by construction, so no lighting rig can blow it to a flat disc. This is the same
discipline the hair atlas learned by measuring its own clipping (GROOM_STAGE_SPEC §2.3).
T_HEAD_SSS is a thin-tissue transmission mask covering ear, lid, lip and nasal ala
(import_char_0001_headasm.py L62-65). The eye stage is where the lid channel of it starts
doing work: the head material moves from default-lit to Subsurface Profile and reads that mask as
its opacity/transmission input, so a lit lid glows at its thin edge the way a real one does. **This
is a one-line change to the head material and it closes a named honest-gap that has been landed and
unused since the head assembly imported.** Register row 15 is the wider SSS/ORM/normal port
(AAAAA_IMPROVEMENT_REGISTER_2026-08-06.md L88); the eye stage takes only the lid half of it and
says so.
margin UV island, with a high-gloss low-roughness material and a soft alpha falloff. Its job is
the wet contact line between lid and globe — the thing whose absence makes eyes look pasted on.
Budget: a single quad strip per lid, ~24 quads per eye.
canthus with the skin material and a caruncle-tinted albedo patch. Its absence is why a
bare-aperture eye reads as a cut hole at the inner corner.
An eye without contact shadow floats. Two mechanisms, and the spec picks one on measurement rather
than in advance:
globe carrying a baked gradient, multiplied into the sclera. Costs geometry; is view-stable.
aperture ring's own geometry. Costs no geometry; is fixed to the bind pose, so it does not follow
the globe as the eye rotates — which is the defect that decides it.
static aperture, so a baked-into-the-globe shadow would swing with the gaze and paint the shadow
onto the iris. The strongest objection is that it adds a fifth shell per eye to a mesh already
carrying seven material slots against a steam_deck_minimum material cap of 4 per garment piece
(register row 29, AAAAA_IMPROVEMENT_REGISTER_2026-08-06.md); the answer is that the AO shell
shares the cornea's material slot with a variant switch rather than minting a new one, and the
budget class it lands in is Lane B's to declare (§3.3).
---
| Map | Channels | Job | State today |
|---|---|---|---|
T_EYE_BC | RGB, sRGB | iris + sclera albedo, concentric by construction | LANDED (char_head_textures.py L406-440) |
T_EYE_IRIS_H | R, linear | iris height for the POM/parallax offset | NEW — authored from the same concentric grid |
T_EYE_ORM | R = AO, G = roughness, B = 0 | per-region roughness (sclera wetter than iris) | NEW |
T_EYE_N | RGB, TC_NORMALMAP | iris fibre relief; sclera flat | NEW |
T_HEAD_SSS | R = lid, G = ear, B = lip/ala | thin-tissue transmission | LANDED, UNUSED (import_char_0001_headasm.py L62-65) |
T_LASH_BCA | RGBA, sRGB | lash and brow strands with real alpha | LANDED |
Every new map is authored by the same generator that authored T_EYE_BC, in the same file, against
the same UV pole. No eye map is ever painted by hand or lifted from a plate — that is the route
whose baked plate lighting is the named exemplar defect the W-LOOK de-light pass exists to catch
(docs/HANDOFF_2026-08-05_ACCOUNT_SWITCH.md L1030-1031).
Eye maps are concentric and pole-centred, so texel density is wildly non-uniform in UV: the
pupil occupies the pole and the sclera occupies the outer annulus. The rule is therefore stated on
the *visible* quantity: **the iris annulus carries at least the same texels per centimetre as the
face skin at the same LOD**, measured on the rendered frame rather than declared in UV. At the
landed head's numbers that lands the eye maps one power of two below the head maps, and the exact
figure is a measured output of the first execution run, not a guess in this document.
The eye stage's triangle and material-slot cost is declared **against the spec-class taxonomy Lane B
is arming this wave**, by class name only: steam_deck_minimum / mid_range_pc / high_end_pc /
ultra (_source/01_Tier_1_Foundation/T1_Build_Pipeline_Contracts [ACTIVE v1.0].md §1.7, the
four-spec-class enum at L166 and the per-category budget shape at L185-188). **This spec states no
triangle number of its own.** Roster item 5 is explicit that budgets must be teeth rather than notes
(DECISIONS_PENDING_JOSH.md L4715-4717), and a second lane inventing a parallel number is how a
budget stops being one. The eye stage's obligation is to *declare its per-LOD counts into whatever
gate Lane B arms*, and §5 is written so those counts are derivable.
---
*"The FF7R appeal at runtime is mostly eyes"* (roster item 2). A perfectly shaded eye that stares
through the player is worth less than a plain one that looks at them. **This is the half of the
stage that is missing outright (§1.3), and it is the half that changes a frame the most.**
The shipped skeleton is SK_Mannequin at 89 bones with no eye joints (§1.3). Three routes exist and
the spec picks one:
eye_l / eye_r joints to the shared skeleton. Rejected on a hard constraint already enforced in the importer: update_skeleton_reference_pose stays False because
*"SK_Mannequin is shared with every animation asset in the project"*
(import_char_0001_headasm.py L25-26, L137). Editing the shared skeleton is not this stage's to
do.
leaves under head.** Appending leaf bones does not disturb the retarget chains or the root
motion contract, because retargeting maps limb chains and the eye joints belong to none of them
(the IK Rig / IK Retargeter model, dossier L530-533). Cost: the character carries its own
SKEL_ asset.
range: it slides a picture across a sphere instead of rotating one, so the specular highlight and
the parallax do not move with the gaze and the tell is immediate at portrait distance.
RECOMMENDATION: Route 2, with eye joints appended as leaves under head on a per-character
skeleton, and Route 3 retained as the crowd-tier implementation for the volume-NPC class where
no frame ever reaches portrait distance (roster item 6, THE VARIATION CAPABILITY,
DECISIONS_PENDING_JOSH.md L4718-4721). The strongest objection to Route 2 is that it forks
the skeleton the whole animation economy runs on, and a forked skeleton is how animation reuse dies.
The answer is that leaf-only appends under head preserve every retarget chain by construction and
are verifiable as such — a hierarchy diff against the 89-bone template that shows exactly two added
leaves and zero changed parents is the gate, and it is mechanical. **This routes to the cage verdict
because the winning cage's head partition determines where the eye joints sit; it is not settled
here.**
angle is derived from the focus distance and the character's own IPD, which is a measured
per-age value (5.44 cm at age 7, char_head_author.py L143) and therefore changes across the age
ladder for free.
±45° adduction, ±25° elevation, ±30° depression). A focus point closer than the clamp allows
results in the eyes converging to the clamp and the HEAD turning the remainder — which is what
people do.
target, the interaction prompt, and an idle-interest selector all write to one focus-point
channel; the rig only consumes it. This keeps the rig one asset rather than one per system.
the lid comes with it. Without this, a downward gaze shows sclera above the iris and reads as a
stare. Implemented as a driven corrective on the lid bones (or lid morph, per §4.5), sourced from
the eye joint's own pitch so it can never desynchronise.
but it declares the contract: the blink drives the lid, the lid drives lid-follow's zero, and
a blink during a gaze change must not fight the follow. Named as the interface, not built here.
degree, a few times a second, with a random walk bounded to the current target. This is the
single cheapest term in the entire stage and it is the difference between "alive" and "animatronic"
at conversation distance.
in-world points of interest with a dwell distribution. **This is the behaviour that satisfies the
standing creature/NPC behavioural-completeness law** (DECISIONS_PENDING_JOSH.md L3755+) at the
eye level.
Eye placement is not age-invariant. The globe reaches near-adult size early while the orbit and the
aperture keep growing, so IPD, set-back, and iris-to-aperture ratio all move across 7 → 18. The rig
therefore reads these as per-age values from the same keystone data the groom stage reads
(7/11/14/18 declared, 8-17 interpolated). The age-7 values are measured and landed (IPD 5.44 cm,
set-back 0.34 cm, globe radius 1.14 cm); the other three keystones' values are SET by the graded
keystone plates and the cage morphs, and this spec refuses to invent them.
AnimBP, containing the look-at solve and the lid-follow correctives. Reasons: it composes with
every existing animation without touching them, it is per-character rather than per-animation, it
survives retargeting, and it can be LOD-gated by the AnimBP's own LOD threshold (§5) with no extra
machinery.
sequencer shot can key the focus point directly. The spec's position is **both, with the AnimBP
layer as the runtime default and a Control Rig only where a cinematic needs hand-keyed gaze.**
MI_CHAR_0001_Eye and MI_CHAR_0001_Cornea at /Game/Meshes/Characters/ carry the material parameters the rig's material-side terms (limbus
Fresnel, parallax scalar, caustic switch) are exposed through; the geometry the rig rotates is the
eye_l/eye_r shells with cornea_l/cornea_r parented to them. The parameter contract those
instances must satisfy is machine-checked by GAME:Tools/char/eye_material_contract.py (this
wave), so the rig can never be wired against a material that lacks the parameter it drives.
---
The eye is the most expensive appeal-per-pixel surface on a character at portrait distance and the
least valuable one at combat distance. The ladder says so.
| LOD | Cornea | Iris | Sclera | Tearline/caruncle | AO shell | Look-at |
|---|---|---|---|---|---|---|
| 0 | clear coat + parallax + meniscus | POM + limbus Fresnel | Subsurface Profile | present | present | full: convergence, lid-follow, saccades |
| 1 | clear coat, parallax only | parallax offset, no POM | Subsurface Profile | present | present | convergence + lid-follow, no saccades |
| 2 | single specular lobe | flat map | default lit, warm tint | removed | removed | convergence only |
| 3 | merged into the head material | baked into head albedo | baked | removed | removed | off |
distance (dossier L876-877), and each threshold is validated by walking the camera through it and
looking for the pop — the same gate the LOD stage already owes.
Bones to Remove, which is what makes the"look-at off" row above free rather than merely disabled. The dossier's finding stands: skeleton
LODs are absent on every asset today (L908), so this is a new capability the eye stage is the
first consumer of.
tris, cause proven by a topology-free control at 51,282 — register row 13). Named here so the eye
stage is not blamed for it and does not try to fix it: docs/GROOM_STAGE_SPEC.md §5 owns it.
---
No eye claim counts unless it was made under the calibrated light. Roster item 4:
*"CALIBRATED LOOKDEV as the polish judge: the W-LOOK standard (declared HDRI set,
grey/chrome/Macbeth, de-light mandatory) becomes the light under which 'textured and polished' is
graded — polish claims under uncalibrated light are not claims"*
(DECISIONS_PENDING_JOSH.md L4712-4714). That standard is being built this same wave by the sibling
W-LOOK lane (docs/HANDOFF_2026-08-05_ACCOUNT_SWITCH.md L1025-1031) and **landed as
docs/LOOKDEV_STANDARD.md — THE CALIBRATED LOOKDEV STANDARD — while this spec was being
written; the eye stage consumes it and does not restate it.** If that path ever moves, find it by
its DOC_MAP row rather than by a path guessed here.
The eye-specific review ceremony on top of it:
a missing limbus Fresnel and a floating cornea both show), and an extreme close-up of one eye.
All four with the calibration geometry in frame, under the declared neutral HDRI.
clamp range. A static eye render is not a review of a look-at rig — the same reason a groom is
reviewed on a run cycle and not on a bust (dossier L490-492).
cornea tuned under one HDRI reads as glass under another; that is precisely the class of defect
the standard exists to catch (dossier L841-842).
sighted audit recorded first; a lane's gate table and its own eye-calls are inputs, never the pass
(DECISIONS_PENDING_JOSH.md L4416-4418).
DECISIONS_PENDING_JOSH.mdL4558-4562).
---
Stated so the unblock is a start command rather than a planning session.
1. Read the cage verdict, and take from it the head partition's eye-socket region, the aperture
ring's topology, and the winning cage's UV block for the lid margin.
2. Graft the authored aperture + refractive cornea onto the winning route — register row 14,
scored 2.5, sized at a tooling-day, with both the geometry and the material slots already proven
through an engine import (AAAAA_IMPROVEMENT_REGISTER_2026-08-06.md L87).
3. Author the three new maps (T_EYE_IRIS_H, T_EYE_ORM, T_EYE_N) in
char_head_textures.py, against the existing UV pole.
4. Build the material graphs against the contract validated by
GAME:Tools/char/eye_material_contract.py, and import them into the existing
MI_CHAR_0001_Eye / MI_CHAR_0001_Cornea slots.
5. Consume T_HEAD_SSS in the head material — the landed-and-unused mask, lid channel first.
6. Build the look-at rig — per-character skeleton with two appended leaf joints, hierarchy diff
against the 89-bone template as the gate, post-process AnimBP layer, focus-point channel.
7. Run the review ceremony under W-LOOK, all four frames plus the gaze sweep plus the
multi-environment pass, imaged.
8. Declare the per-LOD counts into Lane B's budget gate, and let it fail loudly if they are over.
9. Cascade — companions, then NPCs, then creatures where the anatomy schema carries eyes,
per the class cascade (DECISIONS_PENDING_JOSH.md L4471-4474).
unmake the first.
spec only declares the interface it needs from them.
geometry is the landed head's.