`_regen.py --audit` is clean for the first time:
racket_play z_r2/z_r3 1.00 0.157 0.565 ok
racket_w1 z_rw1/z_rw1b 1.00 0.112 0.424 ok
racket_w2 z_rw2/z_rw2b 1.00 0.077 0.372 ok
racket_f_play z_r2_f/z_r3_f 1.00 0.049 0.552 ok
racket_f_w1 z_rw1_f/…b_f 1.01 0.112 0.716 ok
racket_f_w2 z_rw2_f/…b_f 1.00 0.054 0.793 ok
Against the reference pairs (brute 1.00/0.000/0.638, shambler 1.00/0.070/0.520)
these are the real thing: one body, same camera, legs swapped. Fifteen rolls
were rejected getting here, every one for a named measurable reason — which is
the whole point of the gate: none of it shipped on luck.
Two calibration lessons, both from watching what the gate rejected:
BRIGHT is off for the racket batches. It counts near-white pixels and was
calibrated on the LIVING opponent, whose racket barely registers — these frames
hold a pale-strung racket FACE-ON and it swings 3%..20% purely with how the
racket is angled. It was rejecting rolls for racket geometry. Redness, shorts
brightness and shorts hue are the kit, and hue is the one that caught the drift
Oliver actually saw.
EACH WOUND STAGE IS HELD TO THE STAGE BEFORE IT, not to the healthy frame two
steps away. Stage 2 kept being rejected at hue -4.2 against the healthy -8.7
while the stage it actually follows sits at -5.0 — the roll was more consistent
with its own neighbour than the gate would allow. Chained references stop drift
compounding without demanding stage 2 match a frame the player never sees next
to it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Oliver: "look at the headless men — the trouser color changed." He was right and
every number in kit() said he was not. Brightness sat at 85 against the healthy
frame's 89, comfortably inside tolerance, while the shorts' blue-minus-red
walked from a warm charcoal -8.7 to a cold +0.2 across the wound stages. All
three existing measures are greyscale or red-channel; none of them can see a
grey going blue, which is most of what "the colour changed" ever means here.
Fourth number: the shorts' hue. It immediately fails the headless men AND finds
a second drift in the wounded women that the brightness test had passed.
The tolerance default went to four entries deliberately — kit_off zips got/ref/
tol, so a three-long tuple would have SKIPPED the new check rather than failed
it. That is the same shape of silent no-op as the read-only floodfill.
Also: DAMAGE NOW ACCUMULATES. Stage 2 said only "headless", so the arm torn off
at stage 1 came back — in a mode where the score IS the body, taking a point off
it made the body look healthier. Stage 2 is now headless AND still one-armed.
And the stride rule got its counterweight: "copy it exactly, only the legs
change" has a second failure mode where the model copies it exactly INCLUDING
the legs and returns the same picture twice (upper 0.017, legs 0.022 — a body
sliding along with frozen feet, the very thing being fixed). Both halves are
stated now: identical above the hips, obviously different below.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The setup screen picks WHAT before WHO and WHERE. Three rows out of a table,
in the court row's own markup:
CLASSIC TENNIS is not the opener with the turn switched off and left there —
it is the mode the other two are built on, so it gets real match scoring: six
games with a two-game lead is a set, best of TUNE.classicSets is the match,
the board shows the sets column (hidden until now outside splatter) and the
bar under it says which set this is. The CPU stops rubber-banding and flubs
less: aiFlubLoss exists to get a new player PAST the opener, and a mode whose
whole promise is a real match cannot be won by an opponent that falls apart
the moment he goes ahead. No tiebreak — 6-6 plays on to 8-6. Marked ponytail.
That needed a second ENDING, the one with no corpse in it: G.done, the same
summary and gated tap as the death screen, its own words (GAME, SET, MATCH. /
BEATEN.) and the man still standing. The three endings now share one block
rather than three copies of it.
Caught by the first classic test: stats banked only the FIRST classic run of a
session. `banked` was cleared by the next KILL, and a classic match has no
kills in it at all — every later match was swallowed by the double-bank guard.
beginRun() is the honest reset and restartRun calls it.
ZOMBIE TENNIS from the menu is one line; the back room keeps its door.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>