Skip to content
Closed
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
1 change: 1 addition & 0 deletions .agents/issue-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,4 @@ rather than merged. `scripts/check-agent-record.py` gates both.
| [#1024](https://github.com/mudler/vllm.cpp/issues/1024) | — | An LTX-2.5 render invoked with `--device cuda` **stages 35.54 GiB onto the GPU and then never uses it**. MEASURED on `dgx.casa` (GB10, boot id `03717c9d-63c8-4652-a8fe-a63d012c5718`, build `0e1bee42f`), 320x192/25f, per-PID over **347 samples**: GPU utilization never exceeded 2%, was **exactly 0 in 321/347**, and **every one of the 26 non-zero samples falls inside the DiT staging window** (t<=251 s) — so **every post-staging sample reads 0**, while the compute-app footprint sits flat at 36396 MiB and the process holds **exactly 1.00 core of 20** across the two `utime` windows this figure covers (+116.7 s over 117 s, +142.2 s over 142 s = **259 s of measurement**; §1.3 of the spec records a third window in the same regime, +648.9 s over 649 s, so 259 s is what these two cover and NOT the sampler's total, which the record cannot settle — [#1040](https://github.com/mudler/vllm.cpp/issues/1040)); 0 frames written. **This row states sample counts and states NO minute figure, because no consistent one exists.** Drafts variously said "17+ minutes" here and "over 15 minutes" over "the first 1192 s" in the spec; 347 samples at a 2 s cadence span 694 s, so neither fits, and no dropped-sample rate was ever recorded. The GPU-zero half is over EVERY sample; the core-count half rests on 259 s. Staging took the device path (`Anonymous` stayed at 0.01 GiB, so no f32 widening — `src/vllm/multimodal/ltx2_video.cpp:786 @ 332aed738`). Leaves a disjunction this issue cannot yet split, because nothing timestamps a phase boundary ([#1010](https://github.com/mudler/vllm.cpp/issues/1010)): either the denoise is not taking `Ltx2DitForwardDevice` (`ltx2_video.cpp:2946` vs `:2948 @ 332aed738`), or it is and something before it burns the rest of the run single-threaded. Broader than [#1007](https://github.com/mudler/vllm.cpp/issues/1007): the 0% GPU is a property of the whole post-load render, not of the decode phase, so `docs/USAGE.md:873-874 @ 332aed738` understates it. **Owed: a positive control that `utilization.gpu` reads high for a real kernel on GB10** — this box already returns `[N/A]` for `--query-gpu=memory.used`. Sampler CSV not retrievable ([#1040](https://github.com/mudler/vllm.cpp/issues/1040)). Listed under `## Owed` in [`ltx25-decode-speed.md`](specs/ltx25-decode-speed.md) | bug |
| [#1040](https://github.com/mudler/vllm.cpp/issues/1040) | — | `LTX25-DECODE-SPEED` ([#1006](https://github.com/mudler/vllm.cpp/issues/1006)) records three sets of PASSING measurements and **none has a retrievable evidence artifact**, which `.agents/verification.md` requires alongside the SHA, command, environment and exit status. Rung 1's 248 per-PID sampler rows, rung 2's 1082 rows and 347 side-car per-PID samples, rung 2's `run.log`, and §1.4's `~/work/ltx25-e2e/render8-console.log` all live only on `dgx.casa` — `ping -c 2 -W 3 dgx.casa` exits 1 with 100% packet loss and `Destination Host Unreachable` (checked 2026-08-16), this box's documented unified-memory OOM-reboot mode, which needs a physical power cycle. The spec's `REMOTE_UNVERIFIED` mark was correctly scoped to rung 2's EXIT REASON; this issue extends the same honesty to the passing numbers. **Second and more corrosive: neither rung's sampler cadence closes.** Rung 1 states 248 samples at 2 s over a 701 s run split 192+56 across 450 s and 164 s windows — at 2 s those windows hold 225 and 82, and 248 samples cover 496 s of 701. A draft of rung 2's §5 stated 347 per-PID samples at 2 s "over the first 1192 s" — at 2 s that window holds 596. No dropped-sample rate is recorded anywhere, so the wall each sample set covers is NOT derivable, and the spec now states sample counts and fractions rather than minute figures. The raw CSVs settle both in one pass. Filed while repairing the fresh review of [PR #1038](https://github.com/mudler/vllm.cpp/pull/1038); not fixable in that flow, because no edit to the tree produces a file on a host that does not answer. Listed under `## Owed` in [`ltx25-decode-speed.md`](specs/ltx25-decode-speed.md) | bug |
| [#1029](https://github.com/mudler/vllm.cpp/issues/1029) | `ENG-EXPERT-STREAM` | `IsCudaKeepQuantSupported` (`src/vt/cuda/cuda_quant_dot.cu`) returns true for `kIQ1_S` and `kIQ1_XXXS` since [#967](https://github.com/mudler/vllm.cpp/pull/967), and THREE dispatch switches consume that predicate while #967 extended only the dense one. `MatmulBTQuantGroupedKernelCuda` uses the predicate to SKIP its CPU fallback and then dispatches through a `switch (w)` with no case for either dtype and no `default:`: it quantizes the activation, launches NOTHING, returns, and `CheckCuda(cudaGetLastError())` reports success because there was no launch to fail, so the output tensor is never written. Measured on GB10 by an independent review through a poisoned output buffer: both IQ1 encodings leave `-12345` in place at NMSE `4.58e6` / `9.96e6` against the CPU oracle, with `iq2_s` passing as the control. Reachable by DEFAULT (`qwen3_5_gguf_weights.cpp` -> `qwen3_5.cpp` `KqGrouped` -> `vt::MatmulBTQuantGrouped`, `VT_QWEN35_GROUPED_MOE` on) on the 96.92 % of `Qwen3.8-2.4T` those two encodings make up, so #967 converted correct-but-slow into silently wrong. Same omission in the fused `MoeGateUpSwiGLUGroupedCuda` seam, where it turned a NAMED refusal into silence. It landed green because the CUDA grouped dispatch had NO test: `grep -rl MatmulBTQuantGrouped tests/` found two files and neither mentioned `kCUDA`. Repaired by adding both arms to both grouped switches, a `default:` that THROWS and names the dtype on all three (the general fix: past that predicate there is no fallback left), and a grouped + fused CUDA gate over the dense gate's case table driven through a POISONED output buffer. Also seals the device codebooks against the CPU tables, which `cuda_quant_iq_tables.cuh` claimed from the day it landed and no test did: 266 of 2048 `d_iq1s_grid` entries (13.0 %) are never addressed by the gate's own `mt19937(0x5EED)` stream. Device evidence is OWED and the issue stays open for it: `dgx.casa` was unreachable throughout and this box has no CUDA device, so only the CPU arm ran. Spec [`expert-streaming.md`](specs/expert-streaming.md) | bug |
| [#1062](https://github.com/mudler/vllm.cpp/issues/1062) | `DOC-PROSE-BUDGET-1062` | `scripts/check-public-doc-tables.py` exits 1 on `origin/main` at `b493f4981`, so **main is RED and every branch inherits it**: the checker gates the `agent-record` CI job, `scripts/agent-preflight.sh` and the pre-push hook, so CI, preflight and pushes are all blocked. `docs/BENCHMARKS.md` measures 36 prose paragraphs against its 35 budget and `docs/FEATURES.md` 22 against 21. Introduced by `e34d71379` ([PR #1054](https://github.com/mudler/vllm.cpp/pull/1054)), whose recorded verification does not include this checker; `283c7e492` is the last green commit and the checker is byte-identical across the pair, so the pages moved and the gate did not. NOT the shared-file-budget antipattern: `check-public-doc-tables.py:17` and `:105` both state that table ROWS are unbudgeted and that nothing budgets the whole file, so adding a measurement was never blocked and the constants are neither raised nor retired. Fixed by moving all three added paragraphs into rows on the same two pages with every fact preserved, including that benchmarking is NOT APPLICABLE and that the binding gate is the Apple Clang build. Spec [`doc-prose-budget-1062.md`](specs/doc-prose-budget-1062.md) | bug |
147 changes: 147 additions & 0 deletions .agents/specs/doc-prose-budget-1062.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# DOC-PROSE-BUDGET-1062: the public pages grew prose where the contract wants rows

**Row:** `DOC-PROSE-BUDGET-1062`
**Issue:** [#1062](https://github.com/mudler/vllm.cpp/issues/1062)
**Base:** `origin/main` `b493f4981`
**Status:** ACTIVE, 2026-08-16

## 1. Scope

`scripts/check-public-doc-tables.py` exits 1 on `origin/main`, so `main` is red
and every branch cut from it inherits the red. The checker runs in the
`agent-record` CI job (`.github/workflows/ci.yml:160`), in
`scripts/agent-preflight.sh`, and in the pre-push hook, so it blocks CI,
preflight, and pushes for everyone.

```
ERROR: the public keyed-table docs are not valid:
- docs/BENCHMARKS.md has 36 prose paragraphs, over the 35 budget
- docs/FEATURES.md has 22 prose paragraphs, over the 21 budget
```

**In scope.** The three prose paragraphs [PR #1054](https://github.com/mudler/vllm.cpp/pull/1054)
added to `docs/BENCHMARKS.md` and `docs/FEATURES.md`, moved into table rows on
the same two pages with every fact preserved, plus this spec and the
[issue index](../issue-index.md) row.

**Out of scope.** The checker itself, its constants, and its tests. The
qwen3.5 source change #1054 landed is correct and stays. Also out of scope, and
inherited rather than introduced here: the 13 two-column rows already sitting
inside four-column tables on `docs/BENCHMARKS.md`, and the malformed
`#1003` row in the issue index, which [#1059](https://github.com/mudler/vllm.cpp/issues/1059)
owns.

## 2. Anchors

Local governance surface. There is no vLLM counterpart: vLLM publishes no
keyed-table contract for its public documents.

| What | Where |
|---|---|
| The failing gate | `scripts/check-public-doc-tables.py` |
| The rule the pages break | `check-public-doc-tables.py:17`, `:105` |
| The prose that broke them | `e34d71379`, PR #1054 |
| Last green commit | `283c7e492` |

## 3. Design

The budget is not the defect and is not touched. `check-public-doc-tables.py:17`
and `:105` both state that table ROWS are unbudgeted and that nothing here
budgets the whole file; only prose paragraphs are capped, because rows are a
keyed table's growth mode and prose is its decay mode. Adding a measurement, the
normal operation, was never blocked. Raising the constants or retiring the
budget would make a red gate green by widening its scope, which AGENTS.md
forbids, so neither is done.

What is wrong is the SHAPE of the content, and the repair is to give each fact
the row its own page's schema already has for it.

**`docs/BENCHMARKS.md`.** "Benchmarking is NOT APPLICABLE, the binding gate is
the Apple Clang build" is a DISPOSITION, which is exactly what a row of the
`Open gaps` table records. That table is `Track | Status | Next gate`, and it
already carries a cluster of "no number owed" build-verification dispositions
(`Ampere consumer`, `Pre-Ampere breadth`) that this row joins. The date moves
into the row, which is what the checker's own regrowth-guard message directs
("put the date in the row or the prose"); `DATED_HEADING_RE` reads headings
only.

**`docs/FEATURES.md`.** The fact is that Apple Clang builds the Qwen3.5 MoE
loader with project warnings promoted to errors, and that the loader's
layout-refusal path is platform-invariant. That is a platform and toolchain
fact, so it belongs to `Backends and hardware`, whose Apple row it updates in
place. This follows the convention that table already sets: its `CPU` row's key
cell carries the same class of platform caveat.

Two alternatives were rejected. The `Registered architectures` row for
`Qwen3_5MoeForConditionalGeneration` measures 195 characters in its correctness
cell against a 220 cap, which does not fit the fact, and the sibling
`Qwen3_5ForCausalLM` cell is at exactly 220. Adding a row to the `At a glance`
table would have forced a claim in the `vLLM`, `SGLang`, and `llama.cpp`
columns about a C++ host-toolchain build that no evidence in this change
supports, and the page's own header says those columns are our reading of
documented behavior, so inventing three marks to house one of our facts is
worse than the prose was.

Neither page loses a fact, and neither page merges two paragraphs into one to
slip under a counter, which would game the count while leaving the page in the
shape the contract rejects.

## 4. Risks

- **A row that does not match its table's schema is a new defect.** Each row is
checked against its own table's column count, not a global one: the `Open
gaps` row is 3 columns, the `Backends and hardware` row is 5.
- **The cell and row caps still bind.** `MAX_CELL_CHARS` is 220 and
`MAX_ROW_CHARS` is 600, and both are ENTRY-scoped, so this change pays for
itself and evicts nobody.
- **Em-dashes are refused by the same checker.** Neither new cell contains one.
- **`docs/BENCHMARKS.md` carries 13 inherited malformed rows.** They are
measured byte-for-byte identical at `b493f4981` and after this change, so a
reviewer reading a row-shape scan does not attribute them here.

## 5. Tests and gates

RED first, from a clean detached worktree rather than the shared checkout:

- `python3 scripts/check-public-doc-tables.py` at `b493f4981` exits 1 with both
budget errors.
- The same checker at `283c7e492` exits 0, and `git diff` proves the checker is
byte-identical between the two commits, so the pages moved and the gate did
not.

GREEN after:

- `python3 scripts/check-public-doc-tables.py` exits 0.
- `docs/BENCHMARKS.md` measures 35 prose paragraphs of 35 and
`docs/FEATURES.md` 21 of 21, both computed with the checker's own
`_prose_paragraphs`.
- Every table row on both pages splits into its own table's column count on
unescaped pipes.
- `scripts/agent-preflight.sh` and `scripts/agent-preflight.sh --staged`.

## 6. Evidence

The verbatim red output, the verbatim green output, the paragraph counts, the
per-row shape scan, and the preflight result travel in the pull request body,
which is the landed commit message.

## 7. Stop conditions

Stop and return `NEEDS_DECISION` rather than relaxing any of these:

- A budget constant would have to move.
- A fact from #1054 would have to be dropped, softened, or merged into another
paragraph.
- A row would have to make a claim about vLLM, SGLang, or llama.cpp that no
evidence in this change supports.

## 8. Now

`ACTIVE`. Records only: no source, test, or gate file changes.

## 9. Nothing owed

[#1062](https://github.com/mudler/vllm.cpp/issues/1062) is fixed in this flow,
not deferred, so this row OWNS it in the issue index. There is deliberately no
`## Owed` section, because a row that owns an issue and also owes it would be
recorded twice by `scripts/check-agent-record.py`.
6 changes: 1 addition & 5 deletions docs/BENCHMARKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -456,11 +456,6 @@ built on it rather than keeping the flattering one.

**CPU elementwise GEMM, transpose-free `[K,N]` path (2026-08-07).** On dgx aarch64 the `[K,N]` path beats `[N,K]` by 1.16x to 1.30x, byte-identically. The x86 arm is INDICATIVE ONLY, not binding: that box is VOID for timing per `CLAIM-KERNEL-CPU-ELEM-GEMM-1`. `VT_CPU_MATMUL_STEAL` ships default OFF and is NOT measured; it must justify itself by measurement and may measure neutral.

**Darwin Qwen3.5 build repair (2026-08-16).** Benchmarking is NOT APPLICABLE.
The change removes a redundant namespace-scope lambda capture that Apple Clang
rejects under `-Werror`; it does not change generated refusal text, model math,
or any runtime path. The binding gate is the Apple Clang build.

## Open gaps

| Track | Status | Next gate |
Expand Down Expand Up @@ -517,6 +512,7 @@ or any runtime path. The binding gate is the Apple Clang build.
| Async serving correctness (#323) | **FIXED**: the decode graph replayed stale HOST token ids, degenerating concurrent requests past slot 0 (classic-dense, graph on = default). Graph declines while the mirror is live; async 7/7, SACRED 184/184 | Graph to read ids at REPLAY |
| Ampere consumer (`sm_86`, RTX 3090 class) | **No number owed; no such board here.** 2026-08-06 build-verify: 7/7 FA2 TUs 0-warn, real `sm_86` SASS. [Detail](../.agents/benchmark-record.md) | External RTX 3090 report. Floor is llama.cpp on that card (GGUF, not our Blackwell-only NVFP4 grid) |
| Pre-Ampere breadth (Turing `sm_75` / Volta `sm_70` / Pascal) | **No number owed; nothing runs on these arches.** 2026-08-06 `sm_75`: 20/20 TUs PASS (0 err/warn), WMMA bodies + all 3 selectors arch-gated; GB10 SASS byte-identical. [Detail](../.agents/benchmark-record.md) | Full-library LINK at `sm_75` + `cuobjdump` SASS, then a build-supported row. The fp16 `fattn` port is speed-only now; its floor when a card exists is llama.cpp on that card |
| Darwin Qwen3.5 build repair (2026-08-16) | **Benchmarking is NOT APPLICABLE.** Dropping a redundant namespace-scope lambda capture that Apple Clang rejects under `-Werror` changes no generated refusal text, no model math and no runtime path | None, and no number is owed. The binding gate is the Apple Clang build |

## Reproduce

Expand Down
6 changes: 1 addition & 5 deletions docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,6 @@ speed-pending, which [BENCHMARKS.md](BENCHMARKS.md) tracks.
| `CohereForCausalLM` | Command-R / Cohere (and Cohere2) | scaffold: W0 tiny-random oracle run-verified; real-checkpoint gate blocked | no run |
<!-- supported-arch-table:end -->

The Qwen3.5 MoE loader also builds under Apple Clang with project warnings
promoted to errors. Its layout-refusal path uses the same messages and behavior
on every platform.

### Standalone and non-registered lanes

These run through dedicated forwards, not the `REGISTER_VLLM_MODEL` registry, so
Expand Down Expand Up @@ -253,7 +249,7 @@ both refuse, naming what is missing.
|---|---|---|---|---|
| CUDA | ✅ sm_80 to sm_121a | ✅ | ✅ | ✅ |
| CPU (x86, Arm i8mm; A76 assembly correct/default, llama speed gate open, and the closed 20-core floor ran a SUPERSEDED fork denominator rather than the stock `b10451` pin, re-take owed #1003) | ✅ | ◐ | ☐ | ✅ |
| Metal (Apple Silicon) | ✅ | ☐ | ☐ | ✅ |
| Metal (Apple Silicon; Apple Clang builds the Qwen3.5 MoE loader with project warnings promoted to errors, and that loader's layout-refusal path uses the same messages and behavior on every platform) | ✅ | ☐ | ☐ | ✅ |
| Vulkan | ◐ | ☐ | ☐ | ✅ |
| ROCm | W0 verified on 5 gfx archs; dense and GDN models run all-native. Strict CPU parity is open in the measured near-tie regime (#269) | 44 registered ops including full GDN; ctest-green gfx1151/1103/1100/1201/1200 ([#41](https://github.com/mudler/vllm.cpp/issues/41)). APU managed allocation is unverified. [ROCM.md](ROCM.md) | ✅ | ✅ |
| XPU / TPU | ☐ | ✅ | ◐ | ☐ |
Expand Down
Loading