feat(LTX25-A2VID-RECIPE): the audio-to-video recipe, and the phase field a boolean could not express (#1117) - #1120
Merged
Merged
Conversation
…ors the dispatch got wrong (#1117, #1118) `A2VidPipelineTwoStage` has no recipe row. #922 closed the audio CONDITIONING — a supplied take rides `distilled_two_stage` today — and the recipe is a different trajectory in four fields, each of which renders: stage 1's schedule is scheduler-derived rather than the frozen distilled sigmas, its guidance is the params table's video row and is caller-overridable, its stepper is plain Euler rather than the ancestral one 2.5 selects, and its AUDIO guider is the default positive-only one rather than the table's cfg-7.0 row. Two anchors are corrected rather than propagated: the a2v guidance default is 3.0 at `utils/args.py:987-996` through `utils/constants.py:54`, not 0.0 at `a2vid_two_stage.py:318-323` (which is `--audio-start-time`); and the `AudioConditioner` is built at `:96-102` and called at `:200`, not `:53`/`:143`. #1118 is filed and owed rather than fixed here: LoRA fuses once at load, so no recipe can put the distilled adapter on stage 2 alone the way upstream does. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…eld a boolean could not express (#1117) `A2VidPipelineTwoStage` (`a2vid_two_stage.py:53` @ `fd4ded7f`) had no recipe row, so `pipeline_kind = a2vid_two_stage` got the generic table refusal naming the pair rather than the missing machinery. #922 closed the audio CONDITIONING, not the recipe: a supplied take rode `distilled_two_stage`, which its own spec records as a different trajectory. Four fields differ and each of them renders. Stage 1's schedule is derived from the step count (`:225-227`) against the frozen distilled list; its guidance is the params table's video row and is caller-overridable (`:353-360`) against `allow_guidance_override = false`; its stepper is plain Euler, because `:229-258` passes none and `utils/blocks.py:526-527` defaults it, against the ancestral one `distilled.py:76-84` selects for 2.5; and its AUDIO guider is the default positive-only `MultiModalGuiderParams()` (`:237-239`) rather than the table's cfg-7.0 row, which would buy an unconditional forward for a stream the freeze holds still. Two things upstream makes REQUIRED are now refused by name rather than defaulted: `--audio-path` (`:312-317`), checked at generate time because `pipeline_kind` is a load knob, and `--distilled-lora` (`utils/args.py:1140-1153`), checked at load. Without the take the soundtrack is generated and the clip looks finished; without the adapter stage 2 runs a three-sigma refinement on undistilled weights. `Ltx2PhaseDenoiser { kGuided, kSimple }` is new because `allow_guidance_override` cannot express a2vid's stage 2. That boolean answers "does this pipeline's CLI carry the guider flags"; a2vid's does, and they reach stage 1 alone because stage 2 is `SimpleDenoiser` (`:278`). Refusing would reject a request upstream accepts and applying would switch on a pass upstream does not run, so stage 2 is `allow_guidance_override = true` AND `kSimple`, and the skip is tested AFTER the refusal so three landed refusals do not become silent ignores. Gated on the reduced fixture, through `LoadVideoEngine` and `Generate`. The frozen take is checked as CONSUMED rather than carried: its latent is bit-identical across seeds and moves with the window, `audio_frozen` is read off the mask after the noiser and `audio_sigma_max` is 0 over every step of both phases. Stage 1's four guidance arms each carry `x0 == latent - sigma*velocity`. The stage-2 skip is measured on artifact bytes, by restating a value that is already stage 1's own. NOT claimed: any render on real weights, and any oracle-run comparison. The adapter placement diverges and cannot be repaired from the request — upstream fuses the distilled LoRA into stage 2 alone and this engine fuses once at load — which is #1118, listed under `## Owed`. Issue #1117. Spec `.agents/specs/ltx25-a2vid-recipe.md`, committed at `d38ab8c86`, before any code. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…ary buffers (#1117) The stage-2 override gate compared two artifact strings directly. Those are PPM pixels and a WAV, so a failing `CHECK(a == b)` dumps raw bytes into the doctest report — and that killed this row's mutation harness with a `UnicodeDecodeError` between applying M12 and restoring it, which is the shape #922's spec already records: the harness then reports the previous mutation's tree as the change's own. The count says the same thing and prints. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
Brings in `a6df72777` (NemotronH paged forward) and `2e025247e` (a FEATURES count). The only textual overlap was `docs/FEATURES.md`, which auto-merged into adjacent rows; the a2vid row this branch adds and the parser count that landed on main touch different tables. `check-public-doc-tables.py` and the READER ANCHORS derivation were both re-run on the merged tree. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…luding the one it caught with one binary (#1117) Twelve mutations applied against the committed head, twelve detected. M6 -- the stepper -- is SURVIVED by the end-to-end case and DETECTED by the recipe case, and that is written down as it measured: the stepper is a recipe field, the end-to-end case has no baseline trajectory to compare against, and this recipe's `noise_seed_offset` is 0 so the ancestral arm moves no digest the trace carries. Also records the two consumption controls the implementation actually uses (the same take across SEEDS is bit-identical; a different WINDOW is not), and the harness defect that a binary artifact comparison caused. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
Brings in `994d30b5d` (the MTP k>1 near-tie gate record). It changes six files and NONE of them is compiled: `.agents/benchmark-record.md`, `.agents/environment.md`, `.agents/specs/mtp-k-gt-1.md`, `docs/BENCHMARKS.md`, `docs/STATUS.md` and a new `scripts/` helper. So the merged tree's binaries are byte-identical to the ones the full gate ran on, and ctest is re-run on it anyway rather than argued about. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…anchors off by a line or a generation (#1117, #1118) The fresh review returned PASS with five non-blocking findings, all of them prose or anchors. No behaviour changes here: every edit is a comment, a spec paragraph or an issue-index row this branch itself appends. The one that mattered is the LoRA divergence. The row said it "changes nothing a caller can read". That is false, and false in the direction that hides work: fusing the distilled adapter into stage 1 changes the trajectory, so it changes the PIXELS, and a caller reads pixels. Worse, an unqualified "nothing a caller can read" implies no instrument could ever detect it, when the real-weights comparison against upstream's own render — the one §0 and `## Owed` already record this row as not having — is exactly the gate that would. Every place now says what is actually invariant: the frame count, the shapes, the sample rate and the errors. Nothing in the SHAPE of the result says anything is wrong. Checking §4.4 before copying it was the right instruction. §4.4 did not say what the review brief reported; it said "or any digest a caller can read", which carries the same overstatement, so copying it verbatim would have propagated the defect into the two other sites rather than repairing it. `docs/USAGE.md` gains the user-facing half of that. A reader running the command in that section could not previously tell whether the divergence reached their output; it does, and the page now says so and says that only a side-by-side render against upstream can see it. The four anchor findings, each re-derived from the sentence making the claim rather than by reading the cited span, against Lightricks LTX-2 @ `fd4ded7f`: - `--a2v-guidance-scale` is `utils/args.py:986-995` — `parser.add_argument(` opens at `:986`, the name is at `:987`, the default at `:989`, the closer at `:995`. The recorded `987-996` started at the name and ran one line past. - `default_2_stage_distilled_arg_parser` is at `:1188`. `:1187` is blank. - Two numbers were the 2.0 generation's. `LTX_2_3_PARAMS` overrides `num_inference_steps` to 30 (`utils/constants.py:85`) and `stg_blocks` to `[28]` (`:86`), `LTX_2_4_PARAMS` inherits both (`:124`), and 2.5 resolves onto that row — so this recipe's stage 1 is a 30-step schedule naming block 28, not 40 and 29. Neither was load-bearing: the code reads `params.num_inference_steps` and the tests assert relatively. - "All four the params table distinguishes" claimed more than upstream does. `_PARAMS_SINCE_VERSION` (`:130-133`) has two rows, `(2,4)` and `(2,3)`, and falls through to `LTX_2_PARAMS` at `:179`. The four are keys of OUR recipe table, which refuses an unknown pair by name rather than defaulting. - The §2 table listed `LightricksNegativePrompt()` flat where the dispatch uses `kOmniNegativePrompt` on `2` and `2.3`. That split is which reference owns the row, and `t2a_one_stage` splits identically at the same four versions. Two anchors beyond the findings, corrected in flow because this branch is what introduced them and shipping a half-corrected set is worse than either whole one. `utils/args.py:947-996` named the six video-guider flags but stopped at the last one's opening line; the group closes at `:1006` and the audio group starts at `:1007`. And `test_ltx2_pipeline.cpp` carried the same 2.0 step count inside a case that resolves 2.5 explicitly. `include/vllm/multimodal/ltx2_video.h:473` carries `utils/args.py:987-996` too, but it is on `main` and predates this row, so it is reported rather than rewritten here. Two LOCAL anchors were stale as well, and one of them this repair staled itself. The spec pointed at `ltx2_pipeline.cpp:1464-1471` for the `t2a_one_stage` rows, which the F4 comment above them moved to `:1471-1478` in this very commit, and `docs/USAGE.md` pointed at `ltx2_pipeline.cpp:1306-1313` for the DFR refusal, which this ROW's 145 inserted lines moved to `:1434-1441`. Both now name the construct rather than a line range, which is what the paragraph one above the USAGE one already did. A line range into a file the same pull request is inserting into is a record that goes stale before it lands. This row moved six more unpinned `docs/USAGE.md` coordinates the same way, in sections it does not own. They are reported to the operator with re-derived values rather than swept here: that page states its own convention — "read an unpinned coordinate as unverified" — and its last re-derivation was a scoped unit of work with its own review, not a rider. READER ANCHORS re-derived with the test's own walk and unchanged at `798 808 809 871 967 983 1018 1109 1134 1239 1280 1322 1324`; the one `ltx2_video.cpp` edit is in place on a line below all thirteen. The deriving instrument was armed first: one line inserted above them moves all thirteen and it reports MISMATCH. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
`main` moved from `994d30b5d` to `589abad12` while this row's review repair was under gate. That commit adds `vt::Conv1d` / `vt::ConvTranspose1d` and touches no LTX-2.5 file, so `git merge` took `docs/USAGE.md` on both sides and nothing else overlapped. Three things checked rather than assumed, because a clean merge is silent about each of them: - The `READER ANCHORS` list in `ltx2_video.cpp` is re-derived on the MERGED tree with the same walk `test_ltx2_video` uses and is unchanged at `798 808 809 871 967 983 1018 1109 1134 1239 1280 1322 1324`. The deriving instrument was armed first: one line inserted above them moves all thirteen. - `.agents/issue-index.md` is untouched by this merge, so the union driver never ran on it. Verified anyway against `589abad12`: byte-identical prefix, no base row changed or dropped, and every issue id unique. This branch appends exactly `#1117` and `#1118`. - `docs/USAGE.md` auto-merged. Both of this branch's edits survive and all three of `main`'s `vocoder-conv-ab` lines are present, so the merge kept both sides rather than one. The full gate is re-run on this merged tree, not on either parent. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
`4d7748646` (#921/#1125) landed the `res2s_two_stage` HQ arm into the same four regions this row edits, so all four conflicts are two arms appended at one place rather than two edits of one thing. BOTH ARMS SURVIVE, and each is proven to still reach its denoiser rather than merely to compile. `ltx2_pipeline.cpp`: the driver interleaved `Res2sTwoStageRecipe` and `A2VidTwoStageRecipe` because they share a tail (`recipe.height = ...` through `return recipe;`). Both functions are restored WHOLE, res_2s first, and the dispatch table carries both keys — `res2s_two_stage` at 2.5 and `a2vid_two_stage` at all four. `ltx2_video.cpp`: only the READER ANCHORS line conflicted. #1125's phase loop is taken unchanged, including the `Evaluate` lambda both samplers share, its `Ltx2GuidedDenoise` call, `dit_forwards` beside `dit_evaluations`, the `step_index` policy (`step_idx`, a literal 0 at the res_2s substep, `n_full_steps` at the terminal one) and the trace-delta `VT_CHECK` that replaced the tautological one. This row's three additive hunks ride on top, and the `Ltx2PhaseDenoiser::kSimple` skip stays AFTER the `allow_guidance_override` refusal — the reverse order turns three landed refusals into silent ignores. `docs/USAGE.md`: the recipe table lists both kinds and the pair count is now TWENTY (16 + a2vid's four). Both prose sections are kept, in table order. `tests/vllm/models/test_ltx2_pipeline.cpp`: both suites append at EOF, so the driver overlapped them. Kept whole: 8 res_2s cases and 2 a2vid cases, 52 cases and 3062 assertions for the binary. `.agents/issue-index.md` union-merged, and the driver's result was NOT accepted. `origin/main` was taken wholesale and this branch's own unlanded rows (#1117, #1118) re-appended, then verified three ways: `origin/main`'s 224719 bytes are a byte-identical PREFIX of the result, the two rows are byte-identical to the branch head's, and 311 rows carry 311 unique ids. READER ANCHORS re-derived with the test's own walk: `809 819 820 882 978 994 1029 1120 1145 1250 1291 1333 1335`, replacing #1125's `... 996 1087 1112 1217 1258 1300 1302`. The instrument was armed first — one line inserted above the readers built clean and took the walk to MISMATCH at exit 1, and the restore is byte-identical. Six mutations on the merged tree, each printing its own `git diff --stat`, whether it BUILT, the compile-error count and the exit code captured directly. All six DETECTED, and the two that matter for this merge are the first two: stripping stage 1's guider from `A2VidTwoStageRecipe` is RED on both binaries, and stripping it from `Res2sTwoStageRecipe` is RED on both. Deleting either dispatch row is RED. Deleting the `kSimple` skip and deleting `im.trace.dit_forwards += 1` are each RED on `test_ltx2_video`. Gate on the merged tree: `CONFIGURE_EXIT=0`, `BUILD_EXIT=0`, 0 `: error:`, `ctest -N` 502, `CTEST_EXIT=8` with 500/502 passing. The two failures are `test_engine_core_proc` (#1052) and `test_async_llm` (#294), both load-dependent and both green when re-run serially at load 33 (they failed at load 82). No `No space left` and no `BFD` in the configure, build or ctest logs, against a positive control that matches both strings in a log that carries them. Not verified here: no render on real weights and no oracle-run comparison for either arm — unchanged by this merge and already recorded under `## Owed` in both specs. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…main `559973cb8` (a ROCm gemma4 GetBlas TLS fix) and `846076463` (#1121, the MUSIC3 2.4B fp32 DiT staged onto the device) landed after this row was gated. Neither touches a `src/`, `include/` or `tests/` file this row touches; the only overlap is the issue index and the two keyed public records. The forge reported a conflict and `git merge` reports none -- GitHub computes mergeability without applying `.gitattributes` merge drivers, so any branch that appends an index row looks conflicted there. The index was rebuilt from `origin/main` wholesale with this branch's own two rows re-appended (#1117, #1118) and verified: byte-identical prefix, 312 rows, 312 unique ids. The full gate at `8f75b98ae` against `4d7748646` was 501 of 502, the single failure being `test_serve_low_tools` (#428), which touches no file this row edits and passed 3 of 3 alone. Both LTX binaries ran whole and green: 77 cases / 2343 assertions and 52 / 3062. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A2VidPipelineTwoStage(a2vid_two_stage.py:53@fd4ded7f) had no recipe row,so
pipeline_kind = a2vid_two_stagegot the generic table refusal naming thepair rather than the missing machinery. #922
is CLOSED and closed the audio conditioning, not the recipe: a supplied take
rode
distilled_two_stage, whichltx25-a2v-audio-input.md:438-446already records as a different trajectory. A closed issue is not evidence.
Issue #1117. Spec
.agents/specs/ltx25-a2vid-recipe.md,committed at
d38ab8c86, before any code.What the recipe is, field by field
Four fields differ from the recipe a take rides today, and each of them
renders — a finished clip at the right size, frame count and sample rate.
distilled_two_stageself._scheduler.execute(steps=num_inference_steps),:225-227MultiModalGuider(params=video_guider_params, ...):230-240, fed fromutils/args.py:947-1006kEulerAncestralon 2.5:229-258passes nostepper, soEulerDiffusionStep()applies,utils/blocks.py:526-527MultiModalGuiderParams()at:237-239,ltx-core components/guiders.py:200-210The audio guider is the field a reader is most likely to "fix" by symmetry with
OneStagePhase, which takes the table's row and is right to(
ti2vid_one_stage.py:215-218). A2Vid does not: the stream it would guide isfrozen, so the table's
cfg_scale = 7.0would buy an unconditional forward and anegative text encode for a delta multiplied into a latent the sampler cannot
move.
Stage 2 is upstream's
STAGE_2_DISTILLED_SIGMAS(:164), the spatial upsample(
:261),noise_scale = stage_2_sigmas[0](:288) andSimpleDenoiser(:278).Four rows — 2, 2.3, 2.4, 2.5 — mirroring the
t2a_one_stagerows one for oneand for the same reason: the pipeline takes whatever
resolve_cli_params()readoff the checkpoint (
:311, againstt2a_one_stage.py:178-179).Two things upstream makes REQUIRED, refused by name
--audio-pathisrequired=True(:312-317). Checked at generate time,because
pipeline_kindis a load knob andaudio_pathis a per-generationextra, so the question is only decidable once a request exists. Without the
take the soundtrack is GENERATED and the clip looks finished.
--distilled-loraisrequired=True(utils/args.py:1140-1153). Checkedat load. Without the adapter, stage 2's three-sigma refinement runs on weights
that were never distilled for it.
Both are keyed on a recipe flag rather than a
pipeline_kindstring compare, forthe reason
audio_onlyalready gives in the header. The second flag has a seconduser waiting:
ti2vid_two_stages(#1093)and
keyframe_interpolation(#1096)select the same parser.
The phase field a boolean could not express
Ltx2PhaseDenoiser { kGuided, kSimple }is new, and it exists becauseallow_guidance_overridecannot describe a2vid's stage 2.That boolean answers "does this pipeline's CLI carry the guider flags at all".
distilled.pyselectsdefault_2_stage_distilled_arg_parser(
utils/args.py:1188), which never adds them, so an override there names a knobthe pipeline has no surface for and the engine refuses it — correctly, and that
refusal is landed and gated.
a2vid_two_stage.py:311selectsdefault_2_stage_arg_parser, which DOES carry them, and they reach stage 1'sguider alone (
:233-236) because stage 2 constructsSimpleDenoiserand takesno params.
Neither value of the boolean says that.
falserejects a request upstreamaccepts.
trueapplies the override to stage 2's positive-only params andswitches on a guidance pass upstream does not run — invisibly, since an extra
forward changes no output shape, frame count or sample rate. So a2vid's stage 2
is
allow_guidance_override = trueandkSimple, and the skip is testedAFTER the refusal: every recipe that refuses today is
kSimpletoo, so the otherorder would turn three landed refusals into silent ignores.
Reachability
Entry point:
LoadVideoEnginewithpipeline_kind = a2vid_two_stage— adocumented value of a documented load extra — then
Generatewith theaudio_pathextra. The chain isinclude/vllm.h->src/capi/vllm_c.cpp->Ltx2VideoEngine::Generate-> the a2vid dispatch row -> the phase loop ->Ltx2GuidedDenoise.ltx2-gen --pipeline-kind a2vid_two_stage --audio-pathisthe same two calls through the ABI. No test constructs a recipe, a guider, a
phase or a modality by hand.
M1 is the reachability mutation: deleting the dispatch row REDs the whole
case at the load.
What does NOT reach it, stated rather than left to be found.
/v1/videoscannot drive this.
VideoGenParamsFromRequest(video_engine.cpp:349-384) neverwrites
gen.extras, so no per-generation extra reaches any engine over HTTP(#928).
pipeline_kindIS aload extra and reaches a server through
--video-extra, and every request tosuch a server is then refused for the missing take. Reachable from
include/vllm.hand fromltx2-gen; not over HTTP.RED before green
Both binaries, with the dispatch row absent and everything else in place:
Green on the same tree with the row present:
test_ltx2_pipeline44/44, 2598assertions, exit 0;
test_ltx2_video74/74, 2275 assertions, exit 0.The take is CONSUMED, not carried
A recipe assertion proves
frozen = Trueandnoise_scale = 0.0are SET. Thesesay the DiT saw the consequence, read off the LAST phase — so stage 2's own
noise_scaleof 0.909375, which the loop applies to both streams, is inside whatthey measure:
audio_frozen, derived from the denoise mask the loop uses and read AFTER thenoiser;
audio_sigma_max == 0.0, the scalarModality.sigmahalf of upstream'sfrozen(utils/types.py:104-106), which the mask cannot reach;and not a sample — and moves with the window, so the first control cannot
be passing on a constant.
The guidance arms, in x0 space, on all four
Stage 1's guider is cfg 3.0 / stg 1.0 / rescale 0.7 / modality 3.0, so all four
passes run and the rescale branch — the one term that is not invariant between
the two spaces — is live.
x0 == latent - sigma*velocityis asserted per arm.M11's RED, verbatim:
The stage-2 skip has no trace field to read, so it is measured on artifact bytes:
two renders whose only difference is
video_stg_scale = 1.0, which is ALREADYstage 1's own value (
utils/constants.py:52) and is 0.0 on stage 2. Equal bytesmean the override stopped at stage 1. Both recipe values are
REQUIREd first, soa table change turns the comparison into a failure rather than a tautology.
Mutations
Focused gate
./build/tests/test_ltx2_video --test-case='ltx2 a2vid:*'— thefilter is admissible only because the harness asserts it matched exactly 2 cases
and a non-zero assertion count; neither case name contains a comma. Recipe-shape
mutations also run the whole
test_ltx2_pipelinebinary.git diff --stat: error:ltx2_pipeline.cpp | 2 +-spatial_downscale2 -> 1ltx2_pipeline.cpp | 2 +-ltx2_pipeline.cpp | 2 +-allow_guidance_override-> falseltx2_pipeline.cpp | 2 +-ltx2_pipeline.cpp | 2 +-kEulerAncestralltx2_pipeline.cpp | 2 +-ltx2_video.cpp | 2 +-ltx2_video.cpp | 2 +-ltx2_video.cpp | 2 +-ltx2_video.cpp | 2 +-ltx2_video.cpp | 3 +--kSimpleskip deleted, so the override reaches stage 2ltx2_video.cpp | 2 +-M6 is stated as it measured, not as it would read better. The stepper is a
recipe field and only the recipe case sees it; the end-to-end case has no
baseline to compare a trajectory against, and this recipe's
noise_seed_offsetis 0 so the ancestral arm changes no digest the trace carries.One harness defect, found and fixed in flow. The stage-2 artifact comparison
was
CHECK(a == b)over PPM pixels and a WAV. A failing one dumps raw bytes intothe report, and that killed the mutation harness with a
UnicodeDecodeErrorbetween applying M12 and restoring it — the exact shape #922's spec records. The
finallyrestored the tree, the comparison is now a differing-byte COUNT(
99c4cf811), and the harness decodes witherrors="replace".Gate
On the merged tree at
85e562d1d,origin/main = 589abad12, CLEAN rebuild(
rm -rf buildfirst, because589abad12adds headers and an incremental buildmasks
-Werror):CONFIGURE_EXITBUILD_EXIT: error:in the build logctest -NCTEST_EXIT100% tests passed, 0 tests failed out of 502(2 skipped:test_modelopt_mixed_precision_checkpoint,test_voxtral_e2e)No space left/BFDin the build log502, not 501:
589abad12addstest_ops_conv1d_general. Nothing known-redfired —
test_async_llm(#294),test_engine_core_proc(#1052),test_serve_low_tools(#428) andtest_cpu_x86_llamacpp_floor(#618) are allload-dependent and all passed;
windows-msvc-*(#584) has nomainbaseline anddoes not run here.
Both ltx2 binaries were also run WHOLE, with no
--test-casefilter, and theircase and assertion counts asserted non-zero rather than read as "no failures":
test_ltx2_video74 cases / 2276 assertions /Status: SUCCESS!/ exit 0, andtest_ltx2_pipeline44 / 2598 /SUCCESS!/ exit 0.Status:is grepped besidethe counts because a thrown doctest case prints
0 failednext toFAILURE!,and the exit code is taken directly rather than after a pipe.
What is NOT claimed
No render on real weights, and no oracle-run comparison. The GPU is out of
bounds for this row and
dgx.casais network-alive with an sshd that will nothandshake.
vllm-omniis UNPINNED (#633)and carries no LTX-2.5 recipe; no LTX-2.5 checkpoint here has a recorded sha256
(#1048). Every value is read off
upstream SOURCE at
fd4ded7fand every number is measured on this tree's ownreduced fixture.
The adapter placement diverges and cannot be repaired from the request.
stage_2_loras = (*loras, *distilled_lora)(:114) puts the distilled adapter onstage 2 ALONE, against
loras=tuple(loras)for stage 1 (:107). This enginefuses at load into ONE weight set —
ltx2_video.cpp:816-820is the onlydit_options.loras.push_backin the tree — so stage 1 sees it too. That changesthe trajectory, so it changes the PIXELS: the frames this renders are not the
ones upstream renders for the same checkpoint, take and seed. What it leaves
untouched is the frame count, the shapes, the sample rate and the errors —
nothing in the SHAPE of the result says anything is wrong. It is therefore
#1118 and
## Owedrather thana comment. It bounds #1093 and #921, which need the same seam.
It is not undetectable, and an earlier draft of this paragraph said it was.
"Changes nothing a caller can read" is false — a caller reads pixels — and it is
false in the direction that hides work, because it implies no instrument could
ever see this. The instrument that WOULD see it is the real-weights comparison
against upstream's own render that the section above records this row as not
having: same checkpoint, same take, same seed, upstream's stage 1 on the base
weights against ours on base + distilled. That comparison is owed, not
impossible, and #1118 owns it.
docs/USAGE.mdtells a reader of the a2vidcommand the same thing in the same change.
Two anchors in the dispatch that started this row were wrong and are corrected
rather than propagated. The a2v guidance default is 3.0, at
utils/args.py:986-995throughutils/constants.py:54, not 0.0 ata2vid_two_stage.py:318-323— which is--audio-start-time. And theAudioConditioneris built at:96-102and called at:200, not:53/:143.Six anchors of this row's own, corrected after review. No gate protects an
anchor here (#632), so each was
re-derived from the sentence making the claim rather than by reading the cited
span:
--a2v-guidance-scaleatutils/args.py:987-996:986-995parser.add_argument(opens at:986, the name is at:987, the default at:989, the closer at:995. The old span started at the name and ran one line pastdefault_2_stage_distilled_arg_parseratutils/args.py:1187:1188:1187is blankutils/args.py:947-1006:947-1006--video-cfg-guidance-scaleat:948through--video-skip-stepat:997-1006; the audio group starts at:1007. The old span stopped at the last flag's opening lineLTX_2_3_PARAMSsetsnum_inference_steps=30(utils/constants.py:85),LTX_2_4_PARAMSinherits it (:124), and 2.5 resolves onto that row. 40 is 2.0's own default (:47)LTX_2_3_PARAMSoverrides 2.0's[29]to[28](:86), inherited the same way_PARAMS_SINCE_VERSION(:130-133) has two rows,(2,4)and(2,3), falling through toLTX_2_PARAMSat:179.Ltx2DetectPipelineParamsmirrors that and already said soNeither number was load-bearing — the code reads
params.num_inference_stepsandthe tests assert relatively — which is exactly why nothing caught them. The §2
table also listed
LightricksNegativePrompt()flat where the dispatch useskOmniNegativePrompton2and2.3; that split is which reference owns therow, and
t2a_one_stagesplits identically at the same four versions.include/vllm/multimodal/ltx2_video.h:473carries the same987-996span, butit is on
mainand predates this row, so it is reported rather than rewrittenhere.
This row's own insertions staled anchors elsewhere, and that is reported rather
than swept. Two are repaired here because this row owns them, and both now name
the construct instead of a line range: the spec pointed at
ltx2_pipeline.cpp:1464-1471for thet2a_one_stagerows, which the F4 commentabove them moved in this very commit, and
docs/USAGE.mdpointed atltx2_pipeline.cpp:1306-1313for the DFR refusal, which this row's 145 insertedlines moved to
:1434-1441.FIVE more
docs/USAGE.mdcoordinates moved the same way, in sections this rowdoes not own. Each was re-derived by matching
main's content at the cited lineagainst this tree:
USAGE.md:918ltx2_video.cpp:2900:2968USAGE.md:1170ltx2_video.cpp:1007-1012:1040-1045USAGE.md:1174ltx2_video.cpp:1955-1990:1998-2033USAGE.md:1176ltx2_video.cpp:1991-2004:2034-2047USAGE.md:2672ltx2_pipeline.h:768-803:848-883They are NOT rewritten here. That page states its own convention — "read an
unpinned coordinate as unverified" — and its three
ltx2_video.cppcoordinatesthat sit beside a
@ b5756ea8cpin are implicitly pinned by it and are correctlyunchanged. Its last re-derivation was a scoped unit of work with its own review,
not a rider on someone else's row, and this one should be too.
Two things checked and found NOT to be this row's doing:
USAGE.md:2644citesltx2_video.cpp:377-383forkKnownLoadExtras, which is at:378-385onmainand on this branch alike, so that one is pre-existing (the same passage already
names #1097 for stale text
beside that array).
Merge hazard. The
READER ANCHORSlist inltx2_video.cppis re-derived inthis change (
798 808 809 871 967 983 1018 1109 1134 1239 1280 1322 1324). Aclean
git mergethat inserts a line above it will not warn, andtest_ltx2_videowill.It was re-derived once more after merging
589abad12, with the same walk thetest uses, and is unchanged — that commit adds
vt::Conv1dand touches noLTX-2.5 file. The deriving instrument was armed before it was believed: one
inserted line above the anchors moves all thirteen and it reports
MISMATCH,exit 1, where the real tree reports
MATCH, exit 0. A checker that reads its ownexpectation out of the file it checks is a tautology unless you make it fail
(#911).
.agents/issue-index.mdwas taken deliberately rather than by the union driver:it is untouched by
589abad12, and it is verified against that revision anyway —byte-identical prefix, no base row changed or dropped, every id unique, this
branch appending exactly
#1117and#1118. That check was armed too: editinga base row trips the prefix and row halves, and appending a duplicate id trips
the third.
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [claude-code]