Context
The native Ollama default was switched to gemma4:26b by the repo-local parity work, but the runtime convergence story still has a gap. #13852 covers the broader local-dev native-Ollama serving lifecycle and the heavy-session proof. This ticket isolates the narrower model-switch residue: when the configured Ollama chat model changes, readiness should converge the actually required resident set, report missing configured tags precisely, and avoid treating stale resident models as capacity success.
Release classification: post-release hardening. This is a follow-up to already-merged repo-local parity work and is not a release blocker by itself; #13852 remains the parent live-proof lane.
Live latest-open sweep: checked latest 20 open issues at 2026-06-22T21:54Z. Closest related tickets were #13852 (native Ollama lifecycle/live proof), #13854 (Ollama/cloud chat-model parity parent), #13855 (native gemma4:26b default + schema slice), #13865 (context-aware Ollama readiness), and #13867 (orchestrator-owned ollama serve). No equivalent model-switch/stale-residency convergence leaf was present. A2A in-flight sweep over latest 30 messages at 2026-06-22T21:54Z found only existing lifecycle updates and no competing claim.
The Problem
The current readiness path can warm required native-Ollama models when they are installed, and it can verify resident context_length. It does not yet fully express model-switch convergence:
- If the configured chat model is
gemma4:26b but the host only has the old dense gemma4:31b, readiness does not install/pull the required tag; the warmup fails with Ollama HTTP 404.
- Non-required resident models remain loaded. This is expected if we intentionally treat Ollama as shared infrastructure, but the readiness envelope currently counts
observedCount and warning text in a way that can make stale resident models look like capacity progress.
- There is no explicit unload/eject policy for stale non-required models after a config switch. That may be correct for shared local infrastructure, but it needs a deliberate contract: either unload them, mark them as
extraModels, or exclude them from capacity-readiness calculations and warnings.
Empirical probe from this session:
- Started temporary
ollama serve on 127.0.0.1:11434.
- Warmed
qwen3-embedding:latest as a non-required resident model at num_ctx=4096, keep_alive=-1.
- Ran
ensureOllamaModelsReady() for configured chat role gemma4:26b, num_ctx=8192, requireParallelModels=1, allowPartial=true.
- Result:
failedModels[0].error = "Ollama chat model warmup failed for 'gemma4:26b': HTTP 404 - {\"error\":\"model 'gemma4:26b' not found\"}", missingModels:["gemma4:26b"], availableModels:["qwen3-embedding:latest"], and the stale non-required embedding model remained loaded afterward.
Memory-mining hits: prior same-day memories 8c41698e-bd99-474b-add6-f7420a18d73f (bounded readiness probe), 74a4ae8b-31cb-4cc2-b378-eba268e29e62 (gemma4:26b is the native Ollama MoE tag), and Grace model-choice memories 492f9393-b59c-4431-824b-38e2ae1251ca / b85293e3-f5a6-401f-9135-a4abbba7b645 (dense 31B was the wrong model; MoE is the target).
The Architectural Reality
Relevant surfaces:
ai/config.template.mjs: aiConfig.ollama.model defaults to gemma4:26b via NEO_OLLAMA_MODEL.
ai/services/graph/providerReadinessHelper.mjs: buildOllamaReadinessConfig() derives role-specific required models; ensureOllamaModelsReady() warms missing or under-context models through /api/chat or /api/embed; warning text comes from createParallelModelCapacityWarning().
ai/daemons/orchestrator/taskDefinitions.mjs: buildOllamaServeEnv() sets OLLAMA_CONTEXT_LENGTH, OLLAMA_KEEP_ALIVE, and OLLAMA_MAX_LOADED_MODELS for orchestrator-owned ollama serve.
ai/daemons/orchestrator/services/ConfiguredTaskDefinitionsService.mjs: wires the orchestrator-owned Ollama task, liveness probe, and post-spawn readiness.
Ollama is shared local infrastructure. That makes blind unloading risky, because an operator or another process may intentionally keep extra models resident. The fix should first make the readiness contract truthful, then decide whether managed-task-owned stale models can be safely unloaded.
The Fix
- Add explicit
extraModels / staleModels reporting to native Ollama readiness: resident models not in the required set must be visible separately from required resident models.
- Compute readiness capacity from required resident models, not total observed resident models. A stale non-required model must not satisfy
requireParallelModels.
- Improve warnings for missing configured tags: tell the operator to
ollama pull gemma4:26b (or equivalent configured tag), rather than only suggesting OLLAMA_MAX_LOADED_MODELS.
- Decide and implement the unload/eject policy:
- conservative option: do not unload shared Ollama models; report stale extras only;
- managed-task option: unload only models the orchestrator previously loaded and no longer requires, with tests proving shared resident models are preserved.
- Add focused unit coverage for missing configured chat model + stale extra resident model.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
ensureOllamaModelsReady() result envelope |
providerReadinessHelper.mjs |
Report required, missing, insufficient-context, and extra resident models separately |
Existing degraded envelope remains backward-compatible |
JSDoc update |
Unit test with stale extra + missing configured model |
createParallelModelCapacityWarning() |
providerReadinessHelper.mjs |
Warning distinguishes missing configured tag from loaded-but-extra resident models |
Existing warning stays for non-Ollama providers |
JSDoc/update inline text |
Unit test for warning text |
| Orchestrator-owned Ollama readiness |
ConfiguredTaskDefinitionsService.mjs + task definitions |
Liveness/postSpawn do not treat stale extras as readiness success |
allowPartial remains degraded, not fatal, when operator action is needed |
Existing task JSDoc |
Focused orchestrator/service test if behavior changes |
Decision Record impact
aligned-with ADR 0019. This keeps config values resolved at the use site and does not add a second config source.
Acceptance Criteria
Out of Scope
- The heavy-session tri-vector proof for #13852.
- Cloud benchmark evidence for #13854.
- Changing the already-merged native Ollama default model from
gemma4:26b.
- Pulling large models during CI.
Avoided Traps
- Do not count total resident Ollama models as readiness when the resident model is not in the required configured set.
- Do not blindly unload models from a shared local Ollama server without ownership evidence.
- Do not re-open the
gemma4:26b model-choice decision; this ticket is runtime convergence after that decision.
Related
- Parent runtime proof: #13852.
- Model parity parent: #13854.
- Native Ollama default/schema leaf: #13855 / PR #13856.
- Native Ollama readiness/context leaf: #13865.
- Orchestrator-owned Ollama serve leaf: #13867 / PR #13868.
Origin Session ID: db5b2ecf-db91-4b7d-9498-ccef00426a1c
Handoff Retrieval Hints: Ollama readiness stale resident model gemma4:26b missing configured tag, ensureOllamaModelsReady extraModels staleModels, OLLAMA_MAX_LOADED_MODELS warning required resident models
Context
The native Ollama default was switched to
gemma4:26bby the repo-local parity work, but the runtime convergence story still has a gap. #13852 covers the broader local-dev native-Ollama serving lifecycle and the heavy-session proof. This ticket isolates the narrower model-switch residue: when the configured Ollama chat model changes, readiness should converge the actually required resident set, report missing configured tags precisely, and avoid treating stale resident models as capacity success.Release classification: post-release hardening. This is a follow-up to already-merged repo-local parity work and is not a release blocker by itself; #13852 remains the parent live-proof lane.
Live latest-open sweep: checked latest 20 open issues at 2026-06-22T21:54Z. Closest related tickets were #13852 (native Ollama lifecycle/live proof), #13854 (Ollama/cloud chat-model parity parent), #13855 (native
gemma4:26bdefault + schema slice), #13865 (context-aware Ollama readiness), and #13867 (orchestrator-ownedollama serve). No equivalent model-switch/stale-residency convergence leaf was present. A2A in-flight sweep over latest 30 messages at 2026-06-22T21:54Z found only existing lifecycle updates and no competing claim.The Problem
The current readiness path can warm required native-Ollama models when they are installed, and it can verify resident
context_length. It does not yet fully express model-switch convergence:gemma4:26bbut the host only has the old densegemma4:31b, readiness does not install/pull the required tag; the warmup fails with OllamaHTTP 404.observedCountand warning text in a way that can make stale resident models look like capacity progress.extraModels, or exclude them from capacity-readiness calculations and warnings.Empirical probe from this session:
ollama serveon127.0.0.1:11434.qwen3-embedding:latestas a non-required resident model atnum_ctx=4096,keep_alive=-1.ensureOllamaModelsReady()for configured chat rolegemma4:26b,num_ctx=8192,requireParallelModels=1,allowPartial=true.failedModels[0].error = "Ollama chat model warmup failed for 'gemma4:26b': HTTP 404 - {\"error\":\"model 'gemma4:26b' not found\"}",missingModels:["gemma4:26b"],availableModels:["qwen3-embedding:latest"], and the stale non-required embedding model remained loaded afterward.Memory-mining hits: prior same-day memories
8c41698e-bd99-474b-add6-f7420a18d73f(bounded readiness probe),74a4ae8b-31cb-4cc2-b378-eba268e29e62(gemma4:26bis the native Ollama MoE tag), and Grace model-choice memories492f9393-b59c-4431-824b-38e2ae1251ca/b85293e3-f5a6-401f-9135-a4abbba7b645(dense 31B was the wrong model; MoE is the target).The Architectural Reality
Relevant surfaces:
ai/config.template.mjs:aiConfig.ollama.modeldefaults togemma4:26bviaNEO_OLLAMA_MODEL.ai/services/graph/providerReadinessHelper.mjs:buildOllamaReadinessConfig()derives role-specific required models;ensureOllamaModelsReady()warms missing or under-context models through/api/chator/api/embed; warning text comes fromcreateParallelModelCapacityWarning().ai/daemons/orchestrator/taskDefinitions.mjs:buildOllamaServeEnv()setsOLLAMA_CONTEXT_LENGTH,OLLAMA_KEEP_ALIVE, andOLLAMA_MAX_LOADED_MODELSfor orchestrator-ownedollama serve.ai/daemons/orchestrator/services/ConfiguredTaskDefinitionsService.mjs: wires the orchestrator-owned Ollama task, liveness probe, and post-spawn readiness.Ollama is shared local infrastructure. That makes blind unloading risky, because an operator or another process may intentionally keep extra models resident. The fix should first make the readiness contract truthful, then decide whether managed-task-owned stale models can be safely unloaded.
The Fix
extraModels/staleModelsreporting to native Ollama readiness: resident models not in the required set must be visible separately from required resident models.requireParallelModels.ollama pull gemma4:26b(or equivalent configured tag), rather than only suggestingOLLAMA_MAX_LOADED_MODELS.Contract Ledger Matrix
ensureOllamaModelsReady()result envelopeproviderReadinessHelper.mjscreateParallelModelCapacityWarning()providerReadinessHelper.mjsConfiguredTaskDefinitionsService.mjs+ task definitionsallowPartialremains degraded, not fatal, when operator action is neededDecision Record impact
aligned-with ADR 0019. This keeps config values resolved at the use site and does not add a second config source.
Acceptance Criteria
requireParallelModels/ capacity readiness is computed from required resident models, not total resident model count.ollama pull gemma4:26b.Out of Scope
gemma4:26b.Avoided Traps
gemma4:26bmodel-choice decision; this ticket is runtime convergence after that decision.Related
Origin Session ID: db5b2ecf-db91-4b7d-9498-ccef00426a1c
Handoff Retrieval Hints:
Ollama readiness stale resident model gemma4:26b missing configured tag,ensureOllamaModelsReady extraModels staleModels,OLLAMA_MAX_LOADED_MODELS warning required resident models