retune(art-edge): within-image relative colour comparison; snip does not clear the validation bar, not persisted - #734
Open
WilfordGrimley wants to merge 1 commit into
Open
Conversation
…lear the validation bar, not persisted classify_art_edge_continuity retuned from an absolute per-band pixel-variance test (tuned for classify_border_color's different question) to a within-image comparison: does the band beside the art crop match the border colour ImageEvidence.layout_class already found for this same image, by Euclidean RGB distance. Fixes the specific defect this was scoped to fix (dark, textured, off-hue artwork no longer gets read as a border merely for being dark and flat - confirmed by a constructed reproduction and pinned by a new test that fails against the pre-retune behaviour), and drops the now-redundant edge-band uniformity re-test. Validated against Scryfall's own images (label and pixels from the same source, unlike the catalogue-cohort measurement this supersedes, which name-matched uploads to printings and never confirmed the pixels themselves) across three cohorts: 30 confirmed extended-art, 20 confirmed borderless, 20 confirmed ordinary framed. Result: 0/30 recall on genuine extended-art images (worse than the pre-retune classifier's 1/30 on the same images), 0 false positives on both negative cohorts. Does not clear the bar stated before measuring. Root cause traced and documented: classify_border_color's own catch-all misreads 20/30 extended-art images as borderless, and for the remaining 10 the trimmed-image edge-band geometry shrinks to ~2px on a Scryfall image, too thin for a reliable colour reference - both upstream of this module's own scope. No ImageEvidence field, migration, Stage C wiring, or EXTRACTOR_OWNERSHIP entry added, per the brief's own stated fallback for a classifier that does not clear its validation bar. Full report: docs/reports/2026-08-06-art-edge-relative-comparison.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Retunes
local_art_edge.classify_art_edge_continuityfrom an ABSOLUTE per-bandpixel-variance test (
local_fallback._BORDER_UNIFORMITY_STD_THRESHOLD, tunedfor
classify_border_color's different question) to a WITHIN-IMAGE relativecolour comparison: does the band beside the art crop match the border colour
this same image's
layout_class(classify_border_color's own output)already says it has?
This fixes the specific, confirmed defect: dark, textured, off-hue artwork
beside a real border used to read
extendedpurely because it was dark andflat (low absolute variance), not because it matched or mismatched the
border's actual colour. See
docs/reports/2026-08-06-art-edge-relative-comparison.mdfor the full defect reproduction, the retune's own colour-distance/threshold
justification, and the validation methodology.
Validated against Scryfall's own images before any persistence decision
(three cohorts: 30 confirmed extended-art, 20 confirmed borderless, 20
confirmed ordinary framed — label and pixels from the same authoritative
source, unlike the earlier catalogue-cohort measurement this supersedes,
which name-matched uploads to printings without ever confirming the pixels
themselves). Result: does not clear the stated bar — 0/30 recall on
genuine extended-art images (worse than the pre-retune classifier's 1/30 on
the same images), 0 false positives on both negative cohorts. Root cause
traced and documented in the report:
classify_border_color's own"not uniform → borderless" catch-all misreads 20/30 extended-art images, and
for the remaining 10 the trimmed-image edge-band geometry shrinks to ~2px on
a Scryfall image (no bleed margin) — too thin for a reliable colour
reference. Both causes are upstream of this module's scope
(
local_fallback.py, PROTECTED CORE).Per the brief's own stated fallback for a classifier that does not clear
its validation bar: no
ImageEvidence.art_edge_classfield, no migration, noStage C extraction wiring, no
EXTRACTOR_OWNERSHIP/manifest entry, no votewiring.
classify_art_edge_continuityships as the new implementation,evidence-only, called from nowhere but its own tests — exactly the state the
pre-retune code was already in, on more defensible internals. Docs updated
to record the measured result (
docs/identification-pipeline.md,docs/pipeline-fidelity-gate.md's calculator roster entry) rather than"pending a validation pass".
Checklist
pre-commitand installed the hooks withpre-commit installbefore creating any commits.MPCAutofill/cardpicker/tests/test_local_art_edge.pyfor the newlayout_class-driven comparison: border-colour-match →framed(blackand white), the defect reproduction (dark off-hue artwork does NOT read
extended), a genuine colour-mismatch positive (extended), theborderlessshort-circuit (proved via a monkeypatch that raises ifpixel sampling is ever reached), an ambiguous-
layout_classabstention,a two-directional mutation-proof test on the distance threshold, the
pre-existing coordinate-frame asymmetry tests, and degenerate-input
abstention.
test_local_art_edge.pyalone: 23 passed. Fullcardpicker/tests/suite (order-dependence, issue Test suite is order-dependent: leaked fetch-failure window trips the envelope across files (8 failures on master) #679): 3678 passed, 8skipped, 0 failed.
(
/tmp/opencode/scratch_art_edge/probe3.py) reproducing the pre-retunebug by hand against the code this PR replaces, confirming the retuned
code no longer exhibits it.
(
/tmp/opencode/scratch_art_edge/scryfall_validation.py) fetching 70real Scryfall card images across three ground-truth cohorts (rate-limited
via the existing
SCRYFALL_REST/SCRYFALL_CDNdestinations, no imagepixels persisted to disk or DB at any point) and running both the
pre-retune and retuned classifiers against identical inputs — see the
report for the full numbers and root-cause trace.
docs_lint.py,check_extractor_manifest_sync.py,check_extractor_ownership_totality.pyall clean (unaffected, since nopersistence/extraction code changed).
docs/identification-pipeline.mdanddocs/pipeline-fidelity-gate.md'scalculator roster entry updated to record the measured (negative) gate
result instead of "pending a validation pass".
docs/reports/2026-08-06-art-edge-relative-comparison.md— the fullmeasurement writeup.