Skip to content

fix(SAMPLER-HOST-LOGITS-DEVICE-TAG): the on-device sampler was handed a host address, and the CUDA arm dereferences it - #1360

Merged
localai-bot merged 13 commits into
mainfrom
fix/sampler-host-logits-device-tag
Aug 22, 2026
Merged

fix(SAMPLER-HOST-LOGITS-DEVICE-TAG): the on-device sampler was handed a host address, and the CUDA arm dereferences it#1360
localai-bot merged 13 commits into
mainfrom
fix/sampler-host-logits-device-tag

Conversation

@localai-bot

@localai-bot localai-bot commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

fix(SAMPLER-HOST-LOGITS-DEVICE-TAG): the on-device sampler was handed 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. src/vt/cuda/cuda_sample.cu::GreedyArgmaxCuda passes
logits.Ptr<float>() straight into a kernel launch on both arms --
src/vt/cuda/cuda_sample.cu::GreedyArgmaxKernelSlow and
src/vt/cuda/cuda_sample.cu::ArgmaxPartialKernel -- and ApplyTemperature,
ApplyTopKTopP, ComputeProbs and ComputeLogprobs reach the same pointer
through the same gate, src/vt/ops.cpp::CheckSamplingLogits. The address IS
dereferenced 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-3665
for that gate. The gate is at :3863 now, so the cited range had drifted into
MlaPrefillAttention -- 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 #1313 row in .agents/issue-index.md and the spec,
and five more runner.cpp line anchors in the spec were stale too. The index row
is 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.py lists it in
FROZEN_FILES for exactly that reason -- nothing would ever have reported the rot
and 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() is
caps.pageable_memory_access && caps.integrated
(src/vt/cuda/cuda_backend.cu::UnifiedMemory). 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.

The user-facing consequence is one bullet under ## First-line troubleshooting
in docs/USAGE.md: which three models stage, that a unified-memory device
samples the logits where they are, that a discrete GPU pays one host-to-device
transfer of rows x vocab x 4 bytes per step, that an older build aborted on an
illegal 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 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::Alloc, with
src/vt/tenstorrent/tenstorrent_backend.cpp::UnifiedMemory returning false), and a discrete Vulkan device's buffers are HOST_VISIBLE and
persistently mapped (include/vt/backend.h::DeviceMemoryIsHostAddressable). 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

commit-protocol-tag was RED on this branch, and the first of its two steps was
not 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 default Merge remote-tracking branch ...
subject and no body at all, because it was made with git merge --no-edit. The
five commits from it to the tip were rebuilt with git commit-tree, which is
why 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]

mudler added 7 commits August 19, 2026 12:12
… 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
localai-bot force-pushed the fix/sampler-host-logits-device-tag branch from 2138f37 to 4784bd4 Compare August 20, 2026 04:02
…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]
mudler added 5 commits August 22, 2026 07:02
…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
localai-bot merged commit aaf828e into main Aug 22, 2026
22 of 27 checks passed
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]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A HOST pointer stamped with the CUDA device is handed to the on-device sampler (nemotron_h, laguna, qwen3_vl)

2 participants