Found independently by three journey PRs (#432 upload, #434 tutor, #437 quiz) and verified by the #432 review panel.
services/rag_service.py (_embed_query, _embed_documents_batch) and routes/documents.py::_index_document_chunks (~:1088–1109, incl. the catalog-relevance gate) construct raw google.genai.Clients directly — they predate the #391 seam (agents/_providers.py::model_for) and never consult SAPLING_MODEL_MODE. Consequences in function mode:
- one live
gemini-embedding-001 call per document upload (post-roll, fire-and-forget, except Exception swallowed) - one per quiz generate (RAG grounding)
- one per tutor turn when the course has a
course_code
Determinism is unaffected (failures are swallowed → empty results), but the 'hermetic' E2E lane silently bills when a real GEMINI_API_KEY is present. The pytest hermetic guard (#379) can't help — it's an autouse fixture, absent in the live uvicorn.
Fix direction: route embeddings through a seam-aware provider (mode-gated no-op or scripted vectors in non-real modes), or gate _index_document_chunks/_embed_query on _model_mode() == "real". Also relevant to the #354/#358 fresh-client sweep.
Interim mitigation used by the journeys: dummy GEMINI_API_KEY during verification runs.
Part of #402 follow-ups.
🤖 Generated with Claude Code
Found independently by three journey PRs (#432 upload, #434 tutor, #437 quiz) and verified by the #432 review panel.
services/rag_service.py(_embed_query,_embed_documents_batch) androutes/documents.py::_index_document_chunks(~:1088–1109, incl. the catalog-relevance gate) construct rawgoogle.genai.Clients directly — they predate the #391 seam (agents/_providers.py::model_for) and never consultSAPLING_MODEL_MODE. Consequences infunctionmode:gemini-embedding-001call per document upload (post-roll, fire-and-forget,except Exceptionswallowed)course_codeDeterminism is unaffected (failures are swallowed → empty results), but the 'hermetic' E2E lane silently bills when a real
GEMINI_API_KEYis present. The pytest hermetic guard (#379) can't help — it's an autouse fixture, absent in the live uvicorn.Fix direction: route embeddings through a seam-aware provider (mode-gated no-op or scripted vectors in non-real modes), or gate
_index_document_chunks/_embed_queryon_model_mode() == "real". Also relevant to the #354/#358 fresh-client sweep.Interim mitigation used by the journeys: dummy
GEMINI_API_KEYduring verification runs.Part of #402 follow-ups.
🤖 Generated with Claude Code