Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c351f51
spec(LTX25-DEVICE-SEAM-SIBLING): the sibling that never adopted the d…
mudler Aug 13, 2026
047e1df
merge: origin/main into row/LTX25-DEVICE-SEAM-SIBLING
mudler Aug 14, 2026
3a697bb
fix(LTX25-DEVICE-SEAM-SIBLING): the third question, and a leakage buc…
mudler Aug 14, 2026
d7d6480
fix(LTX25-DEVICE-SEAM-SIBLING): the bucket missed the purest spelling…
mudler Aug 14, 2026
0ab263e
merge: origin/main into row/LTX25-DEVICE-SEAM-SIBLING
mudler Aug 14, 2026
70d11c6
fix(LTX25-DEVICE-SEAM-SIBLING): the docstring named the target type, …
mudler Aug 14, 2026
60246da
merge: origin/main (33f570ea9) into row/LTX25-DEVICE-SEAM-SIBLING
mudler Aug 14, 2026
8415214
fix(LTX25-DEVICE-SEAM-SIBLING): re-derive the tenstorrent anchor at t…
mudler Aug 14, 2026
cbc2ee1
fix(LTX25-DEVICE-SEAM-SIBLING): one reason per blind spot (#659, #660)
mudler Aug 14, 2026
0184943
merge: origin/main (3ce5a1dc1) into row/LTX25-DEVICE-SEAM-SIBLING
mudler Aug 14, 2026
872b27b
record(LTX25-DEVICE-SEAM-SIBLING): anchor the scanned file count to a…
mudler Aug 14, 2026
ddf314e
merge: origin/main (4a4ab89cb) into row/LTX25-DEVICE-SEAM-SIBLING
mudler Aug 15, 2026
be9b0a6
record(LTX25-DEVICE-SEAM-SIBLING): re-derive five anchors at the merg…
mudler Aug 15, 2026
7502004
merge: origin/main (62406c30e) into row/LTX25-DEVICE-SEAM-SIBLING
mudler Aug 15, 2026
ae72e72
merge: origin/main (e8048ef63) into row/LTX25-DEVICE-SEAM-SIBLING-REB…
mudler Aug 15, 2026
f0b4650
fix(LTX25-DEVICE-SEAM-SIBLING): the "refuses by name" assertion could…
mudler Aug 15, 2026
c5d6b1b
merge: origin/main (0785cfc4d) into row/LTX25-DEVICE-SEAM-SIBLING-REB…
mudler Aug 15, 2026
0600a7e
record(LTX25-DEVICE-SEAM-SIBLING): re-derive the anchors the merge mo…
mudler Aug 15, 2026
4e7a708
fix(LTX25-DEVICE-SEAM-SIBLING): re-derive the READER ANCHORS that thi…
mudler Aug 15, 2026
bf77c94
merge: origin/main (2f2bce926) into row/LTX25-DEVICE-SEAM-SIBLING-REB…
mudler Aug 15, 2026
3520940
merge: origin/main (fba312c67) into row/LTX25-DEVICE-SEAM-SIBLING-REB…
mudler Aug 15, 2026
2ce0625
record(LTX25-DEVICE-SEAM-SIBLING): the anchor that rotted between two…
mudler Aug 15, 2026
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 @@ -224,6 +224,7 @@ rather than merged. `scripts/check-agent-record.py` gates both.
| [#691](https://github.com/mudler/vllm.cpp/issues/691) | `ROAD-V1-LTX25` | The LTX-2.5 out-of-scope ledger's reachable/marker split gates the MESSAGE TEXT, not reachability: give `kLoraFusion` a product call site and the ledger test still passes while the shipped refusal tells the caller `DECLARED, NOT REQUESTABLE` right after they requested it. Copy the anti-tautological shape of the extras inventory gate | bug |
| [#692](https://github.com/mudler/vllm.cpp/issues/692) | `ROAD-V1-LTX25` | Campaign spec `ltx-2-5.md:291` still records the FABRICATED `multishot` arm as owed after row `LTX25-RETIRE-DEAD-ARMS` retired it; same line needs `CFG parallelism` renamed to multi-GPU. Operator-owned file, so filed rather than edited by that row | bug |
| [#886](https://github.com/mudler/vllm.cpp/issues/886) | `POLICY-NOTHING-LANDS-DEAD` | The seam checkers police where a capability routes and nothing polices whether anything reaches it, so a change can land wired downward and driven only by its own test, as tensor parallelism did (guide [`reachability.md`](reachability.md)) | feature |
| [#828](https://github.com/mudler/vllm.cpp/issues/828) | — | `check-device-leakage.py`'s `dev_cast` bucket enforces a set of SPELLINGS, not the property "an integer becomes a `vt::DeviceType`": four review rounds each found a spelling the previous round's message already claimed, every one closing at ZERO hits, so widening is not the answer. The structural fix is an AST-level check (clang tooling), where the destination type canonicalises and the source type is known. Listed under `## Owed` in [`ltx25-device-seam-sibling.md`](specs/ltx25-device-seam-sibling.md) | feature |
| [#673](https://github.com/mudler/vllm.cpp/issues/673) | — | LTX-2.5 prompt-AdaLN: the row's checkpoint-derived evidence is MANUAL and host-local. `LTX2_CHECKPOINT_ROOT` is set by no workflow (`grep -rn CHECKPOINT_ROOT .github/` exits 1 with zero hits, positive control matches in `tests/` and `.agents/`), so CI executes 784 of 9031 assertions — 8.7%, measured 2026-08-15 — of `test_ltx2_video`, at a case count identical in both configurations, and `scripts/measure-ltx2-prompt-adaln.py` is a manual tool no gate invokes. Listed under `## Owed` in [`ltx25-prompt-adaln.md`](specs/ltx25-prompt-adaln.md) | bug |
| [#900](https://github.com/mudler/vllm.cpp/issues/900) | — | LTX-2.5 prompt-AdaLN is REACHED from `vllm_video_generate` but no test ENTERS through that entry point and observes it: deleting the term's only consumer (`ltx2_dit.cpp:140`) takes `test_ltx2` red at 3 of 43 cases while `test_ltx2_video` stays GREEN at 37 of 37, so the ABI-level gate measures that the pipeline runs rather than that this capability is in it. The second half of `AGENTS.md` `## Nothing lands dead`, whose rule post-dates the row (#886). Listed under `## Owed` in [`ltx25-prompt-adaln.md`](specs/ltx25-prompt-adaln.md) | bug |
| [#891](https://github.com/mudler/vllm.cpp/issues/891) | `MODEL-MM-qwen3-5-qwen3-5-moe-for-conditional-generation` | MoE vision tower (M2/M3): image and video for `Qwen3_5MoeForConditionalGeneration` — the dense arm has it, the MoE arm does not | feature |
Expand Down
726 changes: 726 additions & 0 deletions .agents/specs/ltx25-device-seam-sibling.md

Large diffs are not rendered by default.

19 changes: 17 additions & 2 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2032,11 +2032,26 @@ only when it reproduces the identical weight contract the shapes describe, and
supplying one for a checkpoint that already declares its own is refused rather
than ordered.

`vllm_video_model_params.device` is `0` for the CPU and `1` for **the
accelerator this build resolves** — not for CUDA. The value is unchanged and it
is CUDA on a CUDA build, but it is read through the platform seam rather than as
an enum value, so the same `1` selects Metal, Vulkan or Tenstorrent on a build
that registers one of those, and is refused by name on a build that registers
none. The C ABI's text-generation `vllm_model_params.device` is a separate,
later selector with its own `0 = auto / 1 = cpu / 2 = cuda` numbering.

The LTX-2.5 arm runs on the CPU in f32 and on CUDA in bf16. `device = 0` takes
the f32 parity forward; `device = 1` stages the DiT to the GPU one tensor at a
time and runs the device-resident forward, so a CUDA handle means a CUDA forward.
On a build with no CUDA backend, `device = 1` is refused by name rather than
served the CPU forward behind a CUDA handle. `encoder_path` loads the Gemma-4
On a build with no accelerator backend, `device = 1` is refused by name rather
than served the CPU forward behind an accelerator handle. It is also refused when the build's
accelerator is a PARTIAL backend that declines this architecture — Metal and
Tenstorrent each register the kernels for a named short list of models, and a
backend that has not registered this one now says so by name instead of binding
a queue and failing later inside a kernel. The same three questions decide
`minimax-h3`'s `device = 1`, which resolves through the platform seam rather
than reading the ABI selector as an enum value, so on a CPU-only build it throws
instead of naming CUDA. `encoder_path` loads the Gemma-4
text tower, and the request's own `prompt` then conditions the render; the tower
itself runs on the CPU in f32 whichever device the DiT is on. Without one,
conditioning comes from the two prompt-embeds files, which must agree on their
Expand Down
13 changes: 10 additions & 3 deletions include/vllm.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,9 @@ typedef struct vllm_model_params {
* silently replaced by another (mirror of vLLM assigning an explicit
* device verbatim, device.py:61-66).
* 0 must stay auto so a zero-initialized struct preserves pre-v14 behaviour;
* the cpu-before-cuda value order follows the v12 precedent
* (vllm_video_model_params.device: 0 cpu, 1 cuda) shifted by the auto slot.
* the cpu-before-accelerator value order follows the v12 precedent
* (vllm_video_model_params.device: 0 cpu, 1 the resolved accelerator)
* shifted by the auto slot.
* Any other value fails vllm_engine_load with VLLM_ERR_INVALID_ARGUMENT. */
int32_t device;
/* ── KV-pool sizing (ABI v16) ──────────────────────────────────────────────
Expand Down Expand Up @@ -874,7 +875,13 @@ typedef struct vllm_video_model_params {
* are byte-structurally identical, so it must be DECLARED; NULL/empty makes
* every generate refuse with the guidance (the #77 guard). */
const char* partition;
int32_t device; /* 0 cpu, 1 cuda */
/* 0 is the CPU; 1 is THE ACCELERATOR THIS BUILD RESOLVES, through the
* platform seam (CurrentPlatform + TryGetBackend +
* supports_model_architecture), never the enum value 1. It is therefore CUDA
* on a CUDA build and refused BY NAME on a build with no accelerator backend,
* or one whose partial backend declines this architecture (#659, #660). The
* ABI value is unchanged; what it means was never "cuda". */
int32_t device;
int32_t dequant_bf16; /* 0 keep-quant, 1 dequant/stream bf16 */
int32_t fp4_resident; /* NVFP4+cuda: keep FP4 packed, Marlin W4A16 GEMM */
/* ── v18 additions (the generalized seam) ─────────────────────────────────
Expand Down
5 changes: 3 additions & 2 deletions include/vllm/config/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
// - The integer values are the C-ABI wire contract
// (vllm_model_params.device, ABI v14): 0 MUST be auto so a zero-initialized
// struct preserves the pre-v14 accelerator-first behaviour byte for byte;
// cpu-before-cuda then follows the shipped v12 precedent
// (vllm_video_model_params.device: 0 cpu, 1 cuda) shifted by the auto slot.
// cpu-before-accelerator then follows the shipped v12 precedent
// (vllm_video_model_params.device: 0 cpu, 1 the accelerator that build
// resolves) shifted by the auto slot.
#ifndef VLLM_CONFIG_DEVICE_H_
#define VLLM_CONFIG_DEVICE_H_

Expand Down
14 changes: 11 additions & 3 deletions include/vllm/multimodal/minimax_h3_video.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,14 @@ namespace vllm::multimodal {
inline constexpr char kMiniMaxH3VideoFamily[] = "minimax-h3";

// Map the stable public video ABI device selector onto the runtime's generic
// backend key. The ABI remains 0=CPU / 1=CUDA; callers below this seam dispatch
// only through the returned DeviceType.
// backend key. The ABI is unchanged — 0 is the CPU, 1 is the accelerator, and
// anything else throws — but 1 is RESOLVED through the platform seam
// (`CurrentPlatform().device_type()` + `TryGetBackend` +
// `supports_model_architecture`), never cast from the integer. It therefore
// THROWS on a build with no accelerator backend, or one whose partial backend
// declines this architecture, instead of naming a device that build cannot run
// (#659, #660). Callers below this seam dispatch only through the returned
// DeviceType.
vt::DeviceType MiniMaxH3VideoDeviceType(int32_t device);

// ── Load-time parameters (the checkpoint set; the C ABI mirror is
Expand All @@ -79,7 +85,9 @@ struct MiniMaxH3VideoModelParams {
// declared-but-unknown and the #77 guard refuses every full render
// (MiniMaxH3PartitionFromFlag / MiniMaxH3CheckTaskPartition).
std::string partition;
int32_t device = 0; // 0 cpu, 1 cuda
// 0 cpu, 1 the accelerator this build resolves — see MiniMaxH3VideoDeviceType
// above; never `static_cast<vt::DeviceType>(device)` (#660).
int32_t device = 0;
int32_t dequant_bf16 = 0; // 0 keep-quant, 1 dequant/stream bf16
// NVFP4 + cuda only: keep the packed FP4 resident and route the quantized
// projections through the Marlin W4A16 GEMM (the pre-fold --fp4-resident).
Expand Down
5 changes: 4 additions & 1 deletion include/vllm/multimodal/video_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ struct VideoModelParams {
// value that is not registered is refused (it is never treated as a hint).
std::string family;

int32_t device = 0; // 0 cpu, 1 cuda
// 0 is the CPU; 1 is the accelerator this build RESOLVES through the platform
// seam, not the enum value 1 (#659, #660). Refused by name when this build has
// no accelerator backend, or its partial backend declines the family.
int32_t device = 0;
int32_t dequant_bf16 = 0; // 0 keep-quant, 1 dequant/stream bf16
int32_t fp4_resident = 0; // keep packed FP4 resident + quantized GEMM
int64_t encoder_max_layers = 0; // 0 => all layers
Expand Down
Loading
Loading