Resolves #13851
Related: #13874, #13923
Adds the missing post-load LM Studio readiness check: after ensureLmsModelsLoaded() reloads context-configured models, it now verifies observed lms ps --json metadata for loaded context length and configured chat parallel slots before declaring LMS ready. Plain presence-only readiness remains unchanged when no context/parallel gate is configured.
Evidence: L2 (mocked lms ps --json dispatch + focused provider-readiness unit coverage) plus a non-mutating live L3 readiness probe. The live probe confirms the corrected burn-source risk: current LM Studio reports text-embedding-qwen3-embedding-8b loaded at 8192 while Neo's config requires 32768, and the rebased helper flags that model as insufficient. Residual: operator may still run the issue's heavy-session digest / choke-sweep post-merge.
Deltas from ticket
- Uses the existing orchestrator task path through
buildLmsPreloadConfig() and ensureLmsModelsLoaded() instead of adding another orchestrator layer.
- Verifies the configured chat
--parallel slot count when present, preventing LM Studio's default multi-slot KV-cache split from satisfying readiness.
- Keeps
lms ps --json narrowly gated to LMS models with configured contextLengths or parallels, so deployments without context enforcement do not gain a new CLI dependency.
- Confirms the embedding-on-ingestion caveat from #13923 separately from the REM/chat retry-loop fix in #13922.
Contract Ledger
| Target Surface |
Source of Authority |
Behavior |
Evidence |
| LM Studio model readiness |
ai/services/graph/providerReadinessHelper.mjs |
Required LMS models with configured context/parallel gates must report observed loaded metadata that satisfies those gates before readiness is true. |
npm run test-unit -- test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs --workers=1 |
| Orchestrator LMS task |
ai/daemons/orchestrator/services/ConfiguredTaskDefinitionsService.mjs |
Existing post-spawn path passes contextLengths and parallels into ensureLmsModelsLoaded(). |
Source audit during implementation |
Test Evidence
node --check ai/services/graph/providerReadinessHelper.mjs
node --check test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs
npm run test-unit -- test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs --workers=1 - 47 passed
node --input-type=module -e '<live lms ps comparator>' - flagged text-embedding-qwen3-embedding-8b observed 8192 required 32768
npm run agent-preflight -- ai/services/graph/providerReadinessHelper.mjs test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs
node buildScripts/util/check-block-alignment.mjs ai/services/graph/providerReadinessHelper.mjs test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs
git diff --check origin/dev..HEAD
Post-Merge Validation
Authored by Euclid (GPT-5, Codex Desktop).
Resolves #13851
Related: #13874, #13923
Adds the missing post-load LM Studio readiness check: after
ensureLmsModelsLoaded()reloads context-configured models, it now verifies observedlms ps --jsonmetadata for loaded context length and configured chat parallel slots before declaring LMS ready. Plain presence-only readiness remains unchanged when no context/parallel gate is configured.Evidence: L2 (mocked
lms ps --jsondispatch + focused provider-readiness unit coverage) plus a non-mutating live L3 readiness probe. The live probe confirms the corrected burn-source risk: current LM Studio reportstext-embedding-qwen3-embedding-8bloaded at8192while Neo's config requires32768, and the rebased helper flags that model as insufficient. Residual: operator may still run the issue's heavy-session digest / choke-sweep post-merge.Deltas from ticket
buildLmsPreloadConfig()andensureLmsModelsLoaded()instead of adding another orchestrator layer.--parallelslot count when present, preventing LM Studio's default multi-slot KV-cache split from satisfying readiness.lms ps --jsonnarrowly gated to LMS models with configuredcontextLengthsorparallels, so deployments without context enforcement do not gain a new CLI dependency.Contract Ledger
ai/services/graph/providerReadinessHelper.mjsnpm run test-unit -- test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs --workers=1ai/daemons/orchestrator/services/ConfiguredTaskDefinitionsService.mjscontextLengthsandparallelsintoensureLmsModelsLoaded().Test Evidence
node --check ai/services/graph/providerReadinessHelper.mjsnode --check test/playwright/unit/ai/scripts/runners/runSandman.spec.mjsnpm run test-unit -- test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs --workers=1- 47 passednode --input-type=module -e '<live lms ps comparator>'- flaggedtext-embedding-qwen3-embedding-8bobserved8192required32768npm run agent-preflight -- ai/services/graph/providerReadinessHelper.mjs test/playwright/unit/ai/scripts/runners/runSandman.spec.mjsnode buildScripts/util/check-block-alignment.mjs ai/services/graph/providerReadinessHelper.mjs test/playwright/unit/ai/scripts/runners/runSandman.spec.mjsgit diff --check origin/dev..HEADPost-Merge Validation
lms unload gemma-4-31b-it && lms load gemma-4-31b-it --context-length 131072 --parallel 1, then verify the choke sweep stops failing at the former 4K boundary.Authored by Euclid (GPT-5, Codex Desktop).