Phase 1 — Schema inference. One cheap model call reads the header plus a representative sample and returns a typed mapping plan: each source column resolved to a CRM field with a confidence score, plus the detected date format and default country code. That plan is injected into every extraction batch as global context.
Phase 2 — Batched extraction. Rows are chunked (25/batch), run 4 at a time under a concurrency limit at temperature 0, each batch carrying the Phase-1 plan and few-shot examples. Decoding is constrained by a schema, so the model physically cannot emit a value outside the CRM shape or the crm_status / data_source whitelists.