diff --git a/.agents/issue-index.md b/.agents/issue-index.md index 31dfa1e79..1ffc08641 100644 --- a/.agents/issue-index.md +++ b/.agents/issue-index.md @@ -491,6 +491,7 @@ rather than merged. `scripts/check-agent-record.py` gates both. | [#1447](https://github.com/mudler/vllm.cpp/issues/1447) | `ENG-EXPERT-STREAM` | **`docs/USAGE.md` said EVERY Qwen3.8 decode figure came from the W0e C ABI harness; the 66.7 s/token streaming-off row of 16 August 2026 came from `vllm-server`, the same binary the section tells the reader to run.** Introduced by #1211 and fixed in the same flow: the sentence is scoped to the W0e and W0f runs and the exception is named, in `docs/USAGE.md` and in the spec paragraph that mirrors it. Provenance read at the source, `.agents/specs/expert-streaming.md:837` (server entry point) and `:905`. | record | | [#1403](https://github.com/mudler/vllm.cpp/issues/1403) | `ENG-CUDAGRAPH-BREAK` | **`test_qwen3_5_decode_graph_seam` SIGSEGVs — a DUPLICATE of [#1394](https://github.com/mudler/vllm.cpp/issues/1394) that was already fixed when it was filed, so no code change was owed.** Filed against `96ed8346f`, which PREDATES the fix `7dec1d990` (PR #1393, merged 2026-08-20 00:49); `git merge-base --is-ancestor` puts the fix outside the reported tree. Re-measured at `b537a5344`, CPU-only Release x86_64: the test passes 5 runs of 5, `8 cases`/`8 passed`, `assertions: 138`, `Status: SUCCESS!`, exit 0. The cause was re-derived by single-variable mutation rather than inherited from #1394's report, and NAMED by a sanitizer rather than reasoned. Debug + `VLLM_CPP_SANITIZE=address,undefined` (NDEBUG OFF) with BOTH halves of `7dec1d990` reverted to their `96ed8346f` bytes: `AddressSanitizer: SEGV on unknown address 0x5045f5f84900`, `The signal is caused by a READ memory access`, at `src/vt/cpu/cpu_paged_attn.cpp:59` in `KvElem` reached from `:224`, on threadpool worker T1, inside case `W6: two spec shapes of EQUAL S and different q get two graphs` (`tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp:800`). **It is NOT a use-after-free and there is no free site**, and `AddressSanitizer can not provide additional info` is the tell: the out-of-bounds block-table read is itself IN-BOUNDS for ASan because it lands inside the neighbouring pooled allocation, so this is not a `heap-buffer-overflow` either — the VALUE read becomes a wild block index that `KvElem` multiplies by the KV block stride and dereferences, which is why the fault address is unmapped rather than a redzone and why the crash is order-dependent instead of deterministic. Both halves are load-bearing: reverting ONLY the `SpecAttnMeta` fixture leaves the kernel bound to refuse by name at `src/vt/cpu/cpu_paged_attn.cpp:152` (exit 1, the case THROWS); reverting the bound as well restores the crash (Release exit 139, 3 runs of 3; ASan exit 1); restoring both gives exit 0, 8/8, zero sanitizer findings. The issue's `5f68e60df` pointer was right about the commit and wrong about the half — `git log -S'SpecAttnMeta'` and `git log -S'W6: two spec shapes of EQUAL S'` each return that commit ALONE, and both hits sit in the TEST fixture, not in the graph eligibility it widened. [#1405](https://github.com/mudler/vllm.cpp/issues/1405)'s truncation reproduced (`assertions: 135` crashed vs `138` complete) and is SHARPER under a threadpool fault: doctest printed the summary TWICE with different totals, `135` then `141`, because the main thread kept running after a worker died. That a red reached `main` unreported is [#1285](https://github.com/mudler/vllm.cpp/issues/1285)/[#1376](https://github.com/mudler/vllm.cpp/issues/1376), not this row | bug | | [#1458](https://github.com/mudler/vllm.cpp/issues/1458) | `VT-ACT-ROUND-POLARITY` | **`4712dac40` reds FOUR suites on `main` — `test_ltx2_text_encoder`, `test_muse_glimmer_text`, `test_muse_glimmer_text_fallback`, `test_minimax_music3_ar` — by exceeding bf16 error floors none of them had re-derived.** Found while gating [#1403](https://github.com/mudler/vllm.cpp/issues/1403) (PR #1457) and filed in flow, not that row's defect. Deterministic, not a load artifact: first seen under `-j4` and re-measured SERIALLY, 101 s across the four. `test_ltx2_text_encoder.cpp:2407` reads `CHECK( 0.1323 <= 0.109394 )` and `:2409` reads `CHECK( 0.0752773 <= 0.0573374 )`, both over by 20-30%, with the file at `26 passed / 1 failed`, `4118 assertions`, `Status: FAILURE!`. ATTRIBUTED BY MUTATION rather than inferred, both directions, in one build directory changing only `src/vt/cpu/cpu_ops.cpp`, compile rc 0 on every arm and `sha256sum` taken before and after: at `0adeb8b0e` four fail; reverted to `4712dac40^` four pass and `test_ltx2_text_encoder` is 27/27 `SUCCESS!`; restored to a re-matched `sha256` four fail again. They also passed at `b537a5344`, three commits earlier, in a full 567-test `ctest` run at 3-6 s each. `4712dac40` is +42/-3 in `src/vt/cpu/cpu_ops.cpp` plus a new `tests/vt/test_ops_activation.cpp`, and touches none of the four. NOT FIXED IN FLOW, deliberately: the question is a numerics decision, not a defect with an obvious repair — either the floors were calibrated against the rounding polarity that commit corrected and need re-deriving against the oracle, or the narrowing is wider than upstream's — and editing the four floors to pick the first branch is the scope-widening `AGENTS.md` prohibits | bug | +| [#1294](https://github.com/mudler/vllm.cpp/issues/1294) | `BACKEND-ROCM` | ROCm decode on gfx1200 is kernel-bound, not transfer-bound, and the profile names which kernels. `rocprofv3` (rocprofiler-sdk 7.2.3) on RX 9060 XT with `Qwen3.6-14B-A3B-VibeForged-v2-Q4_K_M.gguf`, decode isolated by differencing `--max-tokens 4` against `--max-tokens 36` and dividing by 32, idle host: wall 88.7 ms/token (11.3 tok/s, matching the unprofiled 11.06-11.18 so the profiler is not the observer), GPU kernel dispatch 59.99 ms/token over 1738 dispatches, and **real H2D+D2H transfer 0.885 ms/token over 160 copies**. `hipMemcpyAsync` reports 59.31 ms/token of API time across 689 calls, which is the CPU blocking on unfinished GPU work rather than PCIe cost — so the host round-trips in the MoE reference path (`qwen3_5.cpp:6736`) are NOT the cost, which refutes the obvious hypothesis. By class: `vt::` kernels 44.92 ms/token (74.9%), hipBLASLt GEMM 13.81 (23.0%), copy/fill plumbing 1.26 (2.1%). Two leads, both measured: `QuantizeQ8KK` at 281 calls/token, 21.25 ms/token, 75.6 us per call, **35% of GPU time**; and `GdnPostConvK` (`rocm_gdn_postconv.hip:57`) at 30 calls/token, 11.24 ms/token, 375 us per call, 19%. Lead one has a named cause ON main and backend-agnostic: `MoeBlock` hands the SAME activation buffer to `KqGrouped` twice (`qwen3_5.cpp:6832-6833`, gate then up), so the identical activation is quantized twice per layer per token, and CPU and CUDA pay it too. NOT FIXED IN FLOW: the quantizer itself is `rocm_grouped_gemm.hip`, which is not on main and arrives with [#523](https://github.com/mudler/vllm.cpp/pull/523), so the 35% figure is feedback on that pull request rather than a main defect, and `GdnPostConvK` has no hypothesis attached yet — both want their own red-first evidence rather than a drive-by. Dispatch counts were byte-identical (281/30/60/20/21) across a contended and an idle run, so the structure is deterministic and only durations moved. Measured on `main` @ `4ee5f4a6` plus #523 plus the #559/#570 `AttnQkNormRopeGate` fix; no pinned-oracle comparison, one model, one prompt, batch 1 | record | | [#1292](https://github.com/mudler/vllm.cpp/issues/1292) | `FIX-GCC15-ARRAY-BOUNDS` | `cmake/CompilerWarnings.cmake:39-42` demoted `-Warray-bounds` to non-fatal for GCC >= 16 only, and its comment asserted "Everything <= 15 is unchanged and still fails the build on a real out-of-bounds." gcc 15.2.0 reproduces the same false-positive class from the OTHER libstdc++ container: `std::vector`'s inlined copy-construct plus `_M_allocate`, reported at `ltx2_samplers.cpp:161,163` as "array subscript -1 is outside array bounds of `float [2305843009213693951]`". That bound is `SIZE_MAX/4`, the allocator's unconstrained size range rather than a real object, which is the same inlining-attribution mechanism the guard's own comment documents for `_Sp_counted_base::_M_release()`. The subscripts are `sigmas.back()` guarded three lines above by `VT_CHECK(sigmas_in.size() >= 2)` on the container it copies, so the code is correct and GCC does not propagate the throwing check through the inlined copy. `main` therefore did not build on gcc 15.x at all, stopping at 146/1552. No CI lane covers the release: the matrix is gcc 13 (ubuntu-latest distro `g++`, every ordinary lane) and gcc 16 (`build-newest-gcc`, `container: gcc:16`, already exempt via the guard), so the failure falls exactly between the two points, and gcc 15 is the current toolchain on Arch, NixOS unstable and Fedora 42. Introduced by `4d774864` (`LTX25-RES2S-LOOP`, 2026-08-17), which added the loop; the guard predates it and was written for the `shared_ptr`/json case. FIXED IN FLOW by widening the existing guard to `VERSION_GREATER_EQUAL 15`, which keeps the diagnostic visible as a warning. Red-before/green-after measured on `4ee5f4a6` with gcc 15.2.0: the TU is `exit 1` with two `-Werror=array-bounds=` errors, and `exit 0` with the same two as warnings once the guard's own `-Wno-error=array-bounds` applies; `scripts/agent-preflight.sh` fails the identical 10 gates before and after, so the change adds no failure. Whether CI should also cover gcc 14/15 is a SEPARATE question and is deliberately NOT bundled: the widened guard already prevents this defect recurring on 15, so a lane would guard a different class (the transitive-include portability the `build-newest-gcc` comment describes) and deserves its own issue rather than riding a build fix | bug | | [#1404](https://github.com/mudler/vllm.cpp/issues/1404) | `SPEC-DFLASH2` | The upstream head this row mirrors MOVED. `SPEC-DFLASH2` W1 and W2 were written against [vllm-project/vllm#52816](https://github.com/vllm-project/vllm/pull/52816) head `19c9351904df4c63042671bc67a866ca48dc7d6f`; the PR head is now `66e5414c6d75a8529473d977f7458c140bbab8a0`, which also FOLDED IN the previously stacked LM-head guard fix [vllm#52883](https://github.com/vllm-project/vllm/pull/52883). `## Risks/decisions` D1 accepted exactly this cost when it chose to mirror an unmerged pull request: "the anchors can move under review, and the port reconciles if they do". Reconciled by W3 on 2026-08-20, which re-read every anchor it cites at the new head and recorded the delta rather than rewriting the old citations in silence. Diffing the two heads changes five files; of the two this row ports, `qwen3_dflash2.py` is +24/-11 and IS exactly two things, both infrastructure rather than math, while `vllm/v1/worker/gpu/spec_decode/dflash2/speculator.py` is +37/-34 and is neither -- it is math and state layout in W4's own territory, so a W4 implementer who reads only this row would under-scope that wave. Both deltas measured with `git diff --no-index --numstat` over the blobs at each head; the per-file table and the enumeration live in the spec's `## Upstream chain`. `set_model_tag("dflash2_candidate_selector")` around the selector's construction is a DELIBERATE NON-PORT (spec D11): upstream needs it because `CandidateSelector` carries its own `@support_torch_compile` and is built under the draft's model tag, so the two would share one compile-cache namespace and the selector would load the draft's graph -- and this engine has no torch.compile and no compile cache. The widened LM-head guard IS ported (spec D12), in its WIDE form: `UnquantizedLinearMethod` beside `UnquantizedEmbeddingMethod`, because a `ParallelLMHead` returns the LINEAR method whenever a quant config leaves the head unquantized. `_score_edges`, `CandidateSelector`, `hidden_projection`, the two codebooks, `_topk`, `output_multiplier` and `final_logit_softcapping` are BYTE-IDENTICAL at the two heads, so the SELECTOR's math is unaffected -- "the anchors moved" and "the port must change" are different statements, and which one is true depends on which file. This does NOT advance the parity pin `555967922`, which does not carry the architecture at all | record | | [#1463](https://github.com/mudler/vllm.cpp/issues/1463) | — | Make public documentation task-oriented and readable; owned under `## Owed` in [`public-docs-readability.md`](specs/public-docs-readability.md) | documentation |