Skip to content

record(LTX25-PROMPT-ADALN): the prompt-AdaLN defect was understated ~138x, and the keyframes claim next door was false (#644) - #663

Open
localai-bot wants to merge 6 commits into
mainfrom
row/LTX25-ADALN-CLAIMS
Open

record(LTX25-PROMPT-ADALN): the prompt-AdaLN defect was understated ~138x, and the keyframes claim next door was false (#644)#663
localai-bot wants to merge 6 commits into
mainfrom
row/LTX25-ADALN-CLAIMS

Conversation

@localai-bot

@localai-bot localai-bot commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Claims-and-records repair for #644, on top of #654. The port itself is untouched
— reviewed PASS, and nothing executable changes here except three refusal
messages.

F1 — the headline numbers were fixture artifacts, and the truth is far worse

The spec Outcome, #654's body and tests/vllm/models/test_ltx2.cpp all quoted
51.7% ("term vs table") and 5.82% (block-0 K/V) as the answer to "does
this matter". Both come from the generator's synthetic init: the static
prompt_scale_shift_table and every prompt-AdaLN MLP parameter are drawn
from the same param_spec rule at scale=0.05
(scripts/gen-ltx2-goldens.py:100-106), so the ratio between them is a property
of the FIXTURE — it moves with the init scale (0.005 → 4.1%, 0.2 → 1450%). The
Outcome disclaimed only the two OUTPUT rows as synthetic-bounded and then called
the other two the answer, though all four have identical provenance.

Re-measured here on the shipped weights, through upstream's own
AdaLayerNormSingle(dim, embedding_coefficient=2) evaluated on sigma * 1000
exactly as transformer_args.py:274-278 / :177 do, against all 48
prompt_scale_shift_table / audio_prompt_scale_shift_table tensors of
/mnt/nas_share/checkpoints/ltx-2.5/lightricks-ltx-2.5/diffusion_models/ltx-2.5-22b-distilled-transformer-nvfp4.safetensors,
with ltx_core at fd4ded7f imported by path and its __file__ asserted:

video (4096) audio (2048)
rms|table|, 48 blocks 0.017553 0.021925
rms|term|, uniform σ∈[0,1] 0.236446 0.347171
term/table, RMS 1347% 1583%
max|term| / max|table| 7119% 2817%
term/table RMS, the file's own LinearQuadratic sampler, 8 steps 1275% 1492%

Like for like — the fixture ratio is max-vs-max and so is the shipped one —
per stream, each against its OWN fixture denominator:

fixture max|term|/max|table| shipped understatement
video (prompt_adaln_single vs prompt_scale_shift_table) 51.7% 7119% 138x
audio (audio_prompt_adaln_single vs audio_prompt_scale_shift_table) 40.6% 2817% 69x

Corrected 2026-08-13 (review finding F-2). This read "138x (video) and 54x
(audio)"
as if both were per-stream. The video figure is right and
like-for-like. The audio one divided the shipped AUDIO ratio by the VIDEO
fixture denominator, because gen-ltx2-goldens.py emits exactly one fixture
ratio and it is the video stream's. 54x is literally true about that single
published figure and errs CONSERVATIVE. The audio stream's own fixture ratio,
recomputed with the identical statistic on the identical fixture (the generator
is imported, so no weight is re-drawn), is 40.6%max|term| 0.0201763 vs
max|table| 0.0496868 — giving 2817 / 40.6 = 69x. Video re-derived in the
same run: 0.0252012 / 0.0487142 = 51.7327%, and 7119 / 51.73 = 137.6.

Fixed at the source. The generator emitted BOTH video-only rows unlabelled
— "timestep term vs static table" and "block 0 modulated prompt K/V" — which is
how a video denominator came to be applied to an audio numerator.
gen-ltx2-goldens.py now names the stream on both and ltx2_goldens.inc was
regenerated against ltx_core fd4ded7f (REGEN_EXIT=0); the diff is
those two comment lines and nothing else, every golden VALUE byte-identical,
the Regenerate with: header unchanged because the committed command was re-run
verbatim. test_ltx2.cpp and the spec's gate-floor table say the same.

On the shipped model the timestep term DOMINATES the static
table; the table is the perturbation. Pre-row renders applied
context*(1 + ~0.018 rms) + ~0.018 where upstream applies
context*(1 + ~0.32 rms) + ~0.10; stated as the quantity actually consumed at
transformer.py:446, on a unit-rms context the modulated context moves +8.8%
(video) and +31.3% (audio).

Both dispositions the finding offered are taken. The four fixture rows are
now labelled GATE-FLOOR numbers from synthetic weights — in the spec, in the
goldens' emitted comment block, and in test_ltx2.cppand the
real-checkpoint measurement is stated as the answer to "does this matter".
Labelling alone would have left the spec with no answer to its own §6 question;
stating the real numbers alone would have left four unlabelled fixture ratios in
three files for someone to re-quote.

scripts/measure-ltx2-prompt-adaln.py is committed so the number is re-runnable
rather than transcribed.

F2 — a false claim about a checkpoint, the same class this row just fixed

ltx2.h:47-49, a line surviving inside the paragraph #654 rewrote, said "LTX-2.5's
checkpoint does not carry the parameter"
about keyframes_abs_pos_embedding.
Verified independently against both files' headers and upstream's own loader:

FP8 (vonkaiser) NVFP4 (first-party)
carries the tensor YESF8_E4M3 [1, 4096] + F32 scale no
declares the flag no __metadata__ AT ALL true
LTXModelConfigurator.from_metadata RAISES KeyError: 'caption_channels' builds it, [1, 4096]

Two corrections to the reasoning that came with the finding, both measured:

  • The FP8 file does not "resolve the flag False at
    model_configurator.py:82". Upstream never reaches line 82 on it —
    _build_caption_projections indexes caption_channels on the empty config
    first and raises. That file ships no config at all, so what its flag resolves
    to is decided entirely out of band, and the tensor it carries is trained.
  • On the NVFP4 file the flag IS on and the module IS built, but the tensor is
    absent — 0 of its 7876 entries match keyframes_abs_pos. What that leaves is
    an UNMATERIALISED META PARAMETER, not a silent zero.

Corrected 2026-08-13 (review finding F-1, the blocking one). This bullet
said the parameter "keeps torch.zeros(1, inner_dim) (model.py:217-219)
through load_state_dict(..., strict=False)
(loader/single_gpu_model_builder.py:98) — a genuine no-op there"
. It is not
a no-op.
It quoted that line while dropping the assign=True that is ON THE
SAME LINE, and upstream builds on the meta deviceloader/helpers.py:84-95,
create_meta_model: with torch.device("meta"): configurator.from_metadata(...)
at :90-91. A key absent from the state dict is never materialised at all. The
row exists to delete a claim asserted with anchors and never checked, and it
replaced it with a claim whose anchors were read but not executed — in
include/, the product tree.

Run here through upstream's own create_meta_model on the shipped file's real
__metadata__ (read with upstream's own read_model_metadata /
SafetensorsModelStateDictLoader, which JSON-decodes each value,
sft_loader.py:58-74 — the flag lives at config.transformer, not at the top
level, which is why a raw __metadata__ read returns None for it):

config.transformer['use_keyframes_abs_pos_embedding'] = True
keyframes_abs_pos_embedding: shape=(1, 4096) dtype=torch.float32 device=meta is_meta=True
supports_keyframes_abs_pos_embedding (BEFORE load) : False
after load_state_dict(sd, strict=False, assign=True):
  neighbour patchify_proj.weight : device=cpu is_meta=False   <- materialised
  keyframes_abs_pos_embedding    : device=meta is_meta=True
  in missing_keys                : True
  reading the value RAISES       : RuntimeError: Tensor.item() cannot be called on meta tensors
supports_keyframes_abs_pos_embedding (AFTER load)  : False

Upstream says so itself, and then never asks.
supports_keyframes_abs_pos_embedding (model.py:166-173) returns False for
"a model whose config set the flag but whose checkpoint carried no weight for it
(the parameter would still be on meta)" (:170), and
enable_keyframes_abs_pos_embedding (model.py:175-200) exists because such a
parameter "would fail at the first forward" (:182). Both are defined and
never called
— one grep -rn hit each across the whole Lightricks/LTX-2
checkout at fd4ded7f, the definition itself, re-confirmed here with a positive
control rather than transcribed.

Polarity is not what fails. apply_keyframes_absolute_embedding is
hidden_states + mask * embedding (transformer_args.py:23-43, the sum at
:43), so real zeros would be inert. The mechanism claim fails on meta,
not on additivity.

This STRENGTHENS the conclusion and changes nothing downstream. The refusal
stays keyed on tensor presence for the FP8 file, and the NVFP4 file is refused by
FLAG in ParseLtx2DitParams (ltx2.cpp:192-198) — where upstream, had it
loaded, would carry a parameter its own guard reports as unsupported.

Confirmed too that it is not keyframe-only: transformer_args.py:269 applies it
on every prepare whose keyframes_mask is set, and tools.py:186-196 sets
that mask unconditionally on the first latent frame.

Refusal keying: UNCHANGED, deliberately. RefuseUnported fires on the
TENSORS the file carries. Keying it on the resolved flag would, on the FP8 DiT,
read a DEFAULT rather than the file — that file declares nothing — and load it
while silently discarding a trained [1, 4096] parameter. Tensor presence is the
only signal that file actually carries. No behaviour changed, so no new gate is
owed; three refusal MESSAGES changed, because they asserted an implication that
is false in both directions.

F3 — records the lifecycle change did not move

  • .agents/model-matrix.md still listed "timestep-INDEPENDENT prompt K/V
    (cacheable once per request)"
    — precisely what the row disproved.
  • docs/STATUS.md did not mention the prompt-side AdaLN. Added inside the
    SHRINK-ONLY ratchet: the cell went 218 → 217 chars and
    check-public-doc-tables.py stays green at oversized_cells: 44.
  • docs/FEATURES.md and docs/USAGE.md described the keyframes opt-in as if one
    file were involved; both DiTs need it, for different reasons.

One finding detail did not hold. It cited .agents/model-matrix.md:98 as
already saying the two DiTs "differ in a TRAINED keyframes_abs_pos_embedding".
grep -n keyframes .agents/model-matrix.md returns nothing on this branch. The
corroborating anchors are .agents/specs/ltx-2-5.md §3.1 and
tests/vllm/multimodal/test_ltx2_video.cpp:913-914.

The two LOW notes, recorded honestly

  • test_ltx2_video's shipped-checkpoint case is env-gated on
    LTX2_CHECKPOINT_ROOT and SKIPS by default, so "unchanged 30/502" meant the
    whole real-header case did not run. With the variable set the same binary
    measures 30 / 8734 — verified here, exit 0 both ways. Recorded in the spec's
    gate table and at the skip site, so the next quote carries its configuration.
    Now also filed as #673:
    LTX2_CHECKPOINT_ROOT is set by no workflowgrep -rn CHECKPOINT_ROOT .github/ exits 1 with zero hits while the same pattern matches in tests/ and
    .agents/ (positive control in the same command) — so CI executes 502 of 8734
    assertions, 5.7%
    , at an unchanged case count of 30, and
    scripts/measure-ltx2-prompt-adaln.py is a manual tool no gate invokes. This
    row's checkpoint-derived evidence is therefore manual and host-local.
    Recorded as visible debt; wiring checkpoints into CI is explicitly not in scope
    here.
  • Upstream loads with strict=False, assign=True
    (single_gpu_model_builder.py:98 — quoted in full, because dropping the
    assign=True is exactly what made the keyframes claim above wrong), so a
    config declaring the prompt-AdaLN flag false over a file that carries the
    module would silently run flag-OFF upstream where we now refuse. Ours is
    better; it is a documented divergence, not a mirror, and is named as one
    alongside the tensor-keyed keyframes refusal.

F4 — the branch was behind, and inherited a red it did not cause

check-device-leakage FAILED on the head: kcuda=2 > baseline 0, both hits in
src/vllm/multimodal/ltx2_video.cpp:532,549 — a file this diff does not touch,
present at the parent 968461cda and already fixed on main by 11cc1d589.
Merging origin/main is the whole repair; no edit of mine was needed and none was
made. Before: FAIL, kcuda=2. After: OK, kcuda=0, DSR 32 == baseline 32.

The merge was not a plain auto-merge and the resolution is recorded in its own
commit message. This branch's base row row/LTX25-PROMPT-ADALN was SQUASHED onto
main as 65e79eee5, so the merge base predates the squash and git reported
add/add conflicts on files where both sides carry identical content. Resolved
deterministically: the tree was set to origin/main wholesale
(git read-tree -u --reset origin/main), then this branch's single commit
968461cda..2990ed81b was reapplied with git apply --3way. Verified, not
assumed
git diff origin/main on the resolved tree is byte-identical to
git diff 968461cda 2990ed81b except two hunk-header line offsets where main's
own later edits shifted the file. The four paths BOTH sides changed
(model-matrix.md, FEATURES.md, STATUS.md, test_ltx2_video.cpp) were each
inspected directly: main's content intact, this branch's edit present exactly
once, no duplicated relocation.

windows-msvc-cpu / windows-msvc-vulkan are red on every open PR in the repo
from a separate cause, tracked as #664 and being fixed on
row/FIX-WINDOWS-POSIX-VIDEO-ENGINE. Not chased here, and
src/vllm/multimodal/video_engine.cpp is untouched.

Gate

Nothing runtime changed. ltx2.h and test_ltx2.cpp move comment text only;
the one script edit (gen-ltx2-goldens.py) alters only the COMMENT the generator
emits; ltx2_goldens.inc moves two comment lines with every value byte-identical.
No src/ file is touched at all — so identical suite counts are the expected
result and the point of measuring them.

BUILD_EXIT=0 on a clean Release configure of the merged head; build log grepped
for No space left|BFD assertion0 hits; warning:|error:0 hits.
ctest -N = 423.

Suite counts, unchanged from the row. All four re-measured on this head,
exit 0 each:

Suite this branch
test_ltx2 35 cases / 2435 assertions
test_ltx2_loader 26 / 4826
test_ltx2_device 15 / 523
test_ltx2_video 30 / 502 skipped-default; 30 / 8734 with LTX2_CHECKPOINT_ROOT

tests/vllm/models/ltx2_goldens.inc was regenerated from
scripts/gen-ltx2-goldens.py against ltx_core fd4ded7f (REGEN_EXIT=0):
every golden VALUE byte-identical, the diff is the two stream labels alone — which
re-proves provenance as well as the wording.

Full ctest -j4 on the merged head: 422/423, CTEST_EXIT=8, 2 skipped as on
the baseline (test_modelopt_mixed_precision_checkpoint, test_voxtral_e2e). The
single failure is test_async_llm, which is on this repo's documented
starve-under--j list; re-run serially it is 1/1 PASS, exit 0.

Two environment failures, recorded rather than reported as verdicts.

  • The first LTX2_CHECKPOINT_ROOT run exited 1 with a zero-byte log — no
    doctest summary at all — under a load average above 190. An empty log is a
    killed process, not a failing test. Re-run: 30 / 8734, Status: SUCCESS, exit 0.
  • test_cpu_x86_llamacpp_floor fails with NO_QUIET_WINDOW (exit 4, busy=102%,
    load 53–204). It is the documented behaviour of that harness on a box that is
    never quiet — around ten agents were building throughout. Both files it
    exercises are byte-identical to origin/main
    (git diff origin/main -- scripts/cpu-x86-llamacpp-floor.sh tests/scripts/test_cpu_x86_llamacpp_floor.py
    is empty), so running it here is running main's version: it cannot be this
    diff. Reported as pending an idle box, not waived and not fixed.

An earlier full run was VOIDED rather than reported: another session's
disk-pressure cleanup deleted build/ while ctest was at 421/423, and the last
two tests recorded Not Run — Failed to change working directory. A run whose
tree vanished under it is not a result; it was rebuilt and re-run from scratch.

Spec: .agents/specs/ltx25-prompt-adaln.md. .agents/specs/ltx-2-5.md is
operator-owned and untouched.

🤖 Generated with Claude Code

mudler added 4 commits August 13, 2026 17:05
`use_prompt_adaln_single` defaults TRUE in both references — diffusers
`transformer_ltx2.py:1185` and LTX-2 `model.py:77` /
`model_configurator.py:76,138` — and the shipped FP8 DiT carries the 18
tensors the flag builds. `ltx2_loader.cpp:988` (and `:573`, `:626`) cleared
it unconditionally, so every render kept only the static
`prompt_scale_shift_table` and dropped the timestep-conditioned half of the
prompt K/V modulation. Shapes, finiteness and every committed golden agree
with the defect, because the goldens were generated with the flag OFF.

Spec only; no code. Records the upstream anchors for the module
(`model.py:222-227`, `:252-257`), the producer
(`transformer_args.py:274-277`, driven by `modality.sigma` and NOT
`timesteps`), the consumer (`transformer.py:441-446`), and what replaces
the cleared flag so `allow_unported_modules` can no longer silently disable
a ported feature.

Issue #644, row 0.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
…learing it

`use_prompt_adaln_single` defaults TRUE in both references — diffusers
`transformer_ltx2.py:1185`, LTX-2 `model.py:77` and
`model_configurator.py:76`/`:138` — and the shipped DiT carries the module's
tensors. `ltx2_loader.cpp` cleared it in three places, so every render kept
only the static `prompt_scale_shift_table` and dropped the
timestep-conditioned half of the prompt K/V modulation. Nothing saw it:
shapes unchanged, values finite, and every committed golden was generated
with the flag OFF.

MEASURED, flag ON vs OFF over the same shared weights: the timestep term is
51.7% the magnitude of the static table it is added to, moves the block-0
modulated prompt K/V by 5.82%, and moves the DiT output by 1.46e-4 — 73x the
gate's f32 floor.

Ported, citing what each piece came from:
  the module      <- model.py:222-227 (video), :252-257 (audio);
                     AdaLayerNormSingle(dim, embedding_coefficient=2), adaln.py:19-45
  the producer    <- transformer_args.py:274-277 driven by `modality.sigma`
                     [batch] and NOT the per-token `timesteps`, scaled by
                     timestep_scale_multiplier at :173-186
  the consumer    <- transformer.py:441-446, summed into the table BEFORE
                     `(1 + scale)` applies, threaded per stream at :288-296/:317-325
  diffusers twin  <- transformer_ltx2.py:1536-1547, :1648-1649, :677-693

Both arms: `Ltx2DitForward` and `Ltx2DitForwardDevice` (f32 and the bf16
production stream).

The three `= false` assignments are replaced by an invariant: the resolved
flag must equal whether the FILE carries `prompt_adaln_single`. And
`Ltx2AdoptDeclaredDitParams` now clears exactly ONE flag in its config copy —
`use_keyframes_abs_pos_embedding`, whose module really is unported — so
`allow_unported_modules=1`, which a real render still needs, can no longer
switch a ported feature off. A config that disagrees with the shapes about
the flag is refused rather than forced into agreement.

Both shipped DiTs were re-read off the NAS to check this refuses neither: the
FP8 file carries no `__metadata__` at all and the NVFP4 file's config OMITS
the key, so upstream's TRUE default decides on both, matching their tensors.

Evidence. Goldens executed from upstream LTX-2 @fd4ded7f at reduced dims
(`gen-ltx2-goldens.py` section 6); every pre-existing golden VALUE is
byte-identical. Five mutations, each RED and each restored byte-for-byte:
dropping the term host-side (3/35 cases), dropping it device-side (1/15),
re-adding the cleared flag (the guard throws; assertion count drops
4826->4815), driving the MLP from `timesteps` instead of `sigma` (2/35), and
swapping the shift and scale rows (2/35). A permanent in-tree case asserts
the flag-ON forward MISSES the flag-OFF golden, so a bound-but-unused module
cannot pass.

Suites vs `cefacd2d0`: test_ltx2 30/1627 -> 35/2435, test_ltx2_loader
24/4817 -> 26/4826, test_ltx2_device 13/498 -> 15/523, test_ltx2_video
30/502 -> 30/502 (its fixture now carries the module, which is the shipped
shape). Full `ctest` 423 registered, 422 pass under -j8 and
`test_serve_low_tools` passes on its serial re-run.

Spec .agents/specs/ltx25-prompt-adaln.md @baa92ccf7. Issue #644, row 0.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
Brings in b81a5e4 (the secondary-oracle registry). No conflict and no
overlap with this row's files; rebuilt clean and re-ran the full gate after
the merge, because a clean merge is not a compiling one: BUILD_EXIT=0,
ctest 423/423.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
…138x, and the keyframes claim next door was false (#644)

The port landed and reviewed PASS. What we WROTE about it did not.

## The headline numbers were fixture artifacts

The spec Outcome, the PR body and test_ltx2.cpp all quoted 51.7% ("term vs
table") and 5.82% (block-0 K/V) as the answer to "does this matter". Both come
from the generator's synthetic init: `prompt_scale_shift_table` AND every
prompt-AdaLN MLP parameter are drawn from the same `param_spec` rule at
scale=0.05 (gen-ltx2-goldens.py:100-106), so the ratio between them is a property
of the FIXTURE. It moves with the init scale: 0.005 gives 4.1%, 0.2 gives 1450%.
The Outcome disclaimed only the two OUTPUT rows as synthetic-bounded and then
called the other two the answer, though all four have identical provenance.

Measured on the SHIPPED weights instead, through upstream's own
AdaLayerNormSingle(dim, embedding_coefficient=2) evaluated on sigma*1000 exactly
as transformer_args.py:274-278/:177 do, against all 48 prompt_scale_shift_table
tensors of
`ltx-2.5-22b-distilled-transformer-nvfp4.safetensors`:

                          video     audio
  rms|table| (48 blocks)  0.017553  0.021925
  rms|term|  (uniform s)  0.236446  0.347171
  term/table RMS          1347%     1583%
  max|term|/max|table|    7119%     2817%

Like for like -- 51.7% is a max-vs-max ratio, and the same ratio on the real
weights is 7119% / 2817% -- the fixture UNDERSTATED the defect by 138x (video)
and 54x (audio). On the shipped model the timestep term DOMINATES the static
table; the table is the perturbation. Pre-row renders applied
`context*(1 + ~0.018 rms) + ~0.018` where upstream applies
`context*(1 + ~0.32 rms) + ~0.10`; on a unit-rms context the modulated context
moves +8.8% (video) / +31.3% (audio).

Both dispositions the finding offered are taken: the four fixture rows are now
labelled GATE-FLOOR numbers from synthetic weights in the spec, the goldens'
comment block and test_ltx2.cpp, AND the real-checkpoint measurement is stated as
the answer. `scripts/measure-ltx2-prompt-adaln.py` is committed so the number is
re-runnable rather than transcribed; it asserts `ltx_core.__file__` under the
named checkout before reading anything.

## A false claim about a checkpoint, the same class this row just fixed

ltx2.h:47-49 -- a line surviving inside the paragraph this row rewrote -- said
"LTX-2.5's checkpoint does not carry the parameter" about
keyframes_abs_pos_embedding. Both shipped DiTs contradict it, each on a different
half, read off their headers and run through upstream's own configurator:

  FP8 (vonkaiser):  CARRIES keyframes_abs_pos_embedding F8_E4M3 [1,4096] + scale,
                    and declares NO __metadata__ at all -- so
                    LTXModelConfigurator.from_metadata cannot configure it:
                    KeyError: 'caption_channels', raised by
                    _build_caption_projections on the empty dict, BEFORE the flag
                    at model_configurator.py:82 is ever read.
  NVFP4 (1st-party): DECLARES the flag true and does NOT carry the tensor, so the
                    parameter stays torch.zeros(1, inner_dim) (model.py:217-219)
                    through load_state_dict(..., strict=False)
                    (single_gpu_model_builder.py:98) -- a genuine no-op there.

It is also not keyframe-only: transformer_args.py:269 applies it on every prepare
whose keyframes_mask is set, and tools.py:186-196 sets that mask unconditionally.

REFUSAL KEYING: unchanged, deliberately. It fires on the TENSORS the file
carries. Keying it on the resolved flag would, on the FP8 DiT, read a DEFAULT
rather than the file -- that file declares nothing -- and load it while silently
discarding a trained [1,4096] parameter. No behaviour changed, so no new gate is
owed; three refusal MESSAGES changed, because they asserted an implication that
is false in both directions.

## Records the lifecycle change did not move

model-matrix.md's inventory row still listed "timestep-INDEPENDENT prompt K/V
(cacheable once per request)" -- precisely what this row disproved.
docs/STATUS.md's LTX-2.5 row did not mention the prompt-side AdaLN at all;
FEATURES.md and USAGE.md described the keyframes opt-in as if only one file were
involved.

## Two things recorded honestly rather than fixed

- test_ltx2_video's shipped-checkpoint case is env-gated on
  LTX2_CHECKPOINT_ROOT and SKIPS by default, so the row's "unchanged 30/502"
  meant the whole real-header case did not run. With the variable set the same
  binary measures 30/8734 -- verified here, exit 0 both ways. Noted in the spec
  and at the skip site.
- Upstream loads with strict=False, so a config declaring the prompt-AdaLN flag
  false over a file that carries the module would silently run flag-OFF upstream
  where we now refuse. Ours is better; it is a DOCUMENTED DIVERGENCE, not a
  mirror, and it is named as one.

## Gate

BUILD_EXIT=0; build logs grepped for `No space left|BFD assertion` (0 hits);
df -h / 92% used, 37G free. ctest -N = 423; full ctest -j8 422/423 with
test_serve_low_tools starved under -j (known parallel flake), 1/1 PASS serially,
exit 0; 2 skipped as on the baseline. Suite counts unchanged from the row:
test_ltx2 35/2435, test_ltx2_loader 26/4826, test_ltx2_device 15/523,
test_ltx2_video 30/502 (skipped default) and 30/8734 with the checkpoint root.
ltx2_goldens.inc REGENERATED from gen-ltx2-goldens.py against ltx_core fd4ded7f:
every golden VALUE byte-identical, the diff is the comment block alone.

An earlier full run was VOIDED rather than reported: another session's
disk-pressure cleanup deleted build/ while ctest was at 421/423 and the last two
tests recorded "Not Run -- Failed to change working directory". A run whose tree
vanished under it is not a result; it was rebuilt and re-run from scratch.

One finding detail did not hold on inspection: it cited
`.agents/model-matrix.md:98` as already saying the two DiTs "differ in a TRAINED
keyframes_abs_pos_embedding". That file contains no occurrence of "keyframes" at
all on this branch; the corroborating anchors are `.agents/specs/ltx-2-5.md`
section 3.1 and `tests/vllm/multimodal/test_ltx2_video.cpp:913-914`.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
mudler added 2 commits August 13, 2026 21:33
…d device-leakage red (#644)

The head was behind and inherited a `check-device-leakage` FAIL it did not cause:
`kcuda=2 > baseline 0`, both hits in
`src/vllm/multimodal/ltx2_video.cpp:532,549` — a file this branch does not touch,
present at the parent `968461cda` and already fixed on `main` by `11cc1d589`.
Merging is the whole repair; no edit of mine was needed and none was made.
`check-device-leakage` before: FAIL, `kcuda=2`. After: OK, `kcuda=0`, DSR 32 ==
baseline 32.

RESOLUTION, recorded because it was NOT a plain auto-merge. This branch's base row
`row/LTX25-PROMPT-ADALN` was SQUASHED onto main as `65e79eee5`, so the merge base
predates the squash and git reports add/add conflicts on files where both sides
carry identical content. Resolved deterministically rather than hunk by hunk: the
tree was set to `origin/main` wholesale (`git read-tree -u --reset origin/main`),
then this branch's single commit `968461cda..2990ed8` was reapplied on top with
`git apply --3way`. All 14 paths applied cleanly.

VERIFIED, not assumed: `git diff origin/main` on the resolved tree is
byte-identical to `git diff 968461c 2990ed8` except for two hunk-header line
offsets (`.agents/model-matrix.md` 429->445,
`tests/vllm/multimodal/test_ltx2_video.cpp` 913->925) where main's own later edits
shifted the file. The four paths BOTH sides changed —
`.agents/model-matrix.md`, `docs/FEATURES.md`, `docs/STATUS.md`,
`tests/vllm/multimodal/test_ltx2_video.cpp` — were each inspected directly: main's
content intact, this branch's edit present exactly once, no duplicated relocation.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
…not zeroed, and the audio factor had the wrong denominator (#644, #673)

Review findings F-1 and F-2 on PR #663. The reviewer re-ran every measurement in
that PR and every published digit reproduced; this repairs the two claims that did
not.

## F-1 (blocking) — a claim about upstream that upstream's own code contradicts

Three places said that on the NVFP4 DiT the absent `keyframes_abs_pos_embedding`
means the parameter "keeps `torch.zeros(1, inner_dim)` (model.py:217-219) through
`load_state_dict(..., strict=False)` (single_gpu_model_builder.py:98) — a genuine
no-op there": `include/vllm/model_executor/models/ltx2.h` (THE PRODUCT TREE), the
spec, and the PR body.

IT IS NOT A NO-OP. The claim quoted `single_gpu_model_builder.py:98` while
dropping the `assign=True` that is on that same line, and upstream builds on the
META DEVICE -- `loader/helpers.py:84-95`, `create_meta_model`:
`with torch.device("meta"): configurator.from_metadata(...)` at `:90-91`. A key
absent from the state dict is therefore never materialised at all.

RUN HERE, not transcribed, through upstream's own `create_meta_model` on the
shipped file's real `__metadata__` (read with upstream's own `read_model_metadata`
/ `SafetensorsModelStateDictLoader`, sft_loader.py:58-74, which JSON-decodes each
value -- the flag lives at `config.transformer`, not at the top level, so a raw
`__metadata__` read returns None for it):

  keys matching 'keyframes_abs_pos' in the file : []  (0 of 7876 entries)
  config.transformer['use_keyframes_abs_pos_embedding'] = True
  keyframes_abs_pos_embedding: shape=(1, 4096) f32 device=meta is_meta=True
  supports_keyframes_abs_pos_embedding (BEFORE load) : False
  after load_state_dict(sd, strict=False, assign=True):
    neighbour patchify_proj.weight : device=cpu is_meta=False   <- materialised
    keyframes_abs_pos_embedding    : device=meta is_meta=True
    in missing_keys                : True
    reading the value RAISES : RuntimeError: Tensor.item() cannot be called on meta tensors
  supports_keyframes_abs_pos_embedding (AFTER load)  : False

Upstream states this itself and then never asks.
`supports_keyframes_abs_pos_embedding` (model.py:166-173) returns False for "a
model whose config set the flag but whose checkpoint carried no weight for it (the
parameter would still be on ``meta``)" (:170), and
`enable_keyframes_abs_pos_embedding` (model.py:175-200) exists because such a
parameter "would fail at the first forward" (:182). BOTH ARE DEFINED AND NEVER
CALLED: `grep -rn` over the whole Lightricks/LTX-2 checkout at fd4ded7f returns
exactly 1 hit each, the definition, re-confirmed here against a positive control
rather than asserted from a null grep.

Polarity is not what fails: `apply_keyframes_absolute_embedding` is
`hidden_states + mask * embedding` (transformer_args.py:23-43, the sum at :43), so
REAL zeros would be inert. The mechanism claim fails on `meta`, not on additivity.

This STRENGTHENS the row's conclusion and changes nothing downstream: the refusal
stays keyed on TENSOR PRESENCE for the FP8 file, and the NVFP4 file is refused by
FLAG in `ParseLtx2DitParams` (ltx2.cpp:192-198).

NOTHING RUNTIME CHANGED IN THIS COMMIT. `ltx2.h` and `test_ltx2.cpp` move comment
text only; the one script edit (`gen-ltx2-goldens.py`) alters only the COMMENT the
generator emits; `ltx2_goldens.inc` moves two comment lines with every value
byte-identical. No `src/` file is touched at all. Suite counts are therefore
expected to be identical, and the point of the gate below is that they are.

The same anchor is now quoted in full at the OTHER place it appears (the
documented-divergence bullet), because dropping the `assign=True` is precisely
what made the claim above wrong.

## F-2 — the audio factor's denominator

The Outcome read "138x (video) and 54x (audio)" as if both were per-stream. The
video figure is right and like-for-like. The audio one divided the shipped AUDIO
ratio by the VIDEO fixture denominator, because `gen-ltx2-goldens.py` emits
exactly ONE fixture ratio and it is the video stream's. 54x is literally true
about that single published figure and errs CONSERVATIVE.

Recomputed by IMPORTING the generator, so the weight stream is bit-identical and
no weight is re-drawn:

  video: max|term| = 0.0252012  max|table| = 0.0487142  -> 51.7327%   (7119/51.73 = 137.6x)
  audio: max|term| = 0.0201763  max|table| = 0.0496868  -> 40.6068%   (2817/40.61 =  69.4x)

FIXED AT THE SOURCE, not only in prose. The generator emitted BOTH video-only
rows unlabelled -- "timestep term vs static table" and "block 0 modulated prompt
K/V" -- which is exactly how a video denominator came to be applied to an audio
numerator. `gen-ltx2-goldens.py` now names the stream on both, and
`ltx2_goldens.inc` was REGENERATED against ltx_core fd4ded7f to carry them
(REGEN_EXIT=0). The regeneration diff is those two comment lines and NOTHING
else: every golden VALUE byte-identical, and the "Regenerate with:" header
unchanged because the committed command was re-run verbatim -- so this re-proves
provenance as well as the labels. The Outcome now carries a per-stream table with
each row against its own denominator, and `test_ltx2.cpp` and the spec's
gate-floor table say which stream they mean.

No fifth golden was added: the audio figure is a denominator for this record, not
a gate floor, so "ALL FOUR ROWS ARE GATE-FLOOR NUMBERS" still holds and the three
files that label those four are otherwise untouched.

## Recorded, not fixed — issue #673

`LTX2_CHECKPOINT_ROOT` is set by NO workflow: `grep -rn CHECKPOINT_ROOT .github/`
exits 1 with zero hits while the same pattern matches in `tests/` and `.agents/`
(positive control run in the same command). CI therefore executes 502 of 8734
assertions -- 5.7% -- of `test_ltx2_video`, at an UNCHANGED case count of 30, and
`scripts/measure-ltx2-prompt-adaln.py` is a manual tool no gate invokes. This
row's checkpoint-derived evidence is manual and host-local. Filed as visible debt
and linked in the roadmap issue table and the spec; wiring checkpoints into CI is
explicitly not in this row.

## No test asserts this text, and none was invented

Searched in the subject's own vocabulary: the corrected claim lives only in a
`ltx2.h` comment, the spec and the PR body. The runtime refusal MESSAGES
(`ltx2.cpp:195-198`, `ltx2_loader.cpp` `RefuseUnported`) never carried the
"zeros"/"no-op" implication, and no checker reads the header comment. Writing a
test here would be writing one that cannot fail, so this change adds none. The
tensor-keyed refusal it defends is already pinned by a mutation the reviewer ran:
making `LoadedElsewhere` swallow the tensor takes `test_ltx2_loader` to 25/26
cases, 4817/4818 assertions, exit 1.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
@localai-bot
localai-bot changed the base branch from row/LTX25-PROMPT-ADALN to main August 13, 2026 21:53
localai-bot pushed a commit that referenced this pull request Aug 13, 2026
…-- retire that refusal, apply nothing (#658)

FOLLOWING_AGENTS_PROTOCOL

The spec recorded a live disagreement for the implementer to settle: one reviewer
read the NVFP4 arm's `keyframes_abs_pos_embedding` as zero-initialized and
therefore an exact no-op; another said it stays on the meta device. Both readings
are consistent with the source. Only one is consistent with what runs, and an
implementer on the sibling row (#663) has now RUN it, using upstream's own
`create_meta_model` and its own metadata reader rather than a hand-rolled probe:

  keys matching 'keyframes_abs_pos' in the file : []   (0 of 7876 entries)
  config.transformer['use_keyframes_abs_pos_embedding'] = True
  keyframes_abs_pos_embedding: shape=(1, 4096) device=meta is_meta=True
  supports_keyframes_abs_pos_embedding (BEFORE load) : False
  after load_state_dict(sd, strict=False, assign=True):
    neighbour patchify_proj.weight : device=cpu is_meta=False   <- materialised
    keyframes_abs_pos_embedding    : device=meta is_meta=True
    in missing_keys                : True
    reading the value RAISES : RuntimeError: Tensor.item() cannot be called on meta tensors
  supports_keyframes_abs_pos_embedding (AFTER load)  : False

The materialised NEIGHBOUR is what makes the result mean anything: the loader ran
and populated the model, and only the absent key stayed on `meta`. Without that
control the transcript would be equally consistent with a loader that did nothing.

So on the first-party NVFP4 DiT upstream never reaches the add at all. The
correct mirror there is to LOAD AND APPLY NOTHING -- neither the refusal
`ltx2.cpp:192` raises today, which is stricter than upstream, nor a synthesised
zero, which would invent the behaviour `supports_...` exists to prevent. The row
retires that refusal outright, and section 6 now names the tempting middle option
as the risk rather than leaving it open.

One narrow consequence, stated narrowly so it is not over-read: a render taken on
the NVFP4 DiT with `allow_unported_modules` is upstream-equivalent FOR THIS
MODULE ONLY. It says nothing about the render as a whole.

Also corrected here: the guards are `model.py:166-173` and `:175-200`, not
`167-182`/`175-193`; and the flag is NOT at the top of `__metadata__` -- a raw
read returns None, it lives at `config.transformer`, which is why upstream's
JSON-decoding reader is needed to see it at all.

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5[1m] [claude-code]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants