fix(SAMPLER-HOST-LOGITS-DEVICE-TAG): the on-device sampler was handed a host address, and the CUDA arm dereferences it - #1360
Merged
Conversation
… a host address, and the CUDA arm dereferences it
`GPUModelRunner` built the `[rows, vocab]` logits tensor the on-device sampler
runs on from a host `std::vector<float>` pointer and stamped `queue_.device` on
it. The issue asked whether `vt::GreedyArgmax` copies before touching that
pointer, because if it did this would be mislabelling rather than a defect. It
does not. `GreedyArgmaxCuda` passes `logits.Ptr<float>()` straight into a kernel
launch on both arms -- `src/vt/cuda/cuda_sample.cu:199` (slow) and `:207` (fast)
-- and `ApplyTemperature`, `ApplyTopKTopP`, `ComputeProbs` and `ComputeLogprobs`
reach the same pointer through the same `CheckSamplingLogits` gate
(`src/vt/ops.cpp:3605-3665`). The address IS dereferenced on device.
It survives here because `CudaBackend::UnifiedMemory()` is
`caps.pageable_memory_access && caps.integrated`
(`src/vt/cuda/cuda_backend.cu:363`). GB10 is integrated, so the driver services
an ordinary host pointer through ATS and the NemotronH A3 gate reads
`96/96 STRICT PASS` over it at host-memory latency. A discrete GPU reports
`integrated == false` and the same address is illegal.
The audit found four such sites, not the one the issue names: the (A')
`VT_GPU_SAMPLE=0` download-then-sample A/B leg, the reported host-logits leg,
the (B) `VT_LOGITS_GATHER=0` re-gather leg, and the `collect_prompt_logprobs`
prompt-row slice. All four are fixed together, which is what covers all three
affected models -- `nemotron_h`, `laguna` and `qwen3_vl`, exactly the
`ForwardLogits.host` producers listed in
`scripts/runner-routing-allowlist.txt`. A2-Q2b removing NemotronH's host-logits
path leaves the other two fixed.
`include/vllm/v1/sample/device_scratch.h` already states the contract this
needed -- unified backends wrap the host buffer in place at zero copy, discrete
backends allocate and copy up -- and applies it to the small derived sampling
tensors. The largest tensor in the path, the one every sampling kernel reads,
bypassed it. `HostBufferStaging` puts it back, with one grow-only allocation
reused across steps rather than `DeviceScratch`'s alloc/free per construction,
because this sits on the per-token decode path. Its unified branch is the
expression it replaces, unchanged, so GB10 does not move.
Two staging buffers, not one: `collect_prompt_logprobs` stages the prompt rows
while the assembled sample-logits tensor is still live, so a shared buffer would
invalidate the tensor the sampler is about to read.
Rejected, and recorded in the spec because both look cheaper than they are. A
sampler that refuses a host pointer carrying a device tag converts a repairable
path into a refusal -- the three models would stop decoding on a discrete GPU
rather than start working -- and it cannot separate a GB10-valid host pointer
from a discrete-invalid one without the same per-backend probe the repair would
need. Building the tensor with the host device instead needs a host queue and
the whole pipeline re-dispatched to CPU, because `CheckSamplingLogits` requires
`logits.device == q.device` for every sampling op; that regresses GB10 from
on-device sampling to host sampling.
The issue's suggested residency assertion in `vt::Tensor::Contiguous` is
rejected too, and this is the part worth keeping: two registered backends
legitimately stamp a host-dereferenceable pointer with a non-unified device.
Tenstorrent's `Alloc` returns `aligned_alloc` host memory by design
(`src/vt/tenstorrent/tenstorrent_backend.cpp:41-47`, `UnifiedMemory() == false`
at `:72`), and a discrete Vulkan device's buffers are HOST_VISIBLE and
persistently mapped (`include/vt/backend.h:56-70`). Both register a
`kGreedyArgmax` provider, so a blanket assert false-fires on both.
The test uses fake backends rather than hardware, and says so in its header:
every backend registered on this fleet reports `UnifiedMemory() == true`, so the
defect is invisible here by construction. A `Backend` over host memory on the
otherwise-unused `kXPU` slot -- the idiom `tests/vt/test_reference_tier.cpp`
already uses to gate the reference tier's discrete/unified split without a GPU
-- gives one unified instance and one discrete instance. The unified case pins
the zero-copy wrap, which is the executable form of "A3 stays 96/96".
RED, against the seam holding the expression `main` has today:
[doctest] test cases: 4 | 2 passed | 2 failed | 0 skipped
[doctest] assertions: 913 | 908 passed | 5 failed |
[doctest] Status: FAILURE!
RC=1
GREEN:
[doctest] test cases: 4 | 4 passed | 0 failed | 0 skipped
[doctest] assertions: 913 | 913 passed | 0 failed |
[doctest] Status: SUCCESS!
RC=0
Closes #1313
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [claude-code]
A catch-up merge of `origin/main` taken while the #1313 fix waited for review. Both sides auto-merged with no conflict: `git merge-tree --write-tree` over the two parents reproduces this commit's tree `c91c4ca4` exactly, so nothing here was resolved by hand. It was originally made with `git merge --no-edit`, which writes Git's default "Merge remote-tracking branch ..." subject and no body at all. The commit therefore carried none of the protocol trailers, and the strict walk in `commit-protocol-tag` reported it. Only this message is rewritten; the tree is unchanged. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
GitHub does not run the `merge=union` driver `.gitattributes:7` sets, so a branch touching `.agents/issue-index.md` re-conflicts whenever main appends a row. Resolved locally where the driver runs: the union auto-merge was DISCARDED, main's file taken wholesale, only rows whose KEY main lacks re-appended, and main's file asserted a strict PREFIX with zero duplicate keys. Any keyed-table collision kept BOTH sides, main's first, so no row is dropped. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
GitHub does not run the `merge=union` driver `.gitattributes:7` sets, so a branch touching `.agents/issue-index.md` re-conflicts whenever main appends a row. Resolved locally where the driver runs: the union auto-merge was DISCARDED, main's file taken wholesale, only rows whose KEY main lacks re-appended, and main's file asserted a strict PREFIX with zero duplicate keys. Any keyed-table collision kept BOTH sides, main's first, so no row is dropped. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
GitHub does not run the `merge=union` driver `.gitattributes:7` sets, so a branch touching `.agents/issue-index.md` re-conflicts whenever main appends a row. Resolved locally where the driver runs: the union auto-merge was DISCARDED, main's file taken wholesale, only rows whose KEY main lacks re-appended, and main's file asserted a strict PREFIX with zero duplicate keys. Any keyed-table collision kept BOTH sides, main's first, so no row is dropped. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
GitHub does not run the `merge=union` driver `.gitattributes:7` sets, so a branch touching `.agents/issue-index.md` re-conflicts whenever main appends a row. Resolved locally where the driver runs: the union auto-merge was DISCARDED, main's file taken wholesale, only rows whose KEY main lacks re-appended, and main's file asserted a strict PREFIX with zero duplicate keys. Any keyed-table collision kept BOTH sides, main's first, so no row is dropped. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
Catch-up merge so the branch's gates run against the tree the change will land on. `git merge-tree --write-tree` reported no conflict. The one keyed record both sides touch is `.agents/issue-index.md`, and it was verified by key rather than trusted to the automatic merge: `origin/main` holds 451 rows, this tree holds 452, all 451 of main's rows are present in main's own order, and the single extra row is this branch's own `#1313` entry. No key is duplicated. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
localai-bot
force-pushed
the
fix/sampler-host-logits-device-tag
branch
from
August 20, 2026 04:02
2138f37 to
4784bd4
Compare
…ce was reddening this branch (#1313) FOLLOWING_AGENTS_PROTOCOL `build-test-cpu` and both `sanitize-cpu` jobs were red here on one test, `175 - test_nemotron_h_paged_forward`, and the defect was never in this branch. #1371 left `CPU_ATTN` as a name in a candidate list with no registrar, so the CPU inherited FlashAttention's `head_size % 8` constraint with no fallback. `9ecaf1bb3` (#1392) fixes that, and `f07f96e1c` (#1444) is the current `origin/main` that carries it. Merging the older SHA would have left this branch behind again, and `commit-trailers` and `commit-style` SKIP on a branch that is behind. A skip is not a green, which is the state this branch was already in. Four files are touched by both sides, and each was verified rather than trusted to the automatic merge. `.agents/issue-index.md` is the keyed record: main carries 462 rows and this tree carries 463, all 462 of main's rows are present byte-identical and in main's own order, the preamble is byte-identical, and the one added row is this branch's own `#1313`. Nothing is removed and no key is duplicated. For `docs/USAGE.md`, `src/vllm/v1/worker/gpu/runner.cpp` and `tests/CMakeLists.txt` the two sides edit disjoint regions, and that is measured rather than asserted: the added and removed content lines of `merged vs main` hash equal to this branch's own delta, and those of `merged vs branch` hash equal to main's own delta, for all three files. No file is touched beyond what the merge itself requires. Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…s branch's note moved to its new home (#1313) FOLLOWING_AGENTS_PROTOCOL This branch was 88 commits behind `origin/main` and `git merge-tree` refused it, so `commit-trailers` and `commit-style` were SKIPPING rather than passing. A skip reports nothing about a tree. This merge takes `origin/main` db648fb and nothing else. One file conflicted, `docs/USAGE.md`, and the conflict is POSITIONAL rather than semantic. #1491 (`aee6c48d6`, "make public documentation task-focused") rewrote that page from 6187 lines to 285 and routed its build, model and backend detail into `docs/guides/` and `docs/models/`. The section this branch appended to, `### ROCm op coverage is incremental`, no longer exists anywhere in `docs/`; only `.agents/specs/public-docs-readability.md` still names it. The conflict region was therefore not a disagreement about this branch's content at all -- it was main's deletion of 5900 lines around an offset this branch had added to. Resolved by key rather than by hunk. `docs/USAGE.md` is taken from `origin/main` byte-for-byte, verified by an empty `git diff origin/main --` against it before the edit was re-applied, and the branch's scoped edit is then re-applied as one bullet under `## First-line troubleshooting`, which is where the restructured page keeps exactly this kind of note (the ROCm and tokenizer bullets beside it are the precedent). Every load-bearing claim of the original 30-line section survives: the three models that return host logits, the unified-versus-discrete split, the one host-to-device transfer of `rows x vocab x 4` bytes per step, the pre-#1313 illegal-address abort, and the admission that the discrete arm is gated at the seam with no hardware run behind it. The page is 14 lines longer than main and loses nothing from it. `.agents/issue-index.md` is the keyed record and was verified by key, not by the merge tool. Main carries 593 rows and the merged tree carries 594. Nothing is removed, the one added row is this branch's own #1313, and no issue key appears twice. `src/vllm/v1/worker/gpu/runner.cpp` and `tests/CMakeLists.txt` auto-merged; the two sides edit disjoint regions there and the merged diff against `origin/main` is this branch's own delta unchanged. No file is touched beyond what the merge itself requires. Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…our citations were repaired before they became unrepairable (#1313) FOLLOWING_AGENTS_PROTOCOL Two things, and the second is the one that mattered. `origin/main` moved to 660d2bd while the previous merge was being gated, and `5539686c7` (#1672) added a bullet at the SAME offset in the SAME `## First-line troubleshooting` section this branch writes to. That is a landing race and not a defect: the section still exists, so the earlier placement decision stands and both bullets are kept. `docs/USAGE.md` is taken from `origin/main` byte-for-byte again, verified by an empty diff, and this branch's bullet is re-applied at its anchor. 14 lines added, none removed, and #1672's `--speech-device` bullet is present and untouched. The citations are the substantive repair. This branch's own description had already been corrected once, and the SAME stale anchors were still sitting in two other places that AGENTS.md requires to agree with it: the `#1313` row in `.agents/issue-index.md` and `.agents/specs/sampler-host-logits-device-tag.md`. Both still said `src/vt/ops.cpp:3605-3665` for the `CheckSamplingLogits` gate, which now sits at `:3863` -- so the cited range lies inside `MlaPrefillAttention`, resolves cleanly, and says nothing about sampling. The spec was worse than the review found: `runner.cpp:1663`, `:1668`, `:1683`, `:1777` and `:2083-2090` were ALL stale too, and `1663` now reads `exec_state_.gdn_meta = std::move(gdn_meta)`. The index row is the reason this could not wait. `.agents/issue-index.md` is append-only, so a row may never be edited once it lands, and `scripts/check-symbol-anchors.py` lists that file in `FROZEN_FILES` for exactly that reason -- "a stale anchor inside one is unrepairable by construction and gating it would be a gate nobody may satisfy". Nothing would ever have reported it and nothing could ever have fixed it. This is the last moment the row is editable, and editing it is legitimate here because the row does not exist on `origin/main`: `check-issue-index-append-only.py` judges the merge-base range, where this row is a pure addition and no line is removed. Every citation in both files is now the SYMBOL form the gate's own docstring argues for. Ten distinct symbols, each verified by whole-word search against the file it names AT THIS HEAD, with a negative control run against a symbol that exists nowhere. The index is not gated for this, so those were checked by hand rather than assumed. Zero `file:line` citations remain in either file. `.agents/issue-index.md` verified by key: main carries 576 rows and this tree carries 577, nothing is removed, the one added row is this branch's own #1313, and no key is duplicated. No file is touched beyond what this merge and that repair require. Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…ice during this re-gate (#1313) FOLLOWING_AGENTS_PROTOCOL Clean, no conflict. `660d2bdc0` (#1669) touches `check-commit-trailers.py`, `.agents/specs/squash-separator.md`, `.github/pull_request_template.md` and that checker's suite, and none of them is a file this branch writes. Recorded because it is a trap and not an inconvenience. `origin/main` is a remote-tracking ref SHARED by every linked worktree of this checkout, so another session's fetch moves it under a run already in flight. It moved from `db648fb88` to `9c206ff7a` and then to `660d2bdc0` while this branch was being re-gated. The visible symptom was a `git diff --cached origin/main` that appeared to show this merge REVERTING 503 lines across four files it never opens -- it was comparing a correct tree against a base three commits newer than the one just merged. `scripts/agent-preflight.sh` pins `BASE_SHA` once for exactly this reason and says so in its own comment; a verdict taken against the ref instead of a pinned commit is a verdict about an unknown revision. The base under judgement here is 660d2bd, resolved once and named. Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…e is re-pinned to it (#1313) FOLLOWING_AGENTS_PROTOCOL Clean, no conflict. `9712ab77f` (#1676) changes a benchmark A/B control and touches nothing this branch writes. Third merge of this re-gate, and the reason is the same shared remote-tracking ref each time: `db648fb88`, `9c206ff7a`, `660d2bdc0`, now `9712ab77f`. A preflight run was already in flight against the previous one and was stopped rather than reported, because `origin/main` had ceased to be an ancestor of HEAD and its trailer gates would have taken the behind-arm and SKIPPED. A skip is not a green, and a green banner over two gates that did not run is the failure this repository added `--fail-on-skip` for. The base under judgement is 9712ab7, resolved once and named here rather than read from the ref at reporting time. Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…1313) FOLLOWING_AGENTS_PROTOCOL Clean, no conflict. `3e5d2f370` (#1677) repairs the DFlash2 speed gate and touches nothing this branch writes. Fourth base for one re-gate: `db648fb88`, `9c206ff7a`, `660d2bdc0`, `9712ab77f`, now 3e5d2f3. Each merge is recorded against a resolved commit rather than against `origin/main`, because that ref is shared by every linked worktree of this checkout and another session's fetch moves it under a run already in flight. Two runs were already discarded for that reason during this re-gate rather than reported: once the trailer gates would have taken the behind-arm and SKIPPED, and a skip is not a green. The base under judgement is 3e5d2f3. Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
localai-bot
pushed a commit
that referenced
this pull request
Aug 22, 2026
…s a conflict (#1250) FOLLOWING_AGENTS_PROTOCOL Clean, no conflict. `aaf828eb8` landed #1360, which appends one row to `.agents/issue-index.md`, and this branch appends two. GitHub then reported `CONFLICTING/DIRTY` on this pull request while `git merge-tree --write-tree` against the same `main` returned CLEAN and exit 0. Both readings are correct about different things. The file carries `merge=union` in `.gitattributes` precisely so that two branches appending rows merge without a conflict, and Git honours that driver. GitHub's merge probe does not, so a concurrent append reads as a textual collision there. The rule this repository already recorded for that state is merge, do not debug: the resolution is to merge `main` and let the union driver do what it is configured to do, and the forge then re-probes a branch that is no longer behind. Verified rather than trusted to the driver, because a union merge is exactly the mechanism that DUPLICATES an edited row instead of merging it. The base carries 599 rows and this tree carries 601. Nothing is removed. The two added rows are this branch's own #1250 and #1253. No issue key appears twice. #1360's newly landed #1313 row is present, byte-identical, and every one of the base's lines survives in the base's own order. The other keyed surfaces are unchanged by this merge and were re-measured anyway: `docs/BENCHMARKS.md` still holds exactly one `**NemotronH paged forward**` row and one `**NemotronH host re-expansion / decode token**` row and differs from the base by one line, `docs/STATUS.md` still carries 27 rows and differs by one line, and `.agents/benchmark-record.md` still adds 245 lines and removes none. The base under judgement is aaf828e. Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(SAMPLER-HOST-LOGITS-DEVICE-TAG): the on-device sampler was handed a host address, and the CUDA arm dereferences it
GPUModelRunnerbuilt the[rows, vocab]logits tensor the on-device samplerruns on from a host
std::vector<float>pointer and stampedqueue_.deviceonit. The issue asked whether
vt::GreedyArgmaxcopies before touching thatpointer, because if it did this would be mislabelling rather than a defect. It
does not.
src/vt/cuda/cuda_sample.cu::GreedyArgmaxCudapasseslogits.Ptr<float>()straight into a kernel launch on both arms --src/vt/cuda/cuda_sample.cu::GreedyArgmaxKernelSlowandsrc/vt/cuda/cuda_sample.cu::ArgmaxPartialKernel-- andApplyTemperature,ApplyTopKTopP,ComputeProbsandComputeLogprobsreach the same pointerthrough the same gate,
src/vt/ops.cpp::CheckSamplingLogits. The address ISdereferenced on device.
Every citation in this change is the SYMBOL form, and that is a repair rather
than a style choice. This description previously cited
src/vt/ops.cpp:3605-3665for that gate. The gate is at
:3863now, so the cited range had drifted intoMlaPrefillAttention-- it still resolved, and it had stopped saying anything.The same dead anchors were sitting in the two other places AGENTS.md requires to
agree with this text, the
#1313row in.agents/issue-index.mdand the spec,and five more
runner.cppline anchors in the spec were stale too. The index rowis the one that could not wait: that file is append-only, so a row may never be
edited after it lands, and
scripts/check-symbol-anchors.pylists it inFROZEN_FILESfor exactly that reason -- nothing would ever have reported the rotand nothing could ever have fixed it. All ten symbols are verified by whole-word
search against the file each names, at the head this pull request pushes.
It survives here because
CudaBackend::UnifiedMemory()iscaps.pageable_memory_access && caps.integrated(
src/vt/cuda/cuda_backend.cu::UnifiedMemory). GB10 is integrated, so the driver servicesan ordinary host pointer through ATS and the NemotronH A3 gate reads
96/96 STRICT PASSover it at host-memory latency. A discrete GPU reportsintegrated == falseand the same address is illegal.The audit found four such sites, not the one the issue names: the (A')
VT_GPU_SAMPLE=0download-then-sample A/B leg, the reported host-logits leg,the (B)
VT_LOGITS_GATHER=0re-gather leg, and thecollect_prompt_logprobsprompt-row slice. All four are fixed together, which is what covers all three
affected models --
nemotron_h,lagunaandqwen3_vl, exactly theForwardLogits.hostproducers listed inscripts/runner-routing-allowlist.txt. A2-Q2b removing NemotronH's host-logitspath leaves the other two fixed.
include/vllm/v1/sample/device_scratch.halready states the contract thisneeded -- unified backends wrap the host buffer in place at zero copy, discrete
backends allocate and copy up -- and applies it to the small derived sampling
tensors. The largest tensor in the path, the one every sampling kernel reads,
bypassed it.
HostBufferStagingputs it back, with one grow-only allocationreused across steps rather than
DeviceScratch's alloc/free per construction,because this sits on the per-token decode path. Its unified branch is the
expression it replaces, unchanged, so GB10 does not move.
Two staging buffers, not one:
collect_prompt_logprobsstages the prompt rowswhile the assembled sample-logits tensor is still live, so a shared buffer would
invalidate the tensor the sampler is about to read.
The user-facing consequence is one bullet under
## First-line troubleshootingin
docs/USAGE.md: which three models stage, that a unified-memory devicesamples the logits where they are, that a discrete GPU pays one host-to-device
transfer of
rows x vocab x 4bytes per step, that an older build aborted on anillegal address there instead, and that the discrete arm is gated at the seam
with no hardware run behind it. #1491 rewrote that page while this branch sat,
so the note sits in the restructured page's own idiom rather than in the section
it was originally written against, which no longer exists.
Rejected, and recorded in the spec because both look cheaper than they are. A
sampler that refuses a host pointer carrying a device tag converts a repairable
path into a refusal -- the three models would stop decoding on a discrete GPU
rather than start working -- and it cannot separate a GB10-valid host pointer
from a discrete-invalid one without the same per-backend probe the repair would
need. Building the tensor with the host device instead needs a host queue and
the whole pipeline re-dispatched to CPU, because
CheckSamplingLogitsrequireslogits.device == q.devicefor every sampling op; that regresses GB10 fromon-device sampling to host sampling.
The issue's suggested residency assertion in
vt::Tensor::Contiguousisrejected too, and this is the part worth keeping: two registered backends
legitimately stamp a host-dereferenceable pointer with a non-unified device.
Tenstorrent's
Allocreturnsaligned_allochost memory by design(
src/vt/tenstorrent/tenstorrent_backend.cpp::Alloc, withsrc/vt/tenstorrent/tenstorrent_backend.cpp::UnifiedMemoryreturning false), and a discrete Vulkan device's buffers are HOST_VISIBLE andpersistently mapped (
include/vt/backend.h::DeviceMemoryIsHostAddressable). Both register akGreedyArgmaxprovider, so a blanket assert false-fires on both.The test uses fake backends rather than hardware, and says so in its header:
every backend registered on this fleet reports
UnifiedMemory() == true, so thedefect is invisible here by construction. A
Backendover host memory on theotherwise-unused
kXPUslot -- the idiomtests/vt/test_reference_tier.cppalready uses to gate the reference tier's discrete/unified split without a GPU
-- gives one unified instance and one discrete instance. The unified case pins
the zero-copy wrap, which is the executable form of "A3 stays 96/96".
RED, against the seam holding the expression
mainhas today:GREEN:
commit-protocol-tagwas RED on this branch, and the first of its two steps wasnot the one that failed. The grep step reported that all new commits carry the
protocol marker, because it skips merge commits; the STRICT step,
scripts/check-commit-trailers.py, does not skip them, and it named the commit:3a883f81999f, which carried Git's defaultMerge remote-tracking branch ...subject and no body at all, because it was made with
git merge --no-edit. Thefive commits from it to the tip were rebuilt with
git commit-tree, which iswhy their SHAs move. Only that one message changed. Every rebuilt commit reuses
its original tree object and its original author and committer identity and
date, verified pairwise, and
git diff <old-tip> <new-tip>is empty.Closes #1313
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [claude-code]