mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 21:47:02 +01:00
Adds the route-independent spine of the planned art-generation bake-off: a harness that decides whether generated art is well-formed, so "non-sloppy" becomes machine-checkable instead of a judgement call. Findings that shaped the design, all measured rather than assumed: - Integer-scale invariance separates true pixel art (impurity 0.0000) from interpolated fakes (1.0000) exactly -- but passes trivially at scale 1, so it must never be trusted alone on native-resolution output. - Gate ORDER is load-bearing. A soft-alpha image has no fully-opaque pixels, so an opaque-only colour count returns 0 and silently passes. ALPHA_NOT_BINARY now runs first and COLOR_COUNT fails closed on an empty opaque set. - Counting must be over opaque RGB only: transparent pixels retain arbitrary RGB and inflated a naive RGBA count, rejecting correct art at 18/16. - Declaring a gate was not enough to run it. hand_painted.toml shipped declaring SILHOUETTE_LOW_CONTRAST with no implementation, so it parsed, ran nothing, and reported a pass. load_spec now fails closed on unimplemented gates, result-only codes, and gates missing their config. Thresholds are calibrated against 250 genuine 32x32 CC0 icons, not guessed: p50=7 p90=13 p99=26 opaque colours; cap 32 rejects 0.0% of real art while raw generator output measured 34403 colours. An initial cap of 16 wrongly rejected a real DCSS icon -- re-derived from the corpus rather than nudged. Verified: 57 tests, 100% branch coverage, zero suppressions, all hooks pass. 58/60 (96.7%) of real CC0 icons pass the full stack; both failures confirmed true positives. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9rQ12yZ7sJxiPQTCS5dUF
83 lines
2.7 KiB
Python
83 lines
2.7 KiB
Python
"""Reason-code vocabulary for art gates.
|
|
|
|
Single source of truth. Every gate failure, every rejects-store record and
|
|
every contact-sheet annotation keys off these constants, so that "feed
|
|
rejections back as negative examples" is a queryable fact next session rather
|
|
than a good intention.
|
|
|
|
Exit codes are deliberately three-valued: conflating a harness crash with an
|
|
art rejection would silently convert our own bugs into art failures and
|
|
poison both the rejects store and the bake-off metrics.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from enum import Enum
|
|
from typing import Final
|
|
|
|
# All applicable gates passed.
|
|
EXIT_PASS: Final = 0
|
|
|
|
# The asset is well-formed but failed at least one gate.
|
|
EXIT_GATE_FAILURE: Final = 1
|
|
|
|
# Spec malformed or image unreadable -- a harness fault, never an art verdict.
|
|
EXIT_HARNESS_ERROR: Final = 2
|
|
|
|
|
|
class Code(str, Enum):
|
|
"""Machine-readable gate failure codes.
|
|
|
|
Values are SCREAMING_SNAKE so they survive a round trip through JSONL and
|
|
remain greppable with ``jq`` without a lookup table.
|
|
"""
|
|
|
|
OFF_PALETTE = "OFF_PALETTE"
|
|
TOO_MANY_COLORS = "TOO_MANY_COLORS"
|
|
NO_OPAQUE_PIXELS = "NO_OPAQUE_PIXELS"
|
|
ALPHA_NOT_BINARY = "ALPHA_NOT_BINARY"
|
|
CANVAS_SIZE = "CANVAS_SIZE"
|
|
MARGIN_TOO_SMALL = "MARGIN_TOO_SMALL"
|
|
EMPTY_CANVAS = "EMPTY_CANVAS"
|
|
SCALE_NOT_INVARIANT = "SCALE_NOT_INVARIANT"
|
|
OUTLINE_INCONSISTENT = "OUTLINE_INCONSISTENT"
|
|
SILHOUETTE_LOW_CONTRAST = "SILHOUETTE_LOW_CONTRAST"
|
|
SEAM_ENERGY = "SEAM_ENERGY"
|
|
QUADRANT_WEIGHT = "QUADRANT_WEIGHT"
|
|
LOOP_POPS = "LOOP_POPS"
|
|
STATIC_ANIMATION = "STATIC_ANIMATION"
|
|
LICENSE_NOT_PERMISSIVE = "LICENSE_NOT_PERMISSIVE"
|
|
LICENSE_AMBIGUOUS = "LICENSE_AMBIGUOUS"
|
|
|
|
def __str__(self) -> str:
|
|
"""Return the bare code, so f-strings do not leak ``Code.`` prefixes."""
|
|
return self.value
|
|
|
|
|
|
# Codes a spec may DECLARE. A code outside this set is either a result-only
|
|
# code (emitted by a gate, never requested) or not yet implemented.
|
|
#
|
|
# This set exists because declaring a gate must never be enough to make it run:
|
|
# a spec that names an unimplemented gate would parse cleanly, run nothing, and
|
|
# report a pass -- indistinguishable from art that genuinely passed. Keeping the
|
|
# declarable set explicit forces `load_spec` to fail closed instead.
|
|
DECLARABLE: Final = frozenset(
|
|
{
|
|
Code.ALPHA_NOT_BINARY,
|
|
Code.TOO_MANY_COLORS,
|
|
Code.OFF_PALETTE,
|
|
Code.CANVAS_SIZE,
|
|
Code.SCALE_NOT_INVARIANT,
|
|
Code.SILHOUETTE_LOW_CONTRAST,
|
|
}
|
|
)
|
|
|
|
# Codes a gate may EMIT but a spec may not request. ``NO_OPAQUE_PIXELS`` is the
|
|
# fail-closed result of the colour and palette gates, not a gate in its own right.
|
|
RESULT_ONLY: Final = frozenset(
|
|
{
|
|
Code.NO_OPAQUE_PIXELS,
|
|
Code.EMPTY_CANVAS,
|
|
}
|
|
)
|