Engine and serving execution matrix

August 22, 2026 · View on GitHub

This is the canonical stable-ID inventory for cross-cutting engine behavior at the parity pin 555967922 (vLLM 0.26.0.dev0 + transformers 5.14.1; advanced 2026-07-26 from the prior e24d1b24/0.25.0 pin, see specs/pin-advance.md), plus the historical additions from the v0.25.0 sync target 702f4814fe54. Model, quantization, kernel, and platform support remain in their own matrices. The inventory audit that established the 26 code-bearing baselines is recorded in feature-anchor-backfill.md.

Cross-ref (roadmap_v1 ORDER-1): the portable automatic op-fusion framework — which binds fusion recipes to forward-pass sites at model build — is tracked as KERNEL-FUSION-FRAMEWORK in kernel-matrix.md (its evidence is per-backend fused-kernel dispatch), spike portable-fusion-framework.md. The build-time recipe→site binding surface touches the engine forward, but the row lives in the kernel matrix; not duplicated here.

ANCHOR-BACKFILL means the named bounded slice has code and tests but still lacks its required leaf spike. PARTIAL means the implementation is also known to omit upstream behavior. Neither state is protocol-complete. A plain planned: specs/... entry is not an accepted spike and cannot make a row READY.

Current SERVE-GATE-ONLINE binding: 9ecd9d0: 114/124 (mem 4/4, c1 20/20, c2 20/20, c16 19/20, c4 & c32 18/20, c8 15/20); two-grid totality with f0fb727 (111/124) is 115/124 effective parity against vLLM 0.25.0 (27B). The bit-identical fast decode-kernel stack (348d12d+9ecd9d0) plus async-default-ON (a0013a2), the vendored Triton GDN cubin (a321d7c) and packed-decode equivalence (e47b4d6) closed +62 axes over the prior superseded bindings (3f256ab 55/124, 246a23c 49/124, a875397 52/124, all retained immutable). The residuals are the low-concurrency-median edge of a net-positive determinism tradeoff (we win the tails

  • high concurrency + throughput); no closeable real 27B deficit. Full grid + forensics: roadmap_v1.md and the parity ledger.
AreaRowsANCHOR-BACKFILLPARTIALSPIKEREADYACTIVEGATINGDONEINVENTORIED
Engine and scheduling3063138225
KV cache and memory2573234204
Parallelism600010005
Sampling and generation1542004014
Structured output and tools704002001
Speculative decoding260010100410
Serving, API, CLI, library361020311334
LoRA and adapters200001001
Long context and attention1050010103
Loading, tokenizer, config1334011121
Total17035184124191238

Engine core and scheduling

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
ENG-SCHED-COREText-generation running-first unified scheduler, FCFS, token budget, output update; two budget-fitting prefills co-schedule into one step (c2 parity — mirrors upstream, no divergence)T0vllm/v1/core/sched/scheduler.py:396,640,1501 @ e24d1b24/702f481; tests/v1/core/test_scheduler.py:86,847src/vllm/v1/core/sched/scheduler.cpp:114,234,365tests/vllm/v1/test_scheduler.cpp:143,205,241,416; tests/vllm/v1/test_engine_core.cpp:271planned: specs/unified-scheduler.md; verdict scheduler-prefill-coschedule.mdANCHOR-BACKFILL-
ENG-CHUNKED-PREFILLBasic token-budget chunked prefillT0vllm/config/scheduler.py:84; vllm/v1/core/sched/scheduler.py:835; tests/v1/core/test_scheduler.py:185,503,903src/vllm/v1/core/sched/scheduler.cpp:225,548tests/vllm/v1/test_scheduler.cpp:192; tests/vllm/models/test_qwen27_paged_forward.cpp:492planned: specs/chunked-prefill.mdANCHOR-BACKFILL-
KV-PREFIX-CACHEAPC hashes, lookup, allocation, partial blocks, eviction, plus explicit/model-default cache policy. W0 ports arbitrary-group no-prefix coordination and makes hybrid/attention-free defaults cache-off. Full-surface re-audit 2026-07-22 (spike) — the ported core is DEEPER than this row read (chain hashing, pool, all three coordinators, the complete hybrid intersection and four single-type managers), and the residual gaps are narrower and DIFFERENT: generate_block_hash_extra_keys: W2 DONE 2026-07-27 (CLAIM-ROADMAP-D4APC) — the hardcoded no-op is replaced by a 1:1 port of kv_cache_utils.py:451-591 (_gen_mm_extra_hash_keys + LoRA name + cache_salt, fixed order lora->mm->salt; prompt_embeds deferred, no prompt-embeds path). Request/EngineCoreRequest carry cache_salt + lora_name; FromEngineCoreRequest sets them BEFORE the first hash (fixed a latent ordering bug: mm_features were assigned after the ctor already hashed). The latent correctness trap is CLOSED and RED-first proven: with the stub, a tenant-B request false-hits tenant-A's 48 cached tokens (n1==48); with extra keys n1==0 (no false-share). This unblocks the MM + LoRA cache consumers. prefix-cache statistics: CLOSED 2026-07-22 (W1) — PrefixCacheStats/CachingMetrics ported 1:1 with log_stats DEFAULTED ON, which unblocks the BACKEND-GATE-CUDA-SGLANG-PREFIX hit-proof requirement; first measured hit rate 0.75 on a repeated-prefix corpus; no cache_salt; 1 of upstream's 4 hash algos; skip_reading_prefix_cache absent; partial-block primitives throw (upstream's own are DEAD CODE — no caller in vllm/ — so they are NOT owed as live behaviour). Also cleared: the "blocked on a supported non-hybrid family" blocker is STALE — dense models default APC ON and five have landed, yet NO gate has ever run cache-ON MLA prefix-cache-hit assert fixed 2026-07-23 (CLAIM-MLA-PREFIX-CACHE-ASSERT): FullAttentionManager::find_longest_cache_hit asserted kind()==kFullAttention, aborting DeepSeek-V2 (MLA group, kind kMlaAttention, APC default-ON) under asserts-enabled builds — latent since ec6f4be, inert under Release/NDEBUG. Relaxed to upstream's precondition isinstance(spec, FullAttentionSpec or ChunkedLocalAttentionSpec) (single_type_kv_cache_manager.py:578-582; MLAAttentionSpec IS-A FullAttentionSpec) ⇒ accept kFullAttention / kMlaAttention / kChunkedLocalAttention; restores DeepSeek-V2 SACRED gate 8/8 asserts-on, full-attention byte-identical, new MLA prefix-cache-hit unit cases.T0vllm/config/model.py:1805-1860; vllm/engine/arg_utils.py:510,1160-1166,2473-2508; vllm/config/cache.py:39,93,95; extra keys vllm/v1/core/kv_cache_utils.py:539-574; hasher factory :673-730; vllm/v1/core/kv_cache_coordinator.py:377-425,782-834; tests/v1/core/test_prefix_caching.py:225,1475,2781hashes/managers src/vllm/v1/core/kv_cache_utils.cpp:259,291; extra_keys generate_block_hash_extra_keys + _gen_mm_extra_hash_keys src/vllm/v1/core/kv_cache_utils.cpp; cache_salt/lora_name on include/vllm/v1/request.h + include/vllm/v1/engine/types.h, copied in src/vllm/v1/request.cpp FromEngineCoreRequest (fields set before the first hash); src/vllm/v1/core/kv_cache_manager.cpp:124; no-prefix coordinator/factory src/vllm/v1/core/kv_cache_coordinator.cpp:260,273,279,545; model-default/hasher selection src/vllm/entrypoints/model_loader.cpp:109,167,180,191; CLI examples/server/main.cpp:126; statistics include/vllm/v1/metrics/stats.h, recorded src/vllm/v1/core/kv_cache_manager.cpp:139-147, reset flag :270-276, take-and-swap make_prefix_cache_stats(), per-step window fold at the end of Scheduler::schedule(), accessors Scheduler/EngineCore/LLMEngine::prefix_cache_metrics(); Request::num_preemptions un-deferred (include/vllm/v1/request.h, incremented in Scheduler::preempt_request)existing APC primitives tests/vllm/v1/test_kv_cache_utils.cpp:411,516,536; no-prefix hybrid allocation/no-hit tests/vllm/v1/test_kv_cache_coordinator.cpp:213; default/override resolution tests/vllm/entrypoints/test_loaded_engine_dense.cpp:343; server help and online cache-off contracts examples/CMakeLists.txt:34; tests/tools/test_online_gate_client.py:582,633; statistics plus the first MEASURED hit rate tests/vllm/v1/test_prefix_cache_stats.cpp 12/12; W2 extra_keys — ported mm/lora/salt cases + ordering + hash-level no-false-share tests/vllm/v1/test_kv_cache_utils.cpp (29/29), manager-level salt-partition no-false-share (RED-proven n1 48->0) tests/vllm/v1/test_kv_cache_manager.cpp (10/10), CPU gate on dgx GB10. W3 DONE 2026-07-27 (CLAIM-ROADMAP-D4APC-W3, dgx GB10, NOT pushed) — the FIRST-EVER cache-ON model gate: tests/parity/test_qwen3_apc_e2e.cpp on Qwen/Qwen3-4B (dense, full-attention, APC-default-ON) 2/2 cases, 84/84 asserts — APC-ON hits 2240/2777 (rate 0.807) / APC-OFF 0; APC-ON == APC-OFF token-exact 5/6 (1 diff a vLLM-confirmed 0.125-nat near-tie); == vLLM-APC-ON teacher-forced (OFF 6/6 gap 0.0, ON 6/6 gap ≤0.125 nats, 0 outside top-20); TTFT 70.1→39.9 ms = 1.76×. NO engine code changed (gate-only over the already-shipped default-ON path); 4B SACRED 16/16 no-regression. Oracle vLLM 0.25.0. Ledger: parity-ledger.md#L746prefix-prompt-caching-parity.md (umbrella); prefix-caching.md (cache-policy leaf)DONE (dense APC path; W4 events/W5 partial/W6 mamba-align/W7 reset endpoint tracked in KV-EVENTS/KV-MAMBA-ALIGN/own future rows)a41af480
KV-PREFIX-MATCH-UNIT--prefix-match-unit (config prefix_match_unit): the finest token boundary a prefix-cache hit can land on == the hash_block_size/"prefix match unit" the block hasher uses. NEW in 0.26 (absent at the prior e24d1b24/0.25.0 pin). For a HYBRID/multi-group model the resolver resolve_kv_cache_block_sizes computes hash_block_size = prefix_match_unit if set else gcd(group_block_sizes) (scheduler block size = lcm), letting matching land FINER than a physical block (e.g. 16/32 tokens inside a 1024-token block) provided every group block size is divisible by it; single-group (dense) models ignore the knob. Backs off to the scheduler block size when no prefix-cache/connector consumer is active or a mamba group diverges from cache_block_size (mamba_cache_mode != "align"); throws on a non-divisible unit. W0 spike + W1 resolver LANDED 2026-07-28 (CLAIM-PREFIX-MATCH-UNIT, NOT pushed): resolve_kv_cache_block_sizes ported 1:1 (explicit-parameter signature vs upstream's VllmConfig, our config surface is threaded), RED-first unit-gated (default gcd != =16 override). PARTIAL: the config/CLI/ABI field (W2), the scheduler threading of a resolved hash_block_size != block_size + mamba partial-tail stop (W3, needs the KV-BLOCK-POOL align path that still throws), and the benchmark (W4) are deferred. Default path byte-identical (single-group inert; scheduler still passes block_size).T1vllm/engine/arg_utils.py:696,1222,1940; vllm/config/cache.py:56-67; resolver vllm/v1/core/kv_cache_utils.py:626-688; hasher :691-748; call site vllm/v1/engine/core.py:154; scheduler vllm/v1/core/sched/scheduler.py:76,268-270,282,312-318; fine-grained view vllm/v1/core/single_type_kv_cache_manager.py:683,697resolver src/vllm/v1/core/kv_cache_utils.cpp:638 (resolve_kv_cache_block_sizes), decl include/vllm/v1/core/kv_cache_utils.h; hash_block_size already plumbed get_request_block_hasher src/vllm/v1/core/kv_cache_utils.cpp:577; DEFERRED align path throws src/vllm/v1/core/block_pool.cpp:93,220 (shared with KV-BLOCK-POOL)tests/vllm/v1/test_prefix_match_unit.cpp:64,88,99,119,129,145,164,186 8/8 (29 assertions): single-group inert + DCP scale, multi-group default=gcd, =16 override finer-than-default (RED), finer-than-1024-block, non-divisible throws, no-consumer back-off + connector-alone re-enable, mamba non-align back-off vs align gcd, hasher-granularity RED (coarse 2 vs fine 4 hashes); parity-ledger.mdprefix-match-unit.mdPARTIALCLAIM-PREFIX-MATCH-UNIT
ENG-PREEMPT-RECOMPUTEFCFS tail preemption with recomputeT0vllm/v1/core/sched/scheduler.py:1142; tests/v1/core/test_scheduler.py:930src/vllm/v1/core/sched/scheduler.cpp:102,157; src/vllm/v1/core/sched/request_queue.cpp:36tests/vllm/v1/test_scheduler.cpp:247,295; tests/vllm/v1/test_request_queue.cpp:91planned: specs/preemption.mdANCHOR-BACKFILL-
ENG-CUDAGRAPHDecode graph capture/replay modes (host-cluster cleanup: capture-size set derived from max_num_seqs mirroring vLLM _set_cudagraph_sizes; 2026-07-18 graph-baked-scratch use-after-free fix — the 35B c2+ online-serving IMA blocker)T0vllm/config/compilation.py:53,1319,683-684,1438-1444; vllm/config/vllm.py:1667-1770; vllm/v1/worker/gpu/cudagraph_utils.py:116; tests/compile/test_config.py:122,229src/vt/cuda/cuda_backend.cu:76,97,105; include/vllm/model_executor/models/decode_graph_sizes.h; src/vllm/model_executor/models/qwen3_5.cpp:3754,3952; src/vllm/v1/worker/gpu/runner.cpp:577,597; graph-safe scratch (retire-on-grow so graph-baked scratch pointers stay valid) src/vt/cuda/graph_safe_scratch.h, src/vt/cuda/cuda_moe_marlin.cu:75, src/vt/cuda/cuda_matmul_nvfp4.cu:766, src/vt/cuda/cuda_matmul_nvfp4_cutlass.cu:105, src/vt/cuda/cuda_matmul_fp8_cutlass.cu:95tests/vt/test_cuda_backend.cpp:98; tests/vllm/models/test_decode_graph_sizes.cpp; tests/vt/test_graph_safe_scratch.cpp; explicit 35B gate tests/parity/test_qwen36_paged_engine.cpp:140blocktable-host-cluster-cleanup.md; decode-graph-scratch-uaf-2026-07-18.mdPARTIALPREFILL capture REFUTED as a lever (2026-08-17, #1161). vLLM's v1 default already captures prefill piecewise (vllm/config/compilation.py:60-63,615,630 @ 555967922) and it is in our denominator; SGLang reached the same coverage without torch.compile via BCG (SGLANG-BCG in sglang-matrix.md). Neither helps us: GB10 2026-07-09 measured prefill GPU-idle-between-launches at 3.8% with GPU-busy >96% on both arms, and the 27B prefill gap at 92.5% non-GEMM glue GPU work with the dominant GEMM at +0.17% and attention AHEAD. There are no launch bubbles in our prefill to collapse. Row stays PARTIAL; the real residuals are exec dedup (#1162) and the break-point seam (#1163). Spec sglang-breakable-cuda-graph.md
ENG-CUDAGRAPH-DEDUPGraph-executable dedup: hash each captured graph's topology and re-point ONE cudaGraphExec with cudaGraphExecUpdate on a signature hit, instead of instantiating one exec per padded bucket per model. A memory and capture-time change, NOT a throughput change — a deduped replay launches the same nodes, and the load-bearing gate is byte-identity rather than a ratioT2vLLM has no analogue (its execs come from torch.compile, vllm/config/compilation.py:60-63,517,615,630 @ 555967922); secondary oracle SGLang python/sglang/srt/model_executor/runner_backend/cuda_graph_dedup_mixin.py:27-37,105-179,219-242,258-275,353-358 @ f63458b5be (oracles/sglang.md)W1+W2 landing here behind VT_CUDA_GRAPH_DEDUP, default OFF until the device A/B measures the per-switch update cost: a device-agnostic dedup registry shared by both accelerator backends plus one CUDA/HIP ops table written once, wired into EndCaptureGraph/ReplayGraph/DestroyGraph. Baseline it replaces: src/vt/cuda/cuda_backend.cu:222-232 instantiates a fresh exec per capture and destroys the raw graph, over the 7 (max_num_seqs=32) or 11 (64) buckets of include/vllm/model_executor/models/decode_graph_sizes.h:32-41, times NINE drivers (count corrected 2026-08-18, #1179; 9bc4d7f44 recorded eight, missing the DFlash draft graph src/vllm/model_executor/models/qwen3_dflash.cpp:771,870,1038,1091,1095,1106)tests/vt/test_graph_dedup.cpp 13/13 cases, 65 assertions, RED-first (written and run against an absent header, and the four cases added by the fresh review of #1178, three of them run against the unfixed source) and gated on every platform via a fake ops table whose launch log makes "the right nodes ran" an observable sequence over MORE than one replay per shape; 13/13 negative mutations detected (9 at implementation, 4 at review repair). That count covers src/vt/graph_dedup.h ONLY. src/vt/graph_dedup_runtime.h had NO executable coverage on any tier, and #1184 is what hid in that gap: the file is DESIGNED to see runtime calls fail — a refused cudaGraphExecUpdate probe is the feature working — and never consumed the runtime's latched error, so the next unrelated kernel reported the refusal as its own failure and every VT_CUDA_GRAPH_DEDUP=1 run died 6/6 on GB10 as greedy_argmax launch: invalid device function from a launch that had succeeded. Repaired structurally rather than at twelve sites: the clear lives in ScopedLatchClear's destructor (src/vt/graph_dedup_latch.h) installed at the six GraphDedupOps entry points by MakeLatchGuardedOps, the table's only constructor, so no raw function address reaches a field and an unwired seventh operation leaves a null the registry refuses; one line covers CUDA and HIP. The device-free half of the signature walk moved to src/vt/graph_dedup_signature.h and is gated by tests/vt/test_graph_dedup_runtime.cpp 13/13 cases, 51 assertions, RED-first against the pre-fix guard (22 failed assertions reproducing the production message), 7/7 negative mutations detected — Kahn ordering, topological re-index, sorted edge emission, the depth-4 child bound and the four graph-level escapes. STILL compile-gated only: the five node-payload cases behind the device policy. DEVICE A/B DELIVERED 2026-08-18 on dgx:gpu0 (GB10, driver 580.173.02, nvcc 13.0.88, rc job f88d484b), and it SPLIT. Gated commit 72de552c8, whose four dedup sources are byte-identical to the merged 2a976eb9f — the row squashed, so the gated tree is not an ancestor of the merge and that sha equality is what carries the claim. CORRECTNESS PASSES: 12/12 cells exit 0, zero invalid device function and zero engine-fatal in every cell log where the pre-fix head e4ce5571a died after exactly one replay, ON replays as often as OFF (60=60, 33=33, 43=43), and --output-token-ids is IDENTICAL over 10/10 comparisons with the three OFF/OFF controls passing FIRST and the three workloads hashing to three DIFFERENT values, so the identity is not vacuous. #1184 is closed by this run, because a CPU suite drives a fake runtime and cannot observe the real latched error. THE BENEFIT IS REFUTED for the case this row was filed for: N == M in every ON cell — 3 graphs to 3 execs on sizes [24 16 8], 2 to 2 on [16 8], 2 to 2 on [32 24] — with the registry's count CLIMBING 1→1, 2→2, 3→3, so more than one capture reached it and the 1:1 is a measurement rather than the single-capture artefact the first attempt produced. Cause pre-registered before the run and then confirmed, structural rather than a tuning miss: AppendKernelPayload hashes (func, gridDim.{x,y,z}, blockDim.{x,y,z}, sharedMemBytes) at src/vt/graph_dedup_runtime.h:121-128 and the memcpy payload hashes the copy extent, so the padded batch dimension sits in the KEY, no candidate group ever forms and cudaGraphExecUpdate is NEVER ATTEMPTED. That contradicts this row's own premise — graph_dedup.h's header says the fold is for "two padded batch sizes … the same node topology with different parameters" — and SGLang keys the same fields (cuda_graph_dedup_mixin.py:105-114), so whatever folds upstream is not decode buckets either. NO throughput or memory number is recorded: clocks unpinned AND the ON arm allocated exactly as many executables as OFF. Honest gaps: per-shape replay counts are unavailable (the driver prints a TOTAL, so B's ~30-per-shape is arithmetic); the driver's "N captured size(s)" counts SLOTS not captures (A reports 6, emits 3); the container's own cuBLASLt was never re-tested at CUDA 13.0 because the staged cu130 prefix was probed first and worked; only the Qwen3 dense decode driver was exercised. STILL OWED: the default flip, now NOT JUSTIFIED on this evidence rather than merely ungated; a COARSER key that could group two decode buckets at all, which the probe-before-fold design makes a cost question rather than an obviously unsafe one (#1226, the next traceable hypothesis, deliberately NOT decided by this record); device-tier signature stability/discrimination tests; probing current_raw instead of raws.front() to retire the update-transitivity assumption; the ROCm compile; a supporting orin:gpu0 leg, BLOCKED because the Jetson 540.4.0 driver cannot run a CUDA 13 runtime (cudaGetDeviceCount err=35); and reaching the feature from the default serving path at all — the async runner captures no decode graph, W5, THE SAME DAY, CONFIRMED THE HYPOTHESIS THAT NEGATIVE PRODUCED (#1226 DELIVERED). Same box, rc-worker-4b8lj, boot_id 3fd9745a-d25a-426c-ba3c-97c958a85515 at both ends, GB10, driver 580.173.02, ### DONE_AB_KEY 2026-08-18T20:58:46Z, binary sha256 ca114abb…c772ad from b48b51df1 (tar sha256 asserted before extraction). Drop the launch dimensions and the memcpy extents from the key and every bucket folds: a_coarse 3 graphs to 2 execs, b_coarse 2 to 1, c_coarse 2 to 1, each probes=1 refused=0, against probes=0 refused=0 in every EXACT cell. probes=0 in the EXACT cells is the direct process-level proof of W4's source-level diagnosis — with the launch dimensions in the key no candidate group forms and cudaGraphExecUpdate is never asked; drop them and it is asked once per fold and ACCEPTED EVERY TIME. The saving W4 recorded as unreachable is reachable via the key. Byte-identity holds on A (five cells, 59ebff4a…) and C (four cells, ff205260…). Workload B is VOID rather than a pass, and its cause is a NEW DEFECT that is not this row's: the two VT_CUDA_GRAPH_DEDUP-unset control cells DISAGREED (5973c5a1… 2638 bytes vs 4cf79230… 2650 bytes) on one binary, one workload, greedy --temperature 0 --seed 777 at --concurrency 16, 23 s apart — 672 tokens both, so the byte delta is JSON width and not a length; exactly rows 17 and 18 of 21 differ, both mid-decode, both in the ragged tail 21 % 16 leaves. B's b_off_a == b_exact and b_off_a == b_coarse_a therefore compare against a baseline that does not reproduce itself and are WORTHLESS; only the OFF/OFF control made that visible, and without it B would have read as three more confirmations. Filed #1283. Caveats that bound this result: nvcc was 13.3.73 here and 13.0.88 for the W4 baseline the recorded dgx gate stack names, so the OFF-vs-ON and EXACT-vs-COARSE comparisons WITHIN this binary are valid while this run and that baseline are NOT directly comparable; clocks unpinned (2405 MHz current, 3003 max, 2418 applications) and nothing measured bytes, so NO throughput and NO memory number is claimed or implied; only the Qwen3 dense decode driver was exercised; refused=0 is ONE driver on ONE hardware and toolkit pair, which is no more a floor than W4's negative was a ceiling; and the coarse key is behind VT_CUDA_GRAPH_DEDUP_COARSE_KEY, default OFF, inside a default-OFF flag, on PR #1232 which is STILL A DRAFT — nothing on main folds today. Row stays ACTIVE, argued: not DONE, because the fold is unreachable on every shipping configuration and the row's stated MEMORY saving has never been measured in bytes on either key; not PARTIAL, because nothing upstream is omitted — the coarse key is our own extension past SGLang, which keys the fields we started from; not BLOCKED, because nothing external stops the next step. What is owed is now a DECISION about the default plus the byte measurement and the probe-cost-at-real-churn measurement it needs, and landing #1232 first W6, 2026-08-19, THE DEVICE-BYTE MEASUREMENT — THE BENEFIT QUESTION IS NOW CLOSED AND THE ANSWER IS NEGATIVE. Tested origin/main 2c8f53d93, which is PR #1232 LANDED, so the "nothing on main folds today" caveat every earlier record carried is RETIRED and this measures a configuration that ships. Same box, rc job 93f783de, pod rc-worker-4b8lj, boot_id 3fd9745a-… at BOTH ends, GB10, driver 580.173.02, nvcc 13.0.88 (the W4 baseline toolkit; W5 ran 13.3.73, so W6 and W5 are NOT directly comparable while comparisons WITHIN this one binary are valid), binary sha256 be697268…0ce657a7, ### DONE_BYTES 2026-08-19T04:57:19Z, 12/12 cells exit 0, zero VOID markers. THE FOLD ENGAGES AT THE SHIPPED BUCKET SET, which is the churn W5 could not produce: vllm-bench sets max_num_seqs = concurrency, so W32 captured [1 2 4 8 16 24 32] 7-of-7 and W64 captured [1 … 64] 11-of-11, exactly decode_graph_sizes.h:32-41, against the 2-3 buckets every earlier conclusion was drawn from. COARSE folds 7 graphs to 3 execs (probes=7 refused=3) and 11 to 5 (probes=22 refused=16); EXACT folds NOTHING at probes=0, reproducing W4 at four times the bucket count. Token ids byte-identical across every cell of a workload INCLUDING both OFF/OFF controls (ff0db6c6…be9d 11720 B; e1cbf5fc…e5d0 57620 B) — neither workload has #1283's ragged-tail shape and neither hit it. THE SAVING DOES NOT SURVIVE ITS OWN NULL CONTROL. nvidia-smi --query-compute-apps tail median (the --query-gpu=memory.used axis returns [N/A] on this box) shows W64 IDENTICAL to the megabyte in all five cells (9737) and W32's coarse arm reading 10-23 MiB HIGHER than OFF (3252/3262 vs 3262/3275). A cudaMemGetInfo shim summed over every instantiate gives a nominal 13.83 MiB at 7 buckets — 0.42% of a 3.25 GiB process — and −0.75 MiB, i.e. NOTHING, at 11. That nominal effect is NOT ESTABLISHED on four independent grounds: EXACT is a TRUE NULL (same 7 and 11 retained execs, probes=0, so it allocates what OFF allocates) and disagrees with OFF by 10.6-13.1 MiB against a 13.83 MiB candidate; the W64 OFF/OFF pair disagrees with ITSELF by 18.2 MiB; one instantiate recorded a NEGATIVE delta (-5,165,056 B); and cudaGraphExecDestroy reclaimed 0 in EVERY cell. Per-instantiate deltas for byte-identical 404-node graphs span 0 to 10,514,432 B and 17 of 27 instantiates in one cell read exactly zero, so these are POOL-GRANULAR readings and the coarse arm's throwaway probes grow that pool exactly like retained execs do. What CAN be priced: one ~390-node executable at 2.08-4.35 MiB, 10.0-10.6 KB per node — the figure to re-run on a deep checkpoint. THE MECHANISM INVERTS THIS ROW'S PREMISE. The driver refuses 43% of probes at 7 buckets and 73% at 11, every one of them probe refused a fold (err=910 result=2) = cudaErrorGraphExecUpdateFailure / cudaGraphExecUpdateErrorTopologyChanged. The shim's cudaGraphGetNodes reading says why false candidates form: the decode graphs are TWO topologies, 376 and 404 nodes, mixed across the buckets (w32_off_a captured 404 404 376 376 404 404 404). Every refusal is about TOPOLOGY, never a parameter, so a COARSER key produces MORE false hits rather than more folds — the opposite of what W5's 2-bucket A/B suggested, and W5's refused=0 is now explained as an artefact of workloads whose buckets only ever SHRANK, so exactly one pair was ever presented. COST: W32 OFF 7 instantiates / 0 updates vs COARSE 10 (3 retained + 7 probes) / 11 updates; W64 OFF 11 / 0 vs COARSE 27 (5 retained + 22 probes) / 28 updates — 2.45x the instantiate calls to retain 6 fewer executables. Peak transient did NOT double — in every ON cell live-bytes peak == end, because Register destroys the probe before returning, so the feared "double the peak to save the steady state" trade did not occur. A replay-time re-point DID occur — 4 and 6 non-probe updates over 88 and 244 replays, ARITHMETIC over two printed totals and not a counter — with every cell exiting 0 and byte-identical, so Replay's transitivity assumption neither aborted nor changed a token; W5 recorded that case as untested. CAVEATS THAT BOUND THIS RESULT: the clock pin was REFUSED inside the lease (The current user does not have permission to change clocks for GPU 0000000F:01:00.0, clocks_pinned=0), so NO time-based figure is attributable and the instantiate-wall and update-wall figures in bytes.log are diagnostics quoted nowhere as a result; result=2 is ONE driver, ONE GB10, ONE toolkit; only the Qwen3 dense decode driver was exercised, as in W4 and W5; VT_ASYNC_RUNNER=0 throughout, so the feature is STILL unreachable on the DEFAULT serving path (#1179); and cudaMemGetInfo cannot separate an executable's own cost from the pool chunk that satisfied it. VERDICT, DELIVERED AND NEGATIVE: VT_CUDA_GRAPH_DEDUP stays default OFF, now on MEASUREMENT rather than on silence; VT_CUDA_GRAPH_DEDUP_COARSE_KEY alone is a NO-OP, not merely unsupportedGraphDedupCoarseKeyEnabled() (src/vt/graph_dedup.h:114) is read only by the signature builder (src/vt/graph_dedup_runtime.h:177), only from Register, only under GraphDedupEnabled() (src/vt/cuda/cuda_backend.cu:237), so with dedup off its sole observable is one stderr line; both on is unsupported. NOT A CEILING. Three things would change it and each is traceable: find where the 376/404 split comes from (the FA-2 split-KV grid is the first suspect — a capture that fixes the node set across buckets removes every refusal); an instrument that resolves a single 2-4 MiB executable against driver pool granularity (cuMemGetAllocationGranularity or a pool-statistics query); and the same measurement on a 60-80 layer checkpoint, where bytes scale with node count. Row STAYS ACTIVE, argued, and the argument is now narrow. The MEASUREMENT obligations are discharged and the DECISION is delivered, which is the DONE case and it is a real one. Three things stop the flip and none is a checker technicality: the feature is unreachable on the DEFAULT serving path, owned by ENG-CUDAGRAPH-BREAK (#1179) and the "nothing lands dead" half of this row; two items still sit under #1162 itself — the device-tier signature stability/discrimination tests and probing group.current_raw instead of raws.front() to retire the transitivity assumption; and the DONE record surface owes a .agents/parity-ledger.md entry, a closing-commit owner in place of the claim, an exact test anchor and the RELEASE of CLAIM-ENG-CUDAGRAPH-DEDUP, which is an operator act and which this record-only branch does not own. Not PARTIAL — nothing upstream is omitted. Not BLOCKED — nothing external stops the next step. Full evidence: benchmark-record.md entry ENG-CUDAGRAPH-DEDUP W6, raw at /mnt/nas_share/rc/dedup-bytes/eng-cudagraph-dedup.md; analysis sglang-breakable-cuda-graph.mdACTIVECLAIM-ENG-CUDAGRAPH-DEDUP (#1162)
ENG-CUDAGRAPH-BREAKOne shared vt capture seam that accepts BREAK POINTS, so a forward containing a host-dependent op is still graphed instead of falling out entirely — and so the NINE hand-rolled drivers become one (count corrected 2026-08-18, #1179; 9bc4d7f44 recorded eight). Coverage AND CORRECTNESS row, not a throughput rowT1mirror vLLM CUDAGraphMode.PIECEWISE splitting at splitting_ops (vllm/config/compilation.py:60-63,517,615,630 @ 555967922); construction from SGLang BCG python/sglang/srt/model_executor/runner_backend_utils/breakable_cuda_graph/breakable_cuda_graph.py:204-243,246-274,309-333,335-367 @ f63458b5be (decorator + runtime stream capture, no compiler); its unit suite test/registered/cuda_graph/breakable/test_breakable_cuda_graph.py:30,172,230 (305 lines, 11 unit cases) is mapped case for case in the spec's ## Tests to portW6 MOVED THE PREDICATE (#1374, 2026-08-19): GPUModelRunner::execute_model names the step's ACTUAL uniform query length once through v1::GraphEligibleQueryLen (src/vllm/v1/worker/gpu/cudagraph_dispatch.h, INERT with no caller since #442 and now called from production) and ships it on ModelForwardInput::uniform_query_len; the two Qwen3.5 registrations stop re-deriving that test in twenty duplicated lines each, and both key their slot ring on (S, q, spec). #1020 CLOSES on the pair, and the key half was a LIVE collision rather than the enabler #1020 called it: S = spec_step ? B : PadToCaptureSize(B) puts a 4-request spec step at 1+1 tokens and an 8-request padded decode on the same S == 8 at the base commit. The widening is BOUNDED by VT_SPEC_GRAPH_MAX_QLENS (default 2), because reading the actual length multiplies the spec shape ceiling by 1 + k. Seven of the nine drivers still read pure_decode and are byte-identical. What did NOT move is 'except at the break points': no driver in this tree serves a prefill or a mixed batch under any predicate, so that needs a prefill capture driver nobody has written and whose benefit D5 already refutes on this hardware — a publishable negative, recorded in the spec's ## Owed as a row-level item. The pre-W6 baseline it replaces: all-or-nothing, src/vllm/v1/worker/gpu/runner.cpp:1338-1341 routing only pure_decode; drivers qwen3_5.h:275, qwen3_5_dense.h:391, qwen3_moe.h:117, qwen3.h:243, deepseek_v2.h:324, voxtral.h:126, plus deepseek_v4.cpp, laguna.cpp — and the spike found the NINTH already written, src/vllm/model_executor/models/qwen3_dflash.cpp:771,1091. The re-derivation is measured, not asserted: StepDevInputs (src/vllm/model_executor/models/qwen3_5.cpp:3894, the persistent DEVICE input path) exists in ONE driver and grep -c returns 0 in qwen3_moe.cpp, qwen3.cpp, deepseek_v2.cpp and voxtral.cpp, which is why src/vllm/model_executor/models/qwen3.cpp's DenseDecodeGraphForward DECLINES the graph outright when the async device-token mirror is live. That decline is why this is also a CORRECTNESS row (#1179): a SHIPPED model has already lost its decode graph to the duplication, on the driver's own measurement (depth-1, graph ON PASS 78/78; depth-2, graph OFF PASS 82/82; depth-2, graph ON FAIL, slots 1-3 degenerate), and the fix its comment names is the sibling's StepDevInputs. The row still makes NO throughput claim: the prefill refutation on the ENG-CUDAGRAPH row (3.8% host idle, >96% GPU-busy, 92.5% glue) stands unchanged; #1305 ADVANCED AND EXPLICITLY NOT CLOSED, and reading the tree found a larger defect than the issue described (2026-08-19): qwen3_moe_registry.cpp, deepseek_v2_registry.cpp and glm4_moe_lite_registry.cpp never constructed a detail::DeviceTokenIdsScope and neither qwen3_moe.cpp's nor deepseek_v2.cpp's EmbedInto ever consulted one, so ModelForwardInput::device_token_ids reached NOTHING in either translation unit — the decode graph AND both eager arms embedded the host vector the runner's mirror arm deliberately leaves stale for decode rows. The three registries now publish the scope (the mechanism qwen3.cpp, qwen3_5.cpp, mistral_registry.cpp, internlm2_registry.cpp and llama_registry.cpp already use), and each decode-graph size slot holds a vllm::StepTokenIds (include/vllm/model_executor/models/step_token_ids.h) whose destination is a device buffer with a stable address, refreshed through vt::PersistentStepInput — host arm for the padded vector, DEVICE arm over the real prefix, both on the main queue so the second is ordered after the combine rather than racing it. That is vt::PersistentStepInput::RefreshFromDevice's FIRST production caller, retiring the staged slice W4 landed with none, and it is the fix qwen3.cpp's own decline comment names rather than a fifth private copy. qwen3.cpp's decline is UNTOUCHED: W4 measured its recorded cause false and its real one is unidentified. THE ISSUE SPLITS, and only one half settles. The EAGER half is fixed and gated on all three registrations and deserves to close. The GRAPH half does not: the mechanism these two drivers now have is functionally what qwen3.cpp ALREADY HAD at 338cbbfd1^ — a registry scope, consumed by EmbedInto, copying the mirror's ids over the embed source OUTSIDE the capture — and W4 recorded at qwen3.cpp:1083-1095 that the depth-2 graph-ON battery STILL FAILED with exactly that in place. A stable device address buys nothing while the embed stays outside the capture, which this change itself concedes. #1305's own settlement condition is that battery, it did not run, and the issue stays OPEN with the ENG-CUDAGRAPH-BREAK row as owner.owed: bit-exactness vs eager on every migrated model over MORE than one replay, on a real GPU — W2 did NOT meet it and says so: no rc lease was obtainable in its window and a CPU harness cannot replay a captured segment, so it moves to W3 with the three drivers of the same shape (G1); the host-lifetime contract of decode-graph-scratch-uaf-2026-07-18.md enforced AT the seam — D1's INPUT half, making the intermediates a segment reads unavailable to the DevicePool free list, which becomes live only for the first PIECEWISE production capture (W4); the auxiliary-stream auto-join before every segment close (:353-361, spec D10), live at src/vllm/model_executor/models/qwen3_5.cpp:6254-6255,6384 and src/vllm/model_executor/models/laguna.cpp:2572-2576,2612 (W4, W5). Delivered by W1 (#1192): the reachability mutation (performed; deleting the call site reds tests/vllm/models/test_qwen3_break_point.cpp and leaves the unit suite green); the ported SGLang unit cases with their arithmetic chains and post-replay assertions; and the break-function OUTPUT writeback (replay_fn/_copy_output breakable_cuda_graph.py:231-235,172-201, spec D9), whose destination is a vt::BreakSlot the seam owns rather than a caller reference it cannot outlive W6 gates (#1374): G2 at THREE levels because the claim has three parts — the engine (tests/vllm/v1/spec_decode/test_mtp_depth.cpp, a real LoadedEngine/EngineCore/Scheduler/runner stack, asserting clamped_spec_steps, measured 0/0/1/2/4 at k=1/2/3/4/6), the driver (tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp, two spec shapes of equal S and different q getting two rings and two captures), and the arithmetic (tests/vllm/v1/worker/gpu/test_cudagraph_dispatch.cpp). Five detecting mutations, each reddening ONE level and leaving the others green, plus an over-fire control. A SIXTH mutation was NOT detected and forced a repair: the per-request verify conjunct is redundant on every model that reads the field (both are GDN hybrids whose prefill trips the first conjunct), so it moved into GraphEligibleQueryLen where a mutation reds 4 assertions, and the spec records it as unreached defence in depth. G1 re-run on thor:gpu0 (sm_110, driver 595.78, nvcc 13.0.88): 2066 assertions, 0 failed, 0 differing on all five migrated drivers — W6 moves no logit. The ring key's own device case was BLOCKED by #1380, a pre-existing cudaMalloc inside a capturing stream on the spec arm that W6 neither caused nor regressed. #1380 is FIXED (2026-08-19, thor:gpu0 sm_110): a backtrace taken AT the failing cudaMalloc named the site as the GDN causal-conv output dconv in GdnBlockPaged, whose block lands in the same DevicePool SIZE CLASS as the retained [S, vocab] logits at the gate's shape, so the driver's one-block pre-grow met a measured demand of two. DevicePool now measures the per-class PEAK a step holds live above its own baseline and PreGrowForCapture makes the free list serve that profile before BeginCapture; both Qwen3.5 drivers record it per SLOT at their cold step. The device case drives one spec shape through BOTH ring slots into a replay against Qwen3_5DenseModel::ForwardDevice, with the two arms SEQUENCED rather than interleaved because an eager forward between the graph arm's steps deepens the shared free list and hides the defect (measured: interleaved passed 1240 assertions at the un-fixed head). The architecture question #1380 asked FIRST is answered by measurement on TWO devices: thor:gpu0 (sm_110) and dgx:gpu0 (GB10, capability 12.1, -DVLLM_CPP_CUDA_ARCHITECTURES=121a) give the SAME message and the same per-step shape at the red sha (507 assertions / 8 failed) and the SAME green after (6 cases / 3306 assertions / 0 failed, 0 differing, 3 replays). SPEC-DSPARK W8's working GB10 capture is explained rather than contradicted: whether the size classes collide is arithmetic over the MODEL's dimensions, and the real 35B's [S, vocab] f32 at vocab = 151936 shares a class with nothing the GDN block allocates. Also fixed in flow: #1394, a block table shorter than the sequence it addresses, which the CPU paged attention read past SILENTLY -- deterministic SIGSEGV on one measured build at main and wrong-page attention on another. #1305 (2026-08-19): tests/vllm/models/test_moe_async_device_ids.cpp, entered at ModelRegistry::Forward over a synthetic safetensors checkpoint for Qwen3MoeForCausalLM and DeepseekV2ForCausalLM — the production entry point, not the driver type. Three runs each: right host ids and no mirror as the reference, stale host ids and no mirror as the CONTROL that must differ, stale host ids with the truth reaching the model ONLY through device_token_ids as the gate. RED first at 2 cases / 65 assertions / 10 failed / exit 1, with 800 of 800 logit values differing over four steps on both architectures and every counter at 0; GREEN after at 65 of 65, exit 0. TWO mutations, each compiled clean and each restored by sha256: deleting the registry's scope line — the production call site — reds 4 assertions across both cases and puts all 800 values back, and swapping the seam's DEVICE arm for its HOST arm leaves the logits BIT IDENTICAL at 0 of 800 differing and reds only device_refreshes and host_refreshes, which is the arm no token gate can see. Neighbours green on the same binary: test_qwen3_moe_decode_graph_seam 228 of 228, test_deepseek_v2_decode_graph_seam 230 of 230, test_qwen3_decode_graph_seam 231 of 231, test_voxtral_decode_graph_seam 230 of 230, test_breakable_graph 265 of 265, test_persistent_step_input 66 of 66, test_model_registry 924 of 924, test_qwen3_moe_forward 504 of 504, test_deepseek_v2_forward 1052 of 1052. NOT measured: the depth-2 four-concurrent battery on a device, which needs a GPU and a real checkpoint; owed. Found red on main and NOT caused here: test_qwen3_5_decode_graph_seam exits 139 while its assertion line reads 135 of 135 passed (#1390); re-measured on this branch at exit 139 with the SAME crash case and site (test_qwen3_5_decode_graph_seam.cpp:800, W6: two spec shapes of EQUAL S and different q get two graphs) both WITH and WITHOUT this branch's working-tree changes, and its printed counts are not reproducible run to run on ONE unchanged binary — three consecutive runs of the same baseline binary gave 6 passed, 2 failed and 141 assertions, then no summary at all, then no summary at all. The exit code is the only stable observation, so no assertion count from that file carries a verdict. THE FRESH REVIEW FOUND THE GATE ABOVE COVERED HALF OF WHAT THE CHANGE CLAIMS and the repair widened it to 6 cases / 191 assertions / exit 0. What was ungated: the EAGER arms of both models — the half no graph refusal could have mitigated — and the THIRD registration, glm4_moe_lite_registry.cpp. Deleting the TakeDeviceTokenIds + d.b.Copy block from BOTH EmbedInto overloads left the old gate green at 2/2 and 65/65; deleting the GLM registry's two-line scope did too. The lane is now selected by the registry's OWN predicate: a case that constructs StaticGraphCpu gets the decode graph, a case that does not gets ForwardDevice, and through_seam asserts the vt::PersistentStepInput counters BOTH ways so a case cannot drift onto the other lane and stay green. Three detecting mutations, each compiled clean and each restored: the two EmbedInto call sites reds the 3 EAGER cases only (exit 1, 3/6); the GLM scope reds the 2 GLM cases only (exit 1, 4/6); the seam's RefreshFromDevice call reds the 3 GRAPH cases only (exit 1, 3/6). A fourth mutation FAILED TO BUILD under -Wunused-parameter and its verdict was DISCARDED rather than read as a pass. Still owed, and not implied: the behavioural half of the device contract — that the copy reads DEVICE memory, and that it is main-queue-ordered after the combine — is untestable on the CPU backend, where Backend::Alloc returns host-addressable memory and both refresh arms reduce to the same memcpy from the same address; swapping the device arm for the host arm leaves the logits BIT IDENTICAL and reds only the counters, which gate the instrument rather than the behaviour.spec eng-cudagraph-break.md (W0 spike DONE 2026-08-18: the existing vt capture vocabulary include/vt/backend.h:208-222 expresses a SEGMENTED capture with NO new virtual, because EndCaptureGraph stores nothing (src/vt/cuda/cuda_backend.cu:225-232); a break point is expressible with one thread_local capture pointer plus a free function, no compiler and no decorator); W1 DONE 2026-08-18 (#1192): the seam LANDSvt::BreakableGraph, vt::GraphCaptureScope and vt::GraphBreak (include/vt/breakable_graph.h, src/vt/breakable_graph.cpp), the SGLang unit suite ported case for case (tests/vt/test_breakable_graph.cpp, 24 cases / 163 assertions, re-derived 2026-08-18 by ninja test_breakable_graph && ./build/tests/test_breakable_graph; the recorded 14/81 never re-derived at any head of this branch), and ONE break point registered at the DENSE ATTENTION ENTRY of Qwen3ForCausalLM (src/vllm/model_executor/models/qwen3.cpp, inside RunLayer). The exit criterion W0 deliberately left open is ANSWERED on a leased GPU: cudaStreamEndCapture then cudaStreamBeginCapture on the SAME stream mid-forward with EAGER work between is LEGAL under cudaStreamCaptureModeThreadLocal (src/vt/cuda/cuda_backend.cu:204-206) — orin:gpu0 via an rc lease, driver 12060, 3 replays with fresh inputs, 0 mismatches, bare zero-work re-begin legal too. G2 reachability is tests/vllm/models/test_qwen3_break_point.cpp, which drives the production Qwen3DenseModel::Forward with a scope open and counts num_hidden_layers + 1 segments (mutation: delete the call site ⇒ 1 segment ⇒ RED), and holds G4 in the same case at 500 logits / 0 differing bit for bit. STAGED SLICE, named: the scope and the container are not yet ENTERED from a production step — no driver opens a scope until W2 migrates Qwen3DenseDecodeGraph — and the spec's ## Owed lists it with W2 as owner, alongside the D10 auxiliary-stream auto-join (W4/W5), G5's ROCm/Tenstorrent arms (W3) and G1 on a real GPU (W2). The capture-failure drain is NOT among them: it landed HERE, as behaviour (std::uncaught_exceptions() compared against the depth recorded at scope entry, so a break function or ordinary model code throwing mid-capture destroys the partial container instead of handing back a forward that reports captured() == true) and as three gated arms (tests 13a, 13b, 13c). The spec's ## Owed strikes the item through and reads DELIVERED in W1; this cell said the opposite until 2026-08-18 because cba969857 re-derived field 6 alone. W2 DONE 2026-08-18 (#1261): Qwen3DenseDecodeGraph MIGRATED and the seam is ENTERED from a production step, which retires W1's staged slice. Qwen3DenseDecodeGraph::Step opens a vt::GraphCaptureScope over a per-slot vt::BreakableGraph and replays through BreakableGraph::Replay; the hand-rolled BeginCapture/EndCaptureGraph pair, the raw void* handle, the bool captured flag, the DestroyGraph loop and the driver's own VLLM_CPP_CUDAGRAPH read are gone (re-derivation items 1, 2, 5, 6). The migration ADDED vt::GraphCaptureMode, mirroring vLLM's CUDAGraphMode (vllm/config/compilation.py:59-63), whose v1 default FULL_AND_PIECEWISE (:63) is documented at :630-632 as a FULL graph for DECODE batches and a piecewise one for prefill/mixed, with decode_mode() (:65-66) selecting the full half and the runtime reading it at vllm/v1/worker/gpu/cudagraph_utils.py:185-186. A decode driver opened kPiecewise would have turned a fully graphed decode step into ONE EAGER ATTENTION CALL PER LAYER between graph replays — not vLLM's decode behaviour, and invisible to every token gate here. GraphBreak in a kFull scope takes the pass-through arm and AppendBreak REFUSES a registration in that mode. G2 is tests/vllm/models/test_qwen3_decode_graph_seam.cpp (3 cases / 124 assertions), which asserts the SEAM's counters because a driver calling Backend::ReplayGraph directly leaves an identical backend log; the mutation restoring the pre-W2 raw pair (18 lines, compiled clean) left test_breakable_graph 27/27, test_qwen3_break_point 2/2 and test_qwen3_forward 10/10 GREEN and reddened only this file. G4 in the same file: capture step vs Qwen3DenseModel::Forward, 100 logits, 0 differing. The async decline at qwen3.cpp STANDS and is now GATED in both arms: migrating the capture does not move the INPUTS, so the depth-2 race is untouched, and the fix is StepDevInputs as a SEAM capability, which is W4. G1 is NOT met by W2 and is recorded owed rather than implied. W3 DONE 2026-08-19 (#1291): the three remaining PLAIN BATCHED drivers migrate — Qwen3MoeDecodeGraph, VoxtralDecodeGraph, DeepseekV2DecodeGraph — one commit each, each with its own RED-first G2 gate. Four of the nine drivers are now on the seam, and the six batched-driver VLLM_CPP_CUDAGRAPH reads ## Our baseline item 1 counted are down to TWO, both in qwen3_5.cpp (W4). Each gate asserts the SEAM's counters and not the backend log, because a driver that kept its raw pair produces identical logits, an identical backend log and an identical replay_count(); red-first on four assertions each (test_qwen3_moe_decode_graph_seam 222/226, test_voxtral_decode_graph_seam 224/228, test_deepseek_v2_decode_graph_seam 224/228, all exit 1), green 3/3 each after. The G2 mutation — restoring each pre-W3 driver file, 25/102, 23/92 and 25/94 lines, each compiled clean — reddens ONLY its own gate and leaves test_breakable_graph 216/216 and W2's test_qwen3_decode_graph_seam 231/231 green. The gate harness is now SHARED (tests/vllm/models/decode_graph_seam_harness.h); three more copies inside tests/ would have reproduced the duplication this row removes from src/. G1 IS DELIVERED and is no longer owed — the item W1 and W2 both carried. tests/vllm/models/test_decode_graph_seam_g1_cuda.cpp runs each driver COLD, CAPTURE and THREE consecutive replays against its own eager arm (selected by max_num_reqs == 0, so both arms are one binary on one device rather than two builds, each with its OWN device KV cache) on thor:gpu0 through an rc lease — NVIDIA Thor sm_110, driver 595.78, nvcc 13.0.88, source c905bb536, 32 .cu.o objects, binary resolving libcudart.so.13/libcublasLt.so.13: 3 cases, 1600 assertions, exit 0, 5 steps x 100 logits, 0 differing, 4 replays per driver. The COUNT carries that claim, not the status line: with no CUDA backend the same file prints SUCCESS! over assertions: 0. Bounded honestly — synthetic tiny models rather than a checkpoint, and W2's driver shares the seam by argument rather than by measurement. W3 also found a gate that could not fail. The three gates' breaks_registered == 0 mode guard is a TAUTOLOGY for any model with no registered break point, and the one production vt::GraphBreak in the tree is W1's in qwen3.cpp: flipping kFull to kPiecewise in qwen3_moe.cpp, one token, compiled clean and left that gate GREEN at 226/226. The mode was UNOBSERVABLE from outside a driver, so vt::GraphBreakStats gains full_scopes/piecewise_scopes, counted in GraphCaptureScope's constructor on the ACTIVE path only, with an inert-scope control; the same flip now reds all three gates on exactly those two assertions. NO break point is registered in these three models, deliberately: under kFull it would be pass-through machinery no gate can exercise, and the break-point set is what the PIECEWISE arm needs (W4/W6). The async decline, per driver: Voxtral needs none (its only construction site is VoxtralGenerateGreedy, unreachable from the runner); Qwen3-Coder and DeepSeek carry a NEW FINDING instead — qwen3_moe_registry.cpp:107, deepseek_v2_registry.cpp:106 and glm4_moe_lite_registry.cpp:125 route an async step into a host-vector replay with no device_token_ids check at all, filed #1305 with W4 as owner rather than mitigated on a measurement W3 cannot make. G5's ROCm/Tenstorrent arm is NOT discharged and moves to W5: the fleet carries no such device, so it is blocked on hardware rather than unattempted. W4 DONE 2026-08-19 (#1307): the persistent device input path becomes a SEAM CAPABILITY, and the two Qwen3.5 drivers migrate. vt::PersistentStepInput (include/vt/persistent_step_input.h, src/vt/persistent_step_input.cpp) binds a capture-stable device destination the DRIVER owns together with its pinned host staging block, and refreshes it in place from a host source or a DEVICE one; it owns the address-stability rule as a REFUSAL, the staging block, and the refreshing ARM as an observable (last_source(), vt::StepInputStats), and deliberately NOT the device allocation, because Qwen3_5DecodeGraph draws its retained inputs from a DEDICATED DevicePool so they never pop a block the captured forward's scratch then needs (D3). RED-first against a stub with the declared API and no guarantees: tests/vt/test_persistent_step_input.cpp 9 cases / 0 passed / 59 assertions / 32 failed / exit 1, GREEN after at 9/9 and 59/59; three mutations (delete the capacity refusal, make a null device source a silent no-op, collapse the host arm out of staging) each compiled clean and each reds exactly one case. Qwen3_5DecodeGraph and Qwen3_5DenseDecodeGraph open a vt::GraphCaptureScope over a per-slot vt::BreakableGraph in kFull and replay through it, and their PinnedStepInputs/StageStepInputs staging now runs THROUGH the capability, which is what makes it reachable rather than a class with a unit test. Six of the nine drivers are on the seam and grep -rn 'std::getenv("VLLM_CPP_CUDAGRAPH")' src/ returns exactly ONE line, src/vt/breakable_graph.cpp:61 — one switch, at last. Gate tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp RED-first on the MoE driver's five seam assertions (3 cases / 62 assertions / 5 failed / exit 1) and GREEN after at 7/7 and 129, G4 reading 40 values, 0 differing per driver; G2 mutations: the whole pre-W4 file restored reds BOTH drivers (296 lines, 10 assertions), the MoE replay bypassing the container reds ONLY the MoE case (7 lines), the MoE kFull->kPiecewise flip reds ONLY its mode counters (3 lines), and deleting the StageStepInputs call site reds ONLY the reachability case while test_persistent_step_input stays 59/59 green — the difference between a class that works and a capability something reaches. W4 FALSIFIED THIS ROW'S OWN PREMISE, which is its most important result. This record and the spec both said the fix qwen3.cpp's DenseDecodeGraphForward's decline names already existed as StepDevInputs. It does not: StepDevInputs has NO token-id member, and its pinned sibling PinnedStepInputs::token_ids was allocated at capture, filled every step, zeroed by the poison hook, and NEVER uploaded or read — the embed runs OUTSIDE the captured region from the HOST vector in every batched driver, so the decode graph carries no token ids to the device in ANY driver. The dead block is removed. Consequently the DECLINE STANDS and #1305 STAYS OPEN: W4 also read the decline's recorded cause against the tree at its own parent and found it falsified (the DeviceTokenIdsScope WAS live on the graph path, consumed by EmbedInto on all three arms at qwen3.cpp:610,621,644 @ 338cbbfd1^), so the measured failure is real and its mechanism is unidentified — not a state from which a refactor may retire a mitigation. The async battery was NOT run and W4 says so plainly: it needs dgx WITH the Qwen3-0.6B/4B checkpoints, dgx:gpu0 was held by another session for W4's whole window, and W4's lease was thor:gpu0. Still NO throughput claim. W5 DONE 2026-08-19 (#1335): the THREE SINGLE-SHAPE drivers migrate — the DFlash draft graph, the DeepSeek V4 decode graph and the Laguna decode graph, whose own note at laguna.cpp:2116-2119 asked for this seam by name and named V4's as the sibling that moves with it. NINE OF NINE DRIVERS ARE ON THE SEAM and the migration is COMPLETE: a call-shaped grep over src/vllm/ for BeginCapture, EndCaptureGraph, ReplayGraph and DestroyGraph, with comment lines excluded, returns NOTHING. The three per-model rollback switches stay (each an A/B lever for one driver); VLLM_CPP_CUDAGRAPH reaches all three for the first time. D10, the auxiliary-stream fork/join, is DISCHARGED and REACHEDGraphCaptureScope owns the outstanding-fork set and joins it before EndCaptureGraph (port of breakable_cuda_graph.py:353-361 plus the wait_stream hook :101-153), registered by vt::GraphNoteFork/GraphNoteJoin from laguna.cpp:2572-2576,2612, the only fork inside a captured region by construction. Every prior stage opened kFull, which has ONE segment and so no between-segments window, so the rule could not be exercised before W5 and untested machinery was not landed for it. Gated as a COUNTER and an ORDER out of one backend trace, five arms including the control where the model joins first, and two mutations (deleting the join reds only the new case on 5 assertions; making it over-fire reds it on 8). DFlash is the ONE single-shape driver gateable without a GPU, because its admission predicate names neither a device type nor a kernel registry: test_qwen3_dflash_decode_graph_seam.cpp RED-first 3 cases/0 passed/16 assertions/7 failed exit 1, GREEN after 3/18, and the G2 mutation reds ONLY that file while seven other suites — the driver's own test_dflash_propose included — stay green. G1 RE-RUN at W5's head on thor:gpu0 (sm_110, driver 595.78, nvcc 13.0.88, 32 .cu.o, source 79dc6b5bd) because D10 put a join on the path of EVERY segment close, so the seam changed underneath the five measured drivers: test_decode_graph_seam_g1_cuda 5 cases / 2066 assertions / 0 failed, each reading 0 differing, 4 replays, plus test_breakable_graph 265 on the same device. And the one thing a green build could NOT have told us was measured separately: Laguna's capture class sits behind #ifdef VT_MARLIN_NVFP4, so a passing build is the SAME OBSERVATION as one that compiled the region out. -DVT_MARLIN_NVFP4=1 is on laguna.cpp's own compile command, and an undeclared identifier injected immediately after its GraphCaptureScope line FAILED the object build under -Werror (laguna.cpp:2735) against an rc-0 baseline, restoring to an empty diff; the identical mutation on V4 failed at deepseek_v4.cpp:1921. Both migrated regions are COMPILED, which retires the could-not-even-be-built half. G1 for all three and G2 for V4 and Laguna are OWED on hardware, per driver and per reason: V4's CanRunResidentDecode refuses kCPU and needs the four CUDA-registered kernel families, Laguna's capture class exists only under VT_MARLIN_NVFP4. G5's ROCm/Tenstorrent arm stays BLOCKED — the fleet is all NVIDIA — and its owner moves from W5 to the ROW. Still NO throughput claim; analysis sglang-breakable-cuda-graph.md W6 DONE 2026-08-19 (#1374): the eligibility predicate, #1020, and the negative result on the piecewise arm.ACTIVECLAIM-ENG-CUDAGRAPH-BREAK-W6; #1163, #1192, #1261, #1291, #1307, #1305, #1020, #1335, #1374, #1380, #1390
ENG-CUDAGRAPH-DIFFUSIONCapture the LTX-2.5 denoise loop (fixed shapes, many identical iterations — the ideal graph target). BLOCKED, and the blocker is ours: the render does almost no device compute to captureT2SGLang enabled BCG on this shape AFTER our pin — LTX-2 H200 two-stage 10.75s->6.90s (d4be483efb), SANA 1024px -26% (6c7498113f), SANA denoise 0.73->0.457s (56ef810cad). Dated events, NOT pinned evidence; their win is mostly PyTorch host tax we do not payNO capture at all: grep for capture across src/vllm/model_executor/models/ltx2*.cpp returns nothingblocked by #1024 (GPU util exactly 0 in 321 of 347 samples, 1.00 core of 20 held for 17+ min after staging), #1007 (VAE decode has no device arm), #1087 (57-66% of wall is ONE resolution-CONSTANT serial host phase), #1010 (no phase-boundary log). Decision point is a MEASUREMENT of GPU-busy vs wall once device-resident, not an implementation. The unblock order now has an owning row: LTX25-DEVICE-RESIDENCY (#1264, ltx25-device-residency.md) stages those defects W0-W6 and carries this decision point as its W7 — if the loop comes back GPU-bound, #1164 closes as a refutation the way #1161 closed prefill capturesglang-breakable-cuda-graph.mdINVENTORIED#1164
ENG-BATCH-INVARIANTOpt-in deterministic execution across scheduler batch sizes (VLLM_BATCH_INVARIANT=1): batch-invariant matmul/norm/attention/collectives plus persistent-scheduler NVFP4; production default remains offT1default/env vllm/envs.py:89,576-578; initialization vllm/v1/worker/gpu_worker.py:1262; NVFP4 dispatch csrc/libtorch_stable/quantization/fp4/nvfp4_scaled_mm_sm120_kernels.cu:212-220; suite fixture tests/v1/determinism/conftest.py:9-12; operator/e2e tests/v1/determinism/test_nvfp4_batch_invariant_scaled_mm.py, tests/v1/determinism/test_nvfp4_batch_invariant.py @ 702f481-W3-C3R executed contract: production-default ours and vLLM both change outputs across batch shapes; no local opt-in implementation is claimedplanned: specs/batch-invariant-execution.mdINVENTORIED-
ENG-ASYNC-SCHEDAsync/overlap scheduling (AsyncScheduler placeholders + depth-2 batch-queue step + async D2H on a copy stream); vLLM's DEFAULT at the pin — mirror obligation per B3. Host-side machinery + runner device-input half + sampler-OUTPUT half LANDED + CPU-gated (2026-07-16): AsyncScheduler placeholder accounting, step_with_batch_queue depth-2, ResolveAsyncScheduling default-ON-when-compatible + MaxConcurrentBatches, VT_ASYNC_SCHED rollback; the runner device-input path combine_sampled_and_draft_tokens; PLUS the sampler-OUTPUT half — vt::Backend event/pinned primitives (AllocPinned/events, CUDA cudaHostAlloc+cudaEvent, CPU sync-degeneration), AsyncGPUModelRunnerOutput (device sampled-id snapshot → non-blocking D2H on a copy queue + event; get_output() waits only that event; MAIN queue never blocked), Sampler::forward(sampled_ids_out) device-resident greedy, GPUModelRunner::sample_tokens_async + runner_supports_async, and the Executor+step_with_batch_queue seam resolving get_output() at CONSUME time. All behind VT_ASYNC_RUNNER/set_async_input_combine, default OFF. Sync path byte-identical (placeholder sites INERT while count 0; combine off; sample_tokens_async degenerates to sync when async off; sampled_ids_out=nullptr). ENABLE-FLIP LANDED + CPU-gated (2026-07-16): (1) LoadedEngine now reorders runner_ before the scheduler and builds an AsyncScheduler + max_concurrent_batches=2 when ResolveAsyncScheduling(runner_.runner_supports_async()) resolves ON (else the byte-identical synchronous Scheduler + depth-1); the resolved mcb threads into AsyncLLMEngineCoreProc (step_with_batch_queue) and the "Asynchronous scheduling is enabled/disabled" log mirrors vLLM for A/B audit; (2) the device combine/scatter kernel (_combine_sampled_and_draft_tokens_kernel + last_sampled scatter) is ported to CUDA (src/vt/cuda/cuda_combine_tokens.cu), main-stream-ordered on the CUDA async path so it DELETES sample_tokens_async's pre-scatter Synchronize; the CPU backend keeps the host loop. VT_ASYNC_RUNNER=1 engages full W3; VT_ASYNC_SCHED=0 is the same-binary rollback. Production default (no env) stays synchronous byte-identical. FULL W3 DGX proof RAN twicef086b64 (5/5 gates PASS; c16 TPOT −5.4 ms WIN, tput neutral, TTFT +36 % = Little's-law repayment) and the 2026-07-16 re-proof on the THROUGHPUT-lever fix (persistent pooled sampled-id/pinned buffers + Sampler greedy scratch removing ALL per-step cudaMalloc/cudaFree/cudaHostAlloc/event-create from the sampled-id path, incl. the overlap-killing cudaFree inside get_output; mirrors gpu_model_runner.py:873-878 + async_utils.py:12-70): token-exactness 6/6 PASS, interleaved c16 tput −0.32 % (gate ≥+1.5 % FAILS), TPOT −4.95 ms retained, TTFT +34.8 % — the allocator lever is REFUTED as the tput unlock (≤0.1 % of a ~165 ms c16 step). DEFAULT FLIPPED ON 2026-07-17 (VT_ASYNC_RUNNER default ON via the pure AsyncRunnerFlagIsOn predicate, mirroring vllm/config/vllm.py:992-1044): the discriminator (6ea7856) proved vLLM's own async pays the identical +26–31 % TTFT / −0.7 to −0.9 % tput / −2.6 to −4.3 ms TPOT envelope and W3-ON nets positive (both binding ITL-tail anomalies flip to PASS), so the "needs a throughput lever" ship-gate is RETIRED — W3 is a parity/mirror obligation with a tails+TPOT win. The flip is TOKEN-NEUTRAL (async-ON ≡ async-OFF bit-identical on DGX). VT_ASYNC_RUNNER=0 = runner-level rollback, VT_ASYNC_SCHED=0 = scheduler-level rollback. TTFT means rise into vLLM's async envelope BY DESIGN — the next binding grid runs async by default and its TTFT must NOT be misread as a regression. ROBUSTNESS FIX 2026-07-20 (discard_request_mask): the runner was missing vLLM's discard_request_mask, so GPUModelRunner emitted a sampled token for prefill-CHUNK requests too; under async this drained a num_output_placeholders never reserved (the is_prefill_chunk path adds none) → the async_scheduler.cpp num_output_placeholders >= 0 assertion aborted on c8 + short-output (chunked prefill + preemption). FIX mirrors vLLM: execute_model computes exec_state_.discard[i] = seq_len < num_tokens (gpu_model_runner.py:2048); sample_tokens clears those rows to empty (outputs.py:303), the async path passes invalid_req_indices to AsyncGPUModelRunnerOutput::get_output (gpu_model_runner.py:3625 + outputs.py:303). Scheduler UNCHANGED (assertion kept — it was correct once the runner honors scheduler.py:1888-1890). Sync/non-chunked decode byte-identical (mask all-zero); DGX 27B 235/235 + 35B 315/315, vllm-bench c8+short-output+chunked+kv-pressure no longer crashes, memcheck 0. Ledger parity-ledger.md 2026-07-20 rowT1vllm/v1/core/sched/async_scheduler.py:12; vllm/config/vllm.py:490,990,1038; vllm/v1/engine/core.py:519; vllm/v1/worker/gpu/input_batch.py:304-406; vllm/v1/worker/gpu/async_utils.py:12-70; vllm/v1/worker/gpu/gpu_model_runner.py:242-332; vllm/v1/outputs.py:298-307src/vllm/v1/core/sched/async_scheduler.cpp:10,45; placeholder plumbing src/vllm/v1/core/sched/scheduler.cpp:148,164,605; src/vllm/v1/engine/core.cpp:91 (step_with_batch_queue, async-output seam); src/vllm/v1/engine/core_proc.cpp:32,46; config include/vllm/config/scheduler.h:117,165,188, src/vllm/config/scheduler.cpp:12; include/vllm/v1/request.h:187; runner input leaf src/vllm/v1/worker/gpu/prepare_inputs.cpp, src/vllm/v1/worker/gpu/input_batch.cpp; runner output leaf include/vt/backend.h+src/vt/backend.cpp+src/vt/cuda/cuda_backend.cu (event/pinned), include/vllm/v1/worker/gpu/async_output.{h,cpp} (AsyncGPUModelRunnerOutput), src/vllm/v1/sample/sampler.cpp (sampled_ids_out), src/vllm/v1/worker/gpu/runner.cpp (sample_tokens_async/runner_supports_async), src/vllm/v1/executor/executor.cpp+include/vllm/v1/worker/gpu/model_runner_base.h (async seam); enable-flip include/vllm/entrypoints/model_loader.h+src/vllm/entrypoints/model_loader.cpp (runner_ before scheduler, ResolveAsyncEnabled/MakeScheduler, AsyncScheduler+mcb=2, log), include/vllm/v1/engine/async_llm.h+src/vllm/v1/engine/async_llm.cpp (mcb param → EngineCoreProc); device kernel include/vt/cuda/combine_tokens.h+src/vt/cuda/cuda_combine_tokens.cu, wired src/vllm/v1/worker/gpu/runner.cpp (CUDA combine/scatter branch removes the pre-sync)tests/vllm/v1/test_async_scheduler.cpp:1 (6 cases, 54 asserts; RED vs base Scheduler 2/6 fail); depth-2 engine cycle tests/vllm/v1/test_engine_core_proc.cpp:479 (mcb=2, async-output seam); config resolution tests/vllm/test_scheduler_config.cpp:75; enable-flip construction matrix tests/vllm/entrypoints/test_loaded_engine_dense.cpp (runner×VT_ASYNC_SCHED → scheduler type + mcb; RED = un-flipped engine, 3/3 ON-arm asserts fail); runner input leaf test_combine_tokens.cpp (RED = stale → 5/7 fail), test_input_batch.cpp, test_runner.cpp (async-ON≡sync); output leaf tests/vt/test_backend.cpp (event/pinned contract), tests/vllm/v1/worker/test_async_output.cpp (materialize/flush/snapshot; RED = +1 splice), test_runner.cpp (sample_tokens_async decode ≡ sync); full CPU ctest 111/111, tools 164/164. Prior diagnostic 3812d8 six-leg control: total 1.002153×, TTFT 0.862159×, no GPU-time reduction (neutral for speed). DEFAULT-FLIP (2026-07-17): new pure CPU flag test test_async_runner_flag.cpp (11 asserts, default-ON/'0'-off); construction matrix test_loaded_engine_dense.cpp INVERTED (default → AsyncScheduler+mcb=2; RED verified 5 asserts fail vs un-flipped). CPU clean -Werror rebuild, full serial ctest 116/116, tools 164/164. DGX re-confirmation (evidence dgx:~/work/vllm.cpp-async-flip, CUTLASS+FA2 hard-verified, one flock): shipping default (async ON + RMSNorm-fast OFF) → 27B 235/235 + 35B 315/315 with the "Asynchronous scheduling is enabled (mcb=2)" log, and both rollback arms (VT_ASYNC_RUNNER=0, VT_ASYNC_SCHED=0) 235/235 + 315/315 log "disabled"; async arms BIT-IDENTICAL (token-neutral). Closing record parity-ledger.md#L502async-serving.mdDONE6ea7856
ENG-PRIORITY-SCHEDPriority request queue + policy + priority preemption + priority plumbing (Request/EngineCoreRequest/OpenAI field); W4 of the async-serving block. Default stays FCFS. GATING: full CPU tier green (93/93; 12 ported priority-scheduler cases + 14 priority-queue cases incl. the seeded random property test); GPU G1 (both greedy engine gates, priority-vs-fcfs token-exactness) deferred to the next GPU-idle window — GPU held by the SERVE-GATE-ONLINE campaign. BLOCKER CORRECTED 2026-08-12 (#534): the GPU is not what is stopping this, and G1 cannot be "rerun" because it does not exist. --scheduling-policy priority is plumbed to the production server (src/vllm/entrypoints/openai/server_main.cpp:408-411,672-673 -> SchedulerPolicyFromString -> SchedulerConfig::policy), but NO priority-vs-fcfs gate exists at the ENGINE/MODEL level. What exists is the scheduler-unit tier (test_scheduler.cpp:674,916 admission/preemption ordering, test_request_queue.cpp heap ordering) plus C-ABI wire-name validation (tests/capi/test_capi.cpp:1159); nothing anywhere drives a real engine with policy=kPriority and compares token streams against the fcfs arm. A next owner writes that gate RED-first, then runs it. The struck deferral is a 2026-07-10 scheduling note that five successive SERVE-GATE-ONLINE bindings (3f256ab, 246a23c, a875397, f0fb727, 9ecd9d0) have since expired. This is the ONLY genuinely open leaf of the ROAD-V1-C6 async-serving blockT1vllm/v1/core/sched/request_queue.py:131,201; vllm/v1/core/sched/scheduler.py:546; vllm/config/scheduler.py:109; tests/v1/core/test_scheduler.py:2382,2978; tests/v1/core/test_priority_scheduler_random.py:1src/vllm/v1/core/sched/request_queue.cpp:101,186; src/vllm/v1/core/sched/scheduler.cpp:178; src/vllm/v1/request.cpp:92; src/vllm/config/scheduler.cpp:21tests/vllm/v1/test_scheduler.cpp:674,916; tests/vllm/v1/test_request_queue.cpp:238,429async-serving.mdGATING-
ENG-PARTIAL-PREFILLConcurrent partial-prefill and long-prompt limitsT1vllm/config/scheduler.py:70-80--planned: specs/partial-prefill-concurrency.mdINVENTORIED-
ENG-BATCH-QUEUEPipelined step_with_batch_queueT1vllm/v1/engine/core.py:519--planned: specs/batch-queue-step.mdINVENTORIED-
ENG-CORE-BUSY-LOOPBusy loop with input/output queue split (in-proc analog of the ZMQ EngineCoreProc boundary); W1 of the async-serving block. Implemented: EngineCoreProc (queues, run_busy_loop, shutdown drain/abort, WAKEUP, ENGINE_CORE_DEAD) + InprocClient on a dedicated engine thread; sync LLMEngine path untouched; UTILITY/DP/aborts-queue/step_with_batch_queue deferred per spec. GATING: CPU suites green; GPU G1 (token-exact twins) + G4 (no-throughput-regression) deferred to the gating handoff — GPU held by the SERVE-GATE-ONLINE campaign. BLOCKER CORRECTED 2026-08-12 (#534): both are covered in substance and were never re-read onto this row. G1 — tests/parity/test_qwen36_async_serving.cpp (1718bf155, 2026-08-05) drives LoadedEngine::async_engine() -> AsyncLLM -> EngineCoreProc::step_with_batch_queue (depth-2) token-exact against the SAME pinned oracle continuation the SACRED sync gate uses, proven RED->GREEN on GB10 with compute-sanitizer 0 errors, joined by the classic-dense arm tests/parity/test_qwen3_dense_async_serving.cpp (52d76f3a9). G4 — the SERVE-GATE-ONLINE binding 9ecd9d0 114/124 runs exactly this path with async default ON. Promotion is the operator's rerun, not a records edit; the state is left unchanged deliberatelyT0vllm/v1/engine/core.py:915,1259; vllm/v1/engine/core_client.py:467include/vllm/v1/engine/core_proc.h:150; src/vllm/v1/engine/core_proc.cpp:51; src/vllm/v1/engine/core_client.cpp:33tests/vllm/v1/test_engine_core_proc.cpp:188,314,395 (9 cases, 82 asserts; CPU ctest 93/93)async-serving.mdGATING-
ENG-SCHED-KNOBSReserve-full-ISL, scheduler class seam, stream intervalT1vllm/config/scheduler.py:26,127,140,163include/vllm/config/scheduler.h:71,95; src/vllm/config/scheduler.cpp:43,52; src/vllm/v1/core/sched/scheduler.cpp:237; src/vllm/v1/engine/output_processor.cpp:68tests/vllm/test_scheduler_config.cpp:10,20; tests/vllm/v1/test_kv_cache_manager.cpp:425planned: specs/scheduler-knobs.mdPARTIAL-
ENG-CASCADE-ATTNCascade attention for shared prefixes. SPIKED 2026-07-22: VERIFIED NOT OWED on the path we mirror, for three independent reasons — (1) disable_cascade_attn defaults True (opt-in per its own docstring), (2) the implementation exists ONLY on the legacy V1 runner gpu_model_runner.py:504,2544; a recursive grep for cascade over the MRV2 tree vllm/v1/worker/gpu/ returns ZERO hits and we port MRV2, (3) FlashAttention is the sole implementing backend while FlashInfer/Triton/Flex/ROCm all hard-return False, and Blackwell resolves FlashInfer FIRST — so it is unreachable on our GB10 gate box. Also forces full CUDA graphs OFF, and the shared-block count is hard-0 for SWA/chunked-local/Mamba (our hybrid gate models). The scheduler-side input is already computed/plumbed, so if upstream moves it into MRV2 only the backend half remainsT2vllm/config/model.py:238,239-244; V1-only impl vllm/v1/worker/gpu_model_runner.py:504,2544,3869; backend support vllm/v1/attention/backends/flash_attn.py:670-671,1307-1319 vs flashinfer.py:1445-1452; Blackwell priority vllm/platforms/cuda.py:145-151; tests/v1/e2e/general/test_cascade_attention.py:20common-prefix input only (not consumed): src/vllm/v1/core/sched/scheduler.cpp:330,381; include/vllm/v1/core/sched/output.h:151per-manager zero policies tests/vllm/v1/test_single_type_kv_cache_manager.cpp:263prefix-prompt-caching-parity.mdSPIKECLAIM-PREFIX-PROMPT-CACHING
ENG-DBO-UBATCHDBO and ubatch overlapT2vllm/config/parallel.py:208,524--planned: specs/dbo-ubatch.mdINVENTORIED-
ENG-MOE-SHARED-AUXMoE shared-expert MLP on an aux CUDA stream concurrent with the routed-expert router/align/grouped-GEMMs (mirror vLLM's decode overlap; the largest remaining 35B c1/c2 engine lever). Fork the shared MLP onto a 2nd persistent per-device stream, join before the combine → byte-identical to serial (independent shared/routed paths both complete before combine; overlap changes WHEN not WHAT). Gated T <= threshold decode + CUDA. The aux stream draws scratch from a SEPARATE AuxPool so the concurrent main-stream routed allocations never share a live block with it (the DevicePool reuse invariant is single-stream ordering; vLLM sidesteps this with its stream-aware caching allocator's record_stream). VT_MOE_SHARED_AUX_STREAM DEFAULT ON (=0 rollback); VT_MOE_SHARED_AUX_THRESHOLD (default 128; GB10 48-SM calibration). Captured in the decode CUDA-graph via the fork/join event edges (ThreadLocal capture, no abort). Only the committed Marlin MoE decode path; wmma fallback/CPU/GGUF and 27B dense unaffectedT1vllm/model_executor/layers/fused_moe/runner/shared_experts.py:99-104,125-142; vllm/utils/multi_stream_utils.py:20-58 (maybe_execute_in_parallel, TRT-LLM port); vllm/utils/torch_utils.py:736-756 (aux_stream); vllm/envs.py:260 (threshold 256)fork/join src/vllm/model_executor/models/qwen3_5.cpp:3999,4114 (MoeBlockFusedMarlinCuda); aux stream+events src/vllm/model_executor/models/qwen3_5.cpp:3575,3581 (MoeAuxStream/MoeAuxStreamFor); predicates :3553,3560; aux-pool isolation :496,3538 (AuxPool/ActivePool/ActivePoolScope) + DBuf pool_ routing :645DGX (prod flags, one flock): overlap ON==OFF BYTE-IDENTICAL — tests/parity/test_qwen36_paged_engine.cpp:116 35B 315/315 + tests/parity/test_qwen27_paged_engine.cpp 27B 235/235 under VT_MOE_SHARED_AUX_STREAM∈{0,1}; captured-vs-eager (VLLM_CPP_CUDAGRAPH=0, ON) 315/315; shipping default (no env) 315/315+235/235, rollback =0 315/315+235/235; compute-sanitizer memcheck (default ON, captured) 0 errors; in-situ interleaved TPOT A/B (drop cold rep1) c1 −5.6% / c2 −2.7% / c4 −3.7% / c8 −3.4% / c16 −1.6% / c32 −1.5% (WINS every conc, zero regression); ledger parity-ledger.md 2026-07-19 rowmoe-shared-aux-stream.mdANCHOR-BACKFILLCLAIM-MOE-SHARED-AUX-1
ENG-RUNNER-MODELSHAPERunner is model-shape-agnostic over the KV-cache group structure — the extensibility deliverable the first additive-model bring-up (Qwen3 dense) forced. Before W1 the GPUModelRunner had only ever executed the Qwen3.6 HYBRID topology and hardcoded it in two places: (#1) the KV-buffer alloc loop indexed config_.layer_types[l], out-of-bounds on a pure-dense model's EMPTY layer_types; (#2) each execute_model step unconditionally built the GDN metadata (gather_block_table(gdn_group_id_) / remap_gdn_state_slots / GDNAttentionMetadataBuilder), which reads block_table[-1] when there is no mamba group. W1 drives both off the resolved KV-group structure — a model-agnostic has_mamba_group / gdn_group_id_ >= 0 predicate (NOT a model-name check): empty/absent layer_types ⇒ all full-attention; no mamba group ⇒ the whole GDN metadata/state path is skipped and gdn_meta stays default-empty. A full-attention-only KV config (one FA group, no MambaSpec) now allocates + steps cleanly; the hybrid gate models keep their GDN group so their path is BYTE-IDENTICAL. This is a one-time generalization: every future dense/non-hybrid arch (Llama, Mistral) now adds new-files-only, zero further runner edits. PER-LAYER KV head_dim extension (Gemma-4 G1b, 2026-07-28, CLAIM-GEMMA4-G1B): the runner's full-attn alloc/view loops now consume an OPTIONAL KVCacheConfig::per_layer_attn_specs (index == layer) so a HETEROGENEOUS-head_dim model (Gemma-4: sliding 256 / global 512, same num_kv_heads) sizes each non-GDN layer's paged KV + PagedKvCache view from its OWN spec. The field is EMPTY for every uniform-KV model ⇒ the loop collapses to the single group spec ⇒ byte-identical allocation/view/indexing/dispatch (same additive-identical property as the model-shape generalization above). Block table / KV manager / scheduler stay head_dim-independent (num_blocks + block_size, uniform) so no per-group block table is introducedT0model-agnostic runner drives off kv_cache_config.kv_cache_groupsvllm/v1/worker/gpu/model_runner.py initialize_kv_cache / attention-metadata build (per-group, no hardcoded hybrid) @ e24d1b24src/vllm/v1/worker/gpu/runner.cpp:458-470 (alloc loop: has_mamba_group && !layer_types.empty() gate) + :651-680 (GDN metadata build gated on gdn_group_id_ >= 0, default-empty gdn_meta otherwise); per-layer KV head_dim: include/vllm/v1/kv_cache_interface.h (KVCacheConfig::per_layer_attn_specs) consumed in src/vllm/v1/worker/gpu/runner.cpp initialize_kv_cache (per-layer FaDims alloc+view), published by src/vllm/model_executor/models/gemma4_registry.cpp (MakeGemma4ForConditionalGenerationKVCache); the full-attention-only KV spec that exercises the base path src/vllm/model_executor/models/qwen3_dense.cpp (MakeQwen3ForCausalLMKVCache)tests/vllm/v1/worker/test_runner.cpp:1129 — "full-attention-only KV config allocates without the GDN path" + "full-attention-only step skips GDN metadata build (no OOB)" (RED→GREEN: both SIGSEGV pre-generalization; GREEN post). Behaviour-preservation gate: DGX 27B 235/235 + 35B 315/315 UNCHANGED under the fix; per-layer-KV inertness: full CPU runner/KV suite green + OLMo-2 SACRED GPU re-gate 16/16 UNCHANGED; heterogeneous path proven by Gemma-4 E4B STRICT 32/32 (tests/parity/test_gemma4_paged_engine.cpp); ASan/UBSan clean on the affected pathsfirst-additive-model-qwen3-dense.md §3 (seam gaps #1/#2), §6 (W1); gemma4-multimodal.md §G1bACTIVECLAIM-MODEL-QWEN3-DENSE
ENG-MM-INPUT-PIPELINEMultimodal INPUT pipeline + encoder-cache engine seam (M1), INERT when no mm input. The C++ mirror of vllm/multimodal/: MultiModalKwargs/MultiModalFeatureSpec/MultiModalInputs, the MultiModalHasher mm-hash (blake3), the Qwen3-VL image processor (smart_resize + fused rescale/normalize + patchify -> pixel_values+image_grid_thw) and placeholder-token expansion, plus the EncoderCacheManager (+ComputeMmEncoderBudget) and the LMCache extra_keys seam. Additive mm_features carried on Request/EngineCoreRequest; with NO mm input every field is empty and every path is byte-identical to the text engine. Processor output is BIT/BYTE-identical to the vLLM 0.25.0 oracle (M0 fixture). Does NOT build the vision tower / embed-merge (M2). SERVING wiring (ROAD-V1-MM MM-SERVE-ENGINE, 2026-07-28, CLAIM-MM-SERVING-W2): the OpenAI server now carries the parsed MultiModalInputs into the engine — additive LLMEngine/AsyncLLM add_request(MultiModalInputs)+generate(MultiModalInputs) overloads via InputProcessor::process_inputs_mm (mirror input_processor.py:333-379, empty mm_features == the tokens path), the chat-template placeholder-STRING helpers (get_placeholder_str/_add_placeholder mirror), and the serving_chat MultiModalChatFn seam (default unset ⇒ text byte-identical). SEAM BODY (ROAD-V1-MM MM-SERVE-E2E W3, 2026-07-28, CLAIM-MM-SERVING-E2E): MakeQwen3VLImageChatFn (chat_mm.cpp) is the seam body the server sets — messages → marker-inject → chat template → EncodeWithSpecialTokens (the single image_pad marker → one image_token_id) → RouteImageRgb EXPAND to 196 image tokens + mm_features; wired in examples/server/main.cpp (guarded on preprocessor_config.json; text-only unset ⇒ byte-identical). Gated test_chat_mm 8/8 + test_openai_serving (seam invoked + routed). ENGINE MM-FORWARD LANDED (ROAD-V1-MM MM-SERVE-E2E, 2026-07-28, CLAIM-ENGINE-MM-FORWARD): the engine model runner now HAS an mm forward — ModelForwardInput gains an ADDITIVE default-nullopt std::optional<MultiModalForwardInput> mm (merged inputs_embeds + 3-D MRoPE positions + DeepStack, borrowed handles; nullopt-for-text ⇒ shared runner path byte-identical BY CONSTRUCTION), Qwen3VLForConditionalGeneration is REGISTER_VLLM_MODEL-registered (qwen3_vl_registry.cpp), and the registered forward FOLDS the M2c decode into ModelRegistry::Forward via the SHARED Qwen3VLForwardStepLastLogits (Qwen3VLGenerateGreedyViaRegistry drives every step through the registry). GPU token-exact gate test_qwen3vl_registry_e2e (image→text THROUGH ModelRegistry::Forward == M2c golden 32/32 STRICT, dgx.casa GB10); text inertness test_runner 16/16 + test_scheduler 36/36 + test_model_registry 24/24 + test_chat_mm 8/8 + test_openai_serving 41/41 all green. RESIDUAL: the FULL in-runner scheduler-fed tower run (batched-loop mm building the field from staged encoder outputs) + the real server /v1/chat/completions GPU e2e — recipe in specs/mm-serving.md. INPUT LIMITS L1 LANDED (#607, 2026-08-13): the per-modality limit_per_prompt + GetLimitPerPrompt precedence (language_model_only ⇒ 0 BEFORE the map, else the map, else 999) and the refusal that gives those numbers effect — AllowedMmLimits folding by min() against the model's own ceiling, ValidateNumItems with upstream's exact message, and both call sites with the enable_mm_embeds escape. NO serve surface and NO live call site: nothing constructs a MultiModalConfig on a request yet, which is L2's. INPUT LIMITS L2 LANDED (#607, #686, 2026-08-14): the flags (--[no-]language-model-only, --limit-mm-per-prompt '<json>'; arg_utils.py:555-556,1276-1279,1691-1692 over ParseLimitMmPerPromptJson, the port of multimodal.py:212-236 + the DummyOptions dataclasses :17-43), the C-ABI fields (vllm_model_params.language_model_only/.limit_mm_per_prompt, ABI v19), and the LIVE CALL SITE: ValidateChatMmLimits (chat_utils.py:648-662) runs as step 0 of MakeQwen3VLImageChatFn over a BaseProcessingInfo folding LoadedEngine::mm_config() with Qwen3VLChatSupportedMmLimits() == {"image": 1} — the seam's own ceiling, which is the min() fold operand #686 recorded as undeclared. A three-image request is now HTTP 400 with upstream's message rather than an opaque 500 / a truncated answer. NOT claimed: any memory win (L3 gates tower construction, unmeasured). Still unwired: the process_inputs_mm call site (context.py:461), blocked on the per-model get_supported_mm_limits() hook. KERNEL GATE L4 RESOLVED 2026-08-19 as a TRACKED EXCEPTION (#607, #414): we do NOT mirror the text_only conjunct of qwen3_next.py:324-331, because mirroring is not representable at our seams. Upstream conjoins it because its fused Triton kernel indexes cos_sin_cache by 1-D positions and cannot express MRoPE (qwen3_next.py:323, # TODO: support MRoPE), falling back to an eager arm whose self.rotary_emb IS the MRoPE module. Ours are not those two arms: vt::AttnQkNormRopeGate takes NO positions, only a precomputed per-token cos_sin cache that qwen3_5.cpp::BuildMropeCosSinHost fills with the interleaved 3-section MRoPE selection, so our FUSED arm is the MRoPE arm while our eager arm (vt::RopeNeox on 1-D positions) has no MRoPE spelling. Conjoining text_only would select 1-D RoPE on exactly the configuration the conjunct protects and would break the landed M3-b image and M3d video STRICT 32/32 gates. Argued in specs/multimodal-track.md §1.6. What the exception does NOT excuse is the DENOMINATOR: #414's defect is a benchmark configuration, and scripts/dgx-online-serving.sh still launched the oracle without --language-model-only while tools/bench/run_serve_low.py passed it, so the two harnesses disagreed about the oracle's own configuration and the next canonical campaign would have reproduced the flattered ratios the 2026-08-13 series superseded. Both now pass it and scripts/check-oracle-denominator-flags.py keeps them agreeing. NO product code path changed, so no token gate and no measurement is claimed and no published number is withdrawn. Owed and filed in flow: #1340 (VT_FUSE_ATTN_PREAMBLE=0 on the MRoPE path substitutes 1-D RoPE instead of refusing; needs a GPU VL token gate) and #1345 (the three in-process LLM(...) bench harnesses leave language_model_only at False with no way to set it).T1vllm/multimodal/{inputs.py,hasher.py:50,processing/processor.py:1663,processing/inputs.py:62}; vllm/model_executor/models/qwen3_vl.py:{1400,1233}; vllm/v1/core/encoder_cache_manager.py:17; transformers image_processing_qwen2_vl.py:62, image_processing_backends.py:327; tests tests/multimodal/test_processing.py, tests/multimodal/test_hasher.py, tests/v1/core/test_encoder_cache_manager.py @ e24d1b24src/vllm/multimodal/hasher.cpp, src/vllm/multimodal/qwen3vl_processor.cpp, include/vllm/multimodal/{inputs.h,hasher.h,qwen3vl_processor.h}; src/vllm/v1/core/encoder_cache_manager.cpp + include/vllm/v1/core/encoder_cache_manager.h; additive inert fields include/vllm/v1/request.h + src/vllm/v1/request.cpp + include/vllm/v1/engine/types.h; extra_keys seam include/vllm/v1/kv_offload/lmcache/chunked_token_database.h + .cpp; M0 scripts/mm/m0_oracle_capture.py; L1 limits include/vllm/config/multimodal.h + include/vllm/multimodal/processing/context.h + src/vllm/multimodal/processing/context.cpp, refusal type relocated to include/vllm/v1/engine/validation_error.h; L2 flags+ABI+call site src/vllm/config/multimodal.cpp (ParseLimitMmPerPromptJson) + src/vllm/entrypoints/openai/server_main.cpp + include/vllm.h (ABI v19) + src/capi/vllm_c.cpp + EngineParams::multimodal/LoadedEngine::mm_config() + src/vllm/entrypoints/openai/chat_mm.cpp (ChatPartModality, ValidateChatMmLimits, Qwen3VLChatSupportedMmLimits) — anchors src/vllm/multimodal/hasher.cpp:56, src/vllm/config/multimodal.cpp:49, src/vllm/entrypoints/openai/chat_mm.cpp:295,311, include/vllm.h:197,403; L4 denominator gate scripts/check-oracle-denominator-flags.py + the --language-model-only oracle arm of scripts/dgx-online-serving.shtests/vllm/multimodal/test_qwen3vl_processor.cpp (processor-parity 23/23 BIT-identical vs the M0 oracle fixture tests/vllm/multimodal/fixtures/qwen3vl/, RED-first: wrong normalize shift -> 1.2M mismatches); tests/vllm/v1/core/test_encoder_cache_manager.cpp 32/32. Text-inertness: test_request/test_engine_types/test_lmcache_codec/test_lmcache_key_agreement/test_openai_conformance all green standalone; SACRED CUDA 27B/35B/Coder = GPU inertness proof; check-device-leakage OK — anchor tests/vllm/multimodal/test_qwen3vl_processor.cpp:59. L1 limits: tests/vllm/config/test_multimodal_config.cpp 7/7 (21 assertions) + tests/vllm/multimodal/test_processing_limits.cpp 19/19 (78 assertions), porting tests/multimodal/test_processing.py:902-941,944-985, tests/entrypoints/multimodal/llm/test_mm_embeds_only.py:41-49 and tests/entrypoints/unit_tests/test_chat_utils.py:1498-1560 @ 5559679229bc; mutations proven RED: map-before-flag precedence, the dropped throw, the dropped min() fold. L2 (aarch64 build-test-cpu-arm64 lane, -DVLLM_CPP_CUDA=OFF): tests/vllm/entrypoints/openai/test_serve_mm_limits.cpp 11/11 (109 assertions, flags + the parser's upstream refusals + the builtin-only reach of extra="forbid") + test_chat_mm 11/11 (126) + test_openai_api_server 56/56 (CASES; its assertion count is timing-dependent — 632/648/651 across three runs of one binary, so only the case count is quotable — the HTTP 400 arm proven against BOTH a 500 and a truncated 200); RED-first behavioural: CHECK(500 == 400), CHECK("InternalServerError" == BadRequestError) and CHECK(200 == 400); mutations proven RED: flag→config plumbing dropped, the call-site wiring dropped, and the refusal re-typed off InputValidationError (which lands as the 500 L1's design avoided). L4: tests/scripts/test_check_oracle_denominator_flags.py 11/11, RED-first behavioural (the checker on the pre-L4 tree exits 1 naming dgx-online-serving.sh:487 and :498 of 3 discovered launches) and mutation-proven (removing the flag from the canonical driver in a scratch copy returns exit 1 with exactly one violation, the exempt q3mxfp4 arm staying exempt)multimodal-track.md §3 (M0/M1)READY-
ENG-MM-VISION-TOWERQwen3-VL vision tower Qwen3_VisionTransformer (M2a), proven faithful vs vLLM 0.25.0 in isolation. The reusable vision half of the whole Qwen3-VL family + Qwen3.6 (27B/35B share this exact tower). Pure-additive C++ forward composed from public vt:: ops: patch-embed (Conv3d-as-matmul + bias), host pos-embed bilinear-interp+spatial-merge-reorder, 24 ViT blocks (LayerNorm + vision attention with partial-rotary NeoX vision RoPE via vt::RopeFromCache + non-causal vt::Attention(causal=false) + tanh-GELU MLP), patch merger (LayerNorm + exact-erf-GELU + 2 FCs), DeepStack 3 post-shuffle-norm mergers at layers 5/11/17 → [196,10240]. Adds 2 additive elementwise vt ops (GeluTanh/GeluErf). NO runner/model/registry edit → text engines byte-identical by construction. Proven faithful in ISOLATION; the merge into input_embeds + the MRoPE/DeepStack text backbone + the e2e image gate are M2b/M2c.T1vllm/model_executor/models/qwen3_vl.py Qwen3_VisionPatchEmbed:347, Qwen3_VisionBlock:413, Qwen3_VisionPatchMerger:467, Qwen3_VisionTransformer:519, forward:800, pos_embed_interpolate_native:277, rot_pos_emb:667; qwen2_5_vl.py::Qwen2_5_VisionAttention.forward:397; rotary_embedding/common.py::ApplyRotaryEmb.forward_static:151 @ e24d1b24src/vllm/model_executor/models/qwen3_vl_vision.{h,cpp}; 2 vt ops include/vt/ops.h + src/vt/ops.cpp + src/vt/cuda/cuda_layernorm.cu + src/vt/cpu/cpu_layernorm.cpp; dumps scripts/mm/m2a_tower_{ref,weight}_dump.py; fixtures tests/vllm/multimodal/fixtures/qwen3vl_tower/tests/vllm/multimodal/test_qwen3vl_tower.cpp — 4 RED-first tower gates vs the dumped vLLM-0.25.0 reference 348/348 (patch-embed 2.1e-3, block0 6.8e-3, merger 6.5e-2, DeepStack 1.2e-2/3.3e-2/4.4e-2, full tower 5.1e-2; pos-embed 2.5e-3 + rope 1.9e-3 TIGHT); bf16-depth envelope RCA'd; RED = rope disabled → block0 0.149/tower 0.75/6 fails; cutlass-ON+FA2 banner; clean -Werror; compute-sanitizer 0 — anchor tests/vllm/multimodal/test_qwen3vl_tower.cpp:96multimodal-track.md §3 (M2a)ACTIVECLAIM-MULTIMODAL-M2A
ENG-MM-TEXT-BACKBONEQwen3-VL text-backbone numeric contracts Qwen3VLGetRopeIndex/Qwen3VLMergeMultimodal/Qwen3VLComputeDeepstack (M2b/M2c), unit-green vs vLLM 0.25.0. The deterministic pieces that fork the plain Qwen3-dense text path for a vision-conditioned decode: (1) MRoPE 3-D get_rope_index positions [3,T] (image tokens get (t,h,w) grid positions, text sequential); (2) the 3-section MRoPE APPLICATION — proven to be the EXISTING vt::RopeFromCache mrope path (positions [3,T] + mrope_section=[24,20,20] interleaved), faithful to MRotaryEmbedding.forward_native for Qwen3-VL's exact config; (3) _compute_deepstack_embeds scatter → [L,T,H] decoder-injection tensor; (4) _merge_multimodal_embeddings masked scatter of the tower's [:,:2560] into input_embeds. Pure-additive TU — NO shared dense forward / runner / registry edit → text engines byte-identical by construction. The e2e image forward (VL weight loader + forked MRoPE/DeepStack decode loop) is the remaining M2c wire-up.T1vllm/model_executor/models/qwen3_vl.py _get_mrope_input_positions:2567, _iter_mm_grid_hw:2482, _compute_deepstack_embeds:2761, Qwen3LLMModel.forward deepstack :1589; vllm/model_executor/models/utils.py::_merge_multimodal_embeddings:524; vllm/model_executor/layers/rotary_embedding/mrope.py MRotaryEmbedding @ e24d1b24src/vllm/model_executor/models/qwen3_vl_text.{h,cpp}; existing vt::RopeFromCache mrope path (src/vt/{cpu,cuda}/*); dump scripts/mm/m2b_text_ref_dump.py; fixtures tests/vllm/multimodal/fixtures/qwen3vl_text/ — anchor src/vllm/model_executor/models/qwen3_vl_text.cpp:9tests/vllm/multimodal/test_qwen3vl_text.cpp — 4 RED-first gates vs the dumped vLLM-0.25.0 reference 85/85 (get_rope_index BIT-exact [3,204], delta −182; MRoPE q rel-L2 1.5e-3 / k 1.5e-3, RED interleaved-off >5e-2; DeepStack + merge BIT-exact); CPU-only, no weights; clean CPU -Werror — anchor tests/vllm/multimodal/test_qwen3vl_text.cpp:99multimodal-track.md §3 (M2b/M2c)ACTIVECLAIM-MULTIMODAL-M2BC
ENG-MM-QWEN36-VL-FORWARDQwen3.6-27B (Qwen3_5ForConditionalGeneration) GDN-hybrid VL forward — IMAGE (M3-b) + VIDEO (M3d) BOTH e2e, STRICT gates PASS 32/32. Our own gate model's image+video paths now work end-to-end (speed pending). The genuinely-new integration completing our own gate model's mm paths: fork the landed bf16 Qwen3_5DenseModel GDN-hybrid forward (48 GDN + 16 full-attn) on gated, default-off points so a text-only 27B request stays byte-identical — (a) inputs_embeds entry (embed ids + Qwen3VLMergeMultimodal scatter of the 27B tower merger [N,5120] into the visual-token rows; 27B has EMPTY deepstack_visual_indexes ⇒ NO DeepStack); (b) 3-section MRoPE (mrope_section=[11,11,10] interleaved, rotary_dim 64, theta 1e7) in the 16 full-attn layers only via the proven vt::RopeFromCache mrope path (GDN layers carry no rope); (c) mixed load = the M2a Qwen3_VisionTransformer (27B vision config, empty deepstack) bf16 tower + the bf16 GDN-hybrid LLM via the EXISTING LoadQwen3_5Dense. M3d (2026-07-25) added VIDEO by REUSE: the M3-b image driver refactored into a shared VLGenerateCoreGdn, image+video wrappers differ ONLY in the merge mask (image_token vs video_token across frames) + the get_rope_index (Qwen3VLGetRopeIndex vs Qwen3VLGetRopeIndexVideo); the M3c processor/windowed-tower/video-MRoPE are reused verbatim.T1vllm/model_executor/models/qwen3_5.py:389 (Qwen3_5ForConditionalGeneration subclasses Qwen3VLForConditionalGeneration; visual = Qwen3_VisionTransformer, modalities {"image","video"}); qwen3_vl.py _process_video_input:2165, _get_mrope_input_positions:2567 video branch, get_video_repl:1479; the 27B config.json (mrope_section=[11,11,10], empty deepstack_visual_indexes) @ e24d1b24 / vLLM 0.25.0M3-b + M3d BUILT + GATED 2026-07-25: vision-only loader LoadQwen3VLVisionWeights (src/vllm/model_executor/models/qwen3_vl.cpp, 27B config) + shared VLGenerateCoreGdn + image driver Qwen3_5VLGenerateGreedy + video driver Qwen3_5VLGenerateGreedyVideo + BuildMropeCosSinHost + the mrope_cos_sin param on DenseForwardLayers (src/vllm/model_executor/models/qwen3_5.cpp, nullptr on every text caller ⇒ byte-identical; the video driver is purely additive, the shared text forward UNTOUCHED per git diff --stat) reusing M2a tower + LoadQwen3_5Dense bf16 LLMIMAGE: golden tests/vllm/multimodal/fixtures/qwen3_5_27b/ (STRICT sha256 ead4b484…); STRICT image gate PASS 32/32 (test_qwen3_5_vl_e2e.cpp, 54/54, re-run post-refactor). VIDEO (M3d): oracle scripts/mm/m3d_video_oracle_capture.py on the M3c synthetic clip (raw sha 8a111599…, grid [4,8,8], 64 video tokens) K=5 DETERMINISTIC ⇒ STRICT golden; STRICT video gate PASS 32/32 (test_qwen3_5_vl_video_e2e.cpp, 27/27; near-tie gaps 0.0000 nats everywhere), fixtures tests/vllm/multimodal/fixtures/qwen3_5_27b_video/. Text-inertness 27B 235/235, 35B 315/315, Coder 138/138 (by construction); clean -Werror 0 warn; compute-sanitizer 0 on the 27B video forward. SPEED MEASURED (2026-07-26, CLAIM-MULTIMODAL-SPEED): image c1 vs vLLM 0.25.0 GRAPHED — decode TPOT 225.0 ms/tok vs 226.9 = AT PARITY (0.99×), LLM prefill 326 ms vs vLLM TTFT 321 ms = at parity; vision tower WAS 2114 ms vs vLLM encode ≤~250 ms = ~10× (THE gap). TOWER LEVER EXECUTED (2026-07-26, CLAIM-MULTIMODAL-SPEED-TOWER, multimodal-speed.md §7): nsys cuda_gpu_kern_sum attributed 98.9 % of the tower forward to the naive vt::cuda::AttentionKernel (56 ms/block; NOT QKV/FA2-routing); fixed by a warp-scoped online-softmax op AttentionDenseFast (separate op ⇒ kAttention/text byte-identical) + one-time resident-weight load ⇒ per-image tower 2114 → 148 ms (14.3×), 0.59× vs vLLM eager encode = FASTER. STRICT image/video e2e HELD 32/32 (+4B DeepStack 32/32), test_ops_attention 37239/37239, 27B text SACRED 235/235, compute-sanitizer memcheck 0, clean -Werror. benchmark_binding=false, single-seq driver (no c2+/server). Remaining: batched/graphed mm serving (c2+) + audio our-side — DONE bar not yet met.multimodal-track.md §M3 + multimodal-speed.md §7 + §8 (decode lever #2 CLOSED 2026-07-27: on-GPU greedy argmax + decode embed round-trip removed on VLGenerateCoreGdn; bit-exact — image/video STRICT 32/32 held; 27B decode NEUTRAL at the ~222 ms bandwidth floor) + §9 (lever #3 FIRST BRICK 2026-07-27, CLAIM-MULTIMODAL-SPEED-GRAPH: the shared VLGenerateCoreGdn decode step now routes through the production Qwen3_5DenseDecodeGraph cold→warm→replay captured decode — the mm decode is now GRAPH-CAPTURABLE, closing the un-graphed-eager-loop structural gap; S==B==1 bit-identical rebuild; token-exact HELD image/video STRICT 32/32 with 30 graph replays confirmed; A/B graphed 232.5 vs eager 233.4 ms/tok = NEUTRAL at the 27B bandwidth floor; the launch-overhead win + batched c2+ + serving ingestion are the recorded W-plan W1-W3) + §16 (vision-forward flash kernel 2026-07-28, CLAIM-MM-SPEED-QWEN-IMAGE: ATTRIBUTION-FIRST nsys attributed ~85% of the 148 ms tower forward to the dense attention AttentionWarpKernel [4.66 ms/block×27]; routed it to the §14 flash-tiled vt::AttentionDenseFlash [head_dim 72, byte-identical — per-warp math verbatim, only K/V from shared-mem tiles]. STRICT image/video e2e HELD 32/32 [27B+4B], test_ops_attention 37239/37239, goldens md5 UNCHANGED, nsys proof AttentionDenseFlashKernel 24 inst/zero warp, RED 30/46→46/46, sanitizer 0. A/B warp 148.3→flash 142.3 ms = 1.04× — the profile REFUTED a big lever: at t=784 the vision attention is serial-latency-bound not bandwidth-bound [audio §14 was 1.82× at t=1500], flash recovers only ~6 ms. HONEST: the tower ALREADY BEATS vLLM — 142 ms vs ~250 ms eager encode = 0.57×; image/video mm-forward is correctness-DONE + speed-BEATS-vLLM; residual = tensor-core MMA hd-72 attention [not needed for parity] + batched c2+/serving)ACTIVECLAIM-MULTIMODAL-SPEED-TOWER + CLAIM-MULTIMODAL-SPEED-DECODE + CLAIM-MULTIMODAL-SPEED-GRAPH + CLAIM-MM-SPEED-QWEN-IMAGE
ENG-MM-VIDEO-FORWARDQwen3-VL VIDEO understanding (M3c) — preprocessing + full wiring LANDED + unit-gated; e2e token-exact PENDING on tower fidelity. Extends the landed image path to video: the genuinely-new piece is video PREPROCESSING (frame sampling + temporal grid + timestamp-interleaved placeholder); the tower handles temporal patches and MRoPE the temporal axis. NEW (additive to qwen3_vl*/multimodal TUs, ZERO text-path TU ⇒ text SACRED byte-identical): (a) ProcessVideo+VideoSmartResize+ComputeVideoTimestamps+BuildVideoRepl+VideoKwargs — video patchify fuses temporal_patch_size REAL frames/row (source frame = grid_t_idx*tp + t, NOT the image duplicate); BuildVideoRepl = per-frame [ts_ids]+vision_start+video_token*Nf+vision_end interleave; (b) tower per-frame windowed attention (cu_seqlens per frame; grid_t==1 image == byte-identical); (c) Qwen3VLGetRopeIndexVideo (per-frame scan); (d) Qwen3VLGenerateGreedyVideo via a shared VLGenerateCore (image driver unchanged).T1qwen3_vl.py: _process_video_input:2165 (same self.visual), _iter_mm_grid_hw:2482/_get_mrope_input_positions:2567 video branch, get_video_repl:1479, cu_seqlens per-frame :744; transformers video_processing_qwen3_vl.py:35,249 @ vLLM 0.25.0M3c BUILT + UNIT-GATED 2026-07-25: src/vllm/multimodal/qwen3vl_processor.cpp (+inputs.h), qwen3_vl_vision.cpp (windowed attn), qwen3_vl_text.{h,cpp} (Qwen3VLGetRopeIndexVideo), qwen3_vl.{h,cpp} (Qwen3VLGenerateGreedyVideo+VLGenerateCore)Video-processor UNIT gate test_qwen3vl_video_processor 41/41, pixel_values_videos BIT-exact 0/393216 (RED-first: image-duplicate mapping → 195838 mismatch); video MRoPE BIT-exact vs vLLM (m3c_mrope_check.py, delta −48); video tower rel-L2 0.072 (within bf16 envelope, m3c_video_tower_ref_dump.py); video e2e test_qwen3vl_video_e2e NEAR-TIE-ROBUST PASS (gate form selected BY MEASUREMENT 2026-07-25, CLAIM-MULTIMODAL-TOWER-FIDELITY): teacher-forcing vLLM 0.25.0 on OUR exact sequence proves the sole divergence is ONE genuine bf16 near-tie at tok22 (' colorful' 33866 vs vLLM ' static' 1099, gap 0.125 nats, our token vLLM's 2nd of 4 tokens tied within 0.25 nats) and EVERY downstream token (tok23-31) IS vLLM's teacher-forced argmax at gap 0.0000 — 22/32 vs greedy is the one-token shift from that single tie. Tower accumulation ALREADY f32 everywhere (cuBLASLt CUBLAS_COMPUTE_32F GEMMs + f32 online-softmax attn + f32 LayerNorm) = matches vLLM's cuBLAS/FlashAttention; the residual rel-L2 is the irreducible inter-op bf16 rounding envelope, NOT a fixable numeric choice — so NO kernel change (methodology fix, mirrors the olmo2/qwen3-dense/glm4 near-tie gates). Gate: our_ids_i32.bin anchor + neartie_gap_mnats_i32.bin (from scripts/mm/m3c_video_neartie_gap.py), max gap 0.125 << 0.5-nat band. NO REGRESSION image e2e 4B STRICT 32/32 (the deterministic strict-pass proof); fixtures tests/vllm/multimodal/fixtures/qwen3vl_video/ + scripts/mm/m3c_*.pymultimodal-track.md §M3 (M3c)READY-
ENG-MM-AUDIO-PIPELINEAUDIO INPUT pipeline (audio-track A0+A1), the genuinely-new AUDIO modality on the modality-agnostic mm spine; INERT when no audio input. Stands audio up on the smallest oracle-runnable vehicle openai/whisper-small (native WhisperEncoder; transformers 5.13.1 constructs it — unlike Gemma-4 which is oracle-blocked). The C++ Whisper-class audio processor WhisperAudioProcessor: canonical PCM16-mono WAV decode (int16/32768.0), identity resample at 16 kHz (genuine windowed-sinc DEFERRED, mirrors the image SmartResize/bicubic deferral), log-mel input_features [80,3000] (pad/truncate 480000 → torch.stft-equiv: reflect-pad n_fft/2, periodic Hann, hop 160, drop last frame, direct DFT over 201 bins → abs(stft)^2mel_filters.T@maglog10(clamp 1e-10)max(x,x.max()-8)(x+4)/4), audio placeholder expansion ([0][0]*1500, num_audio_tokens = max_source_positions = encoder output length), and MultiModalHasher::HashAudioF32 (float32 1-D ndarray "<f4"/(N,) byte stream, the audio analogue of the image u1/(H,W,3)). REUSE the M1 MultiModalKwargs/MultiModalFeatureSpec(modality)/EncoderCacheManager/LMCache extra_keys seam; adds a default-null AudioKwargs audio_data on MultiModalFeatureSpec. NO audio input ⇒ every field empty, text/image/video byte-identical. Does NOT build the audio ENCODER tower (A2) or the e2e audio→text (A3). CPU-only (no CUDA kernel).T1transformers feature_extraction_whisper.py (_torch_extract_fbank_features — the torch STFT path that runs when torch is installed; __init__ mel params), audio_utils.mel_filter_bank (slaney/slaney, dumped as a golden constant); vllm/model_executor/models/whisper.py:{103,469-476,656,738,740-753} (WhisperEncoder conv stride, get_num_audio_tokens=max_source_positions, _get_prompt_updates [0][0]*N); vllm/multimodal/hasher.py:{50,108-127} + processing/inputs.py::get_mm_hashes @ e24d1b24 / transformers 5.13.1A0+A1 BUILT 2026-07-25: src/vllm/multimodal/audio_processor.{h,cpp}, include/vllm/multimodal/audio_processor.h; AudioKwargs+audio_data include/vllm/multimodal/inputs.h; MultiModalHasher::HashAudioF32 include/vllm/multimodal/hasher.h + src/vllm/multimodal/hasher.cpp (shared refactor: extracted FinalizeHex, byte-identical); CMakeLists.txt (1 source line); A0 capture scripts/mm/a0_audio_ref.py; fixtures tests/vllm/multimodal/fixtures/whisper_audio/ — anchor include/vllm/multimodal/audio_processor.h:69A1 audio-processor parity gate PASS 77/77 (tests/vllm/multimodal/test_audio_processor.cpp vs the A0 vLLM-0.25.0/transformers-5.13.1 oracle fixture): log-mel input_features rel-L2 1.96e-7 (stated 2e-4 band; torch.stft-FFT vs our DFT summation order, transformers' own torch/numpy claim is 1e-5 — we sit 2 orders tighter; ids+mm-hash BIT/BYTE-exact); WAV decode byte-identical 0 mismatches; placeholder [0]*1500 byte-identical; mm-hash 2d0c7e4c… byte-identical; RED-first (perturb largest mel weight → rel-L2 2.6e-3, wrong hop 161 → 0.70, skip (x+4)/4 → 9.27). Inertness (shared hasher.cpp/inputs.h): image processor 23/23 (hasher refactor inert — image mm-hash unchanged), video processor 41/41, request 71/71, encoder-cache 32/32, text backbone 85/85; clean CPU -Werror 0 warn; check-device-leakage unchanged (32==baseline); no CUDA kernel ⇒ compute-sanitizer N/A. benchmark_binding=false, speed pending — anchor tests/vllm/multimodal/test_audio_processor.cpp:84audio-track.md §0 (A0/A1)ACTIVECLAIM-AUDIO-PIPELINE
ENG-MM-AUDIO-ENCODERWhisper-class AUDIO encoder TOWER (audio-track A2), proven faithful vs the transformers-5.13.1 WhisperEncoder in ISOLATION. Consumes the A1 log-mel input_features [80,3000], produces encoder hidden states [1500,768] (the encoder half of audio understanding, toward A3 e2e audio→text on Voxtral-Mini-3B over the LANDED Mistral backbone). Pure-additive C++ forward composed from public vt:: ops: conv frontend as im2col + vt::MatmulBT (Conv1d(80→768,k3,pad1,s1)+GELU-erf → Conv1d(768→768,k3,pad1,s2 halving 3000→1500)+GELU-erf; NO new CUDA kernel — Whisper conv is a full cross-channel conv, not the depthwise vt::CausalConv1d), + fixed sinusoidal embed_positions (dumped golden constant), 12 pre-norm bidirectional encoder blocks (self_attn_layer_norm → q(bias)/k(NO bias)/v(bias) → vt::Attention(causal=false) scale=head_dim⁻⁰·⁵ → out_proj → residual → final_layer_norm → GELU-erf MLP → residual), + final layer_norm. All GEMMs bf16, norm/softmax f32. Delta from the M2a vision tower: NO patch-merger/DeepStack/RoPE (fully bidirectional + fixed additive sinusoid), a conv frontend not a patchify matmul, GELU-erf everywhere (vision used tanh-GELU MLP). NO runner/model/registry/other-model TU edit → every text/image/video/audio-pipeline gate byte-identical by construction. Proven faithful in ISOLATION; the projector + masked-scatter merge into the Mistral decoder + the e2e audio→text gate are A3. The USM-Conformer tower (Gemma-4/Granite family) is a SEPARATE tower delta (A2-follow, Granite-Speech-2b).T1transformers models/whisper/modeling_whisper.py WhisperEncoder.forward:641-721, WhisperEncoderLayer.forward:400-430, WhisperAttention.forward:298-368 (k_proj no-bias, q pre-scaled, scaling=head_dim⁻⁰·⁵), sinusoids:54 @ 5.13.1; cross-checked vllm/model_executor/models/whisper.py WhisperEncoder:458, WhisperEncoderLayer:353, WhisperMLP:322, conv stride :473-476 @ e24d1b24src/vllm/model_executor/models/whisper_audio.{h,cpp} (+ include/vllm/model_executor/models/whisper_audio.h); CMakeLists.txt (1 source line); dumps scripts/mm/a2_audio_encoder_{ref,weight}_dump.py; committed golden fixtures tests/vllm/multimodal/fixtures/whisper_audio/enc_* — anchor src/vllm/model_executor/models/whisper_audio.cpp:174A2 encoder-tower fidelity gate PASS 203/203 (tests/vllm/multimodal/test_whisper_audio.cpp vs the dumped bf16 transformers-5.13.1 WhisperEncoder reference, GPU under flock on a cutlass-ON build, sibling 27B NOT co-resident): post_conv rel-L2 4.7e-3, post_pos 2.8e-3, block0 6.6e-3, encoder-output 3.0e-2 (bf16-depth envelope ~0.28%/layer over 12 layers, matches M2a); bands post_conv/post_pos<8e-3 / block0<1.5e-2 / final<5e-2 (measured×1.6–2.3). RED-first: wrong conv-stride → post_conv 0.34 (FAIL), missing sinusoid → post_pos 0.86 (FAIL), skipped final-LN → 4.22 (FAIL); honest non-discriminators (GELU-tanh≈erf in-envelope; single conv-weight aggregate-insensitive). cutlass-nvfp4/fp8+FA2+Triton-AOT sm_121a banner CONFIRMED; clean CUDA + CPU -Werror 0 warn; im2col+existing GEMM ⇒ no new kernel, no compute-sanitizer needed; additive ⇒ check-device-leakage unchanged. benchmark_binding=false, speed pending — anchor tests/vllm/multimodal/test_whisper_audio.cpp:69audio-track.md §0b (A2)READY-
ENG-MM-AUDIO-E2Ee2e AUDIO→TEXT on Voxtral-Mini-3B (audio-track A3) — the FIRST audio understanding in the tree. The full C++ pipeline: A1 log-mel input_features [128,3000] (Voxtral config: 128 mel/window 400/hop 160) → the A2 WhisperAudioEncoderForward at Voxtral's Whisper-large-v3 encoder config (d_model 1280/32L/20 heads/head_dim 64/ffn 5120/1500 src-pos) → downsample-concat reshape ([1500,1280][375,5120], factor 4) → AudioLanguageAdapter projector (w_in→GELU→w_out, no bias) → masked-scatter merge (Qwen3VLMergeMultimodal, modality-agnostic) into the LANDED Mistral/Llama decoder at the 375 audio-token-24 rows → forked greedy (VoxtralGenerateGreedy, shared dense_attn::AttnBlock, untied lm_head). Weight loader reads Voxtral consolidated.safetensors (mistral naming); the text q/k weights get the Meta-interleaved→HF-NeoX rope PERMUTE vLLM applies on the mistral load path (verified bit-exact permute(wq)==vLLM q_proj), v/o raw. Additive driver+loader gated on audio ⇒ text-only Mistral byte-identical.T-e2evllm/model_executor/models/voxtral.py embed_multimodal:382-412, AudioLanguageAdapter:660-668, load_weights:502-568, VoxtralEncoderModel:671-839 @ e24d1b24; text q/k permute mirrors vLLM's mistral load path (is_neox_style=True, llama.py:233-244)include/vllm/model_executor/models/voxtral.h + src/vllm/model_executor/models/voxtral.cpp; tests/vllm/multimodal/test_voxtral_e2e.cpp; oracle scripts/mm/a3_voxtral_oracle_capture.py + scripts/mm/a3_voxtral_neartie_gate.py; committed fixtures tests/vllm/multimodal/fixtures/voxtral_audio/; CMakeLists.txt (1 source line) + tests/CMakeLists.txt (test)A3 e2e audio→text gate PASS 14/14 (test_voxtral_e2e, GPU under flock, cutlass-ON, VLLM_VOXTRAL_SAFETENSORS→consolidated.safetensors; sibling 27B NOT co-resident). Gate form BY MEASUREMENT: vLLM greedy K=5 DETERMINISTIC ⇒ STRICT is the bar — STRICT prefix 33/48 exact vs vLLM greedy (log-mel rel-L2 7.7e-7; decoder proven token-exact: vLLM ref-audio→48/48). Bit-exact infeasible (encoder uses different bf16 GEMM/attn kernels than vLLM's cuBLASLt+FLASH_ATTN → 8.7% encoder rel-L2 = the A2 bf16-depth envelope over 32 layers), so the binding gate is the ratified near-tie-robust one (exactly as M3c/M3d): teacher-force vLLM on OUR sequence — worst gap 0.0 nats, 0 over-band failures; the SOLE greedy branch (pos 33) is a 4-way EXACT bf16 tie at -2.069 nats and every one of our 48 tokens is vLLM's teacher-forced argmax. RED evidence: the mistral q/k rope-permute bug drove text-only 1/22 & e2e 0/48 → after the fix text-only 22/22 & first token exact. INERT: additive only (git diff --stat = 2 modified lines [CMakeLists +1 src, tests/CMakeLists +test] + new files); Mistral text 541/541, A1 77/77, A2 203/203 re-run byte-identical; check-device-leakage unchanged; NO new CUDA kernel (reuses A2 im2col+GEMM + merge scatter) ⇒ no compute-sanitizer needed. Clean CUDA -Werror 0 warn, cutlass-ON banner CONFIRMED. benchmark_binding=false, speed pending. SPEED (2026-07-26, CLAIM-MULTIMODAL-SPEED, multimodal-speed.md): vLLM 0.25.0 GRAPHED denominator captured — Voxtral-Mini-3B audio c1 TTFT 43 ms, TPOT 41 ms/tok (388-tok prompt, 375 audio). OUR-SIDE UNMEASURED — build-blocked (no A3 binary on a reusable dgx tree; dgx disk 100% full ⇒ ENOSPC-risky). Because the 3B decode is cheap (~41 ms), audio is where the eager single-seq driver's per-token host overhead would NOT be hidden — the top follow-on measurement. UPDATE 2026-07-27 (CLAIM-MULTIMODAL-SPEED-DECODE, multimodal-speed.md §8): audio our-side MEASURED + decode lever #2 CLOSED. On-GPU greedy argmax + decode-embed round-trip removal ⇒ Voxtral decode TPOT 61.85 ms (band 61.73–61.94) vs 62.08 ms host = ~0.25 ms/tok (~0.4%) bit-exact win (14/14 held, near-tie seq 48/48). The §-hypothesis is REFINED: our audio decode is ~62 ms/tok eager (not 41), so the host round-trips are a THIN slice; the real 1.52× gap vs vLLM's 40.8 ms graphed is eager per-step launch overhead (lever #3, graphed decode). UPDATE 2026-07-27 (CLAIM-MM-SPEED-GRAPH-W1, multimodal-speed.md §10): lever #3 W1 — the Voxtral decode graph — LANDED. New VoxtralDecodeGraph (voxtral.{h,cpp}, the Voxtral-text sibling of Qwen3MoeDecodeGraph: pure full-attention over the same dense_attn::AttnBlock+vt::PagedAttention stack, no GDN); VoxtralGenerateGreedy's pure-decode loop now runs VoxtralDecodeGraph::Step (captures the exact ForwardLastLogits op sequence; S==B==1 bit-identical rebuild), eager fallback VT_MM_DECODE_EAGER=1. RED line HELD (proven-to-run, VT_DECODE_GRAPH_STATS: captured S=1 + 46 replays): 14/14 (near-tie seq 48/48, strict prefix 33/48); goldens md5 unchanged. A/B (throwaway VT_MM_DECODE_EAGER toggle, 6 reps/mode, rep0 dropped, steady-state): graphed 60.94 ms/tok (60.79–61.07) vs eager 61.71 (61.57–61.88) = −0.77 ms/tok (~1.25%), NON-OVERLAPPING — a real clean win, but it NARROWS the gap 1.52×→1.49× vs vLLM's 40.8 ms, does NOT close it. Honest refinement: the removable launch overhead was only ~1.25% of TPOT, so the ~20 ms/tok residual is per-step COMPUTE/kernel efficiency (vLLM's torch.compile-fused + graphed decode), NOT launch overhead. Structural value: Voxtral's Mistral/Llama stack now HAS a decode-graph class (last mm text stack without one) — prerequisite for batched c2+ (W2). UPDATE 2026-07-27 (CLAIM-MM-SPEED-DECODE-KERN, multimodal-speed.md §11): the ~20 ms/tok residual ATTRIBUTED to ONE kernel + a VALIDATED bf16-near-tie ceiling. nsys (graph-node trace) of the graphed decode: the gap is the decode ATTENTION — the naive scalar PagedAttentionKernel (1410 inst = 30 layers × 47 steps @ 723 µs/call = 21.7 ms/step, ~120× the KV-memory floor), NOT the GEMMs (cuBLAS gemvx, near-BW-floor) nor the norm/rope/silu glue. Voxtral (head_dim 128, GQA 32q/8kv bf16 causal) matches the fa2_decode_qwen3 path (the 1:1 flash_attn_varlen decode vLLM runs, DEFAULT-ON) EXCEPT the driver's single KV block block_size=444 is not ÷16, so decode fell to the scalar fallback. Rounding block_size to ÷16 routes decode through FA2 (flash_fwd_splitkv 1410 @ 18.5 µs = 0.65 ms/step, 39× faster): same-binary A/B (throwaway) TPOT 59.4→38.2 ms/tok (−21.2, ~36%, NON-OVERLAPPING); 38.2 = 0.94× vLLM's 40.8 ms — BEATS parity. BUT it changes the bf16 attention reduction order → flips the committed near-tie golden's exact-tie branch (repro 48→18) → repro==48 FAILS. The FA2 sequence is FULLY VALID (teacher-force vLLM 0.25.0: 0 divergences, worst gap 0.0000 nats, PASS — a different-but-equal greedy branch, not a bug). So the audio gap is a bf16 near-tie / golden-pinning ceiling: the win is real, validated and vLLM-1:1, but shipping it needs the near-tie golden regenerated (which the teacher-force PASS proves valid). The RED line forbids touching the golden, so the shipped byte-exact path keeps the scalar kernel (14/14, golden md5 unchanged, ~1.46–1.49× vLLM). RECORDS-ONLY (no code change; win is a one-line block_size÷16 + golden-regen away). Row stays ACTIVE/speed-pending. UPDATE 2026-07-27 (CLAIM-MM-SPEED-DECODE-KERN-ADOPT, multimodal-speed.md §12): USER-APPROVED — FA2 decode SHIPS as the Voxtral default; the LAST mm decode-speed gap is CLOSED (audio decode BEATS vLLM 0.97×). One-line block_size÷16 in VoxtralGenerateGreedy routes decode through FA2 varlen LaunchDecodeVarlenFA2Bf16 (dispatch fa2_decode_qwen3 needs block_size%16==0, cuda_paged_attn.cu:2621; seq still one block, slot==abs_idx unchanged). FA2-routing PROVEN (nsys --cuda-graph-trace=node): flash_fwd_splitkv 1410 @ 18.5 µs + combine 1410 @ 3.1 µs, ZERO PagedAttentionKernel in decode. Gate converted to the ratified near-tie DISTRIBUTIONAL form: binding correctness = the teacher-force PASS (result==PASS+n_divergent==0+over_band==0+worst_gap<=0.5), KERNEL-INDEPENDENT (scalar AND FA2 both PASS); strict prefix = token-exact vs vLLM greedy up to the first genuine bf16 exact tie — FA2 takes the OTHER side of the pos-18 2-way EXACT tie (24466 vs golden 1584, IDENTICAL logprob −1.9875, gap 0.000) ⇒ strict prefix 18 (was 33 for the scalar branch; both teacher-force-valid), asserted >=18; the old byte-match repro==48 (scalar branch) is downgraded to a determinism anchor (regenerated to the FA2 seq). voxtral_neartie.json md5 3d199c2d…937b9ad3…; STRICT greedy golden voxtral_golden.json 8ab87b7e… UNCHANGED. Gate PASS 16/16 (strict prefix 18/48; teacher-force result=PASS, divergent=0, worst_gap=0.0, over-band=0; FA2 seq 48/48). Teacher-force (fresh, vLLM 0.25.0 on the FA2 seq): 0 divergent, worst gap 0.0000 nats, PASS. CAPTURE SAFETY (FA2 inside the captured VoxtralDecodeGraph): captured S=1 + 46 replays (all 48 tokens valid); compute-sanitizer memcheck ERROR SUMMARY 0 errors on the graphed-FA2-decode surface (text-only path: prefill + captured FA2 decode, 20 replays, 22/22, exit 0); 3 e2e runs byte-identical ⇒ capture-safe, ships as the DEFAULT graph path (no eager-FA2 fallback). A/B (same-binary, throwaway timer, VT_FA2_DECODE_QWEN3 toggle, 6 reps/mode rep0 dropped, steady-state): scalar 60.50 ms/tok (60.39–60.62) vs FA2 39.50 ms/tok (39.41–39.58) = −21.0 ms/tok (~35%), NON-OVERLAPPING; 39.50 = 0.97× vLLM 0.25.0 graphed 40.8 ms — BEATS parity. Clean CUDA -Werror 0-warn; additive/kernel-config only (kAttention untouched ⇒ text/other-model byte-identical). Audio DECODE now correctness- AND speed-DONE (ratified near-tie + BEATS vLLM); row stays ACTIVE/PARTIAL — the every-axis DONE bar has audio TTFT (32-layer Whisper encoder, UNMEASURED our-side vs vLLM 43 ms) + batched c2+ / audio_url serving ingestion still open (same structural gaps as image/video). UPDATE 2026-07-27 (CLAIM-MM-SPEED-AUDIO-ENC, multimodal-speed.md §13): audio ENCODER TTFT MEASURED our-side + a warp-attention brick LANDED (4.7×), NOT at parity. The Whisper encoder ran the naive vt::Attention (kAttention, O(t²) per-key block-__syncthreads) over the non-causal 1500-frame context — nsys-attributed as the encoder's dominant kernel. Routed the encoder self-attention (head_dim 64, non-causal) to the warp-scoped vt::AttentionDenseFast (the §7 vision-tower fix; kAttention untouched ⇒ text byte-identical). One src file (whisper_audio.cpp), VT_WHISPER_ENC_EAGER=1 fallback. RED line HELD: test_voxtral_e2e 16/16 with the fast kernel default (strict prefix 18/48, teacher-force PASS, seq 48/48); the naive arm ALSO passes 16/16 with the SAME tokens ⇒ warp kernel flips ZERO tokens (bit-exact at token level, like §7's 32/32); goldens md5 UNCHANGED (voxtral_golden.json 8ab87b7e…, voxtral_neartie.json 937b9ad3…). Proof-of-run: nsys shows AttentionWarpKernel 32 inst (= 32 layers), zero naive. A/B (throwaway VT_WHISPER_ENC_TIME, 6 reps rep0 dropped): encoder forward 8870 ms → 1890 ms (4.7×, NON-OVERLAPPING). HONEST verdict — NOT closed: ~1.89 s vs vLLM's 43 ms TTFT (~44×). nsys of the fast arm: AttentionWarpKernel STILL 31.8 ms/layer × 32 = 1.02 s — O(t²) memory-bound on redundant K/V reads (~5.7 GB/layer, no shared-mem tile reuse); the rest is per-call host weight marshalling + conv round-trip. Ranked residual levers (grounded, NOT implemented): (1) flash-TILED non-causal hd-64 encoder attention (vLLM flash_attn_varlen_func; vendored FA2 has non-causal templates but only hd {128,192,256} paged → needs hd-64 + dense layout — LARGE); (2) resident one-time encoder weights + drop conv round-trip (MEDIUM, byte-exact). Row stays ACTIVE/PARTIAL.audio-track.md §1 (A3) + multimodal-speed.md §8/§10/§11/§12/§13ACTIVECLAIM-AUDIO-E2E + CLAIM-MULTIMODAL-SPEED-DECODE + CLAIM-MM-SPEED-GRAPH-W1 + CLAIM-MM-SPEED-DECODE-KERN + CLAIM-MM-SPEED-DECODE-KERN-ADOPT + CLAIM-MM-SPEED-AUDIO-ENC
ENG-SGLANG-BEHAVIOR-FLAGSGLang-alike runtime behavior scope + the enable/disable control (the "etc." beyond RadixAttention). Per-technique fuse-or-flag: (1) cache-aware LPM scheduling — SGLang reorders the waiting queue by longest matched prefix (schedule_policy.py LPM/DFS + in-batch prefix caching); our scheduler is FCFS/priority only, NO cache-hit ordering ⇒ genuinely DISTINCT ⇒ FLAG --schedule-policy=lpm (SGLang's own default is fcfs, so the default is already covered; lpm is opt-in). (2) overlap/zero-overhead scheduler — SGLang event_loop_overlap == our ENG-ASYNC-SCHED (DONE, default-ON) ⇒ already FUSED, no flag. (3) jump-forward decoding — grammar FSM-forced token elision, our structured-output path masks per-step with no elision ⇒ DISTINCT but opt-in ⇒ FLAG (deferred) --enable-jump-forward. Survey (chunked-prefill/continuous-batching/DFlash/ngram/priority/HiCache/Mamba-radix) = already-covered. Optional --sglang-compat umbrella composes the switches. SGLang pin v0.5.15 f63458b.T2SGLang cache-aware managers/schedule_policy.py:155,139,176,205,253 (LPM/in-batch), default server_args.py:692; overlap managers/scheduler.py:1563,344, server_args.py:776; jump-forward constrained/outlines_jump_forward.py:182,146,159; eviction strategies server_args.py:739LPM landed (SW1, CLAIM-SGLANG-IMPL): SchedulerPolicy::kLPM (include/vllm/config/scheduler.h, src/vllm/config/scheduler.cpp "lpm"); reorder Scheduler::maybe_reorder_waiting_for_lpm() src/vllm/v1/core/sched/scheduler.cpp (ToQueuePolicy kLPM→FCFS deque; stable descending sort by match, >128-waiting fcfs fallback, ported FROM schedule_policy.py:205,229); side-effect-free match KVCacheManager::num_matched_prefix_tokens() src/vllm/v1/core/kv_cache_manager.cpp (pure find_longest_cache_hit, no stats/LRU touch); RequestQueue::reorder() src/vllm/v1/core/sched/request_queue.cpp; --schedule-policy/--scheduling-policy (fcfs / priority / lpm) + lpm+cache-off→fcfs warn examples/server/main.cpp; overlap == ENG-ASYNC-SCHED; grammar src/vllm/v1/structured_output/manager.cpp:50; SW2 landed (CLAIM-SGLANG-SW2): in-batch prefix-collision de-prioritization inside the kLPM reorder — maybe_reorder_waiting_for_lpm() src/vllm/v1/core/sched/scheduler.cpp:183-243 walks the pre-sort (arrival) queue building an ephemeral seen-set of OUR block-hash APC keys (NOT a second trie), de-prioritizes a later request whose in-batch prefix match ≥ kInBatchDeprioritizeThreshold when its real match ≤ kInBatchCheckThreshold (both 32, scheduler.h), sort key mirrors SGLang's float("inf"); ported FROM schedule_policy.py:253-301,311. Output-neutral; throughput lever NOT-APPLICABLE (our APC caches at allocation kv_cache_manager.cpp:267 → 2nd same-step collider already hits, no redundant prefill vs SGLang's post-forward radix). SW3 jump-forward safe subset landed (CLAIM-SGLANG-SW3): forced-token detection hook StructuredOutputGrammar::forced_token() (include/vllm/v1/structured_output/backend_types.h; native impl src/vllm/v1/structured_output/backend_native.cpp, trie×FSM DFS short-circuiting on a 2nd valid token) + opt-in driver DrainForcedTokens (src/vllm/v1/structured_output/jump_forward.{h,cpp}, env VT_ENABLE_JUMP_FORWARD, default OFF); jumps ONLY the TOKEN-UNIQUE forced run (exactly one grammar-valid token at a non-accepting state ⇒ sampler's only finite-logit token ⇒ PROVABLY byte-identical to per-token decode, no re-tokenization); ported FROM constrained/outlines_jump_forward.py:146-172 + schedule_batch.py@935cda944b^:503-544/:1094-1145. RESIDUAL: the general byte-forced multi-tokenizable span (SGLang's re-tokenize + boundary rollback) deliberately NOT jumped (falls back to normal decode); production scheduler splice needs the jumped-token KV recompute. ABI/API/flag EXPOSURE (CLAIM-SGLANG-ABI-DOCS, 2026-07-28, reconciled to ABI v10): LPM + jump-forward are now first-class DOCUMENTED knobs on all three surfaces (were server-only / env-only). LPM: C++ EngineParams::policy=kLPM, C-ABI vllm_model_params.scheduling_policy="lpm" (the concurrent session's v9 string field; NO duplicate int knob), server --scheduling-policy lpm. Jump-forward: C++ EngineParams::enable_jump_forward (std::optional<bool>), C-ABI vllm_model_params.enable_jump_forward (tri-state int, ABI v10 appended after the v9 fields), server --[enable|disable]-jump-forward; VT_ENABLE_JUMP_FORWARD retained as override (JumpForwardEnabled(optional<bool>), env-wins-when-set). Resolution observable via LoadedEngine::jump_forward_enabled() / Scheduler::policy(); the jump-forward tri-state translation is folded INLINE in vllm_engine_load (src/capi/vllm_c.cpp, single field — no shared helper). ABI e2e tests/capi/test_capi.cpp (2 v10 jump-forward cases; LPM-via-ABI covered by the concurrent session's scheduling_policy string cases). vllm_abi_version()==10. Docs specs/sglang-enablement.md + docs/SGLANG-COMPAT.md.tests/vllm/v1/test_scheduler_lpm.cpp:143 6/6 (47 asserts): SW1 output-neutral + reorder RED-first + hits-under-pressure + cache-off→fcfs (unchanged 3), SW2 de-prioritizes collider RED-first (fcfs/raw-prefix admits collider before solo; lpm+SW2 admits solo before collider) + output-neutral (per-req tokens + total hits 112 identical) + within-step-dedup-subsumes-redundant-prefill (NOT-APPLICABLE proof) + inert-when-prefix-cached (check-threshold gate); inertness test_scheduler 36/36 + test_prefix_cache_stats 12/12 unchanged. SW3 jump-forward safe subset gate tests/vllm/v1/structured_output/test_jump_forward.cpp 5/5 (40 asserts): output-identity WITH vs WITHOUT jump over a forced span + jump-FIRED (4 steps→1) + inert-no-forced-span + default-off untouched + RED (naive longest-match re-tokenization of a boundary-ambiguous span emits DIFFERENT tokens; safe subset refuses and stays byte-identical); inertness test_backend_native 35/35 + test_structured_output 12/12 + test_apply_grammar_bitmask 5/5 + test_response_format_e2e 3/3 unchanged. SW4 deferred; cache-ON throughput A/B owned by BACKEND-GATE-CUDA-SGLANG-PREFIXsglang-radixattention.mdANCHOR-BACKFILLCLAIM-SGLANG-IMPL
ENG-PLUGIN-SYSTEMOut-of-core PLUGIN system: the discovery + orchestration layer that lets an external translation unit / shared object register a model factory / platform / quant method through the EXISTING registration seams (REGISTER_VLLM_MODEL, RegisterPlatform, the quant registry) WITHOUT editing engine core — directly serves the extensibility-first priority. W0 SPIKE + W1 CPU BRICK LANDED 2026-07-29 (CLAIM-PLUGIN-SYSTEM, NOT pushed): vllm::plugins::LoadGeneralPlugins() (idempotent load-once latch + the VLLM_PLUGINS allowlist parse + per-plugin try/catch failure isolation, all mirroring load_general_plugins) + the general-plugin registration seam RegisterGeneralPlugin / the REGISTER_VLLM_GENERAL_PLUGIN macro (mirror of the vllm.general_plugins entry-point group). Python entry points have NO C++20 analogue, so discovery is the project's static-init/dlopen registration idiom (recorded porting-inventory §9). Proven by an OUT-OF-CORE toy-model plugin TU (compiled only into the test exe) that registers a toy arch via the public vllm::RegisterModel seam: RED-first — the toy arch throws "are not supported for now" before load AND under VLLM_PLUGINS="", and resolves to the plugin factory ONLY after LoadGeneralPlugins runs it. RESIDUALS (named, spec §Work breakdown): real .so dlopen + the C-ABI vllm_plugin_register entry (W2), the engine/CLI --load-plugins wiring (W3), the platform/quant plugin kinds (W4), io_processor/stat_logger/endpoint groups (W5).T2vllm/plugins/__init__.py:18,33,36-74,77-90 (group, latch, load_plugins_by_group allowlist + failure isolation, load_general_plugins); vllm/envs.py:1104-1108 (VLLM_PLUGINS); vllm/model_executor/models/registry.py:1039-1083 (register_model a plugin calls); vllm/v1/worker/worker_base.py:245-247; vllm/v1/engine/core.py:115-117 (invocation sites); tests/plugins_tests/test_oot_registration_offline.py:14-45include/vllm/plugins/plugins.h; src/vllm/plugins/plugins.cpp:74,80,111; CMakeLists.txt:464tests/vllm/plugins/test_plugin_system.cpp:52; tests/vllm/plugins/toy_model_plugin.cpp:99 (1 case / 29 assertions, RED-first, CPU)plugin-system.mdANCHOR-BACKFILLCLAIM-PLUGIN-SYSTEM

KV cache and memory

Maintenance checkpoint for KV-OFFLOAD (2026-07-31): GCC 12 -Werror portability is restored for the thread-local temporary suffix with append operations. Suffix values, atomic publication behavior, and the row's ACTIVE lifecycle are unchanged.

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
KV-BLOCK-POOLFree list, refcounts, LRU eviction, core block lifecycle. Record corrected 2026-07-22 (ANCHOR-BACKFILL -> PARTIAL): the spike gap is closed by prefix-prompt-caching-parity.md, and the row's stated scope UNDERSOLD the port — it also covers group-aware hash mapping, the partial-alias map, the unhashed-front/hashed-tail free ordering that is what actually makes eviction LRU (the queue itself is plain FIFO), reset with the null-block invariant, usage and duplicate-hash eviction, under 13 tests. PARTIAL (not DONE) because four upstream behaviours are genuinely absent, all throw-if-called or inert and none reachable from a ported call site: KV-cache EVENTS (LANDED 2026-07-27 by KV-EVENTS — the emission is now wired at the store/remove/clear sites, guarded default-OFF so this row stays byte-identical), partial-block primitives (upstream's are dead code, so not owed live), connector-driven evict_blocks, and the align path where block_size != hash_block_sizeT0vllm/v1/core/block_pool.py:144,163-197,199-224,226-356,542,574-595,597-612,614-635,656-690,700-711; dead partial primitive :358-457; queue vllm/v1/core/kv_cache_utils.py:179-408; tests/v1/core/test_prefix_caching.py:1315,1991src/vllm/v1/core/block_pool.cpp:42,77,206,231,254; deferrals recorded include/vllm/v1/core/block_pool.h:18-46tests/vllm/v1/test_block_pool.cpp:70,115,202,251,280,308,337,384,398prefix-prompt-caching-parity.mdPARTIAL-
KV-MANAGER-ALLOCSlot allocation, watermark, admission, releaseT0vllm/v1/core/kv_cache_manager.py:110,244; tests/v1/core/test_single_type_kv_cache_manager.py:380,413src/vllm/v1/core/kv_cache_manager.cpp:88,124,144tests/vllm/v1/test_kv_cache_manager.cpp:119,168,298,349,380,425planned: specs/kv-cache-manager.mdANCHOR-BACKFILL-
KV-DEVICE-RESIDENCYPersistent full-attention KV plus GDN convolution/recurrent state must be backend-resident; indexed mixed-prefill state I/O replaces row-wise host round trips. W0 ownership and W1 indexed gather/scatter are implemented and component-gated; W2 direct convolution update, fresh oracle closure, and inherited pool teardown remainT0allocation/views vllm/v1/worker/gpu/attn_utils.py:166-182,327-346; runner ownership vllm/v1/worker/gpu/model_runner.py:478-488; indexed conv/SSM vllm/model_executor/layers/mamba/gdn/qwen_gdn_linear_attn.py:1309-1375,1503-1532; tests tests/v1/worker/test_gpu_model_runner.py:968,1265; tests/v1/worker/test_mamba_utils.py:342-358W0 owner/allocation include/vllm/v1/worker/gpu/runner.h:173-200,249-266, src/vllm/v1/worker/gpu/runner.cpp:305-330,388-450; W1 API/dispatch include/vt/ops.h:867-877, src/vt/ops.cpp:840-895; CPU/CUDA kernels src/vt/cpu/cpu_ops.cpp:865-909, src/vt/cuda/cuda_gdn.cu:156-232; persistent metadata and mixed-path integration src/vllm/model_executor/models/qwen3_5.cpp:1565-1653,1737-1892; diagnostic fallbacks VT_DEVICE_KV_CACHE=0, VT_GDN_INDEXED_STATE_IO=0W0 gates remain green: c16/48 785.49/769.15 tok/s = 1.021239×, 20/20; access memcheck 234/234 + 315/315. W1 op/mask and mixed-turnover tests tests/vt/test_ops_gdn.cpp:994-1136, tests/vllm/models/test_qwen27_paged_forward.cpp:443-532; focused CPU/access-sanitizer/CUDA/op, indexed/fallback 27B+35B, turnover smoke and current local serial CTest 105/105 pass. Strict local model LSan retains 58,624 B/153 pooled allocations while the indexed op is leak-clean; earlier remote suites exposed the unrelated intermittent C-API timing flake. W1 c16/48 781.799/776.946 tok/s = 1.006246×, 20/20 axes, six memory returns; traces collapse async copies 163,540→7,508 and D2D calls 142,717→1,231. Manifest 34285a91…a5b; profiler ratio is invalidated by unequal perturbation. W0 full leak-check still fails inherited pools at 47.29 MB/36.82 GB while W0 caches are absentdevice-resident-kv-gdn-state.mdANCHOR-BACKFILLCLAIM-KV-DEVICE-1
KV-HYBRID-COORDFull-attention and GDN/Mamba group coordinator. Record corrected 2026-07-22: the row read as breadth-incomplete, but the ENTIRE cross-group intersection is ported verbatim — the iterate-to-fixed-point loop (a single-pass intersection would be WRONG), the full-attention downward-closed fast path with its not-yet-looked-up sentinel, EAGLE extra-block/drop bookkeeping, the is_simple_hybrid shortcut, final full-attention truncation and num_uncached_common_prefix_tokens, plus the two-phase local-then-external touch. Stays PARTIAL for a narrow, assert-guarded residue only: differing per-group block sizes, DCP/PCP > 1, cross-attention encoder branch, find_longest_cache_hit_per_group, and the retention-interval env readT0vllm/v1/core/kv_cache_coordinator.py:61-374,187-231,514,560-600,630-740,742-779,782-834; tests/v1/core/test_prefix_caching.py:347,836,987src/vllm/v1/core/kv_cache_coordinator.cpp:294,370,389; intersection :424-537; sentinel/EAGLE :281-323; truncation :507-521; guards :344,348-349tests/vllm/v1/test_kv_cache_coordinator.cpp:130,154,169,209,306prefix-prompt-caching-parity.mdPARTIAL-
KV-MAMBA-ALIGNMamba/GDN prefix retention in align mode; required for the matched vLLM/SGLang shared-prefix cache-on gate. mamba_cache_mode has THREE values (all/align/none): APC-on + none resolves to all when the model supports it else align, all on an unsupported model downgrades to align, align ASSERTS chunked prefill, and APC-off forces none; Qwen3.5/3.6 raise on all, so they take align. Record CORRECTED 2026-07-22 — this row was INVENTORIED with no code anchor, and that understated reality: the align ALLOCATOR is already substantially ported (mode read + branched across remove_skipped_blocks, get_num_blocks_to_allocate, allocate_new_blocks, pop_blocks_for_free, with reachable_block_mask and retention_interval). Three specific things are missing, not open-ended breadth: (1) no config path SELECTS align — MambaSpec defaults "none" and no caller overrides it, so production is effectively mode-none; (2) the RUNNER-side recurrent state copy the align path presumes does not exist (zero hits for last_state_block_idx under src/vllm/v1/worker/gpu/); (3) no align-mode test — all four local Mamba cases exercise mode "none"T1default policy vllm/config/model.py:1842-1847; three-value resolution vllm/model_executor/models/config.py:550-593; Qwen constraint vllm/model_executor/models/qwen3_5.py:297; manager vllm/v1/core/single_type_kv_cache_manager.py:1026,1196-1204,1265-1327,1341,1364; config vllm/config/cache.py:38,134; e2e tests/v1/e2e/general/test_mamba_prefix_cache.py:745,803 (the _mrv2 case is the binding one)align allocator ALREADY ported src/vllm/v1/core/single_type_kv_cache_manager.cpp:639,687-700,737,773,803,865; spec field defaulting to none include/vllm/v1/kv_cache_interface.h:306,318mode-none coverage only tests/vllm/v1/test_single_type_kv_cache_manager.cpp:811,849,866,875prefix-prompt-caching-parity.mdSPIKECLAIM-PREFIX-PROMPT-CACHING
KV-SLIDING-LOCAL-SPECSBlock row (claim the two leaves below, not this row): sliding-window and chunked-local KV specsT1vllm/v1/kv_cache_interface.py:205-307,480-586; tests/v1/test_kv_cache_spec_registry.py:174-306--sliding-local-yarn-long-context.mdREADY-
KV-SLIDING-WINDOW-SPECSlidingWindowSpec sizing, grouping, admission, allocation, eviction, and prefix-cache policy; CPU G1/G2 green, while feature-positive attention/model/oracle/performance gates remainT1vllm/v1/kv_cache_interface.py:518-586; vllm/v1/core/single_type_kv_cache_manager.py:669-873; tests/v1/core/test_single_type_kv_cache_manager.py:127,259,380,413,489; tests/v1/core/test_prefix_caching.py:2457-3909include/vllm/v1/kv_cache_interface.h:187; src/vllm/v1/kv_cache_spec_registry.cpp:69; src/vllm/v1/core/single_type_kv_cache_manager.cpp:350,377,470,920; src/vllm/v1/core/kv_cache_utils.cpp:21; src/vllm/v1/core/kv_cache_coordinator.cpp:36,119tests/vllm/v1/test_kv_cache_interface.cpp:157,204,258; tests/vllm/v1/test_single_type_kv_cache_manager.cpp:283,331,368,411,453,476; tests/vllm/v1/test_kv_cache_utils.cpp:592,617; tests/vllm/v1/test_kv_cache_coordinator.cpp:163,238,357sliding-local-yarn-long-context.mdGATING-
KV-CHUNKED-LOCAL-SPECChunkedLocalAttentionSpec sizing, grouping, admission, allocation, fixed-chunk prefix-cache/recycling policy and hybrid-disabled fallback; CPU G1/G2 green, while W4/model/oracle/runtime gates remainT1vllm/v1/kv_cache_interface.py:480-514; vllm/v1/core/single_type_kv_cache_manager.py:876-1023; vllm/v1/core/kv_cache_utils.py:1403-1496; tests/v1/core/test_single_type_kv_cache_manager.py:54,198,456; tests/v1/test_kv_cache_spec_registry.py:174-315include/vllm/v1/kv_cache_interface.h:219; src/vllm/v1/kv_cache_spec_registry.cpp:71; src/vllm/v1/core/single_type_kv_cache_manager.cpp:535,553,618,933; src/vllm/v1/core/kv_cache_utils.cpp:21; src/vllm/v1/core/kv_cache_coordinator.cpp:47tests/vllm/v1/test_kv_cache_interface.cpp:188,204,258; tests/vllm/v1/test_single_type_kv_cache_manager.cpp:576,643,683,705,730,1072; tests/vllm/v1/test_kv_cache_utils.cpp:629,654,674,686; tests/vllm/v1/test_kv_cache_coordinator.cpp:188,258,380,524sliding-local-yarn-long-context.mdGATING-
KV-FP8FP8 KV cache and scale handling. W0 spike + W1 CPU brick LANDED 2026-07-29 — fp8-e4m3 K/V STORE (Quantize(hp/scale)) + the paged-attention READ dequant (Dequant(fp8)*scale) + the cache_dtype config parse, all CPU-gated RED-first. Storage is 1-byte fp8 (DType::kI8) + the Fp8KVCacheDataType interpretation enum (mirrors vLLM's cache_t=uint8_t+KV_DTYPE), per-tensor k/v scales (kv_cache.py:108-191). W2 CUDA arm LANDED 2026-08-21 (#1593) -- the fp8-e4m3 store kernel + the fp8 dequant on the paged-attention read, gated for parity against the W1 CPU oracle; the two W1 device-class refusals that made the CUDA arm unreachable are gone, and the READ keeps a NAMED CPU-or-CUDA refusal because it rides additive PagedAttentionArgs fields on an op kMETAL/kROCM register for the FLOAT path. Its DEVICE cases are UNEXECUTED (no device in the implementing session), though the CUDA TUs DO COMPILE: CI cuda-fat-build built them for ten architectures under -Werror=all-warnings on 4d71e776e (run 32495320287). That job sets -DVLLM_CPP_BUILD_TESTS=OFF, so nothing has EXECUTED them -- see the spec's ## Owed. Residuals (honest, named): the runner/spec integration (half-sized KV blocks + checkpoint-scale threading + --kv-cache-dtype/--calculate-kv-scales), fp8_e5m2 CPU compute + per-head scales — all W2-W5 in the specT1vllm/config/cache.py:19-36,76; vllm/model_executor/layers/quantization/kv_cache.py:42,108-191; store csrc/libtorch_stable/cache_kernels.cu:241-252,314-401; scale convention csrc/quantization/w8a8/fp8/nvidia/quant_utils.cuh:296-308codec include/vt/fp8_kv.h; store src/vt/cpu/cpu_cache.cpp:143; wrapper src/vt/ops.cpp:2255; read dequant src/vt/cpu/cpu_paged_attn.cpp:82; config parse include/vllm/v1/kv_cache_dtype.h:37tests/vt/test_ops_fp8_kv_cache.cpp:1 (8 cases / 511 assertions; RED-first: wrong store direction fails 3/480)fp8-kv-cacheANCHOR-BACKFILLCLAIM-KV-FP8
KV-NVFP4-TURBONVFP4, per-token-head, and TurboQuant KVT2vllm/config/cache.py:14,28-35,272--planned: specs/nvfp4-kv-cache.mdINVENTORIED-
KV-OFFLOADKV offload tiering: CPU primary tier plus secondary tiers, including the filesystem (disk) tier that is vLLM's KV-persistence-to-disk answer. Record CORRECTED 2026-07-22 (spike) — the prior row text named a class that does not exist and omitted the half the user asked for. There is no LRUOffloadingManager at this pin: LRU and ARC are pluggable CachePolicy objects behind ONE CPUOffloadingManager, and the row's scope ('CPU tiering with LRU and ARC') left out the entire secondary-tier surface. Disk format enumerated: ONE RAW FILE PER BLOCK, no container and no index, <root>/<model>_<sha256 prefix>_r<rank>/<hhh>/<hh>_g<group>/<hash>.bin, written via temp-file + atomic rename under O_DIRECT and self-healing by deleting unreadable files. Two upstream WEAKNESSES recorded as beyond-parity targets: config.json is written and NEVER read (the only identity check is a path digest omitting checkpoint content, weight quantization, rope config and sliding_window), and the disk tier has NO capacity accounting and NO eviction. Secondary tiers can never touch GPU memory — all traffic cascades through the CPU primary tier W1-W3 IMPLEMENTED 2026-07-22. Deterministic block hashes (W1), the CPU primary tier (W2: CachePolicy LRU+ARC with the ref_cnt == -1 tri-state and the ATOMIC evict, CPUOffloadingManager incl. the prepare_store -> nullopt skip path, pinned backing store plus side-queue event-polled device/host transfer), and the DISK tier (W3: one raw file per block, temp-file + atomic rename publish, self-healing unlink, dual-queue read/write pool). BOTH recorded upstream weaknesses are now EXCEEDED, not merely noted: the identity block is a VERIFIED header read on every open that REFUSES on mismatch across 27 fields (upstream's config.json is never read), and the tier carries a byte budget with policy-driven eviction honoured across restarts (upstream has none). O_DIRECT is deliberately NOT ported — a header+payload file breaks its alignment requirement; recorded. W4 IMPLEMENTED 2026-07-23. The TIERING MANAGER (ONE manager over the CPU primary + disk secondary tier: disk→CPU promotion is RETRY this step / HIT the next with the reserved slot marked in-flight, cascade demotion on store, reset drains the secondary FIRST and DELIBERATELY never resets it so a persisted cache survives a prefix-cache reset) and the CONNECTOR/SCHEDULER HALF (OffloadingConnector mirroring KVConnectorBase_V1's scheduler hooks — get_num_new_matched_tokens with the load-bearing NULLOPT third state, Request::block_hashes striding, load-before-compute ordering, build_connector_meta reset — wired OPT-IN and DEFAULT-OFF into the scheduler so a cross-request/restarted-process prefix HIT shortcuts prefill). The semantics are ported, NOT the Python plugin ABI (compile-time wiring replaces the importlib module path; the full 7-method abstract ABI + registration + KVTransferConfig is the W5 generalization behind the same seam). Deviation recorded: W4 ships the SYNCHRONOUS-load shape (async flag always false), the disk→CPU promotion being the async part handled by RETRY/re-ask; the cross-step WAITING_FOR_REMOTE_KVS GPU-load buffer is W5. First measured offload speedup: a restarted-prefix workload through the real scheduler saved 32/48 prefill tokens (2/3 blocks HIT from disk) with the promoted bytes proven byte-identical to the cold store. W5 LANDED 2026-07-23 (the connector seam is now a first-class C++ ABI — abstract KVConnector base + KVConnectorFactory + KVTransferConfig, the disk connector refactored onto it behaviour-identically; see the KV-CONNECTORS row). D1 CORRECTION 2026-07-24 (CLAIM-DOCS-T2-FIXES): the disk connector's WORKER HALF IS NOT IMPLEMENTED and is now REFUSED, not merely absent. OffloadingConnector emits ConnectorLoadJobs that NOTHING consumes, and its bytes live in a host PrimaryByteView that is never copied into a KV page — on any device. Because its scheduler half DOES shortcut prefill for matched blocks, wiring it into an engine would have made the model attend over never-written KV (silently wrong output); BuildKvConnector previously built it for any device with no guard. It is now refused at construction by a per-connector capability predicate (KVConnector::supports_worker_transfer_on / the registered KVConnectorWorkerTransferFn, queried by name BEFORE construction via KVConnectorFactory::WorkerTransferSupportedOn), with an error naming the connector, the device, the consequence and the admissible connectors. The scheduler-side 32/48 e2e is UNAFFECTED (it never reaches a worker). Implementing the worker half remains OPEN work and is NOT claimed. W6 (LMCache study) and W7 (named save/restore) remain openT2core vllm/v1/kv_offload/base.py:27-47,88-108,177-347,486-588,536-549; CPU tier vllm/v1/kv_offload/cpu/manager.py:36,169-237, policies cpu/policies/base.py:10-33,36-92, lru.py:12, arc.py:12; disk tier vllm/v1/kv_offload/tiering/fs/io.py:32-72,75-101, tiering/fs/manager.py:95-103,131-137, tiering/fs/thread_pool.py:50-57,153-180; naming/identity vllm/v1/kv_offload/file_mapper.py:112-120,128-139; tiering ordering tiering/manager.py:238-329,408-459,498-556,643-681; transfer cpu/gpu_worker.py:240-421,388-394; config docs/features/kv_offloading_usage.md:64-82,95-121; tests tests/v1/kv_offload/tiering/test_fs_tier.py, tests/v1/kv_offload/test_file_mapper.py, tests/v1/kv_offload/cpu/test_manager.pyW1-W3 LANDED. Core include/vllm/v1/kv_offload/base.h (OffloadKey verified byte-identical to upstream's packing); policies include/vllm/v1/kv_offload/cache_policy.h + src/vllm/v1/kv_offload/cache_policy.cpp; CPU tier include/vllm/v1/kv_offload/cpu_manager.h + src/vllm/v1/kv_offload/cpu_manager.cpp; transfer include/vllm/v1/kv_offload/kv_block_transfer.h + src/vllm/v1/kv_offload/kv_block_transfer.cpp (plus the new non-blocking vt::Backend::QueryEvent seam with its CUDA override in src/vt/cuda/cuda_backend.cu); disk byte path + naming include/vllm/v1/kv_offload/fs_io.h + src/vllm/v1/kv_offload/fs_io.cpp; tier include/vllm/v1/kv_offload/fs_tier.h + src/vllm/v1/kv_offload/fs_tier.cpp; the verified identity header include/vllm/v1/kv_offload/cache_identity.h + src/vllm/v1/kv_offload/cache_identity.cpp; determinism fix src/vllm/v1/core/kv_cache_utils.cpp (init_none_hash seed resolution + none_hash_provenance), caller src/vllm/entrypoints/model_loader.cpp:140-152; W4 tiering manager include/vllm/v1/kv_offload/tiering_manager.h + src/vllm/v1/kv_offload/tiering_manager.cpp; connector/scheduler half include/vllm/v1/kv_offload/kv_connector.h + src/vllm/v1/kv_offload/kv_connector.cpp; scheduler wiring src/vllm/v1/core/sched/scheduler.cpp (set_kv_connector, null = zero change) + include/vllm/v1/core/sched/scheduler.h; BlockPool::evict_blocks src/vllm/v1/core/block_pool.cpp:139-155 (1:1, replaces the throw)tests/vllm/v1/test_none_hash_determinism.cpp:108 7/7 (cross-PROCESS byte-identical hash chains via a /proc/self/exe re-exec, both env escape hatches, and the =random negative control); tests/vllm/v1/test_kv_offload_cpu.cpp 21/21 (atomic evict, pinning, ARC promotion, HIT_PENDING, failed-store rollback, same-batch protection, store_threshold, events, transfer round-trip); tests/vllm/v1/test_kv_offload_fs.cpp 22/22 + 3 SKIP (byte-exact round trip for full attention AND MLA rank-3, truncation/foreign-magic/misfiled refusal with self-heal, a 27-field identity-refusal matrix with a positive control, the byte budget across a restart, and a 6/6 cross-restart hit measurement); the SKIPs are row-tagged to KV-SLIDING-WINDOW-SPEC, KV-FP8/KV-NVFP4-TURBO and KV-MAMBA-ALIGN; W4 tests/vllm/v1/test_kv_offload_tiering.cpp 5/5 (promotion RETRY→HIT byte-identical, CPU-eviction→disk-survival→re-promotion, reset clears CPU but disk survives, a FRESH manager on the same directory promotes = restart, and identity REFUSAL through a promotion — a corrupt disk block is unlinked and treated as absent, never trusted) and tests/vllm/v1/test_kv_offload_connector.cpp 4/4 (null-connector inertness, external match shortcuts prefill by exactly ext, the nullopt third state defers then schedules next step, and the END-TO-END restarted-prefix disk HIT through the real scheduler: hit rate 2/3 blocks, 32/48 prefill tokens saved, promoted bytes byte-identical)kv-persistence-lmcache.mdANCHOR-BACKFILLCLAIM-KV-PERSISTENCE-LMCACHE
KV-EXTERNAL-CACHEExternal KV-cache provider ABI plus LMCache interoperability: producer/consumer/both roles, the scheduler/worker metadata split, cache registration, block-hash lookup, asynchronous load/store and completion/free ownership. SPIKED 2026-07-22 (spike) — the ABI is smaller than the row implied and the LMCache half is larger. The minimum viable connector is exactly 7 abstract methods (worker start_load_kv/wait_for_layer_load/save_kv_layer/wait_for_save, scheduler get_num_new_matched_tokens/update_state_after_alloc/build_connector_meta); roughly thirty further hooks all have safe defaults. Three traps recorded: get_num_new_matched_tokens has a THIRD state (None = deschedule and re-ask, not zero), request_finished returning True transfers block-freeing OWNERSHIP to the connector, and non-HMA connectors ASSERT a single KV cache group while our gate models are two-group hybrids. LMCache determination: it is an EXTERNAL PyPI package (lmcache >= 0.3.9 in an opt-in extras file that setup.py/pyproject.toml never reference; not installed on any of this project's boxes). vLLM vendors roughly 2396 lines of lmcache_integration/ glue, but every one of those files imports the external package at module scope — the storage engine, the paged-memory GPU connectors, the config schema, the ZMQ message queue and the CUDA-IPC handoff are all outside the tree, and no upstream test exercises it without importing lmcache. Scoped as an interop STUDY, not a from-scratch client, and gated on two blockers we own: our sha256_cbor hashes are not byte-compatible with vLLM's default, and our NONE_HASH is per-process random. REOPENED 2026-07-23 (client spike) on the user's connect-as-client hypothesis, and the prior "no specified wire protocol" verdict is REFUTED by reading the LMCache package (LMCache/LMCache@8570aad). vLLM connects to a RUNNING LMCache instance over two fully-specified, language-agnostic wires: (1) the lm:// remote-store server — plain TCP + a fixed struct.pack header + raw KV bytes, no ZMQ/msgpack/pickle/CUDA-IPC (lmcache/v1/protocol.py:214-321, server/__main__.py:24-147, lm_connector.py:28-177); and (2) the MP server — ZMQ DEALER↔ROUTER + msgspec.msgpack control + CUDA-IPC data (multiprocess/mq.py:270-353, custom_types.py:120-234), the mode the user recalled as "zmq". BOTH need ZERO lmcache in our process and BOTH sidestep the R1 hash blocker — LMCache keys on its OWN blake3 rolling token hash (token_hasher.py:54-79), never vLLM block hashes. Pickle appears ONLY in the MP one-time IPC-wrapper registration (platform/base/ipc_wrapper.py Serialize); CUDA-IPC ONLY in MP data (portable via RawCudaIPCWrapper cudaIpcGetMemHandle, but co-located). Verdict: a C++ client is FEASIBLE — recommend MODE (1) first (stabler/simpler); the standing risk is LMCache being an unpinned moving target, so it is an interop feature with a version-sync cost, not a mechanical core portT2ABI vllm/distributed/kv_transfer/kv_connector/v1/base.py:171,293,311,325,347,454,489,510,542,585; roles :124; HMA :85,93; factory + out-of-tree module seam vllm/distributed/kv_transfer/kv_connector/factory.py:28,31,96,102-123,152-238; config vllm/config/kv_transfer.py:22-75,102-106; MRV2 worker hooks vllm/v1/worker/gpu/kv_connector.py:56,61-75,77-95; scheduler call sites vllm/v1/core/sched/scheduler.py:280,736-742,933-937,1118-1119,2340-2371; LMCache vllm/distributed/kv_transfer/kv_connector/v1/lmcache_connector.py:74-115,259,281, lmcache_mp_connector.py:1-50, lmcache_integration/vllm_v1_adapter.py:11-35,175-188,368-376,781, external requirement requirements/kv_connectors.txt:1; tests tests/v1/kv_connector/unit/test_lmcache_integration.py:60-223, test_kv_connector_lifecycle.py:37, test_config.py:51W1 LANDED 2026-07-23 — the LMCache MODE-1 lm:// wire CODEC (pure CPU, INERT: no call site routes to it, the connector is W3): src/vllm/v1/kv_offload/lmcache/remote_protocol.{h,cpp} (186-byte ClientMetaMessage / 36-byte ServerMetaMessage fixed-struct framing + ClientCommand/ServerReturnCode/DTYPE_TO_INT/Location maps), cache_engine_key.{h,cpp} (model@world@worker@chunk_hash_hex@dtype to/from string), token_hasher.{h,cpp} (blake3 rolling chunk hash over vendored third_party/blake3/ 1.5.5), memory_format.{h,cpp} (the KV_2LTD [2,L,T,D] repack); wired in CMakeLists.txt (blake3_vendored static lib). Later-connector seams still NAMED: include/vllm/v1/core/kv_cache_manager.h:31 (ext_comp), include/vllm/v1/core/single_type_kv_cache_manager.h:122, include/vllm/v1/core/sched/output.h:30-31, include/vllm/v1/engine/types.h:26,30. W5 worker-side store/load LANDED 2026-07-24 (the last open arm): src/vllm/v1/worker/gpu/runner.cpp (ConnectorLoadExternalKv writes the external-prefix KV into the allocated GPU blocks BEFORE the forward = load-before-compute; ConnectorStorePromptKv stores each newly-complete prompt block AFTER the forward; both behind a kv_connector_ != nullptr guard so default-off is byte-identical) + include/vllm/v1/worker/gpu/runner.h (set_kv_connector), src/vllm/entrypoints/model_loader.cpp (BuildKvConnector builds the connector from EngineParams::kv_transfer_config via KVConnectorFactory, injects the runner's full-attention KV geometry, wires it to scheduler + runner) + include/vllm/entrypoints/model_loader.h (EngineParams::kv_transfer_config, LoadedEngine::kv_connector())W1 byte/bit-exact gate GREEN (CPU): tests/vllm/v1/kv_offload/lmcache/test_lmcache_codec.cpp:105 (6 cases / 2074 assertions) vs tests/fixtures/lmcache/lmcache_fixtures.json — our wire bytes == the real Python codec's (stdlib struct framing + blake3 PyPI hashes + numpy KV_2LTD); blake3 digest VERIFIED byte-identical on x86-64 AND dgx.casa aarch64. W2 (client, CPU) GREEN — go/no-go PASSED: src/vllm/v1/kv_offload/lmcache/remote_client.{h,cpp} (blocking POSIX-socket PUT/GET/EXIST/HEALTH/LIST + partial-read/write loops + PutKv2ltd/GetKv2ltd KV_2LTD repack + LmcacheClientConfig/VT_LMCACHE_* env); tests/vllm/v1/kv_offload/lmcache/test_lmcache_client.cpp round-trips a REAL lmcache.v1.server (8570aad, run headless from source in a throwaway venv — torch imported before lmcache to dodge a torch circular import, the compiled c_ops ext stubbed as unused by the lm:// CPU store) byte-identical (36/36), and interop is BIDIRECTIONAL with LMCache's OWN Python protocol codec (scripts/lmcache/{lm_server,lm_interop_client}.py+run_live_roundtrip.sh); always-on CI gate = a same-binary C++ mock-server round-trip (45/45, no Python). W3 LANDED 2026-07-23 — the lm:// client wired as a KVConnector over the W5 seam (the FIRST time engine -> connector -> W2 client -> a running lm:// server -> back runs): src/vllm/v1/kv_offload/lmcache/lmcache_connector.{h,cpp} (LMCacheConnector : KVConnector, REGISTER_KV_CONNECTOR("LMCacheConnector", …), selected by KVTransferConfig{kv_connector="LMCacheConnector", kv_connector_extra_config={host,port,hash_algo,chunk_tokens,…}}, default OFF). Scheduler side is real: get_num_new_matched_tokens computes the request's rolling-blake3 chunk hashes, builds the CacheEngineKey per chunk and Exist-probes the REMOTE store for the longest cached prefix (synchronous -> (n, false), mirroring lmcache_connector.py:230-259); update_state_after_alloc records the load (drops blocks upstream, :261-268); worker StoreChunk (PUT KV_2LTD) / LoadChunk (GET+unpack, foreign-block REFUSAL via GetKv2ltd). Gate ACHIEVED = the connector-level round-trip: store -> lookup -> prefill-shortcut through the REAL scheduler -> load byte-identical (32/48 prefill tokens saved), foreign/mismatched-key REFUSAL, default-off inertness (tests/vllm/v1/kv_offload/lmcache/test_lmcache_connector.cpp 5 cases / 50 assertions vs an in-process mock; the store->load round-trip ALSO passes vs a REAL lmcache.v1.server 8570aad, 16 assertions, under VT_LMCACHE_LIVE_*). W4 LANDED 2026-07-23 — REAL peer KEY-AGREEMENT + a peer->us interop LOAD, both PROVEN (the interop-correctness milestone is complete; the row stays ACTIVE only for the DGX full-model output-invariance + throughput arm, spec gates 4/6): the actual lm:// key derivation is NOT the blake3 MP TokenHasher (a different subsystem) but ChunkedTokenDatabase (lmcache/v1/token_database.py:298-449) — chunk_size 256, a rolling prefix-hash chain over the 3-tuple (prefix_int, tuple(tokens), extra_keys=()), keyed by vLLM's OWN hash function (pre_caching_hash_algorithm; the portable interop choice sha256_cbor = cbor2-canonical + SHA-256, vllm/utils/hashing.py:43), folded to uint64 each step (_normalize_hash_to_int token_database.py:34-56), with NONE_HASH = fold8(sha256_cbor(str(PYTHONHASHSEED))) (kv_cache_utils.py:99-114). Mirrored BYTE-EXACT in src/vllm/v1/kv_offload/lmcache/chunked_token_database.{h,cpp} (reusing the project's CborValue+sha256_cbor, already Python-cbor2/hashlib-exact), and wired into the connector as key_mode=kVllmSha256Cbor (hash_algo="vllm"/"sha256_cbor", chunk 256) alongside W3's kept-green blake3 path. Key-agreement gate GREEN: tests/vllm/v1/kv_offload/lmcache/test_lmcache_key_agreement.cpp (4 cases / 85 assertions) asserts our CacheEngineKey strings + chunk boundaries + folded hashes are BYTE-IDENTICAL to the REAL lmcache ChunkedTokenDatabase.process_tokens() (fixtures tests/fixtures/lmcache/key_agreement_fixtures.json dumped by scripts/lmcache/gen_key_agreement_fixtures.py driving the unmodified real driver, with vLLM's pinned sha256_cbor/init_none_hash), incl. the connector's own peer-mode ChunkKey. Sample: tokens 1000..1511 -> meta-llama/Llama-3.1-8B@1@0@33d6862800fff40c@bfloat16. Peer->us interop LOAD gate GREEN (over the wire, real server): scripts/lmcache/{lm_key_interop.py,run_key_interop.sh} has the REAL lmcache ChunkedTokenDatabase derive a key from tokens and PUT KV to a REAL lmcache.v1.server (8570aad, headless); our C++ INDEPENDENTLY re-derives the SAME key and GETs the peer-written 512 B byte-identical (test_lmcache_key_agreement LIVE case under VT_LMCACHE_LIVE_SPEC). ASan+UBSan clean on the connector path. Text-only scope (mm-hash extra_keys deferred); the DGX full-model output-invariance + throughput are the W5 arm below. W5 OUTPUT-INVARIANCE GATE GREEN 2026-07-24 (spec gates 4+6 met — the LAST open arm CLOSED): tests/vllm/models/test_lmcache_output_invariance.cpp on a REAL OPT-125m bf16 loop vs a live lmcache.v1.server (8570aad, headless per the W2 recipe) proves connector-ON generated tokens are BIT-IDENTICAL to connector-OFF cold full prefill (first-divergence index -1) in BOTH modes — (a) store->restart->load within one process AND (b) a genuinely COLD second process that only hits the server (VT_LMCACHE_OI_MODE=loadonly) — with prefill SAVED on the hit = 48 tokens (3×16-token blocks) and chunks_stored>0; driven by scripts/lmcache/run_output_invariance.sh under flock $HOME/gpu.lock, VT_ASYNC_SCHED=0. Throughput reported HONESTLY: on a 125M model wall-clock is noise-dominated (fixed TCP/copy overhead ~ tiny compute saved) so NO binding speedup is claimed — a real speed number is owed by an every-axis grid on a larger model + long shared-prefix corpus (docs/BENCHMARKS.md). No-regression WITNESS: OPT SACRED gate UNCHANGED default-off (test_opt_paged_engine 6/6 prompts, 96/96 tokens, 63/63 assertions) with the connector code present; connector units green (codec 6/6·2074, client 3/3·45, connector 5/5·50, key-agreement 4/4·85, kv_offload_connector 11/11·80); ASan+UBSan clean on the connector path (0 sanitizer hits); CUDA -Werror 0 warnings. Additive + default-off inert (scheduler/worker/seam untouched)kv-persistence-lmcache.md; LMCache client wire analysis + W-plan lmcache-cpp-client-connector.mdANCHOR-BACKFILL (W1-W5 landed; the connector-ON full-model OUTPUT-INVARIANCE arm is CLOSED — connector-ON == connector-OFF tokens BIT-IDENTICAL on a real OPT-125m loop vs a live lmcache.v1.server, both after an in-process restart and from a cold second process, spec gates 4/6 met; a BINDING every-axis LMCache throughput grid on a LARGER model stays PENDING, mirroring the Llama 'correctness DONE, speed PENDING' disposition — a 125M model's wall time is noise-dominated)CLAIM-LMCACHE-CPP-CLIENT (W1 codec + W2 client + W3 connector + W4 key-agreement + W5 output-invariance); parent seam CLAIM-KV-PERSISTENCE-LMCACHE
KV-CONNECTORSRemaining connector breadth and prefill/decode disaggregation over the KV-EXTERNAL-CACHE base seam. SPIKED 2026-07-22 (spike): the registry is enumerated at SIXTEEN connectors and the breadth is DISPOSITIONED, not merely listed. Registered: ExampleConnector (the former SharedStorageConnector — RENAMED at this pin, so the old name in the record is stale), ExampleHiddenStatesConnector, LMCacheConnectorV1, LMCacheMPConnector, NixlConnector/NixlPullConnector/NixlPushConnector, MultiConnector, MoRIIOConnector, OffloadingConnector, DecodeBenchConnector, MooncakeConnector, MooncakeStoreConnector, FlexKVConnectorV1, SimpleCPUOffloadConnector, HF3FSKVConnector. P2pNcclConnector NO LONGER EXISTS — no file, no registry entry, no reference. NIXL / Mooncake / MoRI-IO / HF3FS / FlexKV and P/D disaggregation are NOT SCHEDULED: each needs an external RDMA or store dependency absent from our boxes and ungateable on GB10. This blanket Mooncake disposition was CORRECTED 2026-08-10 (#287, spec) — it conflated TWO connectors. MooncakeConnector (P2P prefiller→decoder over the Transfer Engine; needs two nodes, a fabric and a disagg proxy) remains NOT SCHEDULED. MooncakeStoreConnector (the shared KV object store, the LMCache analogue) SPLITS OUT to its own row KV-MOONCAKE-STORE: Mooncake is native C++ (mooncake::Client in mooncake-store/include/client_service.h; the MooncakeDistributedStore vLLM imports is a pybind wrapper over it) so we LINK rather than reimplement a wire, and its single-node protocol: "tcp" + mooncake_master configuration is gateable on one box with no RDMA NIC. What this row DOES own after the spike is the generalization of the first ported connector into a reusable C++ seam — abstract base, compile-time registration replacing vLLM's dynamic Python module-path import (recorded deviation), KVTransferConfig, the fail-by-default load-failure policy, deferred block-free ownership, and SupportsHMA multi-group finish. W5 LANDED 2026-07-23: the abstract KVConnector base (the full scheduler + worker method set mirroring KVConnectorBase_V1 — the scheduler methods get_num_new_matched_tokens/update_state_after_alloc/build_connector_meta/request_finished are load-bearing for correctness, the worker hooks register_kv_caches/start_load_kv/wait_for_layer_load/save_kv_layer/wait_for_save/get_finished are defaulted no-ops for our synchronous runner, documented in the header), a compile-time KVConnectorFactory + REGISTER_KV_CONNECTOR macro (the C++ analogue of the Python importlib module path, mirroring REGISTER_VLLM_MODEL), the KVTransferConfig selection surface (default kv_connector empty == no connector == zero behaviour change) with kv_role validation and the fail-default load policy, and SupportsHMA multi-group finish + deferred-free ownership on the base. The W4 disk connector now IMPLEMENTS this abstract base behaviour-identically (the restart-hit e2e reproduces byte-for-byte, and a config-selected owning connector shortcuts prefill by the exact same 32/48). This closes the seam so LMCache W3 is 'implement the abstract KVConnector with the landed W2 lm:// client' — no further seam change. NIXL / MooncakeConnector (P2P) / MoRI-IO / HF3FS / FlexKV and P/D disaggregation remain NOT SCHEDULED; MooncakeStoreConnector moved to KV-MOONCAKE-STORE 2026-08-10T2registry vllm/distributed/kv_transfer/kv_connector/factory.py:152-238; renamed disk reference impl vllm/distributed/kv_transfer/kv_connector/v1/example_connector.py:104,109,203,405-442; MultiConnector HMA gate factory.py:145; SimpleCPUOffloadConnector vllm/v1/simple_kv_offload/worker.py:198,204,269; load-failure policy vllm/config/kv_transfer.py:70-74 with vllm/v1/core/sched/scheduler.py:1529-1535; tests tests/v1/kv_connector/unit/test_multi_connector.py:818, tests/v1/kv_connector/unit/test_kv_load_failure_recovery.py, tests/v1/kv_connector/unit/test_remote_prefill_lifecycle.py, tests/v1/kv_connector/unit/test_nixl_connector.pyW5 abstract ABI + factory + config LANDED. The abstract base + factory + registration include/vllm/v1/kv_offload/kv_connector.h + src/vllm/v1/kv_offload/kv_connector.cpp (the KVConnector base with the full method set, KVConnectorFactory/KVConnectorRegistrar/REGISTER_KV_CONNECTOR, the OffloadingConnector now deriving from it plus its CreateFromConfig owning builder registered as "OffloadingConnector"); the selection surface include/vllm/config/kv_transfer.h + src/vllm/config/kv_transfer.cpp (KVTransferConfig, KVRole, KVLoadFailurePolicy, Validate/predicates/string round-trips); scheduler holds the renamed KVConnector* (non-owning, null = zero change) include/vllm/v1/core/sched/scheduler.h + src/vllm/v1/core/sched/scheduler.cpp; wired in CMakeLists.txt. Still the throw stub for evict_blocks at src/vllm/v1/core/block_pool.cpp:139-155 (owned jointly with KV-BLOCK-POOL, replaced in W4)tests/vllm/v1/test_kv_offload_connector.cpp:177 11/11 (80 assertions): the pre-existing null-connector inertness + external-match shortcut + nullopt-third-state + restart-hit e2e, PLUS W5 — KVTransferConfig validation/predicates (kv_role required when kv_connector set, producer/consumer predicates, policy-default fail, string round-trips), KVConnectorFactory selection (absent config == nullptr, unknown name + duplicate registration throw, disk connector registered + selectable + reports HMA, missing root_dir refused), an interface-completeness oracle overriding EVERY base method (mirrors test_multi_connector_overrides_all_base_methods) with the worker-hook defaults exercised, and a behaviour-identical e2e where the config-selected OWNING connector shortcuts prefill by the exact same 32/48 as the borrowing path. 2026-07-24 (CLAIM-DOCS-T2-FIXES) — WORKER-HALF CAPABILITY on the seam + a USER-FACING selector. The base gained supports_worker_transfer_on(vt::DeviceType) (default FALSE: the base's worker hooks are no-ops, so a connector that does not override it has no worker half); the registry gained a parallel static KVConnectorWorkerTransferFn (REGISTER_KV_CONNECTOR_WITH_WORKER) so an unsafe (connector, device) pair is refused BY NAME before anything is constructed; EnsureWorkerTransferSupported is the single refusal point the engine calls. LMCacheConnector registers the predicate (true on every device — its worker half is vt::Backend::Copy-based and device-agnostic); OffloadingConnector does not, so it is refused everywhere. Selection is now reachable from the server: --kv-transfer-config '<json>' (vllm::ParseKVTransferConfigJson, vLLM's own flag name and JSON shape) threaded into EngineParams::kv_transfer_config; absent == no connector == byte-identical. New cases in tests/vllm/v1/test_kv_offload_connector.cpp (18/18, 144 assertions): the base default, a per-device partial-implementation stand-in, the disk refusal + message content on cpu/cuda/metal, the LMCache admission, empty-name inertness, unknown-name reporting, and the JSON parse/round-trip/malformed matrixkv-persistence-lmcache.mdANCHOR-BACKFILLCLAIM-KV-PERSISTENCE-LMCACHE; worker-half guard + CLI selector by CLAIM-DOCS-T2-FIXES
KV-MOONCAKE-STOREMooncakeStoreConnector: Mooncake's distributed KV object store as an external cache pool, over the landed KV-CONNECTORS W5 seam. SPEC COMMITTED 2026-08-10 (#287); split out of KV-CONNECTORS, whose blanket "Mooncake NOT SCHEDULED" verdict conflated the P2P connector with the store connector. Two findings reopen it. (1) Mooncake is native C++, so we LINK it instead of reimplementing a wire. mooncake-store/include/client_service.h exposes mooncake::Client (Create/Get/BatchGet/Put/BatchPut/IsExist/Query/Remove/RegisterLocalMemory/MountSegment) and mooncake.store.MooncakeDistributedStore — the object vLLM imports — is a pybind wrapper (pyclient.h) over that class; the Transfer Engine also ships a pure C ABI (transfer_engine_c.h). This inverts the LMCache cost shape, where a Python-only library forced the from-scratch lm:// codec (remote_protocol.cpp 201 lines + remote_client.cpp 313 lines). (2) The single-node TCP configuration is gateable on hardware we havemooncake_master --port 50051 with "protocol": "tcp", "mode": "embedded" needs no RDMA NIC, and is the same gate shape KV-EXTERNAL-CACHE already runs against a live lmcache.v1.server. The seam needs NO change: the std::nullopt third state, the load_async flag, build_connector_meta, delay_free ownership, SupportsHMA and REGISTER_KV_CONNECTOR_WITH_WORKER are all already on KVConnector. Deviations recorded in the spec: upstream's LookupKeyClient/LookupKeyServer ZMQ RPC collapses to a direct call (their scheduler and worker are separate PROCESSES; ours are not), and upstream's PYTHONHASHSEED=0 requirement does not apply to us (deterministic hashes since KV-OFFLOAD W1 — we are strictly better on that axis). SPEED IS AN OPEN AXIS, NOT A CEILING: the RDMA/GPUDirect zero-copy-into-paged-blocks path that is the whole point of this connector is UNMEASURABLE for want of a fabric on any box we own (spec §Gates G5), and the loopback-TCP arm is expected noise-dominated. Out of scope and dispositioned: MooncakeConnector/P-D, MultiConnector composition, the SSD enable_offload tier, standalone-store mode, cross-layer block packing, multi-replica steering, and TP>1/PCP/DCP sharded keys. W0 is a genuine go/no-go link spikeT2registry vllm/distributed/kv_transfer/kv_connector/factory.py:224; connector vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/connector.py; key format .../store/data.py:80,100,116,137,158; token→key/address map .../store/data.py:188,197,241; scheduler hooks .../store/scheduler.py:73,120,155,343,367; config schema + client construction .../store/worker.py:106,1017-1037; buffer registration + stride layout detection .../store/worker.py:1237; batch transfer .../store/worker.py:698,911; existence probe .../store/worker.py:604,1532; async issue point .../store/worker.py:1367; lookup RPC (NOT ported) .../store/worker.py:1607,1686; operator surface docs/features/mooncake_store_connector_usage.md. Mooncake side mooncake-store/include/client_service.h, pyclient.h, mooncake-transfer-engine/include/transfer_engine_c.h (revision pinned at W0). No upstream test runs without the mooncake package--mooncake-store-connector.mdSPIKECLAIM-MOONCAKE-STORE
KV-EVENTSBlock create/evict event publication (BlockStored / BlockRemoved / AllBlocksCleared, ZMQ publisher, enable_kv_cache_events default off). W1 DONE 2026-07-27 (CLAIM-ROADMAP-D4-KV-EVENTS) — event GENERATION + PAYLOAD ported and gated. The event data types (kv_events.py:25-121) + the msgpack payload encoder (byte-exact vs msgspec.msgpack.Encoder(), verified against msgspec 0.21.1 on the 1:1 upstream structs, BOTH the default int-truncated hash form and the raw-bytes form) + the emission at the BlockPool store/remove/clear sites are landed, guarded by enable_kv_cache_events (default OFF ⇒ default path byte-identical) + a NullEventPublisher/CollectingEventPublisher seam faithful to --kv-events-config. W3 DONE 2026-08-11 (#352) — the events are now REACHABLE. The Scheduler builds its publisher from --kv-events-config (a null config, what every existing call site passes, resolves the enable flag to the false it used to hard-code), drains kv_cache_manager->take_events() at the end of update_from_output and publishes one KVEventBatch{ts=wall clock, events} per step, and shutdown() reaches the publisher. SamplingParams::extra_args (string-valued slice of upstream's dict[str, Any]) carries kv_cache_report_mode onto Request, and KVCacheManager::get_computed_blocks fires emit_cached_block_events per group under report_mode=="full" — so a prefix-cache HIT re-reports its reused blocks, which is what a prefix-cache-aware router actually consumes. RED-first in two stages: the API absent (compile RED, 14 errors), then the API present with the four behaviours absent (5/12 cases, 5 assertions RED); GREEN 12/12, 105 assertions. DEFERRED (honest residual): the LIVE ZMQ transport (PUB/ROUTER sockets, replay buffer, publisher thread, DP port offset) is stubbed behind the seam (EventPublisherFactory throws loudly on "zmq") — it needs a third-party socket library that does not exist under third_party/, a dependency decision rather than an implementation one. Also deferred, each recorded at its call site: the connector leg of the drain (scheduler.py:1903-1910 — our OffloadingEvent is a different type owned by KV-OFFLOAD), vllm_xargs (so report_mode is reachable from the C++ engine API but not yet over HTTP), and DP aggregation. Found and filed, not silently fixed: #353, KVEventsConfig has no PostInit, so an enabled config with an unset publisher throws unknown event publisher '' instead of resolving to zmq per kv_events.py:50-52. Optional int-truncated block hashes (VLLM_KV_EVENTS_USE_INT_BLOCK_HASHES, upstream DEFAULT True) narrow the digest to its low 64 bits — ported. SPIKE context (2026-07-22): the scaffolding pre-existed (placeholder KVCacheEvent, always-empty take_events, marked-out emission no-ops), so this was a bounded fill-in — KVCacheEvent is an empty placeholder struct, take_events() returns an always-empty queue, and the three emission points inside cache_full_blocks / _remove_cached_block_hashes / reset_prefix_cache are marked-out no-ops, so this is a bounded fill-in rather than a fresh port. Optional int-truncated block hashes (VLLM_KV_EVENTS_USE_INT_BLOCK_HASHES) narrow the digest to its low 64 bitsT2vllm/config/kv_events.py:11-52; event classes vllm/distributed/kv_events.py:48-108,278,505; emission vllm/v1/core/block_pool.py:340-356; vllm/v1/core/kv_cache_manager.py:121,149; scheduler wiring vllm/v1/core/sched/scheduler.py:154,1791,1802-1805; hash truncation vllm/v1/core/kv_cache_utils.py:79-82; tests tests/v1/core/test_prefix_caching.py:2040,2170,2228,2282,2368,2405types + encoder + publisher include/vllm/distributed/kv_events.h + src/vllm/distributed/kv_events.cpp; ExternalBlockHash/maybe_convert_block_hash include/vllm/v1/core/kv_cache_utils.h + src/vllm/v1/core/kv_cache_utils.cpp; emission src/vllm/v1/core/block_pool.cpp (cache_full_blocks store, _emit_block_removed_events/_maybe_evict_cached_block remove, reset_prefix_cache clear, emit_cached_block_events, _build_block_stored_event); KVCacheEvent alias include/vllm/v1/core/block_pool.h; W3 envelope ctor + publisher + per-step drain/publish + shutdown src/vllm/v1/core/sched/scheduler.cpp:119,153,173,1020, seam + members include/vllm/v1/core/sched/scheduler.h:134,231,249,357; W3 report_mode SamplingParams::extra_args include/vllm/sampling_params.h:251, Request::kv_cache_report_mode include/vllm/v1/request.h:247 derived in src/vllm/v1/request.cpp:71, reuse emission src/vllm/v1/core/kv_cache_manager.cpp:148 gated on the retained flag include/vllm/v1/core/kv_cache_manager.h:247tests/vllm/v1/test_kv_events.cpp (6 cases / 62 assertions: byte-exact msgpack ×2 + store/reuse/evict/reset SEQUENCE + RED-first); default-off + APC unchanged tests/vllm/v1/test_block_pool.cpp 132/132, tests/vllm/v1/test_prefix_cache_stats.cpp 36/36 — anchor tests/vllm/v1/test_kv_events.cpp:91; W3 the same target grows to 12 cases / 105 assertions (envelope through a real scheduler step, empty-step publishes nothing, shutdown, extra_args -> report_mode, the "full" reuse re-report vs the "incremental" control, and scheduler-level default-off inertness) — anchor tests/vllm/v1/test_kv_events.cpp:482; W3 regression tests/vllm/v1/test_scheduler.cpp 36/423, tests/vllm/v1/test_llm_engine.cpp 23/450, tests/vllm/v1/test_block_pool.cpp 14/132, tests/vllm/v1/test_kv_cache_manager.cpp 10/74, tests/vllm/v1/test_async_scheduler.cpp 7/63; full CPU ctest 368/369 at -j 6, and 369/369 once test_openai_conformance (a known load-starver) is re-run serially at 23/23kv-events.md; prefix-prompt-caching-parity.mdACTIVECLAIM-ROADMAP-D4-KV-EVENTS
KV-MLA-SPECLatent MLA KV specificationT2vllm/v1/kv_cache_interface.py:363--planned: specs/mla-kv-spec.mdINVENTORIED-
KV-CROSS-ENCODER-SPECSCrossAttentionSpec and EncoderOnlyAttentionSpec KV interface specs (ATTN-ENCODER-CROSS covers backends only); carried from porting-inventory §2 (T2) at the v1 foldT2vllm/v1/kv_cache_interface.py:710,717--planned: specs/encoder-cross-kv-specs.mdINVENTORIED-
KV-SIZINGGPU memory utilization and block-count overridesT0vllm/config/cache.py:68,87,168; tests/v1/core/test_kv_cache_utils.py:2224,2303fixed inputs src/vllm/entrypoints/model_loader.cpp:117,129; watermark src/vllm/v1/core/kv_cache_manager.cpp:118watermark only tests/vllm/v1/test_kv_cache_manager.cpp:298planned: specs/kv-sizing.mdPARTIAL-
KV-WARMUP-PROFILEDummy runs, warmup, and startup memory profiling that derive the KV budget (KV-SIZING covers the sizing knobs only); carried from porting-inventory §3 (T0 there) at the v1 foldT0vllm/v1/worker/gpu_worker.py::determine_available_memory; vllm/v1/worker/gpu/model_runner.py::profile_run; vllm/v1/worker/gpu/model_runner.py::model_memory_usage--planned: specs/warmup-memory-profiling.mdINVENTORIED-
ENG-EXPERT-STREAMExpert streaming from disk: bank-only routed-MoE weights paged into fixed contiguous Marlin slots after logical-expert→slot remap (low-concurrency capacity mode; surpass-track — inference-time disk expert paging is ABSENT in pinned vLLM)T2absent in-pin: vllm/model_executor/offloader/uva.py:21 (CPU-blanket UVA only), vllm/model_executor/offloader/prefetch.py:557-560 (cpu-only); design reference antirez/ds4 (ds4_metal.m, ds4_cuda.cu, ds4_ssd.c); local dense-stride constraint src/vt/cuda/marlin/libtorch_stable/moe/marlin_moe_wna16/marlin_template.h:543-550--expert-streaming.mdREADY-
ENG-WEIGHT-OFFLOADInference-time CPU weight offload mirror floor: UVA cpu_offload_gb per-parameter offload with pinned+zero-copy views and opt-in name-segment targeting (cpu_offload_params), plus layer-group PrefetchOffloader; v1-supported at the pinT2vllm/config/offload.py:23,34-44,47-76; vllm/model_executor/offloader/uva.py:64,80-108; vllm/model_executor/offloader/base.py:23-33,46-92,94-125,126-162; install point vllm/v1/worker/gpu_model_runner.py:939 (re-derived at the pin — the previously recorded :445,913 are STALE and now unrelated lines); layer-wrap site vllm/model_executor/models/utils.py:816,824; loader re-offload vllm/model_executor/model_loader/utils.py:160-193; cudagraph seam vllm/compilation/cuda_graph.py:310,324,359 + breakable_cudagraph.py:379,387,421; env vllm/envs.py:278-279,1938-1943; helpers vllm/utils/platform_utils.py:51-57, vllm/utils/torch_utils.py:766-776; upstream lineage: offloader/base.py header records adaptation from SGLang srt/utils/offloader.py; tests tests/basic_correctness/test_cpu_offload.py:9-29, tests/quantization/test_cpu_offload.py:18-64W0a config surface: include/vllm/config/offload.h, src/vllm/config/offload.cpp (backend enum, both sub-configs, Validate() = 2 hard errors + 3 collected warnings, dot-anchored segment match, int(gb*1024**3) truncation, auto-selection order, layer grouping, JSON parse mirroring the kv_transfer_config precedent). UNREACHABLE: nothing constructs one yet. W0b wires it end to end: include/vllm.h offload_config (ABI v21), the C-API parse+Validate()+record in src/capi/vllm_c.cpp, EngineParams::offload_config, and the server --offload-config flag. Still UNREACHABLE by design: the config is validated and recorded, and no weight moves until W2/W5 Totality guard: ModelFactory::supports_weight_offload (defaults FALSE) + RefuseUnsupportedWeightOffload before any weight I/O + VerifyWeightOffloadWasConsulted after load; no model declares support yet, pinned by test. W2a decision: include/vllm/model_executor/weight_offload_policy.h + src/vllm/model_executor/weight_offload_policy.cpp (per-weight offload/not-targeted/budget-exhausted, running byte budget, FromConfig for the UVA arm only). Application seam CHOSEN as the LOADERS, beside GgufKeepQuantPolicy::Route, because a constructed LoadedModel has already allocated its device copy. W1 seam: include/vllm/model_executor/weight_offloader.h + src/vllm/model_executor/weight_offloader.cpp (interface, no-op default, process-global, factory), installed at LoadedEngine::FromModelDir and read at ModelRegistry::Prepare -- our analogue of make_layers, which this tree does not havetests/vllm/config/test_offload_config.cpp 11/11 cases, 126/126 assertions; RED-first captured on a compiling stub (11/11 cases, 51/122 assertions RED, build rc=0 / 0 compile errors); mutation-proven 6/6 with compile status reported per mutation; W0b ABI round-trip tests/capi/test_capi.cpp "offload_config defaults to NULL and is parsed+validated (ABI v21)" 21/21 (7 refusal cases each asserted INVALID_ARGUMENT not MODEL_LOAD, plus the warning-is-not-a-refusal case), mutation-proven 2/2 (drop Validate() -> 3 red; warning-as-throw -> 1 red)weight-offload-uva.mdACTIVECLAIM-WEIGHT-OFFLOAD-W0A
ENG-HYBRID-PLACEMENTHybrid device placement: per-tensor-group device assignment resolved at model build, delivering routed-MoE expert COMPUTE on the CPU backend while attention/dense/router/norms stay on GPU (surpass-track — vLLM has the CPU MoE kernels but selects them platform-wide via current_platform.is_cpu(), so hybrid placement is ABSENT in pin). Moves compute toward the weights, the inverse of ENG-WEIGHT-OFFLOAD/ENG-EXPERT-STREAM; composes with BACKEND-DISTRIBUTED-TP sharding on an orthogonal axis and refuses where they conflict. Issue #149 (CPU-MoE half only)T2absent in-pin (placement): vllm/model_executor/layers/fused_moe/oracle/mxfp4.py:533, oracle/fp8.py:129, oracle/int8.py:53, oracle/int_wna16.py:111, oracle/unquantized.py:97,202, oracle/w4a8_int8.py:40 (all current_platform.is_cpu()); kernels present but platform-gated: vllm/model_executor/layers/fused_moe/experts/cpu_moe.py, cpu_fused_moe.py:398,430, vllm/_custom_ops.py:3790,3803; secondary oracle llama.cpp @ 237ad9b96 (gateable = yes): common/arg.cpp:2451-2478 (-ot/-cmoe/-ncmoe), common/common.h:1046-1054 (LLM_FFN_EXPS_REGEX), src/llama-model-loader.cpp:1158-1160, src/llama-model.cpp:1032, include/llama.h:530, auto-fit common/fit.h:24 + common/fit.cpp:457,485 (TP conflict refused at :181)--hybrid-placement.mdREADY-
ENG-RESIDENCY-CONFIGThe host-RAM→DISK weight-residency tier as a CONFIG surface: a vllm.cpp-original vllm_cpp extension key inside the existing --offload-config document ({"vllm_cpp":{"mmap":{"enabled","prefault"},"expert_stream":{"enabled","slots","slot_bytes"}}}), reaching the loader through EngineParams::weight_residency and installed in LoadedEngine::FromModelDir ahead of all weight I/O. Closes the asymmetry the two rows above created: ENG-WEIGHT-OFFLOAD's device→host tier is configurable and expert-AWARE (cpu_offload_params:["experts"]), while the tier that actually makes Qwen3.8-2.4T-A95B UD-Q1_0 (370 GiB) serve on a 119 GB box was environment-only. The MIRRORED structs are untouched — upstream has no disk tier, so include/vllm/config/offload.h stays a byte-faithful transcription and the extension is vllm.cpp-original by construction. Precedence is env var > JSON config > built-in default, deliberately: the VT_* variables exist so a benchmark arm is switchable without restarting the server, and an A/B in flight depends on it. VT_MOE_EXPERT_STREAM_STATS_EVERY stays environment-only by decision (it changes only a diagnostic cadence — the instrument, not the configuration). Also fixes #1109 in flow. Issue #1110T1ABSENT in-pin, and not a mirror gap: vllm/config/offload.py:12 is Literal["auto","uva","prefetch"] with no disk arm, vllm/model_executor/offloader/uva.py:21 is CPU-blanket UVA and offloader/prefetch.py:557-560 is cpu-only — nothing upstream reads a weight off a file at inference time. Surface SHAPE mirrored from the flag next door: vllm/entrypoints/openai/cli_args.py JSON-object config arguments, parsed and REFUSED at startupinclude/vllm/config/weight_residency.h, src/vllm/config/weight_residency.cpp; field include/vllm/entrypoints/model_loader.h; install src/vllm/entrypoints/model_loader.cpp (LoadedEngine::FromModelDir); flag src/vllm/entrypoints/openai/server_main.cpp; ABI src/capi/vllm_c.cpp; resolve sites src/vllm/model_executor/model_loader/gguf_keep_quant.cpp (VT_GGUF_MMAP), src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp (VT_GGUF_PREFAULT), src/vllm/model_executor/models/qwen3_5.cpp (VT_MOE_EXPERT_STREAM, _SLOTS, _SLOT_BYTES)tests/vllm/config/test_weight_residency_config.cpp (parse, unknown-key REFUSAL, the mirrored config coming out byte-identical from the same document, precedence in both directions, the latch); tests/vllm/entrypoints/test_weight_residency_reach.cpp (FromModelDir and the C ABI install it); tests/vllm/entrypoints/openai/test_serve_residency_config.cpp (the REAL VllmServerMain on a real argv — the suite the reachability mutation deletes the install call site under)weight-residency-config.mdACTIVECLAIM-ENG-RESIDENCY-CONFIG
KV-SGLANG-RADIX-CACHESGLang RadixAttention behavior-parity scope (fuse-or-flag). VERDICT: already FUSED into our APC. SGLang's radix TREE of KV prefixes (token/page-granular trie, longest-prefix match with mid-node split, LRU-over-tree eviction, lock_ref protection, extra_key tenant isolation) is functionally equivalent to our block-hash APC (per-block chain hash, block pool, block-LRU, ref-count, extra_keys). The ONLY behavioral delta is sharing granularity (token/page vs block_size), bounded to one block at the divergence point, already parametrized by our block_size, and output-neutral (APC-ON==APC-OFF token-exact, KV-PREFIX-CACHE W3). A second token-granular trie would be a redundant incompatible abstraction against MIRROR-vLLM ⇒ NO distinct path. The flag --enable-radix-attention is an ALIAS for the APC toggle (enable_prefix_caching); implementation = CLI alias + a C-ABI enable_prefix_caching tri-state field (currently absent from vllm_model_params). SGLang pin v0.5.15 f63458b.T2SGLang mem_cache/radix_cache.py:280 (RadixCache), :217 (TreeNode), :355/:648 (match_prefix/helper), :563 (evict LRU heap), :592/:607 (lock_ref), :136/:191 (page-aligned match); mem_cache/registry.py:83-94 (ChunkCache fallback); server_args.py:755 (--disable-radix-cache), :739 (eviction policy)our APC (== the fused equivalent): src/vllm/v1/core/kv_cache_utils.cpp:259,291; src/vllm/v1/core/kv_cache_coordinator.cpp:260; src/vllm/v1/core/kv_cache_manager.cpp:124; toggle examples/server/main.cpp:185, include/vllm/entrypoints/model_loader.h:76; alias landed (RW1, CLAIM-SGLANG-IMPL): --enable-radix-attention/--disable-radix-attention server aliases for the same enable_prefix_caching tri-state examples/server/main.cpp; C-ABI int32_t vllm_model_params.enable_prefix_caching (0/1/2) ABI v6→v7 include/vllm.h, mapped in src/capi/vllm_c.cppKV-PREFIX-CACHE cache-ON proof reused (tests/parity/test_qwen3_apc_e2e.cpp:235, hits 0.807, token-exact); ABI round-trip tests/capi/test_capi.cpp "enable_prefix_caching tri-state" 9/9 (default 0, valid 0/1/2, out-of-range→INVALID_ARGUMENT); alias adds server-help + C-ABI contract only, NO engine change (RadixAttention is fused into APC)sglang-radixattention.mdANCHOR-BACKFILLCLAIM-SGLANG-IMPL
ENG-EXPERT-STREAM-DEVICEThe DESTINATION half of expert streaming: where a streamed expert slice lives and which platform may read it, so a larger-than-pool GGUF serves on --device cuda instead of refusing at load. ENG-EXPERT-STREAM beside it owns the MECHANISM (cache, streamer, pread filler, host store) and is unchanged by this row. Three waves. W0 is the critical path and the only one that produces a GPU number on hardware this project owns: a probed host_memory_is_device_addressable() predicate lets a unified/integrated platform read slices out of the existing host slot store, while a discrete CUDA device keeps falling through to KqResidentSlice and keeps the #1123 refusal. W0 is FOUR edits rather than one guard, because the slot arm itself calls ResidentWeight (which stages the whole 1.1875 GiB tower on a staging platform, the exact allocation #1123 died on) and because the load-time fit refusal fires before any forward exists to take the slot arm. W1 adds DeviceExpertSlotStore plus the CommitSlot fill contract without which a device slot cannot be filled at all (SlotForWrite is handed straight to ::pread); W2 adds the virtual SlotForRead that makes W1 reachable, since the read today is the CONCRETE HostExpertSlotStore::Slot(). Surpass-track: inference-time disk expert paging is ABSENT in pinned vLLM and no secondary oracle implements it, so the correctness reference is our own CPU arm and the gate is token-exactness against it. Sized: 2790 slices per token at 2,490,368 B is 6.95 GB per token, against 335.62 GiB of *_exps towers and a 119.631 GiB device pool. Issue #1124T2absent in-pin: vllm/model_executor/offloader/uva.py:21 (CPU-blanket UVA over whole parameters), vllm/model_executor/offloader/prefetch.py:557-560 (cpu-only); no secondary oracle either, since llama.cpp -ot/-ncmoe (common/arg.cpp:2451-2478 @ 237ad9b96) moves expert COMPUTE and not slots. Mirrored platform seam this row extends: vllm/platforms/interface.py:914 + vllm/platforms/cuda.py:675 is_integrated_gpu--expert-stream-device-slots.mdACTIVECLAIM-ENG-EXPERT-STREAM-DEVICE-W0

Parallelism and scale-out

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
PAR-TPTensor parallelism. End-to-end spike LANDED 2026-08-08 at the CURRENT pin (task #287): at-pin S1 inventory + landed-vs-claimed audit of the scale-out W1/W2 code (vt::Communicator/TpShard/TpAllReduceSum real; the tp handle dead-ends at the layer boundary and no production loader passes it), S2 decisions (thread-per-rank; additive TP>1 Forward branch, TP=1 byte-identical; ABI field at next bump; per-weight-class shard map), the TP2-on-CPU token-exact gate design, and the ranked TP-W0..W7 plan (TP-W1..W4+W7 CPU-completable)T2vllm/distributed/parallel_state.py:358,1718-1804; vllm/model_executor/layers/linear.py:418,660,1021,1612; vllm/config/parallel.py:124,824-828 @ 555967922include/vt/communicator.h:47; include/vllm/model_executor/models/tensor_parallel.h:26-64; seams dense_attn_block.h:544,555 + qwen3.cpp:104 + dense_weight_loaders.h:137tests/vt/test_communicator.cpp; tests/vt/test_tp_forward.cpp (60/60, RED-verified)tensor-parallelism-spike.md (+ tensor-parallelism.md §2 layer semantics)READY-
PAR-PPPipeline parallelismT2vllm/config/parallel.py:120--planned: specs/pipeline-parallel.mdINVENTORIED-
PAR-EP-EPLBExpert parallelism and EPLBT2vllm/config/parallel.py:162,481-487; vllm/v1/worker/gpu/eplb_utils.py:1--planned: specs/expert-parallel.mdINVENTORIED-
PAR-DPData parallelismT2vllm/config/parallel.py:126-155--planned: specs/data-parallel.mdINVENTORIED-
PAR-SEQUENCE-MOEMoE sequence parallelism without requiring data parallelism, including TP/EP collectives, token padding and CUDA-graph sizing; v0.25.0 reports a 1.9–5.0% end-to-end throughput gainT2vllm/config/parallel.py:642; vllm/forward_context.py:62-108; vllm/distributed/parallel_state.py:1224-1266; vllm/v1/worker/gpu_model_runner.py:3430,3879; tests/kernels/moe/test_moe_layer.py:1359-1509 @ 702f481--planned: specs/sequence-parallel-moe.mdINVENTORIED-
PAR-MULTINODEMulti-node Ray and multiprocessing executor behaviorT3vllm/v1/executor/abstract.py:37; vllm/config/parallel.py:245--planned: specs/multi-node.mdINVENTORIED-

Sampling and generation controls

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
SAMPLE-COREOrdered temperature, top-k/p, min-p, penalties, seed, stop, length, output-kind pipelineT0vllm/v1/sample/sampler.py:20,72,243; vllm/sampling_params.py:264,500; vllm/v1/worker/gpu_input_batch.py:889-963; tests/v1/sample/test_sampling_params_e2e.py:17,25,40,176src/vllm/sampling_params.cpp:25,35,167; src/vllm/v1/sample/sampler.cpp:152,215; src/vllm/v1/worker/gpu/input_batch.cpp:255,344,451; src/vllm/v1/core/sched/utils.cpp:12tests/vllm/test_sampling_params.cpp:13,64,231,265; tests/vllm/v1/sample/test_sampler.cpp:46,78,118,142,165,253; tests/vllm/v1/worker/test_input_batch.cpp (C7 wiring: min_p/min_tokens/logprobs-count reach SamplingMetadata + condense/swap); tests/vllm/v1/test_input_processor.cpp (all_stop_token_ids)sampling-controls-c7.md (SAMPLE-CORE)ANCHOR-BACKFILLCLAIM-ROADMAP-C7
SAMPLE-PHILOXTorch-Philox bit-exact stochastic parityT1vllm/v1/sample/ops/topk_topp_sampler.py:70; vllm/v1/sample/sampler.py:243--planned: specs/philox-rng-parity.mdINVENTORIED-
SAMPLE-LOGPROBSToken logprobs payload end to endT1vllm/logprobs.py:12,157,175; vllm/v1/engine/logprobs.py:29,69,348; vllm/v1/outputs.py:28,38; vllm/v1/core/sched/scheduler.py:1815-1836; vllm/entrypoints/openai/completion/serving.py:652; vllm/entrypoints/openai/chat_completion/serving.py:1114,1141; tests/v1/sample/test_logprobs.py:303include/vllm/logprobs.h (Logprob/LogprobsOnePosition/SampleLogprobs + AppendLogprobsForNextPosition); include/vllm/v1/engine/logprobs.h+src/vllm/v1/engine/logprobs.cpp (LogprobsProcessor); src/vllm/v1/outputs.cpp:24 (LogprobsTensors::slice_request); src/vllm/v1/worker/gpu/runner.cpp:1272 (ModelRunnerOutput.logprobs); src/vllm/v1/core/sched/scheduler.cpp:674 (slice -> EngineCoreOutput.new_logprobs); src/vllm/v1/engine/output_processor.cpp (LogprobsProcessor integration -> CompletionOutput.logprobs); src/vllm/entrypoints/openai/serving_utils.cpp (BuildCompletionLogProbs/BuildChatLogprobs); src/vllm/entrypoints/openai/protocol.cpp (CompletionLogProbs/ChatCompletionLogProbs to_json); src/vllm/entrypoints/openai/serving_{completion,chat}.cpptests/vllm/entrypoints/openai/test_logprobs.cpp:67,103 (serialization vs vLLM oracle, RED-first N vs N+1; LogprobsProcessor accumulation + inertness :137,167); tests/vllm/entrypoints/openai/test_serving.cpp:411,668 (e2e through the CPU engine: logprobs=K + chat top_logprobs, inert-when-off :467). Closing record parity-ledger.md#L741 2026-07-27 W5 row. #231 (2026-08-09): logprobs=-1 crashed the engine — the sentinel was preserved instead of widened, routing live requests into the sampler's raw-vocab arm (sampler.py:122-125), whose empty ids/ranks the scheduler's LogprobsTensors::slice_request (src/vllm/v1/outputs.cpp:31-37, from src/vllm/v1/core/sched/scheduler.cpp:920-924) copies out of a null begin() — SIGSEGV there, one layer BEFORE LogprobsProcessor::UpdateSampleLogprobs, which carries the identical defect but is never reached. (fd9af7d9 landed the fix while attributing the crash to UpdateSampleLogprobs; corrected 2026-08-10 by the record repair, instrumented proof in the spec.) Fixed by mirroring gpu_input_batch.py:434-440 (widen to vocab_size at admission); the recorded -1 deviation is GONE. tests/vllm/v1/test_llm_engine.cpp (full-vocab dict e2e, RED = SIGSEGV in slice_request; finite-k no-regression) + tests/vllm/v1/worker/test_input_batch.cpp (widening at admission, paired and alone) + tests/vllm/entrypoints/openai/test_serving.cpp (chat top_logprobs=-1 e2e, the HTTP path this unblocks; no request-side range is enforced — that is #249) — logprobs-all-sentinel.mdsampling-controls-c7.md (W5)DONEecda3ce1
SAMPLE-PROMPT-LOGPROBSPrompt logprobs end-to-end (runner source + payload); OpenAI echo serialization pendingT1vllm/v1/engine/logprobs.py:121; vllm/v1/worker/gpu_model_runner.py:3842 (_get_prompt_logprobs_dict); vllm/sampling_params.py:303payload path: src/vllm/v1/engine/logprobs.cpp:75,100 (UpdatePromptLogprobs/pop_prompt_logprobs); include/vllm/v1/engine/types.h:129,161 (ModelRunnerOutput.prompt_logprobs_dict, EngineCoreOutput.new_prompt_logprobs_tensors); src/vllm/v1/core/sched/scheduler.cpp:688 (prompt_logprobs_dict slice); src/vllm/v1/engine/output_processor.cpp:224 (RequestOutput.prompt_logprobs). RUNNER SOURCE landed (#223): src/vllm/v1/worker/gpu/prepare_inputs.cpp (StepInputs::prompt_logprob_rows row selection), src/vllm/v1/worker/gpu/runner.cpp (collect_prompt_logprobs + the full-logits route for a step that owes prompt logits), src/vllm/v1/sample/sampler.cpp (Sampler::compute_prompt_logprobs), src/vllm/v1/worker/gpu/input_batch.cpp (num_prompt_logprobs, -1 widened to vocab_size). RESIDUAL: the OpenAI echo + prompt_logprobs response serialization (serving_completion.cpp:350)tests/vllm/entrypoints/openai/test_logprobs.cpp:137,167 (LogprobsProcessor accumulation/inertness over the shared consume path); tests/vllm/v1/test_llm_engine.cpp §9 (8 engine-level cases, RED-first: shape, values cross-checked through the sampled-logprobs path, -1 normalization, chunked-prefill equality, inertness, concurrency, the gather-route DECISION, and a zero-row final chunk in a MIXED batch)prompt-logprobs.mdACTIVECLAIM-SAMPLE-PROMPT-LOGPROBS-W1
SAMPLE-LOGPROB-TOKEN-IDSlogprob_token_ids generative scoring + the logprobs_mode variants (SAMPLE-LOGPROBS covers the payload only); carried from porting-inventory §6 (T1) at the v1 fold. logprobs_mode LANDED (#238): all four modes in Sampler::forward (raw snapshot per mode) and Sampler::sample (processed_out at the two upstream snapshot points); the runtime refusal is GONE. GENERATIVE SCORING LANDED 2026-08-10 (CLAIM-SAMPLE-LOGPROB-TOKEN-IDS, #264): a request may name an EXPLICIT set of vocab ids and get back exactly those plus the sampled token — no logprobs=-1, no full-vocab sort. SamplingParams.logprob_token_ids + the num_logprobs() property; InputBatch tracks the ids by req_id and re-keys them to req_INDEX in make_sampling_metadata; GatherSpecificTokenLogprobs builds the padded [n, max+1] row with the sampled token in column 0, -inf in the padding, and the sampled rank still over the FULL vocab; the snapshot now fires when ONLY logprob_token_ids is set (sampler.py:86), and explicit ids WIN over a logprobs count (sampler.py:133-136). Three consumers that spelled the property as the raw logprobs field are corrected 1:1 (scheduler slice gate, LogprobsProcessor, RequestState::FromNewRequest) — without them a scoring request produced sampler output nothing downstream ever read. Every id is bounds-checked into [0, vocab) (what torch.gather raises on), so issue #249's defect class cannot recur in the new gather; #249's own instance (GatherLogprobs' unbounded k) is untouched. The two features COMPOSE and are gated together: the mode selects WHICH tensor the snapshot holds, the ids select WHICH entries are read out of it. RESIDUALS keeping this PARTIAL: the OpenAI logprob_token_ids request field + /v1/generative_scoring, the logprob_token_ids vocab-range validation (engine-time, like allowed_token_ids'), and the config/CLI/SamplingParams plumbing to select a logprobs_mode from outside the library — the modes are reachable only by constructing a Sampler directlyT1vllm/sampling_params.py:31,278-283,724-729,772-801; vllm/v1/sample/sampler.py:85-93,86,111-136,151-225,255-302; vllm/v1/sample/metadata.py:49; vllm/v1/worker/gpu_input_batch.py:273,443-444,574,934-951; vllm/v1/core/sched/scheduler.py:1815-1821; vllm/config/model.py:82,221include/vllm/sampling_params.h:168 (field + kMaxLogprobTokenIds + num_logprobs()); src/vllm/sampling_params.cpp:38 (property + the two model-config-free validations); include/vllm/v1/sample/metadata.h (field promoted out of the STUB block); src/vllm/v1/worker/gpu/input_batch.cpp:306 (add_request/remove_request/make_sampling_metadata); src/vllm/v1/sample/sampler.cpp:160 (GatherSpecificTokenLogprobs), :310,313,315 (Sampler::forward raw snapshot per mode + the logprob_token_ids snapshot/precedence wiring) and :203,376 (Sampler::sample processed_out); include/vllm/v1/sample/sampler.h:55 (enum semantics) and :95 (sample out-param); src/vllm/v1/core/sched/scheduler.cpp, src/vllm/v1/engine/logprobs.cpp, src/vllm/v1/engine/output_processor.cpp (the num_logprobs() gates)tests/vllm/v1/sample/test_sampler.cpp:405 (4 logprobs_mode cases over one shared logits row — raw_logits unnormalized, raw_logprobs default regression, processed_logits top-k mask, processed_logprobs renormalized over the kept set; RED-first, 3 threw on the refusal) and :522 (exact ids + request order, heterogeneous/absent rows padded to -inf, precedence over a count, out-of-vocab id throws, empty map inert; RED-first) and :706 (the COMPOSITION: explicit ids read out of the PROCESSED snapshot, added at the 2026-08-11 merge because neither PR's base could express it) + tests/vllm/v1/worker/test_input_batch.cpp:752 (req_id → req_INDEX re-key, max_num_logprobs stays unset, removal, inertness) + tests/vllm/test_sampling_params.cpp:363 (num_logprobs() five cases + both validations) + tests/vllm/v1/test_llm_engine.cpp:1128 (e2e: exactly the requested ids plus the sampled token, nothing else)logprobs-mode.md; logprob-token-ids.mdPARTIALCLAIM-SAMPLE-LOGPROBS-MODE; CLAIM-SAMPLE-LOGPROB-TOKEN-IDS
SAMPLE-LOGIT-FILTERSLogit bias, allowed-token IDs, bad wordsT1vllm/sampling_params.py:318,321,337,341,388-413,659-698; vllm/v1/sample/sampler.py:396; vllm/v1/worker/gpu_input_batch.py:446-471; vllm/entrypoints/openai/completion/protocol.py:369-371; tests/v1/sample/test_sampler.py:367,413; tests/v1/sample/test_sampling_params_e2e.py:106,147include/vllm/sampling_params.h+src/vllm/sampling_params.cpp (fields+validation); src/vllm/entrypoints/openai/protocol.cpp (ParseLogitFilters/ApplyLogitFilters clamp); src/vllm/v1/worker/gpu/input_batch.cpp:255,344 (per-slot wiring+condense/swap); src/vllm/v1/engine/input_processor.cpp (bad_words tokenization); src/vllm/v1/sample/sampler.cpp:239; src/vllm/v1/sample/logits_processor/builtin.cpp:41; src/vllm/v1/sample/ops/bad_words.cpp:13,55tests/vllm/v1/sample/test_logits_processors.cpp:121,163,200; tests/vllm/test_sampling_params.cpp (bad_words/allowed_token_ids validation); tests/vllm/entrypoints/openai/test_protocol.cpp (logit_bias clamp+parse); tests/vllm/v1/worker/test_input_batch.cpp (wiring, RED-first); tests/vllm/v1/test_input_processor.cpp (bad_words tokenization)sampling-controls-c7.md (SAMPLE-LOGIT-FILTERS)ANCHOR-BACKFILLCLAIM-ROADMAP-C7
SERVE-COMPLETION-LONGTAILBest-of, echo, suffix, user request fieldsT1vllm/entrypoints/openai/completion/protocol.py:56,67,70; tests/entrypoints/openai/completion/test_token_in_token_out.py:56echo parse only include/vllm/entrypoints/openai/protocol.h:196; src/vllm/entrypoints/openai/protocol.cpp:204,295acceptance-only tests/vllm/entrypoints/openai/test_conformance.cpp:589planned: specs/completions-longtail-fields.mdPARTIAL-
SAMPLE-BEAMBeam search: an OUTER loop over the engine (NOT a core-sampler param). Each step runs ONE decode per active beam (logprobs=2*beam_width, max_tokens=1, the beam temperature), expands each beam to those next tokens (cum_logprob += logprob), keeps the top-beam_width by the length-penalty score get_beam_search_score = cum_logprob / seq_len**length_penalty (seq_len INCLUDES the prompt, −1 when the last token is EOS), retires EOS-terminated beams into completed, and after max_tokens (or once all beams complete) returns the top-beam_width completed beams as multiple outputs (reuses the SAMPLE-N multi-output aggregation seam). The scoring + top-k-beam selection + EOS + length-penalty are DETERMINISTIC ⇒ token-EXACT vs vLLM, gated model-free on a hand-computed toy tree. std::stable_sort DESCENDING reproduces vLLM's sorted(reverse=True) tie behaviour. OpenAI-endpoint use_beam_search is WIRED on both /v1/completions and /v1/chat/completions over BOTH engine seams, REAL vLLM-0.26 surface: the SYNC LLMEngine (BeamSearch, offline.py) AND the PRODUCTION AsyncLLM HTTP server (BeamSearchAsync, online.py) — the server (examples/server/main.cpp) holds an AsyncLLM, so a beam request there now RUNS instead of raising "requires the synchronous engine". BeamSearchAsync drives the AsyncLLM per-beam single-token generate (pre-tokenized overload added to AsyncLLM) and calls the SAME model-free BeamSearchStep/get_beam_search_score — the algorithm is shared verbatim via a template driver body, only the engine object differs (mirrors online.py mirroring offline.py). GATE: BeamSearchAsync returns beams token-IDENTICAL to sync BeamSearch over the same synthetic CPU model (tokens/order/scores/text), for beam_width 1/2/3. CONCURRENCY FINDING: per-step beam decodes are issued SEQUENTIALLY (one isolated request each), byte-identical to the sync driver; online.py's asyncio.gather per-beam CONCURRENT stepping is a NAMED RESIDUAL (AsyncLLM supports concurrent requests — a future throughput optimization, correctness-first here). OTHER RESIDUALS: streaming beam (rejected like upstream), C-ABI beam params, grammar-constrained beam search (structured-output bitmask branch), encoder-decoder/LoRA beamsT1vllm/entrypoints/generate/beam_search/utils.py:18,102,112,137,156; vllm/entrypoints/generate/beam_search/offline.py:58,118,160,193,291-327; vllm/entrypoints/generate/beam_search/online.py:28-220 (the OpenAI-serving beam generator); vllm/entrypoints/openai/completion/protocol.py:260/chat_completion/protocol.py:589 (to_beam_search_params); vllm/entrypoints/openai/completion/serving.py:173-205/chat_completion/serving.py:319-343 (use_beam_search routing); vllm/sampling_params.py:1114 (BeamSearchParams)include/vllm/entrypoints/beam_search.h + src/vllm/entrypoints/beam_search.cpp (model-free core + shared template BeamSearchDrive + BeamSearch(LLMEngine&, …) sync driver + BeamSearchAsync(AsyncLLM&, …) production driver); include/vllm/v1/engine/async_llm.h+src/vllm/v1/engine/async_llm.cpp (pre-tokenized add_request/generate overloads the async beam driver steps on); include/vllm/entrypoints/openai/protocol.h+src/vllm/entrypoints/openai/protocol.cpp (use_beam_search/length_penalty fields + to_beam_search_params, both requests); src/vllm/entrypoints/openai/serving_completion.cpp + serving_chat.cpp (use_beam_search routes to BeamSearchAsync when async-backed, else BeamSearch + set_beam_search_tokenizer); examples/server/main.cpp (wires set_beam_search_tokenizer on the production handlers so beam runs on the HTTP server); CMakeLists.txt — anchor src/vllm/entrypoints/beam_search.cpp:59tests/vllm/entrypoints/test_beam_search.cpp (model-free token-EXACT tree) + tests/vllm/v1/test_llm_engine.cpp (e2e beam over the CPU engine; BeamSearchAsync == sync BeamSearch token-identical for bw 1/2/3) + tests/vllm/entrypoints/openai/test_serving.cpp (endpoint use_beam_search choices IDENTICAL to the direct driver, completion + chat, over BOTH the sync AND the production AsyncLLM engine; to_beam_search_params round-trip; streaming-beam + tokenizer-less async beam rejected) — anchor tests/vllm/entrypoints/test_beam_search.cpp:82sampling-controls-c7.md (SAMPLE-BEAM)ACTIVECLAIM-C7-BEAM-ASYNC
SAMPLE-REASONINGReasoning parsers (<think> reasoning/content split, streamed as reasoning deltas + non-stream reasoning_content) and reasoning-gated grammar integrationT1vllm/reasoning/abs_reasoning_parsers.py:26,213; vllm/reasoning/__init__.py:22 (registry, 28 names); vllm/reasoning/basic_parsers.py:18 (BaseThinking); deepseek_r1_reasoning_parser.py:10; deepseek_v3_reasoning_parser.py:20,83; identity_reasoning_parser.py:17SEAM LANDED (record backfill 2026-07-28 — the seam shipped under da933828/eb9d1291/5fffe7e6 but this row was never advanced): base+registry src/vllm/entrypoints/openai/reasoning_parsers/abstract.cpp:19 + include/vllm/entrypoints/openai/reasoning_parsers/abstract.h:53; BaseThinkingReasoningParser src/vllm/entrypoints/openai/reasoning_parsers/basic.cpp:27; parsers deepseek_r1.cpp, mistral.cpp, minimax_m2.cpp, step3.cpp, olmo3.cpp, think_auto.cpp (auto-detect default); template detection + --reasoning-parser resolve src/vllm/entrypoints/openai/reasoning_parsers/detect.cpp:59; C ABI v5 src/capi/vllm_c.cpp (reasoning_parser); serving src/vllm/entrypoints/openai/serving_chat.cpp (reasoning-before-tools routing, reasoning SSE delta). W1 2026-07-28 (CLAIM-SAMPLE-REASONING): + src/vllm/entrypoints/openai/reasoning_parsers/identity.cpp:8 (passthrough delegate) + src/vllm/entrypoints/openai/reasoning_parsers/deepseek_v3.cpp:9 (thinking-gated: deepseek_v3→Identity / holo2→R1) → 9 registered names. W3 first brick 2026-08-13 (#605, CLAIM-SAMPLE-REASONING): the first ENGINE-BACKED reasoning adapter — include/vllm/entrypoints/openai/reasoning_parsers/parser_engine_adapter.h:54 (ParserEngineReasoningAdapter, ports vllm/parser/engine/adapters.py:35) + Qwen3ParserReasoningAdapter (registered_adapters.py:48, registered under BOTH qwen3 __init__.py:115 and mimo :87) over the already-landed src/vllm/parser/engine/ parser; engine-side overrides src/vllm/parser/qwen3.cpp:30,40 (Qwen3Parser, ports vllm/parser/qwen3.py:201,247,256 — thinking-off passthrough + unpaired-<tool_call> reasoning end; seed_oss now shares this class as upstream does) + ParserEngine::extract_reasoning_streaming / is_reasoning_end(text) src/vllm/parser/engine/parser_engine.cpp:349,361 (parser_engine.py:519,595) → 12 registered namestests/vllm/entrypoints/openai/reasoning_parsers/test_qwen3.cpp:148 (ports tests/reasoning/test_qwen3_reasoning_parser.py: all 10 TEST_CASES fixtures × non-streaming AND streaming, the 5 MULTI_TOKEN_DELTA_CASES, THINKING_DISABLED_CASES, and is_reasoning_end incl. the unpaired-tool-call rule; RED-first) + tests/vllm/entrypoints/openai/reasoning_parsers/test_deepseek_v3.cpp:40 (ports tests/reasoning/test_deepseekv3_reasoning_parser.py: thinking-gated selection + identity passthrough + no-think edge, RED-first) + tests/vllm/entrypoints/openai/reasoning_parsers/test_detect.cpp:105 (pinned name-count, 10→12) + existing test_{base_thinking,deepseek_r1,mistral,minimax_m2,step3,olmo3,detect,think_auto}.cpp + reasoning_test_utils.h (ports tests/reasoning/utils.py)specs/reasoning-parsers.mdANCHOR-BACKFILLCLAIM-SAMPLE-REASONING
SAMPLE-THINKING-BUDGETThinking budget state and logit combinationT1vllm/v1/sample/sampler.py:381-386--planned: specs/thinking-budget.mdINVENTORIED-
SAMPLE-REPETITIONRepetition detection and penalty stateT1vllm/v1/sample/sampler.py:437--planned: specs/repetition-detection.mdINVENTORIED-
SAMPLE-CUSTOM-PROCESSORSCustom logits-processor plugin point — a host-registered per-request callback the sampler invokes each decode step (generated token-ids + a mutable logits view) BEFORE sampling, at vLLM's non-argmax-invariant stage (after allowed_token_ids/bad_words/min_tokens/logit_bias, before penalties). Exposed through the C-ABI (vllm_logits_processor, ABI v8); default (no processor) byte-identical. Mirrors vLLM's SamplingParams.logits_processors structure/ordering; also satisfies SGLang's custom_logit_processor. Residual: single per-request C callback (not a batched plugin graph); no Python-side registration; on the async scheduler the generated-token view is fed by the scheduler (may lag) — the strict token-ids contract is gated at the sampler levelT2vllm/v1/sample/logits_processor/__init__.py:49-97; vllm/v1/sample/logits_processor/interface.py:60; vllm/v1/sample/sampler.py:399; sglang python/sglang/srt/sampling/custom_logit_processor.py:24ABI include/vllm.h:186 (typedef) + :239 (field, v8); include/vllm/logits_processor_callback.h:40; src/capi/vllm_c.cpp:207; include/vllm/sampling_params.h:214; include/vllm/v1/sample/metadata.h:101; src/vllm/v1/sample/logits_processor/builtin.cpp:75 (apply_logits_processors) + include/vllm/v1/sample/logits_processor/builtin.h:59; wired src/vllm/v1/sample/sampler.cpp:308; per-slot src/vllm/v1/worker/gpu/input_batch.cpp:284 + emit :468tests/vllm/v1/sample/test_sampler.cpp:310,353,378 (forces-token EXACT + per-request + inert; RED-first); tests/vllm/v1/sample/test_logits_processors.cpp:236,253,264 (mutate/no-op/null-skip); tests/capi/test_capi.cpp:409 (ABI v8 e2e forces token, fires per step)sampling-controls-c7.md (SAMPLE-CUSTOM-PROCESSORS)ANCHOR-BACKFILLCLAIM-C7-CUSTOM-LOGITS
SAMPLE-ROUTED-EXPERTSRouted-experts return (enable_return_routed_experts per-token expert-routing output); carried from porting-inventory §6 (T2) at the v1 foldT2vllm/v1/outputs.py:281; vllm/sampling_params.py:328--planned: specs/routed-experts-return.mdINVENTORIED-
SAMPLE-NParallel sampling: a request with n>1 fans out into n child sequences sharing the prompt tokens (and its prefill KV via the block-hash APC), each with its own decode state + RNG offset (seeded children get seed+index), aggregated back into ONE RequestOutput carrying n CompletionOutputs (OpenAI: n indexed choices). n==1 (default) never constructs a ParentRequest — byte-identical single-sequence path. Mirrors vLLM's ParentRequest/child-request machinery. Greedy n>1 is rejected exactly as upstream (_verify_greedy_sampling); the determinism gate uses top_k=1 (a legal n>1 config that collapses to the argmax ⇒ every child token-identical to the single greedy result). RESIDUALS: best_of/beam (SAMPLE-BEAM), async-streaming per-child collation via RequestOutputCollector, and the C-ABI n field (needs an ABI bump + multi-output return)T1vllm/v1/engine/parallel_sampling.py:13,52,83,100; vllm/v1/engine/llm_engine.py:270-293; vllm/v1/engine/output_processor.py:217,323-331,720; vllm/sampling_params.py:213,625; vllm/entrypoints/offline_utils.py:561include/vllm/v1/engine/parallel_sampling.h+src/vllm/v1/engine/parallel_sampling.cpp (ParentRequest: get_child_info/get_outputs); src/vllm/v1/engine/llm_engine.cpp (FanOutParallelSampling, the n>1 fan-out, n==1 untouched); src/vllm/v1/engine/output_processor.cpp (parent_req aggregation in make_request_output + parent_requests_ cleanup); include/vllm/sampling_params.h:128 (n); src/vllm/entrypoints/openai/protocol.cpp:398,433 (sp.n)tests/vllm/v1/test_llm_engine.cpp:426 (n>1 fans out into n token-identical deterministic outputs; RED-first 1→n; n=1 inertness) + tests/vllm/entrypoints/openai/test_serving.cpp (n>1 returns n indexed deterministic choices)sampling-controls-c7.md (SAMPLE-N)ACTIVECLAIM-C7-N-SAMPLING
SAMPLE-BEST-OFOpenAI best_of endpoint control: generate best_of sequences (via the SAMPLE-N ParentRequest fan-out — sp.n = best_of) and RETURN the n highest-cumulative-logprob ones, re-indexed 0..n-1. best_of >= n; best_of == n (default) is byte-identical (no fan-out, no re-rank). best_of < n rejected; best_of > 1 under greedy rejected via PostInit (upstream greedy restriction). Ranking needs the per-child cumulative logprob, which our engine accumulates only when logprobs are computed, so best_of>n forces sp.logprobs=0 (the sampled-token logprob; NO user-visible payload). HONEST FINDING: vLLM 0.26 has DROPPED best_of from the live path — NOT on CompletionRequest/ChatCompletionRequest, no SamplingParams.best_of; the only survivor is a vestigial, NEVER-consumed field on BatchChatCompletionRequest (chat_completion/protocol.py:1048). We therefore implement the CLASSIC OpenAI-spec / vLLM-V0 best_of contract, gated on OUR deterministic fan-out (there is no 0.26 best_of oracle). RESIDUALS: streaming/async best_of ride the SAMPLE-N engine coverage; C-ABI best_of; grammar-beam N/AT1vllm/entrypoints/openai/chat_completion/protocol.py:1048 (vestigial best_of); classic OpenAI Completions best_of contract (best_of >= n, return top-n by per-token logprob)include/vllm/entrypoints/openai/protocol.h (best_of field, both requests); src/vllm/entrypoints/openai/protocol.cpp (ApplyBestOf — fan-out + forced ranking logprob + best_of<n reject); include/vllm/entrypoints/openai/serving_utils.h+.cpp (SelectBestOf — top-n by cum logprob, stable, re-index, inert); src/vllm/entrypoints/openai/serving_completion.cpp + serving_chat.cpp (guarded trim) — anchor src/vllm/entrypoints/openai/serving_utils.cpp:211tests/vllm/entrypoints/openai/test_serving.cpp (SelectBestOf unit rank/tie/inert; best_of→sp.n + forced logprob RED-first; best_of<n reject; e2e best_of=4,n=2 returns exactly n ranked choices; unset/==n inertness) — anchor tests/vllm/entrypoints/openai/test_serving.cpp:408sampling-controls-c7.md (SAMPLE-BEST-OF)ACTIVECLAIM-C7-BESTOF-BEAM-API

Structured outputs and tool calling

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
TOOLS-STRUCTURED-COREJSON schema/object, regex, choice, grammar, response formatT0vllm/v1/structured_output/request.py:77; vllm/v1/structured_output/__init__.py:36,204; vllm/v1/structured_output/backend_xgrammar.py:78; tests/entrypoints/llm/test_struct_output_generate.py:214src/vllm/v1/structured_output/request.cpp:12,43; src/vllm/v1/structured_output/manager.cpp:14,67; src/vllm/v1/structured_output/backend_native.cpp:1334; production wiring src/vllm/entrypoints/model_loader.cpp:283 (manager into Scheduler/EngineCore/AsyncLLM); C ABI v2 src/capi/vllm_c.cpp:143 + include/vllm.h:127tests/vllm/v1/structured_output/test_structured_output.cpp:114,352; tests/vllm/v1/structured_output/test_response_format_e2e.cpp:205; tests/capi/test_capi.cpp:669 (production-wired blocking/streaming constraint + exactly-one rejection); native backend testsplanned: specs/structured-outputs.mdPARTIAL-
TOOLS-XGRAMMARxgrammar structured-output backend (vLLM's DEFAULT auto) as a 2nd registerable backend behind the shared seam. W1 landed (CLAIM-TOOLS-XGRAMMAR, 2026-07-29): XgrammarStructuredOutputBackend composes the native matcher (xgrammar's algorithm — pushdown FSM + token-byte trie — already ours portably; §9 decision: mirror portably, do NOT vendor the C++ lib) and adds the xgrammar-FAITHFUL front-end where the two diverge: JSON-schema→EBNF preserving property DECLARATION order (nlohmann::ordered_json) + the any_whitespace ws rule + the basic_* set emitted VERBATIM — closing the whitespace/key-order/exotic-schema parity gap. disable_any_whitespace mirrored (= not any_whitespace). GRAMMAR/REGEX/CHOICE/STRUCTURAL_TAG delegate to the native compile paths. Backend selection mirrored: ResolveStructuredOutputBackend (autoxgrammar, sampling_params.py:1031) + MakeStructuredOutputBackendFactory. RESIDUALS (W2+): optional object properties, strict-compact separators, the has_xgrammar_unsupported_json_features guard + validate_xgrammar_grammar feeding the auto fallback, model_loader.cpp production wiring, GPU oracle parity (DGX offline).T1vllm/v1/structured_output/backend_xgrammar.py:36,78,128 (json_schema_converter.cc @ mlc-ai/xgrammar a32ac89); selection sampling_params.py:932-949,1024-1061, __init__.py:133-165, config/structured_outputs.py:13include/vllm/v1/structured_output/backend_xgrammar.h + src/vllm/v1/structured_output/backend_xgrammar.cpp (XgrammarStructuredOutputBackend, ResolveStructuredOutputBackend, MakeXgrammarBackendFactory, MakeStructuredOutputBackendFactory); include/vllm/v1/structured_output/xgrammar_json_schema.h + src/vllm/v1/structured_output/xgrammar_json_schema.cpp (XgrammarJsonSchemaToEbnf, XgrammarJsonObjectEbnf)tests/vllm/v1/structured_output/test_backend_xgrammar.cpp 6/6 (39 asserts): exact-valid-next-tokens; declaration key order vs native sort (RED-first); disable_any_whitespace; json_object; converter EBNF; auto→xgrammar selection — anchor tests/vllm/v1/structured_output/test_backend_xgrammar.cpp:176xgrammar-backend.mdACTIVECLAIM-TOOLS-XGRAMMAR
TOOLS-STRUCTURAL-TAGFull structural-tag surfaceT1vllm/v1/structured_output/backend_xgrammar.py:108; vllm/tool_parsers/structural_tag_registry.py:238; tests/entrypoints/llm/test_struct_output_generate.py:990src/vllm/v1/structured_output/json_schema_to_gbnf.cpp:415; src/vllm/v1/structured_output/backend_native.cpp:1366; src/vllm/entrypoints/openai/serving_chat.cpp:98tests/vllm/v1/structured_output/test_backend_native.cpp:910,939,952,987; tests/vllm/entrypoints/openai/tool_parsers/test_tool_choice_grammar.cpp:180planned: specs/structural-tag.mdPARTIAL-
TOOLS-GUIDANCE-OUTLINESGuidance, outlines, and LM-format-enforcer backendsT2vllm/v1/structured_output/__init__.py:140-159--planned: specs/guidance-outlines-backends.mdINVENTORIED-
TOOLS-CALLING-COREAuto, required, named tool choice; streaming deltas; Hermes and Qwen3 parsersT0vllm/entrypoints/openai/chat_completion/serving.py:428,688,872; vllm/tool_parsers/hermes_tool_parser.py:34; vllm/tool_parsers/qwen3_engine_tool_parser.py:7src/vllm/entrypoints/openai/serving_chat.cpp:98,224,239; src/vllm/entrypoints/openai/tool_parsers/hermes.cpp:124,180; src/vllm/entrypoints/openai/tool_parsers/qwen3.cpp:13tests/vllm/entrypoints/openai/tool_parsers/test_tool_parsers.cpp:27,121,159; tests/vllm/entrypoints/openai/tool_parsers/test_tool_choice_grammar.cpp:248,260,280; tests/vllm/entrypoints/openai/test_serving.cpp:625,741,903; SELECTION SURFACE 2026-07-24 (CLAIM-DOCS-T2-FIXES) — the bundled OpenAI server no longer hardcodes "hermes"/"": --tool-call-parser and --reasoning-parser (vLLM's own flag names) select any registered dialect, auto runs the same chat-template detection the C ABI uses, none disables, and an unknown name aborts startup listing the registry. The name lists are ENUMERATED from the factories (tool_parser_names() 40 names / reasoning_parser_names() 7), not hand-written at the flag; the whole flag behaviour lives in ResolveToolParserName / ResolveReasoningParserName so it is unit-tested without a server. DEFAULTS REPRODUCE THE OLD HARDCODE EXACTLY (hermes / disabled), so an invocation naming neither flag is unchanged. Anchors: examples/server/main.cpp (flags), src/vllm/entrypoints/openai/tool_parsers/{abstract,detect}.cpp, src/vllm/entrypoints/openai/reasoning_parsers/{abstract,detect}.cpp; tests tests/vllm/entrypoints/openai/tool_parsers/test_detect.cpp, tests/vllm/entrypoints/openai/reasoning_parsers/test_detect.cppplanned: specs/tool-calling.mdPARTIAL-
TOOLS-STREAMING-PARSERUnified streaming parser engine for reasoning and tool calls, including token-ID scanning, coalesced deltas, replay adapters and parser-specific configurationsT1vllm/parser/engine/streaming_parser_engine.py:89; vllm/parser/engine/token_id_scanner.py:29; vllm/parser/engine/incremental_lexer.py:80; vllm/parser/engine/events.py:11,22; vllm/parser/qwen3.py:88; vllm/parser/kimi_k2.py:52; vllm/parser/engine/parser_engine.py:79 (assembly, residual); tests/parser/engine/test_engine.py, test_token_id_scanner.py, test_qwen3.py @ 555967922CORE engine landed 2026-07-27 (CLAIM-ROADMAP-C8-PARSER): include/vllm/parser/engine/{events,parser_engine_config,incremental_lexer,token_id_scanner,streaming_parser_engine,configs,registry}.h + src/vllm/parser/engine/{incremental_lexer,token_id_scanner,streaming_parser_engine,configs,registry}.cpp (scanner + prefix-buffering lexer + transition state machine + JSON-arg brace hold-back + drop-info + qwen3/seed_oss/kimi_k2 configs + unified name->config registry). ASSEMBLY landed 2026-07-27 (CLAIM-ROADMAP-C8-ASSEMBLY): include/vllm/parser/engine/{parser_engine,py_json}.h + src/vllm/parser/engine/parser_engine.cpp (ParserEngine: SemanticEvent -> streaming DeltaMessage + one-shot ExtractedToolCallInformation, held-back streaming-arg prefix, tool_index++, finish() flush, qwen3 <parameter=> arg-converter) + include/vllm/parser/{kimi_k2,parser_manager}.h + src/vllm/parser/{kimi_k2,parser_manager}.cpp (kimi native-header id/name overrides + name->parser dispatch) + assembly fields on parser_engine_config.h/configs.cpp. SERVING-SSE dispatch swap landed 2026-07-27 (CLAIM-ROADMAP-C8-SERVING): src/vllm/entrypoints/openai/serving_chat.cpp (ShapeChatDeltaEngine/ShapeChatMessageEngine/MakeParserEngine + 3 name-selected drive-site branches + ChatSseStream engine member) + include/vllm/entrypoints/openai/serving_chat.h; faithful include_reasoning request field on protocol.{h,cpp}. CONFIG FAMILIES landed 2026-07-27 (CLAIM-ROADMAP-C8-CONFIGS): 5 more engine-backed families ported as additive ParserEngineConfig builders in src/vllm/parser/engine/configs.cpp (minimax_m2_config, glm47_moe_config, deepseek_v4_config, deepseek_v32_config, nemotron_v3_config + _minimax_m2/_glm47/_dsml std::regex arg-converters) + registry.cpp/parser_manager.cpp dispatch + include/vllm/parser/glm47_moe.{h,cpp} (name-.strip() over the existing hooks). CONFIG FAMILIES C8-2 landed 2026-07-27 (CLAIM-ROADMAP-C8-CONFIGS-2): the last 2 deferred families gemma4 + inkling PORTED — added 4 additive assembly-core virtual seams (default-inert for the other 8 families) preprocess_feed (parser_engine.py:210), virtual events_to_delta (:706), virtual single_pass_parse (:645), args_wrapper_keys from _extract_args_value (:1064) + virtual reset/extract_reasoning; src/vllm/parser/engine/configs.cpp (gemma4_config + _gemma4_arg_converter key:value scanner; inkling_config + _inkling_arg_converter JSON-span carver) + include/vllm/parser/{gemma4,inkling}.{h,cpp} (gemma4 _preprocess_feed channel-injection + _events_to_delta thought\n-strip + extract_reasoning; inkling args_wrapper_keys unwrap + _single_pass_parse trailing flush) + registry.cpp/parser_manager.cpp dispatch. JSON-SCHEMA ARG-TYPE COERCION landed 2026-07-28 (CLAIM-C8-ARG-COERCION): _fix_arg_types / _streamable_string_keys / find_tool_properties (parser_engine.py:227,269,365,348) ported over the ALREADY-ported extract_types_from_schema / coerce_to_schema_type helpers (tool_parsers/utils.cpp) — ParserTool now carries the function parameters JSON-schema (threaded from serving_chat.cpp ToParserRequest), so a request whose tools declare typed params (int/number/bool/string/array/null) has its assembled tool_calls[].function.arguments coerced to the declared types in BOTH streaming (parse_delta) and one-shot (extract_tool_calls/parse); no-schema/absent-tools = identity (byte-identical). Additive to parser_engine.{h,cpp} (recursive _coerce_dict/_coerce_value + find_tool_properties) + serving_chat.cpp schema threading; no other TU changed — anchor src/vllm/parser/engine/streaming_parser_engine.cpp:143tests/vllm/parser/engine/test_streaming_parser_engine.cpp (586/586, 8 scenarios) + test_parser_engine_assembly.cpp (..._goldens.inc): 5038/5038 field-for-field over 30 scenarios (streaming DeltaMessage + one-shot extract_tool_calls + non-streaming parse()) vs vLLM 0.26 assembly — scenarios 27-30 (CLAIM-C8-ARG-COERCION) add qwen3 typed-schema coercion (whole+char, days5/activetrue/temp3.14/tags[1,2,3] coerced, unit stays string), qwen3 schema-mismatch (uncoercible "abc" left as-is + nullable "null"->null), kimi_k2 JSON-native "5"->int in extract (converter-less: streaming stays raw, extract coerces — divergence gated); RED-first proven (38 asserts, first boundary qwen3_typed_schema_wholedelta extract tc[0] arguments: identity {"days": "5", …} vs coerced {"days": 5, "unit": "celsius", "active": true, "temp": 3.14, "tags": [1, 2, 3]}); scenarios 10-19 (CLAIM-ROADMAP-C8-CONFIGS) add minimax_m2 / glm47_moe / deepseek_v4 / deepseek_v32 / nemotron_v3, scenarios 20-26 (CLAIM-ROADMAP-C8-CONFIGS-2 2026-07-27) add gemma4 (explicit + elided channel, whole+char) + inkling (think/tool/trailing-text + non-object-args fallback, whole+char), each whole-delta AND char-by-char; RED-first proven for all seams (32 asserts _safe_arg_prefix; 2 asserts glm47 name-.strip(); 13 asserts gemma4 _events_to_delta at gemma4_channel_tool_wholedelta delta[0] reasoning; 5 asserts gemma4 _preprocess_feed at gemma4_elided_channel_wholedelta delta[0] content; 4 asserts inkling args_wrapper_keys at inkling_nonobject_args_wholedelta extract tc[0] arguments; 2 asserts inkling _single_pass_parse at inkling_think_tool_text_wholedelta parse content); serving tests/vllm/entrypoints/openai/test_serving_chat_stream.cpp (..._goldens.inc): 210/210 chunk-for-chunk SSE parity over the 9 scenarios vs vLLM 0.26 chat_completion_stream_generator (role frame + per-delta reasoning/content/tool-call deltas + terminal tool_calls flip + name-selected dispatch), RED-first proven (6 CHECKs, first boundary chunk[1] reasoning-vs-raw-content); goldens byte-reproduced by tools/parity/dump_{streaming_parser_engine,parser_engine_assembly,serving_chat_stream}.py — anchor tests/vllm/parser/engine/test_streaming_parser_engine.cpp:99specs/streaming-parser-engine.md, specs/parser-assembly-c8.mdACTIVECLAIM-ROADMAP-C8-PARSER, CLAIM-ROADMAP-C8-ASSEMBLY, CLAIM-ROADMAP-C8-SERVING, CLAIM-ROADMAP-C8-CONFIGS, CLAIM-ROADMAP-C8-CONFIGS-2, CLAIM-C8-ARG-COERCION
TOOLS-PARSER-BREADTHQwen-Coder XML, Mistral, pythonic, and the remaining --tool-call-parser dialects. RECORD BACKFILL 2026-08-13 (#608 W0) — NO code shipped in this move; the surface below landed incrementally under other rows and was never recorded here, the same defect SAMPLE-REASONING carried before its own W0. Landed: 42 accepted parser names over 38 parser families, the count PINNED by the registry test rather than asserted in prose. Aliases account for the difference: llama3_json/llama4_json → one class, qwen3_coder/qwen3_xml/mimo → one, glm45/glm47 → one. All three families this row names by title are among them (qwen3_coder, mistral, pythonic). Selection is three-way — explicit --tool-call-parser NAME, auto template sniffing over a 27-row ordered marker table, or none; an unknown name throws enumerating the whole registry. Known omission vs the pin, which is why this is PARTIAL and not further: upstream's lazy registry carries 44 names to our 42, and 4 are still upstream-onlyopenai (GptOssToolParser, a declared Harmony STUB that raises on both methods), minimax_m3 (MinimaxM3ToolParser, Rust-crate-backed), cohere_command3 + cohere_command4 (shims over the out-of-tree cohere_melody package, referenced by ZERO recipes, so a usage-driven audit cannot see them). inkling (InklingEngineToolParser) LANDED 2026-08-13 under W1 — it was the only one of the five with a grammar in vLLM source to port. Conversely 2 of our names are absent from upstream's registry at the pin: qwen3 (our local alias for the Hermes-JSON Qwen dialect) and muse_glimmer (muse_glimmer exists in NO vLLM revision in the pin's ancestry — it is decorator-registered at muse_glimmer_tool_parser.py:183 on the UNMERGED vllm#51655, head 075d645af, the off-pin anchor exception recorded in porting-inventory.md §16) — so 44 − 4 = 40 shared, 40 + 2 = 42. nemotron_json, kimi_k3 and ling3 are in NEITHER registry (post-pin; they arrive with the pin advance). W1 is PARTLY landed (inkling done; openai and minimax_m3 remain), and W2 (both Cohere) and W3 (port ToolParserTestConfig as a shared harness) remain owedT1registry vllm/tool_parsers/__init__.py:24-201 (the 44-name _TOOL_PARSERS_TO_REGISTER dict) + :204,210 (register_lazy_tool_parsers); manager vllm/tool_parsers/abstract_tool_parser.py:223,236,318 (ToolParserManager, get_tool_parser, register_module); the upstream-only classes gptoss_tool_parser.py:17, minimax_m3_tool_parser.py:7, cohere_command_tool_parser.py:125,138, plus the LANDED inkling_tool_parser.py:7 over vllm/parser/engine/adapters.py:128 (ParserEngineToolAdapter) and registered_adapters.py:68-70factory src/vllm/entrypoints/openai/tool_parsers/abstract.cpp:73 (get_tool_parser, 42 name branches → 38 classes) + :281 (tool_parser_names, the enumeration the flag's error message is built from); the engine-backed tool face src/vllm/entrypoints/openai/tool_parsers/parser_engine_adapter.{h,cpp} (ParserEngineToolAdapter + InklingEngineToolParser); autodetect src/vllm/entrypoints/openai/tool_parsers/detect.cpp:76 (kToolParserMarkers, 27 ordered rows, unchanged by W1 — inkling is EXPLICIT-ONLY because it has NO jinja chat template upstream, so this table has nothing to match) + :17 (the ORDER MATTERS collision analysis recording which families are deliberately EXPLICIT-ONLY) + :111 (DetectToolParser, first-match with hermes fallback) + :135 (ResolveToolParserName, auto/none/explicit plus the enumerating throw); per-family parsers under src/vllm/entrypoints/openai/tool_parsers/registry pin tests/vllm/entrypoints/openai/tool_parsers/test_detect.cpp:206 — every enumerated name resolves and every marker-table name is registered — with :222 pinning names.size() == 42, so a factory branch added without listing its name fails the suite instead of silently shipping an unreachable dialect; 39 test files under tests/vllm/entrypoints/openai/tool_parsers/ = 35 per-family + 4 cross-cutting (test_detect.cpp, test_tool_parsers.cpp:27 covering hermes+qwen3, test_tool_choice_grammar.cpp, test_structural_tags.cpp), and deepseek_v31 shares test_deepseek.cpp, so all 38 families are covered. NOT a ported common suite: every file is hand-written per parser, so the floor differs per parser — upstream's ToolParserTestConfig is unported (W3)tool-parser-breadth.mdPARTIAL-

Speculative decoding

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
SPEC-MTPQwen3.6 MTP heads, k=1 first. M-mtp-0 CLOSED 2026-07-24: the standalone draft head is oracle-parity-proven on BOTH checkpoints (27B dense + 35B MoE, k=1, vLLM 0.25.0 executable @ pin e24d1b24) - argmax exact on 26/26 unambiguous rows each; the one remaining row per checkpoint is an EXACT oracle top1==top2 tie where vLLM's own argmax and topk disagree and our pick is a tied maximum; logits within the whole-model bound (atol 0.05 + rtol 0.05), 0/216 out-of-tol on both; shared lm_head isolated is bit-exact on the 35B NVFP4 head. I2 scheduler-half LANDED (2026-07-24): host-side spec plumbing + the FROZEN spec-metadata ABI (spec §2.7) - SpeculativeConfig, DraftTokenIds, Request::spec_token_ids/NumTokensWithSpec, populated scheduled_spec_decode_tokens, Scheduler::update_draft_token_ids, take_draft_token_ids seam, EngineCore::post_step, InputBatch::num_accepted_tokens/update_req_spec_token_ids; DEFAULT-OFF and INERT (no SpeculativeConfig => num_lookahead_tokens == 0). I3 verify-half LANDED (2026-07-24): greedy rejection sampler + per-request logits expansion (see SPEC-REJECTION, now ACTIVE). I4 GDN-half LANDED (2026-07-24): the GDN speculative slot path + bit-exact state rollback, the piece BOTH GDN-hybrid gate checkpoints need (see SPEC-GDN-SEGMENTS, now ACTIVE). I5a GDN LAYER ROUTING + runner spec-metadata upload LANDED (2026-07-24, CLAIM-SPEC-MTP-I5A): GdnBlockPaged now routes a pure-spec batch through vt::GdnSpecDecode/vt::CausalConv1dSpecUpdate and the runner uploads I4's six spec device tensors — first sub-increment of the scoped M-mtp-1 (I5a GDN wiring → I5b prepare_prefill → I5c MTP paged propose → I5d config+runner-loop+the 27B token gate, spec §5). DEFAULT-OFF INERT, bit-exact vs the I4 ops, no e2e loop yet. I5b prepare_prefill_inputs LANDED (2026-07-24, CLAIM-SPEC-MTP-I5B, recorded under SPEC-REJECTION): the drafter prefill input-prep host routine (shift-splice + query_len -= num_rejected + last-token index / metadata) — second scoped M-mtp-1 sub-increment, DEFAULT-OFF INERT, unit-gated RED-first, additive. I5d CONFIG + RUNNER LOOP LANDED, PARTIAL (2026-07-25, CLAIM-SPEC-MTP-I5D): --speculative-config JSON parse -> EngineParams::speculative_config; LoadedEngine resolution (ResolveSpecConfig/ResolveMtp, widened KV MakeQwen3_5KVCacheSpec(num_spec>0), BuildMtpDraft, forced sync scheduling, MakeScheduler(spec), EngineCore(check_for_draft=true)); the full runner verify/propose loop (draft splice, hidden-tap capture, GDN builder spec-overload feed, k+1 GDN state-slot remap + widened conv cache + draft-KV alloc, MtpProposePrefill post-sampling, take_draft_token_ids, acceptance telemetry). CUDA -Werror 0 warnings, cutlass-ON banner. SPEC-OFF BYTE-IDENTICAL (all gated on spec_on()): SACRED 27B 235/235, 35B 315/315, Coder 138/138 + unit test_runner 257 / test_mtp_speculator 169 / test_gdn_metadata_builder 483 / test_ops_gdn 3630 ALL PASS. The three-way 27B token gate is NOT yet passing (tests/parity/test_qwen27_spec_decode.cpp RUNS the loop + MEASURES the blocker): the spec-ON engine throws on the FIRST prefill step at gdn_state_gather: working/cache row shapes must match (src/vt/ops.cpp:1773) — I4's spec conv rollback needs the conv row widened to (K-1)+num_spec but the non-spec GDN conv ops assume (K-1). Closing needs widened-cache-aware non-spec GDN conv ops + the MIXED GdnBlockPaged split/merge. Row LEFT GATING at I5e. I5e LANDED 2026-07-25 (CLAIM-SPEC-MTP-I5E) — SPEC-MTP LEAVES GATING. Made the non-spec GDN conv ops widened-cache-aware (mirror vLLM state_len=KERNEL_WIDTH-1 + physical stride_conv_state_tok; leading (K-1) sub-window; byte-identical at num_spec==0, contiguous fast path kept) AND RCA'd the resulting 0-acceptance dead-drafter to the async input-combine overwriting the verify batch's draft position with the committed token (forced off under spec, nullopt-guarded). THREE-WAY 27B GATE PASSES (single-request greedy): our-ON == vLLM --speculative-config mtp greedy == our-OFF token-for-token; acceptance 16/16 drafts accepted, ~16 target steps saved. Spec-OFF SACRED byte-identical (27B 235/235, 35B 315/315, Coder 138/138), test_ops_gdn 3678, compute-sanitizer 0 on the spec step. NOT DONE: MIXED GdnBlockPaged split/merge (concurrency) + throughput A/B are I6. I6 LANDED 2026-07-25 (CLAIM-SPEC-MTP-I6), benchmark_binding=true — the §5 c1 THROUGHPUT GATE, first spec-decode speed number: OURS spec-ON (examples/vllm-bench + an additive --speculative-config flag, production config) vs pinned vLLM 0.25.0 spec-ON (graphed vllm serve --speculative-config mtp + vllm bench serve, enforce_eager=False/FULL_AND_PIECEWISE/inductor; MTP confirmed Resolved architecture: Qwen3_5MTP), SAME {"method":"mtp","num_speculative_tokens":1}, 27B ~/bench/q36-27b-nvfp4-vllm, c1, greedy, 8 real prompts x 256 out, prose + code, idle box one-engine-at-a-time under one flock, 3 reps (cold TTFT discarded), token-identity re-confirmed FIRST (test_qwen27_spec_decode PASS 16/16). RESULT — ours AT/ABOVE vLLM on EVERY measured axis (prose / code): TPOT 66.2/62.95 vs 69.1/65.3 ms (ours ~1.04x faster), output tput 15.10/15.72 vs 14.43/15.13 tok/s (+4.6%/+3.9%), ITL 121.6/121.1 vs 123.2 ms, TTFT(warm) 131/131 vs 151.5/181 ms, acceptance ours 0.85/0.92 vs vLLM 0.838 overall (within noise, live drafter both), peak RSS 28.4 GB ON / 24.8 GB OFF (both inside the 119 GiB pool). Spec helps both (ours 1.52x/1.59x, vLLM 1.51x/1.60x TPOT); ours already ~4% faster spec-OFF. STAYS ACTIVE: the c>1 mixed spec+non-spec GdnBlockPaged split/merge is still refused (needs a row IndexSelect/IndexCopy vt op) + owes a c>1 A/B, and no user-facing supported --speculative-config on the OpenAI server yet (bench flag example-only/additive). Raw logs dgx ~/work/mtp-bench-i6/{results,vresults}. I7 LANDED 2026-07-25 (CLAIM-SPEC-MTP-I7, benchmark_binding=true) — the MIXED spec+non-spec GDN batch (concurrency), the server/CLI --speculative-config, and the c>1 A/B — implementation COMPLETE + at vLLM parity; STAYS ACTIVE for one honest reason (below), NOT a lag. New row op vt::IndexSelect/vt::IndexCopy (CUDA==CPU bit-exact at GDN widths, RED-first); GdnBlockPagedMixedSpec split/merge (mirror qwen_gdn_linear_attn.py:1329-1576) proven MODEL-INDEPENDENTLY bit-exact (mixed == pure spec + pure prefill, 27B/35B, test_qwen3_5_gdn_spec_routing, RED-first by a broken merge); compute-sanitizer 0 on the mixed step + op; server (I5d) + CLI (ABI v6) --speculative-config. c>1 A/B (both spec-ON, same config): ours ON-PAR-OR-ABOVE vLLM at c2/c4/c8 (output tput within ~+/-2%, ours +1.6%/+2.5% c2, +0.9%/+1.7% c4, +0.9%/-1.1% c8 within noise, prose/code; both ~1.5x spec speedup — does NOT go neutral; acceptance 0.84-0.92 vs vLLM 0.835). Why STAYS ACTIVE (honest, not a lag): the DONE criterion's strict token-exact at c>1 clause is a proven MODEL impossibility — the 27B greedy is bf16-batch-nondeterministic (spec-OFF max_seqs 4-vs-1 differs 2/3 short prompts, NO spec involved), affecting vLLM identically, so exact c>1 token identity cannot be met by any correct implementation; c>1 correctness is instead established by the model-independent bit-exact split/merge proof + acceptance parity (near-tie-distributional-gate), with token-exact strict at c1 (I6). No missing work, no lever — the DONE final call is deferred to the user given this criterion ambiguity. SACRED spec-OFF byte-identical 27B 235/235, 35B 315/315, Coder 138/138; CUDA -Werror 0 warnings. Raw logs dgx ~/work/mixed-batch/{cN_results,cN_vresults}. I8 — SPEC-MTPDONE 2026-07-26 (CLAIM-SPEC-MTP-DONE, records-only, ZERO code): the user RATIFIED the deferred c>1 criterion — at concurrency > 1 the DONE bar is the near-tie-distributional form (ours ∈ vLLM's batch-nondeterministic set) + the SPEED delta, NOT strict token-exact (a proven bf16-batch-nondeterminism MODEL impossibility that affects vLLM identically). Both I6-owed DONE items are therefore CLOSED: (1) the MIXED spec+non-spec GdnBlockPaged split/merge (I7, model-independently bit-exact + compute-sanitizer 0) with the c2-c8 A/B on-par-or-above vLLM, and (2) the server + CLI + C-ABI(v6) --speculative-config flag (I5d/I7, examples/server/main.cpp+examples/cli/main.cpp+src/capi/vllm_c.cpp). MTP k=1 spec-decode is COMPLETE and gated: 27B three-way token-exact at c1 (I5e), c1 above vLLM on every axis (I6), c2-c8 on-par-or-above (I7), spec-OFF byte-identical SACRED (27B 235/235, 35B 315/315, Coder 138/138). This transition is byte-identical BY CONSTRUCTION (git diff --stat = records only; ZERO src//include//examples/ touched, so the I5d/I6/I7 GPU gates stand on this exact code). Tracked follow-ons: the 35B Qwen3_5MoeMTP full e2e token gate (M-mtp-2) is now CLOSED — DONE 2026-07-26 (CLAIM-SPEC-MTP-M-MTP-2): three-way token-exact 16/16 vs the live vLLM 0.25.0 oracle (spec-ON AND spec-OFF), acceptance 16/16 both sides, c1 spec-ON 1.19x TPOT / +16.3% output-tput vs spec-OFF (0.908) — MODEL-SPEC-qwen3-5-mtp-qwen3-5-moe-mtp GATINGDONE, so MTP is DONE on BOTH gate models. Remaining spec-decode follow-on: SPEC-DFLASH (oracle-BLOCKED, vllm#40898)T1vllm/v1/worker/gpu/spec_decode/mtp/speculator.py:12; vllm/model_executor/models/qwen3_5_mtp.py:63,129-165,192-301; I5d vllm/engine/arg_utils.py (--speculative-config); vllm/v1/worker/gpu/model_runner.py:1455-1489include/vllm/config/speculative.h; include/vllm/v1/core/sched/scheduler.h; src/vllm/v1/core/sched/scheduler.cpp; include/vllm/v1/worker/gpu/input_batch.h; include/vllm/model_executor/models/qwen3_5_mtp.h:23,58; src/vllm/model_executor/models/qwen3_5_mtp.cpp:271; src/vllm/model_executor/models/qwen3_5.cpp:3336,3359; I5d src/vllm/config/speculative.cpp; src/vllm/entrypoints/model_loader.cpp (ResolveSpecConfig/MakeKVCacheMaybeSpec/ctor wiring); src/vllm/v1/worker/gpu/runner.cpp (splice/tap/GDN spec feed/propose_drafts/take_draft_token_ids/spec-slot remap/draft-KV alloc); examples/server/main.cpptests/vllm/v1/test_scheduler.cpp:1135,1238,1272,1316; tests/vllm/v1/worker/test_input_batch.cpp; tests/vllm/v1/spec_decode/test_mtp_speculator.cpp:201,225,263,299,331 (7/7 cases, 141 assertions); oracle runner tests/parity/test_op_parity.cpp:1373 + focused case :1914 (20/20 assertions, both checkpoints, VLLM_MTP_REQUIRE_CHECKPOINTS=1); goldens tests/parity/goldens/qwen3_5_mtp_head_{27b,35b}/; dump tools/parity/dump_qwen3_5_mtp.py:144; I5d tests/parity/test_qwen27_spec_decode.cpp (three-way gate, RUNS + measures the RCA blocker); I6 examples/bench/{main.cpp,bench_core.h} (additive --speculative-config bench flag + acceptance telemetry); I7 tests/vllm/models/test_qwen3_5_gdn_spec_routing.cpp (mixed == pure spec + prefill bit-exact), tests/parity/test_qwen27_spec_decode_concurrent.cpp, tests/vt/test_ops_gdn.cpp (IndexSelect/IndexCopy); DONE closure ledgermtp-spec-decode.mdDONE72f9fb1
SPEC-MTP-K-GT-1MTP speculation DEPTH (num_speculative_tokens > 1). Ports the autoregressive multi-step propose the k=1 early exit sits in front of, so a configured depth is SERVED instead of silently degraded. Before it, --num-speculative-tokens 3 reserved KV for 3, captured the verify shape at T=4 and stashed ONE draft per request, with no error and no log; a refusal by name landed first and this row removed it in the same flow. MtpProposeDrafts runs the prefill, the k=1 early exit, then prepare_decode_inputs and the k-1 single-token draft decode steps over the draft's own paged KV, with update_draft_inputs recording each step and feeding it forward. Greedy plus accept-if-equal makes the emitted sequence INDEPENDENT of k, so a token-identity gate cannot see a clamped drafter and every depth assertion needs a positive witness beside the identity. The per-depth counters were the FIRST witness and a fresh review proved them BLIND: they report the LENGTH of the emitted draft list, so a propose that runs one forward and pads all k columns satisfies them, and acceptance is zero at every depth on the CPU model, so no acceptance figure separates the arms either. TWO witnesses survive, because one does not cover both failures. spec_mtp_draft_decode_forwards() == spec_mtp_propose_calls() * (k - 1), counted after each draft decode forward RETURNS and guarded by a non-zero call count, catches a propose that SHORT-CIRCUITS or CLAMPS. A third fresh review then proved it does NOT catch PADDING, since a loop that runs every forward and then discards what it sampled increments it honestly. spec_mtp_proposals_with_varied_drafts(), read at the CONSUMER on the array the propose delivered, catches exactly that. NEITHER shows per-column provenance, and neither does a non-zero acceptance count AT DEPTH, which a padded row earns whenever the target repeats a token. The owed DGX gate closes it with a per-depth acceptance RATE against a PADDED CONTROL. The CPU tier therefore proves k drafts are PROPOSED and VERIFIED, never ACCEPTED at depth. DEFAULT unchanged at k=1 (both checkpoints' n_predict). NO speed number at any k>1: the GPU was held by another session for the whole flow, so the DGX three-way at k=2..4 on the 27B and 35B and the matched-k throughput A/B are OWED, as is the bf16 GDN-state arm (the CPU gate runs the f32 arm because vt::CausalConv1dSpecUpdate rejects bf16 off CUDA). Also owed and filed: #1020, a step whose ACTUAL draft count differs from the configured k leaves the captured verify graph silently.T1vllm/v1/worker/gpu/spec_decode/autoregressive/speculator.py:129-274,335-371,374-419,426-471,597-671,674-771 @ 555967922; vllm/config/speculative.py:967-991src/vllm/v1/worker/gpu/spec_decode/mtp/speculator.cpp (MtpProposeDrafts); prepare_decode_inputs.cpp; Qwen3_5MTPModel::GatherHiddenRows (qwen3_5.cpp); GPUModelRunner::propose_drafts + the per-depth counters (runner.cpp, runner.h); the in-memory mtp_weights seam (model_loader.h)test_mtp_depth 5/5, 63 assertions (k=1,2,3,4 through LoadedEngine, greedy tokens identical to spec-OFF, each arm witnessed BOTH by the draft decode forwards the propose RAN and by whether the DELIVERED draft row varied with depth; neither witness shows per-column provenance, which is owed to the DGX gate); test_prepare_decode_inputs 8/8, 33 (both kernel ports + both max_model_len clamps, 5 mutations caught); test_speculative_mtp_depth 4/4, 20; full CPU suite ctest 493 passed / 0 failed / 2 skipped of 495 (the two skips checkpoint-gated and unrelated)mtp-k-gt-1.mdACTIVECLAIM-SPEC-MTP-K-GT-1 (#81)
SPEC-MTP-GGUFMTP speculative decoding from a GGUF TARGET. Today FromModelDir refuses mtp+GGUF outright (src/vllm/entrypoints/model_loader.cpp:717-723) on the original spike's assumption that GGUF exports carry no mtp.* (mtp-spec-decode.md:979-980, "until we re-export GGUFs with the head"). That is stale: llama.cpp's Qwen3.5 converter DOES emit the head, under layer-indexed nextn naming, and our own HfConfigFromGguf ALREADY reads nextn_predict_layers (it just discards the value into the trunk layer count). Gap is a TensorResolver over GgufFile mapping mtp.* onto blk.{L+i}.nextn.* with dequant-to-bf16, one config field, and narrowing the rejection to dflash. ngram+GGUF already works and is untouched. Qwen3.5/3.6 only (the widened spec KV path serves no other arch). NO ABI changeT2llama.cpp (the producer contract; vLLM has no GGUF MTP path) conversion/qwen.py:535-604 _Qwen35MtpMixin (the authoritative mtp.*->nextn remapper + add_nextn_predict_layers); gguf-py/gguf/constants.py:129,910-917,1494-1501; gguf-py/gguf/tensor_mapping.py NEXTN_*G1-G3 LANDED 2026-07-28. HfConfigFromGguf republishes the head depth src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:598 (c.raw["mtp_num_hidden_layers"] = nextn, previously read then discarded); the head loader LoadQwen3_5MTPFromGguf src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:971 (+ decl include/vllm/model_executor/models/qwen3_5_gguf_weights.h:143) reusing the TRUNK helpers OwnNormMinus1/OwnMatmulWeight/OwnBf16/LoadAttnGguf/LoadMoeGguf so the head inherits the GGUF (w+1) norm storage, quantization/residency routing and torch [N,K] shapes; NumMtpLayers/UsesDedicatedEmbeddings exported out of the anon namespace include/vllm/model_executor/models/qwen3_5_mtp.h; rejection narrowed to dflash + a head-less-GGUF check src/vllm/entrypoints/model_loader.cpp and the head attached in the GGUF branch; G4 GREEN + CPU-SPEC-DIVERGENCE FIXED 2026-07-28: root cause src/vllm/model_executor/models/qwen3_5.cpp:3616 sized the GDN state gather/scatter row by (Kw-1) while the speculative persistent row is (Kw-1)+num_spec, so GatherRows/ScatterRows mis-strode the slot AND every channel past the first, corrupting post-prefill recurrent state. Fix = CopyStateRowsStrided (same TU) used by GatherStateF32/ScatterStateF32 when cache.shape[2] != work.shape[2]; the contiguous helpers are kept when the widths agree, so every non-spec path is byte-identical by construction. CPU-only in effect (the fp16/bf16 arm routes through the GdnStateGather/Scatter ops, so CUDA was never exposed; no GPU result affected)tests/vllm/models/test_qwen3_5_gguf_mtp.cpp:109,146,156,184 4 cases, and the split is the 2026-08-21 repair (#1454): the file used to be the env-gated pair ALONE, each opening on a bare return, so with VLLM_MTP_GGUF_MODEL unset it reported test cases: 2 | 2 passed, assertions: 0, Status: SUCCESS!, exit 0 - which is every CI run of this repository, the variable being set nowhere in .github/workflows/. The 18 assertions this cell used to record was the LIVE count and was never once reached in CI. Now :109 and :146 are HERMETIC (KV-only synthetic GGUFs, no weight bytes, 18 assertions on any machine) and pin the arithmetic the old file only NAMED in a comment above CHECK(c.num_hidden_layers > 0): num_hidden_layers + mtp_num_hidden_layers == block_count over 65/1, 25/1 and 28/3 - the third arm separating - nextn from - 1 - plus the head-less arm, where the key is NOT published and NumMtpLayers answering 1 for an absent key is exactly why the invariant cannot be written with that helper alone. :156 and :184 stay env-gated on VLLM_MTP_GGUF_MODEL (so CI stays asset-free) and now SKIP LOUDLY with a MESSAGE naming the variable, as tests/vllm/entrypoints/test_gguf_mmproj_reach.cpp does; :156 re-derives the same invariant from the file's OWN block_count kv. Unset: 4 cases / 18 assertions / Status: SUCCESS! / rc 0. Live on Qwen3.8-27B-Q4_K_M.gguf (block_count 65, nextn_predict_layers 1): 4 cases / 38 assertions / Status: SUCCESS! / rc 0. Mutation-proved on the production line src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:889, both compiling clean and both restored against a pre-taken sha256: = block_count (drop the subtraction) 3/4 cases, 9/18 red, exit 1; = block_count - 1 (the wrong constant) 2/4 cases, 5/18 red, exit 1. The SAME mutations left the PREVIOUS file at 2/2 cases, 0 assertions, SUCCESS!, exit 0. Correctness of the production line is unchanged and was never in question (1a4db5c3c, 493327b4e); this was a test defect. Live-arm content unchanged: depth reaches config.raw; fc is [H,2H] verbatim; 3 norms [H]; head block is full-attention. RED-first BEHAVIOURAL (reverting only the G1 line fails both cases 2/2). Trunk inertness: test_gguf 103, test_gguf_qwen36_loader 99, test_gguf_keep_quant 5958, test_gguf_dequant 215, test_capi 33/232 all unchanged; tests/parity/test_qwen35_gguf_spec_decode.cpp:74,139 - spec-ON == spec-OFF token-exact with 13 proposed/11 accepted, plus an ngram regression guard (widens the cache, never runs the spec conv update) that was token-exact throughout and pinned the widening as innocent. Regression sweep all unchanged: ops_gdn 1825, gdn_metadata_builder 483, gdn_prefill_conv 28, gdn_spec_routing 12, gguf 103, gguf_qwen36_loader 99, gguf_keep_quant 5958, gguf_dequant 215, llm_engine 196, input_batch 163, runner 257, capi 232 GPU CLOSE-OUT + DEVICE-DELTA ATTRIBUTION 2026-07-28 (G5-G7), ledger parity-ledger.md#L800. The GPU end-to-end gate re-run on a from-scratch RELEASE-TARGET build (-DVLLM_CPP_CUDA_ARCHITECTURES=121a, build dir DELETED first; arch VERIFIED by build-cuda/CMakeFiles/vllm.dir/flags.make --generate-code=arch=compute_121a,code=[compute_121a,sm_121a] and by cuobjdump -lelf 20 cubins ALL sm_121a zero sm_75, NOT by CMakeCache.txt, whose CMAKE_CUDA_ARCHITECTURES:STRING=75 is the enable_language(CUDA) compiler-probe default shadowed by the normal variable at CMakeLists.txt:186 - the prior wrong-arch conclusion was that decoy): dgx.casa GB10 under flock $HOME/gpu.lock, 35B A3B NVFP4 GGUF, 2/2 cases, 10/10 assertions, exit 0, spec-ON token-identical to spec-OFF, 13 proposed / 11 accepted, 90.2 GiB peak RSS, 8m01s; re-run on the EXACT committed source 3/3 cases, 10/10 assertions, exit 0, 7m25s, the new probe case SKIPping and adding zero assertions. The CPU-vs-GPU token delta is a MEASURED near-tie, not a defect (it was never this row's bar - spec-ON == spec-OFF WITHIN a device is): NEW double-gated spec-OFF-only probe tests/parity/test_qwen35_gguf_spec_decode.cpp:217 (asset + VLLM_MTP_GGUF_PROBE=1, 20 alternatives per position, 484/484 assertions per arm, GPU then CUDA_VISIBLE_DEVICES= in one flock series) shows both arms picking 11751 at position 0 and forking at position 1 on a BIT-IDENTICAL prefix: GPU rank1 13 -0.773180 over rank2 11 -0.847055 (margin 0.0739 nats), CPU rank1 11 -0.765499 over rank2 13 -0.830374 (margin 0.0649 nats). Each device's pick is the other's rank 2, both ~7x inside the ratified 0.5-nat band, and the cross-device disagreement on the SAME token (0.057 and 0.082 nats) EXCEEDS the margin being decided, so rounding settles it; the 24 texts look unrelated only because positions 2+ cascade off that one coin flip. Margin sweep over all 24 positions: GGUF GPU and GGUF CPU carry ZERO exact ties, minimum margins 0.0482 and 0.0649 nats, and both arms reproduced their sequence across every run. Gate 4 MET on the safetensors sibling of the same quantization run (FromModelDir takes it unchanged): acceptance 12 proposed / 11 accepted vs the GGUF's 13 / 11. That arm, however, FAILS spec-ON == spec-OFF at concurrency 1 and does not reproduce its own spec-OFF sequence run to run, and the probe attributes both to THREE EXACT ties (positions 7, 10, 16, bit-identical logprobs) produced by its 1/16-grid quantized-GEMM logits - which EXONERATES the GGUF arm and opens a recorded, not-root-caused SPEC-MTP item on the safetensors NVFP4 path, not on this row. Gate 3 is NOT APPLICABLE twice over: no F16/F32 head-carrying export exists, and the only same-weights sibling is not token-stable against itself. EVIDENCE RE-ANCHORED 2026-07-29 to a PRODUCTION-CONFIGURED build, because every GPU number above came from a build configured WITHOUT -DVLLM_CPP_CUTLASS_DIR and WITHOUT -DVLLM_CPP_TRITON=ON (the defect CLAIM-27B-GATE-RCA proved, which runs the emulation fp4 GEMM + hand GDN kernels). Re-run from a clean git archive tree of main 3f34534d, build proven correct three ways (configure log has ZERO CUTLASS not found and prints CUTLASS found ... sm120a NVFP4 cutlass GEMM + FlashAttention-2 ... ENABLED for arch(es) [121a] + the vendored sm_121a Triton-AOT lines with MANIFEST hashes OK; cuobjdump -lelf 40 cubins ALL sm_121a, zero sm_75; SACRED test_qwen27_paged_engine 235/235 exit 0, and the build precondition proven to FIRE by recompiling only that TU without the two defines against the same libvllm.a, which throws and exits 1 with 0 assertions). The row PASSES UNCHANGED: tests/parity/test_qwen35_gguf_spec_decode 3/3 cases, 10/10 assertions, exit 0, spec-ON token-identical to spec-OFF, 13 proposed / 11 accepted (identical to the recorded number), 90.26 GiB, 7m13.59s; loader gate 19 assertions on the Qwen3.5-2B and 18 on the 35B A3B, unchanged. ONE recorded finding is RETRACTED by the re-measurement: the CPU-vs-GPU token delta was a BUILD artifact, not a device near-tie cascade. On the production build both devices emit the SAME 24 tokens; the probe shows GPU rank1 11 -0.763897 over rank2 13 -0.824083 where the defective build had rank1 13 -0.773180 over rank2 11 -0.847055, while the CPU arm is bit-identical to the earlier measurement (CUTLASS and Triton are CUDA-only). Zero exact ties in either arm, min margins 0.060186 GPU / 0.064875 CPU, 484/484 assertions per arm. Evidence: docs/BENCHMARKS.md top section, parity-ledger.mdspecs/gguf-mtp-spec-decode.mdDONEedf91449
SPEC-DFLASH-GGUFDFlash speculative decoding from GGUF, two axes: (A) GGUF DRAFT + safetensors target, (B) GGUF target too. llama.cpp master carries a full dflash GGUF contract (arch string dflash, tensors fc/enc.output_norm/output_norm/blk.N.*, KVs dflash.target_layers + dflash.target_hidden_size); the arch is ABSENT from checkouts older than ~2026-07, so a stale tree reads as "no contract exists". The GGUF tensor set omits token_embd/output because the draft SHARES the target's embed+lm_head, which is exactly what LoadDflashDraft already does. Blockers are in the loader, not the model: MakeDflashDraftConfig reads draft_dir/config.json (a GGUF has none), ResolveDflashDraftDir probes for config.json so it cannot see a .gguf, and LoadDflashDraft is typed on std::vector<SafetensorsFile> for the shared bf16 head (the axis-B blocker). Axis A independently shippable. NO ABI changeT2llama.cpp origin/master @ 2026-07-28 (tag era b10158): gguf-py/gguf/constants.py:547,1151,4350; gguf-py/gguf/tensor_mapping.py:1297-1305 (ENC_OUTPUT_NORM<-model.hidden_norm, FC<-model.fc); conversion/qwen.py:351 (mask token via the standard tokenizer KV); convert_hf_to_gguf.py --target-model-dirGD1-GD7 LANDED 2026-07-28 (BOTH AXES COMPLETE and PROVEN end to end on GB10): MakeDflashGgufConfig + LoadQwen3DFlashFromGguf src/vllm/model_executor/models/qwen3_dflash_gguf.cpp:88,227 (+ header), IsDflashGgufDraft + the .gguf branch in ResolveDflashDraftDir/LoadDflashDraft src/vllm/entrypoints/model_loader.cpp:121,222. Goes through the TensorResolver seam (unlike SPEC-MTP-GGUF) because dflash norms are RAW, so the existing LoadQwen3DFlash qkv/gate_up concatenation is reused unchanged. GD4 defect FIXED (model_loader.cpp:238-249): the GGUF branch left config.vocab_size 0 - correct for MakeDflashGgufConfig (the DFLASH arch has no vocab KV and no token_embd) but fatal for the forward, which sizes the shared embedding view as {config.vocab_size, H}, so the first propose threw cuda embedding: empty table (vocab 0). Now back-filled from the target's embed_tokens rows (the condition is on the VALUE, not the draft source, so it generalizes to a GGUF target). Load-level green had hidden it; only GENERATING found it. GD5-GD7 = axis B: SharedHeadSource src/vllm/entrypoints/model_loader.cpp re-expresses the shared bf16 embed_tokens+lm_head seam as a SOURCE and re-types LoadDflashDraft's second parameter - THAT TYPE was the whole axis-B blocker - with the GGUF arm LoadGgufSharedEmbedAndHeadBf16 src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:773 reusing the trunk loader's tied-embedding rule and sidecar-aware dequant instead of restating them; the shared-head load moved into ONE common tail so all four (draft format x target container) combinations run identical code; the dflash half of the GGUF-branch rejection model_loader.cpp is deleted (the mtp half untouched) and the draft load is wired into the GGUF branchtests/vllm/models/test_qwen3_dflash_gguf.cpp:36,84 2 cases / 47 assertions against the REAL published Qwen3.6-27B DFlash draft (env-gated VLLM_DFLASH_GGUF_MODEL, CI asset-free): the +1 target-layer offset undone against the KV read back from the same file, block_size/mask_token present, vocab_size left 0, layer_types cover every block, fc [H, H*num_taps] with nk SET, qkv/gate_up row-concat shapes, embed/lm_head left EMPTY for the target. RED-first BEHAVIOURAL (dropping the -1 fails the offset checks). GD4 e2e gate tests/parity/test_qwen27_dflash_spec_decode.cpp:343 (second case, draft source env-driven via VLLM_DFLASH_DRAFT/_B; asset-gated, CI-inert): on dgx GB10 sm_121a against the Qwen3.6-27B NVFP4 safetensors target, the Q4_K_M GGUF draft and the bf16 z-lab safetensors draft produce token-for-token IDENTICAL DFlash-ON continuations with IDENTICAL accepted/proposed (20/80 on a 24-token prompt, 42/96 on a 48-token prompt), spec-OFF self-reproducible 3/3 and 0 exact ties (min margin 0.197/0.400 nats). Regression: gguf_mtp 19, qwen35_gguf_spec_decode 10, gguf 103, gguf_qwen36_loader 99, gguf_keep_quant 5958, ops_gdn 1825, llm_engine 196, capi 232, runner 257 all unchanged. GD5 unit gate tests/vllm/test_gguf_qwen36_loader.cpp 3 new synthetic-GGUF cases (6 cases / 286 assertions total, CPU and the dgx CUDA build): the untied head really comes from output.weight and not the embedding (distinct fill values), the tied fallback aliases it onto token_embd, the nk flags separate the gather table from the MatmulBT weight, a file with no token_embd is refused. 3-mutant battery, 3 caught (nk flipped, head forced to the embedding, tied forced false). GD7 e2e gate tests/parity/test_qwen27_dflash_spec_decode.cpp third case (targets env-driven via VLLM_DFLASH_TARGET_B; asset-gated, CI-inert): on dgx GB10 sm_121a the Qwen3.6-27B NVFP4 GGUF target + Q4_K_M GGUF draft loads, takes the shared head from the GGUF, generates, and its DFlash-ON continuation is token-for-token IDENTICAL to that same target's spec-OFF (24/24, the STRICT form) with acceptance ALIVE at 14/160; 1 case / 15 assertions, exit 0. The spike's highest risk is EMPTY on this asset, proven not assumed: the 27B NVFP4 GGUF stores token_embd/output as ggml BF16, byte-identical to the safetensors sibling (2,542,796,800 bytes each, ZERO differing), so B1's shared-head read is verbatim, not a dequant. Acceptance IS lower than the safetensors-target arm and is NOT chargeable to the head: the two containers diverge at index 4 with NO speculation, because QUANT-GGUF-NVFP4 is dequant-only so the GGUF target computes in bf16 while the safetensors target runs the true W4A4 kernels. RE-MEASURED 2026-07-29 on a PRODUCTION-CONFIGURED build (CLAIM-GGUF-SPEC-REVERIFY), because every GD4/GD7 GPU number above came from a build configured WITHOUT -DVLLM_CPP_CUTLASS_DIR and WITHOUT -DVLLM_CPP_TRITON=ON. Build proven correct three ways (see the SPEC-MTP-GGUF row; SACRED 27B 235/235, cuobjdump 40 cubins all sm_121a). AXIS B HOLDS EXACTLY: test_qwen27_dflash_spec_decode -tc="dflash axis-B*" 15/15 assertions, exit 0, GGUF-target DFlash-ON token-identical to that target's own spec-OFF 24/24, acceptance 14/160 unchanged, cross-target spec-OFF divergence still at index 4, 81.01 GiB peak RSS, 6m53.08s. AXIS A WAS RED ON THE 48-TOKEN PROMPT (reproducibly, 3 of 3 runs) AND IS NOW CLOSED. The RED was real: cross-format TOKEN identity held on both prompts, but the exact accept-count half of bar (a) failed (arm_a.proposed == arm_b.proposed / arm_a.accepted == arm_b.accepted) because the Q4_K_M draft measured 46/112 against the bf16 z-lab draft's 47/96 (one extra 16-wide propose block, one fewer acceptance, zero token difference), 15/17, exit 1; the 24-token prompt stayed green at 17/17 with both drafts at 15/144. GD9 2026-07-29 root-caused it IN WEIGHT SPACE as ordinary Q4_K_M cost, category (a), not a defect in our GGUF draft path - and the bar's own premise ("Same weights, two containers") was false for the asset it was pointed at. The publishing repo also carries an UNQUANTIZED BF16 GGUF (3,471,497,440 B) beside Q8_0/Q6_K/Q5_K/Q4_K_M, which the spec had recorded as nonexistent; that retired the NOT APPLICABLE on gate 2. CPU gate tests/vllm/models/test_qwen3_dflash_gguf.cpp third case (asset-gated VLLM_DFLASH_GGUF_BF16_MODEL + VLLM_DFLASH_ST_DIR): LoadQwen3DFlashFromGguf(BF16) is BYTE-IDENTICAL to LoadQwen3DFlash(z-lab shards) on all 58 tensors, 302/302 assertions, exit 0, and FUNCTIONALLY RED against the Q4_K_M file (21/302 red, exactly the 21 quantized matmul tensors), so not a vacuous pass. Supporting: our DequantGgufRowToBf16 is bit-equal to gguf-py's gguf.quants.dequantize on the real fc.weight (Q4_K), blk.0.attn_q.weight (Q4_K) and blk.2.ffn_down.weight (Q6_K), zero differing bf16 values; the ladder's mean relative weight error is monotone and uniform with NO outlier tensor (BF16 0, Q8_0 5.6e-3, Q6_K 1.85e-2, Q5_K 3.85e-2, Q4_K_M 7.6e-2); the only numeric config delta is rms_norm_eps at 2.5e-9 relative. Also landed: an off-by-default VT_SPEC_TRACE=1 per-block propose/accept trace in GPUModelRunner::sample_tokens_with_rejection (src/vllm/v1/worker/gpu/runner.cpp). GD10 2026-07-29 CONFIRMED IT END TO END ON GB10 and closed gates 3 and 5. Build proven production-configured three ways (configure log 0 CUTLASS not found; cuobjdump -lelf 40 cubins ALL sm_121a zero sm_75 on both binaries; SACRED test_qwen27_paged_engine 235/235, exit 0, 31.34s, 23.67 GiB). The BF16 GGUF draft reads EXACTLY 47/96, the safetensors draft's own number, at 48 tokens on the discriminating prompt - reproduced 2 of 2 - plus 27/64 = 27/64 at 24 tokens and 15/144 = 15/144 on the second prompt, tokens IDENTICAL throughout, 17/17 exit 0 each time; the Q4_K_M arm reads 46/112 on the SAME binary in the SAME flock series. Restoring only the draft's numeric precision restores the count, so quantization is the whole cause and nothing structural survives. Bar (a) is consequently SPLIT rather than relaxed (tests/parity/test_qwen27_dflash_spec_decode.cpp): tokens stay EXACT unconditionally; accept counts are EXACT on a cross-FORMAT arm and BANDED (abs(d_accepted) <= 2, abs(d_proposed) <= k*2) on a cross-QUANTIZATION one, with the arm chosen by IsQuantizedGgufDraft reading the draft file's ggml types (GgmlTraits().block_elems > 1) rather than by a flag. The band is derived, not picked: measured d_accepted is 0, 0, -1, so the bound is that maximum plus one quantum; and d_proposed = -k * d_accepted EXACTLY once the token streams match (confirmed at -1 / +16), so the proposed bound follows. Mutation-proved non-vacuous: rebuilt at band 0 the Q4_K_M arm is 15/17 exit 1 while the BF16 arm stays 17/17 exit 0 on the exact branch. AXIS B BROADENED from ONE prompt to THREE, strict form green on all: "The capital of France is" IDENTICAL 14/160 (15/15), "Write a Python function that reverses a string:" IDENTICAL 24/64 (15/15), "Photosynthesis is the process by which" IDENTICAL 15/128 (9/9), all exit 0, ~6m30-6m52 and ~81 GiB peak RSS each. The second prompt REFINES the recorded acceptance claim: the safetensors-target arm is ALSO 24/64 there with the two containers' DFlash-ON streams IDENTICAL, so the GGUF target's lower acceptance is prompt-dependent (their spec-OFF streams diverge at index 4 on the first prompt, index 16 on the second) and not a standing penalty; the cause remains QUANT-GGUF-NVFP4 being dequant-only, with the shared head excluded by a byte comparison. Gates 1-5 and 7 MET; gate 6 (speed) PENDING BY DESIGN and not owed - a DFlash-ON throughput A/B between the two target containers is not a fair comparison until a native NVFP4 GGUF GEMM exists. Evidence: docs/BENCHMARKS.md top section, parity-ledger.mdspecs/gguf-dflash-draft.mdDONEc62f2fa3
SPEC-REJECTIONRejection sampler. I3 verify half LANDED (2026-07-24): per-request logits EXPANSION to 1 + k_i rows (StepInputs::cu_num_logits / num_draft_tokens_per_req / expanded logits_indices) plus the GREEDY rejection sampler — accept a draft iff it equals the target argmax at its own position, emit the target argmax on the FIRST mismatch and stop, emit the bonus argmax when all k_i accept, num_sampled = accepted + 1, num_rejected = k_i - accepted (feeds I2's num_computed_tokens rollback and InputBatch::num_accepted_tokens). One additive vt op (kGreedyRejectionSample) with a CPU reference and a CUDA two-phase mirror of upstream's row-argmax + one-thread-per-request accept walk. DEFAULT-OFF and INERT: with no SpeculativeConfig no drafts are ever scheduled, cu_num_logits is arange(num_reqs+1), logits_indices is the pre-change array and the runner never enters the rejection branch. STOCHASTIC/Gumbel, block verification, apply_sampling_params over the expanded batch, and the spec grammar bitmask stay DEFERRED (M-mtp-3). I5b DRAFTER PREFILL INPUT-PREP LANDED (2026-07-24, CLAIM-SPEC-MTP-I5B): the draft-token input splice this row's I3 note deferred to I5 — vllm::v1::prepare_prefill_inputs + its SpecPrefillInputs output struct shift each request's input_ids left one within its query span, splice the just-sampled next token (num_sampled>0 ? last_sampled[idx_mapping[r]] : next_prefill_tokens[...]) into the freed slot, query_len -= num_rejected, and emit last-token index / query_start_loc / seq_lens + CG padding (mirror speculator.py:469-588, k=1 early-exit :236-238). A HOST routine in a NEW spec_decode-tree TU (no new CUDA kernel; mirrors the DEVICE-NEUTRAL prepare_inputs/combine_sampled_and_draft_tokens family — the DGX runner leaf ports the loop to the Triton kernel at I5d), unit-gated test_prepare_prefill_inputs 7 cases / 27 assertions RED-first, DEFAULT-OFF INERT (nothing calls it until I5d), additive by construction. Row stays ACTIVE — the e2e greedy token gate (M-mtp-1) is owed before DONET1vllm/v1/worker/gpu/spec_decode/rejection_sampler.py:43,101-160; rejection_sampler_utils.py:524,564-585,628,828-841,846-849,863-1125; vllm/v1/worker/gpu/model_runner.py:866-898,1065-1077; vllm/v1/worker/gpu/input_batch.py:303-397,408-453; I5b vllm/v1/worker/gpu/spec_decode/autoregressive/speculator.py:469-588,236-238include/vllm/v1/spec_decode/rejection_sampler.h; src/vllm/v1/spec_decode/rejection_sampler.cpp; include/vt/ops.h (kGreedyRejectionSample, vt::GreedyRejectionSample); src/vt/cpu/cpu_sample.cpp (CPU reference); src/vt/cuda/cuda_sample.cu (RejectionRowArgmaxKernel + GreedyRejectAcceptKernel); src/vt/ops.cpp; include/vllm/v1/worker/gpu/prepare_inputs.h + src/vllm/v1/worker/gpu/prepare_inputs.cpp (the expansion); include/vllm/v1/worker/gpu/runner.h + src/vllm/v1/worker/gpu/runner.cpp (step_num_logits, sample_tokens_with_rejection); I5b include/vllm/v1/worker/gpu/spec_decode/autoregressive/prepare_prefill_inputs.h + src/vllm/v1/worker/gpu/spec_decode/autoregressive/prepare_prefill_inputs.cpp — anchor include/vllm/v1/spec_decode/rejection_sampler.h:96tests/vllm/v1/spec_decode/test_rejection_sampler.cpp; tests/vllm/v1/worker/test_prepare_inputs.cpp (expansion + no-draft byte-identity); tests/vt/test_cuda_ops.cpp (CUDA==CPU bit-exact at vocab 248320); I5b tests/vllm/v1/spec_decode/test_prepare_prefill_inputs.cpp (7 cases / 27 assertions, RED-first) — anchor tests/vllm/v1/spec_decode/test_rejection_sampler.cpp:128mtp-spec-decode.md §2.4,§5ACTIVECLAIM-SPEC-REJECTION-I3, CLAIM-SPEC-MTP-I5B
SPEC-GDN-SEGMENTSGDN speculative metadata and slot-snapshot rollback. I4 LANDED (2026-07-24): the spec/non-spec metadata split with decode→prefill reclassification (the #34845 case), the T>1/IS_SPEC GDN recurrence with per-timestep state snapshots, the conv sliding window advancing by the ACCEPTED count, and the k+1 state-slot allocation. DEFAULT-OFF and INERT (num_spec==0num_spec_decodes==0, no shipped kernel branched — both spec kernels are NEW op ids). ROLLBACK PROVEN bit-exact: for every rejection point j the surviving SSM state and conv window are memcmp-identical to running only the accepted prefix through the shipped vt::GdnDecode/CausalConv1dUpdate, at the real 27B (Hv=48) and 35B (Hv=32) GDN dims on CPU and CUDA. MEASURED state cost: one f32 SSM slot = Hv·Dv·Dk·4B ⇒ 144 MiB/req (27B, 48 layers) / 60 MiB/req (35B, 30 layers) per extra slot; k=1 doubles the GDN SSM state. I5a GDN LAYER ROUTING WIRED (2026-07-24, CLAIM-SPEC-MTP-I5A): GdnBlockPaged's num_spec_decodes>0 branch now routes a PURE-spec batch through vt::CausalConv1dSpecUpdate + vt::GdnSpecDecode (mirror qwen_gdn_linear_attn.py:1344-1357,1455-1475), and the runner per-step upload (StepDevInputs/BuildStepDevInputs + the two decode-graph Refresh copies) now carries I4's six spec device tensors, gated by the extended ValidateGdnAttentionMetadata spec contract. DEFAULT-OFF INERT (num_spec_decodes==0 ⇒ stub uploads + the identical non-spec branch). BIT-EXACT vs the I4 ops applied as a token-sequential decode chain, at the real 27B/35B GDN dims, via GdnBlockPagedForTest (tests/vllm/models/test_qwen3_5_gdn_spec_routing.cpp, CPU bit-exact + CUDA on-device); RED-first by a reverted stub (spec recurrence zeroed ⇒ 4/8 fail, maxΔ 1.3-1.6). MIXED spec+non-spec batch refused loudly — lands with I5d's runner loop. Row advances to ACTIVE: the M-mtp-1 e2e greedy token gate (verify/propose runner wiring) is owed before DONE, and SPEC-MTP STAYS GATINGT1vllm/v1/attention/backends/gdn_attn.py:189-326,413-462; fla/ops/fused_sigmoid_gating.py:66-72,103-116,156-166; mamba/ops/causal_conv1d.py:818-1067,1181-1184; qwen_gdn_linear_attn.py:1329-1576; mamba_utils.py:213-234; mamba/abstract.py:55-59include/vllm/v1/attention/backends/gdn_attn.h; src/vllm/v1/attention/backends/gdn_attn.cpp; include/vt/ops.h (kGdnSpecDecode, kCausalConv1dSpecUpdate); src/vt/ops.cpp; src/vt/cpu/cpu_ops.cpp; src/vt/cuda/cuda_gdn.cu; src/vllm/model_executor/models/qwen3_5_common.{h,cpp} (MakeQwen3_5KVCacheSpec); I5a: src/vllm/model_executor/models/qwen3_5.cpp (GdnBlockPaged spec branch, StepDevInputs/BuildStepDevInputs, ValidateGdnAttentionMetadata), src/vllm/model_executor/models/qwen3_5_internal.h (GdnBlockPagedForTest)tests/vllm/v1/attention/test_gdn_metadata_builder.cpp (20 cases / 483 assertions incl. the full upstream GDN_BUILD_TEST_CASES + default-off byte-identity); tests/vt/test_ops_gdn.cpp (reject-at-every-j rollback, CPU + CUDA, real dims); tests/vllm/models/test_model_registry.cpp (k+1 slot / widened-conv sizing + num_spec==0 identity); I5a tests/vllm/models/test_qwen3_5_gdn_spec_routing.cpp (spec-routing bit-exact, RED-first) — anchor tests/vllm/v1/attention/test_gdn_metadata_builder.cpp:83mtp-spec-decode.md §3,§5ACTIVECLAIM-SPEC-GDN-I4, CLAIM-SPEC-MTP-I5A
SPEC-DFLASHBlock-diffusion drafter. READINESS RE-ASSESSED 2026-07-25 (CLAIM-SPEC-DFLASH-READINESS, design-only, DONE) against the LANDED MTP machinery (SPEC-MTP I1..I7). Verdict GREEN, dispatch-ready, NO hardware/oracle/download blocker (spec §0). Refreshed reuse-vs-new map: DFlash gets FREE from landed MTP — the frozen spec-metadata ABI, the greedy rejection sampler (k-general, I3 tested k∈{1,3}), the GDN spec slot path + rollback + mixed spec/non-spec batch (GdnBlockPagedMixedSpec/IndexSelect/IndexCopy, general num_spec), the widened-cache-aware conv ops (I5e), the draft-KV layer pattern (fa_draft), the I5d/I7 runner verify/propose loop, and num_lookahead_tokens=k+1 ALREADY coded (speculative.h:91-108 use_dflash()); EXTENDS the single I5d-pre hidden_tap seam to multi-tap [T,H×taps]; builds NEW the qwen3_dflash drafter, the project's FIRST non-causal in-block attention primitive, context-KV precompute, prepare_dflash_inputs, and the uniform-1+k FULL CG. k>1 verdict: the landed rejection + GDN machinery is MECHANICALLY k-general (no k==1 hardwiring) — DFlash's k=15 blocks need NO mechanism extension, only exercise/validation at scale (D4) + the k+1-slot memory measurement (~2.3 GiB/req 27B GDN state at block-16, the #1 risk, §5). Checkpoint-fit: both z-lab drafts EXIST on HF (27B 1.73 GB / 35B 368 MB bf16, DFlashDraftModel) and FIT the 119 GiB pool trivially (drafts NOT yet on dgx — D0 downloads ≤1.73 GB); the active dgx oracle vllm-oracle-v0.25.0-stage CONSTRUCTS DFlash (registry DFlashDraftModel→qwen3_dflash, speculator dir present) — soft D0 risk = confirm it SERVES DFlash+NVFP4 on sm_121 (non-causal backend; community AEON-7/vllm-dflash container proves the combination runs on GB10). W-plan D0-D6 in the spec. D0+D1 LANDED 2026-07-26 (CLAIM-DFLASH-D0D1) on the ADVANCED pin 555967922/vLLM 0.26.0.dev0 — SPEC-DFLASHACTIVE. D0 UNBLOCKED (vllm#40898 resolved under VLLM_USE_V2_MODEL_RUNNER=1): the mixed-attn z-lab 27B draft CONSTRUCTS + the drafter is ALIVE (acceptance 2.21/8.80/4.75/4.57 > 1, num_spec=16, flashinfer-native fp8-KV, goldens committed); gate FORM measured STRICT MODE-MATCHED (vLLM-ON run-deterministic K>=3 but != vLLM-OFF — the k=16 block verify diverges at bf16 near-ties, so NOT the MTP three-way identity). D1 DF-AUX-TAPS DONE: Qwen3_5AuxTaps + ModelForwardInput::aux_tap route to Qwen3_5{,Dense}Model::ForwardDeviceMultiTap capturing (hidden+res) at target_layer_ids into [T,H×taps] (eagle3 _maybe_add_hidden_state, aux key L+1); config-gated byte-identical off. Unit gate 598 assertions (independent truncated-model reference, RED-first reversed-concat 384 fail); CUDA 697/697 + compute-sanitizer 0; INERTNESS PROVEN — 27B MTP e2e 9/9 + 27B text SACRED 235/235 byte-identical on the new oracle. D2 DF-DRAFT-MODEL CODE LANDED + CPU-GATED 2026-07-26 (CLAIM-DFLASH-D2, kernel row KERNEL-ATTN-DFLASH-BLOCK): the qwen3_dflash draft model (plain 5-layer Qwen3-dense reusing dense_attn_block.h ops), the project's FIRST non-causal / bidirectional attention primitive vt::DFlashBlockAttention (a SEPARATE op — causal kAttention/kPagedAttention byte-identical), the fc aux-combine, mask-embed, per-layer SWA/full resolution, and the z-lab loader. CPU gate GREEN (op 12/12 incl. RED non-causal; model forward 95/95 incl. RED full-layer-causal-flip + block isolation + fc RED); existing causal test_ops_attention 9/9 + test_qwen3_forward 1028 UNCHANGED. D2 GPU PROMOTION GREEN on dgx (CLAIM-DFLASH-D2): CUDA -Werror clean, CUDA==CPU 198412/198412 + compute-sanitizer 0, draft-forward parity vs the REAL vLLM draft (fc rel-L2 0.46%, hidden ≤1.3%, 11 STRICT + 5 near-tie ids), 27B SACRED 235/235 + MTP 9/9 byte-identical — D2 DONE. D3 DF-DRAFT-KV-PREP DONE 2026-07-26 (CLAIM-DFLASH-D3): PrecomputeContextKV + PrepareDflashInputs + ForwardBlockLogitsWithContext (reuse the UNCHANGED D2 kernel via [context;block]); GPU numeric-parity test_qwen3_dflash_kvprep_parity 61/61 (prepare INTEGER bit-exact vs vLLM's Triton kernel, context-KV K/V rel-L2 0.31%/0.26%, 13 STRICT + 3 near-tie = 16/16), CPU 114/114 RED-proven, inertness 235/235 + 9/9 + D2 37/37 byte-identical. D4 DF-ENGINE-INTEGRATION propose brick + dflash config-select CODE LANDED + CPU-GATED 2026-07-26 (CLAIM-DFLASH-D4D5): DflashProposeBlock/SampleDflashBlockDrafts (the non-autoregressive whole-block propose composing D3 ForwardBlockLogitsWithContext + greedy per-mask argmax, anchor not sampled, dflash/speculator.py:300-413) + ParseSpeculativeConfigJson/ResolveDflash accept method:"dflash". CPU gate test_dflash_propose 5/19 GREEN (RED-first anchor-read fails 4/5; brick composes forward+sampler; empty-ctx degenerates to D2; config lookahead k+1). Additive + config-gated ⇒ MTP + non-spec byte-identical BY CONSTRUCTION (git diff --stat = new speculator TU + config accept-list + CMake + test, NO runner/model/loader/scheduler edit). D5 DF-ENGINE-INTEGRATION runner-loop LANDED + e2e RUNS on dgx 2026-07-26 (CLAIM-DFLASH-D5): full verify/propose loop wired — loader loads the SEPARATE z-lab draft (LoadDflashDraft, host bf16 + target-SHARED bf16 embed/lm_head) via a --speculative-config model key + ResolveSpecConfig dflash branch + runner.set_dflash_draft; the verify forward captures the D1 multi-tap (aux_tapForwardDeviceMultiTap) instead of the MTP single tap; propose_drafts_dflash ACCUMULATES the per-request combined-feature context (CombineAuxFeatures(aux_tap)) across steps and honors the num_rejected rollback by appending only the (T_req−num_rejected) accepted-prefix features, then runs DflashProposeBlock (k=16 GDN-spec exercised first time). e2e (test_qwen27_dflash_spec_decode, 4 prompts×32 tok, our-DFlash-ON vs the committed vLLM-DFlash-ON golden): 2/4 STRICT token-exact (fibonacci, three-laws) + acceptance ~ vLLM on ALL 4 (accepted 19/39/29/25 vs golden 17/39/30/25, deltas +2/0/−1/0 — the MANDATORY dead-drafter-trap condition MET). The 2 divergences (France tok11 297211751, 1723 tok12 567488) are SINGLE bf16 near-tie flips (1723 RE-CONVERGES after one token = proven near-tie; France cascades from one flip) — the ratified near-tie ROOT the D0 gate-form anticipated, rooted in the D3-documented inline bf16 context-KV recompute envelope (~0.3-1.3% rel-L2), NOT a wiring bug (proven by the 2 exact prompts + near-exact acceptance + a non-trivial shared prefix). Inertness GREEN on this build: SACRED test_qwen27_paged_engine 235/235 + MTP test_qwen27_spec_decode 9/9 byte-identical; CUDA -Werror clean; NO new CUDA kernel (host orchestration reusing D1/D2/D3-sanitized ops). NOT a clean strict-4/4 pass; STRICT 4/4 token-identity + the speed A/B = D6 (the persistent paged draft-KV bit-matching vLLM's fused context-KV projections + the uniform-1+k FULL CG). Row STAYS ACTIVE (correctness at the ratified near-tie envelope; D6 remains) D6 2026-07-27 (CLAIM-DFLASH-D6) — c1 SPEED A/B DONE + STRICT-irreducibility RCA + CG feasibility (records-only, NO source code): (1) c1 speed A/B (examples/vllm-bench at 361189a7, 8 prose+code prompts×256 tok greedy c1, 2 reps): our DFlash-ON = 2.50x TPOT (40.4 vs 101.2 ms) / 2.48x output-tput (24.4 vs 9.86 tok/s) over our OFF, acceptance 0.22 (3.56/16), rep-stable <1.5%; benchmark_binding=true. vs vLLM-DFlash-ON graphed (same workload): vLLM-DFlash-ON graphed = 28.5 tok/s / 35.1 ms TPOT / acceptance_len 4.30 (same 8 prompts, VLLM_USE_V2_MODEL_RUNNER=1, mm-off, gpu_util 0.30), so OURS IS ~14% BELOW vLLM-DFlash-ON on output throughput (24.4 vs 28.5 tok/s) - both ~on-par at spec-OFF (9.86 vs 9.83 tok/s), but vLLM extracts a larger DFlash speedup (2.90x vs our 2.47x) because its draft step is fully device-resident + CUDA-graphed (ours host-orchestrates 13 downloads/step) + slightly higher acceptance (~4.3 vs ~3.6 draft tokens/step). The DONE speed bar (ours >= vLLM) is NOT met; closing it = the device-resident draft rewrite + FULL CG (D6 part 2). (2) STRICT-4/4 proven bf16-IRREDUCIBLE — the draft KV cache is bf16 not fp8 (torch_utils.py:398 auto→model dtype; the D0 "fp8-KV" was the backend name, not the KV storage dtype), the D3 golden already compares pre-storage bf16 (residual K 0.31%/V 0.26% = sub-ULP kernel noise), and a fused multi-layer KV GEMM is per-element invariant to our per-layer GEMMs ⇒ bit-exact needs vLLM's exact kernels ⇒ the ratified near-tie gate is the FINAL correctness form (no fused-KV code landed). (3) FULL CG BLOCKED on a device-resident draft-path rewrite (the D5 path does 13 device→host downloads/step + host [context;block] interleaving) — the remaining throughput-parity increment (the perf form of persistent-paged-KV + the graph). Inertness by construction (the gated binary is the D5 binary; SACRED 235/235 + MTP 9/9 stand). Evidence tool scripts/spec/vllm_dflash_timing.py. **D7 2026-07-27 (CLAIM-DFLASH-D7) — within-step draft forward made DEVICE-RESIDENT (source-owning): PrecomputeContextKVDevice keeps per-layer K/V on device; ForwardBlockLogitsWithContext builds [context;block] with vt::IndexCopy/IndexSelect (removes ~30 D→H Downloads/step). BIT-IDENTICAL (identity bf16↔f32 round-trips replaced) — e2e test_qwen27_dflash_spec_decode 27/27 SAME tokens (2/4 STRICT + 2/4 near-tie, acceptance 19/39/29/25), SACRED 235/235 + MTP 9/9, CUDA -Werror clean, compute-sanitizer 0 (198412). But the direct old-vs-new A/B = +2.0% output-tput (IN-NOISE) ⇒ D6's "downloads = the ~14% gap" REFUTED by measurement; ours 19.68 tok/s STILL ~33% BELOW vLLM-DFlash-ON 29.2 tok/s (reconstructed 8-prompt set, more prose-heavy); OFF parity our 9.97 ≥ vLLM 9.66. Residual re-attributed: acceptance (ours 2.49 vs vLLM ~3.13 accepted draft-tok/step, bf16-irreducible) + per-step context-KV RECOMPUTE (O(context²), needs the cross-step persistent paged draft-KV store) + eager-vs-graphed. SPEED BAR NOT met; SPEC-DFLASH stays ACTIVE; next = persistent paged draft-KV store → then FULL CG. D9 2026-07-27 (CLAIM-DFLASH-D9) — PERSISTENT PAGED DRAFT-KV LANDED (bit-identical, +22.7% throughput, 0.69×→0.917×); D8 acceptance-ceiling REFUTED; residual = FULL CG ONLY: qwen3_dflash.cpp AppendContextKVHost (project ONLY newly-accepted rows → per-layer bf16 K/V, append to PrecomputedContextKV) + ForwardBlockLogitsWithPrecomputedKV (upload the persistent store, NO re-projection) share the core ForwardWithCtxKVDev with the old recompute; runner.cpp::propose_drafts_dflash swaps the O(context²) per-step recompute (dflash_ctx_feats_) for an append-only per-request dflash_kv_store_ (rollback=don't-append). NO new CUDA kernel; config-gated. BIT-IDENTICAL: CPU test_dflash_propose two new D9 cases = exact float equality vs full recompute; GPU e2e test_qwen27_dflash_spec_decode 27/27 SAME tokens (acceptance 19/39/29/25, same divergences France@11/17×23@12); SACRED 235/235 + MTP 9/9 byte-identical; CUDA -Werror clean. A/B (c1, 8 prose+code×256 tok input-len 512, 2 reps <0.1%, benchmark_binding=true): ours-ON 25.75 tok/s (was D8 20.99, +22.7%) / 38.40 ms TPOT / acc 3.68/step vs vLLM-ON graphed 28.09 / 35.60 / acc 3.31 = 0.917× (~8% below, was 0.69×). Part 1 same-trajectory: on the 2 token-identical-trajectory prompts ours per-step acceptance == vLLM's EXACTLY (fibonacci 7.80/7.80, three-laws 3.571/3.571, ratio 1.00) AND on the A/B ours acceptance (3.68) is HIGHER than vLLM's (3.31) ⇒ D8's 0.80–0.85× "bf16 acceptance ceiling" is a trajectory-divergence CONFOUND, REFUTED. Residual (~8%) = eager-vs-graphed ONLY (ours ON/OFF 2.60× vs vLLM 2.91×, OFF at parity, recompute eliminated, acceptance higher) — NOT an irreducible ceiling; the FULL uniform-(1+k) CG (device paged-KV store + paged attn, new-CUDA multi-file) is the SOLE un-landed increment. SPEC-DFLASH stays ACTIVE (speed not yet ≥ vLLM; residual isolated to FULL CG). D12 2026-07-27 (CLAIM-DFLASH-D12) — A-wire + Part B LANDED + GPU-gated; Part C (capture) remaining; 0.917×: A-wire makes the D11 Part-A device store the PRODUCTION path (runner.{h,cpp} dflash_kv_store_shared_ptr<DflashDeviceKVStore>, MakeDeviceKVStore/AppendContextKVDevice/ForwardBlockLogitsWithDeviceKV; GPU-gated e2e test_qwen27_dflash_spec_decode 27/27 all-exact acceptance 19/39/29/25 + SACRED 235/235 + MTP 9/9 byte-identical, -Werror clean). Part B adds vt::DFlashPagedBlockAttention (OpId::kDFlashPagedBlockAttention), the capture-safe paged kernel with EVERY metadata input a persistent DEVICE tensor and NO function-local host cu_seqlens upload (fixes the cuda_ops.cu:1277-1280 capture-UAF class), gated CPU==CUDA + cross-check vs materialized DFlashBlockAttention test_ops_dflash_paged_block_attn 795648/795648 + compute-sanitizer 0. Speed 0.917× (A-wire eager + Part B not yet wired into the forward); benchmark_binding=false. Part C (static-shape capture + device mask-scatter + BeginCapture/replay + the ≥vLLM c1 A/B) is the SOLE remaining piece; if ours-ON-graphed ≥ vLLM-ON → SPEC-DFLASH DONE. Stays ACTIVE. D13 2026-07-27 (CLAIM-DFLASH-D13) — Part C LANDED + GPU-GATED; capture-correctness PROVEN; c1 throughput NEAR-PARITY (ours 0.978x, ~2% below vLLM); gap CLOSED 0.917x→0.978x; STAYS ACTIVE (≥vLLM bar not yet met): single-file additive change (qwen3_dflash.cpp +368/-58). (C.1) DflashDeviceKVStore → fixed-capacity PAGED cache (per-layer pool [max_pages,16,Hkv,Dh] + identity block_table + seq_lens; append = vt::IndexCopy scatter at slot==abs-pos, bit-identical to the D9/D11 store). (C.2) ForwardPagedBody runs the (1+k) block through the D12 vt::DFlashPagedBlockAttention reading the paged store (no [context;block] materialization, no function-local host uploads); runner P==1 propose routes through it, P>1 bit-identical materialized fallback. (C.3) per-request CUDA GRAPH over the paged draft step (warm-in-step repopulates the shared pool free-list right before BeginCapture — the fix for a cudaMalloc-in-capture Get miss from the intervening 27B target forward — then BeginCapture → ForwardPagedBody → EndCaptureGraph, replay with growing context entering only via in-place seq_lens). Capture-correctness (MANDATORY): test_qwen27_dflash_spec_decode 27/27 with the graph (VT_DFLASH_GRAPH=1) BIT-IDENTICAL to eager (=0) — same divergence tokens (France@11 got[…2972…], 17×23@12 got[…567…]), same acceptance 19/39/29/25 as D5/D7/D9/D12; graph ENGAGED (5 captures C=2048/5/4/15/6, 32+ replays); the token-diff is the capture-safety proof ([[cudagraph-capture-bakes-stack-addresses]]). c1 A/B (one flock series, cold rep discarded, 8 prompts×256 tok): our OFF 10.24 / our ON eager-paged 28.65 (28.69,28.61) / our ON GRAPHED 28.70 (28.70,28.70), TPOT 34.40 / vLLM-ON graphed steady-state 29.35 (tight 3-rep 29.33/29.37/29.33, TPOT 34.07, acc_len 4.44); D9's 28.09 was a colder cross-session outlier — NEAR-PARITY: ours 0.978× (~2% below) on the rigorous same-session band (across sessions ours 28.70 falls inside vLLM's observed 28.09–29.37 range). ON/OFF 2.80× (vLLM ~2.98×), our OFF ≥ vLLM OFF. Per the acceptance rule ("below on any axis = an open gap; near-parity is NOT met"), the ≥vLLM bar is NOT met; STAYS ACTIVE. Residual (data-grounded): NOT acceptance (ours realized ~3.68 accepted draft-tok/step > vLLM's 3.44) and NOT launch/graph (both graphed, CG neutral) — per-step COMPUTE (~2% slower target-step); next lever = nsys both draft steps (--cuda-graph-trace=node), no premature ceiling. ATTRIBUTION (supersedes D9): the CUDA graph is perf-NEUTRAL (+0.3%); the ACTUAL lever was the paged context read (C.1/C.2) removing the D9/D12 per-layer [context;block] IndexCopy materialization of the whole growing context (25.75 D9 → 28.65 eager-paged, +11%) — the roadmap's "the full CG closes the gap" premise is corrected by measurement. Inertness VERIFIED on the capture binary: SACRED 235/235 + MTP 9/9 byte-identical, CUDA -Werror clean, no new kernel (D12 paged kernel already memcheck-0 795648), check-device-leakage not increased (paged path REMOVES the materialized-buffer allocs + host uploads). benchmark_binding=true. Correctness-complete (ratified near-tie); throughput NEAR-PARITY (0.978×, ~2% residual) ⇒ STAYS ACTIVE (the capture-correctness gate is MET; the ≥vLLM speed bar is the sole remaining item, a ~2% per-step-compute residual for an nsys). Anchors: src/vllm/model_executor/models/qwen3_dflash.cpp (DflashDeviceKVStore paged store, ForwardPagedBody, the per-request graph in ForwardBlockLogitsWithDeviceKV). D14 2026-07-27 (CLAIM-DFLASH-D14) — SPEED GATE MET → SPEC-DFLASH DONE: an nsys (--cuda-graph-trace=node) of the graphed spec-on step attributed the D13 ~2% residual to the from-scratch DFlashPagedBlockAttentionKernel draft attention (242.9 ms = 1.8% of GPU time, median 460 us/call over context C500-640, vs vLLM's fused flash draft-attn ~0.15%; BOTH engines run identical cutlass_80_wmma for the draft bf16 GEMMs, so the GEMMs were NOT the gap). Ported it to a WARP-scoped online-softmax variant DFlashPagedBlockAttentionWarpKernel (mirrors the shipped AttentionWarpKernel: one warp per (block-query,head), __shfl_xor butterfly reduction, register accumulator, NO __syncthreads storm; SAME paged/block combined-index read + causal/SWA mask + GQA; default ON, VT_DFLASH_ATTN_BLOCK=1 keeps the bit-identical D12/D13 block kernel for A/B). Draft attn 242.9 → 77.9 ms (3.1x); our-ON c1 28.60 → 29.32 tok/s (+2.5%). FINAL same-session 3-rep A/B (8 prompts×256 tok, cold leg discarded): our-ON graphed 29.42/29.27/29.32 (med 29.32) vs vLLM-ON graphed 29.240/29.247/29.233 (med 29.240) — our WORST rep (29.27) > vLLM's BEST (29.247), NON-OVERLAPPING bands, 1.003× ⇒ the ≥vLLM speed gate is MET. Correctness UNCHANGED (output is exact by spec-decode construction — the target verify is untouched, only which draft proposals are accepted can shift): e2e test_qwen27_dflash_spec_decode 27/27 with graph==eager BIT-IDENTICAL, acceptance 19/39/29/25 unchanged (draft accepted 1629 identical warp-vs-block across the whole A/B set), 2/4 STRICT (France@11, 17×23@12 unchanged); CUDA==CPU test_ops_dflash_paged_block_attn 795648/795648 (warp within the f32 1e-4 / bf16 3e-2 envelope) + compute-sanitizer 0. Inertness SACRED 235/235 + MTP 9/9 byte-identical; CUDA -Werror clean; check-device-leakage not increased. benchmark_binding=true. Block-diffusion drafting is now correctness-complete (ratified near-tie) AND at/above vLLM throughput — this was the roadmap's FINAL open speed item. Anchors: src/vt/cuda/cuda_ops.cu (DFlashPagedBlockAttentionWarpKernel + UseDflashAttnBlockKernel; the D12 block kernel retained as the VT_DFLASH_ATTN_BLOCK=1 reference).T1vllm/v1/worker/gpu/spec_decode/dflash/speculator.py; vllm/model_executor/models/qwen3_dflash.py; vllm/model_executor/models/interfaces.py:1382 (aux value); eagle3_utils.py:41-56 (+1 shift)include/vllm/model_executor/models/qwen3_5.h (Qwen3_5AuxTaps, ForwardDeviceMultiTap); qwen3_5_dense.h; model_registry.h (aux_tap); src/vllm/model_executor/models/qwen3_5.cpp (MaybeCaptureAuxTap/ValidateAuxTapLayerIds/ForwardDeviceMultiTap); qwen3_5_moe.cpp+qwen3_5_dense.cpp (routing); D2/D3 include/vllm/model_executor/models/qwen3_dflash.h + src/vllm/model_executor/models/qwen3_dflash{,_weights}.cpp; D4 include/vllm/v1/worker/gpu/spec_decode/dflash/speculator.h + src/vllm/v1/worker/gpu/spec_decode/dflash/speculator.cpp (DflashProposeBlock/SampleDflashBlockDrafts); D5 src/vllm/entrypoints/model_loader.cpp (LoadDflashDraft/DflashDraft) + include/vllm/entrypoints/model_loader.h; D5 src/vllm/v1/worker/gpu/runner.cpp (set_dflash_draft/propose_drafts_dflash/aux-tap capture) + include/vllm/v1/worker/gpu/runner.h; src/vllm/config/speculative.cpp + include/vllm/config/speculative.h (ResolveDflash + dflash/model parse); D14 warp kernel cuda_ops.cutests/vllm/models/test_qwen27_paged_forward.cpp (multi-tap 598); tests/vt/test_ops_dflash_block_attn.cpp; tests/vllm/models/test_qwen3_dflash_forward.cpp; tests/vllm/v1/spec_decode/test_dflash_kvprep.cpp; tests/parity/test_qwen3_dflash_{draft,kvprep}_parity.cpp; D4 tests/vllm/v1/spec_decode/test_dflash_propose.cpp (5/19, RED-first); D5 tests/parity/test_qwen27_dflash_spec_decode.cpp (e2e 27/27, 2/4 strict + acceptance~vLLM); scripts/spec/d{0,2,3}_dflash_*.py; tests/parity/goldens/dflash_27b{,_draft,_kvprep}/; D6 scripts/spec/vllm_dflash_timing.py (vLLM-DFlash c1 timing); D7 device-resident src/vllm/model_executor/models/qwen3_dflash.cpp (PrecomputeContextKVDevice + ForwardBlockLogitsWithContext via vt::IndexCopy/IndexSelect); D9 persistent paged draft-KV qwen3_dflash.{h,cpp} (AppendContextKVHost/ForwardBlockLogitsWithPrecomputedKV/ForwardWithCtxKVDev/PrecomputedContextKV) + runner.{h,cpp} (dflash_kv_store_/propose_drafts_dflash) + tests/vllm/v1/spec_decode/test_dflash_propose.cpp (2 D9 bit-identity cases); D12 A-wire runner.{h,cpp} (device store as production path) + D12 Part B include/vt/ops.h/src/vt/ops.cpp/src/vt/cpu/cpu_ops.cpp/src/vt/cuda/cuda_ops.cu (kDFlashPagedBlockAttention) + tests/vt/test_ops_dflash_paged_block_attn.cpp (CPU==CUDA + cross-check, 795648/795648 + sanitizer-0); D13 src/vllm/model_executor/models/qwen3_dflash.cpp (fixed-capacity paged DflashDeviceKVStore + ForwardPagedBody + the per-request draft-step CUDA graph in ForwardBlockLogitsWithDeviceKV); D14 test_ops_dflash_paged_block_attn + ledgerdflash-spec-decode.mdDONE489a7544
SPEC-DFLASH2DFlash2 (DFlash2DraftModel) — a SECOND DFlash architecture, not a change to DFlash. Upstream leaves the DFlash draft untouched and adds two mechanisms carried by a new architecture: a GROUPED DYNAMIC DEPTHWISE CONVOLUTION wrapped around each attention and each MLP sublayer (out[i,c] = sum_t (base[t,c] + delta[i,t,g(c)]) * x[i-t,c], taps zeroed across the block boundary) so a proposal position sees the ones before it without another backbone pass; and a CANDIDATE SELECTOR replacing the independent per-slot argmax — keep the target head's top-K per slot, score adjacent transitions <A[p] * project(h), B[c]> + unary[c], walk the best path from the verified anchor, and at T>0 walk by GUMBEL-MAX noise keyed by the candidate token ids, caching the realized scores as q for the lossless verify (this row said "inverse CDF" from its opening brief until W4 read the kernel; no inverse-CDF walk exists at either PR head). The published checkpoint is the authority on shapes (z-lab/Qwen3.8-27B-DFlash2, safetensors header range-read 2026-08-19, 81 tensors): DFlash1's set plus layers.N.{attention,mlp}_conv.{base_kernel (2,2,5120), kernel_projection.weight (1280,5120)} x5 and candidate_selector.{hidden_projection.weight (256,5120), predecessor_codebook, successor_codebook} at (248320,256) bf16 each, ~254 MB resident the DFlash1 lane never allocates. conv_kernel_size 2, conv_group_size 16, selector_rank 256, selector_top_k 16, block_size 8. One config rule would land silently wrong: the checkpoint declares all five layers sliding_attention AND is_causal false, and our causality resolution mirrors the OLD upstream rule (causal iff SWA), so every layer would run CAUSAL, emit plausible tokens, pass a token gate against our own output, and lose only ACCEPTANCE — which no token gate can see, because the verify is lossless. Upstream changes _dflash_layer_causal to read is_causal first, in the same commit. BEYOND-PIN: the parity pin 555967922 does not carry the architecture at all; anchors cite the PR head, and this row does NOT advance the pinT1vllm#52816 @ head 66e5414c6d75a8529473d977f7458c140bbab8a0, which superseded 19c9351904df4c63042671bc67a866ca48dc7d6f on 2026-08-19 (#1404) and folded vllm#52883 in model_executor/models/qwen3_dflash2.py:1-346 + v1/worker/gpu/spec_decode/dflash2/speculator.py:1-224 + registry.py + config/vllm.py (_is_dflash2_draft) + the _dflash_layer_causal edit in qwen3_dflash.py; stacked guard fix vllm#52883; tests tests/v1/spec_decode/test_dflash2.py, tests/test_config.py::test_dflash2_draft_forces_v2_model_runner, the edited test_dflash_causality.pyW1 LANDED (the route and the causality rule; NO DFlash2 mechanism). (1) is_causal PRECEDENCE: src/vllm/model_executor/models/qwen3_dflash_weights.cpp::ResolveQwen3DFlashAttnModes, with its coercion helper src/vllm/model_executor/models/qwen3_dflash_weights.cpp::DeclaredCausal, resolves an explicit top-level is_causal BEFORE dflash_config.causal and before the legacy layer_types == sliding_attention rule, and src/vllm/model_executor/models/qwen3_dflash_weights.cpp::MakeQwen3DFlashDraftConfig (moved out of the loader's anonymous namespace so the key it carries is gateable) copies the key off the draft's own config.json. Without both halves the published checkpoint runs every layer CAUSAL. (2) The ROUTE: include/vllm/config/speculative.h::IsDflash2Draft plus src/vllm/entrypoints/model_loader.cpp::ReadDflashDraftArchitectures + src/vllm/entrypoints/model_loader.cpp::CheckDflash2DraftArm, called from the dflash branch of LoadedEngine::ResolveSpecConfig and from the top of LoadedEngine::FromModelDir, ahead of every path, config, tokenizer and weight operation. A DFlash2 checkpoint is REFUSED with both missing mechanisms named rather than drafted through the DFlash1 lane, which would succeed silently: its tensor set is DFlash1's plus the conv and selector tensors. (3) The GGUF axis of BOTH halves, which the architecture string cannot reach: the published z-lab/Qwen3.8-27B-DFlash2-GGUF @ 57ab3265 writes general.architecture = "dflash", byte-identical to a DFlash1 drafter, and a GGUF carries no architectures array at all. src/vllm/model_executor/models/qwen3_dflash_gguf.cpp::IsDflash2Gguf keys on the DFlash2-only metadata (dflash.selector_rank, dflash.selector_top_k, dflash.conv_kernel_size) and feeds the same refusal, and src/vllm/model_executor/models/qwen3_dflash_gguf.cpp::MakeDflashGgufConfig carries dflash.attention.causal, the GGUF spelling of is_causal, into the same raw key. The shipped DFlash1 GGUF muse-glimmer-30b-gguf/dflash-kquant.gguf carries NEITHER, verified by reading both files on 2026-08-19, so its resolution is unchanged. Reused unchanged when the mechanisms land: vt::DFlashBlockAttention (KERNEL-ATTN-DFLASH-BLOCK), the DFlash runner/rejection/GDN-rollback lane (SPEC-DFLASH), and the loader's target-shared embed_tokens+lm_head (the TryLoadBf16 comment on src/vllm/model_executor/models/qwen3_dflash_weights.cpp and the two calls it documents in src/vllm/model_executor/models/qwen3_dflash_weights.cpp::LoadQwen3DFlash) which is already what a DFlash2 checkpoint needs. W2 LANDED (the grouped dynamic depthwise convolution, REACHED). vt::DFlashGroupedConv (OpId::kDFlashGroupedConv, kernel-matrix row KERNEL-DFLASH2-GROUPED-CONV) is the project's FIRST dynamic, grouped, block-masked convolution: out[i,c] = sum_t (base[side,t,c] + delta[i,side,t,g(c)]) * x[i-t,c], tap t live only where (i mod (1+k)) >= t, g(c) = c / conv_group_size, and base_kernel dim 0 the prepare/finish SIDE rather than a tap. src/vt/cpu/cpu_ops.cpp::DFlashGroupedConvKernel is the authoritative reference and rounds to the tensor dtype after each step, mirroring upstream's bf16 chain, so src/vt/cuda/cuda_ops.cu::DFlashGroupedConvKernelCuda is specified BIT-IDENTICAL rather than within an envelope. Both of upstream's position-mask arms are ported (pos & (block-1) and pos % block) and gated at block 5, 8 and 16. The conv weights load in src/vllm/model_executor/models/qwen3_dflash_weights.cpp::LoadQwen3DFlash under the published tensor names, and src/vllm/model_executor/models/qwen3_dflash.cpp::DflashConvPrepare / src/vllm/model_executor/models/qwen3_dflash.cpp::DflashConvFinish run them in ALL THREE draft layer bodies, the third being the paged body the production decode path reaches through ForwardBlockLogitsWithDeviceKV. The REFUSAL moved so the conv could be reached (spec D10): a safetensors DFlash2 draft is now ADMITTED at src/vllm/entrypoints/model_loader.cpp::CheckDflash2DraftArm with a startup NOTICE naming the boundary, and refused BY NAME AFTER the block forward (W2 refused at RefuseDflash2CandidateSelector, which W3 retired; W3's boundary RefuseDflash2PathWalk is retired by W4 in turn); the GGUF arm keeps its startup refusal and moves with W5. W2 also discharged the spec's ## Owed O3 and O4: src/vllm/model_executor/models/qwen3_dflash_weights.cpp::MakeQwen3DFlashDraftConfig could not parse EITHER published DFlash2 config.json (rope_theta and block_size are nested under rope_parameters and dflash_config) nor MiMo's DFlash1 draft (no layer_types), and dflash_config.attention_sink_bias is now REFUSED BY NAME because this lane has no attention sink and the parse repair alone would have turned a loud error into a quiet wrong answer. W3 LANDED (the candidate selector, PRODUCTION-REACHED). vt::Dflash2SelectorEdges (OpId::kDflash2SelectorEdges, kernel-matrix row KERNEL-DFLASH2-SELECTOR-EDGES) scores the transition lattice edge(b,l,p,c) = unary[b,l,c] + <pred[pid(b,l,p)] * project(h)[b,l], succ[cand[b,l,c]]>, with the verified ANCHOR as every predecessor slot at step 0; vt::TopKValuesIndices (OpId::kTopKValuesIndices, row KERNEL-TOPK-PAIRS) is the vocabulary top-k that EMITS (id, value) pairs, extending the sort-free pivot-bracket search in src/vt/cuda/cuda_sample.cu rather than porting FlashInfer's 3380-line radix kernel (spec D2). The selector's three tensors load in src/vllm/model_executor/models/qwen3_dflash_weights.cpp::LoadQwen3DFlash, and src/vllm/model_executor/models/qwen3_dflash2.cpp::Qwen3DFlash2Model::ComputeCandidates applies the org-vocab rebase, output_multiplier and final_logit_softcapping to the candidate VALUES in upstream's order. The REFUSAL moved again and the duplicate was collapsed: RefuseDflash2CandidateSelector is retired, both propose paths now call ONE src/vllm/v1/worker/gpu/spec_decode/dflash2/speculator.cpp::Dflash2SelectCandidates, and the boundary was RefuseDflash2PathWalk, which TOOK the scored lattice so the selector's execution was observable at the production call site (W4 retires it). W3 discharged ## Owed O7 by proving that entry rather than deferring it: the missing piece was never an on-disk harness but an in-memory DflashDraft overload of src/vllm/entrypoints/model_loader.cpp::LoadedEngine, the exact seam mtp_weights already had. W3 also ports upstream's WIDE LM-head guard as src/vllm/model_executor/models/qwen3_dflash2.cpp::RefuseQuantizedDflash2LmHead and REFUSES a declared dflash_config.input_embedding_scale != 1.0 by name. W4 LANDED (the PATH WALK; a DFlash2 draft DRAFTS). vt::Dflash2PathWalk (OpId::kDflash2PathWalk, kernel-matrix row KERNEL-DFLASH2-PATH-WALK) turns the selector's lattice into k tokens -- start at the verified anchor (already every predecessor slot of step 0), take the best child, then read the NEXT step's block at the predecessor row just chosen -- in UPSTREAM'S OWN GRID, one program per request with the step loop INSIDE it, which is spec ## Risks/decisions D3's requirement because the identical sequential walk shipped host-side in DSpark and measured 28% of the 27B draft step (#436). Unlike the lattice op it is BIT-EXACT across backends: it performs no arithmetic, only comparisons and one gather. Two contract points decide tokens and are pinned by literals -- a tie resolves to the LOWEST slot (which then selects the next step's PREDECESSOR row, so it moves the whole remaining path) and an all -inf row resolves to slot 0 rather than to "no index". src/vllm/v1/worker/gpu/spec_decode/dflash2/speculator.cpp::Dflash2WalkPath consumes it and BOTH propose paths call it. The REFUSAL IS GONE and what replaces it points the other way: RefuseDflash2PathWalk is retired and src/vllm/v1/worker/gpu/spec_decode/dflash2/speculator.cpp::RefuseDflash1ArgmaxOnDflash2Block throws when a DFlash2 block reaches the DFlash1 per-slot argmax, living inside the DFlash1 sampler's own closure in GPUModelRunner::propose_drafts_dflash rather than beside the walk it defends. W4 also part-discharges ## Owed O5 STRUCTURALLY: LoadQwen3DFlash no longer seeds conv_block_size from the checkpoint's block_size, so dropping the loader's resolved-k assignment now leaves 0 and the first DFlash2 forward refuses by name instead of masking taps against a plausible wrong block. The PROBABILISTIC arm is deliberately NOT ported (spec D13, ## Owed O12): at the moved head _cache_draft_logits runs only when draft_logits is not None, which is set only for draft_sample_method == "probabilistic" -- a value ParseSpeculativeConfigJson refuses BY NAME here against an accept-iff-equal verify -- so landing it would land two mechanisms no production entry point can reach; its layout (draft_logits_spec: fp32, -inf fill, None for greedy) is recorded instead, and the None-for-greedy half IS honoured. Still owed per ## Port map (W5-W6): the GGUF drafter arm, and the G2/G3 run gatesW1 gated CPU, RED-first. test_dflash_causality.cpp 13 cases / 105 assertions (114 with the real GGUFs) — the port of upstream's test_dflash_causality.py branch table as edited by vllm#52816, the precedence no upstream row pins (is_causal set together with dflash_config.causal), the published DFlash2 shape, and the assertion that the z-lab DFlash1 shape resolves EXACTLY as before. RED at 39 assertions / 11 failed before the rule landed. Three of the cases and 32 of the assertions are the IN-FLOW repair of #1366, raised by this wave's fresh reviewer against the same function: the two rows of upstream's _resolve_layer_attention docstring table that its parametrize list never exercises (layer_types absent + use_swa, and all-full layer_types + use_swa, both non-causal upstream and both CAUSAL here), plus the bool() coercion that made "is_causal": 0 fall through in silence while the GGUF arm's KvI64 already honoured it. RED at 103 assertions / 14 failed before the repair, the 4 CHECK_FALSE(true) of the use_swa arm among them. BOTH #1366 halves are UNREACHED at this merge commit, exactly as D4 is, and an earlier revision of this row's spec claimed otherwise for the use_swa half: XiaomiMiMo/MiMo-V2.5-Pro-FP4-DFlash is the only published draft of that shape, it declares no layer_types and MakeQwen3DFlashDraftConfig throws key 'layer_types' not found on the absent key, its target MiMoV2ForCausalLM is INVENTORIED and unimplemented here, and MakeDflashGgufConfig can never write use_swa. Recorded as the spec's ## Owed O4, owner W2, with the reason the reachability repair was not attempted in flow. test_dflash2_draft_routing.cpp 11 cases / 30 assertions (33 with the real GGUFs) — REACHABILITY, entered at LoadedEngine::ResolveSpecConfig and at LoadedEngine::FromModelDir against a nonexistent target directory, which is what proves the refusal precedes all weight I/O. RED at 12 assertions / 2 failed, and the GGUF cases RED again at 24 / 1 before their arm landed. Mutation-proven 2026-08-19 in this worktree, each restored byte-for-byte and each verified by sha256: restoring the is_sliding fallback (#1366's defect, 4 failed), accepting only a JSON boolean again (5 failed), dropping the named uncoercible-type refusal (2 failed), dropping it silently instead (1 failed), gating the draft-config carry on .is_boolean() again (1 failed), swapping the two explicit arms' precedence (2 failed), removing the top-level arm (7c/48a -> 12 failed), inverting the precedence (2 failed), dropping the is_causal carry from the draft-config builder (1 failed), deleting the ResolveSpecConfig call site (the reachability mutation, 2 failed), breaking the architecture string (4 failed), deleting the FromModelDir early guard (2 failed), dropping the GGUF attention.causal read (1 failed), neutralising the GGUF arm of the refusal (1 failed), and breaking the DFlash2-only GGUF keys (1 failed) each turn the focused suite RED. W2 gated CPU. test_ops_dflash2_grouped_conv.cpp 6 cases / 9410 assertions, Status: SUCCESS!, exit 0 -- upstream's own sequential reference loop from tests/v1/spec_decode/test_dflash2.py at block 5 (the % block arm), 8 and 16 (the two PUBLISHED checkpoints; upstream's parametrize covers 5 and 8 only, so 16 is ours), both published taps/group shapes on both sides, plus hand-computed corners for the block boundary, the group map and the side. test_qwen3_dflash2_draft.cpp 16 cases / 108 assertions, Status: SUCCESS!, exit 0 -- the two PUBLISHED DFlash2 config.json documents verbatim (sha256 recorded) through the production builder, MiMo's dflash/config.json verbatim, conv weights read off a REAL on-disk safetensors shard by the production loader, an IDENTITY conv proven BIT-IDENTICAL to no conv, and each conv driven ALONE through each layer body. test_dflash2_walk_refusal.cpp 3 cases / 18 assertions (renamed from test_dflash2_selector_refusal.cpp when W3 moved the boundary, and again to test_dflash2_argmax_guard.cpp when W4 retired the refusal). RED-first at 5 cases / 4 failed with [json.exception.out_of_range.403] key 'rope_theta' not found, which is O3 exactly as the spec predicted it. Mutation-proven 2026-08-19, each restored byte-for-byte and verified by sha256, each with its compile status printed: deleting the conv call sites in ForwardBlockLogits (5 cases / 9 assertions red), in ForwardWithCtxKVDev (1/1) and in ForwardPagedBody (1/1); forcing args.side to 0 (op 2/4353, model 1/1); dropping the block mask (3/449); the wrong group map (3/7436); dropping the rope_parameters fallback (2/2), the dflash_config.block_size fallback (2/2), the layer_types fallback (2/2), the attention_sink_bias refusal (1/1), the uniform-block guard (1/1) and the DflashProposeBlock selector-refusal call (1/1); and restoring W1's startup refusal (3 cases / 2 assertions red). TWO GATE WEAKNESSES were found BY that pass and repaired before landing rather than hidden: activating both convs at once could not see one missing call site, and the first side probe could not see a forced side. Three mutations came back GREEN and are recorded as ## Owed rather than as passes: the loader's own conv_block_size = k + 1 (O5), the CUDA arm which had NEVER COMPILED on this host (O6 — DISCHARGED 2026-08-20, #1489), and the runner's selector-refusal call site (O7). W3 gated CPU. test_ops_dflash2_selector_edges.cpp 7 cases / 199 assertions and test_ops_topk_values_indices.cpp 7 cases / 210 assertions, both Status: SUCCESS!, exit 0; test_qwen3_dflash2_draft.cpp grew to 26 cases / 232 assertions with Muse Glimmer's OUTPUT SCALARS gated against values that DIFFER from the defaults (D9); and test_dflash2_runner_reach.cpp 3 cases / 14 assertions drives a real LoadedEngine into GPUModelRunner::propose_drafts_block, where the walk refusal names the selector's OWN output. That last suite DISCHARGES O7 and supersedes its stated reason. W4 gated CPU, RED-first. test_ops_dflash2_path_walk.cpp 7 cases / 49 assertions, Status: SUCCESS!, exit 0 -- upstream's own _selector_walk_kernel control flow at SAMPLE_PROBABILISTIC=False over three shapes including the PUBLISHED one (top_k 16, 7 steps), plus hand-written literals for the PREDECESSOR CARRY (built so the carrying answer, the row-0 answer and the off-by-one answer all differ at step 1), the TIE resolving to the lowest slot and then choosing the next step's predecessor row, the all -inf row resolving to slot 0, and the GATHER with ids that are not the identity permutation of the slots. RED-BEFORE captured with its exit status: rc=2, 10 error: lines, 'Dflash2PathWalk' is not a member of 'vt'. test_dflash2_argmax_guard.cpp 5 cases / 30 assertions (renamed from test_dflash2_walk_refusal.cpp when W4 retired the refusal). W4's fresh review returned FAIL and the repair is in this same wave: the walk wrapper's [B,L,K,K] guard was ungated -- its case mutated one shape field of a Contig tensor -- so dropping either trailing conjunct, or deleting the whole VT_CHECK, left every suite green. The MECHANISM this row recorded for that was backwards, corrected by #1518: the mutation desynchronises the strides, but the wrapper checks shape before contiguity, so with the guard present the SHAPE check still answered the case. What the mutation costs is the deleted state -- remove the shape check and the throw falls through to contiguous tensors required, so a bare CHECK_THROWS still passes and the deletion is invisible (measured: 7 cases / 47 assertions, Status: SUCCESS!, rc 0). Both axes are now driven by genuinely contiguous wrong-extent lattices matched on the message, and all three mutations redden (1 case / 1 assertion, 1/1, 1/2). The same repair, and the same #1518 correction, apply to the sibling test_ops_dflash2_selector_edges.cpp, whose lattice guard had the same gap (now 7 cases / 203 assertions; deleting it reddens 1 case / 2). Dflash2WalkPath's candidate-set and i32-range refusals are gated the same way (deleting them together reddens 1 case / 4). And the CUDA lane comparator is reconciled to a STRICT >: it carried an (v == best && j < slot) disjunct that is unreachable once a lane has claimed anything, whose one effect was letting a lane holding -inf claim on the -inf seed, so [NaN,-inf] read cpu 0 and cuda 1 while every NaN-free row agreed. That deletion is VERIFIED on a device as of 2026-08-20 (#1518, correcting an UNVERIFIED state this row carried at the W4 merge): CI's build-cuda-fat job compiles src/vt/cuda/cuda_ops.cu for ten architectures on every pull request, and the operator ran test_ops_dflash2_path_walk on dgx:gpu0 (GB10, sm_121a) at the W4 merge commit -- 83 assertions on device against 49 on CPU, Status: SUCCESS!, zero skip lines, the chained NaN row among the increment. The rest of spec ## Owed O11 stands. test_qwen3_dflash2_draft.cpp grew to 27 cases / 277 assertions: DflashProposeBlock on a DFlash2 draft now DRAFTS, and the case asserts the two things an argmax fallback cannot do -- every drafted id is one of the SELECTOR's own candidates (top_k 3 over a vocabulary of 8, so a full-vocab argmax lands outside it most of the time), and the draft differs from SampleDflashBlockDrafts' answer on the SAME block logits, MEASURED at 5 of 7 slots agreeing. test_dflash2_runner_reach.cpp 3 cases / 83 assertions drives a real LoadedEngine through propose_drafts_block, GENERATES, reads the drafts off the production VT_SPEC_TRACE line at REAL fd 2 (a std::cerr rdbuf swap cannot see a std::fprintf(stderr, ...)), and requires them to MOVE between two engines differing ONLY in D9's output scalars -- MEASURED at 2 of 8 blocks, with the count logged. Mutation-proven 2026-08-20, each with its match count and compile_rc printed and each restored sha256-verified: dropping the previous carry (2 cases / 17 assertions red), > to >= (2/3), the -inf collapse answering K-1 (1/1), the gather ignoring the winner (4/26), the walk's per-request row indexing (1/2), DELETING the runner's walk call site (2/5), REPLACING the walk with the DFlash1 argmax (1/1, the guard-independent reachability proof), deleting DflashProposeBlock's walk call (1 case), restoring the conv_block_size seed (1/2), breaking the startup notice (1/1 and 1/1), and dropping the final_out capture (2/5). TWO came back GREEN and are recorded as ## Owed rather than as passes: deleting LoadDflashDraft's conv_block_size = draft->k + 1 (O5, because the only real-engine harness enters through the in-memory overload and bypasses that function), and deleting the argmax guard's own call (a guard reachable only under another mutation; its throwing arm is gated directly). The walk's CUDA arm is written, registered, compiled by CI's build-cuda-fat job on every pull request and RUN on dgx:gpu0 at the W4 merge commit (#1518); it still skips on the authoring host, which has no nvcc, and the remainder of ## Owed O11 stands. Still owed, all in the spec ## Gates: the lattice half of G1, and the conv's CUDA arm; conv+lattice vs upstream references at the checkpoint's real shapes; draft-token identity vs vLLM built at 19c93519 under the ratified DFlash near-tie envelope (strict identity is bf16-irreducible, SPEC-DFLASH D6); ACCEPTANCE measured SAME-TRAJECTORY, because SPEC-DFLASH D8 spent a campaign on a divergent-trajectory confound D9 refuted; the GGUF arm with a LOWER bound; and the CUDA top-k's NaN ordering, which a GB10 measured DISAGREEING with the CPU contract on 2026-08-20 and which #1489 owns; both W3 CUDA arms otherwise compile and run, and the tie rows O10 called the real risk AGREE (O10). The acceptance gate has since read, and the speed ratio recorded below was taken after it. W5 LANDED (the GGUF DRAFTER ARM; both containers draft). src/vllm/model_executor/models/qwen3_dflash_gguf.cpp::MakeDflashGgufConfig carries conv_kernel_size, conv_group_size, selector_rank and selector_top_k into dflash_config (ALL FOUR REQUIRED once IsDflash2Gguf classifies the file, because it answers on any ONE of three and a guessed conv_group_size sizes the projection wrong and is acceptance-only), plus any of the three output scalars the file declares; LoadQwen3DFlashFromGguf resolves blk.N.{attn,ffn}_conv_base, blk.N.{attn,ffn}_conv_proj.weight and selector_{hidden,predecessor,successor}.weight. The KEY spelling is MEASURED -- every DFlash2 config key the published file writes is the HF name VERBATIM under dflash., five of five, read 2026-08-20 -- and the TENSOR names are not derivable at all, so they are read off the artifact and held against all three published arms by an asset-gated case. src/vllm/model_executor/models/qwen3_dflash_gguf.cpp::DflashGgufTokenizerVocab supplies the vocabulary the selector's codebook check needs, from tokenizer.ggml.tokens and NOT from the codebooks, because a check reading its expectation off the tensor under test would pass a transposed or truncated pair; src/vllm/v1/worker/gpu/spec_decode/dflash2/speculator.cpp::Dflash2SelectCandidates gains the codebook-vs-target-vocabulary refusal that W5 is the first wave to be able to need, since a GGUF draft declares no vocabulary while the ids that index its codebooks come from the target's head. The STARTUP REFUSAL is gone on BOTH containers: CheckDflash2DraftArm now only ever prints, and what it prints names the bf16 residency a GGUF drafter pays. W5 gated CPU, RED-first. test_qwen3_dflash2_gguf.cpp 9 cases / 4746 assertions, Status: SUCCESS!, exit 0 -- and 4945 with BOTH published artifacts present (VLLM_DFLASH2_GGUF_MODEL on qwen3.8-27b-dflash2-gguf/Qwen3.8-27B-DFlash2-Q4_K_M.gguf, whose sibling walk reads all three arms, and VLLM_DFLASH_GGUF_MODEL on muse-glimmer-30b-gguf/dflash-kquant.gguf), so the asset-gated case REPORTS rather than skipping silently (#1382's shape). The 4719/4906 pair this row carried until 2026-08-21 never reproduced and is corrected here: re-measured on the CI recipe at 238041548 the pre-repair suite read 4720 and 4919, and no subset reproduced the recorded pair (#1314 F2, #1518's shape -- squash_merge_commit_message = PR_BODY makes a wrong number permanent). RED-BEFORE captured with its exit status: rc=1, 7 cases / 5 failed, 260 assertions / 12 failed, Status: FAILURE!. The NAME MAP is gated BY CONSTRUCTION: the bf16 GGUF arm is required BIT-IDENTICAL to the same draft written as safetensors under the published HF names, 1 120 000 bf16 elements over 30 COMPARED TENSORS from ONE set of source values -- the fixture writes 36 GGUF tensors and the loader's q/k/v and gate/up merges leave 30 comparable slots, and both numbers are now ASSERTED (gm.size() == 30, compared == 1120000) rather than quoted. The "25 tensors" carried here until 2026-08-21 is the DFLASH1 fixture's count (#1314 F6). The QUANTIZED arms carry the LOWER BOUND this lane needs because it dequantizes by design, and its three parts are NOT three equal legs (#1314 F3 corrected the claim that they were): L1 is a PRECONDITION ON THE FIXTURE -- it reads the ggml type and byte count off the tensor table of the file the test just wrote (22 quantized tensors, 1 114 112 elements in 626 688 bytes for Q4_K and 1 183 744 for Q8_0, against 2 228 224 in bf16), which proves the bytes are block-encoded and says nothing about the loader; L2 IS THE BOUND -- the VALUES bit-for-bit over 266 240 elements against the suite's OWN Q8_0 and Q4_K encoders, including the inverse of get_scale_min_k4's 6-bit pack, so the comparison is a round trip through two implementations and every decoder mutation lands here; L3 is a cheap COROLLARY -- DIFFERENCE from the bf16 arm at 7/7 quantized DFlash2 tensors and 2048/2048 block logits, with the F32 tensors no arm quantizes required IDENTICAL. A byte-hashing loader passes L1 and L3 and fails L2 hard, which is the ordering. AND THE FIXTURE'S OWN COVERAGE IS COUNTED, one counter per packed field, because L2 bounds only what the fixture drove: W5 shipped one instance of that gap and its review found two more (#1314 F1). The Q4_K encoder produced a scale of EXACTLY 3 for all 17 408 low-half sub-blocks, two bits of a six-bit field, so *d = q[j] & 63 mutated to & 15 left the suite 9/9 at 4720 assertions, SUCCESS!, rc 0; the min field ran 36..38 everywhere, which catches & 15 but not & 47, and that mutation passed too. The repair drives sub-block 0 to 19 and sub-block 1 to 63, pins the min of sub-blocks 2 and 6 at 63, and DELIBERATELY leaves sub-blocks 2 and 3 fine so the 4-bit quant still spans 0..15 in both nibble positions -- lifting all four collapses q to 0..2 and trades the fix for the same defect one field down. Every arm then DRAFTS through DflashProposeBlock, from the SELECTOR's candidate set, differing from the DFlash1 argmax on 5, 6 and 6 of 6 swept blocks. Mutation-proven 2026-08-20, each with its match count and compile_rc printed and each restored sha256-verified then rebuilt: dropping conv_group_size (7 cases / 2 assertions red -- the load throws, so cases abort), swapping the two codebook names (3/6), pointing attention_conv.base_kernel at the MLP sublayer (3/6), pointing the MLP projection at the attention one (3/6), dropping the vocabulary substitution (6 cases), reading the tokenizer array one short (6 cases), dropping the three optional scalars (1/3), deleting the codebook-vs-target guard (1/2), deleting the startup notice (routing 3 cases / 20, reach 1/8) and stopping the GGUF classification entirely (routing 2/10). A first attempt at the guard mutation FAILED TO BUILD (-Werror=unused-variable) and was re-run in a compiling form rather than counted. The W5 REVIEW REPAIR added seven more on 2026-08-21, same discipline: q[j] & 63 -> & 15 and q[j+4] & 63 -> & 47 each pass 9/9 BEFORE the fixture repair and redden 1 case / 7 assertions after; the high-half min's (q[j-0] >> 6) << 4 deleted also reddens 1/7; removing the low-half scale lift, removing the min pin, taking the naive all-four lift, and dropping one tensor from the comparison map each redden 2 assertions -- so each new precondition is proven to bite. The guard comment at dflash2/speculator.cpp claimed the two vocabularies "could not differ" on safetensors; they always could (model_loader.cpp takes draft_vocab_size from the TARGET's lm_head while the codebook extent is checked against the DRAFT's config.json), and the comment is corrected (#1314 F7). Still owed: ## Owed O13 records that a GGUF drafter is DEQUANTIZED to bf16 at load -- this lane's own design since SPEC-DFLASH-GGUF, but W5 makes the bill bigger and MEASURES it at 3 848 808 960 bytes (3.584 GiB) resident against 1 143 006 752 on disk for Q4_K_M, 254 279 680 of them the selector's codebooks -- and O14 records that LoadDflashDraft's GGUF branch is still not reachable from a production entry point, O5's shape unchanged, and the W5 REVIEW added O15 (the three optional output-scalar GGUF key spellings are INFERRED from the five that are measured, and none of the three appears in any of the 47 KV entries of any published arm), O16 (the codebook-span guard compares ==, which is stricter than the out-of-range read needs; the local oracle is at the parity pin and carries no DFlash2, so W6 reads upstream's condition at the PR-head oracle -- a strict == is a NEW refusal class on the shipping safetensors lane for a padded target head), O17 (no wave has LOADED a published artifact: the asset case reads HEADERS only and the fixture runs at H = 256, so "drafts in all three published arms" is an inference from encodings) and O18, now DISCHARGED 2026-08-21 (the fixture's fp16 block scales were fixed at one value each -- F1's class one field over, and the recorded reason for keeping them, that varying d costs bit-exactness, was refuted by the SECOND POWER OF TWO the same entry named as the remedy. EncodeQ8_0 now alternates d between 0x1C00 and 0x2000 per BLOCK and counts it; hoisting DequantQ8_0's d to block 0 left the pre-repair suite at 9/9 / 4730 / SUCCESS! / rc 0 and reddens 1 case / 7 assertions after. Q4_K's d/dmin stay at 0x2400/0x2000, above a fully driven 6-bit scale and min). The published Q4_K_M file is MIXED and is now named as such wherever it is claimed gated: 32 F32 / 45 Q4_K / 4 Q6_K (blk.{2,4}.{attn_v,ffn_down}.weight), measured 2026-08-21; none of the four is a DFlash2 tensor, and Q6_K decodes through the shared DequantQ6_K gated by tests/vllm/test_gguf_dequant.cpp (#1314 F5) W6 TOOK THE GATES 2026-08-21 on dgx:gpu0 against vLLM 0.1.dev1+g66e5414c6 (vllm#52816, BEYOND-PIN, wheel sha256 fbc247ab1bda93a81ff7a68658cdda65b697e263ad2c43a2bc62c2591d207439, TRITON_ATTN -- NOT vLLM's default backend here, #1456). G2: 4/4 prompts token-exact and 45/47 draft blocks byte-identical, the two that differ each by ONE token at slot 2 in the selector's rank contraction, which this row specifies within-envelope rather than bit-exact. G3, SAME-TRAJECTORY BY CONSTRUCTION (all four streams identical): acceptance IDENTICAL PER PROMPT -- 49/54/54/52 on both engines, 209 total -- and the OTHER instrument agrees too, our runner's counter 216 against vllm:spec_decode_num_accepted_tokens 216, and our 47 verified blocks against vllm:spec_decode_num_drafts 47. G4 and ## Owed O17: the published Qwen3.8-27B-DFlash2-Q4_K_M.gguf LOADED through examples/vllm-cli over the real 27B, proposed 7 blocks and generated, at 44.85 GiB peak RSS against 44.54 GiB for the safetensors drafter -- 0.70% apart on files 2.52 GiB apart, so O13's "the small file saves nothing at runtime" is now MEASURED and the quantized arm is the LARGER of the two. All seven device suites green on sm_121a with ZERO no CUDA backend; skipping lines. SPEED TAKEN 2026-08-22 and RECORDED, which is NOT a pass: 0.8016987337853048 ours/vLLM on output_throughput_tok_s (13.051 vs 16.27918250335551 tok/s, 16 warm legs folded per arm), verdict RECORDED, no floor declared, on dgx:gpu0 under rc job ec9cf6cd at d25730fbb with GATE_RC=0; three of four axes stay NOT MEASURED and four caveats travel with it (#1673, #1685, #1667, and the missing axes). The sentence this replaced read SPEED NOT TAKEN AND NONE INFERABLE and was true when written. One of its two bounds still holds -- our DFlash2 draft is off the paged CUDA-graph fast path while the oracle GRAPHS its draft step (Capturing dflash2 CUDA graphs (FULL), 77 s, in its own startup log) -- and the other does not: since O32 marked the legs, the CIFS reads of the 51.75 GiB target sit outside every folded span. Record in .agents/benchmark-record.md. ## Owed O16 SETTLED -- upstream has NO codebook-span comparison at either head, it masks the head's padded tail to -inf before the top-k -- and O21/O22/O23 opened (#1538, #1456). W6's fresh review returned FAIL and a fresh implementer repaired it on the same branch: vllm#52816 had MERGED 46 minutes before W6's work commit, so the gate head is kept at 66e5414c as a DATED exception because the capture predates the merge, and reconciling onto merged upstream is #1561; a golden carrying ZERO drafts passed the liveness precondition and produced a structural verdict about OUR engine, now VOID rather than failed and gated on every box; G3's headline is a COROLLARY of G2 on this capture rather than a second measurement; the near-tie attribution is WITHDRAWN (#1564); the pinned tree was the FAILING run's; and the oracle capture harness exists only as prose (#1562).dflash2-spec-decode.md, #1314, #1327ACTIVECLAIM-SPEC-DFLASH2-W6
SPEC-DSPARKDSpark semi-autoregressive block drafter for DeepSeek-V4 and Qwen3, including native and Speculators checkpoint layouts, anchor-vs-bonus-token semantics, reduced/heterogeneous vocabulary mapping, sequential Markov sampling, noncausal draft attention, rejection/metrics and full-CUDA-graph compatibility; user-promoted scope at the v0.25.0 audit; re-grounded at the CURRENT pin 2026-08-08 (USER-requested rider, task #287): DSparkSpeculator(DFlashSpeculator) drafts a block in ONE parallel pass (anchor + N−1 noise queries); method "dspark" V2-runner-ONLY (forced at config/vllm.py:560-568, "parallel drafting natively in V2" :2173-2177); draft models exist for BOTH our registered target families (Qwen3 + Gemma4) and slot beside our landed MTP + DFlash lanes (src/vllm/v1/worker/gpu/spec_decode/{mtp,dflash}/speculator.cpp). SPIKE COMMITTED 2026-08-09 (CLAIM-SPEC-DSPARK, developer goal "a full DSpark implementation, based on vLLM"): the whole upstream surface is 1613 lines over 5 files, 3 of them class X(DFlashY) subclasses; the delta over our landed SPEC-DFLASH lane is A) the low-rank Markov logit-bias head (markov_rank=256 in every shipped ckpt), B) the sequential N-step sample loop, C) the sample_from_anchor N-query layout (the PrepareDflashInputs field already exists, always false today; NumLookaheadTokens() already returns k for dspark — verified), D) reduced draft vocab + d2t, E) config/method resolution incl. the k >= dspark_block_size hard error, F) Speculators-format config translation (a subsystem we have ZERO of today). Gate-model drafts EXIST (RedHatAI/Qwen3.6-35B-A3B-speculator.dspark 1.90 GB, satgeze/Qwen3.6-27B-DSpark 8.80 GB) and the upstream test's own 4B pair (Qwen/Qwen3-4B-FP8 + deepseek-ai/dspark_qwen3_4b_block7, 2.79 GB) is the smallest honest lane; DeepSeek-V4 DSpark stays OUT OF SCOPE (HW-blocked)T1vllm/v1/worker/gpu/spec_decode/dspark/speculator.py:37; vllm/config/speculative.py:62,310,706-709; vllm/model_executor/models/qwen3_dspark.py:36,95 + gemma4_dspark.py:134,182; registry registry.py:609,611 @ 555967922--dspark-spec-decode.md (spike, 2026-08-09; supersedes the grounding note)ACTIVECLAIM-SPEC-DSPARK
SPEC-TLITokenizer-agnostic speculative decoding across heterogeneous draft/target vocabularies: shared-token mapping, target↔draft ID translation, constrained draft logits and greedy-only validationT1vllm/config/speculative.py:145-149,1173-1203; vllm/v1/spec_decode/vocab_mapping.py:68-160; vllm/v1/spec_decode/draft_model.py:34-58; vllm/v1/spec_decode/llm_base_proposer.py:432-495,688-691,831-837; tests/v1/spec_decode/test_vocab_mapping.py:1-50 @ 702f481--planned: specs/tli-spec-decode.mdINVENTORIED-
SPEC-NGRAMDraft-FREE n-gram proposer. DONE 2026-07-27 (CLAIM-ROADMAP-D3): 1:1 port of ngram_proposer.py (KMP-LPS suffix-ngram matcher + batch propose) wired as a third --speculative-config method reusing the LANDED MTP/DFlash verify/reject/take_draft_token_ids loop (no draft model / hidden tap / draft KV; GDN spec verify reused via MakeQwen3_5KVCacheSpec(num_spec>0)). 27B gate 5/5 STRICT our-ngram-ON == vLLM-ngram-ON + 180/180 drafts accepted; unit 19/19; spec-OFF byte-identical; host-side, no new kernel, -Werror cleanT2vllm/v1/spec_decode/ngram_proposer.py:184-276,128-180; vllm/config/speculative.py:734-762,1224-1234; tests/v1/spec_decode/test_ngram.py @ 555967922src/vllm/v1/spec_decode/ngram_proposer.{h,cpp}; include/vllm/config/speculative.h (ResolveNgram/use_ngram); src/vllm/config/speculative.cpp; src/vllm/entrypoints/model_loader.cpp (ResolveSpecConfig); src/vllm/v1/worker/gpu/runner.cpp (propose_drafts_ngram)tests/vllm/v1/spec_decode/test_ngram_proposer.cpp (19/19); tests/parity/test_qwen27_ngram_spec_decode.cpp (5/5 STRICT, 180/180 accepted, dgx); golden tests/parity/goldens/ngram_27b/ngram_27b_spec_on.json + scripts/spec/ngram_27b_golden.py; ledger parity-ledger.md 2026-07-27 — anchor tests/vllm/v1/spec_decode/test_ngram_proposer.cpp:30specs/spec-decode-breadth-d3.mdACTIVECLAIM-ROADMAP-D3
SPEC-EAGLE3EAGLE3 proposer and draft model. SCOPED — reachable-blocked 2026-07-27 (CLAIM-ROADMAP-D3): port designed (reuse DFlash D5 separate-draft loader + D1 aux multi-tap + verify/reject loop; config-select method="eagle3"). BLOCKER (W0 RUN-verify, no fabrication): no ungated oracle-runnable EAGLE3 draft ARCH/checkpoint for a Qwen3.6 gate model at pin 555967922 — registry.py:572-648 has Qwen3_5MTP but no Eagle3Qwen3_5*; dgx cache has zero eagle checkpoints; z-lab published DFlash not EAGLE3; our spec path is Qwen3.6-only. Mirrors the Command-R HF-gate honest-blocked patternT2vllm/v1/spec_decode/eagle.py; vllm/model_executor/models/registry.py:612-648; vllm/config/speculative.py:869-885 @ 555967922- (port scoped, not implemented)- (blocked: no checkpoint)specs/spec-decode-breadth-d3.mdBLOCKED-

Note: grammar-bitmask application under speculative decode (the multi-row bitmask, one row per draft token) is deferred — see porting-inventory.md §6 — and is in scope for neither the TOOLS-STRUCTURED-CORE row nor the SPEC-* rows above until a spike claims it.

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
SPEC-DRAFT-MODELGeneric model-agnostic SEPARATE draft-model proposer (method="draft_model"): a full smaller standalone LM runs K autoregressive greedy steps to propose K draft tokens; the target verifies in one forward and the longest-accepted-prefix is emitted. Distinct from MTP/EAGLE/DFlash — pass_hidden_states_to_model=False, shares NEITHER embeddings NOR lm_head with the target. W0 spike + W1 CPU brick LANDED 2026-07-29 (CLAIM-SPEC-DRAFT-MEDUSA, NOT pushed): the greedy k-step autoregressive propose (DraftModelProposeGreedy/Batch) over a DraftLogitsFn next-token oracle, reusing the LANDED SPEC-REJECTION verify/accept UNCHANGED (only the proposer is net-new, mirror of the SPEC-NGRAM shape). Unit-gated RED-first: propose->verify->accept equivalence (accepted tokens == the target's own greedy run, every draft/target (dis)agreement pattern) + full-acceptance on a matching draft (num_sampled==k+1) + the RED witness that full acceptance DEPENDS on the autoregressive feed-back (5/6 fail with feed-back dropped). ParseSpeculativeConfigJson accepts "draft_model" (requires model + num_speculative_tokens). Additive + default-inert (no runner construction; engine byte-identical with no SpeculativeConfig). Clean CPU -Werror. RESIDUAL (W3, DGX-offline): the real draft-model forward behind the oracle (paged KV + CUDA-graph) + e2e greedy our-ON==vLLM-ON token-exact gate + throughput speed gate.T2vllm/v1/spec_decode/draft_model.py:19 (pass_hidden_states :29, no shared embed/lm_head :108-115); propose vllm/v1/spec_decode/llm_base_proposer.py:502-767 (_greedy_sample :428-438, set_inputs_first_pass :838-851, K-1 feed-back :682-761); config vllm/config/speculative.py:684,692-701,1195; runner vllm/v1/worker/gpu_model_runner.py:604-609; e2e tests/v1/e2e/spec_decode/test_spec_decode.py:500-561 @ 555967922include/vllm/v1/spec_decode/draft_model_proposer.h; src/vllm/v1/spec_decode/draft_model_proposer.cpp; src/vllm/config/speculative.cpp (draft_model accept); reuses src/vllm/v1/spec_decode/rejection_sampler.{h,cpp} — anchor src/vllm/v1/spec_decode/draft_model_proposer.cpp:27tests/vllm/v1/spec_decode/test_draft_model_proposer.cpp (6/6, 41 assertions, CPU; RED-first 5/6 fail with feed-back dropped); ledger parity-ledger.md 2026-07-29 — anchor tests/vllm/v1/spec_decode/test_draft_model_proposer.cpp:143specs/draft-model-medusa-spec.mdACTIVECLAIM-SPEC-DRAFT-MEDUSA
SPEC-MEDUSAMedusa multi-head speculator (method="medusa"): the target carries N extra Medusa LM heads, each predicting ONE future position from the SAME target hidden state in a single (non-autoregressive) pass; draft_tokens = stack([argmax(head_logits)]) -> [batch, num_heads], num_speculative_tokens == num_heads. Verify/accept is the SAME SPEC-REJECTION loop (linear, not tree, at this pin). W0 spike ONLY (CLAIM-SPEC-DRAFT-MEDUSA, 2026-07-29): proposer scoped in specs/draft-model-medusa-spec.md; deferred to W2 because its multi-head target-tap propose needs the target model's Medusa heads (a model change) a pure host brick cannot meaningfully stand up. No code yet.T2vllm/v1/spec_decode/medusa.py:18 (propose :40-58: model(hidden)->per-head compute_logits->stacked argmax); config vllm/config/speculative.py:822,888-889; runner vllm/v1/worker/gpu_model_runner.py:642-645 @ 555967922- (spike only, not implemented)- (W2)specs/draft-model-medusa-spec.mdSPIKECLAIM-SPEC-DRAFT-MEDUSA
SPEC-NGRAM-GPUOn-device n-gram proposer (method="ngram_gpu"): the KMP suffix match + batch propose run on GPU (pinned idx/val buffers + a device token table) rather than the CPU SPEC-NGRAM path. Draft-FREE, gate-model usable — the cheapest breadth gap (value #1).T2vllm/v1/spec_decode/ngram_proposer_gpu.py:217; dispatch vllm/v1/worker/gpu_model_runner.py:610-626- (enumerated, not implemented)-specs/spec-decode-inventory.mdINVENTORIED-
SPEC-SUFFIXSuffix Decoding proposer (method="suffix", arXiv 2411.04975): a per-prompt suffix tree over prompt+output proposes drafts (tree-depth / spec-factor / min-token-prob knobs). Draft-FREE but depends on the EXTERNAL arctic_inference package (lazy import). Value #2.T2vllm/v1/spec_decode/suffix_decoding.py:9,26; dispatch vllm/v1/worker/gpu_model_runner.py:634-635--specs/spec-decode-inventory.mdINVENTORIED-
SPEC-EAGLEEAGLE(1) proposer (method="eagle"), distinct from SPEC-EAGLE3: a separate small draft consuming the target's LAST hidden state (single aux tap) that runs K AR draft steps; EagleProposer is shared with eagle3/mtp/dspark via use_eagle(). Separate draft weights; the eagle-draft max_position_embeddings clamp is already ported (SpeculativeConfig::MaybeOverrideDraftMaxPositionEmbeddings) ahead of the loader. Value #3.T2vllm/v1/spec_decode/eagle.py:10; use_eagle() vllm/config/speculative.py:1324-1328; models vllm/model_executor/models/{llama_eagle,mistral_eagle,cohere_eagle}.py--specs/spec-decode-inventory.mdINVENTORIED-
SPEC-MTP-FAMILYMTP method breadth beyond Qwen3.5 (SPEC-MTP DONE): the canonical mtp method dispatched per family by draft_model_config.hf_config.model_type. DeepSeek-V4 nextn is already ACTIVE-W1 (weight-blocked GGUF, model row MODEL-SPEC-deepseek-v4-deep-seek-v4-mtp); the ~18 other family heads (glm4_moe / ernie / nemotron_h / longcat_flash / bailing_hybrid / exaone / mimo / hy_v3 / minimax_m3 / inkling / openpangu / qwen3_next / gemma4 / step3p5) are model-matrix-INVENTORIED. gemma4_mtp / step3p5_mtp take dedicated proposers.T2vllm/config/speculative.py:37-59 (MTPModelTypes); dispatch vllm/v1/worker/gpu_model_runner.py:627-637; models vllm/model_executor/models/*_mtp.py--specs/spec-decode-inventory.mdINVENTORIED-
SPEC-ACCEPT-VARIANTSAcceptance / draft-sampling variants beyond SPEC-REJECTION's greedy standard: rejection_sample_method ∈ {standard, synthetic, block} and draft_sample_method ∈ {greedy, probabilistic} (typical / rejection acceptance for non-greedy sampling). Cross-cuts every proposer.T2vllm/config/speculative.py:77-78,216,283; MRV2 vllm/v1/worker/gpu/spec_decode/rejection_sampler.py:82-91--specs/spec-decode-inventory.mdINVENTORIED-
SPEC-DYNAMICDynamic speculation length (num_speculative_tokens_per_batch_size): a batch-size -> k schedule that adapts draft length to load (uses_dynamic_speculative_decoding()). A config axis layered on top of any drafter.T2vllm/config/speculative.py:1336-1337; vllm/v1/spec_decode/dynamic/utils.py:7,77--specs/spec-decode-inventory.mdINVENTORIED-
SPEC-CUSTOM-CLASSPluggable custom proposer (method="custom_class"): the proposer class path is read from speculative_config.model and must expose a propose method — serves the extensibility-first priority (drop-in third-party speculators).T2vllm/v1/spec_decode/custom_class_proposer.py:12; dispatch vllm/v1/worker/gpu_model_runner.py:596-599--specs/spec-decode-inventory.mdINVENTORIED-
SPEC-EXTRACT-HIDDENHidden-state extraction proposer (method="extract_hidden_states"): an offline / data-collection path that runs the target with aux hidden-state outputs (for training EAGLE/MTP drafts) rather than accelerating decode; model row MODEL-SPEC-extract-hidden-states-extract-hidden-states-model.T2vllm/v1/spec_decode/extract_hidden_states.py:29; dispatch vllm/v1/worker/gpu_model_runner.py:646-650--specs/spec-decode-inventory.mdINVENTORIED-
SPEC-MLP-SPECULATORMLP speculator (method="mlp_speculator"): a small MLP head predicting K tokens. UPSTREAM-DEPRECATED at the pin — the enum still resolves it but the V1 dispatch has NO branch, so it raises ValueError (gpu_model_runner.py:651-654); V0-only. Rowed for enumeration completeness, lowest priority.T2vllm/model_executor/models/mlp_speculator.py; enum vllm/config/speculative.py:69,890--specs/spec-decode-inventory.mdINVENTORIED-
SPEC-DSPARK-QWEN3-ROUTINGDSpark draft-architecture routing: a draft whose config declares architectures=["DSparkDraftModel"] together with model_type qwen3 must resolve to the landed Qwen3 DSpark lane, and the predicate that decides it must be reached from the loader. At the pin, upstream forces EVERY DSpark draft that is not Qwen3DSparkModel or Gemma4DSparkModel onto model_type deepseek_v4 plus architectures ["DSparkDraftModel"] (speculative.py:934-944); BEYOND-PIN vLLM PR vllm#52197, merged 2026-08-17 at 7075ddac, puts a leading branch in front of that catch-all which normalizes the pair to Qwen3DSparkModel, and adds the same pair to the method = "dspark" auto-detection at :882-887. We diverged from BOTH ends until W1-W4 landed. Before: the forced rewrite was NEVER ported, so no code read a draft config's architectures key (the three reads in src/vllm/entrypoints/model_loader.cpp were the TARGET model's), and include/vllm/config/speculative.h::IsDsparkDraft had NO production caller — every reference outside its header was in tests/vllm/config/test_speculative_dspark.cpp, while LoadedEngine::ResolveSpecConfig branched on cli.method alone. So the checkpoint loaded by never having ported the pinned behavior rather than by decision, and the DeepSeek-V4 arm we do not implement had no named refusal. Now (W1-W4 landed): the dspark branch of src/vllm/entrypoints/model_loader.cpp::ResolveSpecConfig reads the draft's own config.json through src/vllm/entrypoints/model_loader.cpp::ReadDsparkDraftIdentity — which translates the Speculators layout first — and classifies it with include/vllm/config/speculative.h::IsDsparkDraft and then include/vllm/config/speculative.h::ResolveDsparkArchitecture. The predicate therefore HAS a production caller, the DSparkDraftModel + qwen3 pair routes to the landed Qwen3 lane, and a draft that resolves to the DeepSeek-V4 lane is refused BY NAME rather than rewritten into the DeepseekV4Model stub (TWO tracked divergences from upstream: that refusal, and the Gemma4 collapse onto one implemented lane). A draft that DECLARES no architecture is deliberately NOT classified, which is narrower than upstream's catch-all and is recorded under ## Owed. REACHED, as of the merge of SPEC-DSPARK-BLOCK-SIZE-GUARD (#1225): that row hoists the DSpark resolution to the top of LoadedEngine::FromModelDir, above the target-directory check and far above maybe_load_dflash, so ResolveSpecConfig and therefore this classification now run BEFORE LoadDsparkDraft. A user arriving through include/vllm.h or the server at a DeepSeek-V4 DSpark draft gets the NAMED refusal, not the draft loader's missing-key message. The second call site inside LoadDsparkDraft that this row previously owed is therefore no longer owed; only two of the resolution's own earlier messages still precede the classification (#1225's missing-k refusal, and the GGUF branch's named refusal). Still owed: the G5 token-exact run gate (2.53 GiB draft + GPU authority) and the G6 spec-off gate. GATEABLE ON THIS HOST: RadixArk/Qwen3.8-27B-DSpark @ 85ef153be924f17ce4bf62726954eeaa4a73e854 carries exactly the shape (one 2718576122-byte shard, sha256 9d26d5e637551c244d543c67c790bd0947f360e005c569e5851a185ffe692786, 5 layers against a 64-layer Qwen3.8-27B target); the 2.4T lane named by the upstream PR stays memory-infeasible and is NOT claimed. Scoped to classification only: the speculator, the weight path and the --speculative-config parser are excludedT1vllm/config/speculative.py:882-887,934-944 @ 555967922; BEYOND-PIN PR vllm#52197 @ 7075ddac28c25d4fd2b84bc2a9a6c5ffde0345c8speculative.h:159-257 (IsDsparkDraft + ResolveDsparkArchitecture); src/vllm/entrypoints/model_loader.cpp::ReadDsparkDraftIdentity, called from the dspark branch of src/vllm/entrypoints/model_loader.cpp::ResolveSpecConfig. SYMBOL-anchored rather than line-anchored by SPEC-DFLASH2 W1's repair: that wave inserted the DFlash2 classification ahead of both and re-anchored the two ranges :460-496 and :1017-1086 by the WRONG shift, so the row then cited a refusal message string and a std::string model_type; declaration under the helper's name. A symbol survives every edit that does not rename it and scripts/check-symbol-anchors.py gates it; that script states it cannot verify a LINE citation at all, which is why nothing caught the bad shifttest_speculative_dspark.cpp:130-216 12 cases / 40 assertions (the predicate); test_dspark_draft_routing.cpp:368-460 7 cases / 19 assertions (REACHABILITY, entered through the LoadedEngine constructor, both published draft layouts). Mutation-proven 2026-08-18 in a scratch copy: deleting the IsDsparkDraft call, making it return constant true, and deleting the ResolveDsparkArchitecture call each turn the routing suite RED (rc=1). G5 run gate and G6 spec-off OWED, GPU/authority-blockeddspark-qwen3-routing.md (#1193)ACTIVECLAIM-SPEC-DSPARK-QWEN3-ROUTING
SPEC-DSPARK-BLOCK-SIZE-GUARDDSpark block floor, reached. SpeculativeConfig::ResolveDspark implements upstream's k >= dspark_block_size hard error, and BOTH production resolutions USED TO pass std::nullopt for n_predict AND for dspark_block_size, so the floor could not fire from any user path — the unpassed-parameter shape of .agents/reachability.md, exercised only by tests/vllm/config/test_speculative_dspark.cpp with hand-written values. The failure was SILENT: our draft step is sized only by k (DsparkBlockLayout::num_speculative_steps in include/vllm/v1/worker/gpu/spec_decode/dspark/speculator.h), nothing under src/vllm/v1/worker/gpu/spec_decode/dspark/ reads the draft's block key, and no weight is shaped by the block, so a short k tripped no VT_CHECK and drafted a structurally wrong block while the tokens kept flowing. A literal port would still not fire: upstream reads dspark_block_size, an identifier that appears nowhere in the pinned checkout except speculative.py, and NEITHER published Qwen3 draft carries it — deepseek-ai/dspark_qwen3_4b_block7 (Qwen3DSparkModel) and RadixArk/Qwen3.8-27B-DSpark @ 85ef153b (DSparkDraftModel, model_type qwen3) both carry block_size: 7 and no n_predict, and upstream's block_size normalization at :945-961 is Gemma4-only, so k=6 is accepted upstream on both sides of vllm#52197. LANDED: a file-local ReadDsparkDraftKeys threads the draft config.json's real values into the ONE resolution that remains. LoadedEngine::FromModelDir no longer resolves a second time with its own argument list — it delegates to LoadedEngine::ResolveSpecConfig before it touches the model directory and hands the result to the draft load — so one resolution applies the floor, defaults k from n_predict, and owns the messages. TWO recorded divergences, both argued in the spec: block_size supplies the floor when dspark_block_size is absent (§2), and the refusal runs BEFORE the model-directory error where upstream builds ModelConfig first (§2a). Upstream's threshold, wording and n_predict rules are otherwise unchanged, and the refusal now names the key the value was read from. test_dspark_block_size_guard is 14/14 with 39 assertions; the reachability mutations red it 8/14 and 2/14, and the spec's §6c records the one claim the tests do NOT carry. G3 (run) and G4 (spec-off) owed, both needing a GPU lease. Excludes the speculator, IsDsparkDraft and the architecture classification (SPEC-DSPARK-QWEN3-ROUTING)T1vllm/config/speculative.py:945-961,973-994,1003-1027 @ 555967922src/vllm/entrypoints/model_loader.cpp ReadDsparkDraftKeys + the ResolveDspark call in LoadedEngine::ResolveSpecConfig, which FromModelDir now delegates totests/vllm/entrypoints/test_dspark_block_size_guard.cppdspark-block-size-guard.md (#1225)ACTIVECLAIM-SPEC-DSPARK-BLOCK-SIZE-GUARD
SPEC-DRAFTER-CHAINA preference-ordered chain of speculators: try the first, and if it yields no draft for a sequence, try the next. ONE WINNER PER SEQUENCE, not an ensemble -- nothing merges proposals, nothing combines distributions, and the lossless verify is untouched because only one proposal ever reaches it. ADDITIVE BY CONSTRUCTION: a new OPTIONAL field on --speculative-config, inert when absent, so every document vLLM accepts keeps its exact meaning KEY FOR KEY (developer decision 2026-08-21) -- a meaning claim and deliberately not a byte-identity one, the single measured delta being that the accepted-key list quoted in an unknown-key refusal now also names vllm_cpp.drafter_chain, which is required because a list omitting an accepted key stops closing the user's search. Entries are methods this engine already implements (mtp, dflash, dspark, ngram), each carrying its own model and num_speculative_tokens -- which is why the shape is a list of OBJECTS and not llama.cpp's comma-separated name string. vLLM implements nothing here: SpeculativeMethod is a single Literal and SpeculativeConfig.method one value of it, verified at the parity pin 555967922 AND at origin/main c20572610, so llama.cpp is an admissible SECONDARY oracle for the chain's SEMANTICS only and never the mirror source. The obstacle is not the chain logic, it is that nothing here records WHICH speculator answered: no analogue of llama.cpp's impl_last, n_gen_drafts or n_gen_tokens, and no per-drafter acceptance counter. That matters because a fallback that never fires is indistinguishable from one that fires and helps -- the verify is lossless, tokens are identical either way, and only ACCEPTANCE moves. So attribution lands BEFORE resolution (W2 before W3): the instrument has to exist before the thing it measures, or the feature is unfalsifiableT2NONE -- vLLM has no composition surface at either revision checked. Secondary oracle llama.cpp: common/arg.cpp:3754-3763 (--spec-type splits on ,), common/speculative.cpp:2164-2186 (per-sequence drafting flag, impl_last[seq_id], n_gen_drafts/n_gen_tokens, loop breaks at n_drafting == 0), common_speculative_n_max (max over enabled types). Its type set has NO draft-dflash, so the pairing that prompted this row is not demonstrable thereW1 LANDED. SpeculativeChainEntry and SpeculativeConfig::drafter_chain plus use_drafter_chain() in include/vllm/config/speculative.h; ParseDrafterChain / ParseChainEntry / CheckEntryKeys in src/vllm/config/speculative.cpp, admitting the ONE new top-level name vllm_cpp into ParseSpeculativeConfigJson's existing #1160 key check; the production READER is LoadedEngine::ResolveSpecConfig in src/vllm/entrypoints/model_loader.cpp, which refuses a well-formed chain by name because nothing resolves one yet, called ahead of the path resolution by LoadedEngine::FromModelDir so the refusal precedes every weight operation. The document key is NESTED (vllm_cpp.drafter_chain), which is the same extension convention --offload-config already uses in src/vllm/config/weight_residency.cpp and which bounds the collision surface with vLLM's own SpeculativeConfig to exactly one name. OWED: resolution (W3), attribution and acceptance counters (W2, W4), draft_model as a chain entry, and two entries of one methodG1 PASS, G5 PASS (CPU, no device), W1. tests/vllm/config/test_speculative_drafter_chain.cpp 13 cases / 149 assertions / 0 failed; tests/vllm/entrypoints/test_drafter_chain_reach.cpp 7 cases / 78 assertions / 0 failed, both re-measured on the MERGED tree after the W1 repair (the earlier record said 136 for the first suite; the value never reproduced and was 135). G1 runs on REAL --speculative-config documents driven into ResolveSpecConfig and FromModelDir, never on a hand-built struct; G5's ordering half is asserted by refusing a chain against a model path that does not exist, so a guard placed after the path resolution returns the directory error instead and the case reddens. Eleven mutations at first landing plus three in the repair, all detected: deleting each of the two production call sites, REVERSING the parsed chain order, narrowing use_drafter_chain() to size() > 1 (which the repair's one-entry loader case now catches and no earlier reach case could), and deleting the class-2 entry-key branch (#1598). G2 attribution, G3 order and G4 per-drafter acceptance are PENDING with no instrument, which is what W2 exists to build. No throughput claim is admissible until G2 and G4 readdrafter-chain.md, #1522ACTIVECLAIM-SPEC-DRAFTER-CHAIN-W1

Serving surface, CLI, and library

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
SERVE-OAI-BASICChat/completions endpoints with SSE transportT0vllm/entrypoints/openai/completion/api_router.py:34; vllm/entrypoints/openai/chat_completion/api_router.py:40; tests/entrypoints/openai/completion/test_completion.py:50,259src/vllm/entrypoints/openai/api_server.cpp:60,108,183; src/vllm/entrypoints/openai/serving_completion.cpp:22,116; src/vllm/entrypoints/openai/serving_chat.cpp:231,380tests/vllm/entrypoints/openai/test_api_server.cpp:351,381,403,449,483,617; tests/vllm/entrypoints/openai/test_conformance.cpp:469,502,614,641planned: specs/chat-completions-endpoints.mdANCHOR-BACKFILL-
SERVE-DISCOVERY-HEALTHModels, health, and version endpointsT0vllm/entrypoints/openai/models/api_router.py:20; vllm/entrypoints/serve/instrumentator/health.py:22; vllm/entrypoints/serve/instrumentator/basic.py:53; tests/entrypoints/openai/models/test_models.py:48src/vllm/entrypoints/openai/api_server.cpp:149,158,167,215; src/vllm/entrypoints/openai/serving_models.cpp:22,50tests/vllm/entrypoints/openai/test_api_server.cpp:434; tests/vllm/entrypoints/openai/test_conformance.cpp:953,976,990planned: specs/models-health-version.mdPARTIAL-
SERVE-METRICSPrometheus /metrics with vLLM names. LANDED + CPU-GATED 2026-07-27 (CLAIM-ROADMAP-C8, NOT pushed): self-contained Prometheus registry (PromRegistry, text-format-0.0.4 exposition: counter _total, histogram _bucket{le}/_sum/_count, Info {labels} 1.0) + the ALWAYS-ON vLLM metric catalog (PrometheusStatLogger) registered 1:1 (names/help/type/buckets, {model_name,engine} labels) + record(SchedulerStats,IterationStats) + GET /metrics opt-in route. Gated by the vLLM scrape spec EXPECTED_METRICS_V1 (substring presence, RED-first). LIVE PER-STEP WIRING LANDED 2026-07-27 (CLAIM-ROADMAP-C8-METRICS-WIRE, NOT pushed): the /metrics endpoint now serves LIVE values, not the primed schema. EngineCoreOutputs carries scheduler_stats (filled by new Scheduler::make_stats(), scheduler.py:2399-2436 — running/waiting/kv-usage + the per-step prefix-cache delta stashed by schedule()) + a stamped timestamp; OutputProcessor::process_outputs builds IterationStats (token counts, TTFT/ITL samples, finished-request breakdowns via RequestState timing — stats.py:377-475); the sync LLMEngine::step() folds both into the attached logger's Record() guarded by outputs>0 (llm_engine.py:308-329). Additive + opt-in: null logger ⇒ no IterationStats, process_outputs byte-identical no-stats path, greedy token stream untouched. /metrics PRODUCTION-SERVING WIRING LANDED + CPU-GATED 2026-08-10 (CLAIM-SERVE-METRICS-ASYNC, #277) — the endpoint the shipped server actually exposes is now LIVE: the server serves every route from AsyncLLM, whose output handler recorded NOTHING, so a real deployment scraped a well-formed catalog whose series never moved (worse than an absent endpoint: it reads as idle). AsyncLLM::set_stat_logger mirrors logger_ref[0] (async_llm.py:648-652) as an atomic pointer; RunOutputHandler builds one IterationStats per step under a non-null logger (:664-665), threads it through process_outputs (:676-678) and folds it + scheduler_stats into Record() OUTSIDE the output-processor mutex (:697-702). Two enablers the fold needed: EngineCore::step_with_batch_queue now stamps scheduler_stats + timestamp exactly as step() does — upstream stamps both in the path BOTH step functions share (scheduler.py:1938-1951, engine/__init__.py:249-251), and unstamped they gave the depth-2 serving path all-zero gauges and TTFT == -arrival_time; and PrometheusStatLogger takes a leaf mutex over Record/Expose/SetCacheConfigInfo, since PromRegistry is not thread-safe and upstream only gets away with it under the GIL. server_main.cpp attaches the one logger to BOTH frontends. Additive + opt-in: no logger ⇒ byte-identical no-stats path. RESIDUAL: config-gated families (spec-decode/kv-connector/mm/LoRA); update_scheduler_stats (LoRA-only upstream); the chat/completion RESPONSE-BODY timing surface (SERVE-RESPONSE-METRICS)T0/T1vllm/entrypoints/serve/instrumentator/metrics.py:52-82; vllm/v1/metrics/loggers.py:480-1060,1100-1257,1284-1305; vllm/v1/metrics/stats.py:186-259,377-475; vllm/v1/core/sched/scheduler.py:2399-2436; vllm/v1/engine/llm_engine.py:308-329; vllm/v1/engine/async_llm.py:638-707 (_run_output_handler: :648-652,:664-665,:676-678,:697-702); vllm/v1/core/sched/scheduler.py:1938-1951 + vllm/v1/engine/__init__.py:249-251 (the stats/timestamp stamp both step paths share); scrape spec tests/entrypoints/serve/instrumentator/test_metrics.py:182-228registry include/vllm/v1/metrics/prometheus.h, src/vllm/v1/metrics/prometheus.cpp:13,189; catalog+record include/vllm/v1/metrics/loggers.h, src/vllm/v1/metrics/loggers.cpp:10,60,208; stats structs + MonotonicSeconds include/vllm/v1/metrics/stats.h:56,160,175,194; make_stats include/vllm/v1/core/sched/scheduler.h, src/vllm/v1/core/sched/scheduler.cpp (+prefix-delta stash in schedule()); scheduler_stats/timestamp on EngineCoreOutputs include/vllm/v1/engine/types.h, stamped src/vllm/v1/engine/core.cpp; IterationStats build src/vllm/v1/engine/output_processor.cpp (+RequestState timing include/vllm/v1/engine/output_processor.h); step-site Record src/vllm/v1/engine/llm_engine.cpp:99, setter include/vllm/v1/engine/llm_engine.h; ASYNC step-site Record + IterationStats src/vllm/v1/engine/async_llm.cpp:262, setter + atomic stat_logger_ include/vllm/v1/engine/async_llm.h; batch-queue scheduler_stats/timestamp stamp src/vllm/v1/engine/core.cpp:219; recorder mutex include/vllm/v1/metrics/loggers.h, src/vllm/v1/metrics/loggers.cpp:208,270; async attach src/vllm/entrypoints/openai/server_main.cpp:930; endpoint src/vllm/entrypoints/openai/api_server.cpp:251 (handle_metrics), route :488tests/vllm/v1/test_prometheus_metrics.cpp 4/4 (81 assertions: EXPECTED_METRICS_V1 substring gate RED-first, label schema, TYPE lines, bucket schedules, record() folding); live-wiring behavioural gate tests/vllm/v1/test_llm_engine.cpp case 6 (44 assertions, RED-first: 14 flip 0→correct when Record disabled) — running/waiting gauges track the batch, prompt/generation counters == exact token counts, request_success counts finished reqs, TTFT/ITL/e2e/TPOT/iteration histograms observe the right sample counts; endpoint tests/vllm/entrypoints/openai/test_api_server.cpp:921; ASYNC serving-path gate tests/vllm/v1/test_llm_engine.cpp:1025 "async_llm: live per-step stats populate the Prometheus registry" (asserts case 6's AND case 7's invariants on the AsyncHarness stack; RED-first: 19 of them read 0 unwired) + :1148 no-logger token-stream identity, and the depth-2 batch-queue pair tests/vllm/v1/test_async_llm.cpp:560,618 (running gauge poll — RED times out; TTFT/e2e _sum > 0 — RED negative/zero); CPU ctest 366/366prometheus-metrics.md, async-metrics.mdANCHOR-BACKFILLCLAIM-SERVE-METRICS-ASYNC
SERVE-RESPONSE-METRICSPer-request timing surface: the QUEUED/SCHEDULED/PREEMPTED EngineCoreEvents the scheduler emits + the per-request queue/prefill/inference timing intervals + preemption counter they feed. EngineCoreEvents + timing LANDED + CPU-GATED 2026-07-27 (CLAIM-ROADMAP-C8-RESPONSE-METRICS, NOT pushed): EngineCoreEventType{QUEUED,SCHEDULED,PREEMPTED} + EngineCoreEvent{type,timestamp} recorded on Request at the add_request / batch-admission / KV-preempt sites (1:1 with vLLM, gated on log_stats_, default no-stats path byte-identical), drained onto EngineCoreOutput.events via take_events(); OutputProcessor folds them (update_from_events) into RequestState.queued_ts/scheduled_tsFinishedRequestStats.queued_time(=scheduled−queued)/prefill_time(=first_token−scheduled)/inference_time(=last_token−scheduled) + IterationStats.num_preempted_reqs, feeding the vllm:request_{queue,prefill,inference}_time_seconds histograms + vllm:num_preemptions_total (already in the catalog, left at 0 by the live-metrics wiring for lack of events). Additive; scheduling/compute/token stream unchanged. ASYNC SERVING PATH COVERED 2026-08-10 (CLAIM-SERVE-METRICS-ASYNC, #277): these intervals only ever reached a registry through LLMEngine. They now populate through AsyncLLM too — its output handler folds the IterationStats these events fill, and EngineCore::step_with_batch_queue stamps the engine-core timestamp the intervals are measured against (unstamped it was 0.0, making every TTFT/e2e observation -arrival_time). Gated on the async stack by tests/vllm/v1/test_llm_engine.cpp:1025: queue/prefill/inference/decode _sum all > 0 and inference == prefill + decode. RESIDUAL: the streaming/non-streaming chat/completion RESPONSE-BODY timing surface (protocol/serving) + CLI validation.T1vllm/v1/engine/__init__.py:150-176 (EngineCoreEvent(Type)); vllm/v1/core/sched/scheduler.py:2135,1003,1221,461,1839 (record/take_events sites); vllm/v1/metrics/stats.py:428-476 (update_from_events / update_from_finished_request); response-body: vllm/entrypoints/openai/engine/protocol.py:118; vllm/entrypoints/openai/{completion,chat_completion}/serving.py:461-481,765-784 @ 555967922events include/vllm/v1/engine/event.h, Request.events+record_event/take_events include/vllm/v1/request.h; EngineCoreOutput.events include/vllm/v1/engine/types.h; emission src/vllm/v1/core/sched/scheduler.cpp (add_request/preempt_request/schedule/update_from_output) + log_stats_ include/vllm/v1/core/sched/scheduler.h; consumption src/vllm/v1/engine/output_processor.cpp (process_outputs) + RequestState.queued_ts/scheduled_ts include/vllm/v1/engine/output_processor.h; logger already consumes src/vllm/v1/metrics/loggers.cpp:225,254-257tests/vllm/v1/test_scheduler.cpp:420 "records QUEUED/SCHEDULED/PREEMPTED engine-core events" (15 assertions, RED-first, real KV-exhaustion preemption); tests/vllm/v1/test_llm_engine.cpp "per-request queue/prefill/inference timing populates" (26 assertions, RED-first: 5 flip 0→positive; asserts inference=prefill+decode, prefill≤inference≤e2e)per-request-response-metrics.mdANCHOR-BACKFILLCLAIM-ROADMAP-C8-RESPONSE-METRICS
SERVE-STREAM-USAGECompletion/chat stream_options: final and continuous native-ID usage frames, non-stream validation, and force-usage server mode. GATING: the host implementation is CPU/sanitizer-green; void 31d053f 27B execution proved exact native counts on all 2,016 standard timed requests, but fresh passing 27B→35B online and serialization A/B gates remain mandatoryT1vllm/entrypoints/openai/engine/protocol.py:241-243; completion protocol.py:66,471-478, serving.py:298-305,359-454; chat protocol.py:214,731-737, serving.py:459-512,570-760; entrypoints/serve/utils/api_utils.py:276-289; tests/entrypoints/openai/completion/test_completion.py:400-553; tests/entrypoints/openai/chat_completion/test_chat.py:348-445schema/parser include/vllm/entrypoints/openai/protocol.h:62,203,318, src/vllm/entrypoints/openai/protocol.cpp:103,223,278; selection src/vllm/entrypoints/openai/serving_utils.cpp:8; completion SSE src/vllm/entrypoints/openai/serving_completion.cpp:22,160; chat SSE src/vllm/entrypoints/openai/serving_chat.cpp:232,450; force CLI examples/server/main.cpp:123protocol/selection tests/vllm/entrypoints/openai/test_protocol.cpp:130,189; sync completion/chat tests/vllm/entrypoints/openai/test_serving.cpp:484,647; production final/continuous/validation/force/disconnect tests/vllm/entrypoints/openai/test_api_server.cpp:403,442,498,607,652,687,712; help examples/CMakeLists.txt:36. CPU CTest 105/105; focused 63 cases/658 assertions; API repeat 100/100; ASan+UBSan 3/3; TSan 1/1. 31d053f retained all 36 standard 27B raw points / 2,016 successful requests with exact native 128-token usagestream-options.mdGATING-
SERVE-UTILITY-ENDPOINTSTokenize, detokenize, ready, ping, server info, prefix reset. LANDED + CPU-GATED 2026-07-27 (CLAIM-ROADMAP-C8, NOT pushed): /tokenize (prompt form → {count,max_model_len,tokens,token_strs?}) + /detokenize ({tokens[]}{prompt}) over the existing tokenizer, /ping (liveness, mirrors /health), /server_info ({vllm_config,vllm_env,system_env}), /reset_prefix_cache ({"success":bool} via an injected callback). All ADDITIVE + opt-in (tokenize/detokenize/reset registered only when their backing is attached). CHAT-FORM /tokenize LANDED + CPU-GATED 2026-07-28 (CLAIM-C8-CHAT-TOKENIZE, NOT pushed): /tokenize now accepts BOTH arms of the vLLM TokenizeRequest union — the raw prompt form AND the TokenizeChatRequest{messages, add_generation_prompt, continue_final_message, add_special_tokens, tools?}; the chat form renders through chat_.prompt_fn() (the IDENTICAL model chat template create_chat_completion tokenizes through), applies the check_generation_prompt mutual-exclusion (→400), tokenizes with the chat-form add_special_tokens default False (vs completion-form True), returns the same {count,max_model_len,tokens,token_strs?}. /tokenizer_info LANDED + CPU-GATED 2026-07-28 (CLAIM-C8-SERVE-ENDPOINTS, NOT pushed): GET /tokenizer_info gated behind a set_tokenizer_info_enabled flag mirroring vLLM's enable_tokenizer_info_endpoint CLI arg (off by default → the route is not registered → 404; on + tokenizer attached → 200). Surfaces the tokenizer_config.json-equivalent fields our byte-level/SentencePiece BPE tokenizer can GENUINELY back — tokenizer_class (the BPE family name), model_max_length, vocab_size, bos_token_id/eos_token_id (omitted when -1), and added_tokens_decoder (id → {content,special,lstrip,rstrip}); NAMED gaps OMITTED (never fabricated): the raw chat_template string (lives in the ChatPromptFn render seam, not the tokenizer), the HF init_kwargs (clean_up_tokenization_spaces/add_bos_token/model_input_names/padding-truncation defaults — not parsed), and the added-token normalized/single_word flags. PRODUCTION main.cpp WIRING LANDED + CPU-GATED 2026-07-28 (CLAIM-C8-SERVE-PROD-WIRING, NOT pushed): the shipped vllm-server binary now lights /tokenize+/detokenize (on by default when a tokenizer exists) and /tokenizer_info (behind the new --enable-tokenizer-info-endpoint flag, mirroring vLLM's enable_tokenizer_info_endpoint) from the LIVE engine+tokenizer through the shared ConfigureUtilityEndpoints seam — the SAME seam the gate drives over a real socket. /metrics + /reset_prefix_cache stay UNWIRED (named residuals): the production AsyncLLM frontend exposes no live PrometheusStatLogger (async stats deferred; missing LoadedEngine::stat_logger() + a Record() site in AsyncLLM::RunOutputHandler) and no thread-safe prefix-cache reset RPC (reset_prefix_cache() is KVCacheManager-private, mutated only on the EngineCore thread; missing AsyncLLM::reset_prefix_cache), so attaching either would be a fabricated wiring that never reaches the live engine — library handlers+tests retained. RESIDUAL: chat_template_kwargs/continue_final_message full template-render passthrough (the ChatPromptFn seam renders only via the add_generation_prompt gate), /ready, full server_info config dump, live /metrics + /reset_prefix_cache backing on the AsyncLLM pathT1vllm/entrypoints/serve/tokenize/api_router.py:37,63,95-108; production gating vllm/entrypoints/openai/api_server.py:222, vllm/entrypoints/serve/__init__.py:11-31, vllm/entrypoints/openai/cli_args.py:140; vllm/entrypoints/serve/tokenize/protocol.py:24,50,156,166,181,185; vllm/entrypoints/serve/tokenize/serving.py:57,70-124,154-195; vllm/entrypoints/serve/sagemaker/api_router.py:47; vllm/entrypoints/serve/dev/server_info/api_router.py:43; vllm/entrypoints/serve/dev/cache/api_router.py:20handlers src/vllm/entrypoints/openai/api_server.cpp:262 (handle_tokenize, prompt+chat union),:368,404,245,422 (handle_detokenize/handle_reset_prefix_cache/handle_ping/handle_server_info),:438 (handle_tokenizer_info); chat render seam include/vllm/entrypoints/openai/serving_chat.h:197 (prompt_fn()); opt-in setters + routes include/vllm/entrypoints/openai/api_server.h:118 (set_tokenizer_info_enabled); production seam include/vllm/entrypoints/openai/api_server.h (ConfigureUtilityEndpoints) + src/vllm/entrypoints/openai/api_server.cpp (impl); production call + CLI flags examples/server/main.cpp (--enable-tokenizer-info-endpoint, ConfigureUtilityEndpoints(...))tests/vllm/entrypoints/openai/test_api_server.cpp:879 (prompt round-trip+schema+raw-form exact ids),:938 (chat-form renders template + exact tokens, RED-first),:1061 (/tokenizer_info backed fields + named-gap omissions + no-tokenizer 500),:1250 (opt-in route gate: 404 flag-off → 200 flag-on over a real socket, RED-first),:1319 (production ConfigureUtilityEndpoints seam over a real socket: no-seam→404 RED, defaults→tokenize/detokenize 200 + info/abort 404, flags-on→200, exact abort delta-count) — 32/32 / 420-assertion suiteutility-endpoints.mdANCHOR-BACKFILLCLAIM-C8-SERVE-PROD-WIRING
SERVE-CHAT-TEMPLATEFull-surface Jinja chat templates (vendored google/minja 021c229 + documented lstrip guard)T0vllm/renderers/hf.py:673,986; vllm/entrypoints/chat_utils.py:1248,1335src/vllm/entrypoints/chat_template.cpp:101,168,181,220tests/vllm/entrypoints/test_chat_template.cpp:65,75,84,96planned: specs/chat-templating.mdANCHOR-BACKFILL-
SERVE-ASYNC-LLMAsyncLLM-equivalent streaming engine API: per-request collectors, concurrent submit/generate/abort, live completion/chat SSE with disconnect abort, additive nonblocking C requests, and enough HTTP delivery capacity for configured concurrent streams. GATING: deterministic c32 capacity is implemented and GPU-classified; broader every-axis parity remains open. CLARIFIED 2026-08-12 (#534) — this row is NOT waiting on a "prod-ON" flip, which is what punch-list item 9 and the ROAD-V1-A SGLang clause both read it as. It IS the production serving path (src/vllm/entrypoints/openai/server_main.cpp:731-734, "the production server uses AsyncLLM over EngineCoreProc's dedicated engine thread"), with the capacity-derived fixed HTTP pool as the default and VLLM_CPP_HTTP_FIXED_POOL=0 retained only as a same-binary diagnostic; the separate runner-side VT_ASYNC_RUNNER/runner_supports_async default is ENG-ASYNC-SCHED's and has been ON since a0013a2. What remains is exactly the every-axis parity named above: 27B ratified (two-grid 115/124 effective), 35B open under ROAD-V1-A, plus open bug #294. Its GPU token-exact gate is tests/parity/test_qwen36_async_serving.cpp (1718bf155) — NOT qwen36_paged_engine, which drives the sync depth-1 path and structurally cannot see this row's defectsT0vllm/v1/engine/async_llm.py:70,280,524,637,709; vllm/v1/engine/output_processor.py:45-105; asyncio server path vllm/entrypoints/openai/api_server.py:1; tests/v1/engine/test_async_llm.py:109,157,228,306,340,598existing async path include/vllm/v1/engine/async_llm.h:45, src/vllm/v1/engine/async_llm.cpp:32; fixed/legacy pool API include/vllm/entrypoints/openai/api_server.h:41-57,101-104; capacity selection src/vllm/entrypoints/openai/api_server.cpp:23-62; production max-seqs wiring + VLLM_CPP_HTTP_FIXED_POOL=0 A/B src/vllm/entrypoints/openai/server_main.cpp:874-883 (moved verbatim out of examples/server/main.cpp by ARCH-ONE-SURFACE #189; the example is now a one-line vllm_server_main client); cpp-httplib defect third_party/httplib/httplib.h:161-169,10359-10377persistent 32-client + control reserve, validation and diagnostic-mode cases tests/vllm/entrypoints/openai/test_api_server.cpp:937-1000; focused Release/help pass, API 100/100, ASan+UBSan 1/1, TSan 1/1; known unrelated serial C-API flake isolated. Exact fixed/legacy c32 AB/BA/AB is healthy and steady-state-neutral: 1097.031/1097.290 tok/s = 0.999764×, 8/20 axes, 1,152/1,152 requests and six memory returns; neither legacy arm samples the rare old stall. Exact 4e1d8ca fixed c32 is healthy 3/3 and 0.9910× vLLMasync-serving.mdGATING-
SERVE-HTTP-TRANSPORTServing-socket transport parity: mirror vLLM's uvicorn/asyncio default TCP_NODELAY on every accepted SSE socket so per-token stream frames are not held by Nagle against the peer's delayed ACK. Implemented + CPU-tested; the non-binding localhost A/B sizing is COMPLETE and NEUTRAL within noise on c1/c2 ITL/TPOT/throughput (loopback ACKs are instant, so Nagle never coalesces ~100 ms-cadence token frames) — no gate-axis credit expected; the mirror stays for real-network parity. Future keep-alive / read-write-timeout / listening-socket option parity noted, not doneT0vLLM serves via uvicorn over asyncio vllm/entrypoints/launcher.py:71,76, vllm/entrypoints/openai/api_server.py:591,630; asyncio disables Nagle per accepted TCP stream socket asyncio/base_events.py:192-197 (_set_nodelay) called from asyncio/selector_events.py:950; cpp-httplib default-off third_party/httplib/httplib.h:142, applied on accept only when set third_party/httplib/httplib.h:12083src/vllm/entrypoints/openai/api_server.cpp:69 (set_tcp_nodelay(true) in the ApiServer setup)behavioral accepted-socket getsockopt(TCP_NODELAY) case tests/vllm/entrypoints/openai/test_api_server.cpp:1076 (helper :380); RED accepted TCP_NODELAY 0 → GREEN 1, full test_openai_api_server 22/22 cases / 242 assertions; non-binding sizing root ~/work/vllm.cpp-tcpnodelay-sizing/ff915e8… (raw-set SHA f5b52900…2128) neutral within noise; closure ledgerserve-tcp-nodelay.mdDONEff915e8
SERVE-C-ABIStable LocalAI-style C FFI (19 exported VLLM_API symbols at VLLM_ABI_VERSION 10; blocking and nonblocking request handles. Count corrected 2026-07-24 from a stale 17, which predated ABI v4/v5 adding tool_parser/reasoning_parser and the chat entry points; include/vllm.h is the source of truth and README:231 already said 19). ABI v9 2026-07-28 (CLAIM-CAPI-ENGINE-CONFIG-V9): the ABI carried strictly LESS engine config than EngineParams does - max_num_batched_tokens, the scheduler scheduling_policy (fcfs / priority / lpm), and kv_transfer_config (the external KV connector / LMCache JSON) were reachable from the bundled server's flags and from NO embedder. All three added, inert at their defaults (zero-filled v8 growth == byte-identical pre-v9 engine); the connector NAME is validated against KVConnectorFactory at load, mirroring the server's startup check. tokenizer_config_path stopped being a declared-since-v1 no-op and now selects the chat template's source file. Malformed speculative_config/kv_transfer_config documents now report VLLM_ERR_INVALID_ARGUMENT (the contract vllm.h documented since v6) instead of VLLM_ERR_MODEL_LOAD, via a catch scoped to the parse block so a real FromModelDir failure still reports MODEL_LOAD. Driver: the LocalAI vllm-cpp backend could not expose LMCache or the prefill budget in a model config)T0Original project ABI; pinned vLLM has no C ABIinclude/vllm.h:143,181,207; src/capi/vllm_c.cpp:229,264,327,391tests/capi/test_capi.cpp:320,428,505,574,606,640; tests/capi/test_dlopen.cpp:77,86; tests/capi/c_header_compile.c:1c-api-library.mdANCHOR-BACKFILLCLAIM-SERVE-C-ABI-SPIKE
SERVE-CPP-APIRich LLM and AsyncLLM C++ APIT1vllm/entrypoints/llm.py:66,422; vllm/v1/engine/async_llm.py:70--planned: specs/cpp-api.mdINVENTORIED-
SERVE-CLI-BENCHServe and latency/throughput/serve benchmark modesT0vllm/entrypoints/cli/serve.py:44; vllm/entrypoints/cli/benchmark/main.py:29; production queue vllm/v1/engine/core.py:200-231,622-669; pinned comparison pretokenizes before timing and synchronously admits a complete concurrency wave before each explicit step tools/bench/vllm_closed_loop_metrics.py:57-102,137-167separate binaries + explicit scheduler-capacity flags examples/server/main.cpp:63,96,116,170; production AsyncLLM benchmark frontend + auditable scheduler depth; #206 default pre-encodes every prompt before t0 and admits token IDs, exact VT_BENCH_PRETOKENIZE=0 retains timed-string admission, and BenchResult reports the resolved path (examples/bench/bench_core.h:190-233,616-665). Atomic queue/wave admission prepares every request and collector before one all-or-zero ordered core publish (include/vllm/v1/engine/core_proc.h:90-126; src/vllm/v1/engine/async_llm.cpp:125-237)server-help/production-frontend/metric assertions plus #206 parser/callback identity, preparation-before-clock, special-token/InputProcessor parity, report-mode capture and synthetic exact-ID A/B (tests/examples/test_bench.cpp:123-186,347-376). Atomic queue 3/3·13 (tests/vllm/v1/test_engine_core_proc.cpp:233-299); ordered/rollback/shutdown wave gates and complete async suite 12/12·433 (tests/vllm/v1/test_async_llm.cpp:288-484), all CPU-GREEN. Real a33993a7 A/B FAILED token identity (98/128 requests, 15,507/16,384 positions); no timing credit. Fresh mutation review, operator gate and real counterbalanced retry remain pendingCLI/serve/benchmark spike; #206 campaign contractPARTIAL-
SERVE-GATE-ONLINESame-corpus online correctness, TTFT/TPOT/ITL, throughput and peak-memory gate vs vLLM v0.25.0T0vllm/benchmarks/serve.py:1,581-615; v0.25 audit; tests/benchmarks/test_serve_cli.py:1Schema-v5 harness plus trace controller, production component driver, and fail-closed component finalizerBINDING 9ecd9d0: 114/124 (async default ON; mem 4/4, c1 20/20, c2 20/20, c16 19/20, c4 & c32 18/20, c8 15/20; benchmark_binding refers here, superseding 3f256ab 55/124 and 246a23c 49/124, both retained immutable). Two-grid totality with f0fb727 (111/124) is 115/124 effective parity vs vLLM 0.25.0 (27B). Async CLOSED the c16/c32 ITL tails (ours now BEATS vLLM: c16 p99 1.055, c32 p90 1.034/p99 1.078) and leaves a stable c8 p99_itl ~0.86 residual, ROOT-CAUSED (2026-07-18, CLAIM-C8-P99-TAIL-1, spec) as IRREDUCIBLE-AS-MIRRORED: our deterministic synchronous forward keeps co-admitted c8 requests in byte-identical lockstep where vLLM's async-future jitter de-phases them; the c16/c32 INVERSION proves this is the trailing edge of the per-step determinism that wins c16/c32 + throughput, not a capability gap (scheduler + async placeholder byte-identical, tests/vllm/v1/test_scheduler_wave.cpp:265, tail spec). Full grid + per-binding forensics: roadmap_v1.md + parity ledger; no packed speed creditonline serving gate; merged GDN projections; packed decodeANCHOR-BACKFILLCLAIM-SERVE-GATE-1
SERVE-E2E-NIGHTLYServer conformance and real-model nightly suites for all release gatesT0tests/entrypoints/openai/; tests/v1/e2e/; .buildkite/test-pipeline.yamlcurrent unit/conformance tests only; no scheduled DGX suitetests/vllm/entrypoints/openai/test_conformance.cpp:1; tests/parity/test_qwen36_paged_engine.cpp:78; tests/parity/test_qwen27_paged_engine.cpp:110planned: specs/server-e2e-nightly.mdINVENTORIED-
ENG-RELEASE-BINARIESDownloadable host-ABI-specific vllm-server bundles: adaptive CPU and fat CUDA primary artifacts, optional per-SM diagnostics, and literal-static feasibility boundaryT0vLLM release lanes .buildkite/release-pipeline.yaml:1-18,34-170 @ 555967922; release-image dependency boundary docker/Dockerfile.cpu:262-290Required W1-W11/W13 implementation is complete: ten-SM gencode/AOT, adaptive CPU tiers, extracted-archive validation and supply chain, least-privilege immutable handoff, eight primary bundles, byte-derived indexes, attestation, and exact-file publication; W12 remains optional/non-primaryv0.0.2 published eight archive/checksum/provenance triplets plus two indexes from 7020de93652ca920424a10ac5255b34810dd2f24 in run 31466516224 (26 assets). Matching-hardware axes and the Windows v0.0.3-pre.1 extension remain pendingrelease-binary-matrix.mdACTIVECLAIM-ENG-RELEASE-BINARIES-W1-W13
ENG-RELEASE-WINDOWSNative Windows x86_64 pre-alpha release extension: one adaptive MSVC/UCRT CPU bundle with AVX2 executed in CI and one Vulkan preview bundle, both deterministic ZIPs and authenticated by the existing release handoffT0vLLM has no Windows release path; runtime behavior remains pinned to vLLM 555967922. Platform substrate reference: llama.cpp src/llama-mmap.cpp:520-590 @ 237ad9b961f009ae19ac29dbce4cd0c1251f94b3; Win32 API is the OS authorityW14 Win32 portability/MSVC CPU, W15 deterministic ZIP/PE packaging + Vulkan, and W16 ten-tuple prerelease workflow/version/docs implemented for one PRLinux portability/release mutation gates are local evidence only. Native windows-2022 MSVC /W4 /WX, extracted runtime/ISA smokes, merged-SHA ten-tuple dry run, v0.0.3-pre.1 publication, attestations, and exact 32-asset audit remain pending; no Windows ZIP exists yetwindows-binary-release.md; #117ACTIVECLAIM-ENG-RELEASE-WINDOWS
ENG-RELEASE-CONTAINERSPublished OCI container images on GHCR, built by GitHub Actions: the same staged server bundle as ENG-RELEASE-BINARIES, shipped from one package ghcr.io/mudler/vllm.cpp with the lane in the tag — :<version>-cuda / -vulkan / -cpu, the moving :latest-cuda / :latest-vulkan / :latest-cpu, and a bare :latest aliasing the cpu lane, with ENTRYPOINT vllm-server. Lanes cuda (one fat image covering every supported SM), vulkan, cpu (adaptive baseline); rocm blocked-preview, tracking its binary channel. Version tags are immutable; every latest-<lane> moves. Each lane is a linux/amd64 + linux/arm64 multi-arch manifest built on native runners — aarch64 is first-class here because GB10 (sm_121a), Thor (sm_110) and Orin (sm_87) are all arm64. The image contains the bundle and nothing else: no weights, no Python, no PyTorch, no compiler, no build tree. BOUNDARY: the GPU driver and container runtime stay on the host and are never bundled; Metal and MLX are NOT-CONTAINERIZABLE (no macOS container runtime and no Metal passthrough exists) and remain static-binary-only lanes, recorded as a permanent boundary rather than pending work. No image, workflow, registry package or pull is claimed to exist.T0release image lanes .buildkite/release-pipeline.yaml:34-170 and the published-image dependency boundary docker/Dockerfile.cpu:262-290 @ 555967922docker/Dockerfile (cpu/vulkan/cuda targets calling the release scripts); docker/healthcheck.sh; release/container-matrix.json; scripts/check-container-matrix.py; scripts/check-container-workflow.py; scripts/validate-container-image.py; scripts/container_tags.py; .github/workflows/containers.yml; SIGTERM handler src/vllm/entrypoints/openai/server_main.cpp (SignalShutdown, all three listen() sites); the pre-existing docker/Dockerfile.arm64 is an unrelated CPU bench cross-checkissues #170, #312, #394; tests/scripts/test_check_container_matrix.py 31/31; test_check_container_workflow.py 29/29; test_check_cuda_fat_gencode.py 7+4 subtests. GB10 2026-08-11 (promaxgb10-4ad8, sm_121a, CUDA 13.3): arm64 cuda image 1.71 GB, 673/673 objects, ten-SM gencode audit PASS, and a REAL GPU boot -- /health 200, /version 200, in-container healthcheck, clean SIGTERM, --gpus all, host driver 580.159.03 injected. cpu amd64 783 MB gated locally; cpu+vulkan amd64 green on hosted CI arm64 cuda lane RUNTIME-VERIFIED on GB10 2026-08-11 -- the first accelerator-hardware evidence for any lane. Four defects were removed to get there, each found by building rather than reading: the CUDA 12.9 base could not compile sm_110, the BuildKit cache mount outlived its toolchain (both #366), Marlin gencode had drifted from the feature table and failed the audit on 14 correctly-compiled TUs (#394, blocking BOTH cuda tuples project-wide), and the validator could only ever produce build evidence because its boot smoke never passed --gpus. NOT established: nothing is published to GHCR; amd64 cuda is unbuilt; the published arm64 image is SBSA (targets/sbsa-linux), so Tegra -- Thor sm_110, Orin sm_87 -- is untested and NOT covered ORIN (Tegra) 2026-08-11: the SBSA image RUNS on Jetson AGX Orin sm_87 (L4T R36.4.3, Docker 27.5.1) -- Qwen3-0.6B (rev c1899de2) loads and GENERATES via /v1/completions, tegrastats GR3D 95-97% during decode vs 14-15% idle. Tegra needs --runtime nvidia --gpus all: --gpus alone is refused by the hook and --runtime alone mounts no drivercontainer-images.md; issues #170, #312, #394ACTIVECLAIM-ENG-RELEASE-CONTAINERS-W1-W7
ENG-DOCS-SITEPublish the 11 docs/*.md as a browsable GitHub Pages site at https://mudler.github.io/vllm.cpp/ WITHOUT a second copy of the prose. A Hugo site at website/ mounts ../docs READ-ONLY and derives everything else from what is already in the files: each page title from the file's first # H1, the sidebar order from website/data/nav.yaml, and links through a Goldmark render hook (internal .md → site URL; the 139 ../.agents/** and ../AGENTS.md escapes → GitHub blob URLs, since the protocol tree is deliberately NOT published). No file under docs/ is modified, moved, renamed, or given front matter, so check-doc-checkpoint.py and every protocol path reference keep working and there is no second surface that can drift — the whole point of the row. Custom lean layouts, NO theme and NO submodule: off-the-shelf docs themes read titles, weights and menus out of front matter this design deliberately does not have, so each would need its title partial, menu and link hook overridden anyway, and hugo-book additionally floors at Hugo 0.158 against the 0.146.3 pin CI and the local toolchain share. Hard prerequisite inside the repo: classify_path in scripts/check-pr-size.py FAILS CLOSED on website/** (verified: raises ValueError: unclassified repository path), so the classifier must learn the path or the PR cannot pass the project's own size gate. Hard prerequisite outside it: GitHub Pages must be enabled with the source set to GitHub Actions — the workflow is inert otherwise. A marketing landing page is explicitly OUT of scope (README.md stays the front door), as is any restructuring of docs/; the custom domain is parked behind the pending vLLM trademark questionT1NO vLLM analogue — upstream's docs are a separate mkdocs site and nothing in this row mirrors upstream behavior, so it carries no parity obligation. The STRUCTURAL reference is LocalAI's .github/workflows/gh-pages.yml (two Hugo sites merged into one Pages artifact), reduced to the docs halfread-only mount website/hugo.toml:29; title-from-H1 website/layouts/partials/title.html:10; link rewriting website/layouts/_default/_markup/render-link.html:27; guard scripts/check-site.py:70; deploy .github/workflows/gh-pages.ymltests/scripts/test_check_site.py:51,56,66,80,89,97 (6 mutation cases: clean tree, H1 stripped, doc absent from nav, nav entry with no file, duplicated entry, missing nav file); build evidence 14 pages with docs/bench-evidence + docs/superpowers absent from public/ and no href ending in .md; 48 protocol links rewritten in docs/status/. NO published page is claimed: GitHub Pages is not yet enabled on the repository, which is the recorded stop condition holding this row at GATINGgh-pages-docs-site.md; issue #224READYCLAIM-ENG-DOCS-SITE
ENG-RECORD-ANCHOR-RATCHETThe record's path:line citations were range-checked and never reported. check-agent-record.py parsed BOTH forms: markdown links, and bare `file.cpp:123` through RAW_LOCAL_ANCHOR_RE since ee511ca8a. On a missing file or an out-of-range line local_line_anchors runs continue, so the bad anchor never reaches the caller, and is_code_anchor then answers with any, so one good sibling covers the rest. There was no symbol test and no report, and 32 of the 38 offenders are IN RANGE, so range-checking could not have found them. Measured at 8daa67b39: 832 of 867 in-scope citations (96.0%) were already parsed and range-checked, and the 35 new to parsing sit under .agents/, docs/ and website/; EVIDENCED_STATES omits ACTIVE/READY entirely and is deliberately NOT widened, because requiring an anchor there raises 85 errors across 53 rows. Even the fraction it saw was only range-checked, never checked to CONTAIN the symbol named beside it — every stale anchor found in the 2026-08-13/14 campaign was in range. LANDED as a device-leakage-shaped ratchet over a recorded baseline, never a bulk cleanup: the backlog is fixed by whoever next touches each rowT1none — this is our own record surface; the discipline mirrors AGENTS.md §Records ("cite the file:line you ported from")parser + classifier + ratchet in check-agent-record.py: scripts/check-agent-record.py::BARE_CITATION_RE (the bare form), scripts/check-agent-record.py::cell_citations (both forms, with the adjacent-symbol rule), scripts/check-agent-record.py::classify_citation (OK / STALE / BROKEN), scripts/check-agent-record.py::RECORD_ANCHOR_STATES (gap 3: ACTIVE and READY join the count), scripts/check-agent-record.py::check_record_anchors (the two-way gate). SYMBOL-anchored rather than line-anchored as of SPEC-DFLASH2 W2, which added a justification paragraph to this file's KERNEL count and shifted all five ranges by 14 lines at once -- the rot this row exists to measure, produced by an edit to the very file the row cites; budget in scripts/record-anchor-baseline.jsonRecordAnchorRatchet tests/scripts/test_agent_record.py:1397 — 10 cases, RED-first, including test_one_good_link_does_not_cover_a_rotted_bare_citation tests/scripts/test_agent_record.py:1465, the any() shape the rot hid in. Five mutants red it: report-only, EVIDENCED_STATES restored, links-only, first-citation-only, range-only. Measured baseline 38 (32 STALE + 6 BROKEN); gate wired in scripts/agent-preflight.sh and the agent-record CI job (--report)record-anchor-ratchet.mdACTIVECLAIM-ENG-RECORD-ANCHOR-RATCHET
ENG-RECORD-CONFLICT-SURFACESRetire the shared record surfaces that make concurrent PRs conflict by construction. MEASURED at origin/main d928e2c3 with git merge-tree --write-tree over every open PR: 16 of 29 conflict (55%), and 13 of the 16 conflict in bookkeeping files ONLY, with no product code involved — .agents/coordination.md in 8, .agents/NOW.md in 5, .agents/roadmap_v1.md in 4, scripts/check-public-doc-tables.py in 4, docs/STATUS.md in 4, and any src//tests/ path in just 3. Three defects, each of which GUARANTEES rather than risks a collision. (1) .agents/NOW.md is a fixed-size shared buffer at EXACTLY 6000/6000 chars (check-now-current.py:31), so adding a row requires evicting another and every PR is a read-modify-write of one global — and the conflict is the LUCKY outcome, since a clean three-way merge would apply both evictions and both additions, silently dropping live rows and blowing the very budget the checker defends. (2) STATUS_RATCHET = {"chars": 243245} (check-public-doc-tables.py:557) is a hardcoded byte count of a DIFFERENT file that may only fall, so a PR owing docs/STATUS.md one lifecycle line must delete unrelated prose from another row to pay for it and edit the checker too; the checker's own comment at :331 already records the failure ("a ratchet pinned to the byte turns every concurrently merged row's one-line status edit into a spurious failure") and answered it with slack instead of removing the coupling. (3) .agents/coordination.md's active-claims table is insert-at-one-anchor: the six ROCm GDN PRs (#334 #336 #341 #343 #345 #348) are ONE author's sequential stack that conflicts on nothing else, each appending a ~1,500-char row — the PR description, transcribed into a file every other claim also writes. It also contradicts the protocol it serves: AGENTS.md holds that "History is git" and "There is no state log", yet both claims tables ARE state logs duplicating gh pr list, row/<ID> branch names and issue state; the argument that refuses a waiver registry applies unchanged to a claims registry. Precedent twice over — policy.csv retired in 0f3e44ee, per-class line budgets retired 2026-08-10 because the gate fired on ordinary work. The exonerated surfaces share ONE property, one writer per file: .agents/specs/<slug>.md (one file per row, zero conflicts in the sample), the *-matrix.md inventories, and the append-only .agents/benchmark-record.md. SCOPE: remove STATUS_RATCHET and the doc-gating global counters while KEEPING the per-cell/per-paragraph caps (local, so they couple nothing); remove the active-claims table and derive claims from open PRs and branch names; drop NOW.md's byte budget; order the roadmap's keyed tables by ID so distinct keys stop colliding at one anchor; and record the invariant — no surface that every PR must write — in AGENTS.md. No product source, kernel or gate semantic movesT0NO vLLM analogue — this is local protocol machinery, so the mirror rule does not apply and no upstream file:line exists to port from. Governed instead by AGENTS.md §"Changing the rules or a checker", which requires a spec, a red-before test or mutation, and green-after evidence-- (spec-before-code: the red-before suites are named in the spec's Tests section — tests/scripts/test_check_public_doc_tables.py, tests/scripts/test_check_now_current.py, a mutation case per removed rule proving the obligation survives in the retained caps and check-doc-checkpoint.py, and a git merge-tree merge-shape regression that must be RED before the NOW.md/roadmap work and GREEN after)retire-shared-record-surfaces.md; issue #364READYCLAIM-ENG-RECORD-CONFLICT-SURFACES
ENG-TRAILER-MERGE-ARTIFACTSThe trailer gate rejects CORRECT commits because of paragraph placement, and that is why main is red on agent-record. check-commit-trailers.py reads trailers via git interpret-trailers --parse, which treats ONLY the final paragraph as the block; GitHub appends Co-authored-by: as a SEPARATE trailing paragraph on a squash merge, so a complete correct block becomes invisible and the gate reports it missing. MEASURED: piping git show -s --format=%B dbd0d51c into git interpret-trailers --parse prints nothing but the co-author line, and 13 of the last 30 commits on main fail the check -- unnoticed only because those runs were cancelled (#274), which HID the defect rather than causing it. FIX: fuse consecutive trailing TRAILER-SHAPED paragraphs before parsing. Nothing is relaxed -- the block must still exist, the marker must still sit above it, each declaration must still appear exactly once, and an AI co-author is still forbidden; the block is merely FOUND where the merge tool left it. A prose paragraph still terminates it. REJECTED IN FLIGHT and recorded because it is the more instructive half: a first attempt also collapsed identical duplicate trailers to fix the multi-commit-squash shape, which relaxes the uniqueness rule an existing test already pins. Rewriting that assertion to suit the change is what AGENTS.md forbids, and the distinction is real -- a doubled block is genuinely malformed and fixable at source, whereas the co-author case is a correct commit defeated by the parser. Reverted in full. SCOPE LIMIT, stated rather than implied: this fixes ONE of five observed shapes. f64f2b71 (bot co-author) is a REAL violation the parse had been hiding and now correctly fails; 87308dea (GitHub's --------- separator), b8293c88 (squash doubled the block) and b580452d (merge button, no trailers) stay red by design. Closing those is a merge-method change, not a checker changeT0NO vLLM analogue -- local protocol machinery, so the mirror rule does not apply and there is no upstream file:line to port from. Governed by AGENTS.md §"Changing the rules or a checker"scripts/check-commit-trailers.py:60 (join_trailing_trailer_paragraphs, _is_trailer_paragraph, and the fused parsed_trailers)tests/scripts/test_check_commit_trailers.py:1 21 cases -- the RED-BEFORE appended-co-author case plus four GUARDS that keep the fusion bounded (doubled block still fails, contradictory declarations still fail, a no-trailer merge message still fails, prose after the block still fails), all four green before and after; closure parity-ledger.md#L941trailer-merge-artifacts.md; issue #406DONE157080c8
ENG-FORGE-COAUTHORThe forbidden-AI-trailer rule was catching ATTRIBUTION rather than an authorship claim, which is why bot-opened PRs red main on merge. GitHub composes the squash message itself and appends the account that opened the PR — Co-authored-by: localai-org-maint-bot <...@users.noreply.github.com> — and most PRs here are opened by a bot, so nearly every squash trips the AI-identity check. Real instance f64f2b71, invisible until #406 repaired the parse, which is why it reads as a new failure and is not one. The rule exists so an AI cannot claim it WROTE the code, and that stays; GitHub is recording who pressed the button, and the AI-involvement claim is already carried separately by AI-Assisted and Assisted-by in the same block. FIX: accept a Co-authored-by at a GitHub account noreply address even when the name matches an AI identity token, keyed on the FORGE'S OWN DOMAIN rather than the name so the exemption cannot be borrowed. A hand-written Co-authored-by: Claude <claude@anthropic.com> still fails; Signed-off-by is excluded from the exemption entirely, because a sign-off is a legal assertion about provenance rather than attribution. AGENTS.md records the same distinction in the same change so prose and checker cannot driftT0NO vLLM analogue -- local protocol machinery, so the mirror rule does not apply and there is no upstream file:line to port from. Governed by AGENTS.md §"Changing the rules or a checker"scripts/check-commit-trailers.py:38 (FORGE_ACCOUNT_EMAIL and the forbidden-trailer skip)tests/scripts/test_check_commit_trailers.py:1 25 cases -- the RED-BEFORE forge-bot case plus THREE guards that matter more than the relaxation because this LOOSENS a rule: a hand-written AI co-author still fails, Signed-off-by at the same noreply address still fails, and a human co-author still passes; all three green before and after. Real commit f64f2b71 re-verified per commitforge-coauthor-attribution.md; issue #418ACTIVECLAIM-ENG-FORGE-COAUTHOR
ENG-NOW-DERIVEDW1-W5 remove the per-row .agents/NOW.md write: each moved row's own spec carries ## Now, scripts/now.py renders the live roster offline-first, and the digest cannot regrow a row table. Implementation merge dbd0d51c; progressive legacy-spec backfill is the selected compatibility policy, not remaining work. Runtime/performance/parity are VOID because this is local protocol machineryT0No vLLM analogue; governed by AGENTS.md §Changing the rules or a checkerscripts/now.py:163; scripts/check-now-current.py:57; AGENTS.md:409tests/scripts/test_now_render.py:34; tests/scripts/test_check_now_current.py:1; closure parity-ledger.md#L939now-derived.md; issue #374DONEdbd0d51c
ENG-UPSTREAM-OMNI-PINPin vllm-project/vllm-omni, the SEPARATE repository holding every omni-only architecture (MiniMax-H3, LTX-2.5, and the ~40-module TTS family incl. IndexTTS-2.5). Its pin now lives in the oracle registry .agents/oracles/vllm-omni.md landed by #650, which records the truth today: pin = UNPINNED, gateable = no, evidence = #633. So the RECORD is no longer missing; the PIN is, and with it any oracle-run gate for those lanes. What this row still owes is what the registry file cannot state on its own: the two pins may legitimately DISAGREE (vllm-omni requires vLLM 0.27.0+ against our 0.26.0.dev0 parity pin, so forcing them equal would move every gated row to suit a lane that touches none), an omni-gated number is therefore labeled with BOTH commits and is NEVER evidence about the core pin's surface, and an omni pin advance does NOT re-open the vLLM-side binding grids provided the omni oracle is isolated in its own virtualenv and touches neither ${VLLM_SOURCE} nor the environment the parity pin measures itself from. NOTE this spec was rewritten mid-flight: its first draft proposed a second pin block inside upstream-sync.md, which #650 superseded with the one-file-per-oracle registry, and the row now proposes no record format at allT1vllm-project/vllm-omni vllm_omni/model_executor/models/registry.py; source-audited at a4ea67a2 (v0.26.0) and at bbe6ccc512a404a2df8c977ea29003002f2683e8 (#609, #610) -- neither is a pin, both read sourcenone -- protocol change, no product codetests/scripts/test_agent_record.py test_omni_pin_row_is_inside_the_engine_ratchet (RED-first vs the exact bad merge: row dropped, ENGINE_ROWS rewound, rollup rewound, every count agreeing -- 1 of 53 tests fails and it is that one). W3-W5 assertions owedupstream-omni-pin.md; issue #633READYunassigned
SERVE-CLI-CHATInteractive chat and complete commands against a running OpenAI-compatible server, plus preservation of the existing local-model completion invocationT1registration vllm/entrypoints/cli/main.py:17-37,73-98; client/model resolution + stream shaping vllm/entrypoints/cli/openai.py:30-100; chat :155-234; complete :237-312 at 5559679229current in-process completion only examples/cli/main.cpp:1-207; remote command implementation absentC-ABI stream baseline tests/capi/test_capi.cpp:567-711; chat-template baseline tests/capi/test_chat_prompt.cpp:37-89; command/fake-server tests absentcli-chat-complete.mdANCHOR-BACKFILLCLAIM-SERVE-CLI-CHAT-SPIKE
SERVE-RECIPE-ARGSAccepted-and-inert serve arguments: an enumerated table of flags that published recipes pass, that are no-ops for this engine, and that must therefore not abort argument parsing. Not a catch-all — anything unlisted still aborts, and mirrored validation still fires. Found by the 2026-08-13 recipe-surface sweep: vllm-serve rejects unknown arguments (src/vllm/entrypoints/openai/server_main.cpp:440), so --enable-auto-tool-choice (89/157 official recipes) and --trust-remote-code (82/157) stop the server before model load even though neither means anything here — including for models we ship token-exact and gatedT1vllm/entrypoints/openai/cli_args.py:105 (enable_auto_tool_choice default), :395 (requires --tool-call-parser, a TypeError otherwise — mirrored, not dropped); threading vllm/entrypoints/openai/api_server.py:426,441,529,544 at 5559679229src/vllm/entrypoints/openai/server_main.cpp:289 (kAcceptedInertArgs, the enumerated table), :312 (FindAcceptedInertArg — returns nullptr for anything unlisted, so the existing unknown argument abort is untouched), :505 (the parse branch + the per-flag notice), :560 (the mirrored cli_args.py:395 validation); docs/USAGE.md § "Accepted for recipe compatibility"tests/vllm/entrypoints/openai/test_serve_recipe_args.cpp:141 (listed flags reach model load), :165 (an unlisted flag STILL aborts — the load-bearing case), :188 (the mirrored cli_args.py:395 refusal), :212 (the per-flag notice); registered tests/CMakeLists.txt:877. 4 cases / 58 asserts GREEN; RED-first against the pre-change binary (17 failed, Status: FAILURE!). Each case re-execs the binary into the REAL VllmServerMain. MUTATION PROVEN in a scratch copy: widening FindAcceptedInertArg into a catch-all turns exactly :165 RED (8 asserts) and leaves the other three GREENserve-recipe-args.mdACTIVECLAIM-SERVE-RECIPE-ARGS
SERVE-POOLING-ENDPOINTSEmbeddings, pooling, score, rerank, classify HTTP surface (/v1/embeddings, /pooling, /score, /rerank, /classify). SPIKED 2026-07-28 (CLAIM-POOLING): the whole pooling task class is scoped in pooling-task-class.md. /v1/embeddings LIVE 2026-08-08 (ARCH-ONE-SURFACE ROW 6, CLAIM-EMBEDDINGS-ONE-SURFACE): task-conditional registration (embed/api_router.py:22-28 mirror; the route exists ONLY on a pooling-model server, and the generate routes do not — both directions socket-404-pinned), OpenAI request/response shape (string-or-array input; dimensions/base64/token-arrays are named-residual 400s), handler drives the ONE engine path (LoadedEngine -> LLMEngine::embed -> registry forward -> PoolingRunner) — the same path vllm_embed (ABI v15) drives. RESIDUALS: /pooling, /score, /rerank, /classify (need a classify arch)T2vllm/entrypoints/pooling/embed/api_router.py:28; vllm/entrypoints/pooling/embed/protocol.py:34,173-185; vllm/entrypoints/pooling/scoring/api_router.py:37,71; vllm/entrypoints/pooling/classify/api_router.py:26src/vllm/entrypoints/openai/api_server.cpp handle_embeddings + the if (embedder_) route gate; examples/server/main.cpp pooling task dispatchtests/vllm/entrypoints/openai/test_api_server.cpp embeddings section (dispatch shape + socket smoke + BOTH-direction 404 pins)embeddings-one-surface.mdACTIVECLAIM-EMBEDDINGS-ONE-SURFACE
ENG-POOLER-SEQThe non-generative POOLER OP — turn hidden states into a pooled embedding/logit row instead of a sampled token. W1 LANDED + CPU-GATED 2026-07-28 (CLAIM-POOLING, NOT pushed): the sequence pooling methods CLSPool/LastPool/MeanPool (+ GetSeqPoolingMethod factory) over a packed [num_tokens, hidden] CPU buffer keyed by a minimal PoolingCursor (CLS/MEAN reject partial prefill, LAST allows it, MeanPool upcasts to float32) and the activation heads PoolerIdentity/PoolerNormalize (L2 F.normalize)/PoolerMultiLabelClassify (sigmoid)/PoolerClassify (sigmoid if num_labels<2 else softmax). Unit-gated vs DOUBLE-PRECISION references, RED-first. W2 LANDED + CPU-GATED 2026-07-29 (CLAIM-POOLING, NOT pushed): the pooler HEADS composite (EmbeddingPoolerHead = projector→matryoshka→normalize; ClassifierPoolerHead = classifier→(logit-mean)/sigma→activation), the SequencePooler (method∩head task intersection) + PoolerForEmbed/PoolerForClassify factories, the DispatchPooler groupby-task routing (ForEmbedding/ForSeqCls + a mixed embed+classify batch + ctor task-support validation), and the PoolerConfig/PoolingParams/PoolingParamsUpdate structs; test_pooler_heads 27/27 (240 asserts) vs double-precision refs, RED-first (disable matryoshka slice + logit_mean calibration → 8 cases / 50 asserts fail). RESIDUALS (named, spec §Work breakdown): the endpoints (W4), tokwise AllPool/StepPool (W5), a concrete pooling MODEL + real-oracle cosine gate (W3-model — see ENG-POOLING-RUNNER)T2vllm/model_executor/layers/pooler/seqwise/methods.py:35-121; vllm/model_executor/layers/pooler/activations.py:106-158; vllm/model_executor/layers/pooler/seqwise/heads.py:19-196; vllm/model_executor/layers/pooler/seqwise/poolers.py:41-138; vllm/model_executor/layers/pooler/special.py:23-140; vllm/model_executor/layers/pooler/common.py:12-30; vllm/pooling_params.py:35-70; vllm/config/pooler.py:16-90; vllm/v1/pool/metadata.py:13-71; tests/model_executor/layers/test_pooler_methods.py, tests/model_executor/layers/test_pooler_activations.py, tests/model_executor/layers/test_pooler_heads.pyinclude/vllm/model_executor/layers/pooler/{methods,activations,pooling_metadata,common,pooling_params,pooler_config,heads,poolers,dispatch_pooler}.h + src/vllm/model_executor/layers/pooler/{methods,activations,heads,poolers,dispatch_pooler}.cpp — anchor src/vllm/model_executor/layers/pooler/dispatch_pooler.cpp:13tests/vllm/model_executor/layers/pooler/test_pooler.cpp (CLS/LAST/MEAN + factory + activations, 50 asserts) + test_pooler_heads.cpp (Embedding/Classifier heads + SequencePooler + DispatchPooler, 240 asserts) — anchor tests/vllm/model_executor/layers/pooler/test_pooler.cpp:81pooling-task-class.mdACTIVECLAIM-POOLING
ENG-POOLING-RUNNERThe pooling RUNNER path — where the generation runner SAMPLES a token, the pooling runner applies the model's Pooler to the last hidden state and returns the POOLED DATA (embedding vector / classification logit row). W3 LANDED + CPU-GATED 2026-07-29 (CLAIM-POOLING, NOT pushed): PoolingRunner over a packed [num_tokens, hidden] last-hidden-state buffer + a PoolingMetadataPool() delegates to the model pooler (DispatchPooler.ForEmbedding), GetSupportedTasks(), ComputeValid() (seq_lens==prompt_len). GATE: a STRUCTURAL cosine-parity gate — the runner's embedding vs an independent double-precision LAST+normalize reference is cosine≈1 (5 cases / 14 asserts), RED-first (CLS-instead-of-LAST drops cosine <0.5; disable normalize → 2 unit-L2 asserts fail). GENERALIZATION DEVIATION: upstream pooling_runner.py hardcodes LAST+normalize; we route through the model Pooler (the general bert.py path), strictly more capable. HONEST RESIDUAL (named): the REAL-model oracle cosine gate (vllm.LLM(task="embed").encode) needs a registered concrete embedding model's forward — no such model is registered yet (W3-model), so no cosine-vs-oracle number is fabricated. LIVE IN THE ENGINE STEP 2026-08-08 (ARCH-ONE-SURFACE ROW 6, CLAIM-EMBEDDINGS-ONE-SURFACE): GPUModelRunner builds a PoolingRunner iff the loaded model registration declares is_pooling_model (gpu/model_runner.py:368-369 mirror) and sample_tokens routes to pool_tokens() — pooled data instead of sampled tokens (model_runner.py:1586-1607), validity = the discard predicate (seq_len < num_tokens == upstream is_valid, pooling_runner.py:40-41); the scheduler finishes a pooling request on pooled output (scheduler.py:1718-1721) and EngineCoreOutput.pooling_output carries it out; async scheduling resolves OFF for pooling models (config/vllm.py:1068-1073, the landed ResolveAsyncScheduling arm now WIRED at model_loader.cpp). First registered pooling arch: LlamaModel (MODEL-EMBED-llama-llama-for-causal-lm). The fold gate re-anchors the lane's cosine gate THROUGH the registry/runner path: engine path == direct ModelRegistry::Forward+PoolingRunner path, identical vectors + f64 LAST+normalize reference + chunked-prefill arm (test_llama_embedding_fold 4/4-231). REMAINING RESIDUAL: the REAL-model vllm.LLM(task="embed").encode oracle cosine (synthetic fixture only — no number fabricated)T2vllm/v1/worker/gpu/pool/pooling_runner.py:18-46; vllm/v1/worker/gpu/model_runner.py:368-369,1586-1607; vllm/v1/core/sched/scheduler.py:1718-1721,1837; vllm/tasks.py:10; tests/models/language/pooling/test_embedding.py (real-oracle gate, DEFERRED)include/vllm/v1/worker/gpu/pool/pooling_runner.h + src/vllm/v1/worker/gpu/pool/pooling_runner.cpp:11; live invocation src/vllm/v1/worker/gpu/runner.cpp pool_tokens + the pooling_runner_ ctor gate; scheduler stop src/vllm/v1/core/sched/scheduler.cpp pooling eliftests/vllm/v1/worker/gpu/pool/test_pooling_runner.cpp:136 (structural cosine gate) + tests/vllm/models/test_llama_embedding_fold.cpp:206 (registry/engine-path arm, 4/4-231, mutation-killed x9)pooling-task-class.md + embeddings-one-surface.mdACTIVECLAIM-EMBEDDINGS-ONE-SURFACE
SERVE-RESPONSES-MESSAGESResponses, Anthropic messages, audioT2vllm/entrypoints/openai/responses/api_router.py:48; vllm/entrypoints/anthropic/api_router.py:49; vllm/entrypoints/speech_to_text/transcription/api_router.py:1--planned: specs/responses-messages-endpoints.mdINVENTORIED-
SERVE-ADMINAbort-requests, sleep, pause/resume, profiling, RL weight updates. /abort_requests LANDED + CPU-GATED 2026-07-28 (CLAIM-C8-SERVE-ENDPOINTS, NOT pushed): POST /abort_requests (from the dev/rlhf admin router) parses {request_ids:[...]} and aborts exactly those (external) ids via an injected abort callback wired to the engine abort path (AsyncLLM::abort); an empty/missing list means "abort all in-flight" (the callback decides). Response {"status":"aborted","aborted":<count>}; malformed JSON → 400 {"detail":"Invalid JSON format"}; abort failure → 500 {"error":...} — all three shapes mirror the upstream router verbatim. ADDITIVE + opt-in (route registered only when the abort callback is attached → 404 otherwise). PRODUCTION main.cpp WIRING LANDED + CPU-GATED 2026-07-28 (CLAIM-C8-SERVE-PROD-WIRING, NOT pushed): the shipped vllm-server binary now wires /abort_requests to the LIVE AsyncLLM::abort through the shared ConfigureUtilityEndpoints seam, DEV-mode gated behind the new --enable-server-dev-mode flag — mirroring vLLM registering the dev/rlhf router only under if envs.VLLM_SERVER_DEV_MODE (api_server.py:238; envs.py:157 default 0). Explicit-id abort tears the request down and reports the exact drop in unfinished requests (before−after); empty request_ids (abort-ALL) reports 0 — NAMED RESIDUAL (AsyncLLM exposes no active-request-id accessor). RESIDUAL: the abort-ALL enumeration (missing AsyncLLM::active_request_ids()); /sleep//wake_up//is_sleeping, /pause//resume, /start_profile//stop_profile, weight-update/EP endpoints still INVENTORIEDT2/T3vllm/entrypoints/serve/dev/rlhf/api_router.py:94-138 (abort_requests); dev-mode gate vllm/entrypoints/openai/api_server.py:238-240, vllm/entrypoints/serve/__init__.py:35, vllm/envs.py:157; vllm/entrypoints/serve/dev/sleep/api_router.py:21; vllm/entrypoints/serve/dev/rlhf/api_router.py:29,74,136; vllm/entrypoints/serve/profile/api_router.py:21handler src/vllm/entrypoints/openai/api_server.cpp:488 (handle_abort_requests); opt-in setter include/vllm/entrypoints/openai/api_server.h:156 (set_abort_requests); production seam src/vllm/entrypoints/openai/api_server.cpp (ConfigureUtilityEndpoints, before/after delta-count) + examples/server/main.cpp (--enable-server-dev-mode); engine abort path include/vllm/v1/engine/async_llm.h:115 (abort)tests/vllm/entrypoints/openai/test_api_server.cpp:1104 (shape + callback wiring: explicit ids passthrough, empty→abort-all branch, malformed→400),:1143 (aborts an in-flight AsyncLLM request → has_unfinished_requests() false),:1250 (opt-in route gate: 404 no-callback → 200 attached, RED-first),:1319 (production seam: dev-mode gate 404→200, live abort exact delta-count==1, empty→0) — in the 32/32 / 420-assertion suiteadmin-endpoints.mdANCHOR-BACKFILLCLAIM-C8-SERVE-PROD-WIRING
SERVE-VIDEOS-OAI/v1/videos in OpenAI's Sora WIRE SHAPE, over the vLLM-Omni-derived job endpoints. CPU-LANDED + GATED 2026-08-06 (CLAIM-SERVE-VIDEOS-OAI): the OpenAI request spellings (model, size "WxH", seconds as a number OR the string enum OpenAI actually types) parse as ALIASES onto the existing native members, NATIVE-wins precedence applied PER-AXIS, both spellings validated either way so a malformed alias is a 400 even when overridden; an unserved model is a job warning echoed for the job's whole life, never a rejection (a Sora client cannot know the local model's name); and GET /v1/videos/{id}/content serves the finished MP4 (404 unknown / 409 unfinished / 500 failed / 500 vanished), without which a caller could start and poll a job but never fetch the result over HTTP. All four routes still register ONLY with a VideoRunner attached, now gated over a REAL socket. RESIDUALS (named): OpenAI's status vocabulary/id shape is not mirrored; reference conditioning (input_reference, the metadata video/audio references) is a stacked follow-up row; the real-weights leg rides the H3 GB10/disk window.T2OpenAI Sora video API (POST /v1/videos, GET /v1/videos/{video_id}/content); vLLM-Omni vllm/entrypoints/openai/video/api_router.py (the async/sync job pair we already mirror)include/vllm/entrypoints/openai/video_api.h:31; src/vllm/entrypoints/openai/video_api.cpp:98; src/vllm/entrypoints/openai/api_server.cpp:279tests/vllm/entrypoints/openai/test_video_api.cpp:64; tests/vllm/entrypoints/openai/test_api_server.cpp:1751minimax-h3.md §9ACTIVECLAIM-SERVE-VIDEOS-OAI
SERVE-VIDEOS-REFSREFERENCE CONDITIONING over /v1/videos: the image an OpenAI request starts from, plus the two modalities OpenAI's schema has no slot for. CPU-LANDED + GATED 2026-08-06 (CLAIM-SERVE-VIDEOS-REFS, stacked on SERVE-VIDEOS-OAI): OpenAI's input_reference (a filesystem path or an RFC 2397 data: URL, decoded by the SAME DecodeDataUri the chat multimodal parts use) maps to fl2va FIRST-FRAME conditioning via MiniMaxH3EncodeKeyframeCondRows, because OpenAI documents it as the frame the video starts from and ref2va would silently change what the API promises; the silent-video and audio references ride the standard free-form metadata map (input_reference_video, a DIRECTORY of frame_%06d.ppm since no demuxer is vendored; input_reference_audio, a 16-bit PCM WAV) and become ref2va blocks, an audio reference ATTACHING to the video block when both are given. fl2va-vs-ref2va exclusivity is enforced in the PARSER, mirroring minimax_h3_pipeline.cpp:251, so an illegal pair is a 400 naming it rather than a dropped reference. Both VAE ENCODER halves load lazily and once. RESIDUALS (named): reference images are binary PPM at the output resolution (no PNG/JPEG codec, no resampler vendored); a video reference is a frame directory; OpenAI's real upload is multipart, ours is the JSON spelling.T2OpenAI Sora video API (input_reference, metadata); exclusivity rule src/vllm/model_executor/models/minimax_h3_pipeline.cpp:251include/vllm/entrypoints/openai/video_api.h:51; src/vllm/entrypoints/openai/video_api.cpp:66; examples/server/main.cpp:96tests/vllm/entrypoints/openai/test_video_api.cpp:172; tests/vllm/entrypoints/openai/test_api_server.cpp:1827minimax-h3.md §10ACTIVECLAIM-SERVE-VIDEOS-REFS
SERVE-OTLPOpenTelemetry tracesT2vllm/config/observability.py:18,36,128--planned: specs/otlp-tracing.mdINVENTORIED-
SERVE-BATCH-APIOffline OpenAI Batch API runner — read a JSONL of BatchRequestInput (custom_id/method/url/body), dispatch each line to the matching serving handler, collect BatchRequestOutput rows (custom_id echoed, per-line error isolation), write the response JSONL. W0 SPIKE + W1 CPU BRICK LANDED + CPU-GATED 2026-07-29 (CLAIM-BATCH-API, NOT pushed): RunBatch (RunLine/RunLines/Run) + RunBatchFile (local paths) as a pure ORCHESTRATOR over the existing OpenAIServingChat::create_chat_completion (the SAME handler handle_chat_completions drives — NO reimplemented generation), 1:1 with vLLM's endpoint_registry url→handler map. /v1/chat/completions wired; BatchResponseData/BatchRequestOutput schema + vllm-<uuid>/vllm-batch-<uuid> ids; the run_request AllResponse/ErrorResponse/stream branches; the unsupported-endpoint (handler None) + unsupported-url error rows. RECORDED DEVIATION: a malformed input line is ISOLATED into an error row (batch continues) where upstream aborts the job (deviation lives in the library; the abort-on-bad-line CLI exit code is a W2 residual). RESIDUALS (named, spec §Work breakdown): the vllm run-batch CLI + BatchFrontendArgs (W2); embeddings/score/rerank dispatch (W3, rides SERVE-POOLING-ENDPOINTS); audio transcription/translation + media fetch (W4); http(s)/data-URL file I/O, metrics server, overlapped AsyncLLM submission (W5)T2vllm/entrypoints/openai/run_batch.py:148-228 (schema),:508-570 (run_request/make_error),:722-777,815-847 (dispatch/run loop); tests/entrypoints/openai/test_run_batch.py:375,402,432include/vllm/entrypoints/openai/run_batch.h; src/vllm/entrypoints/openai/run_batch.cpp:70,84,87,142tests/vllm/entrypoints/openai/test_run_batch.cpp:434 (7 cases / 80 assertions, CPU, RED-first: dropping the custom_id echo fails 9 assertions)batch-api.mdANCHOR-BACKFILLCLAIM-BATCH-API
SERVE-REQUEST-LENGTH-GUARDA REFUSING byte bound at the request boundary, checked BEFORE any tokenization (#1541). 67823aee2 removed the QUADRATIC term from the BPE merge loop and added no BOUND; the only size limit in the stack was httplib's 100 MB CPPHTTPLIB_PAYLOAD_MAX_LENGTH, and there is no authentication anywhere in src/vllm/entrypoints/, so /tokenize -- which needs neither an engine nor a model -- pays an unbounded encode on an HTTP worker for an anonymous caller. The bound is DERIVED, never configured: max_model_len * Tokenizer::MaxTokenBytes(), the longest stored token text in the loaded vocabulary (measured 256 / 256 / 192 / 48 bytes over the four committed goldens). Token texts concatenate back to the input, so a prompt above it provably exceeds max_model_len tokens and ValidatePromptLen would refuse it after the encode -- the guard refuses nothing the server would have served, it only moves an already-certain refusal ahead of the work that pays for it. It REFUSES with a 400 naming the length received, the limit and the derivation; it never truncates. Covers POST /tokenize, POST /v1/completions and POST /v1/chat/completions; /v1/embeddings, /v1/audio/*, /v1/videos* and the C ABI are NAMED GAPS under ## Owed. vLLM HAS NO EQUIVALENT for a prompt BYTE bound and the paths are named: h11_max_incomplete_event_size bounds the header block only, validate_prompt_list_length bounds a prompt COUNT, read_upload_with_limit bounds an audio upload. The shape is mirrored from the second and third; the number is ours, which is why it is derived.T1vllm/entrypoints/openai/completion/protocol.py:536; vllm/entrypoints/speech_to_text/base/utils.py:38; vllm/entrypoints/serve/utils/constants.py:9; vllm/entrypoints/openai/cli_args.py:292src/vllm/entrypoints/openai/api_server.cpp:190,209,260,341,872; src/vllm/tokenizer/tokenizer.cpp:590; include/vllm/entrypoints/openai/api_server.h:289; include/vllm/tokenizer/tokenizer.h:107tests/vllm/entrypoints/openai/test_api_server.cpp:1680,1828specs/serve-request-length-guard.mdGATING-

LoRA and adapters

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
LORA-RUNTIMEPunica-style batched LoRA apply. W1 CPU BRICK LANDED + CPU-GATED 2026-07-28 (CLAIM-LORA-RUNTIME, NOT pushed): the LoRALayerWeights container (optimize scaling-fold, dummy) + the portable punica shrink/expand ops (BgmvShrink/BgmvExpand/BgmvExpandSlice, -1-slot SKIP semantics mirroring the triton early-exit + the test CPU refs) + AddLoraLinear (buffer=shrink; y+=expand) + a LoRALinear (ReplicatedLinear n_slices=1: create/set/reset/apply, scaling folded into b at SetLora exactly like the manager optimize path). RUNTIME-VERIFIED on CPU: test_punica_cpu 6/6 (101 assertions) vs an independent double-precision per-LoRA matmul reference; RED-first proven (base-only output differs; -1 base token unchanged; ResetLora → identity). W2 PACKED + MERGED/TP LAYERS LANDED + CPU-GATED 2026-08-10 (CLAIM-LORA-RUNTIME-W2, issue #278): PackedLoRALayerWeights (Pack optimize-then-scaling-1, per-slice Optimize, is_packed) + the multi-slice punica AddShrink/AddExpand (output_slices + offset_start window walk) + multi-slice AddLoraLinear + AddLoraEmbedding (expand only — the embedding shrink is a table gather) + AddLoraLogits (sampler-indexed, clamped to the narrower of the adapter's vocab and the logits width, lora_ops.py:42) + the wrapped LAYER FAMILY (BaseLinearLayerWithLoRA create/reset/set/apply over N slices; replicated, column, row, merged-column/gate_up, qkv, merged-qkv, variable-slice) with the TP SliceLoraA/SliceLoraB rules INCLUDING the fully-sharded (S-LoRA) rank-dim overrides, plus VocabParallelEmbeddingWithLoRA (lora_a stored transposed, gather + expand) and LogitsProcessorWithLoRA (vocab<=258048 guard, sharded->full reindex). RUNTIME-VERIFIED on CPU: test_lora_layers 16/16 (4,498 assertions) porting tests/lora/test_layers.py including test_merged_column_parallel_variable_slice (unequal slice widths) and upstream's active_lora_ids=[0] reset arm, so the -1 SKIP path is exercised; RED-first captured as the compile failure against the absent layers.h, and the surviving-mutation set from the fresh review (AddShrink -1 guard, SetLora A/B slicer swap, AddExpand per-slice offset, CopyIntoSlot stride, AddShrink A-stride, embedding base-token clamp) each now turns a ported case red. DEFERRED WITH REASON, and it REFUSES rather than approximating: the fully-sharded APPLY (_mcp_apply) needs the TP all-gather/all-reduce our seam does not expose, so a sharded class at tp_size>1 throws std::logic_error from ApplyLoraToOutput instead of returning a partial delta; only its slicing is ported. pack_moe/pack_moe_stacked belong to the fused-MoE layer (W7). Mapping metadata, adapter load, LRU manager, GPU kernels + model gate are W3-W7 (see spec).T2vllm/lora/lora_model.py:60; vllm/lora/lora_weights.py:13; vllm/lora/ops/torch_ops/lora_ops.py:24; vllm/lora/punica_wrapper/punica_cpu.py:265; vllm/lora/layers/base_linear.py:100; vllm/lora/punica_wrapper/punica_gpu.py:33; vllm/v1/worker/lora_model_runner_mixin.py:30include/vllm/lora/lora_weights.h:27,98; include/vllm/lora/punica.h:42,69,84,95,114,125; include/vllm/lora/layers.h:75,201,273,345,384; src/vllm/lora/punica_cpu.cpp:45,87,104,125,159,168; src/vllm/lora/layers.cpp:50,183,372,508,530; CMakeLists.txt:671,672; tests/CMakeLists.txt:31,32tests/vllm/lora/test_punica_cpu.cpp:76,91,109,138,161,219,285,329 (8/8, 149 assertions, CPU); tests/vllm/lora/test_lora_layers.cpp (16/16, 4,498 assertions, CPU)lora-adapter.mdACTIVECLAIM-LORA-RUNTIME-W2
LORA-ENDPOINTSDynamic adapter load and unload (POST /v1/{load,unload}_lora_adapter); builds on the runtime, scoped as W6 of lora-adapter.mdT2vllm/entrypoints/serve/lora/api_router.py:43,60--planned: specs/lora-adapter.mdINVENTORIED-

Long context and attention breadth

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
ATTN-YARNTyped YaRN RoPE config/factory/cache plus plain and mrope_section supplied-cache apply; CPU/oracle/sanitizer green. GPU-GATED 2026-07-27 (CLAIM-ROADMAP-C5, dgx GB10 sm_121a, clean CUDA build of 489f7771): the shared scaled-RoPE CUDA apply+cache path COMPILES/RUNS on GB10 — test_ops_rope_cache 6/6 (6692 assertions), test_rotary_embedding 14/14, and the same RopeFromCache op is exercised by the Phi-4-mini/Llama-3.2-1B model gates below. Model-level YaRN e2e is REACHABLE-BLOCKED (no cached oracle-runnable YaRN consumer — Nomic-bert/gpt-oss absent, cached Qwen3-4B is default-rope); the YaRN formula itself stays oracle-gated (G3 CPU goldens). SPEED pendingT1vllm/model_executor/layers/rotary_embedding/__init__.py:243-284; vllm/model_executor/layers/rotary_embedding/yarn_scaling_rope.py:10-84; vllm/model_executor/layers/rotary_embedding/mrope.py:201-340; tests/kernels/core/test_mrope.py:47-235; tests/models/language/pooling/test_nomic_max_model_len.py:93-113include/vllm/transformers_utils/hf_config.h:21; src/vllm/transformers_utils/hf_config.cpp:129; src/vllm/model_executor/layers/rotary_embedding/base.cpp:182; src/vllm/model_executor/layers/rotary_embedding/yarn_scaling_rope.cpp:16; src/vllm/model_executor/layers/rotary_embedding/mrope.cpp:29; include/vt/ops.h:723; src/vt/cpu/cpu_ops.cpp:462; src/vt/cuda/cuda_ops.cu:422tests/vllm/test_hf_config.cpp:424; tests/vllm/model_executor/layers/rotary_embedding/test_rotary_embedding.cpp:47; tests/vt/test_ops_rope_cache.cpp:76; tests/parity/test_op_parity.cpp:357,387,1578; tests/parity/goldens/long_rope_yarn_neox_f32_truncate/manifest.json:1sliding-local-yarn-long-context.mdANCHOR-BACKFILLCLAIM-ROADMAP-C5
ATTN-ROPE-FAMILYBlock row (claim the three leaves below, not this row): Llama 3, LongRoPE, and dynamic-NTK scalingT1/T2vllm/model_executor/layers/rotary_embedding/__init__.py:155-171,200-230,315-335; tests/kernels/core/test_pos_encoding.py:66-193--sliding-local-yarn-long-context.mdREADY-
ATTN-ROPE-LLAMA3Llama 3 typed config/factory/cache with exact unchanged, smoothed and scaled frequency bands including equal factors; CPU/oracle/sanitizer green. GPU-GATED 2026-07-27 (CLAIM-ROADMAP-C5, dgx GB10 sm_121a, clean CUDA build of 489f7771, oracle vLLM 0.26.0.dev0+g5559679): feature-positive model SACRED gate test_llama_paged_engine (Llama-3.2-1B, unsloth/Llama-3.2-1B) 16/16 (12 STRICT token-exact + 4 near-tie gap 0.0 nats, 0 forward-divergent) — llama3 band-rescale is applied at ALL positions (not thresholded). 0.26 oracle recapture ALL-DETERMINISTIC over K=5 and BIT-IDENTICAL to the committed golden ⇒ zero drift ⇒ STRICT-valid vs the 0.26 oracle. SPEED pendingT1vllm/model_executor/layers/rotary_embedding/__init__.py:155-171; vllm/model_executor/layers/rotary_embedding/llama3_rope.py:11-54include/vllm/transformers_utils/hf_config.h:21,32; src/vllm/transformers_utils/hf_config.cpp:184,215; include/vllm/model_executor/layers/rotary_embedding/base.h:80; src/vllm/model_executor/layers/rotary_embedding/base.cpp:148,220; include/vllm/model_executor/layers/rotary_embedding/llama3_rope.h:14; src/vllm/model_executor/layers/rotary_embedding/llama3_rope.cpp:11,33tests/vllm/test_hf_config.cpp:467,539; tests/vllm/model_executor/layers/rotary_embedding/test_rotary_embedding.cpp:202,244,294; tests/parity/test_op_parity.cpp:357,395,1586; tests/parity/goldens/long_rope_llama3_neox_f32_bands/manifest.json:1sliding-local-yarn-long-context.mdANCHOR-BACKFILLCLAIM-ROADMAP-C5
ATTN-ROPE-LONGROPEPhi-3 LongRoPE typed factor arrays, optional mscales, concatenated short/long caches and one runtime-length-global selection; CPU/oracle/sanitizer green. GPU-GATED 2026-07-27 (CLAIM-ROADMAP-C5, dgx GB10 sm_121a, clean CUDA build of 489f7771, oracle vLLM 0.26.0.dev0+g5559679): feature-positive model SACRED gate test_phi3_paged_engine (Phi-4-mini-instruct) 16/16 (7 STRICT + 9 near-tie <=0.5 nats, 0 forward-divergent; RED-first proven — disabling the LongRoPE mscale flips 11 roots the gate catches); the LONG cache is selected globally (max_model_len 131072 > original 4096). 0.26 oracle recapture ALL-DETERMINISTIC over K=5 and BIT-IDENTICAL to the committed golden ⇒ zero drift ⇒ STRICT-valid vs the 0.26 oracle. SPEED pendingT2vllm/model_executor/layers/rotary_embedding/__init__.py:315-335; vllm/model_executor/layers/rotary_embedding/phi3_long_rope_scaled_rope.py:16-159include/vllm/transformers_utils/hf_config.h:35; src/vllm/transformers_utils/hf_config.cpp:196,247; include/vllm/model_executor/layers/rotary_embedding/base.h:98; src/vllm/model_executor/layers/rotary_embedding/base.cpp:193,256; include/vllm/model_executor/layers/rotary_embedding/phi3_long_rope_scaled_rope.h:16; src/vllm/model_executor/layers/rotary_embedding/phi3_long_rope_scaled_rope.cpp:13,60,77,88tests/vllm/test_hf_config.cpp:497,599; tests/vllm/model_executor/layers/rotary_embedding/test_rotary_embedding.cpp:281,335,411; tests/parity/test_op_parity.cpp:357,399,1604; tests/parity/goldens/long_rope_phi3_neox_f32_short/manifest.json:1sliding-local-yarn-long-context.mdANCHOR-BACKFILLCLAIM-ROADMAP-C5
ATTN-ROPE-DYNAMIC-NTKDynamic-NTK typed alpha/factor dispatch with alpha precedence, optional trained length, exact base transforms and dimension guard; CPU/oracle/sanitizer green. GPU-GATED 2026-07-27 (CLAIM-ROADMAP-C5, dgx GB10 sm_121a, clean CUDA build of 489f7771, oracle vLLM 0.26.0.dev0): model SACRED gate test_internlm2_paged_engine (internlm2-chat-1_8b, rope_scaling type dynamic factor 2.0) 16/16 (12 STRICT + 4 near-tie, 0 forward-divergent) proves the dynamic config-parse + cache build on GB10. HONEST: dynamic-NTK is IDENTITY at gate-battery lengths (seq < trained length ⇒ unchanged base — exactly mirrors vLLM); the nontrivial NTK base transform needs a >trained-length prompt (unreached at the gate battery) and stays oracle-gated by G3 CPU goldens. SPEED pendingT1/T2vllm/model_executor/layers/rotary_embedding/__init__.py:200-230; vllm/model_executor/layers/rotary_embedding/dynamic_ntk_scaling_rope.py:30-73; vllm/model_executor/layers/rotary_embedding/dynamic_ntk_alpha_rope.py:9-43; tests/test_config.py:543-587include/vllm/transformers_utils/hf_config.h:42; src/vllm/transformers_utils/hf_config.cpp:200,265; src/vllm/model_executor/layers/rotary_embedding/base.cpp:243; include/vllm/model_executor/layers/rotary_embedding/dynamic_ntk_scaling_rope.h:15; src/vllm/model_executor/layers/rotary_embedding/dynamic_ntk_scaling_rope.cpp:12,31; include/vllm/model_executor/layers/rotary_embedding/dynamic_ntk_alpha_rope.h:15; src/vllm/model_executor/layers/rotary_embedding/dynamic_ntk_alpha_rope.cpp:12,26tests/vllm/test_hf_config.cpp:532,650; tests/vllm/model_executor/layers/rotary_embedding/test_rotary_embedding.cpp:389,411,429,500; tests/parity/test_op_parity.cpp:357,399,1611; tests/parity/goldens/long_rope_dynamic_factor1_neox_f32/manifest.json:1sliding-local-yarn-long-context.mdANCHOR-BACKFILLCLAIM-ROADMAP-C5
ATTN-SLIDING-WINDOWSliding-window attention semantics and backend dispatch; generic config/window seam plus CPU, portable-CUDA, and vendored-FA2 local masks are implemented. GPU-GATED 2026-07-27 (CLAIM-ROADMAP-C5, dgx GB10 sm_121a, clean CUDA build of 489f7771, oracle vLLM 0.26.0.dev0): the local-mask CUDA kernel is POSITIVELY gated at operator level — test_ops_paged_attn 25/25 (454474 assertions) incl. WMMA sliding-window max_abs_err 2.10e-6 vs f32 ref + FA-2, and test_attention_window 3/3 (window-straddling (left,right) masks, mask-exact). Model consumers gated on GB10: Gemma-2 (test_gemma2_forward) 48/48 + Gemma-3 (test_gemma3_forward) 48/48 CUDA greedy tokens vs the vLLM oracle. Correctness-complete, SPEED pending; the window is INERT at the short gate battery (ctx < W) so the long-context positive-mask (prompt > W) model e2e + the KV-memory-optimization G8 are the honest tailT1vllm/v1/attention/backends/flash_attn.py:255-300,674-717,840-955; tests/v1/attention/test_attention_backends.py:745-867; tests/v1/e2e/general/test_correctness_sliding_window.py:19-78include/vllm/model_executor/layers/attention/attention.h:24,33; src/vllm/model_executor/layers/attention/attention.cpp:12,33; include/vt/ops.h:239,260; src/vt/cpu/cpu_paged_attn.cpp:86; src/vt/cuda/cuda_paged_attn.cu:85,1892,2051; src/vt/cuda/cuda_flash_attn_fa2.cu:234tests/vllm/model_executor/layers/attention/test_attention.cpp:22,67,81,100; tests/vt/test_ops_paged_attn.cpp:454,500,779,1145; tests/vllm/test_hf_config.cpp:342; tests/vllm/models/test_gemma2_forward.cpp; tests/vllm/models/test_gemma3_forward.cppsliding-local-yarn-long-context.mdANCHOR-BACKFILLCLAIM-ROADMAP-C5
ATTN-CHUNKED-LOCALChunked-local cached wrapper, virtual Q/K batches, reusable block-table gather/update plan, cudagraph rejection, spec emission and ordinary-backend delegation; CPU G1/reference G5 green. On the clean CUDA build of 489f7771 (CLAIM-ROADMAP-C5, dgx GB10 sm_121a) it compiles -Werror-clean and test_chunked_local_attention 5/5 (18849 assertions, all six pinned virtual-batch vectors) passes; delegation runs the ordinary paged backend (already GPU-gated). Model-level feature-positive e2e is REACHABLE-BLOCKED: no Llama4ForCausalLM model row is implemented (the representative chunked-local consumer). Row stays GATING on that vehicleT1vllm/model_executor/layers/attention/chunked_local_attention.py:30-128; vllm/v1/attention/backends/utils.py:225-420; tests/v1/attention/test_chunked_local_attention.py:28-204include/vllm/model_executor/layers/attention/chunked_local_attention.h:37,82,113; src/vllm/model_executor/layers/attention/chunked_local_attention.cpp:82,108,126; include/vllm/v1/attention/backends/utils.h:17; src/vllm/v1/attention/backends/utils.cpp:29,74; include/vllm/v1/attention/backend.h:58,79,94tests/vllm/v1/attention/test_chunked_local_attention.cpp:224,265,343,370,416,436; tests/vllm/v1/attention/test_common_attn_metadata.cpp:42sliding-local-yarn-long-context.mdGATING-
ATTN-MLAMLA prefill/decode backends and latent KVT2vllm/v1/attention/backends/mla/flashinfer_mla.py:1; vllm/v1/attention/backends/mla/triton_mla.py:1--planned: specs/mla-backends.mdINVENTORIED-
ATTN-MAMBAMamba1/Mamba2, short-conv, linear backendsT2vllm/v1/attention/backends/mamba_attn.py:30,79; vllm/model_executor/layers/mamba/short_conv.py:1--planned: specs/mamba-backends.mdINVENTORIED-
ATTN-ENCODER-CROSSEncoder and cross-attentionT2vllm/model_executor/layers/attention/attention.py:1; vllm/v1/attention/backends/utils.py:1--planned: specs/encoder-cross-attention.mdINVENTORIED-

Loading, tokenizer, and config

IDItemTierUpstream code/testsOur codeOur tests/evidenceSpike/specStateOwner
LOAD-SAFETENSORSGeneral safetensors loading, stacked parameters, weights mapping. Binding memory scan finds all source mappings live through load plus a persistent CPU mirror of selected tensors; windowed progressive madvise(DONTNEED) release now drops each copied-then-dead source range during the copy loop so the mirror build no longer double-resides with the full source mmapT0streamed target-device construction vllm/model_executor/model_loader/base_loader.py:43-82; incremental safe_open yield vllm/model_executor/model_loader/weight_utils.py:905-954; immediate parameter copy vllm/model_executor/models/utils.py:170-180,252-279all mappings opened/retained src/vllm/entrypoints/model_loader.cpp:47-63,303-312; MAP_PRIVATE reader src/vllm/model_executor/model_loader/safetensors_reader.cpp:43-70; windowed release primitive/gate src/vllm/model_executor/model_loader/safetensors_reader.cpp:285-340; copy-helper instrumentation src/vllm/model_executor/models/qwen3_5_weights.cpp:88,104,119,171,190,226,231 + qwen3_5_dense_weights.cpp:64,80,109,159,164,263,323reader contracts + windowed-release cases green (smaps-Rss drop, byte-identity, gate semantics, neighbor safety); exact 27B accounting finds 1,155 tensors / 24,610,136,064 B (22.920 GiB) persistent host bytes. VmHWM A/B MEASURED at cb2d310 (root ~/work/vllm.cpp-windowed-load/cb2d310c…518/evidence, one flock, single 27B load per arm): OFF 48,285,916 kB vs ON 24,750,704 kB = VmRSS (−23.54 GB, load transient eliminated), ON-arm smoke 6/6; ledger row 2026-07-15. Exact-grid memory axes remain FAILED (projected PASS); direct-device streaming gate still openspecs/safetensors-windowed-load.mdPARTIAL-
ENG-LOAD-DIRECT-UPLOADCut the SECOND copy out of a safetensors load: a weight the device consumes VERBATIM VIEWS the read-only shard mmap (OwnedBytes::Borrow, keep-alive carried on StTensor::mapping) instead of being copied into an owned host buffer, so ResidentWeight uploads straight from the file mapping and the load moves those bytes ONCE. Backend- and arch-agnostic: it lives in the shared dense loader helpers, so every arch that routes through them inherits it. Additive leaf below LOAD-SAFETENSORS; the windowed source-page release is preserved and now also runs after the device upload. Non-verbatim paths (transpose, dtype conversion, dequant, concatenation, GGUF load-time repack) are unchanged and keep their copy. Also lands the measurement half of issue #150: per-phase load timing plus host-copy / borrowed / device-upload byte counters (VT_LOAD_STATS)T1one move per byte: streamed shard iterator vllm/model_executor/model_loader/weight_utils.py:905-954; immediate copy into the destination parameter vllm/model_executor/models/utils.py:252-279; driver vllm/model_executor/model_loader/base_loader.py:43-82 @ 555967922refcounted mapping src/vllm/model_executor/model_loader/safetensors_reader.cpp:46-80,231-262; byte counters :337-400; BorrowStTensorBytes + post-upload adoption/release src/vllm/model_executor/models/qwen3_5_weights.cpp; qualifying call sites include/vllm/model_executor/models/dense_weight_loaders.h (LoadBf16Direct, LoadCtNvfp4W4A16, LoadCtMxfp4W4A16), src/vllm/model_executor/models/qwen3_5_dense_weights.cpp (LoadModelBf16Direct, LoadCtNvfp4Raw), src/vllm/model_executor/models/qwen3_5_weights.cpp (35B LoadBf16Direct); upload counter include/vllm/model_executor/models/dense_attn_block.h; fp4 resident upload counter + post-upload residency include/vllm/model_executor/models/dense_nvfp4_gemm.h (ResidentNvfp4) and src/vllm/model_executor/models/qwen3_5.cpp (private ResidentNvfp4); shared checker text normalization scripts/checker_text.pymechanism gate 14/14, 183 assertions (178 through round 4) — the 6 borrow-mechanism cases, 4 post-upload residency cases that pin the adopt branch, its RELEASE-BEFORE-REASSIGN ordering and the VT_ADOPT_DEVICE_BYTES decoupling, 3 fp4-resident cases that pin ResidentNvfp4's upload accounting, its d_dev publication, its adoption and the previously unexercised NON-borrowed/host-addressable regime, and 1 case that pins the GENERAL adopt branch's MADV_DONTNEED by OBSERVING RESIDENCY (mincore() over the host mirror's interior pages, glibc pinned to the sbrk arena so free() cannot return them by itself) — the RSS half of this row, which every value assertion was blind to. RED under eleven mutations, each applied alone with the binary rebuilt (a failed build aborts rather than re-running a stale one), tree md5-verified restored and re-GREEN after each. Mutations are named by the TEST CASE they land on, never by a line ref, because carried-forward line refs are how the counts below were twice recorded wrong: drop the size-identity check 1 case / 5 assertions; skip the borrow in LoadBf16Direct 2 / 7; delete the adopt branch 5 / 19; move the release after the bytes reassignment 5 / 7 (incl. the ordering assertions read from inside the munmap); move the release after the host-addressable early return but BEFORE the env one 2 / 3; move it after the VT_ADOPT_DEVICE_BYTES early return, i.e. after BOTH, 3 / 4; delete the general branch's MADV_DONTNEED 1 / 1; ResidentNvfp4 drop both AddDeviceUpload 3 / 3; drop both d_dev publications 3 / 20; drop both AdoptDeviceBytesAsHost 3 / 16; all six at once 3 / 23. FOUR of those rows had been recorded wrong (1/1, 2/2, 3/7 and 3/3) — every one a count measured against an older suite and copied forward rather than re-measured; all eleven are measured on this tree. The qwen3_5.cpp duplicate of ResidentNvfp4 is in an anonymous namespace no test can call, so it is held to the same invariant by scripts/check-fp4-resident-consistency.py (42-case mutation suite), which checks PER BUFFER inside each buffer's own if (!w.d_<buf>) upload block — body-wide matching let one surviving AddDeviceUpload satisfy both buffers, so dropping exactly one counter passed (reproduced against the real qwen3_5.cpp text: old checker exit 0, new exit 1). Nine drop-one/substitute-one mutations of the LIVE duplicate now go RED. Round 5 closed two holes in it. It matched RAW source, so a statement left behind as a COMMENT, inside #if 0, or inside if (false) read as present while the compiler saw a deletion; the clause matchers now run on scripts/checker_text.py's normalize_source, which blanks all three IN PLACE so byte offsets and line numbers survive — strip_comments had existed as two byte-identical private copies (check-runner-routing-consistency.py, check-surface-coverage.py) and both now import the shared helper instead of a third copy being written. And the ordering clause required PUBLISH-before-ADOPT but not COPY-before-ADOPT, so a body whose adoption runs BEFORE its copy passed although the upload then reads pages the adoption already released; new clause (f) READ-FIRST covers it. WHICH MOTION produces that order is part of the claim, because the two are different mutations: SINKING d.b.Copy(...) to below AdoptDeviceBytesAsHost leaves the d_dev publication in place so ONLY clause (f) bites (MEASURED on the live duplicate, old exit 0 / new exit 1 — the 0/1 row below), whereas HOISTING the adoption above the copy also lifts it above the publication and trips the PRE-EXISTING clause (e), which the old checker already caught (MEASURED 1/1) and which is therefore no evidence for (f). The equivalent mutations of the SHARED dense_nvfp4_gemm.h copy are red at run time, MEASURED one at a time with the binary DELETED before each rebuild and the header md5-verified (4665255f7af6f52254367f9118ad92ee) before and after each: sink packed's Copy 2 cases / 2 assertions, sink scale's 2 / 2, sink BOTH 2 / 4 — the failures are w.<buf>.bytes.data()[0] == kSrcPattern and AllBytesMatchPattern(...) in fp4 resident: ResidentNvfp4 COUNTS its upload… and fp4 resident: a host-addressable device adopts an OWNED fp4 mirror too, TWO per mutated buffer, so an ODD count is not obtainable; hoist packed's adoption 3 / 8 and hoist both 3 / 16, wider because a null d_dev makes the adoption return immediately and also takes the NON-host-addressable case. This clause had been recorded as 2 cases / 3 assertions, which is the count of the release after the host-addressable early return, BEFORE the env one row carried onto a different mutation — the same failure mode as the four rows above, found by a fifth reviewer and re-measured here rather than copied. MEASURED on the LIVE qwen3_5.cpp on disk, one mutation at a time, md5-verified restored after each (35b5ea250f490105d579f4ffb573aa36 before and after all eleven) — old checker exit / new checker exit: delete the packed adoption 1/1, // it out 0/1, /* */ it out 0/1, #if 0 around it 0/1, if (false) around it 0/1, // the packed upload counter 0/1, // the packed d_dev publication 0/1, #if 0 around that publication 0/1, if (false) around it 0/1, SINK the packed Copy to below its adoption 0/1. That gate is STRUCTURAL: it guards the duplicate against DELETION — including deletion disguised as a comment, an #if 0 or a never-taken branch — against gross substitution and against mis-ordering, NOT against corruption, and it does not model the preprocessor (extending it to arbitrary #ifdef conditions is DECLINED: #ifdef VT_CUTLASS_NVFP4 around the live adoption stays exit 0 in both checkers, because a build configuration is not a disguised deletion). Run-time proof exists only for the shared copy. The mincore() residency case now also carries a RUNTIME allocator guard — #if __GLIBC__ proves the headers, not that glibc's allocator is running — which goes red (1 case / 1 assertion) when a purging allocator is simulated; the mallopt calls leave glibc's no_dyn_threshold set for the process either way, MEASURED as not specific to M_TRIM_THRESHOLD (glibc 2.39, mallinfo2().hblks probe: no mallopt LIVE, M_TRIM_THRESHOLD DISABLED, M_MMAP_MAX DISABLED), so it is recorded rather than removed. Round-4 re-run on the dev box, CLEAN Vulkan/llvmpipe Release build: test_load_direct_upload 14/14 (178), test_safetensors 34/34 (79), test_qwen36_weights 7/7 (45), test_vulkan_backend 35/35 (2107), test_backend_cross_device 11/11 (132), test_opt_paged_engine 6/6 token-exact (96/96), 0 declines, device type 3. Round-5 re-run on the same box, branch rebased onto a0fa12c7, all identical except test_load_direct_upload 14/14 (183) — the five added assertions are the RSS-reclaim case's runtime allocator guard, no case-count change — plus test_checker_text 33/33 and scripts/gen-vulkan-spirv.py --check committed SPIR-V is up to date run with the pinned ~/tools/glslang-16.5.0/bin/glslang (without it the script exits 1 on this tree, so the green is a real compile-and-compare and not a skip). Round 6 changed NO compiled file — this row, the spec, the (f) clause docstring and one checker-test name — and re-ran the whole battery on the branch rebased onto e3cc4f64, CLEAN Release Vulkan build, 0 warnings: every count above reproduces byte-for-byte, check-fp4-resident-consistency rc 0, its suite 42, test_checker_text 33, test_check_surface_coverage 46, test_check_runner_routing_consistency 31, SPIR-V check up to date, preflight all green. GB10 Vulkan gates on the changed tree: test_vulkan_backend 35/35 (2650), test_backend_cross_device 11/11 (132), test_opt_paged_engine 6/6 prompts token-exact (96/96), 0 declines, device type 3. GB10 CUDA (cutlass+triton) full ctest 383/393, BOTH SACRED gates PASS (test_qwen36_paged_engine, test_qwen27_paged_engine); all 10 failures reproduce with the same signature on a clean origin/main CUDA build. MEASURED 27B bf16 load 1.54x warm / 1.61x cold, bytes moved 100.196 -> 81.260 GiBspecs/load-direct-upload.mdACTIVECLAIM-ENG-LOAD-DIRECT-UPLOAD
LOAD-SAFETENSORS-DIRECT-DENSELayer-bounded target-device loading for ordinary plain-BF16 Qwen3.5 dense safetensors on discrete CUDA; additive leaf below LOAD-SAFETENSORS, preserving windowed source release and owned-shard lifetime. Plain weights, stacked raw-NK owners, tied logits, logical resident state and same-queue layer staging are implemented and locally CUDA-gated. H32 Triton AOT, plain-BF16 decode graphs and ratio-4 FA2 repair the transplanted hot path; the broader row remains speed-gatingT1target-device model construction vllm/model_executor/model_loader/base_loader.py:43-82; incremental safetensors yield vllm/model_executor/model_loader/weight_utils.py:820-954; stacked/tied parameters vllm/model_executor/models/qwen3_5.py:276-303,483-492load/dispatch src/vllm/model_executor/models/qwen3_5_dense_weights.cpp:52-133,187-246,334-472; discrete/unified classifier src/vt/cuda/cuda_backend.cu:251-265; plain execution/residency and graph selection src/vllm/model_executor/models/qwen3_5.cpp, src/vllm/model_executor/models/qwen3_5_dense.cpp; H32 recurrence src/vt/cuda/cuda_gdn.cu; ratio-4 FA2 src/vt/cuda/cuda_flash_attn_fa2.cu, src/vt/cuda/cuda_paged_attn.cu; exact benchmark corpus/output capture examples/bench/bench_core.h:61-68,357-386,409-589; reference metrics/token collector tools/bench/vllm_closed_loop_metrics.py; guarded driver and summarizer tools/bench/run_qwen35_4b_compare.sh, tools/bench/summarize_qwen35_4b_compare.pyReal 4B graph/direct ON/OFF/eager gate passes 3/3, 1672/1672; H32/GDN tests 10/10 flag and 66/66, 4242/4242 full; paged-attention tests 25/25, 454474/454474. Final 18-leg root /tmp/qwen35-main-final-fa2-20260725 plus stable vLLM confirmation: direct ON/OFF/vLLM-0.25 total 5769.99/5660.70/5849.80 tok/s, output 638.03/625.94/646.85, TPOT/ITL 43.72/43.84/38.55 ms, peak PSS 2.406/8.592/7.662 GiB, stable PSS 0.759/8.589/4.029 GiB, VRAM 12850.7/12843.3/12942.7 MiB. ON=OFF output IDs 128/128 every pair; ON is +1.93% total and cuts peak/stable PSS 72.0%/91.2%. H32 AOT/graph/FA2 A/B gains are +4.59%/+0.39%/+1.60%. Graph-node trace has 453 launches and 200972 child kernels; local FA2 is 180.28 us/call vs vLLM 178.40, so the remaining 0.9864x throughput and TPOT gap is host/engine-side. Sanitizer availability and external 27B/35B remain openplain-BF16 direct-load spike; 2026-07-25 evidenceGATING-
ENG-MOE-HOSTFREEMoE Marlin resident host-weight release: after BuildMoeMarlinResident uploads+repacks the routed experts to the device Marlin resident, free the per-expert fp4 HOST mirror (OwnedTensor packed+scale bytes) and madvise(MADV_DONTNEED) the pages back to the OS — returns the ~16.9 GiB steady 35B host double-store (LoadNvfp4Raw MakeOwned copies kept resident forever). Guarded to the committed Marlin path (MarlinMoeEnabled(); retained for the VT_NVFP4_MARLIN=0 wmma fallback that re-reads them); VT_MOE_HOST_FREE=0 A/B rollback. Realizes release_host_weights_after_upload for the dominant host consumer. Item-2 (2026-07-19, CLAIM-BACKEND-PLATFORM-2): the host-free decision is now CONSUMED from GetPlatform(d.q.device.type).residency_policy() via vllm::platforms::ShouldReleaseHostWeights(policy, MarlinMoeEnabled()/*kernel-path*/, VT_MOE_HOST_FREE/*env*/)CudaPlatform flag flipped false→true (reproduces today EXACTLY); MarlinMoeEnabled() stays the orthogonal KERNEL-PATH safety gate.T0streamed target-device weight construction vllm/model_executor/model_loader/base_loader.py:43-82; residency capability vllm/platforms/interface.py:134-229; Marlin MoE in-place repack (no host mirror) vllm/model_executor/layers/quantization/utils/marlin_utils_fp4.py:375-434free region src/vllm/model_executor/models/qwen3_5.cpp:3743-3781; OwnedTensor::ReleaseHost decl include/vllm/model_executor/models/qwen3_5_weights.h:65 + impl (madvise+swap) src/vllm/model_executor/models/qwen3_5_weights.cpp:24; public hook Qwen3_5Model::PrepareMarlinResident src/vllm/model_executor/models/qwen3_5.cpp:4472tests/vllm/test_qwen36_weights.cpp:273 (ReleaseHost frees buffer+capacity) + :314 (PrepareMarlinResident release under Marlin / retention under VT_NVFP4_MARLIN=0, DGX release 27/27 + retention 15/15); DGX A/B (VT_MOE_HOST_FREE) 35B STEADY serving PSS 20.17→3.53 GiB (root dgx:~/work/mem35-hostfree); token-neutral 315/315 + 235/235; c2 smoke clean; memcheck clean. Whole-window load-phase PEAK bounded by the ENG-MOE-LOADSTREAM follow-up. Ledger parity-ledger.md#L521moe-marlin-host-free.mdDONEac77bec
ENG-MOE-LOADSTREAM35B load-phase PEAK-PSS interleave (follow-up to ENG-MOE-HOSTFREE): the steady free returns the routed-expert host mirror only AFTER the whole model loads, so whole-window peak_pss/peak_rss (~19.8 GiB) is still set by all N layers' ~256 experts host-coexisting at load. DEFER the routed-expert host copies (LoadQwen3_5Moe loads each layer WITHOUT experts + installs a per-layer load_layer_experts streaming closure that owns the mmap'd shards) and materialize ONE layer's experts inside PrepareMarlinResident immediately before that layer's device Marlin build + host free — so at most one layer's experts coexist on the host (peak ~ one layer, not all N). Device residents byte-identical (same source bytes, same per-layer build order). Non-CUDA/VT_NVFP4_MARLIN=0/no-Marlin build falls back to bulk host materialization (their forward reads the host bytes). 27B is a different loader (LoadQwen3_5Dense, true-W4A4) → unaffected; GGUF/synthetic/borrowed pass no shards owner → eager. Item-2 (2026-07-19, CLAIM-BACKEND-PLATFORM-2): the per-layer interleave gate is now CONSUMED from GetPlatform(queue.device.type).residency_policy() via vllm::platforms::ShouldInterleaveLoadStream(policy, MarlinMoeEnabled()) — reproduces the old queue.device.type != kCUDA OR !MarlinMoeEnabled() gate EXACTLY (unified/CPU retain-host ⇒ policy false ⇒ materialize-all fallback); the ~4 GiB load-peak win is preserved.T0streamed target-device construction vllm/model_executor/model_loader/base_loader.py:43-82; in-place Marlin repack, no host mirror vllm/model_executor/layers/quantization/utils/marlin_utils_fp4.py:375-434; residency capability vllm/platforms/interface.py:134-229deferred field include/vllm/model_executor/models/qwen3_5_weights.h:307 (Qwen3_5MoeWeights::load_layer_experts); loader defer + closure src/vllm/model_executor/models/qwen3_5_weights.cpp:331,399 (LoadMoeExpertsInto/LoadQwen3_5Moe); shared shards owner include/vllm/model_executor/models/model_registry.h:60 + src/vllm/model_executor/models/model_registry.cpp:411 (ModelSource::FromSafetensorsOwned) + src/vllm/entrypoints/model_loader.cpp:365 (LoadFromDir); per-layer interleave + MaterializeAllDeferredExperts src/vllm/model_executor/models/qwen3_5.cpp:4498,4508 (PrepareMarlinResident)CPU coexistence-bound contract tests/vllm/test_qwen36_weights.cpp:324 ("deferred routed-expert load: move-safe closure + bounded coexistence", peak==1 across the per-layer materialize→free loop, move-safe closure); clean -Werror CPU build 0 warn, full ctest (3 HTTP/engine-proc parallel-port flakes pass isolated), tools 164/164. DGX PROVEN (~/work/vllm.cpp-mem35-loadstream new vs -parent 7a1a6d6 eager, production flags CUTLASS sm120a+Marlin+FA2 sm_121a, one flock): 35B load-to-ready peak RSS (VmHWM) 21.43 GiB → 4.19 GiB (−17.24 GiB / −80%, below vLLM 13.3 GiB); token BYTE-IDENTICAL both binaries — 35B test_qwen36_paged_engine 315/315 + 27B test_qwen27_paged_engine 235/235; 27B UNAFFECTED (peak RSS 24.8 GiB, matches its baseline — dense loader, no deferral); compute-sanitizer memcheck on the deferred load path 0 errors / 315 assertions (no use-after-free of the freed host bytes); weights unit 127 assertions (CPU coexistence peak==1 + DGX residency). benchmark_binding=false — the orchestrator re-grids the binding peak_pss/peak_rss axes to confirm the FAIL→PASS flipmoe-expert-load-stream.mdANCHOR-BACKFILLCLAIM-MEM35-LOADSTREAM
LOAD-GGUFGGUF reader, dequantization, Qwen name transforms, embedded vocabularyT0Pinned vLLM has no GGUF loader: vllm/model_executor/model_loader/__init__.py:31-65; compatibility reference is llama.cppsrc/vllm/model_executor/model_loader/gguf_reader.cpp:302; src/vllm/model_executor/model_loader/gguf_dequant.cpp:223; src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:432; src/vllm/entrypoints/model_loader.cpp:240tests/vllm/test_gguf.cpp:53; tests/vllm/test_gguf_dequant.cpp:25; tests/vllm/test_gguf_qwen36_loader.cpp:153; real 35B tests/parity/test_qwen36_gguf_engine.cpp:145planned: specs/gguf-loader.mdPARTIAL-
LOAD-GGUF-MMPROJA SECOND, clip-architecture GGUF projector file beside the language file, and the Qwen3-VL vision tower loaded out of it. W1 LANDED (#821): EngineParams::mmproj_path / vllm_model_params.mmproj_path (C ABI v22) / the server --mmproj flag name the file, clip_mmproj_gguf.h reads its clip.* metadata and v.* / mm.* tensors into the SHARED multimodal::Qwen3VLVisionWeights, and LoadedEngine::vision_tower() holds the result. The two-tensor temporal patch embedding (v.patch_embd.weight + v.patch_embd.weight.1) is INTERLEAVED per channel into the [out, C*T*p*p] conv3d operand the tower reads, and a file carrying only the first half is refused by name — the MuseGlimmer condition enforced rather than assumed. MuseGlimmer's own MuseGlimmerRefuseMmproj now has a PRODUCTION caller (routed on clip.projector_type == "muse-glimmer"), which is a change to MuseGlimmer's behaviour and is stated as one. NOT supported: no forward consumes the loaded tower yet — there is no multimodal request path on the C ABI and no GGUF image/video driver — and the COMMITTED 334-name manifest with its CI accounting is owed by QUANT-QWEN38-27B-GGUF-ARM, because the live confirmation below is env-gated on a NAS file and CI reads only the synthetic fixture. Auto-discovery of a sibling mmproj*.gguf is deliberately out of scope: a directory holding two unrelated models must not silently fuse them. First consumer is Qwen3.8-27B (#821), whose mmproj-BF16.gguf (334 tensors, clip.projector_type = qwen3vl_merger, header-verified 2026-08-18: data end == file size 931,146,432) ships BOTH halves; MuseGlimmer's lacks the secondT0Pinned vLLM has no GGUF loader at all (555967922, model_loader/__init__.py:33-49), so the compatibility reference is llama.cpp b10451 = 10bf611e5 (PROJECTOR_TYPE_QWEN3VL; the previously recorded tools/mtmd/clip-impl.h:330 was read at the SUPERSEDED local fork 237ad9b96 and is owed re-anchoring, #1003)the flag EngineParams::mmproj_path (model_loader.h:1), the reader clip_mmproj_gguf.cpp:1, the open + refuse + read site src/vllm/entrypoints/model_loader.cpp::LoadedEngine::FromModelDir (the .gguf branch, after the device-fit refusal and BEFORE the tokenizer), the reader src/vllm/model_executor/models/clip_mmproj_gguf.cpp::LoadQwen3VLVisionFromClipMmproj + ::ClipMmprojVisionConfig + ::RefuseUnsupportedClipMmproj, the holder include/vllm/entrypoints/model_loader.h::vision_tower on LoadedEngine, the C face include/vllm.h vllm_model_params.mmproj_path (ABI v22) wired in src/capi/vllm_c.cpp, the server flag src/vllm/entrypoints/openai/server_main.cpp --mmproj, and the now-reached refusal src/vllm/model_executor/models/muse_glimmer_gguf_weights.cpp::MuseGlimmerRefuseMmprojtest_clip_mmproj_gguf.cpp:1 (9 cases / 272 assertions hermetic: the clip.* config mapping, the DeepStack discovery, the per-position patch-embedding interleave, every block/merger slot, and four refusals; the ninth is the LIVE confirmation, which skips loudly unless VLLM_CPP_QWEN38_27B_MMPROJ names the real mmproj-BF16.gguf and adds 43 assertions when it does — 334 consumed names == 334 shipped with nothing unread, the clip.* geometry, and the join checked at all 1,769,472 positions against F32 bytes read straight from the mmap. Renaming a tensor in the reader AND the fixture together leaves the hermetic gate green at 9/9 and reds only the live case, which is what the live case buys) and test_gguf_mmproj_reach.cpp:1 (6 cases / 19 assertions hermetic, all through LoadedEngine::FromModelDir; the sixth is the LIVE confirmation that the ENGINE holds the tower, and it skips loudly unless BOTH VLLM_CPP_QWEN38_27B_GGUF and VLLM_CPP_QWEN38_27B_MMPROJ name the real files, so the 19 assertions belong to the five hermetic cases). The two are separate targets on purpose: deleting the LoadQwen3VLVisionFromClipMmproj call site in model_loader.cpp reds the SECOND and leaves the FIRST fully green, which is the measured difference between gating a class and gating a capability. The port target for the vision config mapping is src/vllm/model_executor/models/minimax_h3_vision_gguf.cpp::MiniMaxH3EncoderVisionConfig, which builds the same Qwen3VLVisionConfig from visual.*quantized arms of Qwen3.8-27BPARTIAL-
LOAD-HF-BPEHF tokenizer.json byte-level BPE and incremental detokenizationT0vllm/tokenizers/registry.py:176; vllm/tokenizers/hf.py:163; tests/tokenizers_/test_hf.py:18; tests/tokenizers_/test_detokenize.py:148src/vllm/tokenizer/tokenizer.cpp:240,484,512; src/vllm/v1/engine/detokenizer.cpp:409tests/vllm/test_bpe.cpp:226; tests/vllm/test_tokenizer_parity.cpp:66,74,82,90; tests/vllm/test_pretokenizer.cpp:130planned: specs/hf-tokenizer.mdANCHOR-BACKFILL-
LOAD-SENTENCEPIECESentencePiece (Metaspace + byte-fallback) BPE tokenizer family — the gate to Mistral/Gemma/SentencePiece tokenizer.json. Tokenizer::FromHfJson now dispatches on the pre_tokenizer FAMILY: a bare Metaspace node selects the SP path (space→▁ U+2581; prepend_scheme first/always/never with the starts-with-▁ guard; split=false; out-of-vocab char → <0xNN> byte-fallback tokens; merge-ranked BPE over the raw-UTF-8 string), else the BYTE-IDENTICAL byte-level path (DetectPattern still fails loudly on Metaspace, so families never overlap). Decode + the incremental detokenizer mirror HF's Sequence decoder (Replace ▁→space, ByteFallback, Fuse, Strip 1 leading space). UNBLOCKS the Mistral (MODEL-TEXT-mistral-mistral-for-causal-lm) paged-engine SACRED gate. split=true fails loudly (no golden in scope). Mirrors HF tokenizers 0.22T1vllm/tokenizers/hf.py:163; vllm/tokenizers/mistral.py:235,467; HF tokenizers 0.22 pre_tokenizers/metaspace.rs, models/bpe/model.rs::merge_word, decoders/{replace,byte_fallback,fuse,strip}.rsdispatch src/vllm/tokenizer/tokenizer.cpp:258 (DetectMetaspace), src/vllm/tokenizer/tokenizer.cpp:983 (EncodePlainSp), src/vllm/tokenizer/tokenizer.cpp:1200 (SpDecodeTokens), src/vllm/tokenizer/tokenizer.cpp:1275 (Decode SP branch); merge-loop factor src/vllm/tokenizer/bpe.cpp:235 (BpeMerge); family/params/accessors include/vllm/tokenizer/tokenizer.h:124 (GetFamily); incremental dispatch src/vllm/v1/engine/detokenizer.cpp:359; generator tools/parity/dump_tokenizer_mistral.pytests/vllm/test_tokenizer_parity_mistral.cpp:78 6/6, 421 assertions byte-exact vs HF tokenizers 0.22.2 (= vLLM 0.25.0 backend) over a 45-entry Metaspace/byte-fallback/special-token corpus (goldens tests/parity/goldens/tokenizer_mistral/{tokenizer.json,encodings.json}); SACRED cross-check vLLM AutoTokenizer (transformers 5.13.1) 0/45 mismatch (±BOS); byte-level suites byte-identical tests/vllm/test_bpe.cpp 852, tests/vllm/test_detokenizer.cpp 221, tests/vllm/test_tokenizer_parity.cpp 1175, tests/vllm/test_tokenizer_parity_deepseek.cpp 2461specs/sentencepiece.mdANCHOR-BACKFILLCLAIM-LOAD-SENTENCEPIECE
SPEC-BPE-QUADRATIC-MERGEThe BPE merge loop is O(n^2) in pretoken length, on the request path, before the length check. src/vllm/tokenizer/bpe.cpp::BpeMerge rescans every adjacent pair per merge and built one std::string key per probe through a MergeKey helper that this row deletes, on the premise its own comment states: "pretokens are tiny". FIVE of the seven pretokenizer rules return an unbounded run (src/vllm/tokenizer/pretokenizer.cpp::MatchLetterRun rule 2, src/vllm/tokenizer/pretokenizer.cpp::MatchPunctRun rule 4, src/vllm/tokenizer/pretokenizer.cpp::MatchWsNewlines rule 5, src/vllm/tokenizer/pretokenizer.cpp::MatchWsNotBeforeNonSpace rule 6, src/vllm/tokenizer/pretokenizer.cpp::MatchWs rule 7); only rule 3 MatchNumbers is capped and only rule 1 MatchContraction is bounded by its own alternation, and on the SentencePiece family src/vllm/tokenizer/tokenizer.cpp::EncodePlainSp merges the WHOLE prompt as one word because Mistral and Gemma declare split: false. MEASURED at 31f93787c, min-of-k on a CONTENDED 20-core box, so these are contended minima and not idle-host constants, and EACH figure carries its own load: 65,535 bytes of one repeated character costs 24.4-45.8 s of one core at load average 25-90; 64 KB of ordinary English prose through the committed Mistral golden costs 25.3 s AT LOAD AVERAGE 4-12 against HF tokenizers 0.22.2's 10.1 ms on the same file for byte-identical identifiers, growing n^2.0. A confirmation run at load 23-57 read 37.6 s where the 65,535-byte figure reads 24.4 s, and a fourth reading through the committed harness tools/bench/bpe_encode_cost.cpp moved the 8 KB English figure about 1.7x at load 194, so the SHAPE is the result and the constants move with the box. src/vllm/v1/engine/input_processor.cpp::ValidatePromptLen runs FIVE LINES AFTER the encode, so max_model_len bounds none of it, and /tokenize reaches the same path with no engine. This is a remote denial of service, not a latency curiosity. Fix mirrors HF tokenizers 0.22.2 Word::merge_all (heap over candidate merges, identifier-keyed merge table); a prototype is bit-identical to today's identifiers on 20 comparisons across BOTH committed goldens, all 20 of which also match HF tokenizers 0.22.2 reading the same files, and 8,192 newlines fall from 580.44 ms to 2.60 ms. A pretoken cap is REFUSED: it changes the token identifiers. A GROWTH-RATIO gate is refused too, by operator ruling recorded in the spec's ## Tests to port item 3: at load 176-268 the defective code's own 4x ratios spread 4.654 to 17.896 and OVERLAP the correct algorithm's, because the two halves of a ratio are independently preemptible. The absolute cost bound of item 2 carries the timing gate alone, on about three orders of magnitude of headroom. The string key is not a separable win either, on the DESIGN: upstream's staleness test compares new_id (word.rs:197-205) and its table is keyed on an identifier pair, so a step that rebuilds a std::string to name a pair cannot express the test; and removing a constant from a quadratic leaves a quadratic. How much the key alone is worth is NOT measured on an idle host and this row claims nothing about itT0HF tokenizers 0.22.2 tokenizers/src/models/bpe/word.rs:162-250 (Word::merge_all), :28-35 (Ord for Merge), tokenizers/src/models/bpe/mod.rs:9 + model.rs:19,174-192 (identifier-keyed merge table and its load-time refusal)src/vllm/tokenizer/bpe.cpp:235 (BpeMerge, the heap mirroring Word::merge_all), src/vllm/tokenizer/bpe.cpp:113 (MergeRanks::Insert) and include/vllm/tokenizer/bpe.h:66 (the identifier-keyed table mirroring MergeMap), src/vllm/tokenizer/tokenizer.cpp:98 (InsertMerge, the load-time vocabulary refusal, reached from src/vllm/tokenizer/tokenizer.cpp::FromHfJson AND src/vllm/tokenizer/tokenizer.cpp::FromGguf), src/vllm/tokenizer/tokenizer.cpp:535 (FinalizeTables, the reserved unk-sentinel identifier); callers unchanged, src/vllm/tokenizer/tokenizer.cpp:959 (EncodePlain) and src/vllm/tokenizer/tokenizer.cpp::EncodePlainSp; request path src/vllm/v1/engine/input_processor.cpp:245 (process_inputs), whose encode at line 260 runs five lines before its own length check at line 265tests/vllm/test_bpe_equivalence.cpp:129 (80 entries x 2 goldens x 2 special-token modes = 320 id vectors, all matching HF tokenizers 0.22.2, longest entry 8,034 bytes in ONE pretoken), tests/vllm/test_bpe_equivalence.cpp:166 (the ONLY timing assertion: two 65,536-byte one-word inputs under an absolute 2,000 ms bound, landed RED at 23,918.5 ms and 23,077.3 ms against the shipped code); tests/vllm/test_bpe.cpp:228 (leftmost tie on a long list), :249 (stale entry, new_id not the pair), :287 (no right neighbour), :317,351 (the table), :685 (the load-time refusal on BOTH surfaces, plus every committed golden still loading); goldens tests/parity/goldens/bpe_equivalence/encodings.json, generator tools/parity/dump_bpe_equivalence.py; test_bpe 24/24 971, test_bpe_equivalence 2/2 334, test_tokenizer_metaspace_split 7/7 28, test_detokenizer 12/12 221, test_tokenizer_parity 4/4 1175, test_tokenizer_parity_mistral 6/6 421, test_tokenizer_parity_deepseek 6/6 2461, test_tokenizer_parity_gpt4o 5/5 1000, test_input_processor 17/17 79; closing gate rerun and promotion parity-ledger.md#L945specs/bpe-quadratic-merge.mdDONE67823aee2
LOAD-CONFIG-SURFACEDataclass-for-dataclass config and serve-compatible flagsT0/T1vllm/config/scheduler.py:26; vllm/config/cache.py:25; vllm/config/compilation.py:378include/vllm/config/scheduler.h:67; src/vllm/config/scheduler.cpp:11; src/vllm/transformers_utils/hf_config.cpp:83; limited flags incl. max_num_seqs/max_num_batched_tokens examples/server/main.cpp:63,116,170tests/vllm/test_scheduler_config.cpp:10; tests/vllm/test_hf_config.cpp:131,224,265; examples/CMakeLists.txt:34planned: specs/config-surface.mdPARTIAL-
ENG-HF-MODEL-DOWNLOADFetch a checkpoint from HuggingFace so --model accepts a repository identifier and not a local path only. Two forms behind one flag, with the local path probed first: org/repo mirrors vLLM's full-snapshot download, and org/repo:Q4_K_M fetches one GGUF file, a form vLLM does not implement and which llama.cpp supplies as the secondary oracle. Mirrors vLLM's two-phase fetch (config JSON first, so a bad repository fails after 200 KB and not 60 GB) and its index-driven file selection, which reads model.safetensors.index.json and fetches the exact names in weight_map instead of every match for *.safetensors. Reference is resolved to a commit before any byte is fetched, so a moving main cannot change what a second run loads. Cache layout is HuggingFace's documented local cache, so a host holding a Python huggingface_hub cache gets a hit and model_loader.cpp:279-303 reads it unchanged. Transport is the already-vendored cpp-httplib with OpenSSL, matching llama.cpp, which retired libcurl at CMakeLists.txt:195 at stock tag b10451. NOT a verbatim port on one point: llama.cpp's is_valid_oid accepts any 40- or 64-character hexadecimal string, and on 17 August 2026 this project measured the tree API answering an unauthenticated caller on gated Lightricks/LTX-2.5 with an lfs.oid of one character repeated 64 times, identical for all 14 large-file-storage files, so this row treats an untokenized lfs.oid as absent and proves completeness structurally insteadT1vllm/model_executor/model_loader/weight_utils.py:345,349-357,459,472-490,493-496,506; vllm/model_executor/model_loader/default_loader.py:167-184; vllm/engine/arg_utils.py:839; vllm/config/model.py:183 at pin 5559679229. Secondary oracle llama.cpp for the :QUANT form only, stock tag b10451, anchors re-verified by W1 at commit 10bf611e533d81f739128304991c5e133c6aebd8W1 and W2 only: src/vllm/transformers_utils/hf_hub.cpp:1, src/vllm/transformers_utils/hf_cache.cpp:1, reached from src/vllm/entrypoints/model_loader.cpp:280. No downloader, no --model grammar, no TLS optiontests/vllm/transformers_utils/test_hf_cache.cpp:1, tests/vllm/transformers_utils/test_hf_hub.cpp:1 (in-process fake hub), tests/vllm/entrypoints/test_dflash_draft_hf_cache.cpp:1 (the loader reach, red when the call site is deleted)hf-model-download.mdREADY-
LOAD-LONGTAILSharded-state, tensorizer, RunAI, BitsAndBytes loadersT3vllm/model_executor/model_loader/__init__.py:33-65--planned: specs/loader-longtail.mdINVENTORIED-

Claim rule

Claims use the stable ID above. An agent first commits the row's leaf spike, updates this matrix to READY, then claims implementation in coordination.md. The umbrella anchor-backfill inventory does not replace any leaf spike. DONE additionally requires merged code, ported upstream tests, end-to-end oracle evidence where applicable, and same-change roadmap/README/ledger/state updates.