Files
animation/.agents/rules/working-files.md
T
jeremy 4bbd1a1732 docs(humans): ship the MD explainer as a PDF with the images baked in
The HTML references screenshots relatively, so it only renders inside a
checkout -- mailing the file on its own gives broken images. The PDF is one
self-contained file, which is what actually gets sent to Ozlem.

- tools/humans_to_pdf.py: renders .humans/*.html via headless Chrome (or
  Edge), so the output is what the browser shows. HTML stays the source.
- @media print block on the page: the wide tables and the pipeline diagram
  scroll on screen but would be cut off at the paper edge; this reflows
  them and keeps figures, callouts and table rows off page breaks.
  Verified at A4 content width -- 6 pages, both screenshots embedded.
- *.pdf -> LFS. Each regeneration is a whole new ~2 MB blob, and unlike
  png/jpg there are no PDFs tracked raw yet, so there is no history to
  rewrite by adding it now.

Also corrects working-files.md: it claimed .gitattributes does not LFS-track
.blend, which was true when written and is no longer -- .blend/.zprj/.obj/
.npy/.npz have since been added. The note now covers what is actually still
excluded (png/jpg, deliberately) and why that makes QA renders scratch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 09:31:37 -07:00

3.8 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.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_healed10_rimheal10_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. .blend, .zprj, .obj, .npy/.npz and the rest of the heavy formats are LFS-tracked in .gitattributes, so a pinned master can be committed safely — but note that .png/.jpg deliberately are not (≈250 are already tracked raw; adding them would rewrite every one without shrinking history). A lane's QA renders are scratch for that reason too, not just a disk one.