29 KiB
WARDROBEGOD — state of play + how to improve it heaps
Recon 2026-07-24 across JING5 / ultra / m3ultra. Every fleet claim below was spot-verified live (see §B).
BUILD STATUS — 2026-07-24
| phase | state | commit | demo |
|---|---|---|---|
| 0 — unblock | ✅ done | b1381d2 |
security hole closed, PNG garments visible, farm3D ✓ |
| 1 — dress + move | ✅ done | b1381d2 |
tradie walks in a red-tinted felt hat, restored from disk after reload |
| 2 — reskin | ✅ done | cfca670 |
phrtt2 wearing a baked corduroy jacket; head-ghosting bug found + fixed |
| 3 — 2D paper doll | ✅ done | 294af7c |
392 layers, per-slot swap, randomise, export dry-run to djsim |
| 4 — donor harvest | ✅ done | 8119e2d |
harvested garment on a different body, bending through a Running clip |
| 5 — dressing room | ✅ done | 305fbf9 |
thumbnail grid, manifest, rig→LOD→dress bench |
| SD salvage + MODELBEAST | ✅ done | 5c80e65 |
juggernautXL beats flux for garments; LoRA stacking + ControlNet + parent_job fix |
| NPCFACTORY folded in | ✅ done | 037f6ef |
vendored three.js (no CDN), 17 NPCs, unitfix |
| nsfw tagging + gate | ✅ done | d6c0ba4 |
"only dressed ships" is now enforced, not a README line |
| export hub + unified wardrobe | ✅ done | 9012e3e |
401-item grid, 3GOD publish, honest 409s |
Export reality (verified against each consumer's real loader, 2026-07-24)
| target | file drop works? | what's actually needed |
|---|---|---|
| djsim doll | ✅ yes | self-healing loader — drop + restart |
| 3GOD depot | ✅ yes | POST http://100.94.195.115:8788/api/upload direct over tailnet — the digalot.fyi front 403s because auth trusts the socket peer |
| djsim ped | ❌ no | rigs.js PED_NAMES (:20-27) hardcoded array |
| procity ped | ❌ no | ped name array; props via pipeline/publish.py on m3ultra (only box with _normalized/) |
| thriftgod prop | ❌ no | literal HERO_FLOOR/HERO_COUNTER strings (index.html:1322-1325) |
| not-tonight | ❌ no | no garment/doll/character art path exists at all |
thriftgod has no paper-doll, atlas or reskin consumer — zero grep hits across web/ and tools/.
Don't generate art for it expecting somewhere to put it.
What John can do right now: python3 server.py → open :8150.
· wardrobe tab — load a rigged NPC, attach + tint props, save/reload the dress-up, play/scrub clips,
RESKIN a nude body with any garment and toggle costumes instantly.
· doll 2D tab — dress a paper doll from 392 real garments, randomise, export to 90sDJsim.
Corrections to the recon below, found while building:
- The live farm exposes 26 operators, not 36 (the 36 was the code registry; not all are hot).
/api/operatorsreturns display names, somflux_image_editappears as "Edit Image (local, Qwen)". - Two live operators the plan under-sold: SF3D (fast image→GLB draft) and MoMask (text→motion BVH).
numpyis not installable on JING5 (PEP 668) — the doll tier parses djsim's anchors out of source withastinstead of importing its numpy-dependent compositor.- Reskin's inherited baker ghosted a second face onto the side of the head; fixed with a neck-height cutoff.
riggermore/rigroomdo not exist under those names anywhere on the fleet — the rigging bench is MIRPAMO.
TL;DR
The bench works, the wardrobe is empty, and one bug is dangerous. The three-column three.js
dress-up shell runs, the local Blender pipeline (convert / scale / decimate-keep-weights / fit /
assemble) works, and the Cloudflare flux generator works — but library/ holds 2 bodies + 1 garment
PNG (which is invisible to its own UI), out/ and jobs/ are empty, the trellis tier is dead (no
MB_TOKEN), and /api/blender is an unauthenticated arbitrary-file → Blender primitive.
Meanwhile the fleet already contains everything wardrobegod is trying to become, several times over:
- NPCFACTORY (ultra) — a further-along dress-up bench: 17 finished rigged, walk-animated NPC GLBs
- a completed reskin engine (paint clothes onto a body's own UV atlas).
- 90sDJsim (ultra) — a shipped $0 2D wardrobe: 441 authored transparent-PNG garment sprites + a self-healing doll compositor.
- MODELBEAST (m3ultra :8777, UP, 26 live operators) — free local virtual try-on
(
mflux_image_edit= "Edit Image (local, Qwen)": "put the shirt from image 2 on the person in image 1"), flux, RMBG-2.0, TRELLIS.2, Hunyuan3D, SF3D, layered-RGBA cutouts, MoMask text→motion. - character_kit_modular (ultra) — a socket-swap costume engine on rigged mixamorig bases.
- MIRPAMO (everywhere) — a local, offline Mixamo (auto-rig → 22-bone mixamorig + retarget).
- ~2,394 + 2,548 + ~163 animation clips already on disk.
The decision: stop treating wardrobegod as a Blender-op bench and make it the one thing the fleet lacks — the canonical garment/outfit LIBRARY + a dressing-room authoring UI + a multi-consumer EXPORT HUB. The dressing engines exist five times over; the connective tissue exists zero times. Graft the fastest proven engines onto that spine (reskin, try-on, the 2D doll, donor-harvest).
A. Where it's at — honest state of play
Works today
server.py(stdlib ThreadingHTTPServer :8150):/api/lib,/glb?p=(Blender convert-cache),/file?p=,/api/upload,/api/blender(op dispatch),/api/gen(CF flux),/api/rmbg,/api/to3d,/api/hangable. No build step.blender_ops.py(166 lines):convert / scale / decimate-keep-weights / fit / assemble. The fit op (data_transferVGROUP_WEIGHTS POLYINTERP_NEAREST+ armature parent,blender_ops.py:128-132) is the proven wardrobe mechanic — wrap it, don't rewrite it.web/index.html(316 lines): OrbitControls + GLTFLoader stage, 3 tabs, body/garment lists, mixer that auto-playsanimations[0].- CF flux
/api/gen→@cf/black-forest-labs/flux-1-schnellworks with only the CF creds in.env. - Blender 5.1.2 + PIL present on JING5 — the whole local pipeline runs with no farm dependency.
Content truth (the real problem)
library/bodies/ phrtt2.glb (1.67M), droidte2-18k.glb (7.97M)
library/gen/ brown-corduroy-jacket.png, -cut.png
library/garments/ brown-corduroy-jacket-cut.png ← INVISIBLE to the UI (bug #2)
out/ jobs/ EMPTY
.env CLOUDFLARE_* only — NO MB_TOKEN
Zero garments have ever been fitted to any body.
The bodies are not the consistent A-pose set the brief assumed
The 6 ~/Documents/anatomy FBX (verified by headless render): 2 A-pose (dudescholng,
2_views_3d), 2 T-pose (phrtt2, droidte2), 2 arms-down/contrapposto. 5 of 6 are unrigged;
only droidte2 has a skeleton (41-bone reduced mixamo) and it's already clothed (shorts+boots),
482k-tri raw. Each is an independent TRELLIS reconstruction — no shared topology, own UV atlas.
→ One fitted garment can't be reused across bodies; each needs its own per-body fit, and only
shrinkwrap/proximity works (no vertex correspondence).
The real bugs (file:line)
- SECURITY —
/api/blenderis unguarded.allowed()guards/file /glb /api/rmbg /api/to3d /api/hangablebut not/api/blender—fx()passesa['path']/a['body']/a['garment']/ a['garments']straight intoglb_of()→run_blender()(server.py:238-265). Under the documentedWG_HOST=0.0.0.0(server.py:7) that's an unauthenticated arbitrary-file → Blender import + library-write for any tailnet peer.allowed()itself is sound (server.py:58-61) — it's just not called here. Fix before any 0.0.0.0 exposure. scan()hides PNG garments.server.py:67usesMODEL_EXTforgarments, but/api/hangablewrites a .png there (server.py:374). Every hanging-texture / doll cutout is silently filtered out — the whole 2D route dead-ends in an unshowable directory. One-line fix, prerequisite for 2D.glb_ofcache-key collision.server.py:96keys onslug(basename(path))only, single-source mtime check (:97). Same-basename files in different dirs collide → serve wrong geometry.- Silent corruption in
mb_download.server.py:156-157writesjson.dumps(data)when the farm response isn't bytes; a JSON error body gets written into the target.png/.glband the job is marked done. Affects/api/gen /api/rmbg /api/to3d. JOBSleaks unbounded (server.py:50), andglb_ofspawns aconvertjob on every cache miss even inside synchronous GET/glb(server.py:98), orphaning records.- Local rmbg keyer is crude — iterative border flood-fill through near-white (
>232), binary alpha,server.py:329-344. On a non-white bg it never seeds → silent no-op opaque copy. - Rigid-attach is ephemeral —
web/index.html:215-225clones into three.js and POSTs nothing; the toast admits "preview only." Attach transforms live only in browser memory. fit: picks body asmax(meshes, key=len(vertex_groups))→ multi-part body donates weights from one mesh only (blender_ops.py:115-117); nomatrix_parent_inverse(:131).assembletrusts an unenforced bone-name contract (blender_ops.py:151-161).- No auth / CORS / rate-limit / delete / thumbnails / search; gen filenames overwrite silently.
Not a bug (verified, don't touch): the suspected
decimatemodifier_move_upinfinite-loop / 30-min hang does not reproduce on Blender 5.1.2 — the operator returns{'FINISHED'}, loop exits in one iteration. Code smell only.
Convention drift
- three.js from unpkg CDN (
index.html:133-136) — house style is vendored r175 (breaks offline / un-shippable into a game build). - README frames the generator as MODELBEAST-only; commit
6f32c08quietly made CF the primary flux backend — a cloud path outside the LOCAL-FIRST doctrine. - "Only dressed outfits ship into games" is one unenforced README line (
README.md:45) — no code gate.
B. What the fleet already gives us (verified live 2026-07-24)
MODELBEAST — http://100.89.131.57:8777 (m3ultra), UP, 26 live operators ✓
Bearer MB_TOKEN (on disk at ~/Documents/backnforth/.env, len 44 — never paste). Contract:
POST /api/assets (multipart) → POST /api/jobs {operator, asset_ids|asset_id, params} → poll
GET /api/jobs/{id} → outputs = assets with parent_job==id → GET /api/assets/{id}/file.
main.py:290-293 already accepts an asset_ids array → multi-image try-on is submittable today.
Wardrobe-critical live operators (display name → slug):
| Display name | Slug | Use |
|---|---|---|
| Edit Image (local, Qwen) | mflux_image_edit |
virtual try-on — 1-3 imgs, "put the shirt from image 2 on the person in image 1". The key unused capability. |
| Qwen-Image-Layered (local) | qwen_layered_local |
image → N editable RGBA layers = the "paper cut-out layers" rep, generated |
| FLUX (local, MLX) | flux_local |
flux2-klein-4b, ~40s, ungated |
| Remove Background (local) | bg_remove_local |
RMBG-2.0 matting (better than the local keyer) |
| SD1.5 + anatomy LoRAs / SD+LoRA (ComfyUI) | sd_local |
OpenPose T-pose ControlNet + IP-Adapter identity lock |
| TRELLIS.2 (SOTA) / TRELLIS.2 MLX | trellis* |
image → GLB (~2-5 min) — single-image only |
| Hunyuan3D 2.1 (local MLX) | hunyuan3d_mlx |
image → GLB, no HF login |
| SF3D (fast draft) | sf3d |
image → textured GLB, seconds — good for quick garment blockouts |
| Motion (MoMask) | text → BVH motion (+mp4) — text-to-animation | |
| Upscale (SeedVR2), Brush 3DGS Train | — | polish / gaussian-splat |
Copyable stdlib CLI: ~/Documents/MODELBEAST/mb → ./mb run flux_local -p prompt=... --wait --download out/.
Launch pattern: export MB_TOKEN=$(grep '^MB_TOKEN=' ~/Documents/backnforth/.env | cut -d= -f2); python3 server.py.
NPCFACTORY (ultra ~/Documents/NPCFACTORY, 410M) — the further-along sibling ✓17 banks confirmed
- Same stdlib + vendored three.js house style; already has orbit stage + clip dropdown + speed/height-normalise, click-a-part bone-attach dress-up, recipe JSON, in-UI Blender bank-builder.
- 17 finished rigged, walk-animated NPC GLBs in
library/banks/(tradie/cop/goth/nanna/postie/ busdriver/bizdad… 7-25MB each) — instant dressed+animated characters to load. - The reskin trio (E6 COMPLETE, all 3 confirmed on disk):
tools/render_plates.py(bind-pose front/back EEVEE ortho plates, 1024, transparent),tools/align_plate.py,tools/bake_skin.py(Cycles DIFFUSE projection bake onto the rig's own UVs, front/back viaNormal.Y<0).archetype_batch.py= batch factory template. - Constraint: reskin only works on single-mesh / single-UVMap / single-material bodies —
John's nude TRELLIS-2 figures are exactly this class. (
droidte2is disqualified: multi-part, clothed.)
90sDJsim (ultra ~/Documents/90sDJsim) — the 2D wardrobe, already shipped ✓441 sprites confirmed
web/world/media/doll/= 441 transparent-PNG garment layers,<slot>_i_<slug>.png. Runtime compositordoll.js(704×1408, ORDER base→bottom→shoes→top→hat, bag last).doll_layout.jsonnudges.- Self-healing loader
server.py:167-178:_art_slug = re.sub(r'[^a-z0-9]+','_',name.lower()).strip('_'). Drop a PNG + restart = that garment wears its own art, zero code change. - $0 generator:
tools/{gen_wardrobe,doll_composite,doll_stage,build_wardrobe_manifest}.py— prompt →flux_localon solid green →bg_remove_local→ stage onto 704×1408 via measuredSLOT_DEFanchors. Prompt template + 321 authored items + 432 reference JPGs exist. - Caveat: the full doll pipeline is ONLY on ultra; the JING5 checkout is stripped → export-to-djsim must rsync to ultra.
character_kit + character_kit_modular (ultra canonical ~/Documents/character_kit/)
- Rigged mixamorig bases (65-bone) + already-rigged wearable props (
rigged/{w_beanie,w_felthat}.glb,props/modular/{beanie,buckethat,felthat,boombox,camera}.glb). scripts/merge_anims.py— base rig + N anim-only FBX → one multi-clip GLB (NLA tracks).modular/scripts/:cut_parts.py(cut a mixamorig char into swappable socket parts),assemble.py(attach_part,fit_partcross-rig auto-scale,attach_attachmentbbox-fit+bone-parent),texture_variants.py(numpy hue-mask recolour).parts_library/library.json= the garment-registry schema to copy.
Animation banks
- ultra
~/Documents/MOTIONLIB/green/mixamo_full= 2,394 anim-only mixamorig FBX (1.3G, shippable w/ attribution) +cmu_bvh2,548 BVH + 100style/accad/kaykit/quaternius. - ~163 local mixamorig clips already on JING5+ultra — enough for a showcase set now, no downloads.
Garment donors + bodies
- ultra
~/Documents/3D=models/characters/people-normal/= ~40 clothed, mixamorig-rigged FBX (man_suit_01,man_dj_streetwear_01,woman_raver_01,man_worker_hivis_01…). Excludeactorcore-unreal/(RED, native-only). - Clean multi-LOD nude base: m3ultra
~/Documents/trellis2-bench/anatomy_{2000,8000,30000,50000,800k}.glb. - ultra
3d-from-m5/AUDIT.md: of 4278 files, 43 are rigged + game-budget (≤10k tris). - fluxgod (JING5) —
mb.py/a1111.py/openrouter.pymulti-lane client with restart-safe queue + autocrop. Copy wholesale rather than re-implement CF-only.
Two honest fleet limits (do NOT build against these)
- TRELLIS.2 is single-image — do NOT build a "4-view sheet → TRELLIS" bridge; multi-view is only for reskin plates / QC.
- No live vision model (m4pro Ollama = text
qwen2.5:7b+nomic-embedonly) → auto-tagging garments is NOT an existing capability (needs aqwen2.5-vlpull or paid OpenRouter). MODELBEAST has a local text LLM (Qwen3-30B) but not a captioner. - No garment/clothing LoRA exists — styled-garment fidelity is prompt-only until
brush_trainmakes one.
C. The plan — phased, each ending in a demo
Guiding principle: the data model (§D) is cheap stdlib JSON — it goes in Phase 1 and every phase populates it. Fast/proven engines first (reskin, try-on, 2D doll), quality-core cloth mid (donor harvest), UI polish last.
Phase 0 — Unblock (½ day)
- Bug #2 (
server.py:67): add.pngtogarmentsscan exts → cutouts/doll layers become visible. - Bug #1 (
server.py:238-265): callallowed()on the blender-op paths before any 0.0.0.0 exposure. - Export
MB_TOKENat launch (unlocks try-on, RMBG-2.0, trellis) — LaunchAgent or launcher script. - Bug #4 (
server.py:156-157): check content-type/magic bytes before writing a farm response; mark the joberroron a JSON body.
Phase 1 — "It dresses and it moves" (1 day) → dressed, animated character on screen
- Track 1 — the stage moves: add a clip dropdown + play/pause/scrub (the mixer exists at
index.html:191-194; there's no selector). Build clips viacharacter_kit/scripts/merge_anims.py(base rig + ~10 local clips → one multi-clip GLB, NLA tracks) → rsync to JING5. - Track 2 — it dresses: load a rigged mixamorig base; rsync one NPCFACTORY bank NPC (already
dressed+animated) as the guaranteed floor. Attach a rigid hat (
character_kit/rigged/w_felthat.glb) via the existing bone-attach, but make it persist (POST anoutfit.attachrecord, not just an in-browser clone). Add runtimematerial.colorcolourway tinting (free). - Demo: a rigged character walks on screen wearing an attached hat, clip dropdown switches animations, a colour swatch retints it.
- Stretch (starts the real nude-figure track): kick off the first reskin bake on
phrtt2(T-pose, single-mesh/UV — ideal reskin class):mirpamo rig phrtt2.glb→render_plates→ repaint →bake_skin.
Phase 2 — Reskin engine: paint clothes onto nude bodies (2-3 days)
Copy the NPCFACTORY trio (137 lines). New POST /api/reskin, mirroring run_blender+job_thread:
1. blender -b -P render_plates.py -- body_rigged.glb plates/ → front.png, back.png
2. MB job mflux_image_edit asset_ids=[front.png, garment_cut.png]
"put the garment from image 2 onto the person in image 1, keep exact pose+silhouette, plain bg"
3. blender -b -P align_plate.py -- edited_front.png front.png aligned_front.png
4. blender -b -P bake_skin.py -- body_rigged.glb aligned_front.png aligned_back.png costume.png
5. three.js: material.map = TextureLoader().load(costume.png); needsUpdate=true
A costume dropdown swaps material.map at runtime — instant, free, reversible toggling between
pre-baked outfits.
- Demo: pick a nude TRELLIS body → pick/generate a garment → walking clothed character; flip a dropdown to change costumes instantly.
- Ceiling (say it out loud): the nude silhouette never changes — sells tight/printed garments & uniforms & mid-distance figures, but a jacket reads as a jacket-print bodysuit. Hero silhouette garments need Phase 4.
Phase 3 — The 2D paper-doll product + first export contract (2-3 days)
Adopt 90sDJsim/tools/{gen_wardrobe,doll_composite,doll_stage,build_wardrobe_manifest}.py wholesale.
Emit media/doll/<slot>_i_<slug>.png honoring _art_slug exactly. Wire qwen_layered_local /
bg_remove_local for matting-grade cutouts (upgrading the crude local keyer). Import the 441 sprites
as a starter pack. POST /api/export {target:"djsim", outfit} writing over rsync to ultra.
- Demo: generate a garment → it appears as a doll layer → drops into 90sDJsim with zero consumer
code change (self-healing
DOLL_ART). Highest-ROI, lowest-risk value on the board.
Phase 4 — Quality-core: real 3D cloth via donor harvest + hide-masks (8-9 days)
New blender_ops.py op harvest: import a clothed mixamorig donor → bpy.ops.mesh.separate(type= 'MATERIAL') (Blender copies all vertex groups onto the separated garment automatically — the whole
trick) → purge empty groups → attach_part → <donor>__<material>-harvest.glb. /api/wear runs
assemble.py fit_part(anchor=mixamorig:Hips). License-gate: exclude actorcore-unreal/.
Batch the ~40 donors → ~80-150 pre-weighted staple garments at $0.
- Graft from proxy-standard: author
hide_torso/hide_upperarm/hide_thigh/hide_shin/hide_foot/ hide_scalpvertex groups once, apply an invertedMASKmodifier per garment'shideslist — replacing the 3mm DISPLACE "puff" hack (blender_ops.py:122-124) — so nude skin stops poking through. - Demo: a real jacket (collar/cuff volume) on a mixamorig body bending correctly through a walk clip, no skin poke-through. The only route that looks like a person in actual clothes.
- Ceiling: garments captive to donor proportions (clip/gap on dissimilar bodies), wardrobe donor-bounded, 65-bone donor vs 22-bone MIRPAMO leaves cuff verts under-driven.
Phase 5 — Dressing Room UI + full export hub (1 week)
Rebuild web/index.html as a real dressing room: vendor three.js r175 (drop the CDN), thumbnail
garment grid with slot tabs + tag search + license filter, live click-to-swap composing by reference
(never re-bake per click), a 2D-doll preview toggle (reuse doll.js verbatim), save/load/randomize
outfits, and an export dropdown (djsim | thriftgod | procity | not-tonight | glb). Add a render_thumb
Blender op (EEVEE 256×256 A-pose). Gate every export on license != "red" — the only actual enforcement
of "only dressed/green ships."
D. The data model (actual JSON — stdlib files, no DB)
library/index.json written on every mutation, read once by the UI. Replaces scan() (which returns
only {name,path,kb,home} and drops PNGs).
Slots & layers
slot ∈ head | torso | legs | feet | hand_l | hand_r | accessory | bag
layer (draw/stack int; drives 3D normal-push AND 2D doll ORDER):
skin=0 underwear=10 legs=20 feet=25 torso=30 outer=40 head=50 accessory=60 bag=70
Garment record (library/garments/<slug>.json)
{
"slug": "coogi-multi-knit", "title": "Coogi multicolour knit",
"slot": "torso", "layer": 30, "skeleton": "mixamorig",
"hides": ["hide_torso","hide_upperarm"],
"tags": ["knit","90s","multicolour","oversized"], "brand": "coogi-parody",
"license": "green",
"colorway": { "base": "#8a2b6d", "tintable": true },
"reps": {
"flat_png": "garments/coogi-multi-knit.png",
"doll_layer": "garments/coogi-multi-knit.doll.png",
"sprite": "garments/coogi-multi-knit.sprite.png",
"glb": "garments/coogi-multi-knit-harvest.glb",
"skin_tex": "garments/coogi-multi-knit.reskin.png",
"thumb": "garments/coogi-multi-knit.thumb.png"
},
"source": { "prompt": "...", "backend": "flux_local", "seed": 42 },
"provenance": { "created": "2026-07-24T...", "donor": null }
}
Outfit record (library/outfits/<name>.json)
{
"name": "raver-fit-01", "body": "bodies/phrtt2_rigged.glb",
"slots": { "torso":"coogi-multi-knit","legs":"baggy-jnco","feet":"doc-8eye","head":"bucket-hat" },
"layerOrder":[ "legs","feet","torso","head","bag" ],
"anim": "wan_walk",
"attach": { "bucket-hat": { "bone":"mixamorig:Head","scale":1.0,"y":0.0,"z":0.0 } }
}
The attach block bakes the currently-ephemeral rigid-attach state (index.html:215-225) so
hats/props survive reload + export.
Export contracts (verified against each consumer's real loader)
| Target | Contract | Slot map |
|---|---|---|
| 90sDJsim / thriftgod doll | write reps.doll_layer → 90sDJsim/web/world/media/doll/<slot>_i_<slug>.png; <slug> = re.sub(r'[^a-z0-9]+','_',name.lower()).strip('_'). Self-healing DOLL_ART = drop file + restart. Rsync to ultra. |
torso→top, legs→bottom, feet→shoes, head→hat, bag→bag |
| thriftgod / procity racks | emit reps.flat_png as fittings.js garment({image}) plane texture / PROCITY StockSlot{kind:'garment'} |
slot → rack kind:'garment' |
| not-tonight | emit reps.sprite (32×48, quantized to the 14-entry outfits.ts PALETTE) |
head→hair/accessory, torso→top, outer→outer, legs→legs, feet→shoes |
| 3D GLB (hero/games) | assemble(body,{torso:garment}) or fit → out/<outfit>.glb → 3GOD depot |
native mixamorig |
Schema is a superset of character_kit_modular/parts_library/library.json → parts flow between
benches (anti-silo, not a new competing format).
E. The 2D paper-doll track (first-class, not a fallback)
John explicitly has "2D paper cut-out" garments, they're the cheapest content, and GODVERSE_MAP.md
already recommends "clothes cutouts on a hanger card OVER 3D garment mesh." Mostly adoption, not building:
- Generator exists & is $0:
90sDJsim/tools/gen_wardrobe.py— prompt →flux_localon solid green →bg_remove_local→doll_stage.pyonto 704×1408 via measuredSLOT_DEFanchors. - Battle-tested prompt (
build_wardrobe_manifest.py): "paper doll clothing item for a dress-up game,<desc>, 1990 australia,<view>, floating centered on a plain pure white background, painterly stylized 3d game illustration, full item visible, no body, no person, no mannequin, no hanger, no text, no logos." Lift verbatim, incl. per-slot VIEW phrasing. - Content on hand: 441 sprites + 321 items + 432 reference JPGs.
- Upgrade:
qwen_layered_local→ RGBA layers = the literal "layered paper cut-out" rep, cleaner than the keyer. - Prerequisite: fix bug #2 or none of this is ever visible.
- Honest scope: the djsim doll dresses one fixed 704×1408 front-view silhouette — it cannot dress arbitrary 3D bodies. The dressing room is two products sharing one library: a 2D doll authoring view (djsim/not-tonight) and a 3D stage (reskin/harvest/socket). Toggle honestly; never pretend a flat sprite is dressing the 3D body.
F. Open questions (only John can answer)
- wardrobegod vs NPCFACTORY — keep wardrobegod as the JING5 library/authoring/export hub and borrow NPCFACTORY's stage+banks (plan assumes this), or physically merge the two?
- Canonical nude base + consent — rig/reskin target: mint from
trellis2-bench/anatomy_8000.glb, usephrtt2(ideal reskin class), or the 43 rigged game-budget set? Hardlicense!="red"export gate? MB_TOKENpersistence — OK to add a LaunchAgent / boot-time read frombacknforth/.env?- Where the canonical library physically lives — JING5 (author), ultra (doll pipeline runs), or 3GOD depot?
- First export target — 90sDJsim (biggest existing 2D consumer, zero-code drop-in) or 3D-in-thriftgod?
- Hero garments — accept painted-on reskin for crowd/mid, donor-harvest for staples; invest in socket-torso swap for true hero couture (bigger build, not in this plan)?
- Garment LoRA — curate a set +
brush_trainfor on-brand 90s Aussie op-shop garments, or prompt-only for now?
G. Risks & what will look bad (no sugar-coating)
- Reskin is a painted-on illusion — zero added geometry; unchanged nude silhouette + a jacket print is a dead giveaway at close range; can't layer, can't drape; re-bake to change (runtime swap only toggles already-baked costumes). Single-mesh/UV bodies only.
- Virtual try-on is a 2D still —
mflux_image_editgives a believable clothed image in ~2 min (great for browsing) but doesn't animate and drifts identity/pose. Preview surface, not hero render. - Donor cloth is proportion-captive — weights transfer perfectly, but a suit molded to
man_suit_01floats/clips on a slim TRELLIS figure (no cloth sim). Wardrobe is donor-bounded. 65-bone vs 22-bone leaves cuffs under-driven. Unknown fraction of donors are single-atlas (skin+cloth fused) → won't separate cleanly — real number unknown until triage runs. - 3D fit on unstructured topology is per-body & clips — no shared topology → fitted garment doesn't transfer across bodies; expect clipping/sleeve mismatch on non-A-pose bodies; MIRPAMO can candy-wrap joints on non-manifold soup.
- The 2D doll can't dress the real 3D bodies — one fixed front-view silhouette only.
- Generation fidelity is prompt-only (no garment LoRA) — exotic garments hit-or-miss.
- Export writes into live game dirs — needs dry-run +
license!="red"gate + write only<slot>_i_<slug>.png(never overwrite generic fallbacks). - Overlap with NPCFACTORY is real — build this as the library/export layer NPCFACTORY lacks, not a third isolated dress-up stage.
- Auto-tagging is not available today (no live vision model) — treat as manual or paid-OpenRouter.
- Farm GPU = 1 job/node — batch gen queues; push flux/RMBG to the 2nd MODELBEAST node on ultra.
One-liner for John: by end of week you get a real "change clothes + walk" button (reskin + rigid attach + clip playback) and a best-in-class 2D wardrobe that drops straight into 90sDJsim; good-looking real-cloth 3D comes in Phase 4 from harvesting donors you already own; and the thing you'll use every day — the dressing-room library + export hub — is the spine that turns every engine into value for five existing consumers.