docs+tools: working-file policy, lane pruner, and a human MD explainer
Two pieces of work.
1. Keep milestones, not steps. Staged NN_*.py lanes were saving a full
~80 MB .blend per attempt, so Lena's lane reached 3.0 GB of which 2.2 GB
was 30 .blend files -- five snapshots to land one crotch fix, five more
for the bra. The .py recipes are the real history; the blends are cache.
- .agents/rules/working-files.md: four-tier policy (KEEP / MASTER /
SCRATCH / UNKNOWN) + how to work a lane.
- tools/prune_lane.py: classifies a lane and prunes the scratch tier.
Dry-run by default. Reads a per-lane .lanekeep manifest, flags
binaries byte-identical to a registered original (canonical name
always survives a duplicate pair), and never auto-deletes a .blend
with no step script beside it -- those cannot be rebuilt.
- .gitignore: scratch patterns can never be committed.
Dry run on characters/female/lena_nude reports 2.3 GB reclaimable.
Not applied -- that lane had a live Blender session at the time.
2. .humans/marvelous-designer.html: how we author garments in Marvelous
Designer, written for people rather than agents -- the six-step process,
what has been made, the traps that cost hours, and what is still
unsolved. Matches the .humans/ HTML convention in ariki-game.
Also committing the docs the AGENTS.md knowledge map and the new page
reference, so they are not dangling: the clothing-lane architecture page,
the marvelous-designer skill, and the two screenshots the page embeds.
characters/ is deliberately untracked and stays that way -- it holds GBs of
blends and GLBs, and .gitattributes does not LFS-track .blend.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+10
-5
@@ -1,7 +1,12 @@
|
||||
# rules/ — always-on conventions for this repo
|
||||
|
||||
No repo-specific rules beyond what's already always-on in root `AGENTS.md`
|
||||
(git via `tinqs push`/`tinqs pull`, stage-by-explicit-path, naming law) and the
|
||||
shared hub rules at `tinqs-ltd/docs/.agents/rules/`. Add a file here when a
|
||||
convention needs to be enforced repo-wide and doesn't fit in `AGENTS.md`'s
|
||||
thin-entry budget.
|
||||
Beyond what's already always-on in root `AGENTS.md` (git via `tinqs push`/
|
||||
`tinqs pull`, stage-by-explicit-path, naming law) and the shared hub rules at
|
||||
`tinqs-ltd/docs/.agents/rules/`:
|
||||
|
||||
| file | rule |
|
||||
|---|---|
|
||||
| `working-files.md` | Keep milestones, not steps — the four-tier policy for staged working lanes (`.lanekeep`, scratch pruning, no `.blend1`) |
|
||||
|
||||
Add a file here when a convention needs to be enforced repo-wide and doesn't fit
|
||||
in `AGENTS.md`'s thin-entry budget.
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# Working files — keep milestones, not steps
|
||||
|
||||
Applies to every staged working lane under `characters/` and `clothing/work/`:
|
||||
folders where a chain of `NN_*.py` scripts each open a `.blend`, change it, and
|
||||
save. Left unmanaged those lanes grow ~80 MB per attempt. Lena's lane reached
|
||||
**3.0 GB, of which 2.2 GB was 30 `.blend` files** — five 80 MB snapshots to land
|
||||
one crotch fix, five more to land one bra fix.
|
||||
|
||||
## The rule
|
||||
|
||||
**A version is a milestone, not a step.** You get a saved copy when a change is
|
||||
finished and approved — not after every cut that got you there. Fixing the bra
|
||||
produces *one* file at the end, not one per attempt.
|
||||
|
||||
Four tiers:
|
||||
|
||||
| tier | what | policy |
|
||||
|---|---|---|
|
||||
| **KEEP** | the `NN_*.py` recipe, mask/input `.npz`/`.npy`, reference images, registered `_vNN.glb` artifacts | permanent. Governed by `characters/REGISTRY.md` (rule 9: superseded artifacts move to `archive/`, never deleted) |
|
||||
| **MASTER** | the handful of `.blend` files a registered artifact was actually built from, plus the live chain head | pinned by name in the lane's `.lanekeep`. Aim for ≤6 per lane |
|
||||
| **SCRATCH** | per-attempt `.blend`, `.blend1` autosaves, `review*/` and `dbg_*/` render dirs, `*_run.log` | overwritten freely, pruned any time, never committed |
|
||||
| **UNKNOWN** | a `.blend` in a folder with no step scripts — hand-authored, so no recipe rebuilds it | never auto-deleted; decide by hand |
|
||||
|
||||
The key asymmetry: **the `.py` scripts are the history.** They are kilobytes and
|
||||
they regenerate any intermediate state from the pinned master above it. Keeping
|
||||
20 `.blend` files is keeping 20 copies of the same 950k-vertex mesh to avoid
|
||||
re-running a script that takes a few minutes.
|
||||
|
||||
## How to work in a lane
|
||||
|
||||
- **Roll one working file.** Pass the same `work.blend` as the output of each
|
||||
experimental step. Only write a new named `.blend` at a phase boundary
|
||||
(geometry done, texture done) or when a step's result gets registered.
|
||||
- **Name the end state, not the attempt.** `10_welded.blend` earns a name;
|
||||
`10_healed` → `10_rimheal` → `10_seamheal` on the way there do not.
|
||||
- **Reuse one `review/` dir.** QA renders are regenerable; minting `review29/`
|
||||
because 28 exist is 8 MB for nothing.
|
||||
- **No `.blend1` autosaves.** Step scripts set
|
||||
`bpy.context.preferences.filepaths.save_version = 0` before saving.
|
||||
- **Pin as you go.** When an artifact is registered in `characters/REGISTRY.md`,
|
||||
add its master `.blend` to `.lanekeep` in the same edit that adds the registry
|
||||
row. Anything not pinned is scratch by definition.
|
||||
|
||||
## `.lanekeep`
|
||||
|
||||
One filename per line, `#` for comments, inline comments allowed. A `.blend`
|
||||
earns a line only when a registered artifact was built from it, or it is the
|
||||
head of the live chain. Unpin the head's parent once the head is accepted.
|
||||
|
||||
## Pruning
|
||||
|
||||
```
|
||||
python tools/prune_lane.py characters/female/lena_nude --recursive # dry run
|
||||
python tools/prune_lane.py <lane> --apply # delete scratch
|
||||
```
|
||||
|
||||
Dry run by default. It never deletes KEEP, MASTER or UNKNOWN, and it flags
|
||||
binaries that are byte-identical to a registered original in
|
||||
`characters/originals/` (the canonical filename always survives a duplicate
|
||||
pair, never the ` - Copy`).
|
||||
|
||||
**Before `--apply`, check nothing is mid-flight.** These runs take minutes and
|
||||
write their output at the end; a lane can gain a new head while you are looking
|
||||
at it. Confirm no `blender` process is running and that the newest `.blend` is
|
||||
pinned.
|
||||
|
||||
## Committing
|
||||
|
||||
Scratch patterns are in `.gitignore` and must never be committed. Note that
|
||||
`.gitattributes` LFS-tracks `.glb/.fbx/.mp4/.task` but **not `.blend`** — an
|
||||
80 MB master committed today goes into git proper, not LFS. Add `.blend` to
|
||||
`.gitattributes` first if masters are ever to be tracked.
|
||||
@@ -0,0 +1,117 @@
|
||||
# Clothing lane — reference image → garment worn in-game
|
||||
|
||||
The animation lane carries **motion** to ariki-game; this is the parallel lane
|
||||
that carries **clothing**. Both converge on the same 65-bone Quaternius
|
||||
skeleton. Built 2026-07-30 in two halves, by two sessions, that meet at a
|
||||
garment mesh.
|
||||
|
||||
```
|
||||
reference photo ──▶ [ UPSTREAM: Marvelous Designer ] ──▶ garment mesh (FBX/OBJ)
|
||||
or concept author · drape on game body 1–4k verts, fitted
|
||||
texture · QC placement + .zprj source
|
||||
│
|
||||
▼
|
||||
[ DOWNSTREAM: clothing/garment_pipeline.py ]
|
||||
census · prepare · fit · reduce · (bake) · skin · export
|
||||
│
|
||||
▼
|
||||
ariki-game/assets/quaternius/outfits/<set>/
|
||||
per-slot GLB on the shared skeleton
|
||||
+ OutfitCatalog.Register entry
|
||||
```
|
||||
|
||||
## The two halves
|
||||
|
||||
| | Upstream — authoring | Downstream — game-ification |
|
||||
|---|---|---|
|
||||
| Question it answers | "What is this garment, and what shape is it on *our* body?" | "How does the game wear it?" |
|
||||
| Tool | Marvelous Designer 2026 + `TinqsMDBridge` socket plugin | Headless Blender 5.1, deterministic, staged |
|
||||
| Lives in | `tools/md_bridge*`, `tools/tailor/` | `clothing/` |
|
||||
| Playbook | `.claude/skills/marvelous-designer/SKILL.md` | `clothing/README.md` |
|
||||
| Driven by | Agent over a socket; **needs a human click** per session, freezes MD's UI | Agent, fully headless, no human in the loop |
|
||||
| Output | Draped garment mesh + `.zprj` + QC screenshot | Per-slot skinned GLB + catalog entry |
|
||||
|
||||
Read each half's own doc for operating detail — this page only owns **how they
|
||||
fit together**. (Repo SoT rule: no second source of truth.)
|
||||
|
||||
## The handoff contract
|
||||
|
||||
Upstream hands downstream a **garment mesh in `tools/tailor/`**
|
||||
(`lena_<garment>_v<N>_garment.fbx|.obj`) plus the `.zprj` it came from.
|
||||
Downstream consumes it via a per-garment config
|
||||
(`clothing/configs/<garment>.json`) naming the source file, island→part mapping,
|
||||
slots, and budgets — new garment = new config, not new code.
|
||||
|
||||
Two properties of **MD-authored** meshes change how the downstream config should
|
||||
be written, and the pilot config does not yet reflect them:
|
||||
|
||||
- **Already at game budget.** MD-authored garments export at **1.2k–3.7k verts**.
|
||||
The pilot config was written against a *downloaded* MD dress at **2.49 M verts
|
||||
/ 110 MB**, where `reduce` is the hard stage. For our own garments, set a
|
||||
generous tri budget and only decimate if the test bed complains.
|
||||
- **Already fitted.** They were draped on `Ariki_Female_QuatSkin.glb` itself, so
|
||||
alignment/scale work is largely moot; the `fit` stage still earns its keep for
|
||||
the +4 mm clearance shell that prevents poke-through.
|
||||
|
||||
The `clothing/README.md` independently reached the same conclusion from research:
|
||||
prefer re-exporting from MD over fighting reduction downstream. Our upstream
|
||||
makes that the default rather than the exception.
|
||||
|
||||
## Why this shape
|
||||
|
||||
- **Why MD for authoring:** it is the only tool in the stack that turns flat
|
||||
panels into cloth physically draped on *our* body. Garments come out
|
||||
pre-fitted, low-poly, and reproducible from a `.zprj`.
|
||||
- **Why not Character Creator:** the CC5/Reallusion clothing lane was
|
||||
investigated and **rejected** — CC5 provably refuses clothing tools on AccuRig
|
||||
"Humanoid" characters (verified via its Python API *and* GUI). See
|
||||
`clothing/README.md`.
|
||||
- **Why not MD's own EveryWear** (its auto retopo/rig/GLB toolkit, which would in
|
||||
principle replace the whole downstream half): it is **GUI-only, absent from the
|
||||
scripting API**, so it cannot be driven agentically. Revisit only if
|
||||
Reallusion/CLO exposes it.
|
||||
- **Why the halves are separate processes:** MD can't run headless and freezes
|
||||
during a bridge session; Blender can and doesn't. Splitting keeps everything
|
||||
after the garment mesh fully automatable.
|
||||
|
||||
## Body and rig facts
|
||||
|
||||
- Target body: `ariki-game/assets/quaternius/derived-bodies/Ariki_Female_QuatSkin.glb`
|
||||
(32.7k verts, 65 bones, 1.777 m).
|
||||
- MD needs it as **FBX**: `tools/tailor/avatar/Lena_QuatSkin_Avatar.fbx`
|
||||
(leaf bones stripped, stray meshes dropped) — regenerate with the converter
|
||||
described in the marvelous-designer skill.
|
||||
- Measurements: `tools/tailor/lena_measurements.json` — she is stylized
|
||||
(108-67-109 cm, 72 cm thighs, 178 cm), so standard size charts don't fit.
|
||||
- The skeleton is the same hub the animation lane targets — see `../ARCHITECTURE.md`.
|
||||
|
||||
## Status (2026-07-31)
|
||||
|
||||
**Proven upstream:** image → decomposition → drafted panels → sewn → draped →
|
||||
textured → QC'd → exported, end to end. Shipped: tee, A-line skirt, and a kapa
|
||||
haka set (tāniko pari + piupiu) matched to a reference photo, all with repo
|
||||
screenshots in `tools/tailor/screenshots/`.
|
||||
|
||||
**Proven downstream:** the dress pilot ran through to an in-game render
|
||||
(`clothing/dress_ingame_2026-07-30.png`).
|
||||
|
||||
**The seam is CROSSED (2026-07-31).** The kapa haka set — MD-authored on our own
|
||||
body — went through `garment_pipeline.py` (`configs/pari.json`,
|
||||
`configs/piupiu.json`) to `Female_Kapahaka_{Body,Legs}.gltf`, and both render on
|
||||
Lena in the game's clothing test bed with the tāniko pattern and piupiu stripes
|
||||
intact. None of the feared surprises materialised: MD's material naming, island
|
||||
splitting, and UV/texture carry-through all worked first time. The predictions on
|
||||
MD-authored meshes above held — both garments arrived at game budget already
|
||||
(4k/8k tri ceilings never bit) and needed no alignment work beyond a z-nudge.
|
||||
|
||||
**What the in-game pass exposed instead** was pose-dependent, not authoring:
|
||||
the bodice neckline opens over the sternum and the piupiu lets a thigh through
|
||||
once the skeleton leaves the rest pose. Both are invisible to the pipeline's own
|
||||
QA, which only ever renders the **rest pose** — the pose the garment was fitted
|
||||
in, i.e. the one pose that cannot fail. Judging cloth in motion is the test bed's
|
||||
job, and until 2026-07-31 the bed could not do it either (its Idle/Walk/Dance
|
||||
buttons were overridden by the AnimationTree; fixed in `ClothingTestBed.PlayClip`).
|
||||
|
||||
**Known gaps:** trousers/shorts don't drape (see the skill's failure catalogue);
|
||||
placement QC's pixel classifier is crude; no skirt bones, so deep leg swings
|
||||
compress hems; garments are flat-coloured until textures are authored.
|
||||
Reference in New Issue
Block a user