Styles in nested subfolders that shared a base JSON name were being
overwritten because load_style keyed self.styles by the raw style["name"]
while the Style object stored the prefixed name. The extra networks page
iterates dict keys, so only one card per name surfaced.
Key the dict by the same prefixed name, and warn when a true duplicate
(same prefix and same name) is still detected.
NetworkOnDisk.fullname stripped only "/" from the post-lora_dir slice,
leaving a leading "\" on Windows. Every prompt typing the file's
natural dot-form name missed both registered aliases. On Linux,
dot-form lookup already missed when the file lived in any subfolder
because only the subfolder-prefixed form was registered.
- network.py: lstrip both separators and normalize backslashes to
forward slashes so fullname has one canonical shape per OS.
- lora_load.py: register a bare-basename-with-dots alias so typing
<lora:my.lora:1> resolves regardless of subfolder placement.
setdefault preserves explicit primary registrations on cross-subfolder
basename collisions.
Existing prompts using the legacy dots-to-underscores form continue
to resolve via entry.name unchanged.
modules/ui_extra_networks.py emits onclick="cardClicked(...)" on
every network card, but cardClicked was module-private in
ui/extraNetworks.ts and got tree-shaken out of the bundle. Attach
it to window like showCardDetails so card clicks resolve and the
<lora:...> insertion path works.
Replaces anima_lora.py's bespoke try_load_lora / group_keys /
resolve_network_key with thin wrappers binding native_loader's generics
to anima's prefix tuples and resolve_targets, mirroring flux2 / zimage /
chroma / ernie. The hand-rolled apply_lora_alphas bake-with-balance
pass goes away; alpha / scale / dora_scale flow through NetworkWeights.w
to NetworkModule.calc_scale at apply time.
native_loader gains an optional network_prefix kwarg (str or
Callable[[prefix_used], str], default "lora_transformer_") used when
constructing network_key. Anima passes a callable picking
lora_transformer_ / lora_llm_adapter_ / lora_te_ per matched prefix.
Single-component siblings keep the default and are unchanged.
network.NetworkModule.apply_weight_decompose grows a dual-path DoRA
convention detector. The pre-fix implementation only handled per-input
dora_scale (DoRA paper / kohya, shape (1, in)), silently broadcasting
per-output LyCORIS / PEFT dora_scale (shape (out, 1)) into an incoherent
element-wise rescaling. Detection is structural: (out, 1, ...) routes
to per-output; everything else (including the square-weight 1D ambiguity)
defaults to per-input for legacy compat. Pre-existing bug surfaced by
the LoKR+DoRA LyCORIS files Anima now loads.
Behavior changes:
- LoHA via the generic try_load_loha (NetworkModuleHada); covers
scenery-anima-base and any other LyCORIS .hada_w* export.
- Kohya lora_te_ prefix recognized. The legacy resolver only matched
BFL text_encoders.qwen3_06b.transformer.model. and silently dropped
lora_te_layers_N_* keys (41% of BlueArcStyle's bases were unloaded).
- LoKR+DoRA LyCORIS files now apply correctly; the per-output dora_scale
is honored instead of silently scrambled.
Adds test/test-anima-native-adapters.py: 37 offline tests across all
five prefixes (LoRA + LoHA), every COSMOS_2_FLAT_RENAME entry, DoRA
threading, marker disambiguation, try_load_chain dispatch, calc_updown
sanity, and both DoRA conventions (per-input / per-output / 1D ambiguous).
Adapter mock mirrors AnimaLLMAdapter's real module tree.