Skip to main content
skill Claude Code CX Codex Cursor GitHub Copilot

img2threejs — Claude Code skill: what it does, install

Builds a procedural Three.js model from an object or character image. Use it for code-based reconstruction, animation preparation, and staged model generation.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add img2threejs/img2threejs --skill img2threejs -a claude-code
Open on GitHub

What img2threejs does

img2threejs turns an object or character reference into a procedural Three.js model built in code. It checks whether the image is suitable, creates a quality contract and sculpt specification, then moves through blockout, structure, form, materials, lighting, interaction, and optimization. Each pass is checked against a screenshot of the reference.

The workflow uses forge/state.py, forge/next.py, and .img2threejs/state.json as its local state. The agent runs the next-step check before starting and before each correction loop, then records completed steps with evidence. The generic and character profiles are built in; other domain profiles come from installed plugins.

A single image cannot show hidden sides or guarantee exact geometry. That means the result should be labeled approximate, stylized, or low-poly when appropriate. The workflow needs an image or screenshot and a reconstruction profile.

What it helps with

  • build a procedural Three.js model from an image
  • split reconstruction into reviewable passes
  • prepare an object or character for animation
  • create a sculpt specification and model code

Example prompts for the agent

  • Build a procedural Three.js model from `reference.png` and run the quality checks for every pass.
  • Initialize a character reconstruction with the `character` profile and `object-sculpt-spec.json`.
  • Continue through `python3 forge/next.py --state .img2threejs/state.json` and show which step still needs evidence.

How to install img2threejs

1Skills CLI (Vercel)

npx skills add img2threejs/img2threejs --skill img2threejs -a claude-code

2Manually: put the files in place

~/.claude/skills/img2threejs/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/img2threejs/

Similar

hatch-pet official openai Creates and packages animated pets and spritesheets for Codex. Use it to turn a character concept, reference image, or brand cues into a pet. Claude Code CX Codex Cursor +1 3,300installs gcode earthtojake Slices STL, 3MF, and OBJ models into printer-ready G-code through OrcaSlicer. Use it when you need a print file without connecting to the printer. Claude Code CX Codex Cursor +1 9,500installs dxf earthtojake Generates and validates 2D DXF drawings from Python build123d scripts: outlines, gaskets, panels, flat patterns for cutting. Claude Code CX Codex Cursor +1 9,100installs threejs nexu-io Guides the agent in building browser 3D scenes, materials, interactive controls, and post-processing with Three.js. Claude Code CX Codex Cursor +1 3,400installs threejs-animation CloudAI-X Skill for keyframe, skeletal and morph-target animation in Three.js. Play glTF animations, control bones, blend and crossfade clips on WebGL and WebGPU. Claude Code CX Codex Cursor +1 20,100installs dfam-check earthtojake Measures mesh files against Design for Additive Manufacturing rules to evaluate printability before slicing or running CAD regeneration. Claude Code CX Codex Cursor +1 4,100installs orbit-card heygen-com Adds a 10-second 1920×1080 HyperFrames motion block where a single feature card orbits a dot sphere using exported Blender camera paths. Claude Code CX Codex Cursor +1 9,800installs sdf earthtojake This skill authors and validates SDFormat files for models and worlds, then helps prepare them for simulator handoff. Claude Code CX Codex Cursor +1 10,500installs

Questions about img2threejs

How do I install img2threejs in Claude Code?

Run npx skills add img2threejs/img2threejs --skill img2threejs -a claude-code, run npx skills add img2threejs/img2threejs --skill img2threejs -a claude-code again, then open ~/.claude/skills/img2threejs/SKILL.md.

What does img2threejs do?

It reconstructs an object or character from a reference image as a procedural Three.js model in code. The skill guides staged construction and checks each pass against screenshots.

Can one image produce exact geometry?

One image cannot show hidden sides or guarantee exact geometry. The result should be described as approximate, stylized, or low-poly when that matches the build.

Source text

SKILL.md · Apache-2.0
---
name: img2threejs
description: Turn an object or character reference image into a quality-gated, animation-ready procedural Three.js model built in code. Use for image-to-3D reconstruction, detail-accurate object rebuilds, stylized/likeness-maximized human characters, sculpt specs, and staged code generation.
license: Apache-2.0
version: 2.0.0
---

# img2threejs — Image to procedural Three.js

Rebuild the object visible in a reference image as a **code-only** procedural Three.js model,
gated by a staged sculpting pipeline and an AI-vision self-correction loop. This is
reconstruction-by-code, **not** photogrammetry, mesh extraction, or downloaded art packs. That
promise governs how the model is *built* — it says nothing about which file formats it can
subsequently be *exported* to; an explicitly-selected emission target (`--target <kind>`) is a
terminal, whole-artifact transform of the already-built model, verified to its own stated limit,
never a second way to build one.

Agent-agnostic: works under Hermes, Claude Code, Codex, or OpenCode. Wherever this doc says "agent vision" or "agent browser tool", use
whatever the host provides — native image reading, a browser MCP (playwright/chrome-devtools), the
project preview, or a user-supplied screenshot.

This file is the always-loaded router: it holds the order of operations and every hard rule as one
line. The full contract behind each rule lives in the `grimoire/` or `docs/` file that rule names —
read the named file at the moment you reach that stage, not before.

## Canonical shared checkout

Keep one checkout of this repository and let every host enter it through a symlink, so the hosts
execute the same code instead of drifting apart. `npx --yes img2threejs@latest install` does this
for the hosts it detects (`hermes`, `claude`, `codex`, `opencode`); it refuses (exit 2) to replace a
link it does not manage, so a hand-made link is never silently swapped for a release copy.
**Hermes** reads skills per profile: also link `~/.hermes/profiles/<profile>/skills/img2threejs`
(the installer writes only `~/.hermes/skills/`). Install, manual symlinks, and troubleshooting:
[`docs/INSTALL.md`](docs/INSTALL.md).

## When To Use

The user attaches/points to an object image and wants a procedural Three.js model, a
reconstruction/animation/destruction plan, a sculpt spec, or code. Also for material studies,
action-ready props, game objects, botanical/mechanical parts, and stylized reconstructions.

## Profile preflight (once per run, before `forge/next.py`)

Domain knowledge (CS2 skins, animated characters, emission targets) lives in plugins, not in this
checkout. Pick the profile from the subject, then confirm this environment can start it:

```bash
python3 forge/state.py init --help | grep -- --profile   # profiles available here
```

- `generic` / `character` are built in: no harness, no plugin, nothing else to check.
- A missing domain profile (e.g. `cs2`) is a setup gap: never downgrade to
  `generic` silently. Installing it edits the user's machine, so give them the commands in
  [`docs/INSTALL.md` §3](docs/INSTALL.md#3-add-a-plugin-only-if-you-need-one), get their go-ahead,
  re-check, and continue.
- Installed but not listed (wrong `$IMG2_HOME`), or a Hermes plugin link: [`docs/PLUGINS.md`](docs/PLUGINS.md).
- Then read what the profile's own steps name, at the moment you reach them: the plugin's
  `SKILL.md` and contracts govern that domain.

## Core Promise

Sculpt from a photo, in order — never one-shot a mesh:
1. **Run `python3 forge/next.py --state .img2threejs/state.json [<spec>]` first**, at every start,
   resume, and before every correction iteration. It reports the ordered checklist, exact next
   command, evidence status, and bounded correction-loop status; it never replaces the spec/pass
   gates. Obey a hard stop; never continue from memory.
2. **Validate** the image is a suitable 3D target (`grimoire/intake/validation_rubric.md`).
3. **Assess** object class + complexity, then write a `qualityContract` before any code.
4. **Spec** it: component hierarchy, materials, lighting, pivots, sockets, action anchors.
5. **Build pass-by-pass** from blockout → structure → form → material → lighting → interaction → optimization.
6. **Verify** each pass with a screenshot compared against the reference; fail a pass if an
   identity-defining feature is wrong even when the global score looks fine.

State explicitly when output is approximate/stylized/low-poly. A single image cannot reveal
hidden sides or guarantee exact geometry — say so instead of faking confidence.

## Mandatory Local State Gate

Conversation context is disposable; `.img2threejs/state.json` is the local checklist authority.
Initialize once per reconstruction, then gate every step through it:

```bash
python3 forge/state.py init --state .img2threejs/state.json --reference <img> --profile <generic|character|installed-domain> --spec object-sculpt-spec.json
python3 forge/next.py --state .img2threejs/state.json [object-sculpt-spec.json]
python3 forge/state.py mark <step-id> --state .img2threejs/state.json --evidence <path>
```

- `next.py` prints the current step, pass, incomplete mandatory steps, exact next command, and
  `loop/max`. Exit code 3 or `status=stopped` is a hard stop: report the reason and request input.
  Never bypass it by reconstructing progress from chat history.
- Every completed step needs evidence; mark a non-applicable step `skipped` only with `--reason` —
  silent omission is forbidden. Loop counts derive from `reviewHistory` actions
  (`refine-spec`/`refine-code`), not agent memory. Defaults: 3 corrections per pass, 6 total.
- A domain profile's steps, gates and reference material come from the **registry**: in-repo
  modules (`character`) and installed plugins (e.g. `cs2`) register identically, and
  `forge/state.py init` names what is available. A profile adds mandatory gates without changing
  the core order -- a domain plugin typically requires an authoritative classification, an intake
  manifest, and a machine-readable domain review before AI review; `character` requires the
  character contracts and landmark evidence; `animated-character` (requires the installed plugin-character) adds all of `character` plus the
  nine Stage R steps (`grimoire/readiness/animation_contract.md`). Pick it whenever the rig must
  MOVE — on `character` the Stage R gates are absent and the build completes without ever running
  them, which is how animation used to ship broken. Its order is load-bearing: repair the mesh,
  freeze it, bind additively, then verify parity. Every profile records suitability, projection
  applicability, and
  material-evidence applicability. The state file is a resumability index, not visual evidence:
  renders, specs, review history, and deterministic gates remain the authoritative artifacts.

## Required Inputs

- one image path / screenshot / URL / attached image (if missing or unreadable, ask)
- intended use: prop, game object, hero render, playable/destructible object, animation rig
  (default: real-time browser prop with interactive performance)
- when a domain plugin serves the item, whatever authoritative record its intake step requires, or
  an explicit request for the user/vision provider to supply one; heuristic detection alone is not
  enough to select a geometry adapter

## The Loop (scripts do enforcement; agent vision does judgment)

Run scripts from the skill root (`forge/...`). Pure Python 3.10+ stdlib, no pip installs.
Full flags: `grimoire/scripts.md`. Never let a script *score* visuals — that is the agent's job.

1. **Analyze the image first** (agent vision, before any script): work the layered observation
   protocol in `grimoire/intake/image_analysis.md` — identify/classify, decompose macro→meso→micro,
   map part relationships, name materials in PBR terms, list identity-defining features, and flag
   what the single view hides. Observation before inference; controlled 3D vocabulary; 3D
   object-space not 2D image-space. Then probe local images:
   `forge/stage1_intake/probe_image.py <image>` (metadata only, not a visual check).
1a. **Local Spec Search** — after image analysis, before writing or refining a spec, pull local
    domain evidence (anatomy/PBR/wear/geometry/runtime/physics) rather than inventing it:
    `python3 forge/stage2_spec/new_pre_spec_assessment.py "Name" --image <img> --out assessment.json`
    (auto-runs BM25 over the `core_3d` collection, or the collection a declared domain contributes
    -- the collection is NEVER guessed from the target name; writes a `localSpecSearch` bundle that
    `new_sculpt_spec.py --assessment` carries into the spec). Full query-expansion recipe
    (bilingual terms, focused `search_specs.py` retrieval, cache rules):
    `grimoire/intake/local_spec_search.md`. MUST read it before retrying an incomplete or
    domain-specific query.
1b. **Domain intake** — when a domain plugin serves the item, complete its intake steps before
    pre-spec authoring (admission, heuristic signal, classification, family/route resolution).
    MUST read the contract its step names, completely, before creating the manifest or
    running pre-spec assessment.
1c. **Optional fidelity evidence adapters** — only when they improve an observed weak point; the
    stdlib core remains authoritative. Thin/complex masks → local SAM2; character face/pose →
    MediaPipe; weak front/back cues → Depth Anything V2
    (`forge/stage1_intake/run_vision_adapter.py <segment|landmarks|depth> ...`; every adapter emits
    provenance; monocular depth is relative only). **MCP-only scene mutations never count as
    implementation** — write the proven change back to the spec or TypeScript, rebuild, recapture.
    Full adapter + MCP routing and authority boundaries:
    `docs/integrations/reference_fidelity_tooling.md`.
2. **Pre-Spec Assessment Gate** — classify + score complexity + write the quality contract:
   `forge/stage2_spec/new_pre_spec_assessment.py "Name" --image <img> --complexity <simple|moderate|complex|ultra-complex> --out assessment.json`. Rules: `grimoire/intake/quality_contract.md`.
   Set `objectClass.primaryDomain` (`object` | `character` | `hybrid`) and fill the seeded
   `detailInventory` (its `targetMinDetails` scales with complexity). A domain plugin may **raise**
   these floors through its augmentation -- the merge clamps, so a plugin can never lower one
   (a skin's finish/wear/hardware IS the item, so such a domain is held to the
   top fidelity bar. Author procedural GEOMETRY but route the FINISH through the projection path in
   step 2c — a procedural finish for a patterned skin (Doppler/Gamma/Marble/Fade) reads visibly
   wrong against the reference. A domain plugin ships its own finish rulebook and texture-acquisition
   guide; read what its checklist steps name.
2b. **Detail inventory** (do not skip for detailed subjects) — scan zones and enumerate every
   identity-defining small detail (gloss, bevel, fasteners, linework, contours, stains):
   `forge/stage1_intake/build_detail_inventory.py <image> --mode grid-3x3 --out-dir <dir> --out di.json`.
   Each detail MUST map to a `component.localFeatures` or `material.localOverrides` entry — never
   prose only. Taxonomy + 3D-term recipes: `grimoire/intake/detail_inventory.md`.
2c. **Projection-first fidelity** (characters AND reference-matched surfaces — painted skins,
   decals, painted patterns) — when the goal is matching a specific reference's surface, put the
   photo's own pixels on the mesh instead of approximating them procedurally. This is the single
   biggest fidelity lever; a procedural material for a patterned surface is the #1 reconstruction
   failure. Recipe (`grimoire/character/likeness_maximization.md` — its two levers generalize past
   characters): solve the camera (`stage1_intake/solve_camera_pose.py` → `referenceCamera`),
   **de-light** the reference (`stage1_intake/delight_albedo.py`, hard requirement — de-lighting is
   what makes projection safe), then project the de-lit crop and bake it into UVs
   (`stage3_build/bake_projected_texture.py --mesh-id <id>`). For a painted skin the projected de-lit
   crop IS the finish — no procedural Doppler material. For characters, first capture landmarks
   (`stage1_intake/extract_landmarks.py --out anatomy.json`), fill `preSpecAssessment.anatomy`,
   route `grimoire/character/reconstruction.md`. A single view cannot show hidden sides — report
   per-region confidence and request more views when it matters.
   Character sub-routes, in order — decide what parts exist before shaping any, and shape the head
   before the hair that sits on it:
   - **Parts** — `grimoire/character/structure_decomposition.md`
   - **Head** — `grimoire/character/head_construction.md` (what the likeness gate reads against)
   - **Hair** — `grimoire/character/stylized_hair_threejs.md` + parameter contract in
     `grimoire/character/threejs_hair_parameter_contract.json`. Lock topology only after the
     silhouette review passes: material tuning cannot repair wrong lock topology.
2d. **Reference-free humanoid** — a generic figure with no reference image has nothing to measure,
   so fill anatomy from public canon:
   `forge/stage2_spec/humanoid_proportions.py <spec> --style-heads 8 --in-place`. It writes
   `anatomy.source: "canon-table"` so canon is never mistaken for measurement, refuses to run when
   the spec names a reference image, and names anything the corpus does not supply rather than
   interpolating it.
3. Author the spec from the assessment:
   `forge/stage2_spec/new_sculpt_spec.py "Name" --image <img> --assessment assessment.json --augmentation spec-augmentation.json --domain <profile> --out object-sculpt-spec.json` (the checklist step carries the resolved flags).
   Replace generic starter `featureReviewTargets` with the object's real identity-defining
   systems (≤5 critical, ≤3 important per pass); for characters add `anatomy-proportion`,
   `face-landmark-placement`, `pose-silhouette`, `outfit-and-palette`. Use 3D-graphics terms only
   (`grimoire/glossary/3d_vocabulary.md`), never "nice/smooth/shiny". Classify every component's
   `topologyClass`/`topologyRationale` per `grimoire/intake/surface_topology.md` before picking a
   `primitive` — this is what prevents a continuous organic form from being picked as a box.
4. When material fidelity matters and a source image exists, analyze each material's **finish** then
   extract reference PBR evidence, both per crop (verify the crop is on the part you think it is):
   - `forge/stage1_intake/analyze_texture.py <crop> --spec spec.json --material-id <id> --in-place`
     classifies the finish, extracts the gradient palette, and writes doc-grounded
     MeshPhysicalMaterial scalars onto the material. Recipes + Three.js texture/PBR rules:
     `grimoire/build/threejs_texture_reference.md`. Rule of thumb: **solid albedo for flat paint,
     real reference crop for patterned finishes**.
   - `forge/stage1_intake/extract_pbr_evidence.py <crop> --out-dir <dir> --material-id <id> --target-threshold 0.7`.
     Confidence < 0.7 is a stop/refine-input signal, not a pass. It is inference, not inverse rendering.
   - For multiple named regions: `forge/stage1_intake/material_region_analysis.py --manifest regions.json --out-dir material-evidence --out material-analysis.json`,
     resolve each assignment from `docs/materials/material-reference.json`, wire it in with
     `forge/stage2_spec/apply_material_analysis.py`.
   - Emit the controlled material camera/crop contract (`forge/stage4_review/material_views.py`),
     compare visible-footprint crops (`material_comparator.py`), apply only bounded material-scoped
     corrections (`material_feedback.py`), and record the blocking result (`material_gate.py`).
5. Validate, then strict-validate before generating code:
   `forge/stage2_spec/validate_sculpt_spec.py object-sculpt-spec.json` then `--strict-quality`.
   Strict blocks shallow specs (a complex object with one root, no repetition systems, no
   local overrides, no micro groups is NOT implementation-ready even if JSON validates).
6. **Locked build passes** — only touch the currently unlocked pass:
   `forge/stage3_build/orchestrate_passes.py status object-sculpt-spec.json`
   `forge/stage3_build/generate_threejs_factory.py object-sculpt-spec.json --out src/createObjectModel.ts`
   The generator is fail-closed: `strict-quality` must pass before it writes any factory, and a
   future `--pass-id` fails until prior passes are reviewed `continue`. If blocked, preserve the
   `BLOCKED` artifact and refine the subject-specific spec; do not substitute a generic template.
   The local state adds `--force` only for a new pass or `refine-spec`; `refine-code` edits the
   current artifact without regenerating it. Before overwriting, carry valid hand refinement back
   into the spec; generated code must not be the only copy of reconstruction decisions.
6a. **Hitting a triangle budget.** `performanceBudget.targetTriangles` selects a tessellation tier
   for every primitive with segment counts (low ≤6k, standard ≤60k, else hero) and caps
   implicit-surface sampling grids. Where a tier is not precise enough, add
   `geometryDescriptor.decimate: {"targetRatio": 0.4}` to that component — a quadric collapse in
   the generated factory, run **before** skin binding so weights are computed on surviving
   vertices. It keeps `position` only (normals recomputed), so it is refused on an
   authored/unwrapped `uvStrategy`. Offline LOD tiers:
   `forge/stage3_build/decimate.py <mesh.json> --ratio <r> --json`.
7. Render the current pass in a browser/preview, capture a screenshot at a review viewpoint.
7a. **Off-axis and placement gates — a single review viewpoint is not evidence about the model.**
   Capture a turntable, not one frame, and run all three; each catches a defect class the older
   gates pass by construction (a hole through a skull, a hat at hip height and a floating charm all
   survived eight front-only review rounds):
   `forge/stage4_review/turntable_gate.py --capture 0=front.png --capture 90=right.png --capture 180=rear.png --capture 270=left.png --json`
   `node runtime/scripts/export_mesh_geometry.mjs --url <preview> --out meshes.json` then
   `forge/stage4_review/self_intersection.py meshes.json --json`
   `forge/stage4_review/attachment_anchor.py object-sculpt-spec.json --measured measured.json --json`
   All three exit `0` clean / `1` gate failure / `2` error. A failure blocks `continue` even when
   the global fidelity score passes. Read `sampledVertexCount` / `unmeasuredAttachments` /
   `missingAzimuths` before believing a clean verdict: each names what the gate did not look at.
8. **Run deterministic gates before AI vision.** MUST read
   `grimoire/review/gates_reference.md` and `grimoire/review/self_correction.md` completely. Run
   `forge/stage4_review/diagnose_render.py` and record the passing Tier 1 result with
   `--spec object-sculpt-spec.json --pass-id <pass> --in-place`; for non-planar forms also run
   `forge/stage4_review/diagnose_render_multi_angle.py` with the fixed view and at least two
   meaningful orbit views. Then run
   `forge/stage3_build/orchestrate_passes.py check object-sculpt-spec.json --pass-id <pass>`.
9. Package one side-by-side sheet, then inspect it with agent vision:
   `forge/stage4_review/make_comparison_sheet.py --reference <img> --render <shot> --out cmp.png --json`.
10. Record the review (overall + per-layer + per-feature scores + decision):
    `forge/stage4_review/append_review.py object-sculpt-spec.json --pass-id <pass> --fidelity <0-1> --action <continue|refine-spec|refine-code|request-input|stop> --summary "..." --render-screenshot <shot> --comparison-image cmp.png --ai-vision-score <0-1> --layer-scores-json '{...}' --feature-reviews-json <f.json> --in-place`.
    When a domain plugin contributes a review gate, produce its versioned report first with
    the command that plugin's review step names, then attach it with
    `--domain-review-json <report>.json --review-scene-json <the plugin's scene fixture>`. The
    checklist step carries the resolved paths.
    A failed family, painted-region, projection-coverage, critical-detail, or orbit gate blocks
    `continue` even when the global score passes. See the plugin's own review-gate documentation.
11. Sync pipeline state after manual review edits, record checklist evidence, then re-run the local
    state gate before another correction or pass:
    `forge/stage3_build/orchestrate_passes.py sync object-sculpt-spec.json --in-place`
    `python3 forge/next.py --state .img2threejs/state.json object-sculpt-spec.json`.
12. Before declaring completion, run
    `forge/stage4_review/check_part_coverage.py --spec object-sculpt-spec.json --manifest parts.json`
    and verify the action-ready hierarchy. Mark `part-coverage` and `action-ready` only with evidence.

## GLB-mediated v2 render-fidelity track (1.5 alpha)

When the user supplies a GLB as an intermediate reference, the browser-rendered GLB is the
structural and visual baseline for an independently authored procedural factory. The raw GLB is
never pixel evidence and its topology/materials are never copied into the factory. Before any
factory edit — full contract in `grimoire/build/python_threejs_render_bridge.md`, machine-readable
schema in `docs/specs/render-profile.v2.schema.json` (+ example; fail-closed validation):

1. `forge/stage1_intake/probe_glb.py` first. A merged one-node/one-mesh asset is `insufficient`
   for semantic labels; request a multipart GLB or a browser semantic-ID pass before claiming
   exact regions.
2. Author ONE shared `render-profile.v2` (`forge/stage4_review/validate_render_profile.py`) used by
   both the GLB and procedural routes. Region IDs are subject-specific, never inherited from the
   example profile; declare the required set in `extensions.requiredSemanticRegions` so omission is
   a hard validation error.
3. Capture six passes per admitted view (`beauty`, `alpha-silhouette`, `semantic-id`, `depth`,
   `normal`, `roughness-material-id`); score with `forge/stage4_review/compare_region_passes.py`.
   Missing semantic-ID data blocks per-region confidence rather than falling back to whole-image
   scores.
4. Use region-specific continuous geometry — never replace a face/head volume, cloth shell, or tail
   with floating primitives when the region's silhouette requires a continuous surface.
5. Run ONE correction group per loop, in order: `camera → silhouette → face → clothing → accessory
   → materials → lighting`; recapture the full pass set after each group and record the changed
   group, hashes and score. Never combine groups when diagnosing improvement.

## Gates (do not skip)

Before any visual review or `continue` decision, MUST read the full gate-by-gate contract in
`grimoire/review/gates_reference.md` (Divine Eye, VLM rescue, multi-angle, interior difference,
chirality, hair, domain review, bounded correction, Divine Eye fitting, screenshot feedback, assembly,
attachment, material, detail inventory, rig payload, character track). In short:

- Validate references first (`grimoire/intake/validation_rubric.md`, `check_reference_admission.py`).
- `divine_eye.py` is deterministic-first; the VLM (`vlm_gate.py`) is a gated last layer, never
  consulted on a hard-gate failure.
- A non-planar form must hold from ≥2 angles (`diagnose_render_multi_angle.py`).
- Measure INSIDE the silhouette every visual pass (`interior_difference.py`). Silhouette IoU reads
  ~11% of figure cells: a model with its face deleted scored the same 0.8803 as the finished face.
- Every `-l`/`-r` pair is a MIRROR, not a rotation — hard at spec time (`validate_chirality`). A pair
  wrong the same way on both sides still passes, and needs `medial_lateral_bias` vs a reference.
- Hair subjects: `scalp_exposure.py` is HARD and runs on geometry before any render; `hair_gate.py`
  is soft and subordinate to it. A coverage shortfall never authorises widening the masses.
- Flat colour regions with hard boundaries (blaze/bib/socks, livery stripe, painted marking) are an
  identity feature, so their boundaries are gated on geometry: `vertex_region_gate.py`. Never a
  texture — this pipeline emits code; the shape predicates live in `_shared/vertex_paint.py`.
- A curve claim ("curled into a hook, not a straight cone") needs `swept_arc_gate.py`: silhouette IoU
  passes a straight cone occupying roughly the right cells.
- Character builds validate the rig payload (`stage5_rig/validate_rig_payload.py`) before binding a
  `THREE.Skeleton`; it proves payload integrity only, never pose stress or likeness.
- A rig that must MOVE runs the animation gates too (`grimoire/readiness/animation_contract.md`;
  the checklist steps and gate come from the installed plugin-character -- `stage5_rig/` remains in
  this repo as the emitter's library, not the checklist authority). A clip that exists is not a
  clip that plays: only G1
  (`maxSampledBindingDelta <= 2^-23`) separates the two, and a gate whose input is missing reports
  `unevaluated`, never a pass. Bind at IDENTITY in attached mode and take the display offset from
  the mesh bounds alone; loop is decided by `poseReturn`, never by travel.
- A domain plugin's review gate also runs against its versioned scene fixture.
- Local state enforces 3 corrections per pass and 6 total by default; reaching either limit is a
  hard stop. `correction_loop.py` may stop earlier on repeated defects, oscillation, or plateau.
- `continue` requires a render + comparison sheet + AI-vision score ≥ threshold, every critical
  feature ≥ its own threshold (`grimoire/feedback/render_capture.md`).
- Every model ships explodable AND clickable — a structure gate, not pixels
  (`check_part_coverage.py`, `grimoire/build/geometry_patterns.md`).
- Action-ready, attachment, material/lighting, detail inventory, and character-track requirements:
  `grimoire/readiness/action_rigging.md`, `grimoire/readiness/joint_attachment.md`,
  `grimoire/feedback/shading_realism.md`, `grimoire/intake/quality_contract.md`,
  `grimoire/intake/validation_rubric.md`.

## Self-Correction

After every pass, decide exactly one: `continue | refine-spec | refine-code | request-input | stop`.
`refine-spec` fixes a wrong/missing/shallow spec (re-validate, don't patch code around it);
`refine-code` fixes geometry/material/lighting that doesn't match a sound spec. Before making the
decision, MUST read the root-cause guide + fidelity scale in `grimoire/review/self_correction.md`,
record the decision, and re-run the local state gate.

**Small features need a different instrument.** Divine Eye's SSIM/tonal/edge signals run on a 64×64
luma grid, so a detail a few pixels wide is absent before any comparison happens. When fidelity
depends on individual tears, spars, fangs or eyes, use the four-tier microscope:
`grimoire/review/divine_eye_microscope.md`. Two empirically established rules from it: measure
fidelity on a component's **visible footprint** (full frame minus a component-hidden frame), never
on an isolation render; and never colour-gate a **concave** feature, where a dark ratio captures
cavity shading rather than material.

## Transparency and Process Debugging

Report what changed each pass with evidence (exact values/coordinates), name what still doesn't
match, and never claim "done" when only "improved". A passing gate is not proof of 3D realism.
Full rule + examples: `grimoire/review/self_correction.md`.

## Left and right

A left/right pair is a **reflection**, never a rotation: negate the lateral axis and nothing else,
`(x, y, z) → (-x, y, z)`. With `forward: +Z`, Y up and a right-handed frame, the character's own
left is **+X**. The convention lives as code in `forge/_shared/chirality.py`
(`CHARACTER_LEFT_SIGN`), with two different gates for the two defects that shipped from getting it
wrong: `validate_chirality` catches a rotation-mistaken-for-reflection at spec time, and
`medial_lateral_bias` vs a reference catches a pair that is wrong the same way on both sides.
Reflecting also inverts triangle winding — flip it back on the mirrored side or `flatShading`
lights the limb as though lit from behind. Full write-up with the measured defects:
`grimoire/scripts.md` ("Left and right").

## Hair

Hair has its own subsystem because it has failure modes no other gate can see. Full contract,
measurements and non-goals: `docs/HAIR_PIPELINE.md`. The hard rules:

- Roots bind to the scalp as `(u, v)`, never absolute positions (hard validation error).
- `standProud` is enforced by the generator, not advisory.
- `scalp_exposure.py` is a HARD gate on geometry before any render; a coverage shortfall never on
  its own authorises widening the masses.
- Default representation tier is `shell`, not locks; strand impression comes from faceting and
  material (`hair.human.code-only`), since this skill emits no textures.
- `plane-card` is rejected for hair (needs an alpha texture this skill cannot emit).
- Hair is rigidly parented, never smooth-skinned (the geodesic field runs through the skull).

## Domain plugins

A domain plugin makes a run exact where this pipeline would otherwise infer. It contributes its own
checklist steps and gates, and publishes a `spec-augmentation.json` that this pipeline pulls at
`spec-authoring`. With no plugin serving the item, nothing here changes: author the skeleton and
infer the shape from the reference, as for any other object.

- The steps a plugin contributes appear in the checklist with their own ids and resolved paths. Read
  what each step names -- a plugin ships its own contract, and it governs its own domain.
- A plugin may **raise** this pipeline's quality floors and can never lower one; the merge clamps.
- A plugin that does not serve an item publishes no augmentation. That is not an error and not a
  blocked run: it is the generic path, and the recon...

© img2threejs · Apache-2.0 · img2threejs/img2threejs

See also

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor