Behaviour for OCR handoff modules used by the {:ocr, module} strategy.
extract/2 receives the original PDF binary and the 0-indexed list of
pages that need OCR, and returns %{page => markdown_text}. Pages missing
from the map keep their placeholder (needs_ocr: true). Returning
{:error, reason} leaves the per-page placeholders untouched and records
reason in result.ocr_errors — classification/extraction results are
not discarded.
Summary
Callbacks
@callback extract(binary(), [non_neg_integer()]) :: {:ok, %{required(non_neg_integer()) => String.t()}} | {:error, term()}