Context
The two same-day serialization repairs, #17051 / PR #17053 and #17054 / PR #17055, removed overlapping LM Studio readiness operations. After both merged and the canonical local host-edge runtime was rebuilt at 03035d1b2a4f791d600b1faea4d572c637dfa168, the configured chat model was still explicitly unloaded during live embedding work.
Live evidence on 2026-08-13:
- 23:19:25 local LM Studio logged
[Client=lms-cli][Endpoint=unloadModel] Unloading model: google/gemma-4-26b-a4b.
- The UI showed that exact configured chat resident in
UNLOADING while the configured embedding resident was computing.
- Both configured identifiers were correct and provider-specific: LM Studio used
google/gemma-4-26b-a4b and text-embedding-qwen3-embedding-8b; the Ollama identifiers were separate and were not passed to this path.
- A live falsifier returned four available model IDs from
/v1/models while lms ps --json returned exactly the two loaded residents. /v1/models is therefore a catalog/availability surface, not residency authority.
- 245 orphaned
lms load chat-model ... --identifier chat-model children with PPID 1 were present. Their fixture-shaped identifier is not proof of one originating test, but it is direct evidence that the current LMS CLI mutation path has no settlement bound and can outlive its caller.
- Containment disabled the host-edge LMS mutation task while keeping the current host-edge runtime active; both permanent exact residents then remained loaded.
An ordinary local embedding is about 0.87 seconds. An unload/reload costs more than 10 seconds and can cancel admitted work, so this is a correctness and throughput regression, not cache polish.
The Problem
ensureLmsModelsLoaded() currently combines two different evidence classes:
/v1/models: the models available through the OpenAI-compatible catalog;
lms ps --json: the models actually resident plus their runtime context/parallel metadata.
When lms ps fails or omits a trustworthy row, current code logs that it is “falling back to reload enforcement.” It can then derive exactResident from /v1/models, set shouldReplaceExact, and execute:
lms unload <exact configured identifier>
lms load <same model> --identifier <same identifier>
That residency inference is false. The existing unit test named unloads an exact resident gated model when initial lms ps fails encodes the destructive ambiguity as expected behavior.
The low-level loadLmsModel() and unloadLmsModel() wrappers also call execFile('lms', ...) without a timeout, hard-kill policy, or bounded child-settlement contract. A stuck LM Studio RPC can therefore strand a CLI process and permanently block the shared mutation FIFO.
The Architectural Reality
ai/services/graph/providerReadinessHelper.mjs owns LMS discovery plus every lms load and lms unload mutation.
ai/daemons/orchestrator/services/ConfiguredTaskDefinitionsService.mjs invokes the helper from the routine host-edge readiness hook.
- #17051 fixed the caller-local Promise latch.
- #17054 fixed same-process mutation serialization.
- Neither predecessor changed the destructive decision that turns untrusted residency metadata into exact-resident replacement.
- #14154 remains the broad residency/eviction parent. This ticket is the new implementation leaf; the resolved predecessors are not reopened.
Scoped structure-map receipt at filing:
ai/services/graph/providerReadinessHelper.mjs: 2,014 code LOC.
ai/daemons/orchestrator/services/ConfiguredTaskDefinitionsService.mjs: 184 code LOC.
- No new file or service is required.
The Fix
Implement one explicit residency state machine at the existing owner:
lms ps rejects, returns invalid JSON, conflicting exact rows, or an exact row whose required numeric context metadata is missing/invalid: metadata-unknown; perform zero mutations and return degraded.
- A successful, valid
lms ps observation omits the exact configured identifier: the model is positively not resident; load it with the stable provider-specific identifier, with no preceding unload.
- The exact row is sufficient: perform no exact-resident mutation. Numeric-suffixed duplicate cleanup may run only after that sufficient witness.
- The exact row is positively insufficient: routine cached telemetry is not eviction authority. Force a fresh exact metadata recheck immediately before replacement; replace only if the complete mismatch is reproduced inside the existing serialized mutation/authority boundary. Otherwise degrade with zero mutations.
- Give every
lms load and lms unload a bounded command deadline derived from the existing full readiness envelope, hard-kill timed-out children, and wait for settlement before releasing the FIFO.
- Every mutation-capable unit test injects the process seam; the focused suite must not launch a real
lms binary.
This is a surgical policy correction at the existing owner. It does not create another actuator, config leaf, daemon, lease, or residency abstraction.
Contract Ledger
| Observation |
Authority |
Mutation |
Result |
| probe rejected / invalid / partial exact row |
no trustworthy residency evidence |
none |
degraded metadata-unknown |
| successful valid probe, exact row absent |
positive non-residency evidence |
exact load only |
verify residency |
| exact complete row sufficient |
positive sufficient witness |
none for exact resident |
ready |
| exact complete row insufficient |
candidate mismatch only |
force-fresh recheck; replace only if reproduced |
repaired or degraded |
| bounded CLI timeout |
existing readiness envelope |
SIGKILL, then settle |
explicit failure; FIFO continues |
Decision Record impact
Aligned with ADR 0026. Observation remains separate from destructive recovery authority, and every intervention stays bounded. No ADR-0019 config change: this ticket adds no config leaf and does not move or re-derive existing provider identifiers.
Acceptance Criteria
Out of Scope
- Changing LM Studio JIT or TTL settings.
- Changing the selected chat or embedding models.
- Provider-lane/Ollama/container deployment work.
- Replacing the existing same-process FIFO from #17054.
- A new residency service, lease, or configuration subsystem.
- Attributing every historical orphan process to one test without process-start provenance.
Avoided Traps
- Do not treat
/v1/models as residency. It is a catalog/availability surface.
- Do not infer mismatch from missing telemetry. Unknown is non-authorizing.
- Do not give cached routine metadata eviction authority. A destructive repair requires the immediate force-fresh witness.
- Do not disable cold residency. A successful valid
lms ps omission still permits load-only repair.
- Do not fix this by swapping identifiers. Current live routing already uses the correct LMS identifiers; Ollama/LMS conflation is falsified for this event.
- Do not reopen #17051 or #17054. Both resolved their measured race boundaries; this is a linked successor.
Related
Live latest-open and A2A claim sweeps found no equivalent owner immediately before creation.
Retrieval Hint: LM Studio exact resident invalid metadata unload orphan lms cli child
Retrieval Hint: commits 920940e939, 2d2dc78c82, runtime 03035d1b2a
Context
The two same-day serialization repairs, #17051 / PR #17053 and #17054 / PR #17055, removed overlapping LM Studio readiness operations. After both merged and the canonical local host-edge runtime was rebuilt at
03035d1b2a4f791d600b1faea4d572c637dfa168, the configured chat model was still explicitly unloaded during live embedding work.Live evidence on 2026-08-13:
[Client=lms-cli][Endpoint=unloadModel] Unloading model: google/gemma-4-26b-a4b.UNLOADINGwhile the configured embedding resident was computing.google/gemma-4-26b-a4bandtext-embedding-qwen3-embedding-8b; the Ollama identifiers were separate and were not passed to this path./v1/modelswhilelms ps --jsonreturned exactly the two loaded residents./v1/modelsis therefore a catalog/availability surface, not residency authority.lms load chat-model ... --identifier chat-modelchildren with PPID 1 were present. Their fixture-shaped identifier is not proof of one originating test, but it is direct evidence that the current LMS CLI mutation path has no settlement bound and can outlive its caller.An ordinary local embedding is about 0.87 seconds. An unload/reload costs more than 10 seconds and can cancel admitted work, so this is a correctness and throughput regression, not cache polish.
The Problem
ensureLmsModelsLoaded()currently combines two different evidence classes:/v1/models: the models available through the OpenAI-compatible catalog;lms ps --json: the models actually resident plus their runtime context/parallel metadata.When
lms psfails or omits a trustworthy row, current code logs that it is “falling back to reload enforcement.” It can then deriveexactResidentfrom/v1/models, setshouldReplaceExact, and execute:lms unload <exact configured identifier>lms load <same model> --identifier <same identifier>That residency inference is false. The existing unit test named
unloads an exact resident gated model when initial lms ps failsencodes the destructive ambiguity as expected behavior.The low-level
loadLmsModel()andunloadLmsModel()wrappers also callexecFile('lms', ...)without a timeout, hard-kill policy, or bounded child-settlement contract. A stuck LM Studio RPC can therefore strand a CLI process and permanently block the shared mutation FIFO.The Architectural Reality
ai/services/graph/providerReadinessHelper.mjsowns LMS discovery plus everylms loadandlms unloadmutation.ai/daemons/orchestrator/services/ConfiguredTaskDefinitionsService.mjsinvokes the helper from the routine host-edge readiness hook.Scoped structure-map receipt at filing:
ai/services/graph/providerReadinessHelper.mjs: 2,014 code LOC.ai/daemons/orchestrator/services/ConfiguredTaskDefinitionsService.mjs: 184 code LOC.The Fix
Implement one explicit residency state machine at the existing owner:
lms psrejects, returns invalid JSON, conflicting exact rows, or an exact row whose required numeric context metadata is missing/invalid:metadata-unknown; perform zero mutations and return degraded.lms psobservation omits the exact configured identifier: the model is positively not resident; load it with the stable provider-specific identifier, with no preceding unload.lms loadandlms unloada bounded command deadline derived from the existing full readiness envelope, hard-kill timed-out children, and wait for settlement before releasing the FIFO.lmsbinary.This is a surgical policy correction at the existing owner. It does not create another actuator, config leaf, daemon, lease, or residency abstraction.
Contract Ledger
metadata-unknownSIGKILL, then settleDecision Record impact
Aligned with ADR 0026. Observation remains separate from destructive recovery authority, and every intervention stays bounded. No ADR-0019 config change: this ticket adds no config leaf and does not move or re-derive existing provider identifiers.
Acceptance Criteria
lms psperforms zero unloads and zero loads and returns a named degraded/unknown-metadata diagnostic.parallel: nullremains readiness-compatible for LM Studio roles that do not expose it, but it never supplies destructive shape proof when a parallel gate is configured.lms psomission loads the exact configured LMS identifier without any preceding unload.lms loadandlms unloadreceive bounded command deadlines; a never-settling child is killed and settled before the Promise rejects; the FIFO admits its next repair.lmsprocesses.NEO_ORCHESTRATOR_LMS_ENABLED=falsecontainment is removed only after that acceptance passes.Out of Scope
Avoided Traps
/v1/modelsas residency. It is a catalog/availability surface.lms psomission still permits load-only repair.Related
Live latest-open and A2A claim sweeps found no equivalent owner immediately before creation.
Retrieval Hint:
LM Studio exact resident invalid metadata unload orphan lms cli childRetrieval Hint: commits920940e939,2d2dc78c82, runtime03035d1b2a