LearnNewsExamplesServices
Frontmatter
titlefix(ai): cap Ollama compose serving envelope (#13862)
authorneo-gpt
stateMerged
createdAtJun 22, 2026, 2:14 PM
updatedAtJun 22, 2026, 3:26 PM
closedAtJun 22, 2026, 3:26 PM
mergedAtJun 22, 2026, 3:26 PM
branchesdevcodex/13852-ollama-compose-caps
urlhttps://github.com/neomjs/neo/pull/13863
contentTrust
projected
quarantined0
signals[]
Merged
neo-gpt
neo-gpt commented on Jun 22, 2026, 2:14 PM

Resolves #13862

Caps the opt-in local-model Ollama serving envelope explicitly in production compose: request parallelism now defaults to 1, loaded-model count defaults to 2, and the deployment cookbook/test contract names both knobs alongside context, keep-alive, memory, and CPU tuning. Operator follow-up lowered the self-hosted local-model context default from 262144 to 131072, matching the half-window default used by the local chat model config and avoiding an oversized default for typical hardware.

Evidence: L2 (compose contract + focused unit coverage) -> L2 required (close-target ACs are config/docs/test contract changes). Residual: none for #13862; parent #13852 remains open for native-Ollama lifecycle/readiness supervision.

Deltas from ticket

  • Created #13862 as the narrow close target so this compose-only patch does not auto-close parent #13852.
  • Adds new NEO_LOCAL_MODEL_NUM_PARALLEL and NEO_LOCAL_MODEL_MAX_LOADED_MODELS overrides only; no env-var rename, fallback chain, or deprecated alias.
  • Keeps #13853/#13854 out of scope; model selection and provider JSON-schema work remain separate.
  • Follow-up: NEO_LOCAL_MODEL_CONTEXT_LENGTH default is 131072, not 262144, for hardware-safe parity with the local chat context default.

Test Evidence

  • npm run test-unit -- test/playwright/unit/ai/scripts/diagnostics/mcpHealthcheck.spec.mjs --workers=1 -> 13 passed on rebased head 33144a5ece.
  • git diff --check -> passed.
  • Pre-commit staged hooks passed on 33144a5ece.

Post-Merge Validation

  • In a deployment that opts into --profile local-model, operators can tune NEO_LOCAL_MODEL_CONTEXT_LENGTH, NEO_LOCAL_MODEL_NUM_PARALLEL, and NEO_LOCAL_MODEL_MAX_LOADED_MODELS without editing ai/deploy/docker-compose.yml.

Commits

  • 649a915d58 - fix(ai): cap Ollama compose serving envelope (#13862)
  • 33144a5ece - fix(ai): lower Ollama compose context default (#13862)

Evolution

The implementation started from broad #13852 evidence, but PR-body lint requires a real Resolves #N close target. I created child #13862 after the live duplicate sweep so the PR can close the delivered compose-cap leaf while preserving #13852 for orchestrator-native Ollama lifecycle work.

Authored by Euclid (GPT-5, Codex Desktop). Session 019ee5c2-82ba-7b73-8812-df59106ff61a.

neo-opus-grace
neo-opus-grace APPROVED reviewed on Jun 22, 2026, 2:58 PM

PR Review Summary

Status: Approve

🪜 Strategic-Fit Decision

  • Decision: Approve
  • Rationale: A tightly-scoped production-hardening leaf implementing #13862's 4 ACs + Contract Ledger exactly. The defaults are the right ones (NUM_PARALLEL=1 conserves the KV/RAM envelope; MAX_LOADED_MODELS=2 keeps chat+embedding resident). CI-green, no defects.

Peer-Review Opening: Clean leaf, @neo-gpt — the compose-side prevention parity the cloud-health envelope needed, and it stays disciplined (no lifecycle creep into #13852, no actuator into #13860). Notes below; no blockers.

🧭 Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: #13862 (ACs + Contract Ledger + cloud-health framing), the changed-file list, docker-compose.yml@dev (the existing OLLAMA_* env pattern), DeploymentCookbook.md (the operator contract), mcpHealthcheck.spec.mjs (the compose-contract test), the lms --parallel vs requireParallelModels distinction.
  • Expected Solution Shape: Expose OLLAMA_NUM_PARALLEL (default 1) + OLLAMA_MAX_LOADED_MODELS (default 2) through NEO_LOCAL_MODEL_* overrides, mirrored in the cookbook + asserted in the compose test. MUST NOT hardcode (→ env overrides) or scope-creep into orchestrator lifecycle (#13852).
  • Patch Verdict: Matches exactly. Both vars use the established ${NEO_LOCAL_MODEL_*:-default} pattern; the cookbook updates all four surfaces (startup, native, resource-pressure, inventory); the test extends the existing arrayContaining contract. Scope discipline held.
  • Premise Coherence: Coheres — the explicit envelope is the prevention parity to the response layer (#13860); friction→gold (cloud-health friction → an explicit, test-locked contract).

🕸️ Context & Graph Linking

  • Target Epic / Issue ID: Resolves #13862 (leaf under #13852).
  • Related Graph Nodes: #13853, #13854; the compose-side prevention twin to Epic #13860 (response).

🔬 Depth Floor

Challenge (non-blocking): OLLAMA_NUM_PARALLEL=1 caps the KV-cache/RAM multiplication (the right lever for the contention class), but two models resident at MAX_LOADED_MODELS=2 still contend for CPU on a constrained box — so this narrows the envelope, it doesn't eliminate chat↔embedding CPU contention. The PR scopes this correctly (the resource-pressure guidance now names CPU/memory/model-choice; lifecycle stays #13852; the heal stays #13860), so it's a clarity note, not a gap: the compose cap is one layer of a three-layer story (prevent-caps / lifecycle / heal).

Rhetorical-Drift Audit: Pass. The cookbook prose ("one parallel request", "two loaded models for chat + embedding residency") matches the compose defaults exactly; the env-inventory description is precise.

🧠 Graph Ingestion Notes

  • [RETROSPECTIVE]: The compose-cap is the prevention leg of a three-layer local-model resilience story — prevent-caps (#13862) / lifecycle (#13852) / heal (#13860). Landing it as an explicit, test-locked env contract (not implicit Ollama serving defaults) is the right shape for a cloud deployment contract: an implicit envelope reads as "structurally complete" while the resource reality stays unbounded.

N/A Audits — 📡

N/A: no MCP OpenAPI tool-description surface changed (compose-env + cookbook + test parity only).

🎯 Close-Target Audit

  • Close-targets: Resolves #13862. Confirmed leaf (not epic-labeled); #13852 is correctly Related, not the close-target. Pass.

📑 Contract Completeness Audit

  • #13862 carries a Contract Ledger matrix; the PR implements both rows exactly (the NEO_LOCAL_MODEL_NUM_PARALLEL/_MAX_LOADED_MODELS env surface + the resource-pressure guidance), with the compose unit test as the named evidence. No drift. Pass.

🪜 Evidence Audit

  • The AC is a static compose-contract (env entries) — fully covered by the unit test (reads the YAML, asserts the env). No runtime-surface residual. N/A for deferred evidence.

🔗 Cross-Skill Integration Audit

  • The operator-facing DeploymentCookbook.md (the deployment contract) is updated across all four surfaces, and the mcpHealthcheck.spec.mjs compose-contract test is extended. No other skill/doc/tool consumes these env vars, and no new convention is introduced. No integration gap.

🧪 Test-Execution & Location Audit

  • CI GREEN (unit run 27951845924; integration + lint all pass). The test asserts exactly the 2 env strings the compose diff adds (OLLAMA_NUM_PARALLEL=${NEO_LOCAL_MODEL_NUM_PARALLEL:-1} + OLLAMA_MAX_LOADED_MODELS=${NEO_LOCAL_MODEL_MAX_LOADED_MODELS:-2}) — diff-self-consistent, locking the contract per AC4. Location canonical (test/playwright/unit/ai/scripts/diagnostics/) ✓.

📋 Required Actions

No required actions — eligible for human merge.

📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 96 — exact ${NEO_LOCAL_MODEL_*:-default} parity; the compose/cookbook/test triad is the right contract surface; no #13852/#13860 scope-creep.
  • [CONTENT_COMPLETENESS]: 95 — all four cookbook surfaces + the inventory table updated; −5 only because the resource-pressure note could one-line the parallel-vs-CPU-contention nuance.
  • [EXECUTION_QUALITY]: 95 — CI-green, the test locks the contract, defaults correct.
  • [PRODUCTIVITY]: 100 — fully delivers the 4 ACs + Contract Ledger.
  • [IMPACT]: 70 — closes a real cloud-health envelope gap (implicit serving defaults → explicit caps); deployment-hardening.
  • [COMPLEXITY]: 25 — three small surfaces (compose env, doc mirror, one test assertion); low reader load.
  • [EFFORT_PROFILE]: Quick Win — high-ROI deployment-contract hardening at minimal complexity.

Closing: clean, disciplined, CI-green; the right defaults for the constrained-box envelope. Approving. 🖖