LearnNewsExamplesServices
Frontmatter
id17071
titleRoutine LMS readiness unloads residents on ambiguous metadata
stateClosed
labels
bugairegressionagent-os
assigneesneo-gpt-emmy
createdAtAug 13, 2026, 11:32 PM
updatedAtAug 14, 2026, 1:02 AM
githubUrlhttps://github.com/neomjs/neo/issues/17071
authorneo-gpt-emmy
commentsCount1
parentIssue14154
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 14, 2026, 1:02 AM

Routine LMS readiness unloads residents on ambiguous metadata

Closed Backlog/active-chunk-15 bugairegressionagent-os
neo-gpt-emmy
neo-gpt-emmy commented on Aug 13, 2026, 11:32 PM

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:

  1. lms unload <exact configured identifier>
  2. 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:

  1. 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.
  2. 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.
  3. The exact row is sufficient: perform no exact-resident mutation. Numeric-suffixed duplicate cleanup may run only after that sufficient witness.
  4. 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.
  5. 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.
  6. 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

  • Rejected or invalid lms ps performs zero unloads and zero loads and returns a named degraded/unknown-metadata diagnostic.
  • Partial/conflicting exact rows and missing/nonnumeric required context metadata perform zero mutations; parallel: null remains readiness-compatible for LM Studio roles that do not expose it, but it never supplies destructive shape proof when a parallel gate is configured.
  • Successful valid lms ps omission loads the exact configured LMS identifier without any preceding unload.
  • A positively observed context/parallel mismatch cannot authorize eviction from routine/cached metadata: a force-fresh, complete exact recheck must reproduce it immediately before replacement.
  • A mismatch that disappears or becomes incomplete on the force-fresh recheck performs zero mutations and degrades truthfully.
  • A reproduced complete mismatch retains the existing serialized exact replacement behavior.
  • Ollama identifiers never enter an LMS command.
  • lms load and lms unload receive bounded command deadlines; a never-settling child is killed and settled before the Promise rejects; the FIFO admits its next repair.
  • Mutation-capable unit tests inject their process seam; running the focused suites creates no real lms processes.
  • Live local acceptance after merge: both exact configured residents remain loaded with no TTL across concurrent chat + embedding traffic and at least three supervisor intervals; LM Studio records zero unproven exact-resident unloads.
  • The temporary local NEO_ORCHESTRATOR_LMS_ENABLED=false containment is removed only after that acceptance passes.

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

tobiu referenced in commit 28c90fd - "fix(ai): make LMS readiness evidence-bound (#17071) (#17075)" on Aug 14, 2026, 1:02 AM
tobiu closed this issue on Aug 14, 2026, 1:02 AM