Repository navigation
test(ep-cuda): list the NMS and Unique materialization syncs, both reviewed - #2157
justinchuby wants to merge 2 commits into
Conversation
…viewed `unconditional_syncs_are_limited_to_capture_unsupported_paths` has been red on main since #2113 (Unique) and #2130 (NMS) each added an unguarded `.synchronize()` without an allowlist entry. Either commit reds the lane on its own; both are in main, so every open PR inherits it. The allowlist is a review decision, so the question is which repair each needs. Both kernels declare `CaptureSupport::unsupported` in production source -- `non_max_suppression.rs:566` and `unique.rs:584`, both naming the 8-byte count D2H that precedes dynamic ORT output allocation -- so both are outside capture and the reviewed entry is the correct repair. Neither needs a `CudaRuntime::is_capturing` guard, which would have been the answer had either been capture-supported. The kernels are untouched. The listed sync is not the one the declaration names: it is the trailing drain after the materialization launch, before the governed workspace is returned. That is recorded in each entry's rationale rather than citing the declaration alone, matching the `dft.rs` and `multi_head_attention.rs` entries. Verified by running the contract's own source over the real kernel tree, with only `kernel_root()` redirected (the CUDA crate does not build without a toolchain here, and the scanner is pure std). Before the change it reproduces CI's failure with a byte-identical left/right set diff; after, both tests pass. Mutation: allowlisting a capture-supported file (`softmax.rs::run`) fails `every_allowlisted_file_can_decline_capture` with its own message, so the premise check is live rather than vacuous. Refs #2149. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2157 +/- ##
=======================================
Coverage 80.57% 80.58%
=======================================
Files 432 432
Lines 218152 218156 +4
Branches 218152 218156 +4
=======================================
+ Hits 175771 175795 +24
+ Misses 36537 36520 -17
+ Partials 5844 5841 -3
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
…ident (#2161) ## What `.roy-scratch/pr.md` reached `main` in #2150 (`b054ff63e`, 22:20:23Z). This removes it, and records the incident in the two places that keep the log. `Root file allowlist` has been **red on `main` and on every PR opened since** — it inherits, so it is currently red on #2157 and on anything else branched after 22:20Z. Fixing it is not a judgement on #2150; the check fired correctly and named the exact file and remedy. ## Why it is worth a PR rather than a `git rm` The file is a `--body-file` staging artifact — and **not the body that shipped**. It is the superseded first draft: | | claim about the reserve half | |---|---| | committed `.roy-scratch/pr.md` | "The reserve half **is not** the identity, and it bites at exactly one width." | | #2150's merged body | "The reserve half **is** the identity on that mask too. **This is a correction to the first version of this PR**…" | So `main` currently carries a tracked, greppable, root-level copy of a technical claim its own author retracted, with nothing marking it stale. That is worse than ordinary scratch: ordinary scratch is merely noise. ## The three changes 1. **Remove the file.** 2. **`.gitignore`: `/.*-scratch/`** — root-anchored, per the `/*.log` convention. The comment labels this as *the guessing half* of the repair, because that is what the record shows it is: five artifacts of this class have now reached `main` (`.msg.txt`, `.commitmsg`, `.pris_v4.log`, `.body.md`, `.roy-scratch/pr.md`) and **each was named outside every pattern written for the previous one** — `.body.md` landed hours after two separate fixes to that very block, and the name it should have had (`.pr-body.md`) was already ignored. 3. **Record the incident** in `.github/root-file-allowlist.txt`'s header *and* the `diff-guard.yml` comment, and bump both counts: seven entries / six incidents → **eight / seven**. Both files state their count in prose; a count that quietly stops being true is how a log stops being read. Per #2036's precedent the row carries the introducing and removing commits and the dwell time. ## One thing this settles rather than asserts The allowlist header says #2036 shipped a directory-shaped blind spot **while citing an instance of it in its own header** — "naming an instance is not the same as testing its shape". `.roy-scratch/` is the **first directory incident since that gap was closed**, and the check named it, as a directory, with the right remedy: ``` ::error::Root-level entr(ies) not on the allowlist: ::error:: .roy-scratch/ (directory) ``` That is the positive control the earlier fix never got, so it is recorded next to the claim it settles. ## Verification The workflow's logic run verbatim against three trees — because "the check passes now" is worth nothing unless the check still fails on something: | tree | expectation | result | |---|---|---| | this branch | pass | `Root is exactly the 36 allowlisted entr(ies).` | | `origin/main` (pre-fix) | report the cause, and only it | `unlisted: .roy-scratch` | | this branch + injected `.gaff-probe/x.md` | still discriminating | `UNLISTED: .gaff-probe`, rc=1 | And `git check-ignore -v` on the new pattern: `.roy-scratch/pr.md` and `.pris-scratch/a.md` both ignored at line 90; `nested/.foo-scratch/b.md` **not** ignored (rc=1), which is the documented root-only scope. No other path in the tree references `.roy-scratch` (`grep -rn`, excluding the three files changed here). ## Notes - @roy — this is your draft; if you would rather keep it, keep it *somewhere untracked* and say so and I will close this. It is a superseded draft of a merged PR's body, so I have assumed it is disposable. - Base is `7cb5d98df`. Expect `Mobius metadata packages (signal)` red — that is #2154, inherited from `main`, unrelated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…re-sync-allowlist
|
Refreshed onto Holding this rather than merging it, and the reason is worth stating.
Evidence the fix is correct in the meantime, since the lane cannot supply it: I ran
The third arm is the one that matters: it shows the suite still rejects a bad entry, so the pass in arm 2 is the fix and not a check that stopped discriminating. Plan: when #2158 lands, re-run this lane, confirm |
|
Re-validated at the merged head Same standalone harness (the contract is pure And the control, since a pass means nothing without one — delete So: still exactly the two entries, still discriminating, no new unallowlisted sync arrived with the merge. Also worth recording here because it decides how long this stays blocked — the two current CUDA reds are the same inherited stack seen at two depths, not two live causes. The distinguishing field is in every job log: A base containing The consequence I care about: as bases roll forward, #2149 stops being visible to anyone, masked behind a compile error in an unrelated crate. It is not fixed by that; it is hidden by it. That is the reason to keep this open and merge it on a green audit step rather than quietly on a skip. |
|
Closing this as superseded by #2180, which landed the same two allowlist entries and more. I held this PR rather than merging it, on a published criterion: its target step, #2180 is a superset. It adds The defect was real, for the record. Before closing I ran the exact CI command locally against both versions of the contract file, on identical kernel sources:
And the step-8 history is worth recording, because the same job colour meant three different things in three days:
The job is red in all three rows. Only the step records distinguish "not passing" from "not run" from "fixed". I originally wrote the middle row as Step 6 is still red at main head — that is #2158, and #2173 is what fixes it. Two instrument errors of mine that this cleanup exposed, both of which briefly produced a confident wrong reading:
Same shape both times, and the same shape as the |
Fixes the red in #2149. Two allowlist entries, no kernel changes.
The decision each half needed
#2149 asks the right question rather than reaching for the allowlist: an entry is only correct if the kernel can decline capture, otherwise the sync must be guarded with
CudaRuntime::is_capturingand an entry would silence a real capture-graph hazard. Both halves check out, read from production source:non_max_suppression.rsCaptureSupport::unsupported("NonMaxSuppression performs one 8-byte count D2H synchronization before dynamic ORT output allocation")unique.rsCaptureSupport::unsupported("Unique performs an 8-byte count D2H synchronization before dynamic ORT output allocation")Both are outside capture, so both take the reviewed entry. NMS is the half #2149 left open — its author did not have that file in their tree — and the answer is the same as Unique's.
One detail I did not want to lose, because it is the sort of thing that makes an entry unreviewable later: the sync being listed is not the sync the declaration names. The declaration names the 8-byte count D2H in the counting phase; the listed one is the trailing drain after the materialization launch, before the governed workspace is returned. Both entries say so. That matches how
dft.rsandmulti_head_attention.rsare written — they explain the specific barrier rather than pointing at the declaration.How it was verified without a CUDA toolchain
The crate does not build here, but
capture_sync_contract.rsis purestd— it scans source text. So I ran the contract's own code, verbatim, with a one-line redirection ofkernel_root()to the real kernel directory (diffagainst the original is exactly that line):That is a green, so on its own it is worth nothing. Two mutations make it mean something:
M1 — the harness reproduces the CI failure, byte for byte. Same file at
origin/main(i.e. without this patch), same kernel tree:Identical to the set diff in the
CUDA compile (Linux x86_64)log on #2151. So the harness is measuring the same thing the lane measures, and this patch is what flips it.M2 — the premise check is live, not vacuous. Adding
softmax.rs::run(a file with noCaptureSupport::unsupported) to the allowlist:So if I had made the wrong call on either kernel, the second test would have caught it.
cargo fmt --checkclean.What this does not do
CUDA compile (Linux x86_64)is advisory — the required set is exactlyFast (Linux x86_64)andRust quality— which is why feat(cuda): add bounded device Unique #2113 and feat(cuda): add bounded device-workspace NMS #2130 merged green through the lane whose entire purpose is to stop exactly this. That is the third instance in the same lane (CUDA capture-sync gate is red on every PR: dft.rs::run missing from the allowlist since #2080 #2094 wasdft.rs::run, three days ago), and it is why I have argued in Required status checks are bypassable, so--automerges before CI reports #1966 that a contract test which has now failed to block three times should be required.Refs #2149.