retrieval_eval.py now runs every existing query through hybrid_query
alongside flat/cascade, and gate criteria 1/3 (no degradation, negative
controls) check hybrid too -- this is the phase's key regression test: does
adding mail chunks to the HNSW index degrade the 7 existing paperless
queries? Criterion 4 (mail hit@3 in hybrid) is wired but skipped with an
explicit report note when queries.yaml's new `mail_queries` placeholder is
empty, rather than silently PASSing/FAILing on absent data.
queries.yaml: added an empty `mail_queries: []` placeholder + inline format
docs. The existing 7-query `queries:` list is untouched.
REMINDER for the operator (per plan §8, Krok 5): 3-5 mail queries are still
needed -- things you know are in last year's mail, plus each one's expected
gmail Message-ID -- before criterion 4 and the full plan §8 gate can PASS.
Until then this only re-verifies the paperless regression check.
docs/kb/modules/05-faza-mailowa-plan.md, §8.
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>
documents_ingest.retrieval: flat_query (baseline) i cascade_query (stage1
document_summary model='claude-haiku-4-5' -> stage2 document_chunk), jedno
dzielone wywołanie embeddingu bge-m3 per zapytanie, tylko +1 SQL na kaskadę.
Czyste query_text -> wyniki(dist, source) pod przyszłe kb-query fazy 4.
166/166 testów (10 nowych, mocki: stage1->stage2, koperta bez chunków,
N > liczba kopert, no-summaries short-circuit).
Eval-set utrwalony 1:1 z pilota (docs/kb/eval/retrieval-pilot-2026-07-16.md,
nietknięty) w eval/queries.yaml + skrypt bramki eval/retrieval_eval.py
(integracyjny, read-only, poza pytest).
Wynik bramki (żywa baza, N=10 k=5): kryterium 1 (brak degradacji) PASS,
kryterium 2 (hit@3 kaskada=5/5 vs płaski=5/5) PASS, kryterium 3 (kontrole
negatywne 0.644/0.553 > 0.55 w obu torach) PASS. Sweep N∈{1,2,3,5,10,20}:
N=5 to zmierzony próg bezpieczny (N<5 degraduje zapytania 3-4), N=10 ma
2x margines — potwierdza domyślną wartość z planu zamiast przyjmować ją
z założenia. Kaskada nie poprawia jakości na 186-dok. korpusie (dystanse
identyczne z płaskim przy N≥5) — zgodnie z przewidywaniem planu: to test
architektury pod skalę mailową, nie optymalizacja pilota.
Decyzja: kaskada (N=10, k=5, claude-haiku-4-5) = domyślna ścieżka retrievalu.
Plan-doc §6.3 zaktualizowany wynikiem; §2 D3 zamknięte rozstrzygnięciem
Oskara (tor kompilacyjny=claude-haiku-4-5, gemma3:12b w odwodzie, decyzja
mailowa odłożona do reconu z flagą prywatności/kosztu).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>