feat(ENG-CUDAGRAPH-BREAK): a forward can be captured as SEGMENTS split at break points, and CUDA permits the re-begin W0 could not test (#1192, #1163) - #1207
Merged
Conversation
…t at break points, and CUDA permits the re-begin W0 could not test (#1192, #1163) W1 of the break-point capture seam. Lands `vt::BreakableGraph`, `vt::GraphCaptureScope` and `vt::GraphBreak`, ports SGLang's unit suite case for case, and registers exactly ONE break point on ONE model. **Coverage and correctness. Not speed, and no throughput claim is made anywhere in this change.** GB10 measured prefill idle between launches at 3.8% with GPU-busy above 96%, and the 27B prefill gap at 92.5% non-GEMM glue GPU work; decode is already captured and already banked its launch-overhead win. The correctness half is shipped damage: `qwen3.cpp` declines its decode graph outright whenever the async device-token mirror is live, because the fix its own comment names lives in one sibling driver and nowhere else. ## The exit criterion, answered before anything was built W0 deliberately did NOT establish that CUDA permits `cudaStreamEndCapture` followed by `cudaStreamBeginCapture` on the same stream mid-forward with eager work between them, on our stream configuration. SGLang does exactly this on a production path at the pin, which is strong evidence and was not our measurement. It is now. On `orin:gpu0` through an `rc` lease, driver 12060, under `cudaStreamCaptureModeThreadLocal` — the mode `src/vt/cuda/cuda_backend.cu:204` uses: segment, host-dependent eager break, RE-BEGIN, segment, bare zero-work re-begin, segment; then three replays with fresh inputs, 0 mismatches on each. The bare re-begin (`breakable_cuda_graph.py:370-374`) is legal too. The first probe REFUSED, and the refusal was the probe's. `dlsym` on a bare symbol name binds `libcuda`'s LEGACY v1 entry points, which are not capture-aware: `cuMemcpyDtoDAsync` (v1) returned `CUDA_ERROR_STREAM_CAPTURE_UNSUPPORTED` inside a legal capture, and `cuStreamBeginCapture` (v1) takes no capture-mode argument, so the probe believed it was testing thread-local mode while testing global. Preferring `_v3` blindly then bound `cuCtxCreate_v3`, which takes two more parameters, and context creation failed `CUDA_ERROR_INVALID_DEVICE`. Both readings presented as a verdict about the design rather than about the instrument. ## The boundary is vLLM's; only the construction is SGLang's vLLM's v1 default splits at `splitting_ops`, defaulted to the attention family (`vllm/config/compilation.py:517,764-772,1145` @ `5559679229`). That boundary transfers; its mechanism, Dynamo and FX, cannot. So the registration form is SGLang's — one line at the site, as `layers/radix_attention.py:256` @ `f63458b5be` — and the site IS the registration. The break point registered here is the dense attention entry of `Qwen3ForCausalLM`, in the destination-carrying form, because `AttnBlock` returns a fresh pooled buffer on every call and the in-place form's contract is one that site cannot meet. ## The writeback is the part a container gets wrong Upstream does not append the caller's function. `eager_on_graph` appends a `replay_fn` closure that calls the captured inner function and writes the result back into the capture-time destination through `_copy_output` (`:231-235`, `:172-201`). On replay N the eager operation returns a FRESH allocation whose address is not the one the next segment baked, so a container replaying the raw function leaves segment `i+1` reading capture-time data while the break writes elsewhere — wrong numerics, not a fault, the class a clean `compute-sanitizer` run cannot see. `BreakableGraph` therefore stores the seam's closures, never the caller's function, and `CopyOutput` is a customization point reproducing all four of upstream's branches, including the non-copyable fallback that fabricates no copy. T7 through T10 pin it; T10 asserts the ABSENCE of the writeback on purpose. ## Gates `tests/vt/test_breakable_graph.cpp`, 14 cases / 81 assertions, exit 0 — T1 through T11 of the spec's `## Tests to port` plus the replay-order case and the ownership case that proves every segment is released through `Backend::DestroyGraph`, so #1162's dedup can interpose at the backend. `tests/vllm/models/test_qwen3_break_point.cpp` is the G2 reachability gate: it drives the production `Qwen3DenseModel::Forward` with a scope open and counts `num_hidden_layers + 1` segments. Deleting the one call site takes that to 1 and the gate to RED, which a unit test constructing the container by hand could not have asked. The same case holds G4 by comparing the logits BIT FOR BIT against the unscoped forward: 500 values, 0 differing. ## Staged slice, named rather than implied `GraphCaptureScope` and `BreakableGraph` are not yet ENTERED from a production step, because no driver opens a scope until W2 migrates `Qwen3DenseDecodeGraph`. The break point itself is on the production path — every forward executes it and takes the pass-through arm, which is byte-identical to the line it replaced and makes zero backend calls. `## Owed` in the spec lists this with W2 as owner, alongside the auxiliary-stream auto-join (D10, W4 and W5), the capture-failure drain as a gated case (W2), the ROCm and Tenstorrent arms (G5, W3), and G1 bit-exactness on a real GPU over more than one replay (W2). FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…ne-matrix summary by hand (#1192) `1f4878fdc` added `SPEC-DSPARK-QWEN3-ROUTING` and moved the engine-matrix totals in the same two cells this row moves, so the `**Total**` line conflicted. It is a KEYED RECORD, so the resolution takes the complete target-branch line and applies this row's scoped edit again on top of it rather than accepting either side: `origin/main` had rows 162 with ready 13 and active 33, and `ENG-CUDAGRAPH-BREAK` moving `READY` to `ACTIVE` makes that ready 12 and active 34. Verified rather than asserted — `scripts/check-agent-record.py` derives the counts from the rows and returns `ENGINE=162`, and the diff against `origin/main` is exactly three lines: the two summary cells and this row. `.agents/issue-index.md` auto-merged as an append with zero deletions, which is the only shape that file may take. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…GE, and the row's own spec has to be its first link (#1192) `scripts/check-doc-checkpoint.py` returned two findings on `7cd2cd6c8` and both are real record defects rather than checker noise. **The row linked the wrong spec first.** `spec_for_row` takes the FIRST `specs/<slug>.md` link on the matrix line as the spec that row owns, and the `owed:` cell cites `decode-graph-scratch-uaf-2026-07-18.md` in the column before the `Spike/spec` one. So a row moving `READY` to `ACTIVE` was asked to update a lifetime-incident spec it does not own. The citation now names the file without claiming the row's spec slot; `eng-cudagraph-break.md` D1 and D2 carry the linked reference, which is where it belongs. **A lifecycle move owes `docs/BENCHMARKS.md`, and `CMakeLists.txt` owes `docs/USAGE.md`.** BENCHMARKS records the honest thing, which is that no number is owed and none was taken: this is a coverage and correctness row, and a speed claim from it needs a path that is both currently eager and currently host-bound named first. What W1 measured is a capability rather than a rate, and the bit-exactness result is recorded in its place. USAGE says what a user can actually act on: `VLLM_CPP_CUDAGRAPH=0` now also turns the break seam inert, and there is no new flag, config key or build option to learn. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…ack slot, and interleaved replay was claimed but never gated (#1192, #1163) A fresh review of the W1 head returned FAIL. Every finding is repaired here, each one red first. The destination of the one production break point was a function-local `std::optional<DBuf>` in `RunLayer`. Both scoped layers registered the SAME stack slot, in a frame gone before the scope closed, and the pooled block it named went straight back on the `DevicePool` free list. The header stated the rule three lines above the call that broke it: the destination must outlive the `BreakableGraph`, because the following segment bakes its address. Inert today because no driver opens a scope, and wrong the moment W2 does. A comment is not a mechanism, and W2 through W5 add nine more callers. The destination form now takes a `vt::BreakSlot<T>` whose storage the seam owns for the life of the replay closure, mirroring upstream's `captured_output` held by value with its storage pinned by the segment mempool, and the reference-taking overload is gone, so the obvious call site cannot express the defect. The slot keeps its value inline until a capture pins it, so the pass-through path every production step takes allocates nothing. Interleaved replay is the container's defining property and nothing measured it. Replacing the loop with "replay all segments, then run all breaks" left the suite green, because segments went into the backend's log and break markers into a separate vector, and the two sequences were asserted independently. They are one sequence now: `ReplayGraph break0 ReplayGraph break1 ReplayGraph`. Four more silent degradations are closed. Renaming `CopyOutput` used to drop the site into the non-copyable fallback with both suites green, which is the D9 wrong-numerics path reached by a typo; the destination form now static-asserts the overload and the fallback must be asked for with `vt::NoWriteback{}`, and the model's overload moved to a header so the G2 gate can assert which branch the production type takes. The `VLLM_CPP_CUDAGRAPH=0` kill switch is gated in a child process, because it is read once per process and the existing case substituted the other conjunct. Nesting and re-entry are refused rather than traced into an illegal capture sequence and a graph whose last break `Replay` drops. And the capture-failure drain was owed as BEHAVIOUR, not only as a test: the destructor's catch guarded a throwing `EndCaptureGraph` alone, so an exception from a break function or from ordinary model code left a partial capture reporting itself as captured, which replays as half a forward. The ported suite claimed fidelity it did not have. T3 had lost upstream's arithmetic chain and T1 its post-replay value, because a recording backend cannot re-execute a segment. The backend now simulates the graph, filing captured work without running it and running it on replay, so every upstream chain and every post-replay assertion ports literally and the two remaining deviations are named. The exit-criterion probe is committed with its recipe and sha256, because a measurement that produced two false refusals is the last one anybody should reconstruct from prose. The leased run's own stdout was not retained, and the record says so rather than inventing one. Gates: `test_breakable_graph` 23 cases 150 assertions, `test_qwen3_break_point` 2 cases 516 assertions, both exit 0, plus `test_qwen3_forward`, `test_qwen3_moe_forward`, `test_decode_graph_sizes` and `test_graph_safe_scratch` unchanged and green. Ten mutations, each restored byte for byte: the pointer destination, batched replay, the renamed `CopyOutput` (a compile error at two sites), the dropped kill switch, the dropped drain, the dropped re-entry and nesting refusals, the stale replay count, the missing agreement check, and the deleted production call site. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
Straight merge; no conflicts and no record to reconcile by hand. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…and one BreakSlot could still serve two break points (#1192, #1163) Three findings from the scoped re-review of PR #1207, none of them touching the code the review verified. F1. Two records instructed a W2 implementer to build something already in the tree. `.agents/engine-matrix.md`'s spec cell listed "the drain case (W2)" among the items the spec's `## Owed` assigns, and the spec's `## Owed` says the opposite: the item is struck through and reads DELIVERED in W1. The `.agents/issue-index.md` row for #1192 said the same, because `7cd2cd6c8` wrote it before the repair and `cba969857` then re-derived field 6 of the matrix row alone, leaving the adjacent cell stating the superseded position. Both now say what landed: the `std::uncaught_exceptions()` comparison against the depth recorded at scope entry, and tests 13a, 13b and 13c. ON THE APPEND-ONLY RULE, and why this is an in-place edit rather than a correcting row. The rule protects the `merge=union` driver, which duplicates an EDITED line instead of merging it. That failure needs two branches to disagree about a line their common ancestor already had. This row does not exist at the merge base -- `git show 5af6e76:.agents/issue-index.md | grep -c '#1192'` returns 0 -- so only this branch has it, and at merge time an in-place correction is indistinguishable from having authored the corrected text. `scripts/check-issue-index-append-only.py` encodes exactly that semantic: it diffs against the MERGE BASE, not against `HEAD~1`, so a row this branch introduced carries no removed line however often it is rewritten before landing. It passes, and not by accident of scope. Appending a correcting row would land the wrong row permanently beside its correction, on a file nobody may ever edit again, which is the outcome the finding is about. F2. A recorded count that did not re-derive. The matrix said `tests/vt/test_breakable_graph.cpp`, 14 cases / 81 assertions, and the claim said "14-case ported suite"; neither figure re-derives at any head of this branch. Re-derived by `ninja test_breakable_graph && ./build/tests/test_breakable_graph`. F3. The spec claimed lifetime rule 1 was "now unexpressible to violate". Only its LIFETIME half was. `BreakSlot` stopped a caller handing the seam a destination that dies first, and left the ALIASING half writable: one slot reused for two break points in one capture compiled, `PinForCapture` returned the cell it had already made, and BOTH replay closures bound to the same address, so break 0's writeback was overwritten and any segment that baked break 0's destination read break 1's data. The production site is correct today because its slot is a `RunLayer` local, and W2 through W5 add nine more callers. Gated rather than documented, because the prose was telling those callers the shape was unwritable. `GraphCaptureScope::AppendBreak` now takes the destination as a REQUIRED parameter -- so no `GraphBreak` form can register without stating where it lands, including one added later -- and throws when a second break in the same capture names a cell already registered. Two details the repair had to get right, both measured rather than reasoned. The identity is the CELL and not the SLOT: the production slot is a per-call local, every layer's slot occupies the same STACK address, and slot-address identity refused the correct program on layer 2 and reddened the G2 gate. And the non-copyable fallback registers no destination, because it pins no cell and its replay writes back nowhere. The spec no longer says "unexpressible to violate"; it names which half the type closes and which half a refusal closes. F4. A residual the review surfaced, recorded and assigned. An exception CAUGHT INSIDE the capture scope leaves `segment_open_ == false` with the rest of the forward uncaptured, and nothing is unwinding at scope exit, so the drain cannot see it and `captured()` stays true over a forward missing its tail. The header and spec state the guarantee only for the propagating case, so this is a residual and not a false claim. Named in the spec's `## Owed` with W2 as owner, in the header beside the drain, and in `docs/STATUS.md`, whose enforcement paragraph would otherwise have overstated it. `docs/STATUS.md` rides here because this change made its recorded counts stale and its enforcement sentence imprecise, which is the record edit AGENTS.md says belongs in the pull request whose change made it stale. The new text is a SEPARATE paragraph rather than an extension: the page's 700-character paragraph cap is a ratchet that may only shrink, and growing the existing 655-character paragraph took `long_paragraphs` from 75 to 76. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
Keeps the branch fast-forwardable so the committed-range gates can report. FOLLOWING_AGENTS_PROTOCOL 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.
W1 of the break-point capture seam. Lands
vt::BreakableGraph,vt::GraphCaptureScopeandvt::GraphBreak, ports SGLang's unit suite case forcase, and registers exactly ONE break point on ONE model.
Coverage and correctness. Not speed, and no throughput claim is made anywhere
in this change. GB10 measured prefill idle between launches at 3.8% with
GPU-busy above 96%, and the 27B prefill gap at 92.5% non-GEMM glue GPU work;
decode is already captured and already banked its launch-overhead win. The
correctness half is shipped damage:
qwen3.cppdeclines its decode graphoutright whenever the async device-token mirror is live, because the fix its own
comment names lives in one sibling driver and nowhere else.
The exit criterion, answered before anything was built
W0 deliberately did NOT establish that CUDA permits
cudaStreamEndCapturefollowed by
cudaStreamBeginCaptureon the same stream mid-forward with eagerwork between them, on our stream configuration. SGLang does exactly this on a
production path at the pin, which is strong evidence and was not our measurement.
It is now. On
orin:gpu0through anrclease, driver 12060, undercudaStreamCaptureModeThreadLocal— the modesrc/vt/cuda/cuda_backend.cu:204uses: segment, host-dependent eager break, RE-BEGIN, segment, bare zero-work
re-begin, segment; then three replays with fresh inputs, 0 mismatches on each.
The bare re-begin (
breakable_cuda_graph.py:370-374) is legal too.The first probe REFUSED, and the refusal was the probe's.
dlsymon a baresymbol name binds
libcuda's LEGACY v1 entry points, which are notcapture-aware:
cuMemcpyDtoDAsync(v1) returnedCUDA_ERROR_STREAM_CAPTURE_UNSUPPORTEDinside a legal capture, andcuStreamBeginCapture(v1) takes no capture-mode argument, so the probe believedit was testing thread-local mode while testing global. Preferring
_v3blindlythen bound
cuCtxCreate_v3, which takes two more parameters, and contextcreation failed
CUDA_ERROR_INVALID_DEVICE. Both readings presented as a verdictabout the design rather than about the instrument.
The boundary is vLLM's; only the construction is SGLang's
vLLM's v1 default splits at
splitting_ops, defaulted to the attention family(
vllm/config/compilation.py:517,764-772,1145@5559679229). That boundarytransfers; its mechanism, Dynamo and FX, cannot. So the registration form is
SGLang's — one line at the site, as
layers/radix_attention.py:256@f63458b5be— and the site IS the registration. The break point registered hereis the dense attention entry of
Qwen3ForCausalLM, in the destination-carryingform, because
AttnBlockreturns a fresh pooled buffer on every call and thein-place form's contract is one that site cannot meet.
The writeback is the part a container gets wrong
Upstream does not append the caller's function.
eager_on_graphappends areplay_fnclosure that calls the captured inner function and writes the resultback into the capture-time destination through
_copy_output(:231-235,:172-201). On replay N the eager operation returns a FRESH allocation whoseaddress is not the one the next segment baked, so a container replaying the raw
function leaves segment
i+1reading capture-time data while the break writeselsewhere — wrong numerics, not a fault, the class a clean
compute-sanitizerrun cannot see.
BreakableGraphtherefore stores the seam's closures, never thecaller's function, and
CopyOutputis a customization point reproducing all fourof upstream's branches, including the non-copyable fallback that fabricates no
copy. T7 through T10 pin it; T10 asserts the ABSENCE of the writeback on purpose.
The destination is a
vt::BreakSlot<T>, not a caller reference, and that isthe fix for the finding below. Upstream holds
captured_outputBY VALUE with itsstorage pinned by the segment mempool (
:156-169). A C++ seam takingOut&getsthe opposite: the natural call site declares the destination as a local of the
function containing the break, which dies on the next
return. The slot's cellis owned by the replay closure, so the rule holds by construction, and the
inline-until-pinned storage keeps the pass-through path allocation-free.
What the review found, and what closed it
A fresh review of
30b9b43bareturned FAIL. All findings are repaired incba969857, each red first. They are listed here because each is a class ofdefect W2 through W5 can repeat.
std::optional<DBuf>: both scoped layers registered the SAME stack slot, in a frame gone before the scope closed, and the pooled block went back on theDevicePoolfree listvt::BreakSlot<T>the seam owns; the reference-taking overload is GONE, so the obvious call site cannot express the defectReplayGraph break0 ReplayGraph break1 ReplayGraphCopyOutputdropped the site into the non-copyable fallback (the D9 wrong-numerics path) with both suites greenstatic_assertin the destination form, an explicitvt::NoWriteback{}opt-in, and the model's overload moved to a header so the G2 gate asserts which branch is selectedVLLM_CPP_CUDAGRAPH=0kill switch was ungated; the existing case substituted the other conjunctEndCaptureGraphalone, so a mid-capture exception left a partial capture reportingcaptured() == truestd::uncaught_exceptions()against the depth at scope entry; three gated armssegment == break + 1was called "asserted" in three records and asserted nowhere; re-entry gaveseg == brk, whose last breakReplaydropsReplayBeginCaptureonto an already-capturing streamprev_deleted with the shape that implied nesting was contemplatedscripts/probe_cudagraph_rebegin.cand.cucommitted, recipe and sha256 in the record; the leased run's own stdout was NOT retained and the record says soCopyOutputsized fromdstalone;Reset()leftreplays_stale; the suite was not hermetic underVLLM_CPP_CUDAGRAPH=0; form numbering conflicted;engine-matrixowed:listed three delivered items;## Owednamed a tracker that dies at mergeVT_CHECKs,replays_cleared, a named precondition per case, one naming scheme, theowed:cell re-derived, and #1163 named as the staged-slice trackerGates
tests/vt/test_breakable_graph.cpp, 24 cases / 163 assertions, exit 0 — T1through T11 of the spec's
## Tests to portwith their arithmetic chains andpost-replay assertions intact, plus the replay-order case (12), the
capture-failure drain (13, all three arms), the non-capturing backend (14), the
lifetime-rule case, the aliasing refusal with its two controls, the nesting and
re-entry refusals, and the ownership case that proves every segment is released
through
Backend::DestroyGraph, so #1162's dedup can interpose at the backend.tests/vllm/models/test_qwen3_break_point.cppis the G2 reachability gate: itdrives the production
Qwen3DenseModel::Forwardwith a scope open and countsnum_hidden_layers + 1segments. Deleting the one call site takes that to 1 andthe gate to RED, which a unit test constructing the container by hand could not
have asked. The same case holds G4 by comparing the logits BIT FOR BIT against
the unscoped forward: 500 values, 0 differing.
Staged slice, named rather than implied
GraphCaptureScopeandBreakableGraphare not yet ENTERED from a productionstep, because no driver opens a scope until W2 migrates
Qwen3DenseDecodeGraph.The break point itself is on the production path — every forward executes it and
takes the pass-through arm, which is byte-identical to the line it replaced and
makes zero backend calls.
## Owedin the spec lists this with W2 as owner,alongside the auxiliary-stream auto-join (D10, W4 and W5), the ROCm and
Tenstorrent arms (G5, W3), G1 bit-exactness on a real GPU over more than one
replay (W2), and D1's INPUT half (W2). The capture-failure drain is no longer
owed: it landed here as behaviour and as three gated arms, and the two records
that still said otherwise — the
engine-matrixspec cell and theissue-indexrow — now say so too.
## Owedgains one residual the scoped re-reviewsurfaced, with W2 as owner: an exception CAUGHT INSIDE the capture scope leaves
the rest of the forward uncaptured while
captured()stays true, becausenothing is unwinding at scope exit for the drain to see. The staged slice is
tracked by #1163, the parent, because #1192 closes with this change and a
tracker that dies at merge tracks nothing.
The aliasing half of HIGH-1, gated after the re-review
BreakSlotclosed the LIFETIME half of lifetime rule 1 and this spec claimedthe whole rule was "unexpressible to violate". It was not. One slot reused for
TWO break points in one capture compiled:
PinForCapturereturns the cell italready made, so both replay closures bound to the SAME address, the earlier
writeback was overwritten, and any segment that baked the earlier destination
read the later break's data. The production site is correct today because its
slot is a
RunLayerlocal, and W2 through W5 add nine more callers.GraphCaptureScope::AppendBreaknow takes the destination as a REQUIREDparameter — no
GraphBreakform can register without stating where it lands,including a form added later — and throws when a second break in the same
capture names a cell already registered. The identity is the CELL and not the
SLOT, measured rather than reasoned: the production slot is a per-call local,
every layer's slot occupies the same STACK address, and slot-address identity
refused the correct program on layer 2 and reddened the G2 gate. The
non-copyable fallback registers no destination, because it pins no cell and its
replay writes back nowhere. Red-first: the case failed on the unrepaired head
with the aliased capture ACCEPTED at
break_count() == 2into one slot.Evidence
./build/tests/test_breakable_graph./build/tests/test_qwen3_break_pointpython3 scripts/check-agent-record.pyENGINE=162 MODEL=377 QUANT=82 KERNEL=52 BACKEND=85python3 scripts/check-public-doc-tables.pypython3 scripts/check-issue-index-append-only.py --base origin/main --head HEADpython3 scripts/check-commit-trailers.py --range origin/main..HEADpython3 scripts/check-commit-style.py --range origin/main..HEAD./build/tests/test_decode_graph_sizes./build/tests/test_graph_safe_scratch./build/tests/test_qwen3_forward./build/tests/test_qwen3_moe_forwardThe RED came first: with the header written and the source not yet in the CMake
source list,
test_breakable_graphfailed to link onvt::BreakableGraph::~BreakableGraph()andvt::GraphCaptureScope::~GraphCaptureScope(), exit 1.Negative mutation
Every mutation asserted its anchor before applying, printed its COMPILE status
and its exit status, and was restored byte for byte, because a mutation that
never applied and a mutation that failed to build both read as a passing test.
The repair pass added ten, on top of the six the first head carried. Every one
went RED or failed to compile for the intended reason.
CopyOutputoverload (a typo, a move, a shadow)static_assertand the G2 gate'sGraphCaptureEnabled()from theactive_conjunctionReset()leavesreplays_staleCopyOutputsizes fromdstalone, no agreement checkvt::GraphBreakcall site inqwen3.cppN10 is the one that matters for "Nothing lands dead". The deleted call site still
COMPILES and the seam's own unit suite stays green without it — which is exactly
the false green the rule exists to catch.
test_qwen3_break_pointis what goesred, because it counts segments coming out of a real model forward.
N1 is the one that matters for HIGH-1. It is the defect the first head shipped,
expressed on the new API, and the lifetime case reds on it — where before, no
case could ask the question at all.
Two known reds, characterised rather than hidden
scripts/check-doc-checkpoint.pyiterates NON-MERGE COMMITS individually, and onthis branch the lifecycle move (
READYtoACTIVE) landed one commit before thedocs/BENCHMARKS.mdanddocs/USAGE.mdedits it obliges. Per commit that is aFAIL. It is not a fail on what actually lands: this repository squash-merges, so
mainreceives the branch as ONE commit.Measured rather than argued. A detached scratch commit carrying this exact tree
as a single commit on top of
origin/main:The branch history is left alone because rewriting it was outside this task's
authority, and because faking a revert to satisfy a per-commit gate would be
worse than the red — it would put a false transition in the history the gate
exists to keep honest.
The two findings that gate raised on the earlier commit were BOTH real and are
both repaired here: the row's
owed:cell cited another spec by link BEFORE theSpike/speccolumn, sospec_for_rowread the wrong spec as this row's own; andthe lifecycle move genuinely did owe
docs/BENCHMARKS.md, whileCMakeLists.txtgenuinely did owe
docs/USAGE.md.tests/scripts/test_cpu_x86_llamacpp_floor.pyalso reds on this box, and thefailing sub-test MOVES between runs (
test_a_contended_leg_is_discarded..., thentest_the_quiet_gate_does_not_see_the_harnesss_own_process_tree, which printedNO_QUIET_WINDOW after 15s busy=114% load=22.05). That is the harness measuringbox load from other sessions, which is #618, not this change.
What is NOT claimed
No throughput result. No GPU bit-exactness over a replayed segmented capture.
No auxiliary-stream auto-join. No ROCm or Tenstorrent arm. Each is listed under
## Owedin the spec with the stage that owns it.Closes #1192. Parent #1163.
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]