Skip to content

local-ocr-v1 / local-phash-v1 / local-fallback-v1: the live-fetch pilot engine channels remain unreachable from the conveyor #723

Description

@WilfordGrimley

Three calculator identities — local-ocr-v1, local-phash-v1 (both cardpicker/local_identify_printing_tags.py, cast by run_pilot's per-card engine loop), and local-fallback-v1 (cardpicker/local_fallback.py, cast by run_fallback_for_card) — remain unreachable from stage_e_dispatch._run_stage_d after the 2026-08-05 "wire the FREE vote channels" pass, and were classified EXPENSIVE rather than wired.

Why these are genuinely EXPENSIVE, not just unwired

Unlike the four channels wired in that pass (ai-art-detector-v1, lands-artist-decomp-v1, residual-classify-v1, art-hash-artist-v1), these three identities' PRIMARY caster is local_identify_printing_tags.run_pilot — the original live-fetch pilot engine, which per stage_e_dispatch._run_attribute_chip_casters's own docstring "has ONE completed run in its history, 2026-07-16". Computing an OCR or phash reading for a card FOR THE FIRST TIME requires a real CDN image fetch plus (for OCR) a tesseract pass or (for phash) a hash computation over real pixels — there is no stored-evidence reconstruction path for the primary computation, unlike stage-d-join-key-v1/stage-d-fallback-v1/lands-artist-decomp-v1, all of which reconstruct their verdict from ImageEvidence fields Stage C already persisted. local-fallback-v1's only real caster (run_fallback_for_card) is in the same position: local_residual_classify.py's own module docstring states plainly that "OCR-flagged rows... NOT free... one real CDN image fetch + a fresh run_ocr_for_card pass" and the equivalent for fallback-flagged rows.

Some votes under these same anonymous_ids ARE already cast opportunistically, for free, by other calculators reconstructing from stored evidence (e.g. lands-artist-decomp-v1's own OCR-resolved branch casts a local-ocr-v1 vote when collector-line OCR alone resolves a land card from stored evidence) — that is a side effect of a DIFFERENT calculator's own free path, not this identity's own primary engine running for free. run_pilot itself remains what would have to run to compute these values for a card with no stored evidence yet, and that computation is unavoidably per-card fetch+extraction cost.

Acceptance criteria

  • A decision is recorded on whether run_pilot (or a successor) is a channel this project still wants live at all, given local_calculate_verdicts.run_join_key_calculator/run_fallback_calculator/run_slow_path_calculator already cover the equivalent ground via Stage C's evidence-first design. If NOT: local-ocr-v1/local-phash-v1/local-fallback-v1 are marked formally retired-as-a-primary-engine in docs/pipeline-fidelity-gate.md (their historical row counts stand; snip new machine votes under these identities continue arriving only as side effects of other calculators' free paths).
  • If YES (the pilot stays a live channel): a fetch-budget design is specified for running it as a Stage D calculator inside a micro-batch — modeled on run_lands_identify/run_frame_mismatch_recovery's own card_ids + zero-budget guard pattern, but for the NON-zero-budget case this channel actually needs, since a fetch budget of N per whole-catalogue invocation silently becomes N × (number of micro-batches) under naive per-batch scoping (see either of those two modules' own docstrings for the exact math). This needs the same "run-scoped budget that means the same thing however the work is sliced" primitive both of those docstrings flag as issue Monolith extractor: one fetch, all pixel work in-memory, all deduction ordered behind it #533's own still-open design decision — this issue depends on that one.
  • Per-card cost is measured on a real sample (fetch latency + OCR/phash compute time) and reported, so a future wiring decision has real numbers rather than an estimate.
  • Backfill scope for the existing catalogue is stated separately (per this project's practice: wiring is a future-passes decision, backfill is a separate deliverable) — in particular, OCR-derived fields are being re-derived under new extractor versions by a pass already live on production as of 2026-08-05, so any backfill plan for local-ocr-v1 specifically should sequence after that pass completes, not before, to avoid producing verdicts against stale extractor output that would need redoing.

Non-goals

Do not wire any of the three by simply calling run_pilot/run_fallback_for_card with a zero fetch budget the way the four FREE channels were wired — unlike those four, these three have no evidence-only computation path at all today; snip a zero-budget call here would resolve nothing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions