Stop the adapter report from claiming things that are not true

Independent review of the adapter resolution work found six defects, all
real and all fixed here.

A kind whose only candidates were rejected had no winning path, so its row
carried path=None and the rejected candidate fell into the shadow loop: the
report said "another adapter of this kind wins for the current mount" while
nothing won, and the real deferred reason was buried. A shadow row now
requires a winner and names it.

"loaded" was backed by a process-global record, so a fresh runtime with no
model still claimed a live adapter. The record is now held by the instance
that attached it, and the report keeps a weak reference: while the model
lives the row says loaded, once it is gone the row says available and
explains that the model is gone.

The sort key had lost the manifest's cartridge tag, which changed which
adapter loads on any machine holding a tagged library copy, and neither the
commit message nor the checklist said so. The tag is back as the middle key.

Proof checks resolved through the library while generation resolved through
the mount, so one proof payload could name two different copies. Both now
resolve the way generation does.

loaded_at was written and never read, so it is gone. The checklist claim that
peft is lazily imported in one place was true only for generation and is now
scoped that way.

The four generation paths and status() had no test coverage, so "no function
was lost" rested on reading. One test now walks the transformers prompt path
end to end with stub weights and asserts the generation answer carries the
adapter it attached.

pytest -q: 225 passed. ruff clean. mypy on the three touched source files:
2 errors, the identical 2 on a stashed HEAD tree, net zero. pyright: 2
errors, both the known qwen_vl_utils tuple artifact, unchanged from HEAD.
This commit is contained in:
ZacharyZhang-NY committed 2026-10-08 00:03:27 -04:00
1 parent 2fbb4af96b
commit 2d1cfdadc7
5 files changed
+128 -38

No files matched your search

+5 -3
View File
@@ -42,6 +42,7 @@ class QwenRuntime:
self.database = Database(self.settings)
self._processor: Any | None = None
self._model: Any | None = None
self._attached: adapters.LoadRecord | None = None
def _adapter_choice(self) -> tuple[adapters.AdapterSource | None, str]:
"""The adapter this runtime would attach, plus the reason if it would not attach one."""
@@ -50,7 +51,8 @@ class QwenRuntime:
return source, reason
def _loaded_adapter(self) -> adapters.LoadRecord | None:
return next((item for item in adapters.load_records() if item.kind == TrainingAdapterKind.hme_core_lora), None)
"""What this instance attached; another instance's model is not this one's claim."""
return self._attached
def _generation_adapter_fields(self) -> dict[str, str | None]:
record = self._loaded_adapter()
@@ -314,7 +316,7 @@ class QwenRuntime:
logger.info("generating without an adapter: %s", reason)
else:
model = adapters.load_into_model(model, source.path)
adapters.record_load(source)
self._attached = adapters.record_load(source, model)
model.eval()
self._model, self._processor = model, processor
return model, processor
@@ -345,7 +347,7 @@ class QwenRuntime:
def unload(self) -> None:
self._model = None
self._processor = None
adapters.clear_loads()
self._attached = None
try:
import torch