From 4834c6a0dc888ac8b9b9d0a6040caa7973196733 Mon Sep 17 00:00:00 2001 From: aaltshuler Date: Sun, 5 Jul 2026 05:08:26 +0300 Subject: [PATCH] fix(engine): warn when OMNIGRAPH_EMBEDDINGS_MOCK overrides an explicit provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mock flag's precedence over OMNIGRAPH_EMBED_PROVIDER is deliberate and stays (pinned by from_env_mock_flag_wins) — but the override was silent, and mock vectors are indistinguishable from real ones (correct dimension, unit norm, deterministic hash), so a leaked test env var silently poisoned persisted embeds (CLI) and query-time nearest() (server, for graphs without a bound cluster embedding profile). Emit a tracing::warn naming the overridden provider; document the precedence in the embeddings env-var table. Closes iss-embeddings-mock-override-silent. --- crates/omnigraph/src/embedding.rs | 18 ++++++++++++++++++ docs/user/search/embeddings.md | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/omnigraph/src/embedding.rs b/crates/omnigraph/src/embedding.rs index 9c8aba3f..c7f5c62b 100644 --- a/crates/omnigraph/src/embedding.rs +++ b/crates/omnigraph/src/embedding.rs @@ -70,6 +70,24 @@ impl EmbeddingConfig { /// 5. provider api-key env (`OPENROUTER_API_KEY`/`OPENAI_API_KEY`, or `GEMINI_API_KEY`). pub fn from_env() -> Result { if env_flag("OMNIGRAPH_EMBEDDINGS_MOCK") { + // The mock flag deliberately wins (pinned by + // from_env_mock_flag_wins) — but overriding an EXPLICITLY + // configured real provider must be loud: mock vectors are + // indistinguishable from real ones (correct dimension, unit + // norm), so a leaked test env var would otherwise silently + // poison persisted embeds and query-time nearest(). + if let Some(provider) = env_string("OMNIGRAPH_EMBED_PROVIDER") + && provider != "mock" + { + tracing::warn!( + target: "omnigraph::embedding", + overridden_provider = %provider, + "OMNIGRAPH_EMBEDDINGS_MOCK is set and overrides the \ + explicitly configured OMNIGRAPH_EMBED_PROVIDER — all \ + embeddings in this process are deterministic mock \ + vectors, not real ones" + ); + } return Ok(Self::mock()); } diff --git a/docs/user/search/embeddings.md b/docs/user/search/embeddings.md index 2f5a55e5..dd5065eb 100644 --- a/docs/user/search/embeddings.md +++ b/docs/user/search/embeddings.md @@ -61,7 +61,7 @@ Direct (`--store`) access, embedded callers, and the offline | `OMNIGRAPH_EMBED_DEADLINE_MS` | total wall-clock budget for one embed call across all retries (default `60000`; `0` = unbounded) | | `OMNIGRAPH_EMBED_TIMEOUT_MS` | per-request HTTP timeout (default `30000`) | | `OMNIGRAPH_EMBED_RETRY_ATTEMPTS` / `OMNIGRAPH_EMBED_RETRY_BACKOFF_MS` | retry policy (defaults `4` / `200`) | -| `OMNIGRAPH_EMBEDDINGS_MOCK` | set truthy to force the deterministic mock provider | +| `OMNIGRAPH_EMBEDDINGS_MOCK` | set truthy to force the deterministic mock provider. Takes precedence over an explicitly configured `OMNIGRAPH_EMBED_PROVIDER` — the override is logged as a warning (`omnigraph::embedding` target), since mock vectors are indistinguishable from real ones (correct dimension, unit norm) | The default zero-config path is OpenRouter: set `OPENROUTER_API_KEY` and run. Reaching Gemini takes `OMNIGRAPH_EMBED_PROVIDER=gemini` plus `GEMINI_API_KEY`.