Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .agents/issue-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@ rather than merged. `scripts/check-agent-record.py` gates both.
| [#1471](https://github.com/mudler/vllm.cpp/issues/1471) | `LTX25-DEVICE-RESIDENCY` | **`vt::Conv2d` and `vt::DepthwiseConv1d` compute their output extents with C++ integer division, which truncates toward zero, where torch's shape contract FLOORS.** `src/vt/ops.cpp:2749-2750` (`hout`/`wout`) and `:2883` (`lout`). The two agree for a non-negative numerator and disagree for a negative one whenever `stride > 1`: at `in = 2, k = 3, stride = 2, pad = 0` the numerator is -1, so torch computes `floor(-1/2) + 1 = 0` and raises "Output size is too small" while truncation computes `-1/2 + 1 = 1` and ACCEPTS an extent of 1, convolving over taps the stride skipped. The `VT_CHECK(... > 0)` guard below each line cannot catch it, because truncation has already produced a positive extent. Found by the fresh review of [#1007](https://github.com/mudler/vllm.cpp/issues/1007) (finding F7) against the sibling `vt::Conv3d`, which carried the identical expression and is FIXED on that row: the span is separated from the division and a negative span is refused by name, proven by mutation — reverting the guard reds *conv3d: the shape contract refuses by name* at exit 1 (`CHECK_THROWS` did not throw, `tests/vt/test_ops_conv3d.cpp:446`), restoring it gives 4/4 and 2036 assertions, both arms BUILT=YES with 0 compile errors. NOT FIXED IN FLOW: extending the repair means two more red-first cases and a fresh review over ops #1007 does not own, and **no caller is yet known to reach either path** — the LTX-2.5 `CausalConv3d` geometry that motivated the Conv3d fix materialises a pad of at least the kernel, and the audio-encoder `kConv2d`/`kDepthwiseConv1d` callers are unaudited, which is part of the owed work. `Conv1dOutLength` (`:2886`) and `ConvTranspose1dOutLength` already guard it correctly with an explicit negative-span return, so three of the five conv wrappers use the right shape already. Listed under `## Owed` in [`ltx25-device-residency.md`](specs/ltx25-device-residency.md) | bug |
| [#1466](https://github.com/mudler/vllm.cpp/issues/1466) | `MODEL-MUSE-GLIMMER` | **`tests/vllm/models/test_muse_glimmer_text.cpp:532`'s `CHECK(diff <= 5e-4)` is a rounded-up W1 measurement, and one correct kernel change already spent 45 points of its 76-point margin.** `3a54c4b7d`'s own body quotes the number the constant was rounded up from ("max abs diff 1.21e-4 on logits of max 4.88e-2"); there is no derivation beside it. `4712dac40` narrowed `act(gate)` to the input dtype — upstream's polarity, and the only form that reproduces the committed `silu_and_mul_bf16_8x256` oracle golden bit-exactly — and grew the envelope 2.8x to 3.43e-04, which is 0.687 of the bound (measured at `aeba0de6f`, CPU-only Release, x86_64). It is the last member of that class in this file: [#1458](https://github.com/mudler/vllm.cpp/issues/1458) replaces the other one (`bdiff <= 1e-5`) in the same case and leaves this one to its own derivation, because a bigger constant is not a repair. Found in flow while gating #1458 (PR [#1461](https://github.com/mudler/vllm.cpp/pull/1461)); also listed under `## Owed` in [`muse-glimmer.md`](specs/muse-glimmer.md) | bug |
| [#1467](https://github.com/mudler/vllm.cpp/issues/1467) | `MODEL-DIFFUSION-ltx-2-5-ltx2-video-transformer-3d-model` | **The ltx2 prompt->conditioning case no longer detects position renumbering, and post-`4712dac40` the instrument is INVERTED — the mutant is closer to the oracle than the correct code.** MEASURED in one build directory, CPU-only Release, x86_64, compile rc 0 on every arm and every source restored `sha256sum`-verified, as ratios to the propagated floor: before `4712dac40`, correct 0.565/0.688 and renumbered 0.831/**1.099** (the 1.10x the case's own note claims, and it reded); at `aeba0de6f`, correct **1.209/1.313** and renumbered 0.683/0.931 — so at the old `1.0x` bound the case reds the port and passes the defect. `4712dac40` is right; what it did here was raise this comparison's noise floor above the defect's signal, and no constant recovers a detection whose ordering has reversed. [#1458](https://github.com/mudler/vllm.cpp/issues/1458) restores a functioning instrument at a derived `2.0x` (its scatter-offset mutation still reds at 14.08x/24.06x) and does not claim this coverage. A repair owes an instrument with no bf16 accumulation between the defect and the assertion — the integer `positions` contract, or the f32 rope table `scripts/gen-ltx2-gemma-tower-goldens.py:363-375` already names as the right one for this class. Found in flow while gating #1458 (PR [#1461](https://github.com/mudler/vllm.cpp/pull/1461)); also listed under `## Owed` in [`ltx-2-5.md`](specs/ltx-2-5.md) | bug |
| [#844](https://github.com/mudler/vllm.cpp/issues/844) | `VT-REFTIER-HOST-ADDRESSABLE` | **The portable CPU reference tier gates on `Backend::UnifiedMemory()`, which is not the property a host kernel needs, so a device tensor reaches a host kernel and the process gets SIGSEGV under a banner reading `correct but slow`.** The eligibility predicate is `ReferenceTierEligible` in `src/vt/op_provider.cpp`; grep the symbol, because this index is append-only and a line number here would be permanent. It asks `Backend::UnifiedMemory()`. The question a host kernel actually asks is `Backend::DeviceMemoryIsHostAddressable()`, whose own comment in `include/vt/backend.h` records the refutation: CUDA on GB10 reports unified memory because host and device address the same physical RAM, yet a plain `cudaMalloc` pointer is still not host-dereferenceable, and its default is `false` because "being wrong here hands a device pointer to a host memcpy and segfaults". `CudaBackend::Alloc` calls `cudaMalloc`, so every CUDA op without a native kernel installed the CPU host kernel and crashed. Measured twice on GB10: `vt::QuantFp8Static` on `sm_110` ([#960](https://github.com/mudler/vllm.cpp/issues/960)), whose spec `## Outcome` relocated the one registration and recorded that the CLASS stayed open; and `vt::MatmulFp8BlockScaled` on a CUTLASS-less CUDA build ([#1435](https://github.com/mudler/vllm.cpp/issues/1435)), which exits 139 with `test cases: 0 assertions: 0`. Fixed by asking the narrow predicate, and by `MetalBackend` and `RocmBackend` answering it truthfully so neither loses the tier: both answers are equal to what those backends report today, so only the CUDA cell moves. The refusal now names why the portable tier did not run, and the banner names its precondition instead of asserting correctness. Reproduced without a GPU in `tests/vt/test_reference_tier.cpp` by a fake backend carrying the GB10 property pair. Spec [`vt-reference-tier-host-addressable.md`](specs/vt-reference-tier-host-addressable.md) | bug |
| [#1482](https://github.com/mudler/vllm.cpp/issues/1482) | `VT-REFTIER-HOST-ADDRESSABLE` | **The remainder of [#844](https://github.com/mudler/vllm.cpp/issues/844), split out so it keeps an open tracker after the crash itself is fixed.** #844 asked for four things. The reference tier no longer hands a device tensor to a host kernel, and the banner no longer claims correctness it cannot hold; those two landed with this row. Two did not. Item 1 also wants the refusal to name the BUILD FEATURE that would have provided the native kernel: the landed message names the op, the device, and which tier precondition the device failed, but not `this build has no cutlass-fp8`, which is the sentence that would have turned #1435's measurement around in one read. It is absent because the op table holds no such mapping -- an `OpId` does not know which CMake feature cell compiles its registering translation unit -- and inferring one by scanning a kernel body for `cutlass` tokens was already argued and rejected in [`vt-fp8-quant-arch-gate.md`](specs/vt-fp8-quant-arch-gate.md) `## Outcome` as transitive through helpers, hence both false-positive and false-negative. A real fix needs a declared, checkable mapping, which is a design question and not a message change. Item 4 -- whether a CUDA build lacking CUTLASS should warn at ENGINE CONSTRUCTION rather than only at configure time -- is untouched. The refusal fires at first dispatch of the missing op, which can be deep inside a model forward, long after the configure log is gone. Filed rather than deferred silently: the fixing pull request carries `Fixes #844`, so without this row the remainder would point at a closed issue and have no owner, which is the ownerless-owed state the protocol forbids. Listed under `## Owed` in [`vt-reference-tier-host-addressable.md`](specs/vt-reference-tier-host-addressable.md) | bug |
| [#1489](https://github.com/mudler/vllm.cpp/issues/1489) | `SPEC-DFLASH2` | **`vt::TopKValuesIndices`'s CUDA arm does not order NaN first, and the CPU arm's contract says it does — 12 failed assertions, all one literal row.** FIRST DEVICE RUN of the DFlash2 kernels: an `rc` job on `dgx:gpu0` (GB10, sm_121a, `nvcc` 13.0 matched to the driver) at `SPEC-DFLASH2` W3 head `b29b6f8869a9eeacc451647e859498491ef6bf1e`, 2026-08-20. It settles more than it opens. `BUILD_RC=0` and `COMPILE_ERRORS=0` for all six DFlash2 suites, so `## Owed` O6 is DISCHARGED — W2's grouped convolution and both W3 ops had never been through `nvcc`. The device arms genuinely RAN, which is the precondition that separates this from a green skip: zero `no CUDA backend; skipping` lines, and `test_ops_topk_values_indices` reports **562 assertions on device against 202 on the CPU-only build**. And the tie divergence O10 called the real risk did NOT materialise: the CPU arm sorts under an explicit comparator while the CUDA arm threshold-searches, compacts and fills from the lowest-indexed equals, and on the straddling group, the group larger than k, the ties inside the kept set and the `-inf`-saturated row the two algorithms agree. Five of the six suites pass. THE ONE FAILURE: 7 cases, 5 passed, 2 FAILED; 562 assertions, 550 passed, 12 FAILED; `Status: FAILURE!`, every one of the twelve on the literal row `"NaN sorts first, as torch.topk does"`, including the direct cross-arm pair `CHECK( gpu.indices[i] == cpu.indices[i] )` reading `2 == 1` and `CHECK( std::isnan(gpu.values[i]) )` reading `false` — a genuine backend disagreement, not a wrong expectation on one side. MECHANISM, derived from `src/vt/cuda/cuda_sample.cu:548-698` before the results were read: `TopKValuesIndicesRowKernel` brackets with `fmaxf`/`fminf`, which return the non-NaN operand, and selects survivors with `r[j] > thr`, which is false for a NaN, so the kernel can never select one whatever the threshold converges to. NOT A SHIPPED DEFECT: no production path feeds this op a NaN logit, because the candidate values come from a target LM head. It IS a red suite on any CUDA build, which AGENTS.md `## Gates` does not permit to stand as recorded debt. REPAIRED BY NARROWING in the W3 repair delta: the row is excluded BY NAME from both device cases and kept on the CPU arm where it is the mutation-proven guarantee, `include/vt/ops.h` states the asymmetry beside the contract instead of asserting an ordering no backend delivers, and the exclusion's match count is asserted on the CPU arm so a filter that matched nothing cannot hide. WHAT THIS ISSUE OWNS: reconciling `TopKValuesIndicesRowKernel` to the NaN-first contract, which is what makes `ops.h` true on both arms and lets the row go back into the device cases. It needs a lease to verify and is not attemptable from a host with no `nvcc`. Reproduce with `/mnt/nas_share/rc/dflash2/cuda-gate.sh` at that SHA; per-suite logs at `/workspace/dflash2/cuda-<suite>.log`. Two instrument caveats recorded there: `NVCC_INVOCATIONS` read 0 and `CUDA_CONFIGURED` read `unknown`, both defects in the harness rather than facts about the build — the parity assertions ran and disagreed, which is what proves CUDA was active. Listed under `## Owed` O10 in [dflash2-spec-decode.md](specs/dflash2-spec-decode.md) | bug |
| [#1493](https://github.com/mudler/vllm.cpp/issues/1493) | `LTX25-DFR-ROUNDS` | **DFR's unclamped `2**round_idx` tile count is mirrored and gated by nothing, because every fixture canvas in this tree has ONE keyframe segment.** `tile_ranges` clamps to `min(num_tiles, n_segments)` (`dfr_layout.py:171`), and the 9-frame fixture pads to a 25-frame canvas with a single segment, so round 1 asks for 2 windows and gets 1 and round 2 asks for 4 and gets 2. A port computing `round_idx + 1`, or `2 * round_idx`, or capping at 2 returns the SAME tile counts on every test here, with every downstream shape, frame count and exit status identical. NOT FIXED IN FLOW and the judgement is recorded rather than reversed: reaching 4 segments needs a materially longer canvas, so round 2 would denoise 4 tiles on a canvas already doubled twice - a new fixture and a substantially longer CPU run in a file that already carries 102 cases, not an assertion added to the existing render. The bound is stated in the test body and in `docs/USAGE.md`, so it was disclosed before it was owned; this row is the ownership. Closing it needs one render whose canvas carries at least 4 segments plus an assertion that `round_tile_counts` reads the unclamped `2**round_idx` for at least one round, which is the only shape that separates `2**round` from every expression agreeing with it at 1 and 2. Listed under `## Owed` in [`ltx25-dfr-rounds.md`](specs/ltx25-dfr-rounds.md) | bug |
| [#1494](https://github.com/mudler/vllm.cpp/issues/1494) | `LTX25-DEVICE-RESIDENCY` | **A SECOND LTX-2.5 phase-coverage ratio decides by box load, and it is NOT the one [#1439](https://github.com/mudler/vllm.cpp/issues/1439) tracks.** `ltx2 video: the three carrying phases contain their work and the load keeps its order` asserts `CHECK_MESSAGE(covered >= c.min_coverage * leaf_seconds, ...)` at `tests/vllm/multimodal/test_ltx2_video.cpp:3696`; #1439 is `CHECK(leaves >= 0.95 * wall)` in a DIFFERENT case, now at `:3259`. Closing one does not close the other. Measured 2026-08-20, x86_64 `Release` `VLLM_CPP_CUDA=OFF`, three consecutive full-suite runs of ONE binary (`sha256 8fdbc31d...`) with no source change: loadavg 10.45 gives 94.6039% RED, a quieter run gives 96.8506% green, loadavg 16.53 gives 94.6039% RED. The comparison prints as `CHECK( 0.00414483 >= 0.00416218 )` - `denoise` is 0.00438124 s, its eight named sub-scopes cover 0.00414483 s, so the un-named residue is 0.00023641 s and **the margin is a quarter of a millisecond**. Same scheduling polarity #1439 recorded, which is the tell that this is the instrument and not the code: the run that PASSED is the run where `denoise` took 0.00940481 s, more than twice the failing runs', because the residue grows more slowly than the leaf it is divided by. NOT FIXED IN FLOW: bounding the residue in SECONDS beside the ratio, so the assertion says the same thing at fixture and production scale, changes a gate's semantics and needs its own row, spec and red-first evidence per `AGENTS.md` `## Changing the rules or a checker` - the same conclusion #1439 reached, and the two should be repaired together because one seconds bound would serve both. Found by the fresh implementer repairing the review findings of [#1481](https://github.com/mudler/vllm.cpp/pull/1481); pre-existing and not that PR's defect | bug |
Expand Down
Loading
Loading