diff --git a/.agents/issue-index.md b/.agents/issue-index.md index 9a66f7d73..c3ed5b776 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 | +| [#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 | | [#1469](https://github.com/mudler/vllm.cpp/issues/1469) | `KERNEL-DFLASH2-GROUPED-CONV` | **`test_audit_live_rows` is RED on `main`.** Measured on a detached worktree at `origin/main` `cae8ace0c` with nothing applied: `test_shipped_record_has_no_abandoned_active_row` fails with `stale ACTIVE rows remain: ['KERNEL-DFLASH2-GROUPED-CONV']`, 57 tests, 1 failure, and `scripts/agent-preflight.sh` reports both `audit-live-rows` and `test_audit_live_rows` as FAILED. `scripts/audit-live-rows.py` alone returns rc 0 and prints `245 live rows; 1 abandoned ACTIVE`, so the count is the gate and the script's exit status does not carry it. The row is `.agents/kernel-matrix.md:143`, state `ACTIVE`, claim `CLAIM-SPEC-DFLASH2-W2`, and its implementation landed on `main` in `028438e68` (SPEC-DFLASH2 W2, [#1314](https://github.com/mudler/vllm.cpp/issues/1314), PR #1465) - a row still claimed as in-progress whose work is already reachable on `main`. NOT FIXED IN FLOW: the kernel matrix, the row and the DFlash2 claim are outside the authority of the row that found it (`LTX25-DEVICE-RESIDENCY` W0, PR #1441), and a lifecycle move owes `docs/STATUS.md`, `docs/BENCHMARKS.md` and the moved row spec's `## Now`. Found while running the full preflight for that row's gate, where it is an inherited red | bug | diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index 0c7918306..92fd72b9c 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -16,11 +16,22 @@ function(vllm_cpp_set_warnings target) set(_vllm_cpp_werror "") endif() - # GCC >= 16 reports -Warray-bounds inside LIBSTDC++ and the vendored nlohmann + # GCC >= 15 reports -Warray-bounds inside LIBSTDC++ and the vendored nlohmann # json for code that is correct, so the diagnostic stays VISIBLE but stops - # being fatal on those compilers only. Everything <= 15 is unchanged and still + # being fatal on those compilers only. Everything <= 14 is unchanged and still # fails the build on a real out-of-bounds. # + # The bound was 16 until gcc 15.2.0 reproduced the same class from the OTHER + # libstdc++ container: `std::vector`'s inlined copy-construct plus + # `_M_allocate`, reported against `ltx2_samplers.cpp:161,163` as "array + # subscript -1 is outside array bounds of 'float [2305843009213693951]'". That + # bound is SIZE_MAX/4, the giveaway that the allocator's unconstrained size + # range reached the subscript check rather than a real object. The subscripts + # are `sigmas.back()` guarded by an explicit `VT_CHECK(sigmas_in.size() >= 2)` + # three lines above, which GCC does not propagate through the inlined copy. So + # `main` did not build on gcc 15.x at all, and no CI lane covers that release: + # `build-newest-gcc` runs 16 (already exempt) and `build-test-cpu` runs older. + # # It is the same false-positive class this file already documents above for # the sanitizer lanes, and it is not something the calling code can avoid: # `_Sp_counted_base::_M_release()` is identical machine code for every @@ -37,7 +48,7 @@ function(vllm_cpp_set_warnings target) # check the same way on the affected releases. set(_vllm_cpp_array_bounds "") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND - CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16) + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15) set(_vllm_cpp_array_bounds -Wno-error=array-bounds) endif() if(MSVC)