Her legs finally swap: the face-transplant cycle ships, and the prompt rules are law now

The female run took the whole evening because the model would not draw her
RUNNING: roll after roll came back with the same leg forward in every frame
— amplitude wiggle, no gait ("she never changes her leg... floating while
strobing"). The set that ships is the FACE TRANSPLANT: her old cycle's poses
(which always alternated properly — swaps at positions 2 and 6, 78%/74%,
where a runner's legs actually cross) redrawn with only the friendly face
and open beds changed. The model returned that roll on a painted CHECKERBOARD
— it has no concept of transparency, the word alone summons the pattern —
and the figures were custom-keyed off it: light checker blanket, dark
checker border-flood only (the dark cell is nearly her skirt colour; the
first blanket pass shredded the pleats), verified whole over a light ground.

Oliver gated every strip by eye. The alternatives lost on their own terms:
hex-only prompts obeyed the background but drew her dainty (max 44%, no
swap); the explicit leg-swap clause got alternation but clustered it in the
back half (step-step-skip). His pick: the transplant.

The lesson is in PROJECT.md now, next to the bed flag: NEVER say
"transparent" to the model — name one flat hex — and never freehand
background prose in one-off scripts; import _regen.py's CANVAS block, which
has said it correctly all along. SPRV 123, main.js v246, all 14 run frames
verified 200.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Fable 5 committed 2026-08-14 14:28:29 +02:00
1 parent 0f9738f5f2
commit ad624d281c
20 files changed
+11 -3

No files matched your search

+8
View File
@@ -1625,6 +1625,14 @@ suspect is the CUT, not the roll** — the sheets on disk are the evidence, and
"Only ink votes" below). Seven families shipped pixelated for two days because every fresh look
started from "the generator drew it badly" instead of diffing sheet against sprite.
**NEVER SAY "TRANSPARENT" TO THE MODEL — name the flat hex (re-learned the hard way 2026-08-14).**
The model has no concept of transparency: the word summons a PAINTED CHECKERBOARD background, and
"cuts out later" invites grey improvisations. Every background/bed instruction names ONE concrete
flat colour ("ONE FLAT solid #FF00FF across the entire canvas") and never mentions cutting,
keying or transparency. This rule already lived in `_regen.py`'s CANVAS block; a freehand one-off
prompt bypassed it and cost three rolls — REUSE THE CANVAS BLOCK (import it from `_regen.py`)
instead of re-writing background prose in scratch scripts.
**STRING BEDS ARE MAGENTA ON PURPOSE, and the cutter must be told (2026-08-14).** Prompts ask for
#FF00FF racket beds so they cut to transparency (the famroll rule). But `_fine.key` REPAINTS
enclosed magenta pale grey — protection from the era when magenta beds were an accident — which is
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 27 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 24 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 27 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 24 KiB

+1 -1
View File
@@ -494,6 +494,6 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
</div>
</div>
</div>
<script type="module" src="src/main.js?v=245"></script>
<script type="module" src="src/main.js?v=246"></script>
</body>
</html>
+2 -2
View File
@@ -221,7 +221,7 @@ function farB(z) {
// Asset cache-buster — bump with main.js?v=N (see the img.src note below). EXPORTED because the
// menu screens hang <img> tags on the same files, and two copies of this number is one copy too
// many: the one that does not get bumped is the one that serves a cached 404.
export const SPRV = 122;
export const SPRV = 123;
// The boot bar in main.js watches this. Nothing here CHANGES when things load — every sprite was
// already requested at import — it just makes the wait visible and holds the menu back until the
// last sheet has landed. See the onerror note below for the other half of "sometimes missing".
@@ -230,7 +230,7 @@ const SPR = {};
for (const n of ['p_idle1','p_idle2','p_bounce','p_bounce2','p_toss','p_smash','p_run1','p_run2','p_run3','p_run4','p_run5','p_run6','p_swing1','p_swing2','p_die1','p_die2','p_die3','p_die4','p_die5',
'p_pull', // the serve wind-up: the racket dropping behind him while the pull is drawn
'o_idle1','o_idle2','o_bounce','o_bounce2','o_toss','o_smash','o_swing1','o_swing2',
'o_run1','o_run2','o_run3','o_run4','o_run5','o_run6','o_run7','o_run8', // the rolled 8-frame cycle (_runroll.py; the friendly refresh landed a full 8 again)
'o_run1','o_run2','o_run3','o_run4','o_run5','o_run6', // the rolled 6-frame cycle (a 2x6 grid roll is TWO cycles — one row IS the cycle, never stitch the halves)
'x_ump','x_boyrun1','x_boyrun2','x_boyrun3','x_boyrun4',
'x_crowd','x_crowd2','x_ads', // CENTRE COURT (grass) — also the fallback set
'x_crowd_c','x_crowd_c2','x_ads_c', // TERRE ROUGE (clay)