fix(LTX25-TILED-DECODE): chunking binds at 81 frames, and the untiled-axis mapper had no gate (#644) - #746
Open
localai-bot wants to merge 16 commits into
Open
fix(LTX25-TILED-DECODE): chunking binds at 81 frames, and the untiled-axis mapper had no gate (#644)#746localai-bot wants to merge 16 commits into
localai-bot wants to merge 16 commits into
Conversation
…emise it refutes (#644) Spec before code, per AGENTS.md. The row was dispatched on "448x256/25f stops because upstream's default decode is tiled and we call the untiled path". Executed against the pinned upstream (fd4ded7f), that half of the premise does not hold: TileSizeConfig.from_long_side with the Conv auto layout (helpers.py:62-63) resolves to ONE tile and ONE temporal group at 448x256/25f, because split_by_size short-circuits when dim <= size (tiling.py:199-200) and the latent is 8x14 against a 14x24 grid tile, 4 frames against a 10-latent-frame temporal tile. Upstream calls forward() once on the whole volume at that size too. Tiling first binds at 896x512 (spatial) and 121 frames (temporal). The decoder's own buffers at that shape are ~2 orders of magnitude too small to be the 60 GiB: the shipped ladder read from the checkpoint's own metadata gives a peak on the order of hundreds of MB, and the whole pixel tensor is 32.8 MiB. The structural port is still owed (ltx2_video_vae.cpp:17-18 records it) and this spec carries it, together with the derived — not rounded — equivalence bound, the blend mutation that must RED, and the memory measurement that decides the attribution. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…60 GiB is not there (#644) Ports `ConvVideoDecoder.tiled_decode` (conv_video_decoder.py:383-484) with `_accumulate_temporal_group_into_buffer` (:508-557), the interval algebra and separable trapezoidal blend (tiling.py:13-49, 174-361, 423-491, 494-571, 619-841), both axis mappers (video_vae.py:549-592) and the CONV AUTO layout (ltx_pipelines/utils/helpers.py:59-88). Upstream pin fd4ded7f. `ltx2_video.cpp` now decodes through `Ltx2VideoDecodeStreaming` and writes each PPM frame as its temporal chunk arrives, mirroring ti2vid_two_stages.py:365-376. The full pixel volume is never materialized. MEASURED BEFORE BUILDING, and it refutes the dispatching premise twice. 1. Upstream's own AUTO layout is a NO-OP at 448x256/25f. `split_by_size` returns one interval when `dim <= size` (tiling.py:199-200); the latent is 8x14 against a 14x24 grid tile and 4 frames against a 10-latent-frame temporal tile. Executed at the pin and emitted as a golden: 1 tile, 1 group. Tiling first binds at 896x512 spatially and 121 frames temporally. So the size that failed is a size upstream does not tile either. 2. The decode's own memory is 170x too small to be the 60 GiB. Real shipped conv VAE, real 448x256/25f latent decoded to completion, exact operator new accounting: heap peak live 361.72 MiB, largest single allocation 99.20 MiB, decode-attributed RSS 362.23 MiB. The analytic ladder model predicted the largest allocation to three significant figures at two scales. The 60 GiB is NOT attributed by this row and the axis stays open with named next steps. Also newly measured: that decode takes 2681 s (44.7 min) of single-threaded double-precision convolution, so the reported 24-second window cannot have been a completed decode. Separate row; phase L6 owes the production-dtype arm. The equivalence gate the brief asked for does not exist and was not fabricated. Swept across tile sizes and both causality arms, upstream's own max|tiled - untiled| is 0.67-1.29 TIMES the output range and does not converge — the receptive field is wider than the 2-latent-cell overlap. What IS exact is the ONE-TILE CONTROL: a config whose splits all short-circuit reproduces `forward` bit for bit, upstream measures 0 and the port is held to == 0.0. That is what makes the pipeline routing safe at every size run so far. Gates: BUILD_EXIT=0 clean, no ENOSPC/BFD, ctest -N 416, full ctest 416/416. test_ltx2_tiling 9/9 830 assertions; test_ltx2_vae 36/36 3039; test_ltx2_video 30/30 502. Blend mutation (linear ramp -> hard cut) REDs 6/9 cases and 39/830 assertions with tiled max|diff| 1.11411 vs a 5e-6 band, and is caught in four independent places; restored byte-for-byte (md5 e734ee2e35..., rebuild GREEN). FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…-axis mapper had no gate (#644) PR #656 was reviewed FAIL. The reviewer confirmed all three refutations independently, regenerated the tiling goldens byte-for-byte, reproduced the memory probe at three scales and verified `Ltx2VideoDecodeStreaming` bit-identical to the untiled path on the real checkpoint. None of that is re-litigated here. Two blocking findings and six minor ones are closed. F1 (BLOCKING) — the AUTO layout first chunks temporally at 81 frames, not 121. `latent_t = (frames - 1) / 8 + 1` reaches 11 at 81, and `split_temporal_causal` short-circuits only while `latent_t <= 10` (tiling.py:239-240). Executed at the pin over `range(1, 137, 8)`, the interval count goes 1 -> 2 exactly at 81. The row's own golden already said so (`kLtx2AutoCases`: `768x768/81f -> t_intervals = 2, chunks = 2`) and `docs/FEATURES.md` said 81; five prose sites said 121 and are corrected — `ltx2_tiling.h`, `ltx2_video.cpp`, `docs/USAGE.md` and three places in the spec. Root cause, recorded because it is the reusable part: `scripts/probe_ltx2_tiling_layout.py` swept 9, 25, 25, 25, 121, 241 and never sampled a frame count between 25 and 121, so it stepped over its own binding point and the number it happened to land on became the threshold. The probe now WALKS the temporal axis one latent frame at a time and ASSERTS the transition is at 81, naming every file to reconcile if it ever moves. The 81..120 window is stated as a user-visible consequence rather than implied: `docs/USAGE.md` records the recipe default as 1024x1536 at 121 frames, so an ordinary request is inside it. New `scripts/probe_ltx2_tiled_equivalence.cpp` measures it on the SHIPPED conv VAE at 64x64/81f, latent 11,2,2 — 2 tiles, 2 chunks, max|diff| 0.716 against the untiled decode on an output whose own |max| is 0.751, 985849 of 995328 channel values not bit-identical. Upstream's own behaviour, mirrored; but the ONE-TILE CONTROL's safety argument covers below 81 frames and NOT 81..120, and now says so. F2 (BLOCKING) — the `!IsTiled()` branches of `map_t` / `map_s` shipped ungated. Reproduced first: with both `{1.0f}` broadcast masks set to `{0.0f}` — which multiplies the whole decoded volume by zero, i.e. renders a black clip — `test_ltx2_tiling` was 9/9 cases, 830/830 assertions, SUCCESS and `test_ltx2_video` 30/30, 502/502, SUCCESS. Measured rather than assumed, over all eight (frames, height, width) x (tiled, untiled) combinations against upstream at the pin: with frames TILED every spatial combination runs and reproduces `forward` with max|diff| == 0.0; with frames UNTILED every combination raises TypeError at conv_video_decoder.py:424, because `DEFAULT_MAPPING_OPERATION` hands it `slice(0, None)` and :424 subtracts that `None` stop. The two halves are therefore not symmetric and are closed differently: * the SPATIAL half is gated end to end — a new UNTILED_SPATIAL arm in the generator (`kLtx2TileDec*UpstreamUntiledSpatialVsUntiled`, `*UntiledSpatialChunkCount`) and a (B'') control in `RunDecodeArm` on both causality arms; * the TEMPORAL half is REFUSED BY NAME in `Ltx2ConvVideoDecodeTiled`, mirroring upstream's own failure rather than inventing a concrete stop upstream never computes; `kLtx2TileDec*UpstreamUntiledFramesRaises` records that upstream raises, so the refusal is mirrored and not local policy; * the mapper output itself is pinned by new goldens section 3b (`kLtx2UntiledMap*`), upstream's `create_tiles` executed on an all-untiled config. The same black-out mutation now goes RED: 10 cases -> 7 passed / 3 failed, 907 assertions -> 5 failed, exit 1, with `untiled-spatial control max|diff| vs untiled = 2.31736` against upstream's 0. Restored, `git diff` empty, GREEN again. F3 — `ctest -N` is 424, not the 416 recorded. 416 was the ninja edge count of `ninja test_ltx2_tiling test_ltx2_vae test_ltx2_video`, whose last line is `[416/416] Linking CXX executable tests/test_ltx2_video`. The configure line that produces 424 is now recorded next to it. F4 `ltx2_video_vae.cpp:17-18` no longer records tiled decode as owed; the encoder half still is. F5 the shared `Ltx2NoiseStream*` across tiles is documented at the declaration and recorded under "What is owed" — it mirrors upstream and is inert on the shipped checkpoint, but a noise-drawing config has no gate. F6 a new multi-chunk `test_ltx2_video` case drives `chunk.first_frame + f` through the PPM writer at 81 frames; per-chunk numbering goes RED at 35 assertions. F7 a previous render's frame tail is deleted before a new render writes, so a shorter re-render can no longer be muxed past its own end; disabling the cleanup goes RED at 72 assertions. F8 the "never materialized" claim is bounded to the tiled case at both anchors. F9 the compile line for both probes is recorded in their headers. F10 the fixture's `res_x_y` block is disclosed in the test header. Gate on 424 tests, clean `rm -rf build` + reconfigure: `cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release`, `BUILD_EXIT=0`, `No space left|BFD assertion` count 0, 0 warnings, `df -h /` 94% -> 95%. `ctest -N` 424; full `ctest` 424/424 passed, 0 failed, `CTEST_EXIT=0`. Focused with COUNTS: `test_ltx2_tiling` 10/10 907/907 (was 9/9 830/830), `test_ltx2_vae` 36/36 3039/3039, `test_ltx2_video` 31/31 673/673 (was 30/30 502/502), `test_ltx2_pipeline` 37/37 2382/2382. The goldens regenerate byte-identically apart from the 23 added lines. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
Forward-merge so the review-response gate runs against current main. Two keyed records conflicted and were resolved by taking main's version wholesale and reapplying only this row's scoped edit: * `.agents/roadmap_v1.md` #644 — main rewrote the row as the LTX-2.5 FULL PORT campaign naming Row 0 `LTX25-PROMPT-ADALN`; the Row 2 `LTX25-TILED-DECODE` sentence is reapplied onto main's cell rather than replacing it. * `docs/FEATURES.md` — main's rewritten `LTX-2.5 DiT` row is taken whole; the separate `LTX-2.5 tiled + streaming Conv VAE decode` row is a different key and is kept as this branch has it. No automatic three-way merge of a keyed record was accepted, and every unrelated key was verified byte-for-byte. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
Main landed 67dc0aa (`MODEL-MM-indextts2`: the DiT's WaveNet final layer, #738) between the previous forward-merge and this gate, so the gate runs against it rather than against a main that no longer exists. No conflicts. Verified rather than assumed, because a lost add is exactly what a clean auto-merge hides: `tests/CMakeLists.txt` still registers `test_wavenet` and `tests/vllm/models/test_wavenet.cpp` is present, and this branch's own keys — `docs/FEATURES.md`'s `LTX-2.5 tiled + streaming Conv VAE decode` row and `.agents/roadmap_v1.md`'s #644 row — are unchanged. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…tts2, MSVC fixes) Main landed four more commits while this row's gate was running — b203871 (`MODEL-MM-dots3-note` scope, #705), 25861b6 (indextts2 offline conversion, #742), 0011bed (#720, `M_PI` under MSVC) and f8cbc23 (#664, the video registry's Windows existence probes). The gate is re-run against them rather than against a main that no longer exists. No conflicts. Verified rather than assumed, because a clean auto-merge is exactly what hides a lost edit on a keyed record: * `.agents/model-matrix.md` now carries main's 371 -> 373 / 375 -> 377 rollup with `Dots3NoteForCausalLM` and `Dots3NoteMTPModel` restored — that delta was main moving, not this branch reverting it; * this row's own keys are unchanged — `.agents/roadmap_v1.md`'s #644 row, `docs/FEATURES.md`'s `LTX-2.5 tiled + streaming Conv VAE decode` row, and the `ltx2_video_vae.cpp` header note recording that the tiled decode is no longer owed. Note for the record: f8cbc23 touches `video_engine.cpp`, which this branch does not, and no part of this merge touches `ltx2_loader.cpp`'s alignment code (#627). FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…16 that was a build number (#644) Replaces the `## Outcome` gate block with the run this branch actually performed after two forward-merges, and closes F3 of the PR #656 review. **F3 — `ctest -N` was recorded as 416 and does not reproduce.** It never could: 416 is the ninja EDGE count of `ninja test_ltx2_tiling test_ltx2_vae test_ltx2_video`, whose last line is `[416/416] Linking CXX executable tests/test_ltx2_video`. A build number was read as a test number, so "full ctest 416/416" describes a run that never happened at that denominator. The configure line is now recorded next to the number, because a denominator without one cannot be reproduced. The denominator moved twice while this gate ran — 424, then 445, then 448 — and that drift is ATTRIBUTED rather than asserted: `git diff origin/main -- tests/CMakeLists.txt` is exactly +7 lines, this row's `test_ltx2_tiling` registration, with no target added or removed anywhere else. This branch is main's count plus one by construction, whatever main's count happens to be that hour. Gate at this head: clean `rm -rf build` + reconfigure, `BUILD_EXIT=0` captured separately from the run, `No space left|BFD assertion` count 0, warnings 0, `df -h /` 89% -> 98%, build directory deleted immediately after. `ctest -N` 448; full `ctest` 447 passed / 1 failed of 448, 438.02 s, with 448 `N/448 Test` lines in the log so the run's own denominator is asserted against `-N` rather than assumed. Focused with COUNTS: `test_ltx2_tiling` 10/10 907/907, `test_ltx2_vae` 36/36 3039/3039, `test_ltx2_video` 31/31 673/673, `test_ltx2_pipeline` 37/37 2382/2382. The single failure is `test_op_parity`, and it is not this row's: test_op_parity.cpp:1989: ERROR: test case THREW exception: [json.exception.type_error.302] type must be string, but is null a null field in the MiniMax-Music3 golden manifest that landed on main the same day, filed as #737 and already reproduced on clean main. This branch touches no parity path — `git diff origin/main --name-only` matches nothing under `tests/parity/` and no music3 file. Two preflight gates also red at this head and neither is this row's: `audit-live-rows` / `test_audit_live_rows` fail on the stale ACTIVE row `MODEL-MUSIC-minimax-music3-...`, and this branch changes no matrix file at all — its only record edits are `.agents/roadmap_v1.md`'s #644 row and this spec — so those records are byte-identical to main's. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…real weights) Main landed 5e646d9 (`MODEL-MM-indextts2`: the ported DiT on the real shipped weights, #743) between this row's gate and its push. Merged forward so the pushed head is a descendant of main rather than a fast-forward refusal at push time. No conflicts. Verified rather than assumed: this row's keys are unchanged — `docs/FEATURES.md`'s `LTX-2.5 tiled + streaming Conv VAE decode` row and `.agents/roadmap_v1.md`'s #644 row — and the branch's whole record delta versus main remains those two files plus its own spec, with `tests/CMakeLists.txt` differing by exactly the `test_ltx2_tiling` registration. This merge changes no compiled source this row owns, so the gate recorded in `.agents/specs/ltx25-tiled-decode.md` stands: `test_ltx2_tiling` 10/10 907/907, `test_ltx2_vae` 36/36 3039/3039, `test_ltx2_video` 31/31 673/673, `test_ltx2_pipeline` 37/37 2382/2382, full `ctest` 447/448 with the single failure being #737's MiniMax-Music3 golden manifest on clean main. CI re-runs the suite on this exact head, which is the check that covers main's own new sources. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…oning front end) Main landed 5e646d9 and d374e83 (`MODEL-MM-indextts2`, #743 and #745) while this row was finishing its handoff checks. Merged forward so the pushed head is a descendant of main; a rejected push would otherwise be git protecting someone else's merge. No conflicts. Verified rather than assumed: after this merge the branch's entire record delta versus main is `.agents/roadmap_v1.md` and its own spec, and the roadmap delta is exactly ONE line — the Row 2 sentence inside issue #644's cell. `docs/FEATURES.md`'s `LTX-2.5 tiled + streaming Conv VAE decode` row and `tests/CMakeLists.txt`'s `test_ltx2_tiling` registration are the only other keys this branch owns, and both are intact. Three preflight gates are red at this head and none is this row's, recorded here so the next reader does not re-derive it: * `audit-live-rows` and `test_audit_live_rows` fail on the stale ACTIVE row `MODEL-MUSIC-minimax-music3-...`, which lives in `.agents/model-matrix.md` — a file this branch does not touch at all, so its input is byte-identical to main's; * `test_cpu_x86_llamacpp_floor` exits `NO_QUIET_WINDOW` (busy 125%, load 78) with several agents building on the shared box, which is the documented failure mode of that floor test rather than a regression. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…ncoder, music3 W2/W3) The reviewed head 3fcfba4 was 7 commits behind origin/main, which made the PR's `git diff origin/main -- tests/CMakeLists.txt` claim read as four targets REMOVED (test_dit_stack, test_indextts2_talker_loader, test_minimax_music3_ar, test_minimax_music3_ar_real) rather than one added. After this merge that diff is exactly +7 lines again — the row's own `test_ltx2_tiling` registration — and `vllm_cpp_add_test(` goes 431 on main to 432 here. `docs/FEATURES.md` conflicted and is a KEYED record, so it is NOT an automatic three-way merge: main's file was taken wholesale with `git checkout origin/main --`, and this row's single key (`LTX-2.5 tiled + streaming Conv VAE decode`) was reapplied on top. `git diff origin/main -- docs/FEATURES.md` is one added line and nothing else. `.agents/roadmap_v1.md` likewise differs from main by its one `#644` row, in place. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5[1m] [claude-code]
… the probe was measuring its own transposition (#644) Answers the FAIL review of PR #746. Issue #644, spec `.agents/specs/ltx25-tiled-decode.md`. BLOCKING — the headline number was a measurement artifact. `scripts/probe_ltx2_tiled_equivalence.cpp` reassembled the streamed chunks with a flat `insert(streamed.end(), chunk.frames.data.begin(), ...)`. A chunk is [C, t, H, W] CHANNEL-MAJOR (ltx2_video_vae.h:211-219), so that append yields [c0 t0..][c1 t0..][c2 t0..][c0 t1..].. — not [C, T, H, W] once C > 1 AND there is more than one chunk, and the published run is [3,81,64,64] with chunks=2, so both hold. It was comparing channel 1 against channel 0's later frames. The probe even carried a comment asserting the opposite ("the C-major layout means the comparison below is elementwise regardless"); that comment was the error, and the row's own test (Collected::Concat in tests/vllm/models/test_ltx2_tiling.cpp) had the correct reassembly all along. Re-derived on the real ltx-2.5-video-vae-conv-bf16.safetensors, same request: committed probe : max|diff| = 0.71614238619804382 985849 / 995328 corrected probe : max|diff| = 0.050304323434829712 962983 / 995328 both : untiled |out|max = 0.75126725435256958 So 6.70% of the output's own range, not 95% — a factor of 14. The corrected probe prints the flat-append figure as a labelled diagnostic, so both columns come out of ONE binary on ONE run and the artifact is reproducible rather than argued. The QUALITATIVE conclusion survives: 96.75% of values still move, 81..120 frames is still a tiled regime the one-tile control does not cover, and the refusal stands. Corrected at all four published sites — ltx2_tiling.h, ltx2_video.cpp, docs/USAGE.md (user-facing) and the spec — plus docs/FEATURES.md. The spec's Outcome now records that this is the THIRD number in campaign #644 to move by a large factor the first time anyone re-derived it: 60 GiB measured 361.72 MiB (170x), "121 frames" measured 81, and 95% measures 6.70% (14x). That self-record is worth more than the number. F1-b — the walk's density was a comment, not an assertion. Reproduced first: the committed scripts/probe_ltx2_tiling_layout.py with its step changed 8 -> 80 and nothing else exits 0 and prints "first splits at 81 frames" after examining two frame counts, skipping latent_t 2..10; saw_untiled and `first_tiled is not None` cannot see that. The walk now asserts it starts at latent_t 1, that consecutive steps move latent_t by exactly 1, and that the transition is 10 -> 11 — the short-circuit's own bound (tiling.py:239-240). The same mutation on the repaired probe exits 1 ("the walk is NOT dense: latent_t jumps [(1, 11)]"); unmutated it exits 0 over 17 densely walked frame counts. MODERATE — the recorded `ctest -N` no longer described the head. Merged origin/main (7 commits) and re-measured: 456 here against 455 on main @ 7b8919d with the same command in this tree, the one added listing being `Test #60: test_ltx2_tiling`; `vllm_cpp_add_test(` goes 431 -> 432 and `git diff -- tests/CMakeLists.txt` is +7 lines with nothing removed. The "448 N/448 lines" line is restated as what it is — a `grep -c` compared against `ctest -N`'s total, both commands recorded — and no longer cited as a committed instrument. MINOR — the "upstream raises" golden pinned the type, not the reason. A bare `except TypeError` kept the constant at 1 for any future TypeError from any line. The generator now walks the traceback to the innermost frame and emits *UpstreamUntiledFramesRaiseFile / RaiseLine / RaiseMessage (measured: conv_video_decoder.py, 424, "unsupported operand type(s) for -: 'NoneType' and 'int'"), with generator-side assertions on the file and message. Goldens regenerate byte-identically apart from those 6 added lines. MINOR — ltx2_video_vae_tiled.cpp said every frames-tiled arm "reproduces `forward` exactly". That holds only where the frames tile exceeds the axis; where it splits, kLtx2TileDecCausalUpstreamTiledVsUntiled is 2.13274002 against an OutputSpan of 2.31735897. Bounded to the one-tile and untiled-spatial controls, which are the arms actually pinned at 0. Gate. Clean `rm -rf build` + `cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release` + `ninja -C build -j4`, BUILD_EXIT=0, 0 warnings, `No space left|BFD assertion` count 0 against a positive control of 462 "Building" lines. df / 89% -> 96%; build directory deleted after the gate. `ctest -N` 456; full `ctest -j4 --output-on-failure` 455 passed / 1 failed of 456, exit 8, with 456 lines matching `^ *[0-9]+/456 Test`. The one failure is test_op_parity (#737, a null in the Music3 golden manifest) which prints "assertions: 70 | 70 passed | 0 failed" while failing; this branch matches nothing under tests/parity/ or any music3 file. test_ltx2_tiling 10/10 915/915 (was 907; +8 = 4 new CHECKs x 2 arms) test_ltx2_vae 36/36 3039/3039 test_ltx2_video 32/32 684/684 (+1 case / +11 assertions arrive with fc903b8 (#674) on main, not this row) test_ltx2_pipeline 37/37 2382/2382 RED-first for the new assertions, goldens mutated in place and restored, verified by sha256 (bf2bdb4d…), rebuilt GREEN each time: RaiseLine 424 -> 425 : 8/10 cases, 2 failed assertions, exit 1 RaiseFile/RaiseMessage -> wrong values : 8/10 cases, 6 failed assertions, exit 1 docs/FEATURES.md and .agents/roadmap_v1.md are keyed records: verified to differ from main @ 7b8919d by exactly this row's one key each. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5[1m] [claude-code]
…, image conditioning landed) 48 commits of main, resolved against pinned `origin/main` = 51e0cb5 rather than the moving ref, because this is a shared checkout and a peer's fetch advances `origin/main` mid-operation. Two keyed records conflicted, and neither was resolved by an automatic three-way merge. Both took main's file whole, and the scoped edit was reapplied by key. `.agents/roadmap_v1.md` is now byte-identical to main. This branch's only edit to it was one row of the issue intake table, and #846 moved that table out of the file into the append-only `.agents/issue-index.md`. The #644 row is already there, already current, and already names Row 0 and Row 1. `check-issue-index-append-only.py` refuses an edit to an existing row because `merge=union` duplicates one rather than merging it, and `check_issue_index` refuses a second #644 row. So the scoped edit has no admissible target on the new surface: the prose about Row 2 belongs in the row's spec, which carries it. Reapplying it anywhere would have been a gate failure, not a record. `docs/FEATURES.md` differs from main by exactly one added line, this row's own `LTX-2.5 tiled + streaming Conv VAE decode` key. Every other key is byte-identical to main, including the `Safetensors direct load, no conversion` row, which was duplicated at this branch's head and is single on main (#769) — taking main whole resolves it without this branch either fixing or multiplying it. Five files auto-merged against `c629b5d0f`, the same campaign's image conditioning row, and a clean `merge-tree` is not a tree that builds. Checked by semantics rather than by the absence of a conflict: `CMakeLists.txt` +6 and `tests/CMakeLists.txt` +7 are this row's two translation units and its one test target, so `ctest -N` on this tree is main's count plus one, by construction. `src/vllm/multimodal/ltx2_video.cpp` drops the `rendered` buffer the counterparty never referenced, hoists the only `std::error_code ec` in `Generate`, and adds `video_factors`, which does not collide with the pre-existing `factors` at :1345. `tests/vllm/multimodal/test_ltx2_video.cpp` appends one case that uses only helpers the counterparty left in place. `docs/USAGE.md` appends a section after the counterparty's own conditioning prose. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…ses, and two goldens went into C literals unescaped (#644) Closes the two nits from the records review of PR #746. The blocking half of that review was about the pull request description and the merge, and is handled by the rewritten body and the preceding merge commit; this commit is the tree half. The walk in `scripts/probe_ltx2_tiling_layout.py` requires `latent_t` to advance by exactly 1 per step, which is correct for the anti-fake purpose and fails in BOTH directions. A step of 4 pixel frames repeats a latent depth, because `latent_t = (frames - 1) // 8 + 1` is constant across 8 consecutive frame counts, so it trips the same assertion as a step of 80 that skips nine depths. The message named only the skipping half, so a future editor tightening the sweep would have read "the walk is NOT dense: latent_t jumps [(1, 1), ...]" as upstream moving the bound. It now names both causes and the fix each needs. Reproduced rather than argued: step 8 -> 80 exits 1 over 2 frame counts, step 8 -> 4 exits 1 over 34, and unmutated the probe exits 0 over 17 densely walked frame counts and prints "first splits at 81 frames". Each mutant is a copy outside the tree, and the tree's sha256 was verified unchanged after every run. `scripts/gen-ltx2-tiling-goldens.py` emitted `untiled_frames_raise_file` and `untiled_frames_raise_message` into C string literals with an f-string quote. Both are UPSTREAM text: a future `TypeError` message or a checkout path carrying a `"` or a backslash would have produced a golden that does not compile, while the generator exited 0 and looked like it had succeeded. Loud rather than silent, so this was filed as a nit, but `json.dumps` costs nothing and JSON string escaping is a subset of C's for these bytes. Byte-identity on today's values is measured, not assumed: a full regeneration to a scratch path yields sha256 bf2bdb4d43e73d4da73e360a816ee20e5f4b9224902fab9486fb173822a41d12, equal to the committed `ltx2_tiling_goldens.inc`, with `diff` exit 0. The negative control shows the old form emitting `"a "quoted" word and a \ backslash"` where the new one emits `"a \"quoted\" word and a \\ backslash"`. The spec records both, the records review they answer, and a re-measured gate on the merged head: `ctest -N` 473 here against 472 on main @ 51e0cb5, focused 10/915, 36/3039, 34/747, 37/2382, full 472 passed / 1 failed of 473 whose one failure passes serially. `test_op_parity` is green here, so the recorded 1-of-456 red at the pre-merge head was a missing fix rather than a standing red. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…nputs_embeds) One commit, `b5a5f3b18`, taken against that pinned SHA rather than the moving ref. `docs/FEATURES.md` conflicted again, and for the reason the record rules predict: its MiniMax-Music3 row sits immediately above this row's key, so any edit to either lands in the same hunk. Resolved the same way as the previous merge — main's file taken whole, then this row's single `LTX-2.5 tiled + streaming Conv VAE decode` key reapplied. `git diff b5a5f3b -- docs/FEATURES.md` is that one added line and nothing else, so every unrelated key, including the Music3 row this merge updates, is byte-identical to main. `.agents/roadmap_v1.md` and `.agents/issue-index.md` are byte-identical to main and were not touched. `CMakeLists.txt`, `tests/CMakeLists.txt` and `docs/USAGE.md` auto-merged. Checked by content rather than by the absence of a conflict: the two CMake diffs against main are exactly this row's two translation units and its one `vllm_cpp_add_test` registration, and `docs/USAGE.md` is this row's appended section. The incoming commit adds tests, so the `ctest -N` denominator moves and is re-measured on both sides at this head. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…ch is 474/474 green (#644) The spec's `### The gate` described `70fddfa32`, and two forward merges have moved the head since. Each recorded denominator describes only the head it was taken on, so the pre-merge record is kept below rather than overwritten, and this one is added above it. Measured on `e34e10e37`, which merges main @ `b5a5f3b18`. Clean `rm -rf build` + reconfigure + `ninja -C build`: `BUILD_EXIT=0` captured separately from the run, `[1407/1407]` reached, `No space left|BFD assertion` count 0 against a positive control of 925 `Building CXX` lines in the SAME log, `warning:` count 0. `ctest -N` is 474 here and 473 on main, measured with the same command in the same tree. `test_ltx2_tiling` is Test #73 in this listing and absent from main's, the `tests/CMakeLists.txt` diff against main is exactly +7 lines for that one registration, and `grep -c '^vllm_cpp_add_test('` goes 448 to 449. Main's side was configured from main's own two CMakeLists.txt files into a scratch directory that was deleted; both files were restored and verified by sha256sum rather than by `git status`. Focused, with counts: test_ltx2_tiling 10/915, test_ltx2_vae 36/3039, test_ltx2_video 34/747, test_ltx2_pipeline 37/2382. The move from 32/684 is MAIN's — `grep -c '^TEST_CASE('` is 33 on main and 34 here, and the diff against main adds exactly one case and removes none. Full ctest: 474 passed / 0 failed of 474, 168.50 s, exit 0, with 474 lines matching `^ *[0-9]+/474 Test` so the run's own denominator is compared against `ctest -N` rather than assumed equal to it. There is no known-red left. `test_op_parity` is green, so the previously recorded 1-of-456 was a missing fix rather than a standing red, and `test_serve_low_tools` — which starved in the intermediate `-j6` run at load average 90-133 and passed serially — passes in the parallel run on the quieter box. The equivalence probe was rebuilt from this head's libvllm.a and re-run against the checkpoint asserted by sha256. Its output is byte-identical to the run on the previous head, from a different build: two builds, two runs, one result. 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.
Answers the FAIL review of PR #656 and the records FAIL review of this PR. Issue #644, spec
.agents/specs/ltx25-tiled-decode.md.Two reviewers have confirmed the engineering independently: all three refutations reproduced, the tiling goldens regenerated byte-for-byte, the memory probe reproduced at three scales, and
Ltx2VideoDecodeStreamingverified bit-identical to the untiled path on the real checkpoint. None of that is re-litigated below. Every finding from both reviews is closed with reproduced RED/GREEN evidence.F1 (BLOCKING) — temporal chunking binds at 81 frames, not 121
latent_t = (frames - 1) / 8 + 1reaches 11 at 81 frames, andsplit_temporal_causalshort-circuits only whilelatent_t <= 10(tiling.py:239-240). Executed against upstream at the pin overrange(1, 137, 8), the interval count goes 1 → 2 exactly at 81.The row's own golden already said so —
kLtx2AutoCasescarries768x768/81f -> t_intervals = 2, chunks = 2— anddocs/FEATURES.mdsaid 81. Five prose sites said 121 and are corrected:ltx2_tiling.h,ltx2_video.cpp,docs/USAGE.md, and §0 / §1 / §2 of the spec.Root cause, recorded because it is the reusable part.
scripts/probe_ltx2_tiling_layout.pyswept 9, 25, 25, 25, 121, 241 — it never sampled a frame count between 25 and 121, so it stepped over its own binding point and the number it happened to land on became the threshold. The probe now walks the temporal axis one latent frame at a time and asserts the transition is at 81, naming every file to reconcile if it ever moves. A sweep that skips its binding point now fails instead of publishing a number.The 81–120 window is stated, not implied.
docs/USAGE.mdrecords the recipe default as 1024x1536 at 121 frames, so an ordinary request is inside it.scripts/probe_ltx2_tiled_equivalence.cppmeasures it on the shipped conv VAE (ltx-2.5-video-vae-conv-bf16.safetensors,sha256 685b06ee3d9b2039647698fc4ea33175112462fc374e2777312c907897dfce8d) at81 64 64:96.75% of channel values move, by up to 6.70% of the output's own range. That is upstream's behaviour, mirrored — but the one-tile control's safety argument covers below 81 frames and not 81–120, and now says so.
That headline was
0.716— "95% of the output's own range" — until it was re-derived, and it was 14x too large. The probe reassembled the streamed chunks with a flat append, and a chunk is[C, t, H, W]CHANNEL-MAJOR (ltx2_video_vae.h:212-220), so appending buffers end to end is not[C, T, H, W]onceC > 1and there is more than one chunk — both true here (C = 3,chunks = 2). It was comparing channel 1 against channel 0's later frames. The refuted figure is kept named as refuted, and the corrected probe prints it as a labelled diagnostic on every run, so both columns come out of one binary on one run:max|diff||out|maxThe qualitative conclusion is untouched — nearly every value still moves, 81–120 is still a tiled regime the one-tile control does not cover, and the refusal stands. Only the magnitude was wrong, and it was wrong in the direction that made the argument look stronger.
F2 (BLOCKING) — the
!IsTiled()mapper branches shipped ungatedReproduced first. With
map_t/map_s's{1.0f}broadcast masks set to{0.0f}— which multiplies the entire decoded volume by zero, i.e. renders a black clip — at the reviewed head:Measured rather than assumed. Swept over all eight (frames, height, width) × (tiled, untiled) combinations against upstream at the pin:
tiled_decodemax|diff|vsforward== 0.0conv_video_decoder.py:424because
DEFAULT_MAPPING_OPERATIONhands itslice(0, None)and:424subtracts thatNonestop. The two halves are therefore not symmetric, and are closed differently:UNTILED_SPATIALarm in the generator (kLtx2TileDec*UpstreamUntiledSpatialVsUntiled,*UntiledSpatialChunkCount) and a(B'')control inRunDecodeArmon both causality arms;Ltx2ConvVideoDecodeTiled, mirroring upstream's own failure rather than inventing a concrete stop upstream never computes.kLtx2TileDec*UpstreamUntiledFramesRaisesrecords that upstream raises, so the refusal is mirrored and not local policy;kLtx2UntiledMap*), upstream'screate_tilesexecuted on an all-untiled config.The same black-out mutation now goes RED: 10 cases → 7 passed / 3 failed, 907 assertions → 5 failed, exit 1, with
untiled-spatial control max|diff| vs untiled = 2.31736against upstream's 0. Restored (git diffempty), rebuilt GREEN.F3 — the recorded
ctest -Ndid not reproduceIt never could. 416 was the ninja edge count of
ninja test_ltx2_tiling test_ltx2_vae test_ltx2_video, whose last line is[416/416] Linking CXX executable tests/test_ltx2_video— a build number read as a test number, so "full ctest 416/416" describes a run that never happened at that denominator. The real value and the configure line that produces it are recorded together under The gate below.F4–F10
ltx2_video_vae.cpp:17-18no longer records tiled decode as owed; the encoder half still is.Ltx2NoiseStream*across tiles is documented at the declaration and recorded under What is owed. It mirrors upstream (self.forwardper tile, one generator) and is inert on the shipped checkpoint (timestep_conditioning: false, noinject_noise); a gate over a noise-drawing config is owed.test_ltx2_videocase driveschunk.first_frame + fthrough the PPM writer at 81 frames. Per-chunk numbering goes RED at 35 assertions.res_x_yblock (a global GroupNorm the shipped ladder lacks) is disclosed in the test header, with which claim it affects and which it does not.The records review of this PR — what closed each finding
F-A (BLOCKING) — this description still published the number the cycle exists to retract. The tree was corrected at five sites; the surface a merger reads was not. This body carried
max|diff| = 0.716…, "99.05% of channel values move, by up to 95% of the output's own range", and actest -Nof 448. That is this row's own defining failure — a 14x-wrong headline on a reader-facing surface — live on the pull request whose subject is repairing it. Closed by rewriting the body from a fresh run of the probe, by its own recorded recipe, on the merged head; the refuted figure stays, named as refuted, because a correction that deletes the wrong number teaches nothing.F-B (BLOCKING) — 48 commits behind, two keyed records in conflict.
git merge-tree --write-treeexited 1 with content conflicts in.agents/roadmap_v1.mdanddocs/FEATURES.md, both keyed records that must never take an automatic three-way merge. Both took main's file whole against a pinnedorigin/mainSHA — never the moving ref, because this is a shared checkout and a peer's fetch advances it mid-operation..agents/roadmap_v1.mdis now byte-identical to main: this branch's only edit to it was one issue-intake row, and #846 moved that table into the append-only.agents/issue-index.md, where the #644 row already exists and is current, and wherecheck-issue-index-append-only.pyforbids editing a row andcheck_issue_indexforbids duplicating one.docs/FEATURES.mddiffers from main by exactly one added line, this row's own key; every unrelated key is byte-identical, including theSafetensors direct load, no conversionrow that was duplicated at the old head and is single on main (#769). The five silent auto-merges againstc629b5d0f(the same campaign's image conditioning) were checked by semantics rather than by the absence of a conflict — a cleanmerge-treeis not a tree that builds — and the result rebuilt and re-gated from scratch.F-C — the recorded
test_op_parityred was expected at the old head and is gone.043e56862(fix(GATE-OP-PARITY-MANIFEST), closes #755) is in main and is not in the old head's ancestry (git merge-base --is-ancestorexit 1, positive control on the merge base exit 0). The 1-of-456 failure was therefore a missing fix, not a standing red, and it does not reproduce on this merged head.F-D (nit) — the density assertion's message named only one of its two causes. The walk requires
latent_tto advance by exactly 1 per step, so a step finer than 8 pixel frames repeats a depth and fails too — correct for the anti-fake purpose, but a future editor tightening the sweep would read the failure as "upstream moved the bound". The message now names both directions and says which fix each needs. Both mutations reproduce: step8 → 80exits 1 (latent_t jumps [(1, 11)], 2 frame counts visited) and step8 → 4exits 1 (17 zero-jumps, 34 frame counts visited); unmutated it exits 0 over 17 densely walked frame counts.F-E (nit) — the raise-mechanism goldens were emitted into C string literals unescaped. A future upstream message or checkout path carrying a
"or a backslash would have produced a golden that does not compile, while the generator reported success. Both fields now go throughjson.dumps. On today's values the output is byte-identical, proven rather than argued: the regenerated file'ssha256isbf2bdb4d43e73d4da73e360a816ee20e5f4b9224902fab9486fb173822a41d12, equal to the committed one,diffexit 0.The gate
Head
84e2ec8ee67c839817a2f932dd81dc3c03dd4432, whose tree ise34e10e37b892dc36167fa677c845850ba2445e2plus this spec's gate record; the gate itself was run one34e10e37, which merges main pinned atb5a5f3b182d7e8c1b4b3781da32726d3d6eda5ec. Two merge commits, each resolved against a pinned SHA rather than the moving ref:02444f5ff(main @51e0cb5b1, 48 commits, the two keyed-record conflicts of F-B) ande34e10e37(main @b5a5f3b18, whose Music3 row sits immediately above this row'sdocs/FEATURES.mdkey and conflicts for that reason alone; resolved the same way). Every number below is from this head — nothing is carried forward.Clean
rm -rf build+cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release+ninja -C build.BUILD_EXIT=0captured separately from the run,[1407/1407]reached.No space left|BFD assertioncount 0 against a positive control of 925Building CXXlines in the same log;warning:count 0.df -h /80G free (82%) at the end;uptimeload average 30.2. The build directory was deleted immediately after the gate.ctest -Nis 474 here and 473 on main, measured with the same command and attributed rather than asserted:test_ltx2_tilingisTest #73in this listing and absent from main's (grep -c1 here, 0 there),git diff b5a5f3b18 -- tests/CMakeLists.txtis exactly+7lines (that one registration) with no target added or removed anywhere else, andgrep -c '^vllm_cpp_add_test('goes 448 on main to 449 here. Main's side was measured by configuring main's own twoCMakeLists.txtfiles in a scratch build directory, which was deleted; both files were restored and verified bysha256sum, not bygit status.Focused, with COUNTS — a changed count is RED unless attributed:
test_ltx2_tilingtest_ltx2_vaetest_ltx2_videogrep -c '^TEST_CASE('is 33 on main and 34 here, andgit diff b5a5f3b18on that file adds exactly oneTEST_CASEand removes nonetest_ltx2_pipelineFull:
ctest --test-dir build -j6 --output-on-failure→ 474 passed / 0 failed out of 474, 168.50 s,ctestexit 0, with 474 lines matching^ *[0-9]+/474 Testin the log, so the run's own denominator is asserted againstctest -Nrather than assumed equal to it. Two tests reportSkippedby their own guards (test_modelopt_mixed_precision_checkpoint,test_voxtral_e2e).Known-red
None in this gate. Two are worth recording because they were expected and did not happen:
test_op_parityis GREEN (Test #422). Its recorded 1-of-456 red at the pre-merge head was a missing fix rather than a standing red — see F-C above.test_serve_low_toolsfailed in the intermediate-j6run at0bf0eb9a8under load average 90–133 and passed serially in 23.54 s; on the quieter box at this head it passes in the parallel run too. It is-jstarvation, not a regression.test_cpu_x86_llamacpp_floor(#618),windows-msvc-*(#664/#720/#757) andsanitize-cpu(#627) are the in-flight repo-wide reds; untouched here.scripts/agent-preflight.shpasses at this head,test_cpu_x86_llamacpp_floorincluded.🤖 Generated with Claude Code