Batched embedding client (input as a list, batch 64 measured live at ~8-18
ms/chunk vs ~150-200 ms/chunk sequential through embed_chunk's
/api/embeddings) for jobs/mail-body-ingest -- embed_chunk stays the
single-text path for kb-query and paperless cyclic ingest. Validates the
response embedding count and each item's dimension (1024), raising
EmbeddingDimensionError (abort-run) on mismatch so a bad batch never silently
writes a mismatched vector (docs/kb/modules/05-faza-mailowa-plan.md, §4,
decision 5).
Module 5 phase 4 step 0 (docs/kb/modules/05-faza4-plan.md, §3, decision 1):
kb-query is a long-lived Docker service, documents-ingest is a venv job with
an `anthropic` dependency and CLI scripts it doesn't need. Move
embed_chunk/_vector_literal/cascade_query/flat_query into a shared package
with minimal deps (asyncpg, aiohttp only) so both can depend on the same
tested retrieval code without the service image pulling in the job's extras.
documents_ingest.chunk_embed/retrieval keep thin re-exports so nothing
importing the old paths breaks. Pure refactor: retrieval_eval.py run live
against kb-postgres@PIHA + Ollama@SOLARIA before/after gives byte-identical
`dist`/hit@3/gate results (still PASS) — zero behavior change in the cascade.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>