feat(printing-metadata): persist Scryfall layout, measure sideways cohort (issue #693) - #696
Merged
Merged
Conversation
…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.
9 tasks
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.
Summary
CanonicalPrintingMetadata.layout(migration0103_canonicalprintingmetadata_layout), populated verbatim fromprinting_metadata_import.PrintingMetadataRow.layout— a value that was already parsed but previously discarded once checked againstDOUBLE_FACED_LAYOUTS. Follows the model's own established field conventions exactly (CharField(blank=True)likeborder_color/frame, added to_METADATA_SYNC_FIELDS, wired into theCanonicalPrintingMetadata(...)constructor call).DOUBLE_FACED_LAYOUTS's existing use ofrow.layoutis unchanged.canonical_cardlink, 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.Card.name(source metadata, independent of identification) name-matched againstCanonicalCardrows whose Scryfalllayoutisplanar/scheme, via the sameto_searchablejoindeductive_backfill.CanonicalNameIndexalready 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 acanonical_cardlink, 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.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.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 isbleed_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.docs/features/catalog-completion-plan.md's Stage C section.makemigrationsblocker (missing staticfiles manifest, unrelated to migrations themselves) indocs/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:0103depends on0102_artbox_phash_exemplar, nothing else branches off0102).pre-commit run(ruff, isort, black, mypy, prettier) green on all touched files.docs-lintclean.0103is not yet applied to production, solayoutwas sourced from the bulk-cache file directly, same as the original measurement — not from the not-yet-migrated DB column).