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>
3.7 KiB
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.blendas the output of each experimental step. Only write a new named.blendat a phase boundary (geometry done, texture done) or when a step's result gets registered. - Name the end state, not the attempt.
10_welded.blendearns a name;10_healed→10_rimheal→10_seamhealon the way there do not. - Reuse one
review/dir. QA renders are regenerable; mintingreview29/because 28 exist is 8 MB for nothing. - No
.blend1autosaves. Step scripts setbpy.context.preferences.filepaths.save_version = 0before saving. - Pin as you go. When an artifact is registered in
characters/REGISTRY.md, add its master.blendto.lanekeepin 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.