Repository navigation
review: a Labels workflow puts area labels on every issue and pull request, and needs-gpu on a card change - #104
Merged
Conversation
…quest, and needs-gpu on a card change Labels so far come only from the issue templates and from whoever opens the issue, so contributors' issues and every pull request carry none. tools/review/labels.py labels a pull request by the paths it changes (an open one's file list, a merged one's merge commit against its first parent, since a closed one's file list can span a whole stack; never its tree) and an issue by its title prefix: gpu, host, model, serve, placement, tools and documentation by area, dgx-spark and measure by kind, bug and hardware from a title in the template's form. A prefix that names a concept (paged, MTP, prefill) gets no area. A crate CRATE_AREA lacks is gpu when it is named gpu-* or reaches cuda-core, else the output names it; the self-test only checks that every entry is still a crate. An open pull request that changes a crate reaching cuda-core (post.py device_dirs) gets needs-gpu while it has neither gpu-evidence nor gpu-verified, and a needs-gpu the bot put on comes off once no device path is left or gpu-evidence is on, as Shingler's apply_labels does; gpu-evidence and gpu-verified are never touched. When the file list is short of changed_files or the device crates are unknown, nothing is removed or decided about the card label. The self-test runs both scripts in several orders, and with Shingler between this script's reads and its writes, to the same labels. Other labels: one a person took off is not put back, and only one this bot put on comes off. Each item's labels, title and events are read again after its files and device crates, right before the writes. Writes happen only inside GitHub Actions, where the labels are github-actions[bot]'s. Missing labels are created (a 422 passes only when it says the label exists); existing ones keep their colour and description. gpu-evidence's colour moves off hardware's green. The workflow runs on pull_request_target (an edit only when it changes the title or base, a close only when it merges) and issues with a base checkout, the number through env and pull-requests: read, and workflow_dispatch labels every open (or every) issue and pull request once, with a dry run. Issues another workflow opens with GITHUB_TOKEN start no workflow and get their labels from that run.
Collaborator
Author
|
컨트리뷰트 체크 완료 했으니 머지합니다 |
7 tasks done
juliankang4
added a commit
that referenced
this pull request
Oct 13, 2026
…ing it, so it runs on a merged pull request On pull_request_target, github.sha is the default branch's head. After a merge made on GitHub that is the pull request's merge_commit_sha, and actions/checkout refuses an explicit ref equal to it on a fork's pull request, so the first run, on #104's own merge, ended at the checkout. With no ref, actions/checkout takes the same commit from the event and skips that check, which applies only to a repository or ref the caller sets.
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.
What and why
Labels today come from the issue templates or from a person, so contributors' issues and all 44 pull requests carry
none. This adds
.github/workflows/labels.ymlandtools/review/labels.py, which label an issue by its title prefixand a pull request by the paths it changes, and put
needs-gpuon an open pull request that changes a device crateuntil it has
gpu-evidenceorgpu-verified. On today's open items it would add 36 labels to 25 of the 43 open issuesand pull requests.
1. What it does
Of the 55 issues, the 37 that carry a label were all opened by the repository owner or the review bot. None of the 13
issues contributors opened has one.
needs-gpuandgpu-evidencehave not been put on any pull request yet, andneither label exists in the repository.
With the workflow:
serve: ...,tools, model: ...), the same prefixes thecommit subjects use, when it is opened and when its title changes.
pulls/<n>/fileswhen it is opened, pushed to, reopened, or its title orbase changes. Its tree is never checked out.
closed pull request's
pulls/<n>/filesruns from the base it was opened on, which for a stacked pull request canhold a whole stack (gpu: on an integrated device, a decode gemv warp asks L2 for its whole row before the walk #27, cargo, tools: host CPU flags per target triple (S2, pin 87bc9518) #36, box.sh: local mode (BLOOMERY_BOX_LOCAL=1): the box command runs in this tree on a contributor's machine with a card of its own #38 and tools/ref: a single-card timing mode under box.sh's local mode (BLOOMERY_BOX_CARD=local): timing-card.sh times the one card nvidia-smi lists by UUID, the lease and its trace sit in BLOOMERY_LOCK_DIR, the witness prints the card, its Xid count, the shared memory pool and the machine, and depth-qwen3moe.sh fails an arm on an Xid or a lost card #39 below). A pull request closed without a merge is skipped.
needs-gpuat once, by the same device listShingler uses. Shingler then swaps it for
gpu-evidencewhen the pull request carries a gate run.workflow_dispatchlabels every open issue and pull request once (or every one, closed included), with a dry runthat writes the plan to the job summary and changes nothing.
One exception: an issue that another workflow opens with
GITHUB_TOKEN(Shingler'sreview-botissues, the ledgerissue) starts no workflow, so it gets labels only from a
workflow_dispatchrun.2. The labels
Area labels, by path for a pull request and by title prefix for an issue. The counts are from the dry run in section
6: open items first, then everything, with merged pull requests counted by their merge diff.
gpucrates/gpu*,crates/appgpu,gpu-gates,gpu-glm5next,gpu-deepseek41,gpu-mimo2,gpu-vision,apphostcrates/{qdot,threads,engram,engram-lab,runtime,sampler,levers,decision,vision,refset}modelcrates/{model,models,hf,gguf,tokenizer,jinja}(the CPU engine and the model files)servecrates/serveserve,serve testsplacementcrates/placementplacementtoolstools/,.github/,.cargo/,.config/,fuzz/,justfile,Cargo.toml,rust-toolchain.toml,deny.toml,clippy.toml,crates/oxide-ice-unrolltools,tools/...,ci,review,github,release,box.sh,fuzz,cargo,justfile,recipesdocumentationdocs/exceptdocs/cards/*.card, and any*.mdoutsidecrates/and.github/docs,docs/...,readme,contributingKind labels:
dgx-sparkdgx-spark:; or a pull request that changesdocs/contrib/dgx-spark.mdordocs/research/sparkdec.mdmeasure(new)measure:,측정:orexperiment:bug,hardwarebug: ...,hardware: ...), for an issue opened without the templateneeds-gputracking(new)How the tables were chosen:
CRATE_AREAnames every directory undercrates/today. A crate it lacks isgpuwhen its name starts withgpu-or it reaches cuda-core, and otherwise gets no area; the run's output then sayscrate not mapped: <name>.The self-test checks only that every entry in the table is still a crate (has a
Cargo.toml), so a pull requestthat adds a crate does not have to touch
tools/review/, which would make Shingler's review a COMMENT.Cargo.lock,THIRD_PARTY_NOTICES.md, the ratchets(
unsafe-ratchet.txt,lint-ratchet.txt),levers-direct.txt,spawn-allow.txt,gate-paths.tsv,defaults-twins.tsv,tools/ref/ptx-shapes.tsv,tools/bloomery/schema/,tools/flow/plans/and the predictioncards
docs/cards/*.card. They give no area, so agpupull request that moves the unsafe ratchet or adds a cardis not also labelled
toolsordocumentation.place gets no area: in the last 300 commit subjects and the issue titles,
MTP,paged,prefill,quant,host tier,GLM stepandgateeach span several areas. A word followed bytestsor테스트counts as theword;
serve seatsdoes not count asserve, because the serve seats live incrates/gpu-gates.dgx-sparkpath rule covers only those two documents. The other files with "spark" in their name(
crates/*/dspark*,gate_dspark_*) belong to the DSpark draft model, not to the DGX Spark, and no code path inthe tree is used only on the Spark.
new-modelstays with its template. Amodel:title cannot tell a new architecture (model: EmbeddingGemma 2 (gemma-embedding2, 0.74B dense) #59, model: GLM-5.3 (glm-dsa, 753B/active unverified) #60, model: MiMo-V2.6-Flash-RL (mimo2, 309B/15B) #61) from work oncrates/model(model: qwen35moe PlanInputs::describe가 호스트 room을 직접 읽음 — describe_in(split, room)으로 분리 #21), so amodel:issue gets themodelarea only.hardwareis only the template's meaning, a report from hardware we have not run. A request for a measurement on agiven card is
measure.3. What it changes and what it leaves alone
documentation,dgx-spark,measure,bug,hardware) andneeds-gpu. Everything else on an issue or pull request stays as it is,gpu-evidenceandgpu-verifiedincluded.label is removed only when the workflow put it on (its last
labeledevent isgithub-actions[bot]'s) and the pathsor the title no longer name it, so a label a person added stays.
needs-gpufollows the paths instead (section 4).GITHUB_TOKENlogin,github-actions[bot], which Shingler's jobs share. Runoutside GitHub Actions, the script is always a dry run, since a write there would carry another login.
LABELS. It does not change thecolour or description of a label that exists (
documentation,dgx-spark,bug,hardwarekeep theirs). A 422 oncreation passes only when GitHub's error says
already_exists; any other error stops the run. The card labels'definitions come from
CARD_LABELSinpost.py, wheregpu-evidencemoves from0e8a16(the existinghardwaregreen) to
bfe5bf. Neither card label exists in the repository yet, so nothing that exists changes colour.changed_files(GitHub lists at most 3,000 files) or a mergediff reaches the compare API's 300-file cap, the run adds the areas it found, removes nothing on that item, decides no
card label, and says so in its output.
accessibility,duplicate,invalid,question,wontfix) and the template labelsare not touched.
4.
needs-gpuand Shinglerlabels.pyimportsCARD_LABELS,device_dirsandapifromtools/review/post.py, so both use one list of devicecrates (
tools/recipes.py pure-crateson the trusted tree) and one definition of each card label. A renamed filecounts for the card label by its new path only, as in Shingler's file list.
The rule matches
apply_labels, and is applied only to an open pull request whose file list is complete and whosedevice crates were computed:
gpu-evidencenorgpu-verified: it getsneeds-gpu, even when a persontook
needs-gpuoff. A card check is recorded by a maintainer'sgpu-verified, not by removingneeds-gpu.gpu-evidence: aneeds-gputhatgithub-actions[bot]put on comesoff. A
needs-gpua person put on stays.the card labels stay as they are. The area labels are still applied.
For the release step, which lists merged pull requests with
needs-gpuand nogpu-verified, this means:no-reviewlabel, past five automatic reviews, a failed review job)still carries
needs-gpuwhile it changes a device crate, so it reaches the list if merged that way.needs-gpu.needs-gpu, so it puts no old merged pull request on the list.The self-test runs
labels.pyandapply_labelsagainst one fake pull request in four orders (workflow then bot,bot then workflow, and the two alternating three and five times), for both bot verdicts and for a rename out of
crates/gpu. Each order ends with the same labels: the areas and the bot's card label, or no card label for therename. It also covers a person taking
needs-gpuoff, a pull request Shingler skipped after its device change wentaway, a short file list, a merged pull request whose stale file list names
crates/gpu, and a failed device list.Concurrent runs
Each item's labels, title and events are read again after its file list and the device crates (about 5 s on a Mac),
right before the writes. The self-test runs Shingler between the workflow's first reads and its writes, and an issue
whose title changes while a backfill is running; both end with the labels of the latest state. What is left is the
time between the last read and the write landing, about one API round trip (a GET took about 400 ms from outside GitHub;
not measured on a runner). If Shingler adds
gpu-evidenceinside that window, the pull request carries both card labelsuntil the next labels run or Shingler's next review, either of which takes
needs-gpuoff while the pull request isopen. The Labels runs for one item queue in one concurrency group and none cancels another, so a merge does not cut
short the run of the push before it. A backfill runs in its own group, so it relies on the re-read.
5. The workflow
pull_request_target(opened, reopened, synchronize, edited, closed) andissues(opened, edited), so a fork's pullrequest gets a token that can label it. The job runs on an edit only when the title or base changed, and on a close
only when it merged. It checks out the branch the workflow runs from (
github.sha), asreview.ymldoes for itstools, and never the pull request's head. Only the issue or pull request number reaches the script, through
env;a title never enters a shell line. Each output line is one line of plain text with backticks replaced, so a title
cannot close the job summary's code fence.
contents: read,issues: write,pull-requests: read. Labels go through the Issues API; the pullrequest API is only read for the file list. I could not check from outside Actions that
issues: writealone letsthe token label a pull request; the first run after merge shows it.
RUSTUP_TOOLCHAIN=stableon the step:recipes.pyreads the workspace withcargo metadata --offline --no-deps --locked, which stable does with an emptyCARGO_HOME. Without it,rust-toolchain.tomlwould install the pinned nightly and its components on every run. The device list is computedonly for an open pull request.
workflow_dispatchwithstate(openorall) anddry_run. A backfill waits 1 s between the writes of twoitems, as GitHub's rate limit guidance asks for a run of write requests. A rerun is safe: it adds only what is
missing and removes only what no longer applies.
tools/check-recipes.sh'sselftests=(, socontrib-checkruns it.After merge, the first
workflow_dispatchrun withdry_runon shows the plan for every open issue and pullrequest; a second run without it applies the plan.
This changes
.github/andtools/review/, so Shingler's review of it is a COMMENT (APPROVE_GUARD), and it waitsfor a person's approval, as
CONTRIBUTING.mdsays for changes to CI and the bot's tools.6. Dry run on this repository
labels.py run --repo midagedev/bloomery --state all --dry-run(GET requests only) over all 55 issues and 44 pullrequests, at upstream
517e0a74.Open items (what the default backfill touches):
19 of the 37 open issues.
needs-gpu: placement, model, gpu, gpu-gates: a Machine's host and unified pool live in Machine::nodes, this process's node first #94, placement: a model's plan over several unified nodes (dgx-spark.md §9), and nodes_scale on one to four Sparks #95, gpu, gate-paths: the tier page is reached over its link; host/link.rs holds the shared page, and the stage card, each tier card and the host take the page's addresses and words there #96, gpu-gates: one helper makes a name a record token #98, gpu-gates: drop the dead feature-off stub main from the 112 bins that declare required-features #99. qdot: Q4_K's one-column kernel, tile and row lanes get AVX-512 VNNI bodies, picked at run time and bit-identical to the AVX2 ones #86 (qdot) getshostandtoolsand no cardlabel.
MTP/mtp(2),paged(2),prefill,quant,host tier,GLM step,plan 레코드,Blackwell probe,native AMD,qwen35/27B native generation.The others have no prefix (Status board (auto-updated) · 작업 현황 #40, 0.3.0 numbers for the README at serving defaults: DGX Spark and RTX 5090 #46, Shingler's slag ledger #92, 0.3.2 release freeze #97, some with labels already) or already carry
dgx-spark(dgx-spark: decode step timeline (nsys) and sampled vs greedy decode rate on GB10 #17, dgx-spark: is prefill byte-bound or tensor-bound on GB10? (grouped GEMM time, pp512/pp4096) #18).Everything, closed included:
dgx-spark: P2, a unified machine plans against one pool; the census reads an integrated device's room from MemAvailable #16, gpu: route_warp_gated's rescan walks a lane's entries four at a time, so a round's shared loads issue together #35) are skipped.
gpu,host,model,serve,placement,tools,measure,tracking,needs-gpu,gpu-evidence.Rows to check by eye:
gpuonly. Itspulls/27/fileslists 66 files from the stack it was opened on, includingdocs/contrib/dgx-spark.md; its merge diff has 14, all undercrates/gpu*or companion files. cargo, tools: host CPU flags per target triple (S2, pin 87bc9518) #36 getstoolsonly, and box.sh: local mode (BLOOMERY_BOX_LOCAL=1): the box command runs in this tree on a contributor's machine with a card of its own #38 and tools/ref: a single-card timing mode under box.sh's local mode (BLOOMERY_BOX_CARD=local): timing-card.sh times the one card nvidia-smi lists by UUID, the lease and its trace sit in BLOOMERY_LOCK_DIR, the witness prints the card, its Xid count, the shared memory pool and the machine, and depth-qwen3moe.sh fails an arm on an Xid or a lost card #39 (
box.shlocal mode) gethostandtools, for the same reason.dgx-sparkanddocumentationfrom the two Spark documents.gpu, gate-paths: ...) getsgpuandneeds-gpu;gate-paths.tsvgives no area.samplerandrouter, so they get nomeasure.7. Limits
merge_commit_shathat is its lastcommit, so its merge diff covers that commit only. Most merges here are merge commits; box.sh: local mode (BLOOMERY_BOX_LOCAL=1): the box command runs in this tree on a contributor's machine with a card of its own #38 is one that is not, and
its last commit is the one it added.
gpu-*gets no area untilCRATE_AREAnames it: the devicelist comes from the branch the workflow runs from, which does not have the crate yet.
list.
run for the same pull request, the merge run replaces the push run, and the card label is not decided for that
push. Shingler's review of the push still sets it.
8. For the maintainers to decide
MTP,paged,prefillandquantissues so far read as card-engine work, so mappingthem to
gpuwould label 6 more open issues. I left them out because each of those words also names host-side code(
crates/runtimefor MTP's width,crates/modelfor the CPU engine's prefill). A line inALIASESadds one.measureby path. A pull request that addsdocs/cards/*.cardcould getmeasure. That would catch sampler: measure relative-weight cutoffs and record the negative CPU result #65 androuter: measure per-layer expert locality on recent prose and code #66, but a code change also adds a card for its A/B (the
mtp:width commit addeddraftgate-noninf.card), socards give no label for now.
tracking. It is defined and created but never set automatically; the open status issues (Status board (auto-updated) · 작업 현황 #40, dgx-spark: what is in progress on the Spark side, as a checklist #53) could getit by hand.
CONTRIBUTING.md("How a pull request is verified andmerged": "is labelled
gpu-evidence... elseneeds-gpuuntil someone runs it") and.github/review/README.md(the paragraph starting "Shingler only reads") now have the workflow putting
needs-gpuon first. TheAGENTS.mdlayout line for
tools/review/says "Shingler's tools", andlabels.pylives there too because it sharespost.py. I left these texts as they are.Code shape
tools/review/post.py.removal (someone took the label off since the read). A short file list, a capped merge diff and a failed
device list are named in the output.
cargo fmtandcargo clippy: no Rust changed.Duplication found or removed (
path:line), or "none": none.What I ran
Python 3.15.0, actionlint 1.7.12. Each of these changes to
labels.pymakes the self-test fail: reading the labels orthe title from the first read instead of the re-read, deciding the card label when the device list failed, putting
needs-gpuback only when no person took it off, keeping a botneeds-gpuafter the device change went away or oncegpu-evidenceis on, usingpulls/<n>/filesfor a merged pull request, removing labels on a short file list,ignoring every 422, leaving a device crate missing from
CRATE_AREAwithoutgpu, and counting a.cardfile asdocumentation.
post.py devicewithRUSTUP_TOOLCHAIN=stable, an emptyCARGO_HOMEand nojustonPATHlistscrates/app/ crates/gpu/ crates/gpu-deepseek41/ crates/gpu-gates/ crates/gpu-glm5next/ crates/gpu-mimo2/ crates/gpu-vision/in about 5 s on a Mac, the same list as with the pinned nightly.
just mac-static upstream/mainon an Apple silicon Mac: 13 of the 14 steps rc 0 (lint 41 warnings, the ratchet).check-recipeswent red in each of three runs on a loaded machine (load average 30 to 46), each time on a differenttimed self-test:
depth-serve.sh(/healthover 3 s) and achaincase at rc 124, then the samechaincase alone,then
q38-3090-server.sh'swidth-record. None of them reads a file this changes, and CI's t0 runscheck-recipeson this pull request.
Not run: the workflow itself, which GitHub runs from the default branch only after merge.
AI help
AI 코딩 에이전트가 코드를 작성한 후 설명을 썼고, 테스트를 마쳤습니다. diff 리뷰와 PR 초안 리뷰는 제가 직접 했습니다.