These docs/plans/2026-03/04-*.md were untracked local notes from earlier sessions
that an over-broad 'git add -A' committed. Untrack them (kept on disk) to restore
the prior state; this session's 2026-06-22 design doc stays.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A real 3-LoRA merge (characters/concept, no style) oversaturated badly (energy
2.52x vs main's 1.02x): additive stacking is wrong for a balanced multi-LoRA blend.
The analyzer cannot tell 'preserve this style' from 'blend these characters' — both
are orthogonal — so additive must never be auto-selected; it has to be user intent.
- Revert _decide_prefix_mode: orthogonal groups blend by default again
(weighted_average / SLERP), exactly like main. No auto sum_preserve.
- Make the preserve flag a general overlay in _merge_diffs: blend the non-preserved
LoRAs with the chosen mode, then add each preserved LoRA's full delta on top
(works for weighted_average/slerp/ties; still exempt from sparsification + TIES
sign-election). Skip the exact-linear fast path when the stack has a preserve flag.
- Remove the standalone sum_preserve mode, its exact-linear handling,
_ORTHO_SUM_HEADROOM, and the sum+ report/legend/strategy-count display.
- Tests: SumPreserveMergeTests -> PrefixModeRoutingTests (asserts additive is never
auto-selected); add preserve-overlay-on-weighted_average tests. 299 pass.
- Docs (Merge-Algorithms, Tips) + design-doc postmortem updated; algo note reworded.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Real run showed the first cut didn't fix it by default: the applied config was
the 'full' strategy (SLERP, energy 1.22x), while the style-preserving sum_preserve
config (no_slerp/basic, energy 1.91x) ranked LOWER and wasn't applied. Cause: the
Phase-2 scorer (_score_merge_result) is effective_rank*0.4 + (1-norm_cv)*0.3 +
sparsity_fit*0.3 — no magnitude/energy term, and (1-norm_cv) rewards uniform norms,
which is exactly SLERP's magnitude-flattening. So the scorer structurally prefers
the style-flattening merge over the style-preserving one.
SLERP is strictly worse than sum_preserve for orthogonal groups anyway (it rotates
two independent directions into a 45-degree blend that loses both, vs keeping each
in its own subspace), so orthogonal non-opposing groups now use sum_preserve in ALL
strategy sets — the AutoTuner's top config preserves the style by default, no manual
selection. SLERP is retained for its real sweet spot: non-orthogonal, similar-
direction (cos ~0.25-0.5) low-conflict groups in the full set.
Tests: orthogonal/full -> sum_preserve; non-orthogonal-aligned/full -> slerp;
non-orthogonal-aligned/no_slerp -> weighted_average. 304 pass. Docs + algo note updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a 'preserve' toggle to LoRAStack and LoRAStackDynamic (advanced). A LoRA
tagged preserve=True is exempt from the two mechanisms that delete a style in a
conflict merge:
- sparsification (DARE/DELLA/conflict-aware): its diff is never trimmed/dropped
- TIES sign-election: instead of being zeroed where it holds the minority sign,
its full contribution is added on top of the TIES-merged content
Plumbed as a 6th stack-tuple field / dict key through _normalize_stack,
_merge_one_group -> _merge_diffs(preserve_flags=...), and the IS_CHANGED cache
keys + LoRAConflictEditor tuple rebuilds (so toggling it invalidates caches and
survives the editor). LoRAStackDynamic JS migration extended 8->9 widgets/slot
(preserve appended at each slot tail; legacy 7- and 8-slot saves re-padded).
The auto-strength exclusion from the design was descoped (single uniform scale is
baked into the linear path + group-cache replay; the reduction is mild/floor-bounded).
7 new tests (PreserveFlagTests); conflict-editor tuple test updated to 6-tuple; 302 pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per-prefix merging routes orthogonal groups to weighted_average, which divides
by Sum-of-weights and collapses each LoRA to a convex fraction. A style LoRA set
to strength 2 still lands below 1x its delta (s/(s+s') asymptotes to 1.0), so the
style vanishes while the heavier content LoRA survives -- confirmed against a real
Flux run (prodigy at 0.67x vs additive's 1.82x) and a deep-research wave.
Add 'sum_preserve': result = Sum(w_i d_i) at full strength, then a per-group energy
cap of headroom (1.5) x strongest single contribution. Two orthogonal LoRAs combine
to ~1.41x and pass through un-capped (style preserved); three equal ones hit ~1.73x
and scale back to 1.5x (no oversaturation). The cap is per-group and independent of
the global auto-strength floor, so it can't be defeated by the orthogonal-floor clamp
the way a raw weighted_sum flip would be.
Route orthogonal, non-opposing groups (no_slerp/basic strategy sets) to sum_preserve;
'full' keeps the video-tuned SLERP path. Opposing groups keep weighted_average.
Reuses the exact-linear fast path (folds the cap as a scalar from Pass-1 norms) so
full-rank Flux patches stay low-rank. Report/legend/strategy-counts updated.
11 new tests (SumPreserveMergeTests); 295 pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Anima is a 2B anime text-to-image DiT that reuses NVIDIA Cosmos-Predict2's
denoiser (split QKV, 28 blocks) with a Qwen3 text encoder + unique llm_adapter.
Verified key forms against live HF files (circlestone-labs/Anima model + real
LoRAs from deadman44/dummy9996).
- Detector 'anima' placed BEFORE ACE-Step/Wan/LTX (its blocks.N.self_attn.q_proj
+ Qwen3 lora_te_layers_N otherwise collide). Discriminators: unique llm_adapter,
Cosmos triple adaln_modulation_{self_attn,cross_attn,mlp}, GPT2 mlp.layer1/2,
{self_attn,cross_attn}.output_proj.
- Normalizer -> canonical diffusion_model.blocks.N.*: handles ComfyUI/diffusion-pipe
(passthrough), Kohya lora_unet_* (underscore->dot restore), diffusers
transformer_blocks.attn1/attn2.to_* (best effort). Split QKV, no fuse/refuse.
- dit preset; arch label 'Anima (Cosmos-Predict2 DiT)'. README + wiki updated.
- 7 tests (detection on all 3 forms + no ACE/Wan/LTX collision; normalization
convergence). 284 passing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extend the per-LoRA key_filter (LoRA Stack + Stack Dynamic) with audio_only and
no_audio, so audio-video models (LTX-2, ACE-Step) can route audio vs video layers
per LoRA without a new field. A layer is 'audio' when 'audio' appears in its LoRA
prefix or resolved model key (audio_embeddings_connector, audio_adaln_single,
audio_patchify_proj, audio_proj_out, av_ca_audio_*, per-block audio sublayers).
Applied at the same two filter sites as shared_only/unique_only. Use cases: merge
two LTX LoRAs keeping one's sound (others -> no_audio); audio LoRA + video LoRA
(audio_only + no_audio). Tests + README/wiki updated; 275 passing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-verified the 10 load-bearing claims with 2 adversarial votes each
(source-fidelity + independent refutation, 20 agents). 7 upheld, 3
disputed — all shipped code changes survive; disputes were attribution
errors, now corrected:
- Mean-source-norm calibration is from the Pico paper (arXiv 2604.16826
"Crowded in B-Space"), not KnOTS — corrected throughout
- k/D chance baseline + canonical-correlation identity are
first-principles facts (proven in-vote: Bjorck-Golub principal
angles; Haar-uniform expectation), not statements of the Pico paper
Appends an addendum with the full tally and the load-bearing caveats:
J1/J0 bias vanishes at rho=0 (MC-verified at 4M samples); the 0.239
multi-SLERP collapse figure was MergeKit's tangent-space multislerp
(Karcher change independently justified via Buss & Fillmore 2001);
stable rank <-> quality is non-monotone (CART bell curve, AdaRank) —
keep the one-sided cap, never maximize rank; DELLA epsilon-convention
difference between paper and official repo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
From the deep-research math validation (docs/research/2026-06-11-math-validation.md):
1. Excess conflict compared a magnitude-WEIGHTED mismatch ratio
(min(|a|,|b|) weights) against the UNWEIGHTED arccos(rho)/pi
expectation (Sheppard / degree-0 arc-cosine kernel). The two are not
the same statistic (Cho & Saul: J1 != J0 angular dependence), and for
correlated LoRAs mismatches concentrate on small-magnitude positions,
so the weighted ratio sat systematically below the baseline — real
conflict was under-detected (excess clamped to 0), biasing decisions
away from TIES. Now: unweighted mismatch fraction AND correlation
computed on the same noise-floored position set, baseline
arccos(rho_strong)/pi. Weighted ratio kept as a separate metric.
2. slerp mode for N>=3 diffs replaced iterative pairwise SLERP with a
weighted Karcher (Frechet) mean on the unit hypersphere (chordal-mean
init, log/exp-map iteration, existing norm correction). Iterative
multi-SLERP is order-dependent and collapses empirically (scores
below plain linear averaging at m=5; Karcher 0.610 vs multi-SLERP
0.239). N=2 keeps standard SLERP (the Karcher mean reduces to it).
Bump AUTOTUNER_ALGO_VERSION 1.7.0 -> 1.8.0 and ANALYSIS_CACHE_VERSION
1.7.1 -> 1.8.0 (pair metrics and merge behavior changed). Adds the full
cited validation report and 8 tests: identical/negated/independent
vectors give zero excess, count-concentrated conflict now detected
(old formula provably clamped it to 0), Karcher order-independence,
symmetric-direction, weight-pull, and N=2 SLERP regression (244 pass).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Wire the documented record_dataset option: new widget on the AutoTuner
node calls _save_tuner_dataset_entry after each full sweep (the
function existed, was tested, and was documented in the wiki — but
nothing ever called it). Wiki wording aligned: entries are recorded
on full sweeps only, cache/memory replays don't append.
- Merge-on-write for shared cache files: lora/pair/analysis cache saves
and the content-hash cache re-read the on-disk state and overlay the
caller's keys (caller wins; None never clobbers a real lora entry;
analysis entries are remapped to the caller's stack order first).
Entries are content-derived so same-key collisions hold equivalent
data — this removes cross-process lost updates without resorting to
cross-platform file locking. The GC's prune save passes merge=False
so dead keys aren't resurrected.
- Model/clip identity tracking via weakrefs (_track_model_identity):
bare id() comparison could alias a new object reusing a freed
object's address and serve a stale cached merge; the guard now also
detects clip swaps and id reuse. Shared by optimize_merge and
auto_tune.
- _extract_block_name is lru_cached (pure function, called per prefix
per smoothing pass with two regex evaluations) and drops its local
re import.
Adds 3 test classes (235 total pass).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When rerun_mode=True and rerun_source='original_progress', restrict the
shuffled combo list to hashes present in the original combo_progress.json
before iteration. Lets the backfill rerun replay exactly the combos that
were processed originally, ignoring any LoRAs added since and any combos
that were never run.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Runs the full local sweep and uploads the resulting config to the HF
community cache, but never replays HF cache hits. Intended for backfill
reruns that need to re-publish enriched configs without being
short-circuited by the existing cached (unenriched) entry.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Task 2: during rerun mode, check HF for a matching enriched config
(any candidate carries per_prefix_decisions); if found, mark the combo
complete and advance. Adds per-instance caches for the HF file list
and per-combo results so the extra traffic is bounded.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Small side plan: temporary BOOLEAN input on LoRACombinationGenerator that
routes progress tracking to combo_progress_rerun.json, enabling a full
re-run of the 400-combo collection to backfill per-prefix decisions
once Phase A of the estimator plan lands. To be reverted after use.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Task-by-task TDD plan for the case-based retrieval estimator. Covers
per-prefix decision capture (Phase A), feature extractor + index builder,
LoRAEstimator runtime, and the ComfyUI node surface.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
k-NN retrieval over HF community cache, emits tuner_data for the
existing optimizer replay path. Per-prefix instrumentation lands
first, dataset gets re-collected, estimator ships with both global
and per-prefix retrieval.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Node that exhaustively generates all 2/3-way LoRA combinations for
AutoTuner dataset collection. Uses seed-based deterministic shuffle
with lightweight completion tracking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The doc previously stated voice identity enters "exclusively" through
cross-attention, which was an inference not supported by any source.
Replace with the actual quote from the ACE-Step 1.5 paper and clarify
that voice info propagates through self-attention/MLP after injection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use actual node names (LoRA Stack, LoRA Optimizer, LoRA AutoTuner)
instead of nonexistent "ZImage LoRA Merger node". Broaden recommendations
to cover all ACE-Step LoRA merges, not just vocal + music.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add dedicated architecture support for ACE-Step music generation model LoRAs
with optimizations informed by the v1.5 hybrid attention architecture — cross-
attention is the primary voice-identity pathway (always global, attending to
timbre+lyric+text conditioning), while self-attention alternates sliding window
(local timbre) and global GQA (long-range structure).
Changes:
- New `acestep_dit` preset: wider orthogonal band (0.30), higher TIES threshold
(0.35), full magnitude preservation (floor 1.0) — biases toward SLERP over
TIES to prevent voice signal trimming in cross-attn layers
- Fix `to_out` → `o_proj` normalization bug (was producing `out_proj`)
- Add v1.0 detection and normalization (transformer_blocks, speaker_embedder,
lyric_encoder mapped to v1.5 canonical form)
- Refine WAN detection to exclude transformer_blocks (prevents v1.0 misdetect)
- Add `acestep_dit` to all architecture_preset UI dropdowns
- 25 new tests (detection, normalization, preset)
- Technical reference doc with architecture analysis and design rationale
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New page covers how it works, privacy model, setup, file structure,
score-based replacement, cache hit log examples, version compatibility,
and troubleshooting. Wired into sidebar and home page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the passive download_only option to encourage contribution.
Users who want community results need to also contribute back.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces dead record_dataset param with community_cache dropdown
(disabled / download_only / upload_and_download).
Downloads are anonymous via urllib; uploads require HF_TOKEN and
huggingface_hub. LoRA filenames are never shared — content hashes
(SHA256[:16]) are used as keys. Per-LoRA/pair conflict metrics and
winning merge configs are shared; network errors fall back silently to
the full local sweep.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add memory_mode, selection, output_mode to AutoTuner entries in Nodes.md
- Add output_mode, memory_mode, selection sections to Configuration-Guide
- Add AutoTuner Caching Infrastructure section covering all three cache types
(.memory.json, .analysis.json, .analysis.partial.json) and how to clear them
- Add 3 troubleshooting entries for cache-related issues in Tips-and-Troubleshooting
- Update speed tip to mention memory_mode=auto
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Task 4: guard min(participating) against empty set
- Task 5: add CPU path hit check before executor.submit
- Task 5/6: guard pair extraction with entry is not None
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5-task plan: parser, passthrough node, tree executor,
optimize_merge integration, and verification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hierarchical merge topology via text formula expression.
Users define merge order (e.g., "(1+2) + 3") to prevent
style LoRAs from being drowned out by character LoRA majority.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clean up README, wiki Nodes, How-It-Works, and maintainer sync docs
to reflect removal of calibration_data feature.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add educational SVG/PNG diagram explaining orthogonal vs conflicting vs
aligned LoRA relationships and when to change merge settings. Update all
README references to use new setting names (merge_refinement,
patch_compression, strategy_set, additive).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>