Skip to content

feat(printing-metadata): persist Scryfall layout, measure sideways cohort (issue #693) - #696

Merged
WilfordGrimley merged 7 commits into
masterfrom
sideways-layout-693
Aug 5, 2026
Merged

feat(printing-metadata): persist Scryfall layout, measure sideways cohort (issue #693)#696
WilfordGrimley merged 7 commits into
masterfrom
sideways-layout-693

Conversation

@WilfordGrimley

@WilfordGrimley WilfordGrimley commented Aug 5, 2026

Copy link
Copy Markdown

Summary

  • Step 1: adds CanonicalPrintingMetadata.layout (migration 0103_canonicalprintingmetadata_layout), populated verbatim from printing_metadata_import.PrintingMetadataRow.layout — a value that was already parsed but previously discarded once checked against DOUBLE_FACED_LAYOUTS. Follows the model's own established field conventions exactly (CharField(blank=True) like border_color/frame, added to _METADATA_SYNC_FIELDS, wired into the CanonicalPrintingMetadata(...) constructor call). DOUBLE_FACED_LAYOUTS's existing use of row.layout is unchanged.
  • Step 2 (redone, same day): the first measurement (41 of 230,488 catalogued cards, 0.018%, 2.4% collector-line parse failure) was retracted — it counted only cards already carrying a canonical_card link, and that link is acquired by having been successfully identified, so a sideways card whose crop lands on rotated content and fails identification could never appear in that cohort. The cohort was drawn from a population selected for not having failed.
  • Redo: cohort defined by expected layout instead — Card.name (source metadata, independent of identification) name-matched against CanonicalCard rows whose Scryfall layout is planar/scheme, via the same to_searchable join deductive_backfill.CanonicalNameIndex already uses. Result: 1,093 cards (0.474% of the catalogue), fully containing the old 41-card cohort; only 43 of the 1,093 (3.9%) carry a canonical_card link, confirming the bias directly. Its collector-line parse failure rate is 53.3% (583/1,093) against the correct comparison group — the unlinked population generally, 40.4% (85,217/210,832) — not the whole-catalogue figure (38.4%), which mixes the unlinked population with the already-successfully-identified linked population (17.1%) and understates the real unlinked baseline. That is a genuine 13-point elevated signal the biased denominator hid.
  • Rotation trial (the test that elevated signal was supposed to gate): 30 real images sampled live from this cohort's never-linked pool (1,046 cards), fetched via image_cdn_fetch.fetch_card_image, run through the existing collector-line and Illus.-anchor crops unmodified, then again with the whole image rotated 90° clockwise and 90° counter-clockwise. Collector-line OCR produced a plausible-looking parse on 17/30 baseline, 9/30 CW, 7/30 CCW — but validated against each card's own real candidates (local_ocr.validate_against_candidates, the same check Stage D applies), zero were genuine matches in any orientation. The Illus.-anchor artist-line crop found zero in all three orientations too.
  • Gate result: crop-box rotation (local_fallback.normalize_crop_box) is not warranted and was not built — not because the cohort is negligible (it isn't, 0.474%) or the failure rate is unremarkable (it isn't, +13 points over baseline), but because the rotation trial found nothing to recover. Matches issue Trimmed-bleed cohort fails collector-line OCR at 12x the bleed rate (remap or classifier tolerance) #683's own finding for the heavily-overlapping trimmed cohort (24/30 of this sample is bleed_class=trimmed): these are disproportionately fan-made custom renders that plausibly never had a machine-readable collector line at all — a content problem, not a crop-geometry problem.
  • golden_set.py's 30 pinned cards contain zero sideways-layout cards, so the golden set cannot catch a regression in this path.
  • Documents the field itself, the retracted first measurement, the redo methodology, and the rotation trial in docs/features/catalog-completion-plan.md's Stage C section.
  • Documents a fresh-worktree makemigrations blocker (missing staticfiles manifest, unrelated to migrations themselves) in docs/troubleshooting.md, hit and resolved while verifying the migration locally.

Test plan

  • pytest cardpicker/tests/test_printing_metadata_import.py cardpicker/tests/test_golden_set.py cardpicker/tests/test_local_fallback.py cardpicker/tests/test_image_evidence.py cardpicker/tests/test_run_image_evidence_cohort.py — 307 passed, 0 failed.
  • makemigrations --check --dry-run — no pending model changes (migration is complete and single-leaf: 0103 depends on 0102_artbox_phash_exemplar, nothing else branches off 0102).
  • pre-commit run (ruff, isort, black, mypy, prettier) green on all touched files.
  • docs-lint clean.
  • Step 2's redone measurement ran read-only against the live database and its Scryfall bulk cache (migration 0103 is not yet applied to production, so layout was sourced from the bulk-cache file directly, same as the original measurement — not from the not-yet-migrated DB column).
  • Rotation trial: 30-card real-image sample, before/after collector-line and artist-line parse outcomes under baseline + 2 rotation directions, validated against real candidates — negative result, documented above.
  • CI not watched by this session.

…hort (issue #693)

Step 1: add CanonicalPrintingMetadata.layout (migration 0102), wired from
PrintingMetadataRow.layout (already parsed, previously discarded after the
DOUBLE_FACED_LAYOUTS check). Follows the existing border_color/frame field
conventions on that model exactly (blank-string sentinel, CharField, added
to _METADATA_SYNC_FIELDS).

Step 2: measured the sideways cohort (Scryfall layout planar/scheme) against
the live catalogue via read-only docker exec queries. 41 of 230,488 catalogued
cards (0.018%) resolve to a sideways layout; the cohort's own collector-line
parse failure rate (2.4%, 1/41) is not elevated versus the whole-catalogue
rate measured multiple ways (15.5%-38.4% depending on denominator). Gate
result: cohort negligible, no elevated failure signal - stopping here per
the brief's own explicit exit ramp. Step 3 (crop-box rotation) not built.

None of golden_set.py's 30 pinned cards is a sideways layout (confirmed via
live query) - the golden set cannot catch a regression in this path.

Also documents a fresh-worktree makemigrations blocker (missing staticfiles
manifest) in docs/troubleshooting.md, hit and resolved while verifying this
migration.
MPCAutofill/urls.py -> MPCAutofill/MPCAutofill/urls.py (Django project's
own urls module, which contains the static() call for the favicon
redirect). Fixes docs_lint.py path-reference failure on PR #696.
…out and the sideways-cohort measurement (issue #693)
…ent, redo with rotation trial (issue #693)

The 41-card/0.018% cohort was drawn only from cards already carrying a
canonical_card link, which is acquired by successful identification -
a sideways card whose crop lands on rotated content and fails
identification could never appear in it. Redone by expected layout
(Card.name join against CanonicalCard's Scryfall layout, independent
of identification success): 1,093 cards (0.474%), 53.3% collector-line
parse failure vs. 40.4% for the correct comparison group (unlinked
population generally, not the whole-catalogue figure that mixes in the
already-identified linked population).

That elevated signal motivated a rotation trial: 30 real images
sampled from the cohort's never-linked pool, existing collector-line
and Illus.-anchor crops run unmodified then again with the image
rotated 90 degrees both directions. Zero candidate-validated genuine
matches in any orientation - a content problem (fan-made renders
without a real collector line, overlapping issue #683's trimmed-cohort
finding), not a crop-geometry problem. Rotation was evaluated and
deliberately not built.

PR #696 body patched to match via gh api PATCH (gh pr edit fails on
this repo).
…03, repoint dependency at 0102_artbox_phash_exemplar (#696)

Merged origin/master into this branch, which brought in 0102_artbox_phash_exemplar
(#701) depending on 0101_delete_printingtagvote — the same parent this branch's
migration used, producing two leaves. Renumbered this branch's migration to 0103
and repointed its dependency at 0102_artbox_phash_exemplar. Operation unchanged.
@WilfordGrimley
WilfordGrimley merged commit 17345a4 into master Aug 5, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant