Adding the same part again now accumulates its instance count (tracked via _part/
_pc tags on the placed boxes, which survive the freeform_genome -> genome dict
round-trip) and RE-distributes the whole set evenly across the anchor face, instead
of piling new copies on the previous ones. So 'add wing' then 'add wing' gives four
wings (two per side, fanned front-to-back), not two stacked pairs.
Also fixes symmetric parts drifting far off to one side: they now straddle the body
(left half hugged to the left face, mirrored across the BODY center to the right)
instead of mirroring within the part and face-aligning the whole pair to one side.
Distribution spans the body's own extent so many instances hug the body.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(edit): replace small-model selector with keyword + parametric assembler
Edit path is now pure Python: an English keyword parser maps the instruction to
a catalog part plus count/scale/anchor/rotation/color, and the assembler snaps it
on deterministically (symmetric pairs first, overflow to rear; float scale rounded
to the grid; exact 90deg integer-grid rotation). Instant, no GPU. Gemma 12B stays
only for full generation, hatch fusion, and the freeform-edit safety valve.
Removes select_part, the MiniCPM selector constants/preflight/warmup bench, and
SELECT_SCHEMA/build_select_messages.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(parts/assembler): catalog parts + deterministic anchor placement
parts.py: hand-authored additive part catalog (horns/wings/tail/ears + props
house/hat/crown) in local coords with anchor/scale/symmetry metadata.
assembler.py: pure-function assemble_part — face-aligns a (scaled, mirrored)
part to the creature's bounding box at the chosen anchor, clamps via repair_boxes,
appends. Unknown part / empty boxes -> unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>