Severity: HIGH (post-#1142 QC found four sibling sites + one wire-shape mismatch)
Status: FIXED in commit 8d51118 on release/v0.7.0. This issue is filed retroactively to provide the audit-trail for the fix per the prime directive (every defect surfaces a tracker entry).
Background
#1142 ported the AI_MEMORY_LLM_BACKEND env-aware resolver from src/daemon_runtime.rs:1746-1798 into the MCP stdio LLM-init at src/mcp/mod.rs:2148-2208. The narrow MCP-LLM symptom was fixed.
A QC pass against the binary at commit f5151201b (using codegraph_callers over OllamaClient::{new, new_with_url, from_env} + rg for production non-test sites) found four sibling code paths that still bypassed the env-aware resolver, plus one wire-shape mismatch in the MCP embed-client fallback:
Defects
src/cli/commands/atomise.rs::build_llm_curator — hardcoded OllamaClient::new(&tier_default_model). ai-memory atomise locked to local Ollama regardless of operator env.
src/cli/curator.rs::build_curator_llm — same hardcode. The ai-memory curator CLI (sweep / reflect / daemon modes) could not reach xAI / OpenAI / Anthropic / Gemini / etc.
src/daemon_runtime.rs::run_curator_daemon_with_primitives — legacy primitive-args entrypoint built the LLM directly from the ollama_model: Option<String> arg, ignoring AI_MEMORY_LLM_BACKEND.
src/mcp/mod.rs embed-client fallback — when embed_url == ollama_url (the default) and AI_MEMORY_LLM_BACKEND set to a non-Ollama vendor, the embed client did llm.clone(). That cloned an OpenAI-compatible chat client and used it for /api/embed requests, which either don't exist (xAI, Anthropic) or hit a different model namespace. Semantic recall silently fell back to keyword-only with no operator-visible warning.
Drive-by: src/handlers/kg.rs:593 was missing use crate::models::Memory at HEAD f5151201b, breaking cargo build --release. Fixed in the same commit per the prime directive (every gap surfaces a fix).
Resolution
Commit 8d511185f:
- New
OllamaClient::build_for_init(legacy_url, legacy_model) -> Result<Option<Self>> in src/llm.rs centralises the env-aware-then-legacy resolution rule. Behaviour mirrors daemon_runtime::build_llm_client's async wrapper.
- New
OllamaClient::is_ollama_native() -> bool introspector so embed-client fallback paths can refuse to clone an OpenAI-compatible chat client for embedding requests.
- All four bypass sites refactored to route through the env-aware path.
- MCP embed-client fallback rebuilds a dedicated Ollama-wire-shape client at the configured embed URL when the LLM is non-Ollama.
Tests
Six new regression tests in src/llm.rs::wiremock_tests::*_1143:
is_ollama_native_true_for_ollama_client_1143
is_ollama_native_false_for_openai_compatible_1143
build_for_init_legacy_arm_when_env_unset_1143
build_for_init_env_arm_routes_to_from_env_1143
build_for_init_env_arm_unknown_alias_errors_1143
build_for_init_env_arm_empty_string_falls_back_to_legacy_1143
All six pass. Full suite AI_MEMORY_NO_CONFIG=1 cargo test --release --lib: 4681/4681 GREEN.
Smoke evidence
$ AI_MEMORY_LLM_BACKEND=xai AI_MEMORY_LLM_API_KEY=$XAI_API_KEY \
AI_MEMORY_LLM_MODEL=grok-4.3 ai-memory mcp --tier autonomous --profile full
ai-memory: requested tier = autonomous
ai-memory: profile = 8 families (...); expected tool count = 73
ai-memory: LLM ready (backend=xai, model=grok-4.3)
ai-memory: LLM client is OpenAI-compatible (non-Ollama wire shape);
building dedicated Ollama embed client at http://localhost:11434 (#1143)
ai-memory: embedder loaded (nomic-embed-text-v1.5 (768-dim, Ollama))
ai-memory: atomisation engine ready (curator=LlmCurator)
ai-memory MCP server started (stdio, tier=autonomous)
The new (#1143) banner line confirms the wire-shape disambiguation is taking effect.
Gates
cargo fmt --check: GREEN
cargo clippy --release --lib -- -D warnings -D clippy::all -D clippy::pedantic: GREEN
AI_MEMORY_NO_CONFIG=1 cargo test --release --lib: GREEN (4681 passed, 0 failed)
Verified per prime directive pm-v3 (memory cd8ede94).
Severity: HIGH (post-#1142 QC found four sibling sites + one wire-shape mismatch)
Status: FIXED in commit 8d51118 on
release/v0.7.0. This issue is filed retroactively to provide the audit-trail for the fix per the prime directive (every defect surfaces a tracker entry).Background
#1142 ported the
AI_MEMORY_LLM_BACKENDenv-aware resolver fromsrc/daemon_runtime.rs:1746-1798into the MCP stdio LLM-init atsrc/mcp/mod.rs:2148-2208. The narrow MCP-LLM symptom was fixed.A QC pass against the binary at commit
f5151201b(usingcodegraph_callersoverOllamaClient::{new, new_with_url, from_env}+rgfor production non-test sites) found four sibling code paths that still bypassed the env-aware resolver, plus one wire-shape mismatch in the MCP embed-client fallback:Defects
src/cli/commands/atomise.rs::build_llm_curator— hardcodedOllamaClient::new(&tier_default_model).ai-memory atomiselocked to local Ollama regardless of operator env.src/cli/curator.rs::build_curator_llm— same hardcode. Theai-memory curatorCLI (sweep / reflect / daemon modes) could not reach xAI / OpenAI / Anthropic / Gemini / etc.src/daemon_runtime.rs::run_curator_daemon_with_primitives— legacy primitive-args entrypoint built the LLM directly from theollama_model: Option<String>arg, ignoringAI_MEMORY_LLM_BACKEND.src/mcp/mod.rsembed-client fallback — whenembed_url == ollama_url(the default) andAI_MEMORY_LLM_BACKENDset to a non-Ollama vendor, the embed client didllm.clone(). That cloned an OpenAI-compatible chat client and used it for/api/embedrequests, which either don't exist (xAI, Anthropic) or hit a different model namespace. Semantic recall silently fell back to keyword-only with no operator-visible warning.Drive-by:
src/handlers/kg.rs:593was missinguse crate::models::Memoryat HEADf5151201b, breakingcargo build --release. Fixed in the same commit per the prime directive (every gap surfaces a fix).Resolution
Commit
8d511185f:OllamaClient::build_for_init(legacy_url, legacy_model) -> Result<Option<Self>>insrc/llm.rscentralises the env-aware-then-legacy resolution rule. Behaviour mirrorsdaemon_runtime::build_llm_client's async wrapper.OllamaClient::is_ollama_native() -> boolintrospector so embed-client fallback paths can refuse to clone an OpenAI-compatible chat client for embedding requests.Tests
Six new regression tests in
src/llm.rs::wiremock_tests::*_1143:is_ollama_native_true_for_ollama_client_1143is_ollama_native_false_for_openai_compatible_1143build_for_init_legacy_arm_when_env_unset_1143build_for_init_env_arm_routes_to_from_env_1143build_for_init_env_arm_unknown_alias_errors_1143build_for_init_env_arm_empty_string_falls_back_to_legacy_1143All six pass. Full suite
AI_MEMORY_NO_CONFIG=1 cargo test --release --lib: 4681/4681 GREEN.Smoke evidence
The new
(#1143)banner line confirms the wire-shape disambiguation is taking effect.Gates
cargo fmt --check: GREENcargo clippy --release --lib -- -D warnings -D clippy::all -D clippy::pedantic: GREENAI_MEMORY_NO_CONFIG=1 cargo test --release --lib: GREEN (4681 passed, 0 failed)Verified per prime directive pm-v3 (memory
cd8ede94).