The kit gate learns hue, because a greyscale check cannot see grey turning blue

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>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-12 10:35:29 +02:00
1 parent 1c405f045f
commit ef88429887
23 files changed
+32 -19

No files matched your search

+13 -4
View File
@@ -116,26 +116,35 @@ def density(path):
return round(float(((d > 40) & solid[:, :-1]).sum() / max(1, solid.sum())), 3)
def kit(path):
"""Three numbers that say whether a roll is wearing the right clothes:
"""Four numbers that say whether a roll is wearing the right clothes:
REDNESS how red the shirt is (r minus the mean of g,b, over the saturated warm pixels).
Brightness alone will NOT do — a brick-red shirt is as bright as a red one.
SHORTS mean brightness of the mid-tone neutral pixels. Charcoal ~61, pale grey ~83.
BRIGHT fraction of the body that is near-white — the shoes and socks. Brown shoes drop it,
pale shorts push it up.
HUE the shorts' blue-minus-red. THE ONE THE FIRST THREE ARE BLIND TO: Oliver spotted the
headless men's trousers had changed colour and every number above said they had not
— brightness sat at 85 against the healthy frame's 89 while the hue walked from a
warm charcoal (-8.7) to a cold blue-grey (+0.2). A greyscale measure cannot see a
grey turning blue, which is most of what "the colour changed" ever means here.
Calibrated on frames known to be right (idle/bounce/run): redness 99-110, shorts 60-63,
bright 2.7-2.9%. Every frame that had visibly drifted fell outside on at least one axis."""
a = np.array(Image.open(path).convert('RGBA')).astype(int)
px = a[..., :3][a[..., 3] > 128]
if not len(px): return (0.0, 0.0, 0.0)
if not len(px): return (0.0, 0.0, 0.0, 0.0)
red = px[(px[:, 0] > px[:, 1] + 45) & (px[:, 0] > px[:, 2] + 45)]
neutral = px[(px.max(1) - px.min(1)) < 55]
shorts = neutral[(neutral.mean(1) > 25) & (neutral.mean(1) < 145)]
bright = neutral[neutral.mean(1) >= 150]
return (round(float((red[:, 0] - (red[:, 1] + red[:, 2]) / 2).mean()) if len(red) else 0, 1),
round(float(shorts.mean()) if len(shorts) else 0, 1),
round(len(bright) / len(px) * 100, 1))
round(len(bright) / len(px) * 100, 1),
round(float((shorts[:, 2] - shorts[:, 0]).mean()) if len(shorts) else 0, 1))
def kit_off(outs, ref_name, tol=(12, 10, 1.5)):
# NOTE the fourth tolerance: kit() returns four numbers and kit_off zips them against this, so a
# three-long tuple would silently skip the hue check rather than fail — the same shape of no-op the
# read-only floodfill in _fine.py was. Every caller passing its own `palette_tol` needs four too.
def kit_off(outs, ref_name, tol=(12, 10, 1.5, 4)):
"""Is this roll wearing the right kit? Generative rolls drift the palette EVERY TIME and nothing
else here catches it: colour_match only runs for `check: finer`, and it is a global mean/sd fit
far too weak to pull brick-red back to red. Before this existed, six frames shipped with a white